All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.butterfaces-dist-bundle-dev-js.butterfaces-third-party.js Maven / Gradle / Ivy

The newest version!
// Copyright (C) 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


/**
 * @fileoverview
 * some functions for browser-side pretty printing of code contained in html.
 *
 * 

* For a fairly comprehensive set of languages see the * README * file that came with this source. At a minimum, the lexer should work on a * number of languages including C and friends, Java, Python, Bash, SQL, HTML, * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk * and a subset of Perl, but, because of commenting conventions, doesn't work on * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class. *

* Usage:

    *
  1. include this source file in an html page via * {@code } *
  2. define style rules. See the example page for examples. *
  3. mark the {@code
    } and {@code } tags in your source with
     *    {@code class=prettyprint.}
     *    You can also use the (html deprecated) {@code } tag, but the pretty
     *    printer needs to do more substantial DOM manipulations to support that, so
     *    some css styles may not be preserved.
     * </ol>
     * That's it.  I wanted to keep the API as simple as possible, so there's no
     * need to specify which language the code is in, but if you wish, you can add
     * another class to the {@code <pre>} or {@code <code>} element to specify the
     * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
     * starts with "lang-" followed by a file extension, specifies the file type.
     * See the "lang-*.js" files in this directory for code that implements
     * per-language file handlers.
     * <p>
     * Change log:<br>
     * cbeust, 2006/08/22
     * <blockquote>
     *   Java annotations (start with "@") are now captured as literals ("lit")
     * </blockquote>
     * @requires console
     */
    
    // JSLint declarations
    /*global console, document, navigator, setTimeout, window, define */
    
    /** @define {boolean} */
    var IN_GLOBAL_SCOPE = true;
    
    /**
     * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
     * UI events.
     * If set to {@code false}, {@code prettyPrint()} is synchronous.
     */
    window['PR_SHOULD_USE_CONTINUATION'] = true;
    
    /**
     * Pretty print a chunk of code.
     * @param {string} sourceCodeHtml The HTML to pretty print.
     * @param {string} opt_langExtension The language name to use.
     *     Typically, a filename extension like 'cpp' or 'java'.
     * @param {number|boolean} opt_numberLines True to number lines,
     *     or the 1-indexed number of the first line in sourceCodeHtml.
     * @return {string} code as html, but prettier
     */
    var prettyPrintOne;
    /**
     * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
     * {@code class=prettyprint} and prettify them.
     *
     * @param {Function} opt_whenDone called when prettifying is done.
     * @param {HTMLElement|HTMLDocument} opt_root an element or document
     *   containing all the elements to pretty print.
     *   Defaults to {@code document.body}.
     */
    var prettyPrint;
    
    
    (function () {
      var win = window;
      // Keyword lists for various languages.
      // We use things that coerce to strings to make them compact when minified
      // and to defeat aggressive optimizers that fold large string constants.
      var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"];
      var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," + 
          "double,enum,extern,float,goto,inline,int,long,register,short,signed," +
          "sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];
      var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," +
          "new,operator,private,protected,public,this,throw,true,try,typeof"];
      var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool," +
          "concept,concept_map,const_cast,constexpr,decltype,delegate," +
          "dynamic_cast,explicit,export,friend,generic,late_check," +
          "mutable,namespace,nullptr,property,reinterpret_cast,static_assert," +
          "static_cast,template,typeid,typename,using,virtual,where"];
      var JAVA_KEYWORDS = [COMMON_KEYWORDS,
          "abstract,assert,boolean,byte,extends,final,finally,implements,import," +
          "instanceof,interface,null,native,package,strictfp,super,synchronized," +
          "throws,transient"];
      var CSHARP_KEYWORDS = [JAVA_KEYWORDS,
          "as,base,by,checked,decimal,delegate,descending,dynamic,event," +
          "fixed,foreach,from,group,implicit,in,internal,into,is,let," +
          "lock,object,out,override,orderby,params,partial,readonly,ref,sbyte," +
          "sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort," +
          "var,virtual,where"];
      var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," +
          "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," +
          "throw,true,try,unless,until,when,while,yes";
      var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,
          "debugger,eval,export,function,get,null,set,undefined,var,with," +
          "Infinity,NaN"];
      var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," +
          "goto,if,import,last,local,my,next,no,our,print,package,redo,require," +
          "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
      var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," +
          "elif,except,exec,finally,from,global,import,in,is,lambda," +
          "nonlocal,not,or,pass,print,raise,try,with,yield," +
          "False,True,None"];
      var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," +
          "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," +
          "rescue,retry,self,super,then,true,undef,unless,until,when,yield," +
          "BEGIN,END"];
       var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "as,assert,const,copy,drop," +
          "enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv," +
          "pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"];
      var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
          "function,in,local,set,then,until"];
      var ALL_KEYWORDS = [
          CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,
          PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
      var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;
    
      // token style names.  correspond to css classes
      /**
       * token style for a string literal
       * @const
       */
      var PR_STRING = 'str';
      /**
       * token style for a keyword
       * @const
       */
      var PR_KEYWORD = 'kwd';
      /**
       * token style for a comment
       * @const
       */
      var PR_COMMENT = 'com';
      /**
       * token style for a type
       * @const
       */
      var PR_TYPE = 'typ';
      /**
       * token style for a literal value.  e.g. 1, null, true.
       * @const
       */
      var PR_LITERAL = 'lit';
      /**
       * token style for a punctuation string.
       * @const
       */
      var PR_PUNCTUATION = 'pun';
      /**
       * token style for plain text.
       * @const
       */
      var PR_PLAIN = 'pln';
    
      /**
       * token style for an sgml tag.
       * @const
       */
      var PR_TAG = 'tag';
      /**
       * token style for a markup declaration such as a DOCTYPE.
       * @const
       */
      var PR_DECLARATION = 'dec';
      /**
       * token style for embedded source.
       * @const
       */
      var PR_SOURCE = 'src';
      /**
       * token style for an sgml attribute name.
       * @const
       */
      var PR_ATTRIB_NAME = 'atn';
      /**
       * token style for an sgml attribute value.
       * @const
       */
      var PR_ATTRIB_VALUE = 'atv';
    
      /**
       * A class that indicates a section of markup that is not code, e.g. to allow
       * embedding of line numbers within code listings.
       * @const
       */
      var PR_NOCODE = 'nocode';
    
      
      
      /**
       * A set of tokens that can precede a regular expression literal in
       * javascript
       * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html
       * has the full list, but I've removed ones that might be problematic when
       * seen in languages that don't support regular expression literals.
       *
       * <p>Specifically, I've removed any keywords that can't precede a regexp
       * literal in a syntactically legal javascript program, and I've removed the
       * "in" keyword since it's not a keyword in many languages, and might be used
       * as a count of inches.
       *
       * <p>The link above does not accurately describe EcmaScript rules since
       * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
       * very well in practice.
       *
       * @private
       * @const
       */
      var REGEXP_PRECEDER_PATTERN = '(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';
      
      // CAVEAT: this does not properly handle the case where a regular
      // expression immediately follows another since a regular expression may
      // have flags for case-sensitivity and the like.  Having regexp tokens
      // adjacent is not valid in any language I'm aware of, so I'm punting.
      // TODO: maybe style special characters inside a regexp as punctuation.
    
      /**
       * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
       * matches the union of the sets of strings matched by the input RegExp.
       * Since it matches globally, if the input strings have a start-of-input
       * anchor (/^.../), it is ignored for the purposes of unioning.
       * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
       * @return {RegExp} a global regex.
       */
      function combinePrefixPatterns(regexs) {
        var capturedGroupIndex = 0;
      
        var needToFoldCase = false;
        var ignoreCase = false;
        for (var i = 0, n = regexs.length; i < n; ++i) {
          var regex = regexs[i];
          if (regex.ignoreCase) {
            ignoreCase = true;
          } else if (/[a-z]/i.test(regex.source.replace(
                         /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
            needToFoldCase = true;
            ignoreCase = false;
            break;
          }
        }
      
        var escapeCharToCodeUnit = {
          'b': 8,
          't': 9,
          'n': 0xa,
          'v': 0xb,
          'f': 0xc,
          'r': 0xd
        };
      
        function decodeEscape(charsetPart) {
          var cc0 = charsetPart.charCodeAt(0);
          if (cc0 !== 92 /* \\ */) {
            return cc0;
          }
          var c1 = charsetPart.charAt(1);
          cc0 = escapeCharToCodeUnit[c1];
          if (cc0) {
            return cc0;
          } else if ('0' <= c1 && c1 <= '7') {
            return parseInt(charsetPart.substring(1), 8);
          } else if (c1 === 'u' || c1 === 'x') {
            return parseInt(charsetPart.substring(2), 16);
          } else {
            return charsetPart.charCodeAt(1);
          }
        }
      
        function encodeEscape(charCode) {
          if (charCode < 0x20) {
            return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
          }
          var ch = String.fromCharCode(charCode);
          return (ch === '\\' || ch === '-' || ch === ']' || ch === '^')
              ? "\\" + ch : ch;
        }
      
        function caseFoldCharset(charSet) {
          var charsetParts = charSet.substring(1, charSet.length - 1).match(
              new RegExp(
                  '\\\\u[0-9A-Fa-f]{4}'
                  + '|\\\\x[0-9A-Fa-f]{2}'
                  + '|\\\\[0-3][0-7]{0,2}'
                  + '|\\\\[0-7]{1,2}'
                  + '|\\\\[\\s\\S]'
                  + '|-'
                  + '|[^-\\\\]',
                  'g'));
          var ranges = [];
          var inverse = charsetParts[0] === '^';
      
          var out = ['['];
          if (inverse) { out.push('^'); }
      
          for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
            var p = charsetParts[i];
            if (/\\[bdsw]/i.test(p)) {  // Don't muck with named groups.
              out.push(p);
            } else {
              var start = decodeEscape(p);
              var end;
              if (i + 2 < n && '-' === charsetParts[i + 1]) {
                end = decodeEscape(charsetParts[i + 2]);
                i += 2;
              } else {
                end = start;
              }
              ranges.push([start, end]);
              // If the range might intersect letters, then expand it.
              // This case handling is too simplistic.
              // It does not deal with non-latin case folding.
              // It works for latin source code identifiers though.
              if (!(end < 65 || start > 122)) {
                if (!(end < 65 || start > 90)) {
                  ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
                }
                if (!(end < 97 || start > 122)) {
                  ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
                }
              }
            }
          }
      
          // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
          // -> [[1, 12], [14, 14], [16, 17]]
          ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });
          var consolidatedRanges = [];
          var lastRange = [];
          for (var i = 0; i < ranges.length; ++i) {
            var range = ranges[i];
            if (range[0] <= lastRange[1] + 1) {
              lastRange[1] = Math.max(lastRange[1], range[1]);
            } else {
              consolidatedRanges.push(lastRange = range);
            }
          }
      
          for (var i = 0; i < consolidatedRanges.length; ++i) {
            var range = consolidatedRanges[i];
            out.push(encodeEscape(range[0]));
            if (range[1] > range[0]) {
              if (range[1] + 1 > range[0]) { out.push('-'); }
              out.push(encodeEscape(range[1]));
            }
          }
          out.push(']');
          return out.join('');
        }
      
        function allowAnywhereFoldCaseAndRenumberGroups(regex) {
          // Split into character sets, escape sequences, punctuation strings
          // like ('(', '(?:', ')', '^'), and runs of characters that do not
          // include any of the above.
          var parts = regex.source.match(
              new RegExp(
                  '(?:'
                  + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]'  // a character set
                  + '|\\\\u[A-Fa-f0-9]{4}'  // a unicode escape
                  + '|\\\\x[A-Fa-f0-9]{2}'  // a hex escape
                  + '|\\\\[0-9]+'  // a back-reference or octal escape
                  + '|\\\\[^ux0-9]'  // other escape sequence
                  + '|\\(\\?[:!=]'  // start of a non-capturing group
                  + '|[\\(\\)\\^]'  // start/end of a group, or line start
                  + '|[^\\x5B\\x5C\\(\\)\\^]+'  // run of other characters
                  + ')',
                  'g'));
          var n = parts.length;
      
          // Maps captured group numbers to the number they will occupy in
          // the output or to -1 if that has not been determined, or to
          // undefined if they need not be capturing in the output.
          var capturedGroups = [];
      
          // Walk over and identify back references to build the capturedGroups
          // mapping.
          for (var i = 0, groupIndex = 0; i < n; ++i) {
            var p = parts[i];
            if (p === '(') {
              // groups are 1-indexed, so max group index is count of '('
              ++groupIndex;
            } else if ('\\' === p.charAt(0)) {
              var decimalValue = +p.substring(1);
              if (decimalValue) {
                if (decimalValue <= groupIndex) {
                  capturedGroups[decimalValue] = -1;
                } else {
                  // Replace with an unambiguous escape sequence so that
                  // an octal escape sequence does not turn into a backreference
                  // to a capturing group from an earlier regex.
                  parts[i] = encodeEscape(decimalValue);
                }
              }
            }
          }
      
          // Renumber groups and reduce capturing groups to non-capturing groups
          // where possible.
          for (var i = 1; i < capturedGroups.length; ++i) {
            if (-1 === capturedGroups[i]) {
              capturedGroups[i] = ++capturedGroupIndex;
            }
          }
          for (var i = 0, groupIndex = 0; i < n; ++i) {
            var p = parts[i];
            if (p === '(') {
              ++groupIndex;
              if (!capturedGroups[groupIndex]) {
                parts[i] = '(?:';
              }
            } else if ('\\' === p.charAt(0)) {
              var decimalValue = +p.substring(1);
              if (decimalValue && decimalValue <= groupIndex) {
                parts[i] = '\\' + capturedGroups[decimalValue];
              }
            }
          }
      
          // Remove any prefix anchors so that the output will match anywhere.
          // ^^ really does mean an anchored match though.
          for (var i = 0; i < n; ++i) {
            if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
          }
      
          // Expand letters to groups to handle mixing of case-sensitive and
          // case-insensitive patterns if necessary.
          if (regex.ignoreCase && needToFoldCase) {
            for (var i = 0; i < n; ++i) {
              var p = parts[i];
              var ch0 = p.charAt(0);
              if (p.length >= 2 && ch0 === '[') {
                parts[i] = caseFoldCharset(p);
              } else if (ch0 !== '\\') {
                // TODO: handle letters in numeric escapes.
                parts[i] = p.replace(
                    /[a-zA-Z]/g,
                    function (ch) {
                      var cc = ch.charCodeAt(0);
                      return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
                    });
              }
            }
          }
      
          return parts.join('');
        }
      
        var rewritten = [];
        for (var i = 0, n = regexs.length; i < n; ++i) {
          var regex = regexs[i];
          if (regex.global || regex.multiline) { throw new Error('' + regex); }
          rewritten.push(
              '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
        }
      
        return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
      }
    
      /**
       * Split markup into a string of source code and an array mapping ranges in
       * that string to the text nodes in which they appear.
       *
       * <p>
       * The HTML DOM structure:</p>
       * <pre>
       * (Element   "p"
       *   (Element "b"
       *     (Text  "print "))       ; #1
       *   (Text    "'Hello '")      ; #2
       *   (Element "br")            ; #3
       *   (Text    "  + 'World';")) ; #4
       * </pre>
       * <p>
       * corresponds to the HTML
       * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>
       *
       * <p>
       * It will produce the output:</p>
       * <pre>
       * {
       *   sourceCode: "print 'Hello '\n  + 'World';",
       *   //                     1          2
       *   //           012345678901234 5678901234567
       *   spans: [0, #1, 6, #2, 14, #3, 15, #4]
       * }
       * </pre>
       * <p>
       * where #1 is a reference to the {@code "print "} text node above, and so
       * on for the other text nodes.
       * </p>
       *
       * <p>
       * The {@code} spans array is an array of pairs.  Even elements are the start
       * indices of substrings, and odd elements are the text nodes (or BR elements)
       * that contain the text for those substrings.
       * Substrings continue until the next index or the end of the source.
       * </p>
       *
       * @param {Node} node an HTML DOM subtree containing source-code.
       * @param {boolean} isPreformatted true if white-space in text nodes should
       *    be considered significant.
       * @return {Object} source code and the text nodes in which they occur.
       */
      function extractSourceSpans(node, isPreformatted) {
        var nocode = /(?:^|\s)nocode(?:\s|$)/;
      
        var chunks = [];
        var length = 0;
        var spans = [];
        var k = 0;
      
        function walk(node) {
          var type = node.nodeType;
          if (type == 1) {  // Element
            if (nocode.test(node.className)) { return; }
            for (var child = node.firstChild; child; child = child.nextSibling) {
              walk(child);
            }
            var nodeName = node.nodeName.toLowerCase();
            if ('br' === nodeName || 'li' === nodeName) {
              chunks[k] = '\n';
              spans[k << 1] = length++;
              spans[(k++ << 1) | 1] = node;
            }
          } else if (type == 3 || type == 4) {  // Text
            var text = node.nodeValue;
            if (text.length) {
              if (!isPreformatted) {
                text = text.replace(/[ \t\r\n]+/g, ' ');
              } else {
                text = text.replace(/\r\n?/g, '\n');  // Normalize newlines.
              }
              // TODO: handle tabs here?
              chunks[k] = text;
              spans[k << 1] = length;
              length += text.length;
              spans[(k++ << 1) | 1] = node;
            }
          }
        }
      
        walk(node);
      
        return {
          sourceCode: chunks.join('').replace(/\n$/, ''),
          spans: spans
        };
      }
    
      /**
       * Apply the given language handler to sourceCode and add the resulting
       * decorations to out.
       * @param {number} basePos the index of sourceCode within the chunk of source
       *    whose decorations are already present on out.
       */
      function appendDecorations(basePos, sourceCode, langHandler, out) {
        if (!sourceCode) { return; }
        var job = {
          sourceCode: sourceCode,
          basePos: basePos
        };
        langHandler(job);
        out.push.apply(out, job.decorations);
      }
    
      var notWs = /\S/;
    
      /**
       * Given an element, if it contains only one child element and any text nodes
       * it contains contain only space characters, return the sole child element.
       * Otherwise returns undefined.
       * <p>
       * This is meant to return the CODE element in {@code <pre><code ...>} when
       * there is a single child element that contains all the non-space textual
       * content, but not to return anything where there are multiple child elements
       * as in {@code <pre><code>...</code><code>...</code></pre>} or when there
       * is textual content.
       */
      function childContentWrapper(element) {
        var wrapper = undefined;
        for (var c = element.firstChild; c; c = c.nextSibling) {
          var type = c.nodeType;
          wrapper = (type === 1)  // Element Node
              ? (wrapper ? element : c)
              : (type === 3)  // Text Node
              ? (notWs.test(c.nodeValue) ? element : wrapper)
              : wrapper;
        }
        return wrapper === element ? undefined : wrapper;
      }
    
      /** Given triples of [style, pattern, context] returns a lexing function,
        * The lexing function interprets the patterns to find token boundaries and
        * returns a decoration list of the form
        * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
        * where index_n is an index into the sourceCode, and style_n is a style
        * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
        * all characters in sourceCode[index_n-1:index_n].
        *
        * The stylePatterns is a list whose elements have the form
        * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
        *
        * Style is a style constant like PR_PLAIN, or can be a string of the
        * form 'lang-FOO', where FOO is a language extension describing the
        * language of the portion of the token in $1 after pattern executes.
        * E.g., if style is 'lang-lisp', and group 1 contains the text
        * '(hello (world))', then that portion of the token will be passed to the
        * registered lisp handler for formatting.
        * The text before and after group 1 will be restyled using this decorator
        * so decorators should take care that this doesn't result in infinite
        * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
        * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
        * '<script>foo()<\/script>', which would cause the current decorator to
        * be called with '<script>' which would not match the same rule since
        * group 1 must not be empty, so it would be instead styled as PR_TAG by
        * the generic tag rule.  The handler registered for the 'js' extension would
        * then be called with 'foo()', and finally, the current decorator would
        * be called with '<\/script>' which would not match the original rule and
        * so the generic tag rule would identify it as a tag.
        *
        * Pattern must only match prefixes, and if it matches a prefix, then that
        * match is considered a token with the same style.
        *
        * Context is applied to the last non-whitespace, non-comment token
        * recognized.
        *
        * Shortcut is an optional string of characters, any of which, if the first
        * character, gurantee that this pattern and only this pattern matches.
        *
        * @param {Array} shortcutStylePatterns patterns that always start with
        *   a known character.  Must have a shortcut string.
        * @param {Array} fallthroughStylePatterns patterns that will be tried in
        *   order if the shortcut ones fail.  May have shortcuts.
        *
        * @return {function (Object)} a
        *   function that takes source code and returns a list of decorations.
        */
      function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
        var shortcuts = {};
        var tokenizer;
        (function () {
          var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
          var allRegexs = [];
          var regexKeys = {};
          for (var i = 0, n = allPatterns.length; i < n; ++i) {
            var patternParts = allPatterns[i];
            var shortcutChars = patternParts[3];
            if (shortcutChars) {
              for (var c = shortcutChars.length; --c >= 0;) {
                shortcuts[shortcutChars.charAt(c)] = patternParts;
              }
            }
            var regex = patternParts[1];
            var k = '' + regex;
            if (!regexKeys.hasOwnProperty(k)) {
              allRegexs.push(regex);
              regexKeys[k] = null;
            }
          }
          allRegexs.push(/[\0-\uffff]/);
          tokenizer = combinePrefixPatterns(allRegexs);
        })();
    
        var nPatterns = fallthroughStylePatterns.length;
    
        /**
         * Lexes job.sourceCode and produces an output array job.decorations of
         * style classes preceded by the position at which they start in
         * job.sourceCode in order.
         *
         * @param {Object} job an object like <pre>{
         *    sourceCode: {string} sourceText plain text,
         *    basePos: {int} position of job.sourceCode in the larger chunk of
         *        sourceCode.
         * }</pre>
         */
        var decorate = function (job) {
          var sourceCode = job.sourceCode, basePos = job.basePos;
          /** Even entries are positions in source in ascending order.  Odd enties
            * are style markers (e.g., PR_COMMENT) that run from that position until
            * the end.
            * @type {Array.<number|string>}
            */
          var decorations = [basePos, PR_PLAIN];
          var pos = 0;  // index into sourceCode
          var tokens = sourceCode.match(tokenizer) || [];
          var styleCache = {};
    
          for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
            var token = tokens[ti];
            var style = styleCache[token];
            var match = void 0;
    
            var isEmbedded;
            if (typeof style === 'string') {
              isEmbedded = false;
            } else {
              var patternParts = shortcuts[token.charAt(0)];
              if (patternParts) {
                match = token.match(patternParts[1]);
                style = patternParts[0];
              } else {
                for (var i = 0; i < nPatterns; ++i) {
                  patternParts = fallthroughStylePatterns[i];
                  match = token.match(patternParts[1]);
                  if (match) {
                    style = patternParts[0];
                    break;
                  }
                }
    
                if (!match) {  // make sure that we make progress
                  style = PR_PLAIN;
                }
              }
    
              isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
              if (isEmbedded && !(match && typeof match[1] === 'string')) {
                isEmbedded = false;
                style = PR_SOURCE;
              }
    
              if (!isEmbedded) { styleCache[token] = style; }
            }
    
            var tokenStart = pos;
            pos += token.length;
    
            if (!isEmbedded) {
              decorations.push(basePos + tokenStart, style);
            } else {  // Treat group 1 as an embedded block of source code.
              var embeddedSource = match[1];
              var embeddedSourceStart = token.indexOf(embeddedSource);
              var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
              if (match[2]) {
                // If embeddedSource can be blank, then it would match at the
                // beginning which would cause us to infinitely recurse on the
                // entire token, so we catch the right context in match[2].
                embeddedSourceEnd = token.length - match[2].length;
                embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
              }
              var lang = style.substring(5);
              // Decorate the left of the embedded source
              appendDecorations(
                  basePos + tokenStart,
                  token.substring(0, embeddedSourceStart),
                  decorate, decorations);
              // Decorate the embedded source
              appendDecorations(
                  basePos + tokenStart + embeddedSourceStart,
                  embeddedSource,
                  langHandlerForExtension(lang, embeddedSource),
                  decorations);
              // Decorate the right of the embedded section
              appendDecorations(
                  basePos + tokenStart + embeddedSourceEnd,
                  token.substring(embeddedSourceEnd),
                  decorate, decorations);
            }
          }
          job.decorations = decorations;
        };
        return decorate;
      }
    
      /** returns a function that produces a list of decorations from source text.
        *
        * This code treats ", ', and ` as string delimiters, and \ as a string
        * escape.  It does not recognize perl's qq() style strings.
        * It has no special handling for double delimiter escapes as in basic, or
        * the tripled delimiters used in python, but should work on those regardless
        * although in those cases a single string literal may be broken up into
        * multiple adjacent string literals.
        *
        * It recognizes C, C++, and shell style comments.
        *
        * @param {Object} options a set of optional parameters.
        * @return {function (Object)} a function that examines the source code
        *     in the input job and builds the decoration list.
        */
      function sourceDecorator(options) {
        var shortcutStylePatterns = [], fallthroughStylePatterns = [];
        if (options['tripleQuotedStrings']) {
          // '''multi-line-string''', 'single-line-string', and double-quoted
          shortcutStylePatterns.push(
              [PR_STRING,  /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
               null, '\'"']);
        } else if (options['multiLineStrings']) {
          // 'multi-line-string', "multi-line-string"
          shortcutStylePatterns.push(
              [PR_STRING,  /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
               null, '\'"`']);
        } else {
          // 'single-line-string', "single-line-string"
          shortcutStylePatterns.push(
              [PR_STRING,
               /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
               null, '"\'']);
        }
        if (options['verbatimStrings']) {
          // verbatim-string-literal production from the C# grammar.  See issue 93.
          fallthroughStylePatterns.push(
              [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
        }
        var hc = options['hashComments'];
        if (hc) {
          if (options['cStyleComments']) {
            if (hc > 1) {  // multiline hash comments
              shortcutStylePatterns.push(
                  [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
            } else {
              // Stop C preprocessor declarations at an unclosed open comment
              shortcutStylePatterns.push(
                  [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
                   null, '#']);
            }
            // #include <stdio.h>
            fallthroughStylePatterns.push(
                [PR_STRING,
                 /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,
                 null]);
          } else {
            shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
          }
        }
        if (options['cStyleComments']) {
          fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
          fallthroughStylePatterns.push(
              [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
        }
        var regexLiterals = options['regexLiterals'];
        if (regexLiterals) {
          /**
           * @const
           */
          var regexExcls = regexLiterals > 1
            ? ''  // Multiline regex literals
            : '\n\r';
          /**
           * @const
           */
          var regexAny = regexExcls ? '.' : '[\\S\\s]';
          /**
           * @const
           */
          var REGEX_LITERAL = (
              // A regular expression literal starts with a slash that is
              // not followed by * or / so that it is not confused with
              // comments.
              '/(?=[^/*' + regexExcls + '])'
              // and then contains any number of raw characters,
              + '(?:[^/\\x5B\\x5C' + regexExcls + ']'
              // escape sequences (\x5C),
              +    '|\\x5C' + regexAny
              // or non-nesting character sets (\x5B\x5D);
              +    '|\\x5B(?:[^\\x5C\\x5D' + regexExcls + ']'
              +             '|\\x5C' + regexAny + ')*(?:\\x5D|$))+'
              // finally closed by a /.
              + '/');
          fallthroughStylePatterns.push(
              ['lang-regex',
               RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
               ]);
        }
    
        var types = options['types'];
        if (types) {
          fallthroughStylePatterns.push([PR_TYPE, types]);
        }
    
        var keywords = ("" + options['keywords']).replace(/^ | $/g, '');
        if (keywords.length) {
          fallthroughStylePatterns.push(
              [PR_KEYWORD,
               new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'),
               null]);
        }
    
        shortcutStylePatterns.push([PR_PLAIN,       /^\s+/, null, ' \r\n\t\xA0']);
    
        var punctuation =
          // The Bash man page says
    
          // A word is a sequence of characters considered as a single
          // unit by GRUB. Words are separated by metacharacters,
          // which are the following plus space, tab, and newline: { }
          // | & $ ; < >
          // ...
          
          // A word beginning with # causes that word and all remaining
          // characters on that line to be ignored.
    
          // which means that only a '#' after /(?:^|[{}|&$;<>\s])/ starts a
          // comment but empirically
          // $ echo {#}
          // {#}
          // $ echo \$#
          // $#
          // $ echo }#
          // }#
    
          // so /(?:^|[|&;<>\s])/ is more appropriate.
    
          // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3
          // suggests that this definition is compatible with a
          // default mode that tries to use a single token definition
          // to recognize both bash/python style comments and C
          // preprocessor directives.
    
          // This definition of punctuation does not include # in the list of
          // follow-on exclusions, so # will not be broken before if preceeded
          // by a punctuation character.  We could try to exclude # after
          // [|&;<>] but that doesn't seem to cause many major problems.
          // If that does turn out to be a problem, we should change the below
          // when hc is truthy to include # in the run of punctuation characters
          // only when not followint [|&;<>].
          '^.[^\\s\\w.$@\'"`/\\\\]*';
        if (options['regexLiterals']) {
          punctuation += '(?!\s*\/)';
        }
    
        fallthroughStylePatterns.push(
            // TODO(mikesamuel): recognize non-latin letters and numerals in idents
            [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],
            [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
            [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],
            [PR_LITERAL,
             new RegExp(
                 '^(?:'
                 // A hex number
                 + '0x[a-f0-9]+'
                 // or an octal or decimal number,
                 + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
                 // possibly in scientific notation
                 + '(?:e[+\\-]?\\d+)?'
                 + ')'
                 // with an optional modifier like UL for unsigned long
                 + '[a-z]*', 'i'),
             null, '0123456789'],
            // Don't treat escaped quotes in bash as starting strings.
            // See issue 144.
            [PR_PLAIN,       /^\\[\s\S]?/, null],
            [PR_PUNCTUATION, new RegExp(punctuation), null]);
    
        return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
      }
    
      var decorateSource = sourceDecorator({
            'keywords': ALL_KEYWORDS,
            'hashComments': true,
            'cStyleComments': true,
            'multiLineStrings': true,
            'regexLiterals': true
          });
    
      /**
       * Given a DOM subtree, wraps it in a list, and puts each line into its own
       * list item.
       *
       * @param {Node} node modified in place.  Its content is pulled into an
       *     HTMLOListElement, and each line is moved into a separate list item.
       *     This requires cloning elements, so the input might not have unique
       *     IDs after numbering.
       * @param {boolean} isPreformatted true iff white-space in text nodes should
       *     be treated as significant.
       */
      function numberLines(node, opt_startLineNum, isPreformatted) {
        var nocode = /(?:^|\s)nocode(?:\s|$)/;
        var lineBreak = /\r\n?|\n/;
      
        var document = node.ownerDocument;
      
        var li = document.createElement('li');
        while (node.firstChild) {
          li.appendChild(node.firstChild);
        }
        // An array of lines.  We split below, so this is initialized to one
        // un-split line.
        var listItems = [li];
      
        function walk(node) {
          var type = node.nodeType;
          if (type == 1 && !nocode.test(node.className)) {  // Element
            if ('br' === node.nodeName) {
              breakAfter(node);
              // Discard the <BR> since it is now flush against a </LI>.
              if (node.parentNode) {
                node.parentNode.removeChild(node);
              }
            } else {
              for (var child = node.firstChild; child; child = child.nextSibling) {
                walk(child);
              }
            }
          } else if ((type == 3 || type == 4) && isPreformatted) {  // Text
            var text = node.nodeValue;
            var match = text.match(lineBreak);
            if (match) {
              var firstLine = text.substring(0, match.index);
              node.nodeValue = firstLine;
              var tail = text.substring(match.index + match[0].length);
              if (tail) {
                var parent = node.parentNode;
                parent.insertBefore(
                  document.createTextNode(tail), node.nextSibling);
              }
              breakAfter(node);
              if (!firstLine) {
                // Don't leave blank text nodes in the DOM.
                node.parentNode.removeChild(node);
              }
            }
          }
        }
      
        // Split a line after the given node.
        function breakAfter(lineEndNode) {
          // If there's nothing to the right, then we can skip ending the line
          // here, and move root-wards since splitting just before an end-tag
          // would require us to create a bunch of empty copies.
          while (!lineEndNode.nextSibling) {
            lineEndNode = lineEndNode.parentNode;
            if (!lineEndNode) { return; }
          }
      
          function breakLeftOf(limit, copy) {
            // Clone shallowly if this node needs to be on both sides of the break.
            var rightSide = copy ? limit.cloneNode(false) : limit;
            var parent = limit.parentNode;
            if (parent) {
              // We clone the parent chain.
              // This helps us resurrect important styling elements that cross lines.
              // E.g. in <i>Foo<br>Bar</i>
              // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.
              var parentClone = breakLeftOf(parent, 1);
              // Move the clone and everything to the right of the original
              // onto the cloned parent.
              var next = limit.nextSibling;
              parentClone.appendChild(rightSide);
              for (var sibling = next; sibling; sibling = next) {
                next = sibling.nextSibling;
                parentClone.appendChild(sibling);
              }
            }
            return rightSide;
          }
      
          var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);
      
          // Walk the parent chain until we reach an unattached LI.
          for (var parent;
               // Check nodeType since IE invents document fragments.
               (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {
            copiedListItem = parent;
          }
          // Put it on the list of lines for later processing.
          listItems.push(copiedListItem);
        }
      
        // Split lines while there are lines left to split.
        for (var i = 0;  // Number of lines that have been split so far.
             i < listItems.length;  // length updated by breakAfter calls.
             ++i) {
          walk(listItems[i]);
        }
      
        // Make sure numeric indices show correctly.
        if (opt_startLineNum === (opt_startLineNum|0)) {
          listItems[0].setAttribute('value', opt_startLineNum);
        }
      
        var ol = document.createElement('ol');
        ol.className = 'linenums';
        var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
        for (var i = 0, n = listItems.length; i < n; ++i) {
          li = listItems[i];
          // Stick a class on the LIs so that stylesheets can
          // color odd/even rows, or any other row pattern that
          // is co-prime with 10.
          li.className = 'L' + ((i + offset) % 10);
          if (!li.firstChild) {
            li.appendChild(document.createTextNode('\xA0'));
          }
          ol.appendChild(li);
        }
      
        node.appendChild(ol);
      }
      /**
       * Breaks {@code job.sourceCode} around style boundaries in
       * {@code job.decorations} and modifies {@code job.sourceNode} in place.
       * @param {Object} job like <pre>{
       *    sourceCode: {string} source as plain text,
       *    sourceNode: {HTMLElement} the element containing the source,
       *    spans: {Array.<number|Node>} alternating span start indices into source
       *       and the text node or element (e.g. {@code <BR>}) corresponding to that
       *       span.
       *    decorations: {Array.<number|string} an array of style classes preceded
       *       by the position at which they start in job.sourceCode in order
       * }</pre>
       * @private
       */
      function recombineTagsAndDecorations(job) {
        var isIE8OrEarlier = /\bMSIE\s(\d+)/.exec(navigator.userAgent);
        isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;
        var newlineRe = /\n/g;
      
        var source = job.sourceCode;
        var sourceLength = source.length;
        // Index into source after the last code-unit recombined.
        var sourceIndex = 0;
      
        var spans = job.spans;
        var nSpans = spans.length;
        // Index into spans after the last span which ends at or before sourceIndex.
        var spanIndex = 0;
      
        var decorations = job.decorations;
        var nDecorations = decorations.length;
        // Index into decorations after the last decoration which ends at or before
        // sourceIndex.
        var decorationIndex = 0;
      
        // Remove all zero-length decorations.
        decorations[nDecorations] = sourceLength;
        var decPos, i;
        for (i = decPos = 0; i < nDecorations;) {
          if (decorations[i] !== decorations[i + 2]) {
            decorations[decPos++] = decorations[i++];
            decorations[decPos++] = decorations[i++];
          } else {
            i += 2;
          }
        }
        nDecorations = decPos;
      
        // Simplify decorations.
        for (i = decPos = 0; i < nDecorations;) {
          var startPos = decorations[i];
          // Conflate all adjacent decorations that use the same style.
          var startDec = decorations[i + 1];
          var end = i + 2;
          while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {
            end += 2;
          }
          decorations[decPos++] = startPos;
          decorations[decPos++] = startDec;
          i = end;
        }
      
        nDecorations = decorations.length = decPos;
      
        var sourceNode = job.sourceNode;
        var oldDisplay;
        if (sourceNode) {
          oldDisplay = sourceNode.style.display;
          sourceNode.style.display = 'none';
        }
        try {
          var decoration = null;
          while (spanIndex < nSpans) {
            var spanStart = spans[spanIndex];
            var spanEnd = spans[spanIndex + 2] || sourceLength;
      
            var decEnd = decorations[decorationIndex + 2] || sourceLength;
      
            var end = Math.min(spanEnd, decEnd);
      
            var textNode = spans[spanIndex + 1];
            var styledText;
            if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s
                // Don't introduce spans around empty text nodes.
                && (styledText = source.substring(sourceIndex, end))) {
              // This may seem bizarre, and it is.  Emitting LF on IE causes the
              // code to display with spaces instead of line breaks.
              // Emitting Windows standard issue linebreaks (CRLF) causes a blank
              // space to appear at the beginning of every line but the first.
              // Emitting an old Mac OS 9 line separator makes everything spiffy.
              if (isIE8OrEarlier) {
                styledText = styledText.replace(newlineRe, '\r');
              }
              textNode.nodeValue = styledText;
              var document = textNode.ownerDocument;
              var span = document.createElement('span');
              span.className = decorations[decorationIndex + 1];
              var parentNode = textNode.parentNode;
              parentNode.replaceChild(span, textNode);
              span.appendChild(textNode);
              if (sourceIndex < spanEnd) {  // Split off a text node.
                spans[spanIndex + 1] = textNode
                    // TODO: Possibly optimize by using '' if there's no flicker.
                    = document.createTextNode(source.substring(end, spanEnd));
                parentNode.insertBefore(textNode, span.nextSibling);
              }
            }
      
            sourceIndex = end;
      
            if (sourceIndex >= spanEnd) {
              spanIndex += 2;
            }
            if (sourceIndex >= decEnd) {
              decorationIndex += 2;
            }
          }
        } finally {
          if (sourceNode) {
            sourceNode.style.display = oldDisplay;
          }
        }
      }
    
      /** Maps language-specific file extensions to handlers. */
      var langHandlerRegistry = {};
      /** Register a language handler for the given file extensions.
        * @param {function (Object)} handler a function from source code to a list
        *      of decorations.  Takes a single argument job which describes the
        *      state of the computation.   The single parameter has the form
        *      {@code {
        *        sourceCode: {string} as plain text.
        *        decorations: {Array.<number|string>} an array of style classes
        *                     preceded by the position at which they start in
        *                     job.sourceCode in order.
        *                     The language handler should assigned this field.
        *        basePos: {int} the position of source in the larger source chunk.
        *                 All positions in the output decorations array are relative
        *                 to the larger source chunk.
        *      } }
        * @param {Array.<string>} fileExtensions
        */
      function registerLangHandler(handler, fileExtensions) {
        for (var i = fileExtensions.length; --i >= 0;) {
          var ext = fileExtensions[i];
          if (!langHandlerRegistry.hasOwnProperty(ext)) {
            langHandlerRegistry[ext] = handler;
          } else if (win['console']) {
            console['warn']('cannot override language handler %s', ext);
          }
        }
      }
      function langHandlerForExtension(extension, source) {
        if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
          // Treat it as markup if the first non whitespace character is a < and
          // the last non-whitespace character is a >.
          extension = /^\s*</.test(source)
              ? 'default-markup'
              : 'default-code';
        }
        return langHandlerRegistry[extension];
      }
      registerLangHandler(decorateSource, ['default-code']);
      registerLangHandler(
          createSimpleLexer(
              [],
              [
               [PR_PLAIN,       /^[^<?]+/],
               [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
               [PR_COMMENT,     /^<\!--[\s\S]*?(?:-\->|$)/],
               // Unescaped content in an unknown language
               ['lang-',        /^<\?([\s\S]+?)(?:\?>|$)/],
               ['lang-',        /^<%([\s\S]+?)(?:%>|$)/],
               [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
               ['lang-',        /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
               // Unescaped content in javascript.  (Or possibly vbscript).
               ['lang-js',      /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
               // Contains unescaped stylesheet content
               ['lang-css',     /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
               ['lang-in.tag',  /^(<\/?[a-z][^<>]*>)/i]
              ]),
          ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
      registerLangHandler(
          createSimpleLexer(
              [
               [PR_PLAIN,        /^[\s]+/, null, ' \t\r\n'],
               [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
               ],
              [
               [PR_TAG,          /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
               [PR_ATTRIB_NAME,  /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
               ['lang-uq.val',   /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
               [PR_PUNCTUATION,  /^[=<>\/]+/],
               ['lang-js',       /^on\w+\s*=\s*\"([^\"]+)\"/i],
               ['lang-js',       /^on\w+\s*=\s*\'([^\']+)\'/i],
               ['lang-js',       /^on\w+\s*=\s*([^\"\'>\s]+)/i],
               ['lang-css',      /^style\s*=\s*\"([^\"]+)\"/i],
               ['lang-css',      /^style\s*=\s*\'([^\']+)\'/i],
               ['lang-css',      /^style\s*=\s*([^\"\'>\s]+)/i]
               ]),
          ['in.tag']);
      registerLangHandler(
          createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
      registerLangHandler(sourceDecorator({
              'keywords': CPP_KEYWORDS,
              'hashComments': true,
              'cStyleComments': true,
              'types': C_TYPES
            }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
      registerLangHandler(sourceDecorator({
              'keywords': 'null,true,false'
            }), ['json']);
      registerLangHandler(sourceDecorator({
              'keywords': CSHARP_KEYWORDS,
              'hashComments': true,
              'cStyleComments': true,
              'verbatimStrings': true,
              'types': C_TYPES
            }), ['cs']);
      registerLangHandler(sourceDecorator({
              'keywords': JAVA_KEYWORDS,
              'cStyleComments': true
            }), ['java']);
      registerLangHandler(sourceDecorator({
              'keywords': SH_KEYWORDS,
              'hashComments': true,
              'multiLineStrings': true
            }), ['bash', 'bsh', 'csh', 'sh']);
      registerLangHandler(sourceDecorator({
              'keywords': PYTHON_KEYWORDS,
              'hashComments': true,
              'multiLineStrings': true,
              'tripleQuotedStrings': true
            }), ['cv', 'py', 'python']);
      registerLangHandler(sourceDecorator({
              'keywords': PERL_KEYWORDS,
              'hashComments': true,
              'multiLineStrings': true,
              'regexLiterals': 2  // multiline regex literals
            }), ['perl', 'pl', 'pm']);
      registerLangHandler(sourceDecorator({
              'keywords': RUBY_KEYWORDS,
              'hashComments': true,
              'multiLineStrings': true,
              'regexLiterals': true
            }), ['rb', 'ruby']);
      registerLangHandler(sourceDecorator({
              'keywords': JSCRIPT_KEYWORDS,
              'cStyleComments': true,
              'regexLiterals': true
            }), ['javascript', 'js']);
      registerLangHandler(sourceDecorator({
              'keywords': COFFEE_KEYWORDS,
              'hashComments': 3,  // ### style block comments
              'cStyleComments': true,
              'multilineStrings': true,
              'tripleQuotedStrings': true,
              'regexLiterals': true
            }), ['coffee']);
      registerLangHandler(sourceDecorator({
              'keywords': RUST_KEYWORDS,
              'cStyleComments': true,
              'multilineStrings': true
            }), ['rc', 'rs', 'rust']);
      registerLangHandler(
          createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
    
      function applyDecorator(job) {
        var opt_langExtension = job.langExtension;
    
        try {
          // Extract tags, and convert the source code to plain text.
          var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);
          /** Plain text. @type {string} */
          var source = sourceAndSpans.sourceCode;
          job.sourceCode = source;
          job.spans = sourceAndSpans.spans;
          job.basePos = 0;
    
          // Apply the appropriate language handler
          langHandlerForExtension(opt_langExtension, source)(job);
    
          // Integrate the decorations and tags back into the source code,
          // modifying the sourceNode in place.
          recombineTagsAndDecorations(job);
        } catch (e) {
          if (win['console']) {
            console['log'](e && e['stack'] || e);
          }
        }
      }
    
      /**
       * Pretty print a chunk of code.
       * @param sourceCodeHtml {string} The HTML to pretty print.
       * @param opt_langExtension {string} The language name to use.
       *     Typically, a filename extension like 'cpp' or 'java'.
       * @param opt_numberLines {number|boolean} True to number lines,
       *     or the 1-indexed number of the first line in sourceCodeHtml.
       */
      function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
        var container = document.createElement('div');
        // This could cause images to load and onload listeners to fire.
        // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
        // We assume that the inner HTML is from a trusted source.
        // The pre-tag is required for IE8 which strips newlines from innerHTML
        // when it is injected into a <pre> tag.
        // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie
        // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript
        container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';
        container = container.firstChild;
        if (opt_numberLines) {
          numberLines(container, opt_numberLines, true);
        }
    
        var job = {
          langExtension: opt_langExtension,
          numberLines: opt_numberLines,
          sourceNode: container,
          pre: 1
        };
        applyDecorator(job);
        return container.innerHTML;
      }
    
       /**
        * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
        * {@code class=prettyprint} and prettify them.
        *
        * @param {Function} opt_whenDone called when prettifying is done.
        * @param {HTMLElement|HTMLDocument} opt_root an element or document
        *   containing all the elements to pretty print.
        *   Defaults to {@code document.body}.
        */
      function $prettyPrint(opt_whenDone, opt_root) {
        var root = opt_root || document.body;
        var doc = root.ownerDocument || document;
        function byTagName(tn) { return root.getElementsByTagName(tn); }
        // fetch a list of nodes to rewrite
        var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
        var elements = [];
        for (var i = 0; i < codeSegments.length; ++i) {
          for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
            elements.push(codeSegments[i][j]);
          }
        }
        codeSegments = null;
    
        var clock = Date;
        if (!clock['now']) {
          clock = { 'now': function () { return +(new Date); } };
        }
    
        // The loop is broken into a series of continuations to make sure that we
        // don't make the browser unresponsive when rewriting a large page.
        var k = 0;
        var prettyPrintingJob;
    
        var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/;
        var prettyPrintRe = /\bprettyprint\b/;
        var prettyPrintedRe = /\bprettyprinted\b/;
        var preformattedTagNameRe = /pre|xmp/i;
        var codeRe = /^code$/i;
        var preCodeXmpRe = /^(?:pre|code|xmp)$/i;
        var EMPTY = {};
    
        function doWork() {
          var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?
                         clock['now']() + 250 /* ms */ :
                         Infinity);
          for (; k < elements.length && clock['now']() < endTime; k++) {
            var cs = elements[k];
    
            // Look for a preceding comment like
            // <?prettify lang="..." linenums="..."?>
            var attrs = EMPTY;
            {
              for (var preceder = cs; (preceder = preceder.previousSibling);) {
                var nt = preceder.nodeType;
                // <?foo?> is parsed by HTML 5 to a comment node (8)
                // like <!--?foo?-->, but in XML is a processing instruction
                var value = (nt === 7 || nt === 8) && preceder.nodeValue;
                if (value
                    ? !/^\??prettify\b/.test(value)
                    : (nt !== 3 || /\S/.test(preceder.nodeValue))) {
                  // Skip over white-space text nodes but not others.
                  break;
                }
                if (value) {
                  attrs = {};
                  value.replace(
                      /\b(\w+)=([\w:.%+-]+)/g,
                    function (_, name, value) { attrs[name] = value; });
                  break;
                }
              }
            }
    
            var className = cs.className;
            if ((attrs !== EMPTY || prettyPrintRe.test(className))
                // Don't redo this if we've already done it.
                // This allows recalling pretty print to just prettyprint elements
                // that have been added to the page since last call.
                && !prettyPrintedRe.test(className)) {
    
              // make sure this is not nested in an already prettified element
              var nested = false;
              for (var p = cs.parentNode; p; p = p.parentNode) {
                var tn = p.tagName;
                if (preCodeXmpRe.test(tn)
                    && p.className && prettyPrintRe.test(p.className)) {
                  nested = true;
                  break;
                }
              }
              if (!nested) {
                // Mark done.  If we fail to prettyprint for whatever reason,
                // we shouldn't try again.
                cs.className += ' prettyprinted';
    
                // If the classes includes a language extensions, use it.
                // Language extensions can be specified like
                //     <pre class="prettyprint lang-cpp">
                // the language extension "cpp" is used to find a language handler
                // as passed to PR.registerLangHandler.
                // HTML5 recommends that a language be specified using "language-"
                // as the prefix instead.  Google Code Prettify supports both.
                // http://dev.w3.org/html5/spec-author-view/the-code-element.html
                var langExtension = attrs['lang'];
                if (!langExtension) {
                  langExtension = className.match(langExtensionRe);
                  // Support <pre class="prettyprint"><code class="language-c">
                  var wrapper;
                  if (!langExtension && (wrapper = childContentWrapper(cs))
                      && codeRe.test(wrapper.tagName)) {
                    langExtension = wrapper.className.match(langExtensionRe);
                  }
    
                  if (langExtension) { langExtension = langExtension[1]; }
                }
    
                var preformatted;
                if (preformattedTagNameRe.test(cs.tagName)) {
                  preformatted = 1;
                } else {
                  var currentStyle = cs['currentStyle'];
                  var defaultView = doc.defaultView;
                  var whitespace = (
                      currentStyle
                      ? currentStyle['whiteSpace']
                      : (defaultView
                         && defaultView.getComputedStyle)
                      ? defaultView.getComputedStyle(cs, null)
                      .getPropertyValue('white-space')
                      : 0);
                  preformatted = whitespace
                      && 'pre' === whitespace.substring(0, 3);
                }
    
                // Look for a class like linenums or linenums:<n> where <n> is the
                // 1-indexed number of the first line.
                var lineNums = attrs['linenums'];
                if (!(lineNums = lineNums === 'true' || +lineNums)) {
                  lineNums = className.match(/\blinenums\b(?::(\d+))?/);
                  lineNums =
                    lineNums
                    ? lineNums[1] && lineNums[1].length
                      ? +lineNums[1] : true
                    : false;
                }
                if (lineNums) { numberLines(cs, lineNums, preformatted); }
    
                // do the pretty printing
                prettyPrintingJob = {
                  langExtension: langExtension,
                  sourceNode: cs,
                  numberLines: lineNums,
                  pre: preformatted
                };
                applyDecorator(prettyPrintingJob);
              }
            }
          }
          if (k < elements.length) {
            // finish up in a continuation
            setTimeout(doWork, 250);
          } else if ('function' === typeof opt_whenDone) {
            opt_whenDone();
          }
        }
    
        doWork();
      }
    
      /**
       * Contains functions for creating and registering new language handlers.
       * @type {Object}
       */
      var PR = win['PR'] = {
            'createSimpleLexer': createSimpleLexer,
            'registerLangHandler': registerLangHandler,
            'sourceDecorator': sourceDecorator,
            'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
            'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
            'PR_COMMENT': PR_COMMENT,
            'PR_DECLARATION': PR_DECLARATION,
            'PR_KEYWORD': PR_KEYWORD,
            'PR_LITERAL': PR_LITERAL,
            'PR_NOCODE': PR_NOCODE,
            'PR_PLAIN': PR_PLAIN,
            'PR_PUNCTUATION': PR_PUNCTUATION,
            'PR_SOURCE': PR_SOURCE,
            'PR_STRING': PR_STRING,
            'PR_TAG': PR_TAG,
            'PR_TYPE': PR_TYPE,
            'prettyPrintOne':
               IN_GLOBAL_SCOPE
                 ? (win['prettyPrintOne'] = $prettyPrintOne)
                 : (prettyPrintOne = $prettyPrintOne),
            'prettyPrint': prettyPrint =
               IN_GLOBAL_SCOPE
                 ? (win['prettyPrint'] = $prettyPrint)
                 : (prettyPrint = $prettyPrint)
          };
    
      // Make PR available via the Asynchronous Module Definition (AMD) API.
      // Per https://github.com/amdjs/amdjs-api/wiki/AMD:
      // The Asynchronous Module Definition (AMD) API specifies a
      // mechanism for defining modules such that the module and its
      // dependencies can be asynchronously loaded.
      // ...
      // To allow a clear indicator that a global define function (as
      // needed for script src browser loading) conforms to the AMD API,
      // any global define function SHOULD have a property called "amd"
      // whose value is an object. This helps avoid conflict with any
      // other existing JavaScript code that could have defined a define()
      // function that does not conform to the AMD API.
      if (typeof define === "function" && define['amd']) {
        define("google-code-prettify", [], function () {
          return PR; 
        });
      }
    })();
    
    ;(function (global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
        typeof define === 'function' && define.amd ? define(factory) :
        global.moment = factory()
    }(this, (function () { 'use strict';
    
        var hookCallback;
    
        function hooks() {
            return hookCallback.apply(null, arguments);
        }
    
        // This is done to register the method called with moment()
        // without creating circular dependencies.
        function setHookCallback(callback) {
            hookCallback = callback;
        }
    
        function isArray(input) {
            return (
                input instanceof Array ||
                Object.prototype.toString.call(input) === '[object Array]'
            );
        }
    
        function isObject(input) {
            // IE8 will treat undefined and null as object if it wasn't for
            // input != null
            return (
                input != null &&
                Object.prototype.toString.call(input) === '[object Object]'
            );
        }
    
        function hasOwnProp(a, b) {
            return Object.prototype.hasOwnProperty.call(a, b);
        }
    
        function isObjectEmpty(obj) {
            if (Object.getOwnPropertyNames) {
                return Object.getOwnPropertyNames(obj).length === 0;
            } else {
                var k;
                for (k in obj) {
                    if (hasOwnProp(obj, k)) {
                        return false;
                    }
                }
                return true;
            }
        }
    
        function isUndefined(input) {
            return input === void 0;
        }
    
        function isNumber(input) {
            return (
                typeof input === 'number' ||
                Object.prototype.toString.call(input) === '[object Number]'
            );
        }
    
        function isDate(input) {
            return (
                input instanceof Date ||
                Object.prototype.toString.call(input) === '[object Date]'
            );
        }
    
        function map(arr, fn) {
            var res = [],
                i;
            for (i = 0; i < arr.length; ++i) {
                res.push(fn(arr[i], i));
            }
            return res;
        }
    
        function extend(a, b) {
            for (var i in b) {
                if (hasOwnProp(b, i)) {
                    a[i] = b[i];
                }
            }
    
            if (hasOwnProp(b, 'toString')) {
                a.toString = b.toString;
            }
    
            if (hasOwnProp(b, 'valueOf')) {
                a.valueOf = b.valueOf;
            }
    
            return a;
        }
    
        function createUTC(input, format, locale, strict) {
            return createLocalOrUTC(input, format, locale, strict, true).utc();
        }
    
        function defaultParsingFlags() {
            // We need to deep clone this object.
            return {
                empty: false,
                unusedTokens: [],
                unusedInput: [],
                overflow: -2,
                charsLeftOver: 0,
                nullInput: false,
                invalidEra: null,
                invalidMonth: null,
                invalidFormat: false,
                userInvalidated: false,
                iso: false,
                parsedDateParts: [],
                era: null,
                meridiem: null,
                rfc2822: false,
                weekdayMismatch: false,
            };
        }
    
        function getParsingFlags(m) {
            if (m._pf == null) {
                m._pf = defaultParsingFlags();
            }
            return m._pf;
        }
    
        var some;
        if (Array.prototype.some) {
            some = Array.prototype.some;
        } else {
            some = function (fun) {
                var t = Object(this),
                    len = t.length >>> 0,
                    i;
    
                for (i = 0; i < len; i++) {
                    if (i in t && fun.call(this, t[i], i, t)) {
                        return true;
                    }
                }
    
                return false;
            };
        }
    
        function isValid(m) {
            if (m._isValid == null) {
                var flags = getParsingFlags(m),
                    parsedParts = some.call(flags.parsedDateParts, function (i) {
                        return i != null;
                    }),
                    isNowValid =
                        !isNaN(m._d.getTime()) &&
                        flags.overflow < 0 &&
                        !flags.empty &&
                        !flags.invalidEra &&
                        !flags.invalidMonth &&
                        !flags.invalidWeekday &&
                        !flags.weekdayMismatch &&
                        !flags.nullInput &&
                        !flags.invalidFormat &&
                        !flags.userInvalidated &&
                        (!flags.meridiem || (flags.meridiem && parsedParts));
    
                if (m._strict) {
                    isNowValid =
                        isNowValid &&
                        flags.charsLeftOver === 0 &&
                        flags.unusedTokens.length === 0 &&
                        flags.bigHour === undefined;
                }
    
                if (Object.isFrozen == null || !Object.isFrozen(m)) {
                    m._isValid = isNowValid;
                } else {
                    return isNowValid;
                }
            }
            return m._isValid;
        }
    
        function createInvalid(flags) {
            var m = createUTC(NaN);
            if (flags != null) {
                extend(getParsingFlags(m), flags);
            } else {
                getParsingFlags(m).userInvalidated = true;
            }
    
            return m;
        }
    
        // Plugins that add properties should also add the key here (null value),
        // so we can properly clone ourselves.
        var momentProperties = (hooks.momentProperties = []),
            updateInProgress = false;
    
        function copyConfig(to, from) {
            var i, prop, val;
    
            if (!isUndefined(from._isAMomentObject)) {
                to._isAMomentObject = from._isAMomentObject;
            }
            if (!isUndefined(from._i)) {
                to._i = from._i;
            }
            if (!isUndefined(from._f)) {
                to._f = from._f;
            }
            if (!isUndefined(from._l)) {
                to._l = from._l;
            }
            if (!isUndefined(from._strict)) {
                to._strict = from._strict;
            }
            if (!isUndefined(from._tzm)) {
                to._tzm = from._tzm;
            }
            if (!isUndefined(from._isUTC)) {
                to._isUTC = from._isUTC;
            }
            if (!isUndefined(from._offset)) {
                to._offset = from._offset;
            }
            if (!isUndefined(from._pf)) {
                to._pf = getParsingFlags(from);
            }
            if (!isUndefined(from._locale)) {
                to._locale = from._locale;
            }
    
            if (momentProperties.length > 0) {
                for (i = 0; i < momentProperties.length; i++) {
                    prop = momentProperties[i];
                    val = from[prop];
                    if (!isUndefined(val)) {
                        to[prop] = val;
                    }
                }
            }
    
            return to;
        }
    
        // Moment prototype object
        function Moment(config) {
            copyConfig(this, config);
            this._d = new Date(config._d != null ? config._d.getTime() : NaN);
            if (!this.isValid()) {
                this._d = new Date(NaN);
            }
            // Prevent infinite loop in case updateOffset creates new moment
            // objects.
            if (updateInProgress === false) {
                updateInProgress = true;
                hooks.updateOffset(this);
                updateInProgress = false;
            }
        }
    
        function isMoment(obj) {
            return (
                obj instanceof Moment || (obj != null && obj._isAMomentObject != null)
            );
        }
    
        function warn(msg) {
            if (
                hooks.suppressDeprecationWarnings === false &&
                typeof console !== 'undefined' &&
                console.warn
            ) {
                console.warn('Deprecation warning: ' + msg);
            }
        }
    
        function deprecate(msg, fn) {
            var firstTime = true;
    
            return extend(function () {
                if (hooks.deprecationHandler != null) {
                    hooks.deprecationHandler(null, msg);
                }
                if (firstTime) {
                    var args = [],
                        arg,
                        i,
                        key;
                    for (i = 0; i < arguments.length; i++) {
                        arg = '';
                        if (typeof arguments[i] === 'object') {
                            arg += '\n[' + i + '] ';
                            for (key in arguments[0]) {
                                if (hasOwnProp(arguments[0], key)) {
                                    arg += key + ': ' + arguments[0][key] + ', ';
                                }
                            }
                            arg = arg.slice(0, -2); // Remove trailing comma and space
                        } else {
                            arg = arguments[i];
                        }
                        args.push(arg);
                    }
                    warn(
                        msg +
                            '\nArguments: ' +
                            Array.prototype.slice.call(args).join('') +
                            '\n' +
                            new Error().stack
                    );
                    firstTime = false;
                }
                return fn.apply(this, arguments);
            }, fn);
        }
    
        var deprecations = {};
    
        function deprecateSimple(name, msg) {
            if (hooks.deprecationHandler != null) {
                hooks.deprecationHandler(name, msg);
            }
            if (!deprecations[name]) {
                warn(msg);
                deprecations[name] = true;
            }
        }
    
        hooks.suppressDeprecationWarnings = false;
        hooks.deprecationHandler = null;
    
        function isFunction(input) {
            return (
                (typeof Function !== 'undefined' && input instanceof Function) ||
                Object.prototype.toString.call(input) === '[object Function]'
            );
        }
    
        function set(config) {
            var prop, i;
            for (i in config) {
                if (hasOwnProp(config, i)) {
                    prop = config[i];
                    if (isFunction(prop)) {
                        this[i] = prop;
                    } else {
                        this['_' + i] = prop;
                    }
                }
            }
            this._config = config;
            // Lenient ordinal parsing accepts just a number in addition to
            // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
            // TODO: Remove "ordinalParse" fallback in next major release.
            this._dayOfMonthOrdinalParseLenient = new RegExp(
                (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
                    '|' +
                    /\d{1,2}/.source
            );
        }
    
        function mergeConfigs(parentConfig, childConfig) {
            var res = extend({}, parentConfig),
                prop;
            for (prop in childConfig) {
                if (hasOwnProp(childConfig, prop)) {
                    if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
                        res[prop] = {};
                        extend(res[prop], parentConfig[prop]);
                        extend(res[prop], childConfig[prop]);
                    } else if (childConfig[prop] != null) {
                        res[prop] = childConfig[prop];
                    } else {
                        delete res[prop];
                    }
                }
            }
            for (prop in parentConfig) {
                if (
                    hasOwnProp(parentConfig, prop) &&
                    !hasOwnProp(childConfig, prop) &&
                    isObject(parentConfig[prop])
                ) {
                    // make sure changes to properties don't modify parent config
                    res[prop] = extend({}, res[prop]);
                }
            }
            return res;
        }
    
        function Locale(config) {
            if (config != null) {
                this.set(config);
            }
        }
    
        var keys;
    
        if (Object.keys) {
            keys = Object.keys;
        } else {
            keys = function (obj) {
                var i,
                    res = [];
                for (i in obj) {
                    if (hasOwnProp(obj, i)) {
                        res.push(i);
                    }
                }
                return res;
            };
        }
    
        var defaultCalendar = {
            sameDay: '[Today at] LT',
            nextDay: '[Tomorrow at] LT',
            nextWeek: 'dddd [at] LT',
            lastDay: '[Yesterday at] LT',
            lastWeek: '[Last] dddd [at] LT',
            sameElse: 'L',
        };
    
        function calendar(key, mom, now) {
            var output = this._calendar[key] || this._calendar['sameElse'];
            return isFunction(output) ? output.call(mom, now) : output;
        }
    
        function zeroFill(number, targetLength, forceSign) {
            var absNumber = '' + Math.abs(number),
                zerosToFill = targetLength - absNumber.length,
                sign = number >= 0;
            return (
                (sign ? (forceSign ? '+' : '') : '-') +
                Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) +
                absNumber
            );
        }
    
        var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,
            localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
            formatFunctions = {},
            formatTokenFunctions = {};
    
        // token:    'M'
        // padded:   ['MM', 2]
        // ordinal:  'Mo'
        // callback: function () { this.month() + 1 }
        function addFormatToken(token, padded, ordinal, callback) {
            var func = callback;
            if (typeof callback === 'string') {
                func = function () {
                    return this[callback]();
                };
            }
            if (token) {
                formatTokenFunctions[token] = func;
            }
            if (padded) {
                formatTokenFunctions[padded[0]] = function () {
                    return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
                };
            }
            if (ordinal) {
                formatTokenFunctions[ordinal] = function () {
                    return this.localeData().ordinal(
                        func.apply(this, arguments),
                        token
                    );
                };
            }
        }
    
        function removeFormattingTokens(input) {
            if (input.match(/\[[\s\S]/)) {
                return input.replace(/^\[|\]$/g, '');
            }
            return input.replace(/\\/g, '');
        }
    
        function makeFormatFunction(format) {
            var array = format.match(formattingTokens),
                i,
                length;
    
            for (i = 0, length = array.length; i < length; i++) {
                if (formatTokenFunctions[array[i]]) {
                    array[i] = formatTokenFunctions[array[i]];
                } else {
                    array[i] = removeFormattingTokens(array[i]);
                }
            }
    
            return function (mom) {
                var output = '',
                    i;
                for (i = 0; i < length; i++) {
                    output += isFunction(array[i])
                        ? array[i].call(mom, format)
                        : array[i];
                }
                return output;
            };
        }
    
        // format date using native date object
        function formatMoment(m, format) {
            if (!m.isValid()) {
                return m.localeData().invalidDate();
            }
    
            format = expandFormat(format, m.localeData());
            formatFunctions[format] =
                formatFunctions[format] || makeFormatFunction(format);
    
            return formatFunctions[format](m);
        }
    
        function expandFormat(format, locale) {
            var i = 5;
    
            function replaceLongDateFormatTokens(input) {
                return locale.longDateFormat(input) || input;
            }
    
            localFormattingTokens.lastIndex = 0;
            while (i >= 0 && localFormattingTokens.test(format)) {
                format = format.replace(
                    localFormattingTokens,
                    replaceLongDateFormatTokens
                );
                localFormattingTokens.lastIndex = 0;
                i -= 1;
            }
    
            return format;
        }
    
        var defaultLongDateFormat = {
            LTS: 'h:mm:ss A',
            LT: 'h:mm A',
            L: 'MM/DD/YYYY',
            LL: 'MMMM D, YYYY',
            LLL: 'MMMM D, YYYY h:mm A',
            LLLL: 'dddd, MMMM D, YYYY h:mm A',
        };
    
        function longDateFormat(key) {
            var format = this._longDateFormat[key],
                formatUpper = this._longDateFormat[key.toUpperCase()];
    
            if (format || !formatUpper) {
                return format;
            }
    
            this._longDateFormat[key] = formatUpper
                .match(formattingTokens)
                .map(function (tok) {
                    if (
                        tok === 'MMMM' ||
                        tok === 'MM' ||
                        tok === 'DD' ||
                        tok === 'dddd'
                    ) {
                        return tok.slice(1);
                    }
                    return tok;
                })
                .join('');
    
            return this._longDateFormat[key];
        }
    
        var defaultInvalidDate = 'Invalid date';
    
        function invalidDate() {
            return this._invalidDate;
        }
    
        var defaultOrdinal = '%d',
            defaultDayOfMonthOrdinalParse = /\d{1,2}/;
    
        function ordinal(number) {
            return this._ordinal.replace('%d', number);
        }
    
        var defaultRelativeTime = {
            future: 'in %s',
            past: '%s ago',
            s: 'a few seconds',
            ss: '%d seconds',
            m: 'a minute',
            mm: '%d minutes',
            h: 'an hour',
            hh: '%d hours',
            d: 'a day',
            dd: '%d days',
            w: 'a week',
            ww: '%d weeks',
            M: 'a month',
            MM: '%d months',
            y: 'a year',
            yy: '%d years',
        };
    
        function relativeTime(number, withoutSuffix, string, isFuture) {
            var output = this._relativeTime[string];
            return isFunction(output)
                ? output(number, withoutSuffix, string, isFuture)
                : output.replace(/%d/i, number);
        }
    
        function pastFuture(diff, output) {
            var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
            return isFunction(format) ? format(output) : format.replace(/%s/i, output);
        }
    
        var aliases = {};
    
        function addUnitAlias(unit, shorthand) {
            var lowerCase = unit.toLowerCase();
            aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
        }
    
        function normalizeUnits(units) {
            return typeof units === 'string'
                ? aliases[units] || aliases[units.toLowerCase()]
                : undefined;
        }
    
        function normalizeObjectUnits(inputObject) {
            var normalizedInput = {},
                normalizedProp,
                prop;
    
            for (prop in inputObject) {
                if (hasOwnProp(inputObject, prop)) {
                    normalizedProp = normalizeUnits(prop);
                    if (normalizedProp) {
                        normalizedInput[normalizedProp] = inputObject[prop];
                    }
                }
            }
    
            return normalizedInput;
        }
    
        var priorities = {};
    
        function addUnitPriority(unit, priority) {
            priorities[unit] = priority;
        }
    
        function getPrioritizedUnits(unitsObj) {
            var units = [],
                u;
            for (u in unitsObj) {
                if (hasOwnProp(unitsObj, u)) {
                    units.push({ unit: u, priority: priorities[u] });
                }
            }
            units.sort(function (a, b) {
                return a.priority - b.priority;
            });
            return units;
        }
    
        function isLeapYear(year) {
            return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
        }
    
        function absFloor(number) {
            if (number < 0) {
                // -0 -> 0
                return Math.ceil(number) || 0;
            } else {
                return Math.floor(number);
            }
        }
    
        function toInt(argumentForCoercion) {
            var coercedNumber = +argumentForCoercion,
                value = 0;
    
            if (coercedNumber !== 0 && isFinite(coercedNumber)) {
                value = absFloor(coercedNumber);
            }
    
            return value;
        }
    
        function makeGetSet(unit, keepTime) {
            return function (value) {
                if (value != null) {
                    set$1(this, unit, value);
                    hooks.updateOffset(this, keepTime);
                    return this;
                } else {
                    return get(this, unit);
                }
            };
        }
    
        function get(mom, unit) {
            return mom.isValid()
                ? mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]()
                : NaN;
        }
    
        function set$1(mom, unit, value) {
            if (mom.isValid() && !isNaN(value)) {
                if (
                    unit === 'FullYear' &&
                    isLeapYear(mom.year()) &&
                    mom.month() === 1 &&
                    mom.date() === 29
                ) {
                    value = toInt(value);
                    mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](
                        value,
                        mom.month(),
                        daysInMonth(value, mom.month())
                    );
                } else {
                    mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
                }
            }
        }
    
        // MOMENTS
    
        function stringGet(units) {
            units = normalizeUnits(units);
            if (isFunction(this[units])) {
                return this[units]();
            }
            return this;
        }
    
        function stringSet(units, value) {
            if (typeof units === 'object') {
                units = normalizeObjectUnits(units);
                var prioritized = getPrioritizedUnits(units),
                    i;
                for (i = 0; i < prioritized.length; i++) {
                    this[prioritized[i].unit](units[prioritized[i].unit]);
                }
            } else {
                units = normalizeUnits(units);
                if (isFunction(this[units])) {
                    return this[units](value);
                }
            }
            return this;
        }
    
        var match1 = /\d/, //       0 - 9
            match2 = /\d\d/, //      00 - 99
            match3 = /\d{3}/, //     000 - 999
            match4 = /\d{4}/, //    0000 - 9999
            match6 = /[+-]?\d{6}/, // -999999 - 999999
            match1to2 = /\d\d?/, //       0 - 99
            match3to4 = /\d\d\d\d?/, //     999 - 9999
            match5to6 = /\d\d\d\d\d\d?/, //   99999 - 999999
            match1to3 = /\d{1,3}/, //       0 - 999
            match1to4 = /\d{1,4}/, //       0 - 9999
            match1to6 = /[+-]?\d{1,6}/, // -999999 - 999999
            matchUnsigned = /\d+/, //       0 - inf
            matchSigned = /[+-]?\d+/, //    -inf - inf
            matchOffset = /Z|[+-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
            matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi, // +00 -00 +00:00 -00:00 +0000 -0000 or Z
            matchTimestamp = /[+-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
            // any word (or two) characters or numbers including two/three word month in arabic.
            // includes scottish gaelic two word and hyphenated months
            matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,
            regexes;
    
        regexes = {};
    
        function addRegexToken(token, regex, strictRegex) {
            regexes[token] = isFunction(regex)
                ? regex
                : function (isStrict, localeData) {
                      return isStrict && strictRegex ? strictRegex : regex;
                  };
        }
    
        function getParseRegexForToken(token, config) {
            if (!hasOwnProp(regexes, token)) {
                return new RegExp(unescapeFormat(token));
            }
    
            return regexes[token](config._strict, config._locale);
        }
    
        // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
        function unescapeFormat(s) {
            return regexEscape(
                s
                    .replace('\\', '')
                    .replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (
                        matched,
                        p1,
                        p2,
                        p3,
                        p4
                    ) {
                        return p1 || p2 || p3 || p4;
                    })
            );
        }
    
        function regexEscape(s) {
            return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
        }
    
        var tokens = {};
    
        function addParseToken(token, callback) {
            var i,
                func = callback;
            if (typeof token === 'string') {
                token = [token];
            }
            if (isNumber(callback)) {
                func = function (input, array) {
                    array[callback] = toInt(input);
                };
            }
            for (i = 0; i < token.length; i++) {
                tokens[token[i]] = func;
            }
        }
    
        function addWeekParseToken(token, callback) {
            addParseToken(token, function (input, array, config, token) {
                config._w = config._w || {};
                callback(input, config._w, config, token);
            });
        }
    
        function addTimeToArrayFromToken(token, input, config) {
            if (input != null && hasOwnProp(tokens, token)) {
                tokens[token](input, config._a, config, token);
            }
        }
    
        var YEAR = 0,
            MONTH = 1,
            DATE = 2,
            HOUR = 3,
            MINUTE = 4,
            SECOND = 5,
            MILLISECOND = 6,
            WEEK = 7,
            WEEKDAY = 8;
    
        function mod(n, x) {
            return ((n % x) + x) % x;
        }
    
        var indexOf;
    
        if (Array.prototype.indexOf) {
            indexOf = Array.prototype.indexOf;
        } else {
            indexOf = function (o) {
                // I know
                var i;
                for (i = 0; i < this.length; ++i) {
                    if (this[i] === o) {
                        return i;
                    }
                }
                return -1;
            };
        }
    
        function daysInMonth(year, month) {
            if (isNaN(year) || isNaN(month)) {
                return NaN;
            }
            var modMonth = mod(month, 12);
            year += (month - modMonth) / 12;
            return modMonth === 1
                ? isLeapYear(year)
                    ? 29
                    : 28
                : 31 - ((modMonth % 7) % 2);
        }
    
        // FORMATTING
    
        addFormatToken('M', ['MM', 2], 'Mo', function () {
            return this.month() + 1;
        });
    
        addFormatToken('MMM', 0, 0, function (format) {
            return this.localeData().monthsShort(this, format);
        });
    
        addFormatToken('MMMM', 0, 0, function (format) {
            return this.localeData().months(this, format);
        });
    
        // ALIASES
    
        addUnitAlias('month', 'M');
    
        // PRIORITY
    
        addUnitPriority('month', 8);
    
        // PARSING
    
        addRegexToken('M', match1to2);
        addRegexToken('MM', match1to2, match2);
        addRegexToken('MMM', function (isStrict, locale) {
            return locale.monthsShortRegex(isStrict);
        });
        addRegexToken('MMMM', function (isStrict, locale) {
            return locale.monthsRegex(isStrict);
        });
    
        addParseToken(['M', 'MM'], function (input, array) {
            array[MONTH] = toInt(input) - 1;
        });
    
        addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
            var month = config._locale.monthsParse(input, token, config._strict);
            // if we didn't find a month name, mark the date as invalid.
            if (month != null) {
                array[MONTH] = month;
            } else {
                getParsingFlags(config).invalidMonth = input;
            }
        });
    
        // LOCALES
    
        var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split(
                '_'
            ),
            MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,
            defaultMonthsShortRegex = matchWord,
            defaultMonthsRegex = matchWord;
    
        function localeMonths(m, format) {
            if (!m) {
                return isArray(this._months)
                    ? this._months
                    : this._months['standalone'];
            }
            return isArray(this._months)
                ? this._months[m.month()]
                : this._months[
                      (this._months.isFormat || MONTHS_IN_FORMAT).test(format)
                          ? 'format'
                          : 'standalone'
                  ][m.month()];
        }
    
        function localeMonthsShort(m, format) {
            if (!m) {
                return isArray(this._monthsShort)
                    ? this._monthsShort
                    : this._monthsShort['standalone'];
            }
            return isArray(this._monthsShort)
                ? this._monthsShort[m.month()]
                : this._monthsShort[
                      MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'
                  ][m.month()];
        }
    
        function handleStrictParse(monthName, format, strict) {
            var i,
                ii,
                mom,
                llc = monthName.toLocaleLowerCase();
            if (!this._monthsParse) {
                // this is not used
                this._monthsParse = [];
                this._longMonthsParse = [];
                this._shortMonthsParse = [];
                for (i = 0; i < 12; ++i) {
                    mom = createUTC([2000, i]);
                    this._shortMonthsParse[i] = this.monthsShort(
                        mom,
                        ''
                    ).toLocaleLowerCase();
                    this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
                }
            }
    
            if (strict) {
                if (format === 'MMM') {
                    ii = indexOf.call(this._shortMonthsParse, llc);
                    return ii !== -1 ? ii : null;
                } else {
                    ii = indexOf.call(this._longMonthsParse, llc);
                    return ii !== -1 ? ii : null;
                }
            } else {
                if (format === 'MMM') {
                    ii = indexOf.call(this._shortMonthsParse, llc);
                    if (ii !== -1) {
                        return ii;
                    }
                    ii = indexOf.call(this._longMonthsParse, llc);
                    return ii !== -1 ? ii : null;
                } else {
                    ii = indexOf.call(this._longMonthsParse, llc);
                    if (ii !== -1) {
                        return ii;
                    }
                    ii = indexOf.call(this._shortMonthsParse, llc);
                    return ii !== -1 ? ii : null;
                }
            }
        }
    
        function localeMonthsParse(monthName, format, strict) {
            var i, mom, regex;
    
            if (this._monthsParseExact) {
                return handleStrictParse.call(this, monthName, format, strict);
            }
    
            if (!this._monthsParse) {
                this._monthsParse = [];
                this._longMonthsParse = [];
                this._shortMonthsParse = [];
            }
    
            // TODO: add sorting
            // Sorting makes sure if one month (or abbr) is a prefix of another
            // see sorting in computeMonthsParse
            for (i = 0; i < 12; i++) {
                // make the regex if we don't have it already
                mom = createUTC([2000, i]);
                if (strict && !this._longMonthsParse[i]) {
                    this._longMonthsParse[i] = new RegExp(
                        '^' + this.months(mom, '').replace('.', '') + '$',
                        'i'
                    );
                    this._shortMonthsParse[i] = new RegExp(
                        '^' + this.monthsShort(mom, '').replace('.', '') + '$',
                        'i'
                    );
                }
                if (!strict && !this._monthsParse[i]) {
                    regex =
                        '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
                    this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
                }
                // test the regex
                if (
                    strict &&
                    format === 'MMMM' &&
                    this._longMonthsParse[i].test(monthName)
                ) {
                    return i;
                } else if (
                    strict &&
                    format === 'MMM' &&
                    this._shortMonthsParse[i].test(monthName)
                ) {
                    return i;
                } else if (!strict && this._monthsParse[i].test(monthName)) {
                    return i;
                }
            }
        }
    
        // MOMENTS
    
        function setMonth(mom, value) {
            var dayOfMonth;
    
            if (!mom.isValid()) {
                // No op
                return mom;
            }
    
            if (typeof value === 'string') {
                if (/^\d+$/.test(value)) {
                    value = toInt(value);
                } else {
                    value = mom.localeData().monthsParse(value);
                    // TODO: Another silent failure?
                    if (!isNumber(value)) {
                        return mom;
                    }
                }
            }
    
            dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
            mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
            return mom;
        }
    
        function getSetMonth(value) {
            if (value != null) {
                setMonth(this, value);
                hooks.updateOffset(this, true);
                return this;
            } else {
                return get(this, 'Month');
            }
        }
    
        function getDaysInMonth() {
            return daysInMonth(this.year(), this.month());
        }
    
        function monthsShortRegex(isStrict) {
            if (this._monthsParseExact) {
                if (!hasOwnProp(this, '_monthsRegex')) {
                    computeMonthsParse.call(this);
                }
                if (isStrict) {
                    return this._monthsShortStrictRegex;
                } else {
                    return this._monthsShortRegex;
                }
            } else {
                if (!hasOwnProp(this, '_monthsShortRegex')) {
                    this._monthsShortRegex = defaultMonthsShortRegex;
                }
                return this._monthsShortStrictRegex && isStrict
                    ? this._monthsShortStrictRegex
                    : this._monthsShortRegex;
            }
        }
    
        function monthsRegex(isStrict) {
            if (this._monthsParseExact) {
                if (!hasOwnProp(this, '_monthsRegex')) {
                    computeMonthsParse.call(this);
                }
                if (isStrict) {
                    return this._monthsStrictRegex;
                } else {
                    return this._monthsRegex;
                }
            } else {
                if (!hasOwnProp(this, '_monthsRegex')) {
                    this._monthsRegex = defaultMonthsRegex;
                }
                return this._monthsStrictRegex && isStrict
                    ? this._monthsStrictRegex
                    : this._monthsRegex;
            }
        }
    
        function computeMonthsParse() {
            function cmpLenRev(a, b) {
                return b.length - a.length;
            }
    
            var shortPieces = [],
                longPieces = [],
                mixedPieces = [],
                i,
                mom;
            for (i = 0; i < 12; i++) {
                // make the regex if we don't have it already
                mom = createUTC([2000, i]);
                shortPieces.push(this.monthsShort(mom, ''));
                longPieces.push(this.months(mom, ''));
                mixedPieces.push(this.months(mom, ''));
                mixedPieces.push(this.monthsShort(mom, ''));
            }
            // Sorting makes sure if one month (or abbr) is a prefix of another it
            // will match the longer piece.
            shortPieces.sort(cmpLenRev);
            longPieces.sort(cmpLenRev);
            mixedPieces.sort(cmpLenRev);
            for (i = 0; i < 12; i++) {
                shortPieces[i] = regexEscape(shortPieces[i]);
                longPieces[i] = regexEscape(longPieces[i]);
            }
            for (i = 0; i < 24; i++) {
                mixedPieces[i] = regexEscape(mixedPieces[i]);
            }
    
            this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
            this._monthsShortRegex = this._monthsRegex;
            this._monthsStrictRegex = new RegExp(
                '^(' + longPieces.join('|') + ')',
                'i'
            );
            this._monthsShortStrictRegex = new RegExp(
                '^(' + shortPieces.join('|') + ')',
                'i'
            );
        }
    
        // FORMATTING
    
        addFormatToken('Y', 0, 0, function () {
            var y = this.year();
            return y <= 9999 ? zeroFill(y, 4) : '+' + y;
        });
    
        addFormatToken(0, ['YY', 2], 0, function () {
            return this.year() % 100;
        });
    
        addFormatToken(0, ['YYYY', 4], 0, 'year');
        addFormatToken(0, ['YYYYY', 5], 0, 'year');
        addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
    
        // ALIASES
    
        addUnitAlias('year', 'y');
    
        // PRIORITIES
    
        addUnitPriority('year', 1);
    
        // PARSING
    
        addRegexToken('Y', matchSigned);
        addRegexToken('YY', match1to2, match2);
        addRegexToken('YYYY', match1to4, match4);
        addRegexToken('YYYYY', match1to6, match6);
        addRegexToken('YYYYYY', match1to6, match6);
    
        addParseToken(['YYYYY', 'YYYYYY'], YEAR);
        addParseToken('YYYY', function (input, array) {
            array[YEAR] =
                input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
        });
        addParseToken('YY', function (input, array) {
            array[YEAR] = hooks.parseTwoDigitYear(input);
        });
        addParseToken('Y', function (input, array) {
            array[YEAR] = parseInt(input, 10);
        });
    
        // HELPERS
    
        function daysInYear(year) {
            return isLeapYear(year) ? 366 : 365;
        }
    
        // HOOKS
    
        hooks.parseTwoDigitYear = function (input) {
            return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
        };
    
        // MOMENTS
    
        var getSetYear = makeGetSet('FullYear', true);
    
        function getIsLeapYear() {
            return isLeapYear(this.year());
        }
    
        function createDate(y, m, d, h, M, s, ms) {
            // can't just apply() to create a date:
            // https://stackoverflow.com/q/181348
            var date;
            // the date constructor remaps years 0-99 to 1900-1999
            if (y < 100 && y >= 0) {
                // preserve leap years using a full 400 year cycle, then reset
                date = new Date(y + 400, m, d, h, M, s, ms);
                if (isFinite(date.getFullYear())) {
                    date.setFullYear(y);
                }
            } else {
                date = new Date(y, m, d, h, M, s, ms);
            }
    
            return date;
        }
    
        function createUTCDate(y) {
            var date, args;
            // the Date.UTC function remaps years 0-99 to 1900-1999
            if (y < 100 && y >= 0) {
                args = Array.prototype.slice.call(arguments);
                // preserve leap years using a full 400 year cycle, then reset
                args[0] = y + 400;
                date = new Date(Date.UTC.apply(null, args));
                if (isFinite(date.getUTCFullYear())) {
                    date.setUTCFullYear(y);
                }
            } else {
                date = new Date(Date.UTC.apply(null, arguments));
            }
    
            return date;
        }
    
        // start-of-first-week - start-of-year
        function firstWeekOffset(year, dow, doy) {
            var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
                fwd = 7 + dow - doy,
                // first-week day local weekday -- which local weekday is fwd
                fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
    
            return -fwdlw + fwd - 1;
        }
    
        // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
        function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
            var localWeekday = (7 + weekday - dow) % 7,
                weekOffset = firstWeekOffset(year, dow, doy),
                dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
                resYear,
                resDayOfYear;
    
            if (dayOfYear <= 0) {
                resYear = year - 1;
                resDayOfYear = daysInYear(resYear) + dayOfYear;
            } else if (dayOfYear > daysInYear(year)) {
                resYear = year + 1;
                resDayOfYear = dayOfYear - daysInYear(year);
            } else {
                resYear = year;
                resDayOfYear = dayOfYear;
            }
    
            return {
                year: resYear,
                dayOfYear: resDayOfYear,
            };
        }
    
        function weekOfYear(mom, dow, doy) {
            var weekOffset = firstWeekOffset(mom.year(), dow, doy),
                week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
                resWeek,
                resYear;
    
            if (week < 1) {
                resYear = mom.year() - 1;
                resWeek = week + weeksInYear(resYear, dow, doy);
            } else if (week > weeksInYear(mom.year(), dow, doy)) {
                resWeek = week - weeksInYear(mom.year(), dow, doy);
                resYear = mom.year() + 1;
            } else {
                resYear = mom.year();
                resWeek = week;
            }
    
            return {
                week: resWeek,
                year: resYear,
            };
        }
    
        function weeksInYear(year, dow, doy) {
            var weekOffset = firstWeekOffset(year, dow, doy),
                weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
            return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
        }
    
        // FORMATTING
    
        addFormatToken('w', ['ww', 2], 'wo', 'week');
        addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
    
        // ALIASES
    
        addUnitAlias('week', 'w');
        addUnitAlias('isoWeek', 'W');
    
        // PRIORITIES
    
        addUnitPriority('week', 5);
        addUnitPriority('isoWeek', 5);
    
        // PARSING
    
        addRegexToken('w', match1to2);
        addRegexToken('ww', match1to2, match2);
        addRegexToken('W', match1to2);
        addRegexToken('WW', match1to2, match2);
    
        addWeekParseToken(['w', 'ww', 'W', 'WW'], function (
            input,
            week,
            config,
            token
        ) {
            week[token.substr(0, 1)] = toInt(input);
        });
    
        // HELPERS
    
        // LOCALES
    
        function localeWeek(mom) {
            return weekOfYear(mom, this._week.dow, this._week.doy).week;
        }
    
        var defaultLocaleWeek = {
            dow: 0, // Sunday is the first day of the week.
            doy: 6, // The week that contains Jan 6th is the first week of the year.
        };
    
        function localeFirstDayOfWeek() {
            return this._week.dow;
        }
    
        function localeFirstDayOfYear() {
            return this._week.doy;
        }
    
        // MOMENTS
    
        function getSetWeek(input) {
            var week = this.localeData().week(this);
            return input == null ? week : this.add((input - week) * 7, 'd');
        }
    
        function getSetISOWeek(input) {
            var week = weekOfYear(this, 1, 4).week;
            return input == null ? week : this.add((input - week) * 7, 'd');
        }
    
        // FORMATTING
    
        addFormatToken('d', 0, 'do', 'day');
    
        addFormatToken('dd', 0, 0, function (format) {
            return this.localeData().weekdaysMin(this, format);
        });
    
        addFormatToken('ddd', 0, 0, function (format) {
            return this.localeData().weekdaysShort(this, format);
        });
    
        addFormatToken('dddd', 0, 0, function (format) {
            return this.localeData().weekdays(this, format);
        });
    
        addFormatToken('e', 0, 0, 'weekday');
        addFormatToken('E', 0, 0, 'isoWeekday');
    
        // ALIASES
    
        addUnitAlias('day', 'd');
        addUnitAlias('weekday', 'e');
        addUnitAlias('isoWeekday', 'E');
    
        // PRIORITY
        addUnitPriority('day', 11);
        addUnitPriority('weekday', 11);
        addUnitPriority('isoWeekday', 11);
    
        // PARSING
    
        addRegexToken('d', match1to2);
        addRegexToken('e', match1to2);
        addRegexToken('E', match1to2);
        addRegexToken('dd', function (isStrict, locale) {
            return locale.weekdaysMinRegex(isStrict);
        });
        addRegexToken('ddd', function (isStrict, locale) {
            return locale.weekdaysShortRegex(isStrict);
        });
        addRegexToken('dddd', function (isStrict, locale) {
            return locale.weekdaysRegex(isStrict);
        });
    
        addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
            var weekday = config._locale.weekdaysParse(input, token, config._strict);
            // if we didn't get a weekday name, mark the date as invalid
            if (weekday != null) {
                week.d = weekday;
            } else {
                getParsingFlags(config).invalidWeekday = input;
            }
        });
    
        addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
            week[token] = toInt(input);
        });
    
        // HELPERS
    
        function parseWeekday(input, locale) {
            if (typeof input !== 'string') {
                return input;
            }
    
            if (!isNaN(input)) {
                return parseInt(input, 10);
            }
    
            input = locale.weekdaysParse(input);
            if (typeof input === 'number') {
                return input;
            }
    
            return null;
        }
    
        function parseIsoWeekday(input, locale) {
            if (typeof input === 'string') {
                return locale.weekdaysParse(input) % 7 || 7;
            }
            return isNaN(input) ? null : input;
        }
    
        // LOCALES
        function shiftWeekdays(ws, n) {
            return ws.slice(n, 7).concat(ws.slice(0, n));
        }
    
        var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            defaultWeekdaysRegex = matchWord,
            defaultWeekdaysShortRegex = matchWord,
            defaultWeekdaysMinRegex = matchWord;
    
        function localeWeekdays(m, format) {
            var weekdays = isArray(this._weekdays)
                ? this._weekdays
                : this._weekdays[
                      m && m !== true && this._weekdays.isFormat.test(format)
                          ? 'format'
                          : 'standalone'
                  ];
            return m === true
                ? shiftWeekdays(weekdays, this._week.dow)
                : m
                ? weekdays[m.day()]
                : weekdays;
        }
    
        function localeWeekdaysShort(m) {
            return m === true
                ? shiftWeekdays(this._weekdaysShort, this._week.dow)
                : m
                ? this._weekdaysShort[m.day()]
                : this._weekdaysShort;
        }
    
        function localeWeekdaysMin(m) {
            return m === true
                ? shiftWeekdays(this._weekdaysMin, this._week.dow)
                : m
                ? this._weekdaysMin[m.day()]
                : this._weekdaysMin;
        }
    
        function handleStrictParse$1(weekdayName, format, strict) {
            var i,
                ii,
                mom,
                llc = weekdayName.toLocaleLowerCase();
            if (!this._weekdaysParse) {
                this._weekdaysParse = [];
                this._shortWeekdaysParse = [];
                this._minWeekdaysParse = [];
    
                for (i = 0; i < 7; ++i) {
                    mom = createUTC([2000, 1]).day(i);
                    this._minWeekdaysParse[i] = this.weekdaysMin(
                        mom,
                        ''
                    ).toLocaleLowerCase();
                    this._shortWeekdaysParse[i] = this.weekdaysShort(
                        mom,
                        ''
                    ).toLocaleLowerCase();
                    this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
                }
            }
    
            if (strict) {
                if (format === 'dddd') {
                    ii = indexOf.call(this._weekdaysParse, llc);
                    return ii !== -1 ? ii : null;
                } else if (format === 'ddd') {
                    ii = indexOf.call(this._shortWeekdaysParse, llc);
                    return ii !== -1 ? ii : null;
                } else {
                    ii = indexOf.call(this._minWeekdaysParse, llc);
                    return ii !== -1 ? ii : null;
                }
            } else {
                if (format === 'dddd') {
                    ii = indexOf.call(this._weekdaysParse, llc);
                    if (ii !== -1) {
                        return ii;
                    }
                    ii = indexOf.call(this._shortWeekdaysParse, llc);
                    if (ii !== -1) {
                        return ii;
                    }
                    ii = indexOf.call(this._minWeekdaysParse, llc);
                    return ii !== -1 ? ii : null;
                } else if (format === 'ddd') {
                    ii = indexOf.call(this._shortWeekdaysParse, llc);
                    if (ii !== -1) {
                        return ii;
                    }
                    ii = indexOf.call(this._weekdaysParse, llc);
                    if (ii !== -1) {
                        return ii;
                    }
                    ii = indexOf.call(this._minWeekdaysParse, llc);
                    return ii !== -1 ? ii : null;
                } else {
                    ii = indexOf.call(this._minWeekdaysParse, llc);
                    if (ii !== -1) {
                        return ii;
                    }
                    ii = indexOf.call(this._weekdaysParse, llc);
                    if (ii !== -1) {
                        return ii;
                    }
                    ii = indexOf.call(this._shortWeekdaysParse, llc);
                    return ii !== -1 ? ii : null;
                }
            }
        }
    
        function localeWeekdaysParse(weekdayName, format, strict) {
            var i, mom, regex;
    
            if (this._weekdaysParseExact) {
                return handleStrictParse$1.call(this, weekdayName, format, strict);
            }
    
            if (!this._weekdaysParse) {
                this._weekdaysParse = [];
                this._minWeekdaysParse = [];
                this._shortWeekdaysParse = [];
                this._fullWeekdaysParse = [];
            }
    
            for (i = 0; i < 7; i++) {
                // make the regex if we don't have it already
    
                mom = createUTC([2000, 1]).day(i);
                if (strict && !this._fullWeekdaysParse[i]) {
                    this._fullWeekdaysParse[i] = new RegExp(
                        '^' + this.weekdays(mom, '').replace('.', '\\.?') + '$',
                        'i'
                    );
                    this._shortWeekdaysParse[i] = new RegExp(
                        '^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$',
                        'i'
                    );
                    this._minWeekdaysParse[i] = new RegExp(
                        '^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$',
                        'i'
                    );
                }
                if (!this._weekdaysParse[i]) {
                    regex =
                        '^' +
                        this.weekdays(mom, '') +
                        '|^' +
                        this.weekdaysShort(mom, '') +
                        '|^' +
                        this.weekdaysMin(mom, '');
                    this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
                }
                // test the regex
                if (
                    strict &&
                    format === 'dddd' &&
                    this._fullWeekdaysParse[i].test(weekdayName)
                ) {
                    return i;
                } else if (
                    strict &&
                    format === 'ddd' &&
                    this._shortWeekdaysParse[i].test(weekdayName)
                ) {
                    return i;
                } else if (
                    strict &&
                    format === 'dd' &&
                    this._minWeekdaysParse[i].test(weekdayName)
                ) {
                    return i;
                } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
                    return i;
                }
            }
        }
    
        // MOMENTS
    
        function getSetDayOfWeek(input) {
            if (!this.isValid()) {
                return input != null ? this : NaN;
            }
            var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
            if (input != null) {
                input = parseWeekday(input, this.localeData());
                return this.add(input - day, 'd');
            } else {
                return day;
            }
        }
    
        function getSetLocaleDayOfWeek(input) {
            if (!this.isValid()) {
                return input != null ? this : NaN;
            }
            var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
            return input == null ? weekday : this.add(input - weekday, 'd');
        }
    
        function getSetISODayOfWeek(input) {
            if (!this.isValid()) {
                return input != null ? this : NaN;
            }
    
            // behaves the same as moment#day except
            // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
            // as a setter, sunday should belong to the previous week.
    
            if (input != null) {
                var weekday = parseIsoWeekday(input, this.localeData());
                return this.day(this.day() % 7 ? weekday : weekday - 7);
            } else {
                return this.day() || 7;
            }
        }
    
        function weekdaysRegex(isStrict) {
            if (this._weekdaysParseExact) {
                if (!hasOwnProp(this, '_weekdaysRegex')) {
                    computeWeekdaysParse.call(this);
                }
                if (isStrict) {
                    return this._weekdaysStrictRegex;
                } else {
                    return this._weekdaysRegex;
                }
            } else {
                if (!hasOwnProp(this, '_weekdaysRegex')) {
                    this._weekdaysRegex = defaultWeekdaysRegex;
                }
                return this._weekdaysStrictRegex && isStrict
                    ? this._weekdaysStrictRegex
                    : this._weekdaysRegex;
            }
        }
    
        function weekdaysShortRegex(isStrict) {
            if (this._weekdaysParseExact) {
                if (!hasOwnProp(this, '_weekdaysRegex')) {
                    computeWeekdaysParse.call(this);
                }
                if (isStrict) {
                    return this._weekdaysShortStrictRegex;
                } else {
                    return this._weekdaysShortRegex;
                }
            } else {
                if (!hasOwnProp(this, '_weekdaysShortRegex')) {
                    this._weekdaysShortRegex = defaultWeekdaysShortRegex;
                }
                return this._weekdaysShortStrictRegex && isStrict
                    ? this._weekdaysShortStrictRegex
                    : this._weekdaysShortRegex;
            }
        }
    
        function weekdaysMinRegex(isStrict) {
            if (this._weekdaysParseExact) {
                if (!hasOwnProp(this, '_weekdaysRegex')) {
                    computeWeekdaysParse.call(this);
                }
                if (isStrict) {
                    return this._weekdaysMinStrictRegex;
                } else {
                    return this._weekdaysMinRegex;
                }
            } else {
                if (!hasOwnProp(this, '_weekdaysMinRegex')) {
                    this._weekdaysMinRegex = defaultWeekdaysMinRegex;
                }
                return this._weekdaysMinStrictRegex && isStrict
                    ? this._weekdaysMinStrictRegex
                    : this._weekdaysMinRegex;
            }
        }
    
        function computeWeekdaysParse() {
            function cmpLenRev(a, b) {
                return b.length - a.length;
            }
    
            var minPieces = [],
                shortPieces = [],
                longPieces = [],
                mixedPieces = [],
                i,
                mom,
                minp,
                shortp,
                longp;
            for (i = 0; i < 7; i++) {
                // make the regex if we don't have it already
                mom = createUTC([2000, 1]).day(i);
                minp = regexEscape(this.weekdaysMin(mom, ''));
                shortp = regexEscape(this.weekdaysShort(mom, ''));
                longp = regexEscape(this.weekdays(mom, ''));
                minPieces.push(minp);
                shortPieces.push(shortp);
                longPieces.push(longp);
                mixedPieces.push(minp);
                mixedPieces.push(shortp);
                mixedPieces.push(longp);
            }
            // Sorting makes sure if one weekday (or abbr) is a prefix of another it
            // will match the longer piece.
            minPieces.sort(cmpLenRev);
            shortPieces.sort(cmpLenRev);
            longPieces.sort(cmpLenRev);
            mixedPieces.sort(cmpLenRev);
    
            this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
            this._weekdaysShortRegex = this._weekdaysRegex;
            this._weekdaysMinRegex = this._weekdaysRegex;
    
            this._weekdaysStrictRegex = new RegExp(
                '^(' + longPieces.join('|') + ')',
                'i'
            );
            this._weekdaysShortStrictRegex = new RegExp(
                '^(' + shortPieces.join('|') + ')',
                'i'
            );
            this._weekdaysMinStrictRegex = new RegExp(
                '^(' + minPieces.join('|') + ')',
                'i'
            );
        }
    
        // FORMATTING
    
        function hFormat() {
            return this.hours() % 12 || 12;
        }
    
        function kFormat() {
            return this.hours() || 24;
        }
    
        addFormatToken('H', ['HH', 2], 0, 'hour');
        addFormatToken('h', ['hh', 2], 0, hFormat);
        addFormatToken('k', ['kk', 2], 0, kFormat);
    
        addFormatToken('hmm', 0, 0, function () {
            return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
        });
    
        addFormatToken('hmmss', 0, 0, function () {
            return (
                '' +
                hFormat.apply(this) +
                zeroFill(this.minutes(), 2) +
                zeroFill(this.seconds(), 2)
            );
        });
    
        addFormatToken('Hmm', 0, 0, function () {
            return '' + this.hours() + zeroFill(this.minutes(), 2);
        });
    
        addFormatToken('Hmmss', 0, 0, function () {
            return (
                '' +
                this.hours() +
                zeroFill(this.minutes(), 2) +
                zeroFill(this.seconds(), 2)
            );
        });
    
        function meridiem(token, lowercase) {
            addFormatToken(token, 0, 0, function () {
                return this.localeData().meridiem(
                    this.hours(),
                    this.minutes(),
                    lowercase
                );
            });
        }
    
        meridiem('a', true);
        meridiem('A', false);
    
        // ALIASES
    
        addUnitAlias('hour', 'h');
    
        // PRIORITY
        addUnitPriority('hour', 13);
    
        // PARSING
    
        function matchMeridiem(isStrict, locale) {
            return locale._meridiemParse;
        }
    
        addRegexToken('a', matchMeridiem);
        addRegexToken('A', matchMeridiem);
        addRegexToken('H', match1to2);
        addRegexToken('h', match1to2);
        addRegexToken('k', match1to2);
        addRegexToken('HH', match1to2, match2);
        addRegexToken('hh', match1to2, match2);
        addRegexToken('kk', match1to2, match2);
    
        addRegexToken('hmm', match3to4);
        addRegexToken('hmmss', match5to6);
        addRegexToken('Hmm', match3to4);
        addRegexToken('Hmmss', match5to6);
    
        addParseToken(['H', 'HH'], HOUR);
        addParseToken(['k', 'kk'], function (input, array, config) {
            var kInput = toInt(input);
            array[HOUR] = kInput === 24 ? 0 : kInput;
        });
        addParseToken(['a', 'A'], function (input, array, config) {
            config._isPm = config._locale.isPM(input);
            config._meridiem = input;
        });
        addParseToken(['h', 'hh'], function (input, array, config) {
            array[HOUR] = toInt(input);
            getParsingFlags(config).bigHour = true;
        });
        addParseToken('hmm', function (input, array, config) {
            var pos = input.length - 2;
            array[HOUR] = toInt(input.substr(0, pos));
            array[MINUTE] = toInt(input.substr(pos));
            getParsingFlags(config).bigHour = true;
        });
        addParseToken('hmmss', function (input, array, config) {
            var pos1 = input.length - 4,
                pos2 = input.length - 2;
            array[HOUR] = toInt(input.substr(0, pos1));
            array[MINUTE] = toInt(input.substr(pos1, 2));
            array[SECOND] = toInt(input.substr(pos2));
            getParsingFlags(config).bigHour = true;
        });
        addParseToken('Hmm', function (input, array, config) {
            var pos = input.length - 2;
            array[HOUR] = toInt(input.substr(0, pos));
            array[MINUTE] = toInt(input.substr(pos));
        });
        addParseToken('Hmmss', function (input, array, config) {
            var pos1 = input.length - 4,
                pos2 = input.length - 2;
            array[HOUR] = toInt(input.substr(0, pos1));
            array[MINUTE] = toInt(input.substr(pos1, 2));
            array[SECOND] = toInt(input.substr(pos2));
        });
    
        // LOCALES
    
        function localeIsPM(input) {
            // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
            // Using charAt should be more compatible.
            return (input + '').toLowerCase().charAt(0) === 'p';
        }
    
        var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i,
            // Setting the hour should keep the time, because the user explicitly
            // specified which hour they want. So trying to maintain the same hour (in
            // a new timezone) makes sense. Adding/subtracting hours does not follow
            // this rule.
            getSetHour = makeGetSet('Hours', true);
    
        function localeMeridiem(hours, minutes, isLower) {
            if (hours > 11) {
                return isLower ? 'pm' : 'PM';
            } else {
                return isLower ? 'am' : 'AM';
            }
        }
    
        var baseConfig = {
            calendar: defaultCalendar,
            longDateFormat: defaultLongDateFormat,
            invalidDate: defaultInvalidDate,
            ordinal: defaultOrdinal,
            dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
            relativeTime: defaultRelativeTime,
    
            months: defaultLocaleMonths,
            monthsShort: defaultLocaleMonthsShort,
    
            week: defaultLocaleWeek,
    
            weekdays: defaultLocaleWeekdays,
            weekdaysMin: defaultLocaleWeekdaysMin,
            weekdaysShort: defaultLocaleWeekdaysShort,
    
            meridiemParse: defaultLocaleMeridiemParse,
        };
    
        // internal storage for locale config files
        var locales = {},
            localeFamilies = {},
            globalLocale;
    
        function commonPrefix(arr1, arr2) {
            var i,
                minl = Math.min(arr1.length, arr2.length);
            for (i = 0; i < minl; i += 1) {
                if (arr1[i] !== arr2[i]) {
                    return i;
                }
            }
            return minl;
        }
    
        function normalizeLocale(key) {
            return key ? key.toLowerCase().replace('_', '-') : key;
        }
    
        // pick the locale from the array
        // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
        // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
        function chooseLocale(names) {
            var i = 0,
                j,
                next,
                locale,
                split;
    
            while (i < names.length) {
                split = normalizeLocale(names[i]).split('-');
                j = split.length;
                next = normalizeLocale(names[i + 1]);
                next = next ? next.split('-') : null;
                while (j > 0) {
                    locale = loadLocale(split.slice(0, j).join('-'));
                    if (locale) {
                        return locale;
                    }
                    if (
                        next &&
                        next.length >= j &&
                        commonPrefix(split, next) >= j - 1
                    ) {
                        //the next array item is better than a shallower substring of this one
                        break;
                    }
                    j--;
                }
                i++;
            }
            return globalLocale;
        }
    
        function loadLocale(name) {
            var oldLocale = null,
                aliasedRequire;
            // TODO: Find a better way to register and load all the locales in Node
            if (
                locales[name] === undefined &&
                typeof module !== 'undefined' &&
                module &&
                module.exports
            ) {
                try {
                    oldLocale = globalLocale._abbr;
                    aliasedRequire = require;
                    aliasedRequire('./locale/' + name);
                    getSetGlobalLocale(oldLocale);
                } catch (e) {
                    // mark as not found to avoid repeating expensive file require call causing high CPU
                    // when trying to find en-US, en_US, en-us for every format call
                    locales[name] = null; // null means not found
                }
            }
            return locales[name];
        }
    
        // This function will load locale and then set the global locale.  If
        // no arguments are passed in, it will simply return the current global
        // locale key.
        function getSetGlobalLocale(key, values) {
            var data;
            if (key) {
                if (isUndefined(values)) {
                    data = getLocale(key);
                } else {
                    data = defineLocale(key, values);
                }
    
                if (data) {
                    // moment.duration._locale = moment._locale = data;
                    globalLocale = data;
                } else {
                    if (typeof console !== 'undefined' && console.warn) {
                        //warn user if arguments are passed but the locale could not be set
                        console.warn(
                            'Locale ' + key + ' not found. Did you forget to load it?'
                        );
                    }
                }
            }
    
            return globalLocale._abbr;
        }
    
        function defineLocale(name, config) {
            if (config !== null) {
                var locale,
                    parentConfig = baseConfig;
                config.abbr = name;
                if (locales[name] != null) {
                    deprecateSimple(
                        'defineLocaleOverride',
                        'use moment.updateLocale(localeName, config) to change ' +
                            'an existing locale. moment.defineLocale(localeName, ' +
                            'config) should only be used for creating a new locale ' +
                            'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'
                    );
                    parentConfig = locales[name]._config;
                } else if (config.parentLocale != null) {
                    if (locales[config.parentLocale] != null) {
                        parentConfig = locales[config.parentLocale]._config;
                    } else {
                        locale = loadLocale(config.parentLocale);
                        if (locale != null) {
                            parentConfig = locale._config;
                        } else {
                            if (!localeFamilies[config.parentLocale]) {
                                localeFamilies[config.parentLocale] = [];
                            }
                            localeFamilies[config.parentLocale].push({
                                name: name,
                                config: config,
                            });
                            return null;
                        }
                    }
                }
                locales[name] = new Locale(mergeConfigs(parentConfig, config));
    
                if (localeFamilies[name]) {
                    localeFamilies[name].forEach(function (x) {
                        defineLocale(x.name, x.config);
                    });
                }
    
                // backwards compat for now: also set the locale
                // make sure we set the locale AFTER all child locales have been
                // created, so we won't end up with the child locale set.
                getSetGlobalLocale(name);
    
                return locales[name];
            } else {
                // useful for testing
                delete locales[name];
                return null;
            }
        }
    
        function updateLocale(name, config) {
            if (config != null) {
                var locale,
                    tmpLocale,
                    parentConfig = baseConfig;
    
                if (locales[name] != null && locales[name].parentLocale != null) {
                    // Update existing child locale in-place to avoid memory-leaks
                    locales[name].set(mergeConfigs(locales[name]._config, config));
                } else {
                    // MERGE
                    tmpLocale = loadLocale(name);
                    if (tmpLocale != null) {
                        parentConfig = tmpLocale._config;
                    }
                    config = mergeConfigs(parentConfig, config);
                    if (tmpLocale == null) {
                        // updateLocale is called for creating a new locale
                        // Set abbr so it will have a name (getters return
                        // undefined otherwise).
                        config.abbr = name;
                    }
                    locale = new Locale(config);
                    locale.parentLocale = locales[name];
                    locales[name] = locale;
                }
    
                // backwards compat for now: also set the locale
                getSetGlobalLocale(name);
            } else {
                // pass null for config to unupdate, useful for tests
                if (locales[name] != null) {
                    if (locales[name].parentLocale != null) {
                        locales[name] = locales[name].parentLocale;
                        if (name === getSetGlobalLocale()) {
                            getSetGlobalLocale(name);
                        }
                    } else if (locales[name] != null) {
                        delete locales[name];
                    }
                }
            }
            return locales[name];
        }
    
        // returns locale data
        function getLocale(key) {
            var locale;
    
            if (key && key._locale && key._locale._abbr) {
                key = key._locale._abbr;
            }
    
            if (!key) {
                return globalLocale;
            }
    
            if (!isArray(key)) {
                //short-circuit everything else
                locale = loadLocale(key);
                if (locale) {
                    return locale;
                }
                key = [key];
            }
    
            return chooseLocale(key);
        }
    
        function listLocales() {
            return keys(locales);
        }
    
        function checkOverflow(m) {
            var overflow,
                a = m._a;
    
            if (a && getParsingFlags(m).overflow === -2) {
                overflow =
                    a[MONTH] < 0 || a[MONTH] > 11
                        ? MONTH
                        : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH])
                        ? DATE
                        : a[HOUR] < 0 ||
                          a[HOUR] > 24 ||
                          (a[HOUR] === 24 &&
                              (a[MINUTE] !== 0 ||
                                  a[SECOND] !== 0 ||
                                  a[MILLISECOND] !== 0))
                        ? HOUR
                        : a[MINUTE] < 0 || a[MINUTE] > 59
                        ? MINUTE
                        : a[SECOND] < 0 || a[SECOND] > 59
                        ? SECOND
                        : a[MILLISECOND] < 0 || a[MILLISECOND] > 999
                        ? MILLISECOND
                        : -1;
    
                if (
                    getParsingFlags(m)._overflowDayOfYear &&
                    (overflow < YEAR || overflow > DATE)
                ) {
                    overflow = DATE;
                }
                if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
                    overflow = WEEK;
                }
                if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
                    overflow = WEEKDAY;
                }
    
                getParsingFlags(m).overflow = overflow;
            }
    
            return m;
        }
    
        // iso 8601 regex
        // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
        var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
            basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
            tzRegex = /Z|[+-]\d\d(?::?\d\d)?/,
            isoDates = [
                ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
                ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
                ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
                ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
                ['YYYY-DDD', /\d{4}-\d{3}/],
                ['YYYY-MM', /\d{4}-\d\d/, false],
                ['YYYYYYMMDD', /[+-]\d{10}/],
                ['YYYYMMDD', /\d{8}/],
                ['GGGG[W]WWE', /\d{4}W\d{3}/],
                ['GGGG[W]WW', /\d{4}W\d{2}/, false],
                ['YYYYDDD', /\d{7}/],
                ['YYYYMM', /\d{6}/, false],
                ['YYYY', /\d{4}/, false],
            ],
            // iso time formats and regexes
            isoTimes = [
                ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
                ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
                ['HH:mm:ss', /\d\d:\d\d:\d\d/],
                ['HH:mm', /\d\d:\d\d/],
                ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
                ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
                ['HHmmss', /\d\d\d\d\d\d/],
                ['HHmm', /\d\d\d\d/],
                ['HH', /\d\d/],
            ],
            aspNetJsonRegex = /^\/?Date\((-?\d+)/i,
            // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
            rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,
            obsOffsets = {
                UT: 0,
                GMT: 0,
                EDT: -4 * 60,
                EST: -5 * 60,
                CDT: -5 * 60,
                CST: -6 * 60,
                MDT: -6 * 60,
                MST: -7 * 60,
                PDT: -7 * 60,
                PST: -8 * 60,
            };
    
        // date from iso format
        function configFromISO(config) {
            var i,
                l,
                string = config._i,
                match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
                allowTime,
                dateFormat,
                timeFormat,
                tzFormat;
    
            if (match) {
                getParsingFlags(config).iso = true;
    
                for (i = 0, l = isoDates.length; i < l; i++) {
                    if (isoDates[i][1].exec(match[1])) {
                        dateFormat = isoDates[i][0];
                        allowTime = isoDates[i][2] !== false;
                        break;
                    }
                }
                if (dateFormat == null) {
                    config._isValid = false;
                    return;
                }
                if (match[3]) {
                    for (i = 0, l = isoTimes.length; i < l; i++) {
                        if (isoTimes[i][1].exec(match[3])) {
                            // match[2] should be 'T' or space
                            timeFormat = (match[2] || ' ') + isoTimes[i][0];
                            break;
                        }
                    }
                    if (timeFormat == null) {
                        config._isValid = false;
                        return;
                    }
                }
                if (!allowTime && timeFormat != null) {
                    config._isValid = false;
                    return;
                }
                if (match[4]) {
                    if (tzRegex.exec(match[4])) {
                        tzFormat = 'Z';
                    } else {
                        config._isValid = false;
                        return;
                    }
                }
                config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
                configFromStringAndFormat(config);
            } else {
                config._isValid = false;
            }
        }
    
        function extractFromRFC2822Strings(
            yearStr,
            monthStr,
            dayStr,
            hourStr,
            minuteStr,
            secondStr
        ) {
            var result = [
                untruncateYear(yearStr),
                defaultLocaleMonthsShort.indexOf(monthStr),
                parseInt(dayStr, 10),
                parseInt(hourStr, 10),
                parseInt(minuteStr, 10),
            ];
    
            if (secondStr) {
                result.push(parseInt(secondStr, 10));
            }
    
            return result;
        }
    
        function untruncateYear(yearStr) {
            var year = parseInt(yearStr, 10);
            if (year <= 49) {
                return 2000 + year;
            } else if (year <= 999) {
                return 1900 + year;
            }
            return year;
        }
    
        function preprocessRFC2822(s) {
            // Remove comments and folding whitespace and replace multiple-spaces with a single space
            return s
                .replace(/\([^)]*\)|[\n\t]/g, ' ')
                .replace(/(\s\s+)/g, ' ')
                .replace(/^\s\s*/, '')
                .replace(/\s\s*$/, '');
        }
    
        function checkWeekday(weekdayStr, parsedInput, config) {
            if (weekdayStr) {
                // TODO: Replace the vanilla JS Date object with an independent day-of-week check.
                var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
                    weekdayActual = new Date(
                        parsedInput[0],
                        parsedInput[1],
                        parsedInput[2]
                    ).getDay();
                if (weekdayProvided !== weekdayActual) {
                    getParsingFlags(config).weekdayMismatch = true;
                    config._isValid = false;
                    return false;
                }
            }
            return true;
        }
    
        function calculateOffset(obsOffset, militaryOffset, numOffset) {
            if (obsOffset) {
                return obsOffsets[obsOffset];
            } else if (militaryOffset) {
                // the only allowed military tz is Z
                return 0;
            } else {
                var hm = parseInt(numOffset, 10),
                    m = hm % 100,
                    h = (hm - m) / 100;
                return h * 60 + m;
            }
        }
    
        // date and time from ref 2822 format
        function configFromRFC2822(config) {
            var match = rfc2822.exec(preprocessRFC2822(config._i)),
                parsedArray;
            if (match) {
                parsedArray = extractFromRFC2822Strings(
                    match[4],
                    match[3],
                    match[2],
                    match[5],
                    match[6],
                    match[7]
                );
                if (!checkWeekday(match[1], parsedArray, config)) {
                    return;
                }
    
                config._a = parsedArray;
                config._tzm = calculateOffset(match[8], match[9], match[10]);
    
                config._d = createUTCDate.apply(null, config._a);
                config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
    
                getParsingFlags(config).rfc2822 = true;
            } else {
                config._isValid = false;
            }
        }
    
        // date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
        function configFromString(config) {
            var matched = aspNetJsonRegex.exec(config._i);
            if (matched !== null) {
                config._d = new Date(+matched[1]);
                return;
            }
    
            configFromISO(config);
            if (config._isValid === false) {
                delete config._isValid;
            } else {
                return;
            }
    
            configFromRFC2822(config);
            if (config._isValid === false) {
                delete config._isValid;
            } else {
                return;
            }
    
            if (config._strict) {
                config._isValid = false;
            } else {
                // Final attempt, use Input Fallback
                hooks.createFromInputFallback(config);
            }
        }
    
        hooks.createFromInputFallback = deprecate(
            'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
                'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
                'discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.',
            function (config) {
                config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
            }
        );
    
        // Pick the first defined of two or three arguments.
        function defaults(a, b, c) {
            if (a != null) {
                return a;
            }
            if (b != null) {
                return b;
            }
            return c;
        }
    
        function currentDateArray(config) {
            // hooks is actually the exported moment object
            var nowValue = new Date(hooks.now());
            if (config._useUTC) {
                return [
                    nowValue.getUTCFullYear(),
                    nowValue.getUTCMonth(),
                    nowValue.getUTCDate(),
                ];
            }
            return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
        }
    
        // convert an array to a date.
        // the array should mirror the parameters below
        // note: all values past the year are optional and will default to the lowest possible value.
        // [year, month, day , hour, minute, second, millisecond]
        function configFromArray(config) {
            var i,
                date,
                input = [],
                currentDate,
                expectedWeekday,
                yearToUse;
    
            if (config._d) {
                return;
            }
    
            currentDate = currentDateArray(config);
    
            //compute day of the year from weeks and weekdays
            if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
                dayOfYearFromWeekInfo(config);
            }
    
            //if the day of the year is set, figure out what it is
            if (config._dayOfYear != null) {
                yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
    
                if (
                    config._dayOfYear > daysInYear(yearToUse) ||
                    config._dayOfYear === 0
                ) {
                    getParsingFlags(config)._overflowDayOfYear = true;
                }
    
                date = createUTCDate(yearToUse, 0, config._dayOfYear);
                config._a[MONTH] = date.getUTCMonth();
                config._a[DATE] = date.getUTCDate();
            }
    
            // Default to current date.
            // * if no year, month, day of month are given, default to today
            // * if day of month is given, default month and year
            // * if month is given, default only year
            // * if year is given, don't default anything
            for (i = 0; i < 3 && config._a[i] == null; ++i) {
                config._a[i] = input[i] = currentDate[i];
            }
    
            // Zero out whatever was not defaulted, including time
            for (; i < 7; i++) {
                config._a[i] = input[i] =
                    config._a[i] == null ? (i === 2 ? 1 : 0) : config._a[i];
            }
    
            // Check for 24:00:00.000
            if (
                config._a[HOUR] === 24 &&
                config._a[MINUTE] === 0 &&
                config._a[SECOND] === 0 &&
                config._a[MILLISECOND] === 0
            ) {
                config._nextDay = true;
                config._a[HOUR] = 0;
            }
    
            config._d = (config._useUTC ? createUTCDate : createDate).apply(
                null,
                input
            );
            expectedWeekday = config._useUTC
                ? config._d.getUTCDay()
                : config._d.getDay();
    
            // Apply timezone offset from input. The actual utcOffset can be changed
            // with parseZone.
            if (config._tzm != null) {
                config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
            }
    
            if (config._nextDay) {
                config._a[HOUR] = 24;
            }
    
            // check for mismatching day of week
            if (
                config._w &&
                typeof config._w.d !== 'undefined' &&
                config._w.d !== expectedWeekday
            ) {
                getParsingFlags(config).weekdayMismatch = true;
            }
        }
    
        function dayOfYearFromWeekInfo(config) {
            var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, curWeek;
    
            w = config._w;
            if (w.GG != null || w.W != null || w.E != null) {
                dow = 1;
                doy = 4;
    
                // TODO: We need to take the current isoWeekYear, but that depends on
                // how we interpret now (local, utc, fixed offset). So create
                // a now version of current config (take local/utc/offset flags, and
                // create now).
                weekYear = defaults(
                    w.GG,
                    config._a[YEAR],
                    weekOfYear(createLocal(), 1, 4).year
                );
                week = defaults(w.W, 1);
                weekday = defaults(w.E, 1);
                if (weekday < 1 || weekday > 7) {
                    weekdayOverflow = true;
                }
            } else {
                dow = config._locale._week.dow;
                doy = config._locale._week.doy;
    
                curWeek = weekOfYear(createLocal(), dow, doy);
    
                weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
    
                // Default to current week.
                week = defaults(w.w, curWeek.week);
    
                if (w.d != null) {
                    // weekday -- low day numbers are considered next week
                    weekday = w.d;
                    if (weekday < 0 || weekday > 6) {
                        weekdayOverflow = true;
                    }
                } else if (w.e != null) {
                    // local weekday -- counting starts from beginning of week
                    weekday = w.e + dow;
                    if (w.e < 0 || w.e > 6) {
                        weekdayOverflow = true;
                    }
                } else {
                    // default to beginning of week
                    weekday = dow;
                }
            }
            if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
                getParsingFlags(config)._overflowWeeks = true;
            } else if (weekdayOverflow != null) {
                getParsingFlags(config)._overflowWeekday = true;
            } else {
                temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
                config._a[YEAR] = temp.year;
                config._dayOfYear = temp.dayOfYear;
            }
        }
    
        // constant that refers to the ISO standard
        hooks.ISO_8601 = function () {};
    
        // constant that refers to the RFC 2822 form
        hooks.RFC_2822 = function () {};
    
        // date from string and format string
        function configFromStringAndFormat(config) {
            // TODO: Move this to another part of the creation flow to prevent circular deps
            if (config._f === hooks.ISO_8601) {
                configFromISO(config);
                return;
            }
            if (config._f === hooks.RFC_2822) {
                configFromRFC2822(config);
                return;
            }
            config._a = [];
            getParsingFlags(config).empty = true;
    
            // This array is used to make a Date, either with `new Date` or `Date.UTC`
            var string = '' + config._i,
                i,
                parsedInput,
                tokens,
                token,
                skipped,
                stringLength = string.length,
                totalParsedInputLength = 0,
                era;
    
            tokens =
                expandFormat(config._f, config._locale).match(formattingTokens) || [];
    
            for (i = 0; i < tokens.length; i++) {
                token = tokens[i];
                parsedInput = (string.match(getParseRegexForToken(token, config)) ||
                    [])[0];
                if (parsedInput) {
                    skipped = string.substr(0, string.indexOf(parsedInput));
                    if (skipped.length > 0) {
                        getParsingFlags(config).unusedInput.push(skipped);
                    }
                    string = string.slice(
                        string.indexOf(parsedInput) + parsedInput.length
                    );
                    totalParsedInputLength += parsedInput.length;
                }
                // don't parse if it's not a known token
                if (formatTokenFunctions[token]) {
                    if (parsedInput) {
                        getParsingFlags(config).empty = false;
                    } else {
                        getParsingFlags(config).unusedTokens.push(token);
                    }
                    addTimeToArrayFromToken(token, parsedInput, config);
                } else if (config._strict && !parsedInput) {
                    getParsingFlags(config).unusedTokens.push(token);
                }
            }
    
            // add remaining unparsed input length to the string
            getParsingFlags(config).charsLeftOver =
                stringLength - totalParsedInputLength;
            if (string.length > 0) {
                getParsingFlags(config).unusedInput.push(string);
            }
    
            // clear _12h flag if hour is <= 12
            if (
                config._a[HOUR] <= 12 &&
                getParsingFlags(config).bigHour === true &&
                config._a[HOUR] > 0
            ) {
                getParsingFlags(config).bigHour = undefined;
            }
    
            getParsingFlags(config).parsedDateParts = config._a.slice(0);
            getParsingFlags(config).meridiem = config._meridiem;
            // handle meridiem
            config._a[HOUR] = meridiemFixWrap(
                config._locale,
                config._a[HOUR],
                config._meridiem
            );
    
            // handle era
            era = getParsingFlags(config).era;
            if (era !== null) {
                config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);
            }
    
            configFromArray(config);
            checkOverflow(config);
        }
    
        function meridiemFixWrap(locale, hour, meridiem) {
            var isPm;
    
            if (meridiem == null) {
                // nothing to do
                return hour;
            }
            if (locale.meridiemHour != null) {
                return locale.meridiemHour(hour, meridiem);
            } else if (locale.isPM != null) {
                // Fallback
                isPm = locale.isPM(meridiem);
                if (isPm && hour < 12) {
                    hour += 12;
                }
                if (!isPm && hour === 12) {
                    hour = 0;
                }
                return hour;
            } else {
                // this is not supposed to happen
                return hour;
            }
        }
    
        // date from string and array of format strings
        function configFromStringAndArray(config) {
            var tempConfig,
                bestMoment,
                scoreToBeat,
                i,
                currentScore,
                validFormatFound,
                bestFormatIsValid = false;
    
            if (config._f.length === 0) {
                getParsingFlags(config).invalidFormat = true;
                config._d = new Date(NaN);
                return;
            }
    
            for (i = 0; i < config._f.length; i++) {
                currentScore = 0;
                validFormatFound = false;
                tempConfig = copyConfig({}, config);
                if (config._useUTC != null) {
                    tempConfig._useUTC = config._useUTC;
                }
                tempConfig._f = config._f[i];
                configFromStringAndFormat(tempConfig);
    
                if (isValid(tempConfig)) {
                    validFormatFound = true;
                }
    
                // if there is any input that was not parsed add a penalty for that format
                currentScore += getParsingFlags(tempConfig).charsLeftOver;
    
                //or tokens
                currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
    
                getParsingFlags(tempConfig).score = currentScore;
    
                if (!bestFormatIsValid) {
                    if (
                        scoreToBeat == null ||
                        currentScore < scoreToBeat ||
                        validFormatFound
                    ) {
                        scoreToBeat = currentScore;
                        bestMoment = tempConfig;
                        if (validFormatFound) {
                            bestFormatIsValid = true;
                        }
                    }
                } else {
                    if (currentScore < scoreToBeat) {
                        scoreToBeat = currentScore;
                        bestMoment = tempConfig;
                    }
                }
            }
    
            extend(config, bestMoment || tempConfig);
        }
    
        function configFromObject(config) {
            if (config._d) {
                return;
            }
    
            var i = normalizeObjectUnits(config._i),
                dayOrDate = i.day === undefined ? i.date : i.day;
            config._a = map(
                [i.year, i.month, dayOrDate, i.hour, i.minute, i.second, i.millisecond],
                function (obj) {
                    return obj && parseInt(obj, 10);
                }
            );
    
            configFromArray(config);
        }
    
        function createFromConfig(config) {
            var res = new Moment(checkOverflow(prepareConfig(config)));
            if (res._nextDay) {
                // Adding is smart enough around DST
                res.add(1, 'd');
                res._nextDay = undefined;
            }
    
            return res;
        }
    
        function prepareConfig(config) {
            var input = config._i,
                format = config._f;
    
            config._locale = config._locale || getLocale(config._l);
    
            if (input === null || (format === undefined && input === '')) {
                return createInvalid({ nullInput: true });
            }
    
            if (typeof input === 'string') {
                config._i = input = config._locale.preparse(input);
            }
    
            if (isMoment(input)) {
                return new Moment(checkOverflow(input));
            } else if (isDate(input)) {
                config._d = input;
            } else if (isArray(format)) {
                configFromStringAndArray(config);
            } else if (format) {
                configFromStringAndFormat(config);
            } else {
                configFromInput(config);
            }
    
            if (!isValid(config)) {
                config._d = null;
            }
    
            return config;
        }
    
        function configFromInput(config) {
            var input = config._i;
            if (isUndefined(input)) {
                config._d = new Date(hooks.now());
            } else if (isDate(input)) {
                config._d = new Date(input.valueOf());
            } else if (typeof input === 'string') {
                configFromString(config);
            } else if (isArray(input)) {
                config._a = map(input.slice(0), function (obj) {
                    return parseInt(obj, 10);
                });
                configFromArray(config);
            } else if (isObject(input)) {
                configFromObject(config);
            } else if (isNumber(input)) {
                // from milliseconds
                config._d = new Date(input);
            } else {
                hooks.createFromInputFallback(config);
            }
        }
    
        function createLocalOrUTC(input, format, locale, strict, isUTC) {
            var c = {};
    
            if (format === true || format === false) {
                strict = format;
                format = undefined;
            }
    
            if (locale === true || locale === false) {
                strict = locale;
                locale = undefined;
            }
    
            if (
                (isObject(input) && isObjectEmpty(input)) ||
                (isArray(input) && input.length === 0)
            ) {
                input = undefined;
            }
            // object construction must be done this way.
            // https://github.com/moment/moment/issues/1423
            c._isAMomentObject = true;
            c._useUTC = c._isUTC = isUTC;
            c._l = locale;
            c._i = input;
            c._f = format;
            c._strict = strict;
    
            return createFromConfig(c);
        }
    
        function createLocal(input, format, locale, strict) {
            return createLocalOrUTC(input, format, locale, strict, false);
        }
    
        var prototypeMin = deprecate(
                'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
                function () {
                    var other = createLocal.apply(null, arguments);
                    if (this.isValid() && other.isValid()) {
                        return other < this ? this : other;
                    } else {
                        return createInvalid();
                    }
                }
            ),
            prototypeMax = deprecate(
                'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
                function () {
                    var other = createLocal.apply(null, arguments);
                    if (this.isValid() && other.isValid()) {
                        return other > this ? this : other;
                    } else {
                        return createInvalid();
                    }
                }
            );
    
        // Pick a moment m from moments so that m[fn](other) is true for all
        // other. This relies on the function fn to be transitive.
        //
        // moments should either be an array of moment objects or an array, whose
        // first element is an array of moment objects.
        function pickBy(fn, moments) {
            var res, i;
            if (moments.length === 1 && isArray(moments[0])) {
                moments = moments[0];
            }
            if (!moments.length) {
                return createLocal();
            }
            res = moments[0];
            for (i = 1; i < moments.length; ++i) {
                if (!moments[i].isValid() || moments[i][fn](res)) {
                    res = moments[i];
                }
            }
            return res;
        }
    
        // TODO: Use [].sort instead?
        function min() {
            var args = [].slice.call(arguments, 0);
    
            return pickBy('isBefore', args);
        }
    
        function max() {
            var args = [].slice.call(arguments, 0);
    
            return pickBy('isAfter', args);
        }
    
        var now = function () {
            return Date.now ? Date.now() : +new Date();
        };
    
        var ordering = [
            'year',
            'quarter',
            'month',
            'week',
            'day',
            'hour',
            'minute',
            'second',
            'millisecond',
        ];
    
        function isDurationValid(m) {
            var key,
                unitHasDecimal = false,
                i;
            for (key in m) {
                if (
                    hasOwnProp(m, key) &&
                    !(
                        indexOf.call(ordering, key) !== -1 &&
                        (m[key] == null || !isNaN(m[key]))
                    )
                ) {
                    return false;
                }
            }
    
            for (i = 0; i < ordering.length; ++i) {
                if (m[ordering[i]]) {
                    if (unitHasDecimal) {
                        return false; // only allow non-integers for smallest unit
                    }
                    if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
                        unitHasDecimal = true;
                    }
                }
            }
    
            return true;
        }
    
        function isValid$1() {
            return this._isValid;
        }
    
        function createInvalid$1() {
            return createDuration(NaN);
        }
    
        function Duration(duration) {
            var normalizedInput = normalizeObjectUnits(duration),
                years = normalizedInput.year || 0,
                quarters = normalizedInput.quarter || 0,
                months = normalizedInput.month || 0,
                weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
                days = normalizedInput.day || 0,
                hours = normalizedInput.hour || 0,
                minutes = normalizedInput.minute || 0,
                seconds = normalizedInput.second || 0,
                milliseconds = normalizedInput.millisecond || 0;
    
            this._isValid = isDurationValid(normalizedInput);
    
            // representation for dateAddRemove
            this._milliseconds =
                +milliseconds +
                seconds * 1e3 + // 1000
                minutes * 6e4 + // 1000 * 60
                hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
            // Because of dateAddRemove treats 24 hours as different from a
            // day when working around DST, we need to store them separately
            this._days = +days + weeks * 7;
            // It is impossible to translate months into days without knowing
            // which months you are are talking about, so we have to store
            // it separately.
            this._months = +months + quarters * 3 + years * 12;
    
            this._data = {};
    
            this._locale = getLocale();
    
            this._bubble();
        }
    
        function isDuration(obj) {
            return obj instanceof Duration;
        }
    
        function absRound(number) {
            if (number < 0) {
                return Math.round(-1 * number) * -1;
            } else {
                return Math.round(number);
            }
        }
    
        // compare two arrays, return the number of differences
        function compareArrays(array1, array2, dontConvert) {
            var len = Math.min(array1.length, array2.length),
                lengthDiff = Math.abs(array1.length - array2.length),
                diffs = 0,
                i;
            for (i = 0; i < len; i++) {
                if (
                    (dontConvert && array1[i] !== array2[i]) ||
                    (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))
                ) {
                    diffs++;
                }
            }
            return diffs + lengthDiff;
        }
    
        // FORMATTING
    
        function offset(token, separator) {
            addFormatToken(token, 0, 0, function () {
                var offset = this.utcOffset(),
                    sign = '+';
                if (offset < 0) {
                    offset = -offset;
                    sign = '-';
                }
                return (
                    sign +
                    zeroFill(~~(offset / 60), 2) +
                    separator +
                    zeroFill(~~offset % 60, 2)
                );
            });
        }
    
        offset('Z', ':');
        offset('ZZ', '');
    
        // PARSING
    
        addRegexToken('Z', matchShortOffset);
        addRegexToken('ZZ', matchShortOffset);
        addParseToken(['Z', 'ZZ'], function (input, array, config) {
            config._useUTC = true;
            config._tzm = offsetFromString(matchShortOffset, input);
        });
    
        // HELPERS
    
        // timezone chunker
        // '+10:00' > ['10',  '00']
        // '-1530'  > ['-15', '30']
        var chunkOffset = /([\+\-]|\d\d)/gi;
    
        function offsetFromString(matcher, string) {
            var matches = (string || '').match(matcher),
                chunk,
                parts,
                minutes;
    
            if (matches === null) {
                return null;
            }
    
            chunk = matches[matches.length - 1] || [];
            parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
            minutes = +(parts[1] * 60) + toInt(parts[2]);
    
            return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
        }
    
        // Return a moment from input, that is local/utc/zone equivalent to model.
        function cloneWithOffset(input, model) {
            var res, diff;
            if (model._isUTC) {
                res = model.clone();
                diff =
                    (isMoment(input) || isDate(input)
                        ? input.valueOf()
                        : createLocal(input).valueOf()) - res.valueOf();
                // Use low-level api, because this fn is low-level api.
                res._d.setTime(res._d.valueOf() + diff);
                hooks.updateOffset(res, false);
                return res;
            } else {
                return createLocal(input).local();
            }
        }
    
        function getDateOffset(m) {
            // On Firefox.24 Date#getTimezoneOffset returns a floating point.
            // https://github.com/moment/moment/pull/1871
            return -Math.round(m._d.getTimezoneOffset());
        }
    
        // HOOKS
    
        // This function will be called whenever a moment is mutated.
        // It is intended to keep the offset in sync with the timezone.
        hooks.updateOffset = function () {};
    
        // MOMENTS
    
        // keepLocalTime = true means only change the timezone, without
        // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
        // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
        // +0200, so we adjust the time as needed, to be valid.
        //
        // Keeping the time actually adds/subtracts (one hour)
        // from the actual represented time. That is why we call updateOffset
        // a second time. In case it wants us to change the offset again
        // _changeInProgress == true case, then we have to adjust, because
        // there is no such time in the given timezone.
        function getSetOffset(input, keepLocalTime, keepMinutes) {
            var offset = this._offset || 0,
                localAdjust;
            if (!this.isValid()) {
                return input != null ? this : NaN;
            }
            if (input != null) {
                if (typeof input === 'string') {
                    input = offsetFromString(matchShortOffset, input);
                    if (input === null) {
                        return this;
                    }
                } else if (Math.abs(input) < 16 && !keepMinutes) {
                    input = input * 60;
                }
                if (!this._isUTC && keepLocalTime) {
                    localAdjust = getDateOffset(this);
                }
                this._offset = input;
                this._isUTC = true;
                if (localAdjust != null) {
                    this.add(localAdjust, 'm');
                }
                if (offset !== input) {
                    if (!keepLocalTime || this._changeInProgress) {
                        addSubtract(
                            this,
                            createDuration(input - offset, 'm'),
                            1,
                            false
                        );
                    } else if (!this._changeInProgress) {
                        this._changeInProgress = true;
                        hooks.updateOffset(this, true);
                        this._changeInProgress = null;
                    }
                }
                return this;
            } else {
                return this._isUTC ? offset : getDateOffset(this);
            }
        }
    
        function getSetZone(input, keepLocalTime) {
            if (input != null) {
                if (typeof input !== 'string') {
                    input = -input;
                }
    
                this.utcOffset(input, keepLocalTime);
    
                return this;
            } else {
                return -this.utcOffset();
            }
        }
    
        function setOffsetToUTC(keepLocalTime) {
            return this.utcOffset(0, keepLocalTime);
        }
    
        function setOffsetToLocal(keepLocalTime) {
            if (this._isUTC) {
                this.utcOffset(0, keepLocalTime);
                this._isUTC = false;
    
                if (keepLocalTime) {
                    this.subtract(getDateOffset(this), 'm');
                }
            }
            return this;
        }
    
        function setOffsetToParsedOffset() {
            if (this._tzm != null) {
                this.utcOffset(this._tzm, false, true);
            } else if (typeof this._i === 'string') {
                var tZone = offsetFromString(matchOffset, this._i);
                if (tZone != null) {
                    this.utcOffset(tZone);
                } else {
                    this.utcOffset(0, true);
                }
            }
            return this;
        }
    
        function hasAlignedHourOffset(input) {
            if (!this.isValid()) {
                return false;
            }
            input = input ? createLocal(input).utcOffset() : 0;
    
            return (this.utcOffset() - input) % 60 === 0;
        }
    
        function isDaylightSavingTime() {
            return (
                this.utcOffset() > this.clone().month(0).utcOffset() ||
                this.utcOffset() > this.clone().month(5).utcOffset()
            );
        }
    
        function isDaylightSavingTimeShifted() {
            if (!isUndefined(this._isDSTShifted)) {
                return this._isDSTShifted;
            }
    
            var c = {},
                other;
    
            copyConfig(c, this);
            c = prepareConfig(c);
    
            if (c._a) {
                other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
                this._isDSTShifted =
                    this.isValid() && compareArrays(c._a, other.toArray()) > 0;
            } else {
                this._isDSTShifted = false;
            }
    
            return this._isDSTShifted;
        }
    
        function isLocal() {
            return this.isValid() ? !this._isUTC : false;
        }
    
        function isUtcOffset() {
            return this.isValid() ? this._isUTC : false;
        }
    
        function isUtc() {
            return this.isValid() ? this._isUTC && this._offset === 0 : false;
        }
    
        // ASP.NET json date format regex
        var aspNetRegex = /^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,
            // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
            // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
            // and further modified to allow for strings containing both week and day
            isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
    
        function createDuration(input, key) {
            var duration = input,
                // matching against regexp is expensive, do it on demand
                match = null,
                sign,
                ret,
                diffRes;
    
            if (isDuration(input)) {
                duration = {
                    ms: input._milliseconds,
                    d: input._days,
                    M: input._months,
                };
            } else if (isNumber(input) || !isNaN(+input)) {
                duration = {};
                if (key) {
                    duration[key] = +input;
                } else {
                    duration.milliseconds = +input;
                }
            } else if ((match = aspNetRegex.exec(input))) {
                sign = match[1] === '-' ? -1 : 1;
                duration = {
                    y: 0,
                    d: toInt(match[DATE]) * sign,
                    h: toInt(match[HOUR]) * sign,
                    m: toInt(match[MINUTE]) * sign,
                    s: toInt(match[SECOND]) * sign,
                    ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign, // the millisecond decimal point is included in the match
                };
            } else if ((match = isoRegex.exec(input))) {
                sign = match[1] === '-' ? -1 : 1;
                duration = {
                    y: parseIso(match[2], sign),
                    M: parseIso(match[3], sign),
                    w: parseIso(match[4], sign),
                    d: parseIso(match[5], sign),
                    h: parseIso(match[6], sign),
                    m: parseIso(match[7], sign),
                    s: parseIso(match[8], sign),
                };
            } else if (duration == null) {
                // checks for null or undefined
                duration = {};
            } else if (
                typeof duration === 'object' &&
                ('from' in duration || 'to' in duration)
            ) {
                diffRes = momentsDifference(
                    createLocal(duration.from),
                    createLocal(duration.to)
                );
    
                duration = {};
                duration.ms = diffRes.milliseconds;
                duration.M = diffRes.months;
            }
    
            ret = new Duration(duration);
    
            if (isDuration(input) && hasOwnProp(input, '_locale')) {
                ret._locale = input._locale;
            }
    
            if (isDuration(input) && hasOwnProp(input, '_isValid')) {
                ret._isValid = input._isValid;
            }
    
            return ret;
        }
    
        createDuration.fn = Duration.prototype;
        createDuration.invalid = createInvalid$1;
    
        function parseIso(inp, sign) {
            // We'd normally use ~~inp for this, but unfortunately it also
            // converts floats to ints.
            // inp may be undefined, so careful calling replace on it.
            var res = inp && parseFloat(inp.replace(',', '.'));
            // apply sign while we're at it
            return (isNaN(res) ? 0 : res) * sign;
        }
    
        function positiveMomentsDifference(base, other) {
            var res = {};
    
            res.months =
                other.month() - base.month() + (other.year() - base.year()) * 12;
            if (base.clone().add(res.months, 'M').isAfter(other)) {
                --res.months;
            }
    
            res.milliseconds = +other - +base.clone().add(res.months, 'M');
    
            return res;
        }
    
        function momentsDifference(base, other) {
            var res;
            if (!(base.isValid() && other.isValid())) {
                return { milliseconds: 0, months: 0 };
            }
    
            other = cloneWithOffset(other, base);
            if (base.isBefore(other)) {
                res = positiveMomentsDifference(base, other);
            } else {
                res = positiveMomentsDifference(other, base);
                res.milliseconds = -res.milliseconds;
                res.months = -res.months;
            }
    
            return res;
        }
    
        // TODO: remove 'name' arg after deprecation is removed
        function createAdder(direction, name) {
            return function (val, period) {
                var dur, tmp;
                //invert the arguments, but complain about it
                if (period !== null && !isNaN(+period)) {
                    deprecateSimple(
                        name,
                        'moment().' +
                            name +
                            '(period, number) is deprecated. Please use moment().' +
                            name +
                            '(number, period). ' +
                            'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'
                    );
                    tmp = val;
                    val = period;
                    period = tmp;
                }
    
                dur = createDuration(val, period);
                addSubtract(this, dur, direction);
                return this;
            };
        }
    
        function addSubtract(mom, duration, isAdding, updateOffset) {
            var milliseconds = duration._milliseconds,
                days = absRound(duration._days),
                months = absRound(duration._months);
    
            if (!mom.isValid()) {
                // No op
                return;
            }
    
            updateOffset = updateOffset == null ? true : updateOffset;
    
            if (months) {
                setMonth(mom, get(mom, 'Month') + months * isAdding);
            }
            if (days) {
                set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
            }
            if (milliseconds) {
                mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
            }
            if (updateOffset) {
                hooks.updateOffset(mom, days || months);
            }
        }
    
        var add = createAdder(1, 'add'),
            subtract = createAdder(-1, 'subtract');
    
        function isString(input) {
            return typeof input === 'string' || input instanceof String;
        }
    
        // type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined
        function isMomentInput(input) {
            return (
                isMoment(input) ||
                isDate(input) ||
                isString(input) ||
                isNumber(input) ||
                isNumberOrStringArray(input) ||
                isMomentInputObject(input) ||
                input === null ||
                input === undefined
            );
        }
    
        function isMomentInputObject(input) {
            var objectTest = isObject(input) && !isObjectEmpty(input),
                propertyTest = false,
                properties = [
                    'years',
                    'year',
                    'y',
                    'months',
                    'month',
                    'M',
                    'days',
                    'day',
                    'd',
                    'dates',
                    'date',
                    'D',
                    'hours',
                    'hour',
                    'h',
                    'minutes',
                    'minute',
                    'm',
                    'seconds',
                    'second',
                    's',
                    'milliseconds',
                    'millisecond',
                    'ms',
                ],
                i,
                property;
    
            for (i = 0; i < properties.length; i += 1) {
                property = properties[i];
                propertyTest = propertyTest || hasOwnProp(input, property);
            }
    
            return objectTest && propertyTest;
        }
    
        function isNumberOrStringArray(input) {
            var arrayTest = isArray(input),
                dataTypeTest = false;
            if (arrayTest) {
                dataTypeTest =
                    input.filter(function (item) {
                        return !isNumber(item) && isString(input);
                    }).length === 0;
            }
            return arrayTest && dataTypeTest;
        }
    
        function isCalendarSpec(input) {
            var objectTest = isObject(input) && !isObjectEmpty(input),
                propertyTest = false,
                properties = [
                    'sameDay',
                    'nextDay',
                    'lastDay',
                    'nextWeek',
                    'lastWeek',
                    'sameElse',
                ],
                i,
                property;
    
            for (i = 0; i < properties.length; i += 1) {
                property = properties[i];
                propertyTest = propertyTest || hasOwnProp(input, property);
            }
    
            return objectTest && propertyTest;
        }
    
        function getCalendarFormat(myMoment, now) {
            var diff = myMoment.diff(now, 'days', true);
            return diff < -6
                ? 'sameElse'
                : diff < -1
                ? 'lastWeek'
                : diff < 0
                ? 'lastDay'
                : diff < 1
                ? 'sameDay'
                : diff < 2
                ? 'nextDay'
                : diff < 7
                ? 'nextWeek'
                : 'sameElse';
        }
    
        function calendar$1(time, formats) {
            // Support for single parameter, formats only overload to the calendar function
            if (arguments.length === 1) {
                if (!arguments[0]) {
                    time = undefined;
                    formats = undefined;
                } else if (isMomentInput(arguments[0])) {
                    time = arguments[0];
                    formats = undefined;
                } else if (isCalendarSpec(arguments[0])) {
                    formats = arguments[0];
                    time = undefined;
                }
            }
            // We want to compare the start of today, vs this.
            // Getting start-of-today depends on whether we're local/utc/offset or not.
            var now = time || createLocal(),
                sod = cloneWithOffset(now, this).startOf('day'),
                format = hooks.calendarFormat(this, sod) || 'sameElse',
                output =
                    formats &&
                    (isFunction(formats[format])
                        ? formats[format].call(this, now)
                        : formats[format]);
    
            return this.format(
                output || this.localeData().calendar(format, this, createLocal(now))
            );
        }
    
        function clone() {
            return new Moment(this);
        }
    
        function isAfter(input, units) {
            var localInput = isMoment(input) ? input : createLocal(input);
            if (!(this.isValid() && localInput.isValid())) {
                return false;
            }
            units = normalizeUnits(units) || 'millisecond';
            if (units === 'millisecond') {
                return this.valueOf() > localInput.valueOf();
            } else {
                return localInput.valueOf() < this.clone().startOf(units).valueOf();
            }
        }
    
        function isBefore(input, units) {
            var localInput = isMoment(input) ? input : createLocal(input);
            if (!(this.isValid() && localInput.isValid())) {
                return false;
            }
            units = normalizeUnits(units) || 'millisecond';
            if (units === 'millisecond') {
                return this.valueOf() < localInput.valueOf();
            } else {
                return this.clone().endOf(units).valueOf() < localInput.valueOf();
            }
        }
    
        function isBetween(from, to, units, inclusivity) {
            var localFrom = isMoment(from) ? from : createLocal(from),
                localTo = isMoment(to) ? to : createLocal(to);
            if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
                return false;
            }
            inclusivity = inclusivity || '()';
            return (
                (inclusivity[0] === '('
                    ? this.isAfter(localFrom, units)
                    : !this.isBefore(localFrom, units)) &&
                (inclusivity[1] === ')'
                    ? this.isBefore(localTo, units)
                    : !this.isAfter(localTo, units))
            );
        }
    
        function isSame(input, units) {
            var localInput = isMoment(input) ? input : createLocal(input),
                inputMs;
            if (!(this.isValid() && localInput.isValid())) {
                return false;
            }
            units = normalizeUnits(units) || 'millisecond';
            if (units === 'millisecond') {
                return this.valueOf() === localInput.valueOf();
            } else {
                inputMs = localInput.valueOf();
                return (
                    this.clone().startOf(units).valueOf() <= inputMs &&
                    inputMs <= this.clone().endOf(units).valueOf()
                );
            }
        }
    
        function isSameOrAfter(input, units) {
            return this.isSame(input, units) || this.isAfter(input, units);
        }
    
        function isSameOrBefore(input, units) {
            return this.isSame(input, units) || this.isBefore(input, units);
        }
    
        function diff(input, units, asFloat) {
            var that, zoneDelta, output;
    
            if (!this.isValid()) {
                return NaN;
            }
    
            that = cloneWithOffset(input, this);
    
            if (!that.isValid()) {
                return NaN;
            }
    
            zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
    
            units = normalizeUnits(units);
    
            switch (units) {
                case 'year':
                    output = monthDiff(this, that) / 12;
                    break;
                case 'month':
                    output = monthDiff(this, that);
                    break;
                case 'quarter':
                    output = monthDiff(this, that) / 3;
                    break;
                case 'second':
                    output = (this - that) / 1e3;
                    break; // 1000
                case 'minute':
                    output = (this - that) / 6e4;
                    break; // 1000 * 60
                case 'hour':
                    output = (this - that) / 36e5;
                    break; // 1000 * 60 * 60
                case 'day':
                    output = (this - that - zoneDelta) / 864e5;
                    break; // 1000 * 60 * 60 * 24, negate dst
                case 'week':
                    output = (this - that - zoneDelta) / 6048e5;
                    break; // 1000 * 60 * 60 * 24 * 7, negate dst
                default:
                    output = this - that;
            }
    
            return asFloat ? output : absFloor(output);
        }
    
        function monthDiff(a, b) {
            if (a.date() < b.date()) {
                // end-of-month calculations work correct when the start month has more
                // days than the end month.
                return -monthDiff(b, a);
            }
            // difference in months
            var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
                // b is in (anchor - 1 month, anchor + 1 month)
                anchor = a.clone().add(wholeMonthDiff, 'months'),
                anchor2,
                adjust;
    
            if (b - anchor < 0) {
                anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
                // linear across the month
                adjust = (b - anchor) / (anchor - anchor2);
            } else {
                anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
                // linear across the month
                adjust = (b - anchor) / (anchor2 - anchor);
            }
    
            //check for negative zero, return zero if negative zero
            return -(wholeMonthDiff + adjust) || 0;
        }
    
        hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
        hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
    
        function toString() {
            return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
        }
    
        function toISOString(keepOffset) {
            if (!this.isValid()) {
                return null;
            }
            var utc = keepOffset !== true,
                m = utc ? this.clone().utc() : this;
            if (m.year() < 0 || m.year() > 9999) {
                return formatMoment(
                    m,
                    utc
                        ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'
                        : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'
                );
            }
            if (isFunction(Date.prototype.toISOString)) {
                // native implementation is ~50x faster, use it when we can
                if (utc) {
                    return this.toDate().toISOString();
                } else {
                    return new Date(this.valueOf() + this.utcOffset() * 60 * 1000)
                        .toISOString()
                        .replace('Z', formatMoment(m, 'Z'));
                }
            }
            return formatMoment(
                m,
                utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'
            );
        }
    
        /**
         * Return a human readable representation of a moment that can
         * also be evaluated to get a new moment which is the same
         *
         * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
         */
        function inspect() {
            if (!this.isValid()) {
                return 'moment.invalid(/* ' + this._i + ' */)';
            }
            var func = 'moment',
                zone = '',
                prefix,
                year,
                datetime,
                suffix;
            if (!this.isLocal()) {
                func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
                zone = 'Z';
            }
            prefix = '[' + func + '("]';
            year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
            datetime = '-MM-DD[T]HH:mm:ss.SSS';
            suffix = zone + '[")]';
    
            return this.format(prefix + year + datetime + suffix);
        }
    
        function format(inputString) {
            if (!inputString) {
                inputString = this.isUtc()
                    ? hooks.defaultFormatUtc
                    : hooks.defaultFormat;
            }
            var output = formatMoment(this, inputString);
            return this.localeData().postformat(output);
        }
    
        function from(time, withoutSuffix) {
            if (
                this.isValid() &&
                ((isMoment(time) && time.isValid()) || createLocal(time).isValid())
            ) {
                return createDuration({ to: this, from: time })
                    .locale(this.locale())
                    .humanize(!withoutSuffix);
            } else {
                return this.localeData().invalidDate();
            }
        }
    
        function fromNow(withoutSuffix) {
            return this.from(createLocal(), withoutSuffix);
        }
    
        function to(time, withoutSuffix) {
            if (
                this.isValid() &&
                ((isMoment(time) && time.isValid()) || createLocal(time).isValid())
            ) {
                return createDuration({ from: this, to: time })
                    .locale(this.locale())
                    .humanize(!withoutSuffix);
            } else {
                return this.localeData().invalidDate();
            }
        }
    
        function toNow(withoutSuffix) {
            return this.to(createLocal(), withoutSuffix);
        }
    
        // If passed a locale key, it will set the locale for this
        // instance.  Otherwise, it will return the locale configuration
        // variables for this instance.
        function locale(key) {
            var newLocaleData;
    
            if (key === undefined) {
                return this._locale._abbr;
            } else {
                newLocaleData = getLocale(key);
                if (newLocaleData != null) {
                    this._locale = newLocaleData;
                }
                return this;
            }
        }
    
        var lang = deprecate(
            'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
            function (key) {
                if (key === undefined) {
                    return this.localeData();
                } else {
                    return this.locale(key);
                }
            }
        );
    
        function localeData() {
            return this._locale;
        }
    
        var MS_PER_SECOND = 1000,
            MS_PER_MINUTE = 60 * MS_PER_SECOND,
            MS_PER_HOUR = 60 * MS_PER_MINUTE,
            MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
    
        // actual modulo - handles negative numbers (for dates before 1970):
        function mod$1(dividend, divisor) {
            return ((dividend % divisor) + divisor) % divisor;
        }
    
        function localStartOfDate(y, m, d) {
            // the date constructor remaps years 0-99 to 1900-1999
            if (y < 100 && y >= 0) {
                // preserve leap years using a full 400 year cycle, then reset
                return new Date(y + 400, m, d) - MS_PER_400_YEARS;
            } else {
                return new Date(y, m, d).valueOf();
            }
        }
    
        function utcStartOfDate(y, m, d) {
            // Date.UTC remaps years 0-99 to 1900-1999
            if (y < 100 && y >= 0) {
                // preserve leap years using a full 400 year cycle, then reset
                return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
            } else {
                return Date.UTC(y, m, d);
            }
        }
    
        function startOf(units) {
            var time, startOfDate;
            units = normalizeUnits(units);
            if (units === undefined || units === 'millisecond' || !this.isValid()) {
                return this;
            }
    
            startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
    
            switch (units) {
                case 'year':
                    time = startOfDate(this.year(), 0, 1);
                    break;
                case 'quarter':
                    time = startOfDate(
                        this.year(),
                        this.month() - (this.month() % 3),
                        1
                    );
                    break;
                case 'month':
                    time = startOfDate(this.year(), this.month(), 1);
                    break;
                case 'week':
                    time = startOfDate(
                        this.year(),
                        this.month(),
                        this.date() - this.weekday()
                    );
                    break;
                case 'isoWeek':
                    time = startOfDate(
                        this.year(),
                        this.month(),
                        this.date() - (this.isoWeekday() - 1)
                    );
                    break;
                case 'day':
                case 'date':
                    time = startOfDate(this.year(), this.month(), this.date());
                    break;
                case 'hour':
                    time = this._d.valueOf();
                    time -= mod$1(
                        time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
                        MS_PER_HOUR
                    );
                    break;
                case 'minute':
                    time = this._d.valueOf();
                    time -= mod$1(time, MS_PER_MINUTE);
                    break;
                case 'second':
                    time = this._d.valueOf();
                    time -= mod$1(time, MS_PER_SECOND);
                    break;
            }
    
            this._d.setTime(time);
            hooks.updateOffset(this, true);
            return this;
        }
    
        function endOf(units) {
            var time, startOfDate;
            units = normalizeUnits(units);
            if (units === undefined || units === 'millisecond' || !this.isValid()) {
                return this;
            }
    
            startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
    
            switch (units) {
                case 'year':
                    time = startOfDate(this.year() + 1, 0, 1) - 1;
                    break;
                case 'quarter':
                    time =
                        startOfDate(
                            this.year(),
                            this.month() - (this.month() % 3) + 3,
                            1
                        ) - 1;
                    break;
                case 'month':
                    time = startOfDate(this.year(), this.month() + 1, 1) - 1;
                    break;
                case 'week':
                    time =
                        startOfDate(
                            this.year(),
                            this.month(),
                            this.date() - this.weekday() + 7
                        ) - 1;
                    break;
                case 'isoWeek':
                    time =
                        startOfDate(
                            this.year(),
                            this.month(),
                            this.date() - (this.isoWeekday() - 1) + 7
                        ) - 1;
                    break;
                case 'day':
                case 'date':
                    time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
                    break;
                case 'hour':
                    time = this._d.valueOf();
                    time +=
                        MS_PER_HOUR -
                        mod$1(
                            time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
                            MS_PER_HOUR
                        ) -
                        1;
                    break;
                case 'minute':
                    time = this._d.valueOf();
                    time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
                    break;
                case 'second':
                    time = this._d.valueOf();
                    time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
                    break;
            }
    
            this._d.setTime(time);
            hooks.updateOffset(this, true);
            return this;
        }
    
        function valueOf() {
            return this._d.valueOf() - (this._offset || 0) * 60000;
        }
    
        function unix() {
            return Math.floor(this.valueOf() / 1000);
        }
    
        function toDate() {
            return new Date(this.valueOf());
        }
    
        function toArray() {
            var m = this;
            return [
                m.year(),
                m.month(),
                m.date(),
                m.hour(),
                m.minute(),
                m.second(),
                m.millisecond(),
            ];
        }
    
        function toObject() {
            var m = this;
            return {
                years: m.year(),
                months: m.month(),
                date: m.date(),
                hours: m.hours(),
                minutes: m.minutes(),
                seconds: m.seconds(),
                milliseconds: m.milliseconds(),
            };
        }
    
        function toJSON() {
            // new Date(NaN).toJSON() === null
            return this.isValid() ? this.toISOString() : null;
        }
    
        function isValid$2() {
            return isValid(this);
        }
    
        function parsingFlags() {
            return extend({}, getParsingFlags(this));
        }
    
        function invalidAt() {
            return getParsingFlags(this).overflow;
        }
    
        function creationData() {
            return {
                input: this._i,
                format: this._f,
                locale: this._locale,
                isUTC: this._isUTC,
                strict: this._strict,
            };
        }
    
        addFormatToken('N', 0, 0, 'eraAbbr');
        addFormatToken('NN', 0, 0, 'eraAbbr');
        addFormatToken('NNN', 0, 0, 'eraAbbr');
        addFormatToken('NNNN', 0, 0, 'eraName');
        addFormatToken('NNNNN', 0, 0, 'eraNarrow');
    
        addFormatToken('y', ['y', 1], 'yo', 'eraYear');
        addFormatToken('y', ['yy', 2], 0, 'eraYear');
        addFormatToken('y', ['yyy', 3], 0, 'eraYear');
        addFormatToken('y', ['yyyy', 4], 0, 'eraYear');
    
        addRegexToken('N', matchEraAbbr);
        addRegexToken('NN', matchEraAbbr);
        addRegexToken('NNN', matchEraAbbr);
        addRegexToken('NNNN', matchEraName);
        addRegexToken('NNNNN', matchEraNarrow);
    
        addParseToken(['N', 'NN', 'NNN', 'NNNN', 'NNNNN'], function (
            input,
            array,
            config,
            token
        ) {
            var era = config._locale.erasParse(input, token, config._strict);
            if (era) {
                getParsingFlags(config).era = era;
            } else {
                getParsingFlags(config).invalidEra = input;
            }
        });
    
        addRegexToken('y', matchUnsigned);
        addRegexToken('yy', matchUnsigned);
        addRegexToken('yyy', matchUnsigned);
        addRegexToken('yyyy', matchUnsigned);
        addRegexToken('yo', matchEraYearOrdinal);
    
        addParseToken(['y', 'yy', 'yyy', 'yyyy'], YEAR);
        addParseToken(['yo'], function (input, array, config, token) {
            var match;
            if (config._locale._eraYearOrdinalRegex) {
                match = input.match(config._locale._eraYearOrdinalRegex);
            }
    
            if (config._locale.eraYearOrdinalParse) {
                array[YEAR] = config._locale.eraYearOrdinalParse(input, match);
            } else {
                array[YEAR] = parseInt(input, 10);
            }
        });
    
        function localeEras(m, format) {
            var i,
                l,
                date,
                eras = this._eras || getLocale('en')._eras;
            for (i = 0, l = eras.length; i < l; ++i) {
                switch (typeof eras[i].since) {
                    case 'string':
                        // truncate time
                        date = hooks(eras[i].since).startOf('day');
                        eras[i].since = date.valueOf();
                        break;
                }
    
                switch (typeof eras[i].until) {
                    case 'undefined':
                        eras[i].until = +Infinity;
                        break;
                    case 'string':
                        // truncate time
                        date = hooks(eras[i].until).startOf('day').valueOf();
                        eras[i].until = date.valueOf();
                        break;
                }
            }
            return eras;
        }
    
        function localeErasParse(eraName, format, strict) {
            var i,
                l,
                eras = this.eras(),
                name,
                abbr,
                narrow;
            eraName = eraName.toUpperCase();
    
            for (i = 0, l = eras.length; i < l; ++i) {
                name = eras[i].name.toUpperCase();
                abbr = eras[i].abbr.toUpperCase();
                narrow = eras[i].narrow.toUpperCase();
    
                if (strict) {
                    switch (format) {
                        case 'N':
                        case 'NN':
                        case 'NNN':
                            if (abbr === eraName) {
                                return eras[i];
                            }
                            break;
    
                        case 'NNNN':
                            if (name === eraName) {
                                return eras[i];
                            }
                            break;
    
                        case 'NNNNN':
                            if (narrow === eraName) {
                                return eras[i];
                            }
                            break;
                    }
                } else if ([name, abbr, narrow].indexOf(eraName) >= 0) {
                    return eras[i];
                }
            }
        }
    
        function localeErasConvertYear(era, year) {
            var dir = era.since <= era.until ? +1 : -1;
            if (year === undefined) {
                return hooks(era.since).year();
            } else {
                return hooks(era.since).year() + (year - era.offset) * dir;
            }
        }
    
        function getEraName() {
            var i,
                l,
                val,
                eras = this.localeData().eras();
            for (i = 0, l = eras.length; i < l; ++i) {
                // truncate time
                val = this.clone().startOf('day').valueOf();
    
                if (eras[i].since <= val && val <= eras[i].until) {
                    return eras[i].name;
                }
                if (eras[i].until <= val && val <= eras[i].since) {
                    return eras[i].name;
                }
            }
    
            return '';
        }
    
        function getEraNarrow() {
            var i,
                l,
                val,
                eras = this.localeData().eras();
            for (i = 0, l = eras.length; i < l; ++i) {
                // truncate time
                val = this.clone().startOf('day').valueOf();
    
                if (eras[i].since <= val && val <= eras[i].until) {
                    return eras[i].narrow;
                }
                if (eras[i].until <= val && val <= eras[i].since) {
                    return eras[i].narrow;
                }
            }
    
            return '';
        }
    
        function getEraAbbr() {
            var i,
                l,
                val,
                eras = this.localeData().eras();
            for (i = 0, l = eras.length; i < l; ++i) {
                // truncate time
                val = this.clone().startOf('day').valueOf();
    
                if (eras[i].since <= val && val <= eras[i].until) {
                    return eras[i].abbr;
                }
                if (eras[i].until <= val && val <= eras[i].since) {
                    return eras[i].abbr;
                }
            }
    
            return '';
        }
    
        function getEraYear() {
            var i,
                l,
                dir,
                val,
                eras = this.localeData().eras();
            for (i = 0, l = eras.length; i < l; ++i) {
                dir = eras[i].since <= eras[i].until ? +1 : -1;
    
                // truncate time
                val = this.clone().startOf('day').valueOf();
    
                if (
                    (eras[i].since <= val && val <= eras[i].until) ||
                    (eras[i].until <= val && val <= eras[i].since)
                ) {
                    return (
                        (this.year() - hooks(eras[i].since).year()) * dir +
                        eras[i].offset
                    );
                }
            }
    
            return this.year();
        }
    
        function erasNameRegex(isStrict) {
            if (!hasOwnProp(this, '_erasNameRegex')) {
                computeErasParse.call(this);
            }
            return isStrict ? this._erasNameRegex : this._erasRegex;
        }
    
        function erasAbbrRegex(isStrict) {
            if (!hasOwnProp(this, '_erasAbbrRegex')) {
                computeErasParse.call(this);
            }
            return isStrict ? this._erasAbbrRegex : this._erasRegex;
        }
    
        function erasNarrowRegex(isStrict) {
            if (!hasOwnProp(this, '_erasNarrowRegex')) {
                computeErasParse.call(this);
            }
            return isStrict ? this._erasNarrowRegex : this._erasRegex;
        }
    
        function matchEraAbbr(isStrict, locale) {
            return locale.erasAbbrRegex(isStrict);
        }
    
        function matchEraName(isStrict, locale) {
            return locale.erasNameRegex(isStrict);
        }
    
        function matchEraNarrow(isStrict, locale) {
            return locale.erasNarrowRegex(isStrict);
        }
    
        function matchEraYearOrdinal(isStrict, locale) {
            return locale._eraYearOrdinalRegex || matchUnsigned;
        }
    
        function computeErasParse() {
            var abbrPieces = [],
                namePieces = [],
                narrowPieces = [],
                mixedPieces = [],
                i,
                l,
                eras = this.eras();
    
            for (i = 0, l = eras.length; i < l; ++i) {
                namePieces.push(regexEscape(eras[i].name));
                abbrPieces.push(regexEscape(eras[i].abbr));
                narrowPieces.push(regexEscape(eras[i].narrow));
    
                mixedPieces.push(regexEscape(eras[i].name));
                mixedPieces.push(regexEscape(eras[i].abbr));
                mixedPieces.push(regexEscape(eras[i].narrow));
            }
    
            this._erasRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
            this._erasNameRegex = new RegExp('^(' + namePieces.join('|') + ')', 'i');
            this._erasAbbrRegex = new RegExp('^(' + abbrPieces.join('|') + ')', 'i');
            this._erasNarrowRegex = new RegExp(
                '^(' + narrowPieces.join('|') + ')',
                'i'
            );
        }
    
        // FORMATTING
    
        addFormatToken(0, ['gg', 2], 0, function () {
            return this.weekYear() % 100;
        });
    
        addFormatToken(0, ['GG', 2], 0, function () {
            return this.isoWeekYear() % 100;
        });
    
        function addWeekYearFormatToken(token, getter) {
            addFormatToken(0, [token, token.length], 0, getter);
        }
    
        addWeekYearFormatToken('gggg', 'weekYear');
        addWeekYearFormatToken('ggggg', 'weekYear');
        addWeekYearFormatToken('GGGG', 'isoWeekYear');
        addWeekYearFormatToken('GGGGG', 'isoWeekYear');
    
        // ALIASES
    
        addUnitAlias('weekYear', 'gg');
        addUnitAlias('isoWeekYear', 'GG');
    
        // PRIORITY
    
        addUnitPriority('weekYear', 1);
        addUnitPriority('isoWeekYear', 1);
    
        // PARSING
    
        addRegexToken('G', matchSigned);
        addRegexToken('g', matchSigned);
        addRegexToken('GG', match1to2, match2);
        addRegexToken('gg', match1to2, match2);
        addRegexToken('GGGG', match1to4, match4);
        addRegexToken('gggg', match1to4, match4);
        addRegexToken('GGGGG', match1to6, match6);
        addRegexToken('ggggg', match1to6, match6);
    
        addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (
            input,
            week,
            config,
            token
        ) {
            week[token.substr(0, 2)] = toInt(input);
        });
    
        addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
            week[token] = hooks.parseTwoDigitYear(input);
        });
    
        // MOMENTS
    
        function getSetWeekYear(input) {
            return getSetWeekYearHelper.call(
                this,
                input,
                this.week(),
                this.weekday(),
                this.localeData()._week.dow,
                this.localeData()._week.doy
            );
        }
    
        function getSetISOWeekYear(input) {
            return getSetWeekYearHelper.call(
                this,
                input,
                this.isoWeek(),
                this.isoWeekday(),
                1,
                4
            );
        }
    
        function getISOWeeksInYear() {
            return weeksInYear(this.year(), 1, 4);
        }
    
        function getISOWeeksInISOWeekYear() {
            return weeksInYear(this.isoWeekYear(), 1, 4);
        }
    
        function getWeeksInYear() {
            var weekInfo = this.localeData()._week;
            return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
        }
    
        function getWeeksInWeekYear() {
            var weekInfo = this.localeData()._week;
            return weeksInYear(this.weekYear(), weekInfo.dow, weekInfo.doy);
        }
    
        function getSetWeekYearHelper(input, week, weekday, dow, doy) {
            var weeksTarget;
            if (input == null) {
                return weekOfYear(this, dow, doy).year;
            } else {
                weeksTarget = weeksInYear(input, dow, doy);
                if (week > weeksTarget) {
                    week = weeksTarget;
                }
                return setWeekAll.call(this, input, week, weekday, dow, doy);
            }
        }
    
        function setWeekAll(weekYear, week, weekday, dow, doy) {
            var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
                date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
    
            this.year(date.getUTCFullYear());
            this.month(date.getUTCMonth());
            this.date(date.getUTCDate());
            return this;
        }
    
        // FORMATTING
    
        addFormatToken('Q', 0, 'Qo', 'quarter');
    
        // ALIASES
    
        addUnitAlias('quarter', 'Q');
    
        // PRIORITY
    
        addUnitPriority('quarter', 7);
    
        // PARSING
    
        addRegexToken('Q', match1);
        addParseToken('Q', function (input, array) {
            array[MONTH] = (toInt(input) - 1) * 3;
        });
    
        // MOMENTS
    
        function getSetQuarter(input) {
            return input == null
                ? Math.ceil((this.month() + 1) / 3)
                : this.month((input - 1) * 3 + (this.month() % 3));
        }
    
        // FORMATTING
    
        addFormatToken('D', ['DD', 2], 'Do', 'date');
    
        // ALIASES
    
        addUnitAlias('date', 'D');
    
        // PRIORITY
        addUnitPriority('date', 9);
    
        // PARSING
    
        addRegexToken('D', match1to2);
        addRegexToken('DD', match1to2, match2);
        addRegexToken('Do', function (isStrict, locale) {
            // TODO: Remove "ordinalParse" fallback in next major release.
            return isStrict
                ? locale._dayOfMonthOrdinalParse || locale._ordinalParse
                : locale._dayOfMonthOrdinalParseLenient;
        });
    
        addParseToken(['D', 'DD'], DATE);
        addParseToken('Do', function (input, array) {
            array[DATE] = toInt(input.match(match1to2)[0]);
        });
    
        // MOMENTS
    
        var getSetDayOfMonth = makeGetSet('Date', true);
    
        // FORMATTING
    
        addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
    
        // ALIASES
    
        addUnitAlias('dayOfYear', 'DDD');
    
        // PRIORITY
        addUnitPriority('dayOfYear', 4);
    
        // PARSING
    
        addRegexToken('DDD', match1to3);
        addRegexToken('DDDD', match3);
        addParseToken(['DDD', 'DDDD'], function (input, array, config) {
            config._dayOfYear = toInt(input);
        });
    
        // HELPERS
    
        // MOMENTS
    
        function getSetDayOfYear(input) {
            var dayOfYear =
                Math.round(
                    (this.clone().startOf('day') - this.clone().startOf('year')) / 864e5
                ) + 1;
            return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');
        }
    
        // FORMATTING
    
        addFormatToken('m', ['mm', 2], 0, 'minute');
    
        // ALIASES
    
        addUnitAlias('minute', 'm');
    
        // PRIORITY
    
        addUnitPriority('minute', 14);
    
        // PARSING
    
        addRegexToken('m', match1to2);
        addRegexToken('mm', match1to2, match2);
        addParseToken(['m', 'mm'], MINUTE);
    
        // MOMENTS
    
        var getSetMinute = makeGetSet('Minutes', false);
    
        // FORMATTING
    
        addFormatToken('s', ['ss', 2], 0, 'second');
    
        // ALIASES
    
        addUnitAlias('second', 's');
    
        // PRIORITY
    
        addUnitPriority('second', 15);
    
        // PARSING
    
        addRegexToken('s', match1to2);
        addRegexToken('ss', match1to2, match2);
        addParseToken(['s', 'ss'], SECOND);
    
        // MOMENTS
    
        var getSetSecond = makeGetSet('Seconds', false);
    
        // FORMATTING
    
        addFormatToken('S', 0, 0, function () {
            return ~~(this.millisecond() / 100);
        });
    
        addFormatToken(0, ['SS', 2], 0, function () {
            return ~~(this.millisecond() / 10);
        });
    
        addFormatToken(0, ['SSS', 3], 0, 'millisecond');
        addFormatToken(0, ['SSSS', 4], 0, function () {
            return this.millisecond() * 10;
        });
        addFormatToken(0, ['SSSSS', 5], 0, function () {
            return this.millisecond() * 100;
        });
        addFormatToken(0, ['SSSSSS', 6], 0, function () {
            return this.millisecond() * 1000;
        });
        addFormatToken(0, ['SSSSSSS', 7], 0, function () {
            return this.millisecond() * 10000;
        });
        addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
            return this.millisecond() * 100000;
        });
        addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
            return this.millisecond() * 1000000;
        });
    
        // ALIASES
    
        addUnitAlias('millisecond', 'ms');
    
        // PRIORITY
    
        addUnitPriority('millisecond', 16);
    
        // PARSING
    
        addRegexToken('S', match1to3, match1);
        addRegexToken('SS', match1to3, match2);
        addRegexToken('SSS', match1to3, match3);
    
        var token, getSetMillisecond;
        for (token = 'SSSS'; token.length <= 9; token += 'S') {
            addRegexToken(token, matchUnsigned);
        }
    
        function parseMs(input, array) {
            array[MILLISECOND] = toInt(('0.' + input) * 1000);
        }
    
        for (token = 'S'; token.length <= 9; token += 'S') {
            addParseToken(token, parseMs);
        }
    
        getSetMillisecond = makeGetSet('Milliseconds', false);
    
        // FORMATTING
    
        addFormatToken('z', 0, 0, 'zoneAbbr');
        addFormatToken('zz', 0, 0, 'zoneName');
    
        // MOMENTS
    
        function getZoneAbbr() {
            return this._isUTC ? 'UTC' : '';
        }
    
        function getZoneName() {
            return this._isUTC ? 'Coordinated Universal Time' : '';
        }
    
        var proto = Moment.prototype;
    
        proto.add = add;
        proto.calendar = calendar$1;
        proto.clone = clone;
        proto.diff = diff;
        proto.endOf = endOf;
        proto.format = format;
        proto.from = from;
        proto.fromNow = fromNow;
        proto.to = to;
        proto.toNow = toNow;
        proto.get = stringGet;
        proto.invalidAt = invalidAt;
        proto.isAfter = isAfter;
        proto.isBefore = isBefore;
        proto.isBetween = isBetween;
        proto.isSame = isSame;
        proto.isSameOrAfter = isSameOrAfter;
        proto.isSameOrBefore = isSameOrBefore;
        proto.isValid = isValid$2;
        proto.lang = lang;
        proto.locale = locale;
        proto.localeData = localeData;
        proto.max = prototypeMax;
        proto.min = prototypeMin;
        proto.parsingFlags = parsingFlags;
        proto.set = stringSet;
        proto.startOf = startOf;
        proto.subtract = subtract;
        proto.toArray = toArray;
        proto.toObject = toObject;
        proto.toDate = toDate;
        proto.toISOString = toISOString;
        proto.inspect = inspect;
        if (typeof Symbol !== 'undefined' && Symbol.for != null) {
            proto[Symbol.for('nodejs.util.inspect.custom')] = function () {
                return 'Moment<' + this.format() + '>';
            };
        }
        proto.toJSON = toJSON;
        proto.toString = toString;
        proto.unix = unix;
        proto.valueOf = valueOf;
        proto.creationData = creationData;
        proto.eraName = getEraName;
        proto.eraNarrow = getEraNarrow;
        proto.eraAbbr = getEraAbbr;
        proto.eraYear = getEraYear;
        proto.year = getSetYear;
        proto.isLeapYear = getIsLeapYear;
        proto.weekYear = getSetWeekYear;
        proto.isoWeekYear = getSetISOWeekYear;
        proto.quarter = proto.quarters = getSetQuarter;
        proto.month = getSetMonth;
        proto.daysInMonth = getDaysInMonth;
        proto.week = proto.weeks = getSetWeek;
        proto.isoWeek = proto.isoWeeks = getSetISOWeek;
        proto.weeksInYear = getWeeksInYear;
        proto.weeksInWeekYear = getWeeksInWeekYear;
        proto.isoWeeksInYear = getISOWeeksInYear;
        proto.isoWeeksInISOWeekYear = getISOWeeksInISOWeekYear;
        proto.date = getSetDayOfMonth;
        proto.day = proto.days = getSetDayOfWeek;
        proto.weekday = getSetLocaleDayOfWeek;
        proto.isoWeekday = getSetISODayOfWeek;
        proto.dayOfYear = getSetDayOfYear;
        proto.hour = proto.hours = getSetHour;
        proto.minute = proto.minutes = getSetMinute;
        proto.second = proto.seconds = getSetSecond;
        proto.millisecond = proto.milliseconds = getSetMillisecond;
        proto.utcOffset = getSetOffset;
        proto.utc = setOffsetToUTC;
        proto.local = setOffsetToLocal;
        proto.parseZone = setOffsetToParsedOffset;
        proto.hasAlignedHourOffset = hasAlignedHourOffset;
        proto.isDST = isDaylightSavingTime;
        proto.isLocal = isLocal;
        proto.isUtcOffset = isUtcOffset;
        proto.isUtc = isUtc;
        proto.isUTC = isUtc;
        proto.zoneAbbr = getZoneAbbr;
        proto.zoneName = getZoneName;
        proto.dates = deprecate(
            'dates accessor is deprecated. Use date instead.',
            getSetDayOfMonth
        );
        proto.months = deprecate(
            'months accessor is deprecated. Use month instead',
            getSetMonth
        );
        proto.years = deprecate(
            'years accessor is deprecated. Use year instead',
            getSetYear
        );
        proto.zone = deprecate(
            'moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/',
            getSetZone
        );
        proto.isDSTShifted = deprecate(
            'isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information',
            isDaylightSavingTimeShifted
        );
    
        function createUnix(input) {
            return createLocal(input * 1000);
        }
    
        function createInZone() {
            return createLocal.apply(null, arguments).parseZone();
        }
    
        function preParsePostFormat(string) {
            return string;
        }
    
        var proto$1 = Locale.prototype;
    
        proto$1.calendar = calendar;
        proto$1.longDateFormat = longDateFormat;
        proto$1.invalidDate = invalidDate;
        proto$1.ordinal = ordinal;
        proto$1.preparse = preParsePostFormat;
        proto$1.postformat = preParsePostFormat;
        proto$1.relativeTime = relativeTime;
        proto$1.pastFuture = pastFuture;
        proto$1.set = set;
        proto$1.eras = localeEras;
        proto$1.erasParse = localeErasParse;
        proto$1.erasConvertYear = localeErasConvertYear;
        proto$1.erasAbbrRegex = erasAbbrRegex;
        proto$1.erasNameRegex = erasNameRegex;
        proto$1.erasNarrowRegex = erasNarrowRegex;
    
        proto$1.months = localeMonths;
        proto$1.monthsShort = localeMonthsShort;
        proto$1.monthsParse = localeMonthsParse;
        proto$1.monthsRegex = monthsRegex;
        proto$1.monthsShortRegex = monthsShortRegex;
        proto$1.week = localeWeek;
        proto$1.firstDayOfYear = localeFirstDayOfYear;
        proto$1.firstDayOfWeek = localeFirstDayOfWeek;
    
        proto$1.weekdays = localeWeekdays;
        proto$1.weekdaysMin = localeWeekdaysMin;
        proto$1.weekdaysShort = localeWeekdaysShort;
        proto$1.weekdaysParse = localeWeekdaysParse;
    
        proto$1.weekdaysRegex = weekdaysRegex;
        proto$1.weekdaysShortRegex = weekdaysShortRegex;
        proto$1.weekdaysMinRegex = weekdaysMinRegex;
    
        proto$1.isPM = localeIsPM;
        proto$1.meridiem = localeMeridiem;
    
        function get$1(format, index, field, setter) {
            var locale = getLocale(),
                utc = createUTC().set(setter, index);
            return locale[field](utc, format);
        }
    
        function listMonthsImpl(format, index, field) {
            if (isNumber(format)) {
                index = format;
                format = undefined;
            }
    
            format = format || '';
    
            if (index != null) {
                return get$1(format, index, field, 'month');
            }
    
            var i,
                out = [];
            for (i = 0; i < 12; i++) {
                out[i] = get$1(format, i, field, 'month');
            }
            return out;
        }
    
        // ()
        // (5)
        // (fmt, 5)
        // (fmt)
        // (true)
        // (true, 5)
        // (true, fmt, 5)
        // (true, fmt)
        function listWeekdaysImpl(localeSorted, format, index, field) {
            if (typeof localeSorted === 'boolean') {
                if (isNumber(format)) {
                    index = format;
                    format = undefined;
                }
    
                format = format || '';
            } else {
                format = localeSorted;
                index = format;
                localeSorted = false;
    
                if (isNumber(format)) {
                    index = format;
                    format = undefined;
                }
    
                format = format || '';
            }
    
            var locale = getLocale(),
                shift = localeSorted ? locale._week.dow : 0,
                i,
                out = [];
    
            if (index != null) {
                return get$1(format, (index + shift) % 7, field, 'day');
            }
    
            for (i = 0; i < 7; i++) {
                out[i] = get$1(format, (i + shift) % 7, field, 'day');
            }
            return out;
        }
    
        function listMonths(format, index) {
            return listMonthsImpl(format, index, 'months');
        }
    
        function listMonthsShort(format, index) {
            return listMonthsImpl(format, index, 'monthsShort');
        }
    
        function listWeekdays(localeSorted, format, index) {
            return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
        }
    
        function listWeekdaysShort(localeSorted, format, index) {
            return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
        }
    
        function listWeekdaysMin(localeSorted, format, index) {
            return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
        }
    
        getSetGlobalLocale('en', {
            eras: [
                {
                    since: '0001-01-01',
                    until: +Infinity,
                    offset: 1,
                    name: 'Anno Domini',
                    narrow: 'AD',
                    abbr: 'AD',
                },
                {
                    since: '0000-12-31',
                    until: -Infinity,
                    offset: 1,
                    name: 'Before Christ',
                    narrow: 'BC',
                    abbr: 'BC',
                },
            ],
            dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        toInt((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
        });
    
        // Side effect imports
    
        hooks.lang = deprecate(
            'moment.lang is deprecated. Use moment.locale instead.',
            getSetGlobalLocale
        );
        hooks.langData = deprecate(
            'moment.langData is deprecated. Use moment.localeData instead.',
            getLocale
        );
    
        var mathAbs = Math.abs;
    
        function abs() {
            var data = this._data;
    
            this._milliseconds = mathAbs(this._milliseconds);
            this._days = mathAbs(this._days);
            this._months = mathAbs(this._months);
    
            data.milliseconds = mathAbs(data.milliseconds);
            data.seconds = mathAbs(data.seconds);
            data.minutes = mathAbs(data.minutes);
            data.hours = mathAbs(data.hours);
            data.months = mathAbs(data.months);
            data.years = mathAbs(data.years);
    
            return this;
        }
    
        function addSubtract$1(duration, input, value, direction) {
            var other = createDuration(input, value);
    
            duration._milliseconds += direction * other._milliseconds;
            duration._days += direction * other._days;
            duration._months += direction * other._months;
    
            return duration._bubble();
        }
    
        // supports only 2.0-style add(1, 's') or add(duration)
        function add$1(input, value) {
            return addSubtract$1(this, input, value, 1);
        }
    
        // supports only 2.0-style subtract(1, 's') or subtract(duration)
        function subtract$1(input, value) {
            return addSubtract$1(this, input, value, -1);
        }
    
        function absCeil(number) {
            if (number < 0) {
                return Math.floor(number);
            } else {
                return Math.ceil(number);
            }
        }
    
        function bubble() {
            var milliseconds = this._milliseconds,
                days = this._days,
                months = this._months,
                data = this._data,
                seconds,
                minutes,
                hours,
                years,
                monthsFromDays;
    
            // if we have a mix of positive and negative values, bubble down first
            // check: https://github.com/moment/moment/issues/2166
            if (
                !(
                    (milliseconds >= 0 && days >= 0 && months >= 0) ||
                    (milliseconds <= 0 && days <= 0 && months <= 0)
                )
            ) {
                milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
                days = 0;
                months = 0;
            }
    
            // The following code bubbles up values, see the tests for
            // examples of what that means.
            data.milliseconds = milliseconds % 1000;
    
            seconds = absFloor(milliseconds / 1000);
            data.seconds = seconds % 60;
    
            minutes = absFloor(seconds / 60);
            data.minutes = minutes % 60;
    
            hours = absFloor(minutes / 60);
            data.hours = hours % 24;
    
            days += absFloor(hours / 24);
    
            // convert days to months
            monthsFromDays = absFloor(daysToMonths(days));
            months += monthsFromDays;
            days -= absCeil(monthsToDays(monthsFromDays));
    
            // 12 months -> 1 year
            years = absFloor(months / 12);
            months %= 12;
    
            data.days = days;
            data.months = months;
            data.years = years;
    
            return this;
        }
    
        function daysToMonths(days) {
            // 400 years have 146097 days (taking into account leap year rules)
            // 400 years have 12 months === 4800
            return (days * 4800) / 146097;
        }
    
        function monthsToDays(months) {
            // the reverse of daysToMonths
            return (months * 146097) / 4800;
        }
    
        function as(units) {
            if (!this.isValid()) {
                return NaN;
            }
            var days,
                months,
                milliseconds = this._milliseconds;
    
            units = normalizeUnits(units);
    
            if (units === 'month' || units === 'quarter' || units === 'year') {
                days = this._days + milliseconds / 864e5;
                months = this._months + daysToMonths(days);
                switch (units) {
                    case 'month':
                        return months;
                    case 'quarter':
                        return months / 3;
                    case 'year':
                        return months / 12;
                }
            } else {
                // handle milliseconds separately because of floating point math errors (issue #1867)
                days = this._days + Math.round(monthsToDays(this._months));
                switch (units) {
                    case 'week':
                        return days / 7 + milliseconds / 6048e5;
                    case 'day':
                        return days + milliseconds / 864e5;
                    case 'hour':
                        return days * 24 + milliseconds / 36e5;
                    case 'minute':
                        return days * 1440 + milliseconds / 6e4;
                    case 'second':
                        return days * 86400 + milliseconds / 1000;
                    // Math.floor prevents floating point math errors here
                    case 'millisecond':
                        return Math.floor(days * 864e5) + milliseconds;
                    default:
                        throw new Error('Unknown unit ' + units);
                }
            }
        }
    
        // TODO: Use this.as('ms')?
        function valueOf$1() {
            if (!this.isValid()) {
                return NaN;
            }
            return (
                this._milliseconds +
                this._days * 864e5 +
                (this._months % 12) * 2592e6 +
                toInt(this._months / 12) * 31536e6
            );
        }
    
        function makeAs(alias) {
            return function () {
                return this.as(alias);
            };
        }
    
        var asMilliseconds = makeAs('ms'),
            asSeconds = makeAs('s'),
            asMinutes = makeAs('m'),
            asHours = makeAs('h'),
            asDays = makeAs('d'),
            asWeeks = makeAs('w'),
            asMonths = makeAs('M'),
            asQuarters = makeAs('Q'),
            asYears = makeAs('y');
    
        function clone$1() {
            return createDuration(this);
        }
    
        function get$2(units) {
            units = normalizeUnits(units);
            return this.isValid() ? this[units + 's']() : NaN;
        }
    
        function makeGetter(name) {
            return function () {
                return this.isValid() ? this._data[name] : NaN;
            };
        }
    
        var milliseconds = makeGetter('milliseconds'),
            seconds = makeGetter('seconds'),
            minutes = makeGetter('minutes'),
            hours = makeGetter('hours'),
            days = makeGetter('days'),
            months = makeGetter('months'),
            years = makeGetter('years');
    
        function weeks() {
            return absFloor(this.days() / 7);
        }
    
        var round = Math.round,
            thresholds = {
                ss: 44, // a few seconds to seconds
                s: 45, // seconds to minute
                m: 45, // minutes to hour
                h: 22, // hours to day
                d: 26, // days to month/week
                w: null, // weeks to month
                M: 11, // months to year
            };
    
        // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
        function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
            return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
        }
    
        function relativeTime$1(posNegDuration, withoutSuffix, thresholds, locale) {
            var duration = createDuration(posNegDuration).abs(),
                seconds = round(duration.as('s')),
                minutes = round(duration.as('m')),
                hours = round(duration.as('h')),
                days = round(duration.as('d')),
                months = round(duration.as('M')),
                weeks = round(duration.as('w')),
                years = round(duration.as('y')),
                a =
                    (seconds <= thresholds.ss && ['s', seconds]) ||
                    (seconds < thresholds.s && ['ss', seconds]) ||
                    (minutes <= 1 && ['m']) ||
                    (minutes < thresholds.m && ['mm', minutes]) ||
                    (hours <= 1 && ['h']) ||
                    (hours < thresholds.h && ['hh', hours]) ||
                    (days <= 1 && ['d']) ||
                    (days < thresholds.d && ['dd', days]);
    
            if (thresholds.w != null) {
                a =
                    a ||
                    (weeks <= 1 && ['w']) ||
                    (weeks < thresholds.w && ['ww', weeks]);
            }
            a = a ||
                (months <= 1 && ['M']) ||
                (months < thresholds.M && ['MM', months]) ||
                (years <= 1 && ['y']) || ['yy', years];
    
            a[2] = withoutSuffix;
            a[3] = +posNegDuration > 0;
            a[4] = locale;
            return substituteTimeAgo.apply(null, a);
        }
    
        // This function allows you to set the rounding function for relative time strings
        function getSetRelativeTimeRounding(roundingFunction) {
            if (roundingFunction === undefined) {
                return round;
            }
            if (typeof roundingFunction === 'function') {
                round = roundingFunction;
                return true;
            }
            return false;
        }
    
        // This function allows you to set a threshold for relative time strings
        function getSetRelativeTimeThreshold(threshold, limit) {
            if (thresholds[threshold] === undefined) {
                return false;
            }
            if (limit === undefined) {
                return thresholds[threshold];
            }
            thresholds[threshold] = limit;
            if (threshold === 's') {
                thresholds.ss = limit - 1;
            }
            return true;
        }
    
        function humanize(argWithSuffix, argThresholds) {
            if (!this.isValid()) {
                return this.localeData().invalidDate();
            }
    
            var withSuffix = false,
                th = thresholds,
                locale,
                output;
    
            if (typeof argWithSuffix === 'object') {
                argThresholds = argWithSuffix;
                argWithSuffix = false;
            }
            if (typeof argWithSuffix === 'boolean') {
                withSuffix = argWithSuffix;
            }
            if (typeof argThresholds === 'object') {
                th = Object.assign({}, thresholds, argThresholds);
                if (argThresholds.s != null && argThresholds.ss == null) {
                    th.ss = argThresholds.s - 1;
                }
            }
    
            locale = this.localeData();
            output = relativeTime$1(this, !withSuffix, th, locale);
    
            if (withSuffix) {
                output = locale.pastFuture(+this, output);
            }
    
            return locale.postformat(output);
        }
    
        var abs$1 = Math.abs;
    
        function sign(x) {
            return (x > 0) - (x < 0) || +x;
        }
    
        function toISOString$1() {
            // for ISO strings we do not use the normal bubbling rules:
            //  * milliseconds bubble up until they become hours
            //  * days do not bubble at all
            //  * months bubble up until they become years
            // This is because there is no context-free conversion between hours and days
            // (think of clock changes)
            // and also not between days and months (28-31 days per month)
            if (!this.isValid()) {
                return this.localeData().invalidDate();
            }
    
            var seconds = abs$1(this._milliseconds) / 1000,
                days = abs$1(this._days),
                months = abs$1(this._months),
                minutes,
                hours,
                years,
                s,
                total = this.asSeconds(),
                totalSign,
                ymSign,
                daysSign,
                hmsSign;
    
            if (!total) {
                // this is the same as C#'s (Noda) and python (isodate)...
                // but not other JS (goog.date)
                return 'P0D';
            }
    
            // 3600 seconds -> 60 minutes -> 1 hour
            minutes = absFloor(seconds / 60);
            hours = absFloor(minutes / 60);
            seconds %= 60;
            minutes %= 60;
    
            // 12 months -> 1 year
            years = absFloor(months / 12);
            months %= 12;
    
            // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
            s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
    
            totalSign = total < 0 ? '-' : '';
            ymSign = sign(this._months) !== sign(total) ? '-' : '';
            daysSign = sign(this._days) !== sign(total) ? '-' : '';
            hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
    
            return (
                totalSign +
                'P' +
                (years ? ymSign + years + 'Y' : '') +
                (months ? ymSign + months + 'M' : '') +
                (days ? daysSign + days + 'D' : '') +
                (hours || minutes || seconds ? 'T' : '') +
                (hours ? hmsSign + hours + 'H' : '') +
                (minutes ? hmsSign + minutes + 'M' : '') +
                (seconds ? hmsSign + s + 'S' : '')
            );
        }
    
        var proto$2 = Duration.prototype;
    
        proto$2.isValid = isValid$1;
        proto$2.abs = abs;
        proto$2.add = add$1;
        proto$2.subtract = subtract$1;
        proto$2.as = as;
        proto$2.asMilliseconds = asMilliseconds;
        proto$2.asSeconds = asSeconds;
        proto$2.asMinutes = asMinutes;
        proto$2.asHours = asHours;
        proto$2.asDays = asDays;
        proto$2.asWeeks = asWeeks;
        proto$2.asMonths = asMonths;
        proto$2.asQuarters = asQuarters;
        proto$2.asYears = asYears;
        proto$2.valueOf = valueOf$1;
        proto$2._bubble = bubble;
        proto$2.clone = clone$1;
        proto$2.get = get$2;
        proto$2.milliseconds = milliseconds;
        proto$2.seconds = seconds;
        proto$2.minutes = minutes;
        proto$2.hours = hours;
        proto$2.days = days;
        proto$2.weeks = weeks;
        proto$2.months = months;
        proto$2.years = years;
        proto$2.humanize = humanize;
        proto$2.toISOString = toISOString$1;
        proto$2.toString = toISOString$1;
        proto$2.toJSON = toISOString$1;
        proto$2.locale = locale;
        proto$2.localeData = localeData;
    
        proto$2.toIsoString = deprecate(
            'toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)',
            toISOString$1
        );
        proto$2.lang = lang;
    
        // FORMATTING
    
        addFormatToken('X', 0, 0, 'unix');
        addFormatToken('x', 0, 0, 'valueOf');
    
        // PARSING
    
        addRegexToken('x', matchSigned);
        addRegexToken('X', matchTimestamp);
        addParseToken('X', function (input, array, config) {
            config._d = new Date(parseFloat(input) * 1000);
        });
        addParseToken('x', function (input, array, config) {
            config._d = new Date(toInt(input));
        });
    
        //! moment.js
    
        hooks.version = '2.29.1';
    
        setHookCallback(createLocal);
    
        hooks.fn = proto;
        hooks.min = min;
        hooks.max = max;
        hooks.now = now;
        hooks.utc = createUTC;
        hooks.unix = createUnix;
        hooks.months = listMonths;
        hooks.isDate = isDate;
        hooks.locale = getSetGlobalLocale;
        hooks.invalid = createInvalid;
        hooks.duration = createDuration;
        hooks.isMoment = isMoment;
        hooks.weekdays = listWeekdays;
        hooks.parseZone = createInZone;
        hooks.localeData = getLocale;
        hooks.isDuration = isDuration;
        hooks.monthsShort = listMonthsShort;
        hooks.weekdaysMin = listWeekdaysMin;
        hooks.defineLocale = defineLocale;
        hooks.updateLocale = updateLocale;
        hooks.locales = listLocales;
        hooks.weekdaysShort = listWeekdaysShort;
        hooks.normalizeUnits = normalizeUnits;
        hooks.relativeTimeRounding = getSetRelativeTimeRounding;
        hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
        hooks.calendarFormat = getCalendarFormat;
        hooks.prototype = proto;
    
        // currently HTML5 input type only supports 24-hour formats
        hooks.HTML5_FMT = {
            DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" />
            DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" />
            DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" />
            DATE: 'YYYY-MM-DD', // <input type="date" />
            TIME: 'HH:mm', // <input type="time" />
            TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" />
            TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" />
            WEEK: 'GGGG-[W]WW', // <input type="week" />
            MONTH: 'YYYY-MM', // <input type="month" />
        };
    
        //! moment.js locale configuration
    
        hooks.defineLocale('af', {
            months: 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
            weekdays: 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split(
                '_'
            ),
            weekdaysShort: 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
            weekdaysMin: 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
            meridiemParse: /vm|nm/i,
            isPM: function (input) {
                return /^nm$/i.test(input);
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours < 12) {
                    return isLower ? 'vm' : 'VM';
                } else {
                    return isLower ? 'nm' : 'NM';
                }
            },
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Vandag om] LT',
                nextDay: '[Môre om] LT',
                nextWeek: 'dddd [om] LT',
                lastDay: '[Gister om] LT',
                lastWeek: '[Laas] dddd [om] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'oor %s',
                past: '%s gelede',
                s: "'n paar sekondes",
                ss: '%d sekondes',
                m: "'n minuut",
                mm: '%d minute',
                h: "'n uur",
                hh: '%d ure',
                d: "'n dag",
                dd: '%d dae',
                M: "'n maand",
                MM: '%d maande',
                y: "'n jaar",
                yy: '%d jaar',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
            ordinal: function (number) {
                return (
                    number +
                    (number === 1 || number === 8 || number >= 20 ? 'ste' : 'de')
                ); // Thanks to Joris Röling : https://github.com/jjupiter
            },
            week: {
                dow: 1, // Maandag is die eerste dag van die week.
                doy: 4, // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
            },
        });
    
        //! moment.js locale configuration
    
        var pluralForm = function (n) {
                return n === 0
                    ? 0
                    : n === 1
                    ? 1
                    : n === 2
                    ? 2
                    : n % 100 >= 3 && n % 100 <= 10
                    ? 3
                    : n % 100 >= 11
                    ? 4
                    : 5;
            },
            plurals = {
                s: [
                    'أقل من ثانية',
                    'ثانية واحدة',
                    ['ثانيتان', 'ثانيتين'],
                    '%d ثوان',
                    '%d ثانية',
                    '%d ثانية',
                ],
                m: [
                    'أقل من دقيقة',
                    'دقيقة واحدة',
                    ['دقيقتان', 'دقيقتين'],
                    '%d دقائق',
                    '%d دقيقة',
                    '%d دقيقة',
                ],
                h: [
                    'أقل من ساعة',
                    'ساعة واحدة',
                    ['ساعتان', 'ساعتين'],
                    '%d ساعات',
                    '%d ساعة',
                    '%d ساعة',
                ],
                d: [
                    'أقل من يوم',
                    'يوم واحد',
                    ['يومان', 'يومين'],
                    '%d أيام',
                    '%d يومًا',
                    '%d يوم',
                ],
                M: [
                    'أقل من شهر',
                    'شهر واحد',
                    ['شهران', 'شهرين'],
                    '%d أشهر',
                    '%d شهرا',
                    '%d شهر',
                ],
                y: [
                    'أقل من عام',
                    'عام واحد',
                    ['عامان', 'عامين'],
                    '%d أعوام',
                    '%d عامًا',
                    '%d عام',
                ],
            },
            pluralize = function (u) {
                return function (number, withoutSuffix, string, isFuture) {
                    var f = pluralForm(number),
                        str = plurals[u][pluralForm(number)];
                    if (f === 2) {
                        str = str[withoutSuffix ? 0 : 1];
                    }
                    return str.replace(/%d/i, number);
                };
            },
            months$1 = [
                'جانفي',
                'فيفري',
                'مارس',
                'أفريل',
                'ماي',
                'جوان',
                'جويلية',
                'أوت',
                'سبتمبر',
                'أكتوبر',
                'نوفمبر',
                'ديسمبر',
            ];
    
        hooks.defineLocale('ar-dz', {
            months: months$1,
            monthsShort: months$1,
            weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
            weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
            weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'D/\u200FM/\u200FYYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            meridiemParse: /ص|م/,
            isPM: function (input) {
                return 'م' === input;
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'ص';
                } else {
                    return 'م';
                }
            },
            calendar: {
                sameDay: '[اليوم عند الساعة] LT',
                nextDay: '[غدًا عند الساعة] LT',
                nextWeek: 'dddd [عند الساعة] LT',
                lastDay: '[أمس عند الساعة] LT',
                lastWeek: 'dddd [عند الساعة] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'بعد %s',
                past: 'منذ %s',
                s: pluralize('s'),
                ss: pluralize('s'),
                m: pluralize('m'),
                mm: pluralize('m'),
                h: pluralize('h'),
                hh: pluralize('h'),
                d: pluralize('d'),
                dd: pluralize('d'),
                M: pluralize('M'),
                MM: pluralize('M'),
                y: pluralize('y'),
                yy: pluralize('y'),
            },
            postformat: function (string) {
                return string.replace(/,/g, '،');
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ar-kw', {
            months: 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split(
                '_'
            ),
            monthsShort: 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split(
                '_'
            ),
            weekdays: 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
            weekdaysShort: 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
            weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[اليوم على الساعة] LT',
                nextDay: '[غدا على الساعة] LT',
                nextWeek: 'dddd [على الساعة] LT',
                lastDay: '[أمس على الساعة] LT',
                lastWeek: 'dddd [على الساعة] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'في %s',
                past: 'منذ %s',
                s: 'ثوان',
                ss: '%d ثانية',
                m: 'دقيقة',
                mm: '%d دقائق',
                h: 'ساعة',
                hh: '%d ساعات',
                d: 'يوم',
                dd: '%d أيام',
                M: 'شهر',
                MM: '%d أشهر',
                y: 'سنة',
                yy: '%d سنوات',
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 12, // The week that contains Jan 12th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap = {
                1: '1',
                2: '2',
                3: '3',
                4: '4',
                5: '5',
                6: '6',
                7: '7',
                8: '8',
                9: '9',
                0: '0',
            },
            pluralForm$1 = function (n) {
                return n === 0
                    ? 0
                    : n === 1
                    ? 1
                    : n === 2
                    ? 2
                    : n % 100 >= 3 && n % 100 <= 10
                    ? 3
                    : n % 100 >= 11
                    ? 4
                    : 5;
            },
            plurals$1 = {
                s: [
                    'أقل من ثانية',
                    'ثانية واحدة',
                    ['ثانيتان', 'ثانيتين'],
                    '%d ثوان',
                    '%d ثانية',
                    '%d ثانية',
                ],
                m: [
                    'أقل من دقيقة',
                    'دقيقة واحدة',
                    ['دقيقتان', 'دقيقتين'],
                    '%d دقائق',
                    '%d دقيقة',
                    '%d دقيقة',
                ],
                h: [
                    'أقل من ساعة',
                    'ساعة واحدة',
                    ['ساعتان', 'ساعتين'],
                    '%d ساعات',
                    '%d ساعة',
                    '%d ساعة',
                ],
                d: [
                    'أقل من يوم',
                    'يوم واحد',
                    ['يومان', 'يومين'],
                    '%d أيام',
                    '%d يومًا',
                    '%d يوم',
                ],
                M: [
                    'أقل من شهر',
                    'شهر واحد',
                    ['شهران', 'شهرين'],
                    '%d أشهر',
                    '%d شهرا',
                    '%d شهر',
                ],
                y: [
                    'أقل من عام',
                    'عام واحد',
                    ['عامان', 'عامين'],
                    '%d أعوام',
                    '%d عامًا',
                    '%d عام',
                ],
            },
            pluralize$1 = function (u) {
                return function (number, withoutSuffix, string, isFuture) {
                    var f = pluralForm$1(number),
                        str = plurals$1[u][pluralForm$1(number)];
                    if (f === 2) {
                        str = str[withoutSuffix ? 0 : 1];
                    }
                    return str.replace(/%d/i, number);
                };
            },
            months$2 = [
                'يناير',
                'فبراير',
                'مارس',
                'أبريل',
                'مايو',
                'يونيو',
                'يوليو',
                'أغسطس',
                'سبتمبر',
                'أكتوبر',
                'نوفمبر',
                'ديسمبر',
            ];
    
        hooks.defineLocale('ar-ly', {
            months: months$2,
            monthsShort: months$2,
            weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
            weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
            weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'D/\u200FM/\u200FYYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            meridiemParse: /ص|م/,
            isPM: function (input) {
                return 'م' === input;
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'ص';
                } else {
                    return 'م';
                }
            },
            calendar: {
                sameDay: '[اليوم عند الساعة] LT',
                nextDay: '[غدًا عند الساعة] LT',
                nextWeek: 'dddd [عند الساعة] LT',
                lastDay: '[أمس عند الساعة] LT',
                lastWeek: 'dddd [عند الساعة] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'بعد %s',
                past: 'منذ %s',
                s: pluralize$1('s'),
                ss: pluralize$1('s'),
                m: pluralize$1('m'),
                mm: pluralize$1('m'),
                h: pluralize$1('h'),
                hh: pluralize$1('h'),
                d: pluralize$1('d'),
                dd: pluralize$1('d'),
                M: pluralize$1('M'),
                MM: pluralize$1('M'),
                y: pluralize$1('y'),
                yy: pluralize$1('y'),
            },
            preparse: function (string) {
                return string.replace(/،/g, ',');
            },
            postformat: function (string) {
                return string
                    .replace(/\d/g, function (match) {
                        return symbolMap[match];
                    })
                    .replace(/,/g, '،');
            },
            week: {
                dow: 6, // Saturday is the first day of the week.
                doy: 12, // The week that contains Jan 12th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ar-ma', {
            months: 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split(
                '_'
            ),
            monthsShort: 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split(
                '_'
            ),
            weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
            weekdaysShort: 'احد_اثنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
            weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[اليوم على الساعة] LT',
                nextDay: '[غدا على الساعة] LT',
                nextWeek: 'dddd [على الساعة] LT',
                lastDay: '[أمس على الساعة] LT',
                lastWeek: 'dddd [على الساعة] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'في %s',
                past: 'منذ %s',
                s: 'ثوان',
                ss: '%d ثانية',
                m: 'دقيقة',
                mm: '%d دقائق',
                h: 'ساعة',
                hh: '%d ساعات',
                d: 'يوم',
                dd: '%d أيام',
                M: 'شهر',
                MM: '%d أشهر',
                y: 'سنة',
                yy: '%d سنوات',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$1 = {
                1: '١',
                2: '٢',
                3: '٣',
                4: '٤',
                5: '٥',
                6: '٦',
                7: '٧',
                8: '٨',
                9: '٩',
                0: '٠',
            },
            numberMap = {
                '١': '1',
                '٢': '2',
                '٣': '3',
                '٤': '4',
                '٥': '5',
                '٦': '6',
                '٧': '7',
                '٨': '8',
                '٩': '9',
                '٠': '0',
            };
    
        hooks.defineLocale('ar-sa', {
            months: 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split(
                '_'
            ),
            monthsShort: 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split(
                '_'
            ),
            weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
            weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
            weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            meridiemParse: /ص|م/,
            isPM: function (input) {
                return 'م' === input;
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'ص';
                } else {
                    return 'م';
                }
            },
            calendar: {
                sameDay: '[اليوم على الساعة] LT',
                nextDay: '[غدا على الساعة] LT',
                nextWeek: 'dddd [على الساعة] LT',
                lastDay: '[أمس على الساعة] LT',
                lastWeek: 'dddd [على الساعة] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'في %s',
                past: 'منذ %s',
                s: 'ثوان',
                ss: '%d ثانية',
                m: 'دقيقة',
                mm: '%d دقائق',
                h: 'ساعة',
                hh: '%d ساعات',
                d: 'يوم',
                dd: '%d أيام',
                M: 'شهر',
                MM: '%d أشهر',
                y: 'سنة',
                yy: '%d سنوات',
            },
            preparse: function (string) {
                return string
                    .replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
                        return numberMap[match];
                    })
                    .replace(/،/g, ',');
            },
            postformat: function (string) {
                return string
                    .replace(/\d/g, function (match) {
                        return symbolMap$1[match];
                    })
                    .replace(/,/g, '،');
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ar-tn', {
            months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split(
                '_'
            ),
            monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split(
                '_'
            ),
            weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
            weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
            weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[اليوم على الساعة] LT',
                nextDay: '[غدا على الساعة] LT',
                nextWeek: 'dddd [على الساعة] LT',
                lastDay: '[أمس على الساعة] LT',
                lastWeek: 'dddd [على الساعة] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'في %s',
                past: 'منذ %s',
                s: 'ثوان',
                ss: '%d ثانية',
                m: 'دقيقة',
                mm: '%d دقائق',
                h: 'ساعة',
                hh: '%d ساعات',
                d: 'يوم',
                dd: '%d أيام',
                M: 'شهر',
                MM: '%d أشهر',
                y: 'سنة',
                yy: '%d سنوات',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$2 = {
                1: '١',
                2: '٢',
                3: '٣',
                4: '٤',
                5: '٥',
                6: '٦',
                7: '٧',
                8: '٨',
                9: '٩',
                0: '٠',
            },
            numberMap$1 = {
                '١': '1',
                '٢': '2',
                '٣': '3',
                '٤': '4',
                '٥': '5',
                '٦': '6',
                '٧': '7',
                '٨': '8',
                '٩': '9',
                '٠': '0',
            },
            pluralForm$2 = function (n) {
                return n === 0
                    ? 0
                    : n === 1
                    ? 1
                    : n === 2
                    ? 2
                    : n % 100 >= 3 && n % 100 <= 10
                    ? 3
                    : n % 100 >= 11
                    ? 4
                    : 5;
            },
            plurals$2 = {
                s: [
                    'أقل من ثانية',
                    'ثانية واحدة',
                    ['ثانيتان', 'ثانيتين'],
                    '%d ثوان',
                    '%d ثانية',
                    '%d ثانية',
                ],
                m: [
                    'أقل من دقيقة',
                    'دقيقة واحدة',
                    ['دقيقتان', 'دقيقتين'],
                    '%d دقائق',
                    '%d دقيقة',
                    '%d دقيقة',
                ],
                h: [
                    'أقل من ساعة',
                    'ساعة واحدة',
                    ['ساعتان', 'ساعتين'],
                    '%d ساعات',
                    '%d ساعة',
                    '%d ساعة',
                ],
                d: [
                    'أقل من يوم',
                    'يوم واحد',
                    ['يومان', 'يومين'],
                    '%d أيام',
                    '%d يومًا',
                    '%d يوم',
                ],
                M: [
                    'أقل من شهر',
                    'شهر واحد',
                    ['شهران', 'شهرين'],
                    '%d أشهر',
                    '%d شهرا',
                    '%d شهر',
                ],
                y: [
                    'أقل من عام',
                    'عام واحد',
                    ['عامان', 'عامين'],
                    '%d أعوام',
                    '%d عامًا',
                    '%d عام',
                ],
            },
            pluralize$2 = function (u) {
                return function (number, withoutSuffix, string, isFuture) {
                    var f = pluralForm$2(number),
                        str = plurals$2[u][pluralForm$2(number)];
                    if (f === 2) {
                        str = str[withoutSuffix ? 0 : 1];
                    }
                    return str.replace(/%d/i, number);
                };
            },
            months$3 = [
                'يناير',
                'فبراير',
                'مارس',
                'أبريل',
                'مايو',
                'يونيو',
                'يوليو',
                'أغسطس',
                'سبتمبر',
                'أكتوبر',
                'نوفمبر',
                'ديسمبر',
            ];
    
        hooks.defineLocale('ar', {
            months: months$3,
            monthsShort: months$3,
            weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
            weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
            weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'D/\u200FM/\u200FYYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            meridiemParse: /ص|م/,
            isPM: function (input) {
                return 'م' === input;
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'ص';
                } else {
                    return 'م';
                }
            },
            calendar: {
                sameDay: '[اليوم عند الساعة] LT',
                nextDay: '[غدًا عند الساعة] LT',
                nextWeek: 'dddd [عند الساعة] LT',
                lastDay: '[أمس عند الساعة] LT',
                lastWeek: 'dddd [عند الساعة] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'بعد %s',
                past: 'منذ %s',
                s: pluralize$2('s'),
                ss: pluralize$2('s'),
                m: pluralize$2('m'),
                mm: pluralize$2('m'),
                h: pluralize$2('h'),
                hh: pluralize$2('h'),
                d: pluralize$2('d'),
                dd: pluralize$2('d'),
                M: pluralize$2('M'),
                MM: pluralize$2('M'),
                y: pluralize$2('y'),
                yy: pluralize$2('y'),
            },
            preparse: function (string) {
                return string
                    .replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
                        return numberMap$1[match];
                    })
                    .replace(/،/g, ',');
            },
            postformat: function (string) {
                return string
                    .replace(/\d/g, function (match) {
                        return symbolMap$2[match];
                    })
                    .replace(/,/g, '،');
            },
            week: {
                dow: 6, // Saturday is the first day of the week.
                doy: 12, // The week that contains Jan 12th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var suffixes = {
            1: '-inci',
            5: '-inci',
            8: '-inci',
            70: '-inci',
            80: '-inci',
            2: '-nci',
            7: '-nci',
            20: '-nci',
            50: '-nci',
            3: '-üncü',
            4: '-üncü',
            100: '-üncü',
            6: '-ncı',
            9: '-uncu',
            10: '-uncu',
            30: '-uncu',
            60: '-ıncı',
            90: '-ıncı',
        };
    
        hooks.defineLocale('az', {
            months: 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split(
                '_'
            ),
            monthsShort: 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
            weekdays: 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split(
                '_'
            ),
            weekdaysShort: 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
            weekdaysMin: 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[bugün saat] LT',
                nextDay: '[sabah saat] LT',
                nextWeek: '[gələn həftə] dddd [saat] LT',
                lastDay: '[dünən] LT',
                lastWeek: '[keçən həftə] dddd [saat] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s sonra',
                past: '%s əvvəl',
                s: 'bir neçə saniyə',
                ss: '%d saniyə',
                m: 'bir dəqiqə',
                mm: '%d dəqiqə',
                h: 'bir saat',
                hh: '%d saat',
                d: 'bir gün',
                dd: '%d gün',
                M: 'bir ay',
                MM: '%d ay',
                y: 'bir il',
                yy: '%d il',
            },
            meridiemParse: /gecə|səhər|gündüz|axşam/,
            isPM: function (input) {
                return /^(gündüz|axşam)$/.test(input);
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'gecə';
                } else if (hour < 12) {
                    return 'səhər';
                } else if (hour < 17) {
                    return 'gündüz';
                } else {
                    return 'axşam';
                }
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
            ordinal: function (number) {
                if (number === 0) {
                    // special case for zero
                    return number + '-ıncı';
                }
                var a = number % 10,
                    b = (number % 100) - a,
                    c = number >= 100 ? 100 : null;
                return number + (suffixes[a] || suffixes[b] || suffixes[c]);
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function plural(word, num) {
            var forms = word.split('_');
            return num % 10 === 1 && num % 100 !== 11
                ? forms[0]
                : num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20)
                ? forms[1]
                : forms[2];
        }
        function relativeTimeWithPlural(number, withoutSuffix, key) {
            var format = {
                ss: withoutSuffix ? 'секунда_секунды_секунд' : 'секунду_секунды_секунд',
                mm: withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
                hh: withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
                dd: 'дзень_дні_дзён',
                MM: 'месяц_месяцы_месяцаў',
                yy: 'год_гады_гадоў',
            };
            if (key === 'm') {
                return withoutSuffix ? 'хвіліна' : 'хвіліну';
            } else if (key === 'h') {
                return withoutSuffix ? 'гадзіна' : 'гадзіну';
            } else {
                return number + ' ' + plural(format[key], +number);
            }
        }
    
        hooks.defineLocale('be', {
            months: {
                format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split(
                    '_'
                ),
                standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split(
                    '_'
                ),
            },
            monthsShort: 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split(
                '_'
            ),
            weekdays: {
                format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split(
                    '_'
                ),
                standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split(
                    '_'
                ),
                isFormat: /\[ ?[Ууў] ?(?:мінулую|наступную)? ?\] ?dddd/,
            },
            weekdaysShort: 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
            weekdaysMin: 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY г.',
                LLL: 'D MMMM YYYY г., HH:mm',
                LLLL: 'dddd, D MMMM YYYY г., HH:mm',
            },
            calendar: {
                sameDay: '[Сёння ў] LT',
                nextDay: '[Заўтра ў] LT',
                lastDay: '[Учора ў] LT',
                nextWeek: function () {
                    return '[У] dddd [ў] LT';
                },
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                        case 3:
                        case 5:
                        case 6:
                            return '[У мінулую] dddd [ў] LT';
                        case 1:
                        case 2:
                        case 4:
                            return '[У мінулы] dddd [ў] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'праз %s',
                past: '%s таму',
                s: 'некалькі секунд',
                m: relativeTimeWithPlural,
                mm: relativeTimeWithPlural,
                h: relativeTimeWithPlural,
                hh: relativeTimeWithPlural,
                d: 'дзень',
                dd: relativeTimeWithPlural,
                M: 'месяц',
                MM: relativeTimeWithPlural,
                y: 'год',
                yy: relativeTimeWithPlural,
            },
            meridiemParse: /ночы|раніцы|дня|вечара/,
            isPM: function (input) {
                return /^(дня|вечара)$/.test(input);
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'ночы';
                } else if (hour < 12) {
                    return 'раніцы';
                } else if (hour < 17) {
                    return 'дня';
                } else {
                    return 'вечара';
                }
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(і|ы|га)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'M':
                    case 'd':
                    case 'DDD':
                    case 'w':
                    case 'W':
                        return (number % 10 === 2 || number % 10 === 3) &&
                            number % 100 !== 12 &&
                            number % 100 !== 13
                            ? number + '-і'
                            : number + '-ы';
                    case 'D':
                        return number + '-га';
                    default:
                        return number;
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('bg', {
            months: 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split(
                '_'
            ),
            monthsShort: 'яну_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
            weekdays: 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split(
                '_'
            ),
            weekdaysShort: 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
            weekdaysMin: 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'D.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY H:mm',
                LLLL: 'dddd, D MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[Днес в] LT',
                nextDay: '[Утре в] LT',
                nextWeek: 'dddd [в] LT',
                lastDay: '[Вчера в] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                        case 3:
                        case 6:
                            return '[Миналата] dddd [в] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[Миналия] dddd [в] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'след %s',
                past: 'преди %s',
                s: 'няколко секунди',
                ss: '%d секунди',
                m: 'минута',
                mm: '%d минути',
                h: 'час',
                hh: '%d часа',
                d: 'ден',
                dd: '%d дена',
                w: 'седмица',
                ww: '%d седмици',
                M: 'месец',
                MM: '%d месеца',
                y: 'година',
                yy: '%d години',
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
            ordinal: function (number) {
                var lastDigit = number % 10,
                    last2Digits = number % 100;
                if (number === 0) {
                    return number + '-ев';
                } else if (last2Digits === 0) {
                    return number + '-ен';
                } else if (last2Digits > 10 && last2Digits < 20) {
                    return number + '-ти';
                } else if (lastDigit === 1) {
                    return number + '-ви';
                } else if (lastDigit === 2) {
                    return number + '-ри';
                } else if (lastDigit === 7 || lastDigit === 8) {
                    return number + '-ми';
                } else {
                    return number + '-ти';
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('bm', {
            months: 'Zanwuyekalo_Fewuruyekalo_Marisikalo_Awirilikalo_Mɛkalo_Zuwɛnkalo_Zuluyekalo_Utikalo_Sɛtanburukalo_ɔkutɔburukalo_Nowanburukalo_Desanburukalo'.split(
                '_'
            ),
            monthsShort: 'Zan_Few_Mar_Awi_Mɛ_Zuw_Zul_Uti_Sɛt_ɔku_Now_Des'.split('_'),
            weekdays: 'Kari_Ntɛnɛn_Tarata_Araba_Alamisa_Juma_Sibiri'.split('_'),
            weekdaysShort: 'Kar_Ntɛ_Tar_Ara_Ala_Jum_Sib'.split('_'),
            weekdaysMin: 'Ka_Nt_Ta_Ar_Al_Ju_Si'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'MMMM [tile] D [san] YYYY',
                LLL: 'MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
                LLLL: 'dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
            },
            calendar: {
                sameDay: '[Bi lɛrɛ] LT',
                nextDay: '[Sini lɛrɛ] LT',
                nextWeek: 'dddd [don lɛrɛ] LT',
                lastDay: '[Kunu lɛrɛ] LT',
                lastWeek: 'dddd [tɛmɛnen lɛrɛ] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s kɔnɔ',
                past: 'a bɛ %s bɔ',
                s: 'sanga dama dama',
                ss: 'sekondi %d',
                m: 'miniti kelen',
                mm: 'miniti %d',
                h: 'lɛrɛ kelen',
                hh: 'lɛrɛ %d',
                d: 'tile kelen',
                dd: 'tile %d',
                M: 'kalo kelen',
                MM: 'kalo %d',
                y: 'san kelen',
                yy: 'san %d',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$3 = {
                1: '১',
                2: '২',
                3: '৩',
                4: '৪',
                5: '৫',
                6: '৬',
                7: '৭',
                8: '৮',
                9: '৯',
                0: '০',
            },
            numberMap$2 = {
                '১': '1',
                '২': '2',
                '৩': '3',
                '৪': '4',
                '৫': '5',
                '৬': '6',
                '৭': '7',
                '৮': '8',
                '৯': '9',
                '০': '0',
            };
    
        hooks.defineLocale('bn-bd', {
            months: 'জানুয়ারি_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split(
                '_'
            ),
            monthsShort: 'জানু_ফেব্রু_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্ট_অক্টো_নভে_ডিসে'.split(
                '_'
            ),
            weekdays: 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার'.split(
                '_'
            ),
            weekdaysShort: 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি'.split('_'),
            weekdaysMin: 'রবি_সোম_মঙ্গল_বুধ_বৃহ_শুক্র_শনি'.split('_'),
            longDateFormat: {
                LT: 'A h:mm সময়',
                LTS: 'A h:mm:ss সময়',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm সময়',
                LLLL: 'dddd, D MMMM YYYY, A h:mm সময়',
            },
            calendar: {
                sameDay: '[আজ] LT',
                nextDay: '[আগামীকাল] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[গতকাল] LT',
                lastWeek: '[গত] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s পরে',
                past: '%s আগে',
                s: 'কয়েক সেকেন্ড',
                ss: '%d সেকেন্ড',
                m: 'এক মিনিট',
                mm: '%d মিনিট',
                h: 'এক ঘন্টা',
                hh: '%d ঘন্টা',
                d: 'এক দিন',
                dd: '%d দিন',
                M: 'এক মাস',
                MM: '%d মাস',
                y: 'এক বছর',
                yy: '%d বছর',
            },
            preparse: function (string) {
                return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
                    return numberMap$2[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$3[match];
                });
            },
    
            meridiemParse: /রাত|ভোর|সকাল|দুপুর|বিকাল|সন্ধ্যা|রাত/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'রাত') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'ভোর') {
                    return hour;
                } else if (meridiem === 'সকাল') {
                    return hour;
                } else if (meridiem === 'দুপুর') {
                    return hour >= 3 ? hour : hour + 12;
                } else if (meridiem === 'বিকাল') {
                    return hour + 12;
                } else if (meridiem === 'সন্ধ্যা') {
                    return hour + 12;
                }
            },
    
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'রাত';
                } else if (hour < 6) {
                    return 'ভোর';
                } else if (hour < 12) {
                    return 'সকাল';
                } else if (hour < 15) {
                    return 'দুপুর';
                } else if (hour < 18) {
                    return 'বিকাল';
                } else if (hour < 20) {
                    return 'সন্ধ্যা';
                } else {
                    return 'রাত';
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$4 = {
                1: '১',
                2: '২',
                3: '৩',
                4: '৪',
                5: '৫',
                6: '৬',
                7: '৭',
                8: '৮',
                9: '৯',
                0: '০',
            },
            numberMap$3 = {
                '১': '1',
                '২': '2',
                '৩': '3',
                '৪': '4',
                '৫': '5',
                '৬': '6',
                '৭': '7',
                '৮': '8',
                '৯': '9',
                '০': '0',
            };
    
        hooks.defineLocale('bn', {
            months: 'জানুয়ারি_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split(
                '_'
            ),
            monthsShort: 'জানু_ফেব্রু_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্ট_অক্টো_নভে_ডিসে'.split(
                '_'
            ),
            weekdays: 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার'.split(
                '_'
            ),
            weekdaysShort: 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি'.split('_'),
            weekdaysMin: 'রবি_সোম_মঙ্গল_বুধ_বৃহ_শুক্র_শনি'.split('_'),
            longDateFormat: {
                LT: 'A h:mm সময়',
                LTS: 'A h:mm:ss সময়',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm সময়',
                LLLL: 'dddd, D MMMM YYYY, A h:mm সময়',
            },
            calendar: {
                sameDay: '[আজ] LT',
                nextDay: '[আগামীকাল] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[গতকাল] LT',
                lastWeek: '[গত] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s পরে',
                past: '%s আগে',
                s: 'কয়েক সেকেন্ড',
                ss: '%d সেকেন্ড',
                m: 'এক মিনিট',
                mm: '%d মিনিট',
                h: 'এক ঘন্টা',
                hh: '%d ঘন্টা',
                d: 'এক দিন',
                dd: '%d দিন',
                M: 'এক মাস',
                MM: '%d মাস',
                y: 'এক বছর',
                yy: '%d বছর',
            },
            preparse: function (string) {
                return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
                    return numberMap$3[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$4[match];
                });
            },
            meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (
                    (meridiem === 'রাত' && hour >= 4) ||
                    (meridiem === 'দুপুর' && hour < 5) ||
                    meridiem === 'বিকাল'
                ) {
                    return hour + 12;
                } else {
                    return hour;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'রাত';
                } else if (hour < 10) {
                    return 'সকাল';
                } else if (hour < 17) {
                    return 'দুপুর';
                } else if (hour < 20) {
                    return 'বিকাল';
                } else {
                    return 'রাত';
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$5 = {
                1: '༡',
                2: '༢',
                3: '༣',
                4: '༤',
                5: '༥',
                6: '༦',
                7: '༧',
                8: '༨',
                9: '༩',
                0: '༠',
            },
            numberMap$4 = {
                '༡': '1',
                '༢': '2',
                '༣': '3',
                '༤': '4',
                '༥': '5',
                '༦': '6',
                '༧': '7',
                '༨': '8',
                '༩': '9',
                '༠': '0',
            };
    
        hooks.defineLocale('bo', {
            months: 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split(
                '_'
            ),
            monthsShort: 'ཟླ་1_ཟླ་2_ཟླ་3_ཟླ་4_ཟླ་5_ཟླ་6_ཟླ་7_ཟླ་8_ཟླ་9_ཟླ་10_ཟླ་11_ཟླ་12'.split(
                '_'
            ),
            monthsShortRegex: /^(ཟླ་\d{1,2})/,
            monthsParseExact: true,
            weekdays: 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split(
                '_'
            ),
            weekdaysShort: 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split(
                '_'
            ),
            weekdaysMin: 'ཉི_ཟླ_མིག_ལྷག_ཕུར_སངས_སྤེན'.split('_'),
            longDateFormat: {
                LT: 'A h:mm',
                LTS: 'A h:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm',
                LLLL: 'dddd, D MMMM YYYY, A h:mm',
            },
            calendar: {
                sameDay: '[དི་རིང] LT',
                nextDay: '[སང་ཉིན] LT',
                nextWeek: '[བདུན་ཕྲག་རྗེས་མ], LT',
                lastDay: '[ཁ་སང] LT',
                lastWeek: '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s ལ་',
                past: '%s སྔན་ལ',
                s: 'ལམ་སང',
                ss: '%d སྐར་ཆ།',
                m: 'སྐར་མ་གཅིག',
                mm: '%d སྐར་མ',
                h: 'ཆུ་ཚོད་གཅིག',
                hh: '%d ཆུ་ཚོད',
                d: 'ཉིན་གཅིག',
                dd: '%d ཉིན་',
                M: 'ཟླ་བ་གཅིག',
                MM: '%d ཟླ་བ',
                y: 'ལོ་གཅིག',
                yy: '%d ལོ',
            },
            preparse: function (string) {
                return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
                    return numberMap$4[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$5[match];
                });
            },
            meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (
                    (meridiem === 'མཚན་མོ' && hour >= 4) ||
                    (meridiem === 'ཉིན་གུང' && hour < 5) ||
                    meridiem === 'དགོང་དག'
                ) {
                    return hour + 12;
                } else {
                    return hour;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'མཚན་མོ';
                } else if (hour < 10) {
                    return 'ཞོགས་ཀས';
                } else if (hour < 17) {
                    return 'ཉིན་གུང';
                } else if (hour < 20) {
                    return 'དགོང་དག';
                } else {
                    return 'མཚན་མོ';
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function relativeTimeWithMutation(number, withoutSuffix, key) {
            var format = {
                mm: 'munutenn',
                MM: 'miz',
                dd: 'devezh',
            };
            return number + ' ' + mutation(format[key], number);
        }
        function specialMutationForYears(number) {
            switch (lastNumber(number)) {
                case 1:
                case 3:
                case 4:
                case 5:
                case 9:
                    return number + ' bloaz';
                default:
                    return number + ' vloaz';
            }
        }
        function lastNumber(number) {
            if (number > 9) {
                return lastNumber(number % 10);
            }
            return number;
        }
        function mutation(text, number) {
            if (number === 2) {
                return softMutation(text);
            }
            return text;
        }
        function softMutation(text) {
            var mutationTable = {
                m: 'v',
                b: 'v',
                d: 'z',
            };
            if (mutationTable[text.charAt(0)] === undefined) {
                return text;
            }
            return mutationTable[text.charAt(0)] + text.substring(1);
        }
    
        var monthsParse = [
                /^gen/i,
                /^c[ʼ\']hwe/i,
                /^meu/i,
                /^ebr/i,
                /^mae/i,
                /^(mez|eve)/i,
                /^gou/i,
                /^eos/i,
                /^gwe/i,
                /^her/i,
                /^du/i,
                /^ker/i,
            ],
            monthsRegex$1 = /^(genver|c[ʼ\']hwevrer|meurzh|ebrel|mae|mezheven|gouere|eost|gwengolo|here|du|kerzu|gen|c[ʼ\']hwe|meu|ebr|mae|eve|gou|eos|gwe|her|du|ker)/i,
            monthsStrictRegex = /^(genver|c[ʼ\']hwevrer|meurzh|ebrel|mae|mezheven|gouere|eost|gwengolo|here|du|kerzu)/i,
            monthsShortStrictRegex = /^(gen|c[ʼ\']hwe|meu|ebr|mae|eve|gou|eos|gwe|her|du|ker)/i,
            fullWeekdaysParse = [
                /^sul/i,
                /^lun/i,
                /^meurzh/i,
                /^merc[ʼ\']her/i,
                /^yaou/i,
                /^gwener/i,
                /^sadorn/i,
            ],
            shortWeekdaysParse = [
                /^Sul/i,
                /^Lun/i,
                /^Meu/i,
                /^Mer/i,
                /^Yao/i,
                /^Gwe/i,
                /^Sad/i,
            ],
            minWeekdaysParse = [
                /^Su/i,
                /^Lu/i,
                /^Me([^r]|$)/i,
                /^Mer/i,
                /^Ya/i,
                /^Gw/i,
                /^Sa/i,
            ];
    
        hooks.defineLocale('br', {
            months: 'Genver_Cʼhwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split(
                '_'
            ),
            monthsShort: 'Gen_Cʼhwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
            weekdays: 'Sul_Lun_Meurzh_Mercʼher_Yaou_Gwener_Sadorn'.split('_'),
            weekdaysShort: 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
            weekdaysMin: 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
            weekdaysParse: minWeekdaysParse,
            fullWeekdaysParse: fullWeekdaysParse,
            shortWeekdaysParse: shortWeekdaysParse,
            minWeekdaysParse: minWeekdaysParse,
    
            monthsRegex: monthsRegex$1,
            monthsShortRegex: monthsRegex$1,
            monthsStrictRegex: monthsStrictRegex,
            monthsShortStrictRegex: monthsShortStrictRegex,
            monthsParse: monthsParse,
            longMonthsParse: monthsParse,
            shortMonthsParse: monthsParse,
    
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D [a viz] MMMM YYYY',
                LLL: 'D [a viz] MMMM YYYY HH:mm',
                LLLL: 'dddd, D [a viz] MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Hiziv da] LT',
                nextDay: '[Warcʼhoazh da] LT',
                nextWeek: 'dddd [da] LT',
                lastDay: '[Decʼh da] LT',
                lastWeek: 'dddd [paset da] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'a-benn %s',
                past: '%s ʼzo',
                s: 'un nebeud segondennoù',
                ss: '%d eilenn',
                m: 'ur vunutenn',
                mm: relativeTimeWithMutation,
                h: 'un eur',
                hh: '%d eur',
                d: 'un devezh',
                dd: relativeTimeWithMutation,
                M: 'ur miz',
                MM: relativeTimeWithMutation,
                y: 'ur bloaz',
                yy: specialMutationForYears,
            },
            dayOfMonthOrdinalParse: /\d{1,2}(añ|vet)/,
            ordinal: function (number) {
                var output = number === 1 ? 'añ' : 'vet';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
            meridiemParse: /a.m.|g.m./, // goude merenn | a-raok merenn
            isPM: function (token) {
                return token === 'g.m.';
            },
            meridiem: function (hour, minute, isLower) {
                return hour < 12 ? 'a.m.' : 'g.m.';
            },
        });
    
        //! moment.js locale configuration
    
        function translate(number, withoutSuffix, key) {
            var result = number + ' ';
            switch (key) {
                case 'ss':
                    if (number === 1) {
                        result += 'sekunda';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'sekunde';
                    } else {
                        result += 'sekundi';
                    }
                    return result;
                case 'm':
                    return withoutSuffix ? 'jedna minuta' : 'jedne minute';
                case 'mm':
                    if (number === 1) {
                        result += 'minuta';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'minute';
                    } else {
                        result += 'minuta';
                    }
                    return result;
                case 'h':
                    return withoutSuffix ? 'jedan sat' : 'jednog sata';
                case 'hh':
                    if (number === 1) {
                        result += 'sat';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'sata';
                    } else {
                        result += 'sati';
                    }
                    return result;
                case 'dd':
                    if (number === 1) {
                        result += 'dan';
                    } else {
                        result += 'dana';
                    }
                    return result;
                case 'MM':
                    if (number === 1) {
                        result += 'mjesec';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'mjeseca';
                    } else {
                        result += 'mjeseci';
                    }
                    return result;
                case 'yy':
                    if (number === 1) {
                        result += 'godina';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'godine';
                    } else {
                        result += 'godina';
                    }
                    return result;
            }
        }
    
        hooks.defineLocale('bs', {
            months: 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split(
                '_'
            ),
            monthsShort: 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split(
                '_'
            ),
            weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
            weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY H:mm',
                LLLL: 'dddd, D. MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[danas u] LT',
                nextDay: '[sutra u] LT',
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[u] [nedjelju] [u] LT';
                        case 3:
                            return '[u] [srijedu] [u] LT';
                        case 6:
                            return '[u] [subotu] [u] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[u] dddd [u] LT';
                    }
                },
                lastDay: '[jučer u] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                        case 3:
                            return '[prošlu] dddd [u] LT';
                        case 6:
                            return '[prošle] [subote] [u] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[prošli] dddd [u] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'za %s',
                past: 'prije %s',
                s: 'par sekundi',
                ss: translate,
                m: translate,
                mm: translate,
                h: translate,
                hh: translate,
                d: 'dan',
                dd: translate,
                M: 'mjesec',
                MM: translate,
                y: 'godinu',
                yy: translate,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ca', {
            months: {
                standalone: 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split(
                    '_'
                ),
                format: "de gener_de febrer_de març_d'abril_de maig_de juny_de juliol_d'agost_de setembre_d'octubre_de novembre_de desembre".split(
                    '_'
                ),
                isFormat: /D[oD]?(\s)+MMMM/,
            },
            monthsShort: 'gen._febr._març_abr._maig_juny_jul._ag._set._oct._nov._des.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split(
                '_'
            ),
            weekdaysShort: 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
            weekdaysMin: 'dg_dl_dt_dc_dj_dv_ds'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM [de] YYYY',
                ll: 'D MMM YYYY',
                LLL: 'D MMMM [de] YYYY [a les] H:mm',
                lll: 'D MMM YYYY, H:mm',
                LLLL: 'dddd D MMMM [de] YYYY [a les] H:mm',
                llll: 'ddd D MMM YYYY, H:mm',
            },
            calendar: {
                sameDay: function () {
                    return '[avui a ' + (this.hours() !== 1 ? 'les' : 'la') + '] LT';
                },
                nextDay: function () {
                    return '[demà a ' + (this.hours() !== 1 ? 'les' : 'la') + '] LT';
                },
                nextWeek: function () {
                    return 'dddd [a ' + (this.hours() !== 1 ? 'les' : 'la') + '] LT';
                },
                lastDay: function () {
                    return '[ahir a ' + (this.hours() !== 1 ? 'les' : 'la') + '] LT';
                },
                lastWeek: function () {
                    return (
                        '[el] dddd [passat a ' +
                        (this.hours() !== 1 ? 'les' : 'la') +
                        '] LT'
                    );
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: "d'aquí %s",
                past: 'fa %s',
                s: 'uns segons',
                ss: '%d segons',
                m: 'un minut',
                mm: '%d minuts',
                h: 'una hora',
                hh: '%d hores',
                d: 'un dia',
                dd: '%d dies',
                M: 'un mes',
                MM: '%d mesos',
                y: 'un any',
                yy: '%d anys',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(r|n|t|è|a)/,
            ordinal: function (number, period) {
                var output =
                    number === 1
                        ? 'r'
                        : number === 2
                        ? 'n'
                        : number === 3
                        ? 'r'
                        : number === 4
                        ? 't'
                        : 'è';
                if (period === 'w' || period === 'W') {
                    output = 'a';
                }
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var months$4 = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split(
                '_'
            ),
            monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_'),
            monthsParse$1 = [
                /^led/i,
                /^úno/i,
                /^bře/i,
                /^dub/i,
                /^kvě/i,
                /^(čvn|červen$|června)/i,
                /^(čvc|červenec|července)/i,
                /^srp/i,
                /^zář/i,
                /^říj/i,
                /^lis/i,
                /^pro/i,
            ],
            // NOTE: 'červen' is substring of 'červenec'; therefore 'červenec' must precede 'červen' in the regex to be fully matched.
            // Otherwise parser matches '1. červenec' as '1. červen' + 'ec'.
            monthsRegex$2 = /^(leden|únor|březen|duben|květen|červenec|července|červen|června|srpen|září|říjen|listopad|prosinec|led|úno|bře|dub|kvě|čvn|čvc|srp|zář|říj|lis|pro)/i;
    
        function plural$1(n) {
            return n > 1 && n < 5 && ~~(n / 10) !== 1;
        }
        function translate$1(number, withoutSuffix, key, isFuture) {
            var result = number + ' ';
            switch (key) {
                case 's': // a few seconds / in a few seconds / a few seconds ago
                    return withoutSuffix || isFuture ? 'pár sekund' : 'pár sekundami';
                case 'ss': // 9 seconds / in 9 seconds / 9 seconds ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$1(number) ? 'sekundy' : 'sekund');
                    } else {
                        return result + 'sekundami';
                    }
                case 'm': // a minute / in a minute / a minute ago
                    return withoutSuffix ? 'minuta' : isFuture ? 'minutu' : 'minutou';
                case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$1(number) ? 'minuty' : 'minut');
                    } else {
                        return result + 'minutami';
                    }
                case 'h': // an hour / in an hour / an hour ago
                    return withoutSuffix ? 'hodina' : isFuture ? 'hodinu' : 'hodinou';
                case 'hh': // 9 hours / in 9 hours / 9 hours ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$1(number) ? 'hodiny' : 'hodin');
                    } else {
                        return result + 'hodinami';
                    }
                case 'd': // a day / in a day / a day ago
                    return withoutSuffix || isFuture ? 'den' : 'dnem';
                case 'dd': // 9 days / in 9 days / 9 days ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$1(number) ? 'dny' : 'dní');
                    } else {
                        return result + 'dny';
                    }
                case 'M': // a month / in a month / a month ago
                    return withoutSuffix || isFuture ? 'měsíc' : 'měsícem';
                case 'MM': // 9 months / in 9 months / 9 months ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$1(number) ? 'měsíce' : 'měsíců');
                    } else {
                        return result + 'měsíci';
                    }
                case 'y': // a year / in a year / a year ago
                    return withoutSuffix || isFuture ? 'rok' : 'rokem';
                case 'yy': // 9 years / in 9 years / 9 years ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$1(number) ? 'roky' : 'let');
                    } else {
                        return result + 'lety';
                    }
            }
        }
    
        hooks.defineLocale('cs', {
            months: months$4,
            monthsShort: monthsShort,
            monthsRegex: monthsRegex$2,
            monthsShortRegex: monthsRegex$2,
            // NOTE: 'červen' is substring of 'červenec'; therefore 'červenec' must precede 'červen' in the regex to be fully matched.
            // Otherwise parser matches '1. červenec' as '1. červen' + 'ec'.
            monthsStrictRegex: /^(leden|ledna|února|únor|březen|března|duben|dubna|květen|května|červenec|července|červen|června|srpen|srpna|září|říjen|října|listopadu|listopad|prosinec|prosince)/i,
            monthsShortStrictRegex: /^(led|úno|bře|dub|kvě|čvn|čvc|srp|zář|říj|lis|pro)/i,
            monthsParse: monthsParse$1,
            longMonthsParse: monthsParse$1,
            shortMonthsParse: monthsParse$1,
            weekdays: 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
            weekdaysShort: 'ne_po_út_st_čt_pá_so'.split('_'),
            weekdaysMin: 'ne_po_út_st_čt_pá_so'.split('_'),
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY H:mm',
                LLLL: 'dddd D. MMMM YYYY H:mm',
                l: 'D. M. YYYY',
            },
            calendar: {
                sameDay: '[dnes v] LT',
                nextDay: '[zítra v] LT',
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[v neděli v] LT';
                        case 1:
                        case 2:
                            return '[v] dddd [v] LT';
                        case 3:
                            return '[ve středu v] LT';
                        case 4:
                            return '[ve čtvrtek v] LT';
                        case 5:
                            return '[v pátek v] LT';
                        case 6:
                            return '[v sobotu v] LT';
                    }
                },
                lastDay: '[včera v] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[minulou neděli v] LT';
                        case 1:
                        case 2:
                            return '[minulé] dddd [v] LT';
                        case 3:
                            return '[minulou středu v] LT';
                        case 4:
                        case 5:
                            return '[minulý] dddd [v] LT';
                        case 6:
                            return '[minulou sobotu v] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'za %s',
                past: 'před %s',
                s: translate$1,
                ss: translate$1,
                m: translate$1,
                mm: translate$1,
                h: translate$1,
                hh: translate$1,
                d: translate$1,
                dd: translate$1,
                M: translate$1,
                MM: translate$1,
                y: translate$1,
                yy: translate$1,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('cv', {
            months: 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split(
                '_'
            ),
            monthsShort: 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'),
            weekdays: 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split(
                '_'
            ),
            weekdaysShort: 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'),
            weekdaysMin: 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD-MM-YYYY',
                LL: 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
                LLL: 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
                LLLL: 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
            },
            calendar: {
                sameDay: '[Паян] LT [сехетре]',
                nextDay: '[Ыран] LT [сехетре]',
                lastDay: '[Ӗнер] LT [сехетре]',
                nextWeek: '[Ҫитес] dddd LT [сехетре]',
                lastWeek: '[Иртнӗ] dddd LT [сехетре]',
                sameElse: 'L',
            },
            relativeTime: {
                future: function (output) {
                    var affix = /сехет$/i.exec(output)
                        ? 'рен'
                        : /ҫул$/i.exec(output)
                        ? 'тан'
                        : 'ран';
                    return output + affix;
                },
                past: '%s каялла',
                s: 'пӗр-ик ҫеккунт',
                ss: '%d ҫеккунт',
                m: 'пӗр минут',
                mm: '%d минут',
                h: 'пӗр сехет',
                hh: '%d сехет',
                d: 'пӗр кун',
                dd: '%d кун',
                M: 'пӗр уйӑх',
                MM: '%d уйӑх',
                y: 'пӗр ҫул',
                yy: '%d ҫул',
            },
            dayOfMonthOrdinalParse: /\d{1,2}-мӗш/,
            ordinal: '%d-мӗш',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('cy', {
            months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split(
                '_'
            ),
            monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split(
                '_'
            ),
            weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split(
                '_'
            ),
            weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'),
            weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'),
            weekdaysParseExact: true,
            // time formats are the same as en-gb
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Heddiw am] LT',
                nextDay: '[Yfory am] LT',
                nextWeek: 'dddd [am] LT',
                lastDay: '[Ddoe am] LT',
                lastWeek: 'dddd [diwethaf am] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'mewn %s',
                past: '%s yn ôl',
                s: 'ychydig eiliadau',
                ss: '%d eiliad',
                m: 'munud',
                mm: '%d munud',
                h: 'awr',
                hh: '%d awr',
                d: 'diwrnod',
                dd: '%d diwrnod',
                M: 'mis',
                MM: '%d mis',
                y: 'blwyddyn',
                yy: '%d flynedd',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,
            // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
            ordinal: function (number) {
                var b = number,
                    output = '',
                    lookup = [
                        '',
                        'af',
                        'il',
                        'ydd',
                        'ydd',
                        'ed',
                        'ed',
                        'ed',
                        'fed',
                        'fed',
                        'fed', // 1af to 10fed
                        'eg',
                        'fed',
                        'eg',
                        'eg',
                        'fed',
                        'eg',
                        'eg',
                        'fed',
                        'eg',
                        'fed', // 11eg to 20fed
                    ];
                if (b > 20) {
                    if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
                        output = 'fed'; // not 30ain, 70ain or 90ain
                    } else {
                        output = 'ain';
                    }
                } else if (b > 0) {
                    output = lookup[b];
                }
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('da', {
            months: 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split(
                '_'
            ),
            monthsShort: 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
            weekdays: 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
            weekdaysShort: 'søn_man_tir_ons_tor_fre_lør'.split('_'),
            weekdaysMin: 'sø_ma_ti_on_to_fr_lø'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY HH:mm',
                LLLL: 'dddd [d.] D. MMMM YYYY [kl.] HH:mm',
            },
            calendar: {
                sameDay: '[i dag kl.] LT',
                nextDay: '[i morgen kl.] LT',
                nextWeek: 'på dddd [kl.] LT',
                lastDay: '[i går kl.] LT',
                lastWeek: '[i] dddd[s kl.] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'om %s',
                past: '%s siden',
                s: 'få sekunder',
                ss: '%d sekunder',
                m: 'et minut',
                mm: '%d minutter',
                h: 'en time',
                hh: '%d timer',
                d: 'en dag',
                dd: '%d dage',
                M: 'en måned',
                MM: '%d måneder',
                y: 'et år',
                yy: '%d år',
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function processRelativeTime(number, withoutSuffix, key, isFuture) {
            var format = {
                m: ['eine Minute', 'einer Minute'],
                h: ['eine Stunde', 'einer Stunde'],
                d: ['ein Tag', 'einem Tag'],
                dd: [number + ' Tage', number + ' Tagen'],
                w: ['eine Woche', 'einer Woche'],
                M: ['ein Monat', 'einem Monat'],
                MM: [number + ' Monate', number + ' Monaten'],
                y: ['ein Jahr', 'einem Jahr'],
                yy: [number + ' Jahre', number + ' Jahren'],
            };
            return withoutSuffix ? format[key][0] : format[key][1];
        }
    
        hooks.defineLocale('de-at', {
            months: 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split(
                '_'
            ),
            monthsShort: 'Jän._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split(
                '_'
            ),
            weekdaysShort: 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
            weekdaysMin: 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY HH:mm',
                LLLL: 'dddd, D. MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[heute um] LT [Uhr]',
                sameElse: 'L',
                nextDay: '[morgen um] LT [Uhr]',
                nextWeek: 'dddd [um] LT [Uhr]',
                lastDay: '[gestern um] LT [Uhr]',
                lastWeek: '[letzten] dddd [um] LT [Uhr]',
            },
            relativeTime: {
                future: 'in %s',
                past: 'vor %s',
                s: 'ein paar Sekunden',
                ss: '%d Sekunden',
                m: processRelativeTime,
                mm: '%d Minuten',
                h: processRelativeTime,
                hh: '%d Stunden',
                d: processRelativeTime,
                dd: processRelativeTime,
                w: processRelativeTime,
                ww: '%d Wochen',
                M: processRelativeTime,
                MM: processRelativeTime,
                y: processRelativeTime,
                yy: processRelativeTime,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function processRelativeTime$1(number, withoutSuffix, key, isFuture) {
            var format = {
                m: ['eine Minute', 'einer Minute'],
                h: ['eine Stunde', 'einer Stunde'],
                d: ['ein Tag', 'einem Tag'],
                dd: [number + ' Tage', number + ' Tagen'],
                w: ['eine Woche', 'einer Woche'],
                M: ['ein Monat', 'einem Monat'],
                MM: [number + ' Monate', number + ' Monaten'],
                y: ['ein Jahr', 'einem Jahr'],
                yy: [number + ' Jahre', number + ' Jahren'],
            };
            return withoutSuffix ? format[key][0] : format[key][1];
        }
    
        hooks.defineLocale('de-ch', {
            months: 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split(
                '_'
            ),
            monthsShort: 'Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split(
                '_'
            ),
            weekdaysShort: 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
            weekdaysMin: 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY HH:mm',
                LLLL: 'dddd, D. MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[heute um] LT [Uhr]',
                sameElse: 'L',
                nextDay: '[morgen um] LT [Uhr]',
                nextWeek: 'dddd [um] LT [Uhr]',
                lastDay: '[gestern um] LT [Uhr]',
                lastWeek: '[letzten] dddd [um] LT [Uhr]',
            },
            relativeTime: {
                future: 'in %s',
                past: 'vor %s',
                s: 'ein paar Sekunden',
                ss: '%d Sekunden',
                m: processRelativeTime$1,
                mm: '%d Minuten',
                h: processRelativeTime$1,
                hh: '%d Stunden',
                d: processRelativeTime$1,
                dd: processRelativeTime$1,
                w: processRelativeTime$1,
                ww: '%d Wochen',
                M: processRelativeTime$1,
                MM: processRelativeTime$1,
                y: processRelativeTime$1,
                yy: processRelativeTime$1,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function processRelativeTime$2(number, withoutSuffix, key, isFuture) {
            var format = {
                m: ['eine Minute', 'einer Minute'],
                h: ['eine Stunde', 'einer Stunde'],
                d: ['ein Tag', 'einem Tag'],
                dd: [number + ' Tage', number + ' Tagen'],
                w: ['eine Woche', 'einer Woche'],
                M: ['ein Monat', 'einem Monat'],
                MM: [number + ' Monate', number + ' Monaten'],
                y: ['ein Jahr', 'einem Jahr'],
                yy: [number + ' Jahre', number + ' Jahren'],
            };
            return withoutSuffix ? format[key][0] : format[key][1];
        }
    
        hooks.defineLocale('de', {
            months: 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split(
                '_'
            ),
            monthsShort: 'Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split(
                '_'
            ),
            weekdaysShort: 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
            weekdaysMin: 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY HH:mm',
                LLLL: 'dddd, D. MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[heute um] LT [Uhr]',
                sameElse: 'L',
                nextDay: '[morgen um] LT [Uhr]',
                nextWeek: 'dddd [um] LT [Uhr]',
                lastDay: '[gestern um] LT [Uhr]',
                lastWeek: '[letzten] dddd [um] LT [Uhr]',
            },
            relativeTime: {
                future: 'in %s',
                past: 'vor %s',
                s: 'ein paar Sekunden',
                ss: '%d Sekunden',
                m: processRelativeTime$2,
                mm: '%d Minuten',
                h: processRelativeTime$2,
                hh: '%d Stunden',
                d: processRelativeTime$2,
                dd: processRelativeTime$2,
                w: processRelativeTime$2,
                ww: '%d Wochen',
                M: processRelativeTime$2,
                MM: processRelativeTime$2,
                y: processRelativeTime$2,
                yy: processRelativeTime$2,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var months$5 = [
                'ޖެނުއަރީ',
                'ފެބްރުއަރީ',
                'މާރިޗު',
                'އޭޕްރީލު',
                'މޭ',
                'ޖޫން',
                'ޖުލައި',
                'އޯގަސްޓު',
                'ސެޕްޓެމްބަރު',
                'އޮކްޓޯބަރު',
                'ނޮވެމްބަރު',
                'ޑިސެމްބަރު',
            ],
            weekdays = [
                'އާދިއްތަ',
                'ހޯމަ',
                'އަންގާރަ',
                'ބުދަ',
                'ބުރާސްފަތި',
                'ހުކުރު',
                'ހޮނިހިރު',
            ];
    
        hooks.defineLocale('dv', {
            months: months$5,
            monthsShort: months$5,
            weekdays: weekdays,
            weekdaysShort: weekdays,
            weekdaysMin: 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'D/M/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            meridiemParse: /މކ|މފ/,
            isPM: function (input) {
                return 'މފ' === input;
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'މކ';
                } else {
                    return 'މފ';
                }
            },
            calendar: {
                sameDay: '[މިއަދު] LT',
                nextDay: '[މާދަމާ] LT',
                nextWeek: 'dddd LT',
                lastDay: '[އިއްޔެ] LT',
                lastWeek: '[ފާއިތުވި] dddd LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'ތެރޭގައި %s',
                past: 'ކުރިން %s',
                s: 'ސިކުންތުކޮޅެއް',
                ss: 'd% ސިކުންތު',
                m: 'މިނިޓެއް',
                mm: 'މިނިޓު %d',
                h: 'ގަޑިއިރެއް',
                hh: 'ގަޑިއިރު %d',
                d: 'ދުވަހެއް',
                dd: 'ދުވަސް %d',
                M: 'މަހެއް',
                MM: 'މަސް %d',
                y: 'އަހަރެއް',
                yy: 'އަހަރު %d',
            },
            preparse: function (string) {
                return string.replace(/،/g, ',');
            },
            postformat: function (string) {
                return string.replace(/,/g, '،');
            },
            week: {
                dow: 7, // Sunday is the first day of the week.
                doy: 12, // The week that contains Jan 12th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function isFunction$1(input) {
            return (
                (typeof Function !== 'undefined' && input instanceof Function) ||
                Object.prototype.toString.call(input) === '[object Function]'
            );
        }
    
        hooks.defineLocale('el', {
            monthsNominativeEl: 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split(
                '_'
            ),
            monthsGenitiveEl: 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split(
                '_'
            ),
            months: function (momentToFormat, format) {
                if (!momentToFormat) {
                    return this._monthsNominativeEl;
                } else if (
                    typeof format === 'string' &&
                    /D/.test(format.substring(0, format.indexOf('MMMM')))
                ) {
                    // if there is a day number before 'MMMM'
                    return this._monthsGenitiveEl[momentToFormat.month()];
                } else {
                    return this._monthsNominativeEl[momentToFormat.month()];
                }
            },
            monthsShort: 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'),
            weekdays: 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split(
                '_'
            ),
            weekdaysShort: 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'),
            weekdaysMin: 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'),
            meridiem: function (hours, minutes, isLower) {
                if (hours > 11) {
                    return isLower ? 'μμ' : 'ΜΜ';
                } else {
                    return isLower ? 'πμ' : 'ΠΜ';
                }
            },
            isPM: function (input) {
                return (input + '').toLowerCase()[0] === 'μ';
            },
            meridiemParse: /[ΠΜ]\.?Μ?\.?/i,
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY h:mm A',
                LLLL: 'dddd, D MMMM YYYY h:mm A',
            },
            calendarEl: {
                sameDay: '[Σήμερα {}] LT',
                nextDay: '[Αύριο {}] LT',
                nextWeek: 'dddd [{}] LT',
                lastDay: '[Χθες {}] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 6:
                            return '[το προηγούμενο] dddd [{}] LT';
                        default:
                            return '[την προηγούμενη] dddd [{}] LT';
                    }
                },
                sameElse: 'L',
            },
            calendar: function (key, mom) {
                var output = this._calendarEl[key],
                    hours = mom && mom.hours();
                if (isFunction$1(output)) {
                    output = output.apply(mom);
                }
                return output.replace('{}', hours % 12 === 1 ? 'στη' : 'στις');
            },
            relativeTime: {
                future: 'σε %s',
                past: '%s πριν',
                s: 'λίγα δευτερόλεπτα',
                ss: '%d δευτερόλεπτα',
                m: 'ένα λεπτό',
                mm: '%d λεπτά',
                h: 'μία ώρα',
                hh: '%d ώρες',
                d: 'μία μέρα',
                dd: '%d μέρες',
                M: 'ένας μήνας',
                MM: '%d μήνες',
                y: 'ένας χρόνος',
                yy: '%d χρόνια',
            },
            dayOfMonthOrdinalParse: /\d{1,2}η/,
            ordinal: '%dη',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4st is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('en-au', {
            months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
            weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY h:mm A',
                LLLL: 'dddd, D MMMM YYYY h:mm A',
            },
            calendar: {
                sameDay: '[Today at] LT',
                nextDay: '[Tomorrow at] LT',
                nextWeek: 'dddd [at] LT',
                lastDay: '[Yesterday at] LT',
                lastWeek: '[Last] dddd [at] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'in %s',
                past: '%s ago',
                s: 'a few seconds',
                ss: '%d seconds',
                m: 'a minute',
                mm: '%d minutes',
                h: 'an hour',
                hh: '%d hours',
                d: 'a day',
                dd: '%d days',
                M: 'a month',
                MM: '%d months',
                y: 'a year',
                yy: '%d years',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('en-ca', {
            months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
            weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'YYYY-MM-DD',
                LL: 'MMMM D, YYYY',
                LLL: 'MMMM D, YYYY h:mm A',
                LLLL: 'dddd, MMMM D, YYYY h:mm A',
            },
            calendar: {
                sameDay: '[Today at] LT',
                nextDay: '[Tomorrow at] LT',
                nextWeek: 'dddd [at] LT',
                lastDay: '[Yesterday at] LT',
                lastWeek: '[Last] dddd [at] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'in %s',
                past: '%s ago',
                s: 'a few seconds',
                ss: '%d seconds',
                m: 'a minute',
                mm: '%d minutes',
                h: 'an hour',
                hh: '%d hours',
                d: 'a day',
                dd: '%d days',
                M: 'a month',
                MM: '%d months',
                y: 'a year',
                yy: '%d years',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('en-gb', {
            months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
            weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Today at] LT',
                nextDay: '[Tomorrow at] LT',
                nextWeek: 'dddd [at] LT',
                lastDay: '[Yesterday at] LT',
                lastWeek: '[Last] dddd [at] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'in %s',
                past: '%s ago',
                s: 'a few seconds',
                ss: '%d seconds',
                m: 'a minute',
                mm: '%d minutes',
                h: 'an hour',
                hh: '%d hours',
                d: 'a day',
                dd: '%d days',
                M: 'a month',
                MM: '%d months',
                y: 'a year',
                yy: '%d years',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('en-ie', {
            months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
            weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Today at] LT',
                nextDay: '[Tomorrow at] LT',
                nextWeek: 'dddd [at] LT',
                lastDay: '[Yesterday at] LT',
                lastWeek: '[Last] dddd [at] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'in %s',
                past: '%s ago',
                s: 'a few seconds',
                ss: '%d seconds',
                m: 'a minute',
                mm: '%d minutes',
                h: 'an hour',
                hh: '%d hours',
                d: 'a day',
                dd: '%d days',
                M: 'a month',
                MM: '%d months',
                y: 'a year',
                yy: '%d years',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('en-il', {
            months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
            weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Today at] LT',
                nextDay: '[Tomorrow at] LT',
                nextWeek: 'dddd [at] LT',
                lastDay: '[Yesterday at] LT',
                lastWeek: '[Last] dddd [at] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'in %s',
                past: '%s ago',
                s: 'a few seconds',
                ss: '%d seconds',
                m: 'a minute',
                mm: '%d minutes',
                h: 'an hour',
                hh: '%d hours',
                d: 'a day',
                dd: '%d days',
                M: 'a month',
                MM: '%d months',
                y: 'a year',
                yy: '%d years',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('en-in', {
            months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
            weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY h:mm A',
                LLLL: 'dddd, D MMMM YYYY h:mm A',
            },
            calendar: {
                sameDay: '[Today at] LT',
                nextDay: '[Tomorrow at] LT',
                nextWeek: 'dddd [at] LT',
                lastDay: '[Yesterday at] LT',
                lastWeek: '[Last] dddd [at] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'in %s',
                past: '%s ago',
                s: 'a few seconds',
                ss: '%d seconds',
                m: 'a minute',
                mm: '%d minutes',
                h: 'an hour',
                hh: '%d hours',
                d: 'a day',
                dd: '%d days',
                M: 'a month',
                MM: '%d months',
                y: 'a year',
                yy: '%d years',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 1st is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('en-nz', {
            months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
            weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY h:mm A',
                LLLL: 'dddd, D MMMM YYYY h:mm A',
            },
            calendar: {
                sameDay: '[Today at] LT',
                nextDay: '[Tomorrow at] LT',
                nextWeek: 'dddd [at] LT',
                lastDay: '[Yesterday at] LT',
                lastWeek: '[Last] dddd [at] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'in %s',
                past: '%s ago',
                s: 'a few seconds',
                ss: '%d seconds',
                m: 'a minute',
                mm: '%d minutes',
                h: 'an hour',
                hh: '%d hours',
                d: 'a day',
                dd: '%d days',
                M: 'a month',
                MM: '%d months',
                y: 'a year',
                yy: '%d years',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('en-sg', {
            months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
            weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
                '_'
            ),
            weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
            weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Today at] LT',
                nextDay: '[Tomorrow at] LT',
                nextWeek: 'dddd [at] LT',
                lastDay: '[Yesterday at] LT',
                lastWeek: '[Last] dddd [at] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'in %s',
                past: '%s ago',
                s: 'a few seconds',
                ss: '%d seconds',
                m: 'a minute',
                mm: '%d minutes',
                h: 'an hour',
                hh: '%d hours',
                d: 'a day',
                dd: '%d days',
                M: 'a month',
                MM: '%d months',
                y: 'a year',
                yy: '%d years',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('eo', {
            months: 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split(
                '_'
            ),
            monthsShort: 'jan_feb_mart_apr_maj_jun_jul_aŭg_sept_okt_nov_dec'.split('_'),
            weekdays: 'dimanĉo_lundo_mardo_merkredo_ĵaŭdo_vendredo_sabato'.split('_'),
            weekdaysShort: 'dim_lun_mard_merk_ĵaŭ_ven_sab'.split('_'),
            weekdaysMin: 'di_lu_ma_me_ĵa_ve_sa'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY-MM-DD',
                LL: '[la] D[-an de] MMMM, YYYY',
                LLL: '[la] D[-an de] MMMM, YYYY HH:mm',
                LLLL: 'dddd[n], [la] D[-an de] MMMM, YYYY HH:mm',
                llll: 'ddd, [la] D[-an de] MMM, YYYY HH:mm',
            },
            meridiemParse: /[ap]\.t\.m/i,
            isPM: function (input) {
                return input.charAt(0).toLowerCase() === 'p';
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours > 11) {
                    return isLower ? 'p.t.m.' : 'P.T.M.';
                } else {
                    return isLower ? 'a.t.m.' : 'A.T.M.';
                }
            },
            calendar: {
                sameDay: '[Hodiaŭ je] LT',
                nextDay: '[Morgaŭ je] LT',
                nextWeek: 'dddd[n je] LT',
                lastDay: '[Hieraŭ je] LT',
                lastWeek: '[pasintan] dddd[n je] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'post %s',
                past: 'antaŭ %s',
                s: 'kelkaj sekundoj',
                ss: '%d sekundoj',
                m: 'unu minuto',
                mm: '%d minutoj',
                h: 'unu horo',
                hh: '%d horoj',
                d: 'unu tago', //ne 'diurno', ĉar estas uzita por proksimumo
                dd: '%d tagoj',
                M: 'unu monato',
                MM: '%d monatoj',
                y: 'unu jaro',
                yy: '%d jaroj',
            },
            dayOfMonthOrdinalParse: /\d{1,2}a/,
            ordinal: '%da',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split(
                '_'
            ),
            monthsShort$1 = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'),
            monthsParse$2 = [
                /^ene/i,
                /^feb/i,
                /^mar/i,
                /^abr/i,
                /^may/i,
                /^jun/i,
                /^jul/i,
                /^ago/i,
                /^sep/i,
                /^oct/i,
                /^nov/i,
                /^dic/i,
            ],
            monthsRegex$3 = /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;
    
        hooks.defineLocale('es-do', {
            months: 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split(
                '_'
            ),
            monthsShort: function (m, format) {
                if (!m) {
                    return monthsShortDot;
                } else if (/-MMM-/.test(format)) {
                    return monthsShort$1[m.month()];
                } else {
                    return monthsShortDot[m.month()];
                }
            },
            monthsRegex: monthsRegex$3,
            monthsShortRegex: monthsRegex$3,
            monthsStrictRegex: /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,
            monthsShortStrictRegex: /^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,
            monthsParse: monthsParse$2,
            longMonthsParse: monthsParse$2,
            shortMonthsParse: monthsParse$2,
            weekdays: 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
            weekdaysShort: 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
            weekdaysMin: 'do_lu_ma_mi_ju_vi_sá'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'DD/MM/YYYY',
                LL: 'D [de] MMMM [de] YYYY',
                LLL: 'D [de] MMMM [de] YYYY h:mm A',
                LLLL: 'dddd, D [de] MMMM [de] YYYY h:mm A',
            },
            calendar: {
                sameDay: function () {
                    return '[hoy a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                nextDay: function () {
                    return '[mañana a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                nextWeek: function () {
                    return 'dddd [a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                lastDay: function () {
                    return '[ayer a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                lastWeek: function () {
                    return (
                        '[el] dddd [pasado a la' +
                        (this.hours() !== 1 ? 's' : '') +
                        '] LT'
                    );
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'en %s',
                past: 'hace %s',
                s: 'unos segundos',
                ss: '%d segundos',
                m: 'un minuto',
                mm: '%d minutos',
                h: 'una hora',
                hh: '%d horas',
                d: 'un día',
                dd: '%d días',
                w: 'una semana',
                ww: '%d semanas',
                M: 'un mes',
                MM: '%d meses',
                y: 'un año',
                yy: '%d años',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var monthsShortDot$1 = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split(
                '_'
            ),
            monthsShort$2 = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'),
            monthsParse$3 = [
                /^ene/i,
                /^feb/i,
                /^mar/i,
                /^abr/i,
                /^may/i,
                /^jun/i,
                /^jul/i,
                /^ago/i,
                /^sep/i,
                /^oct/i,
                /^nov/i,
                /^dic/i,
            ],
            monthsRegex$4 = /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;
    
        hooks.defineLocale('es-mx', {
            months: 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split(
                '_'
            ),
            monthsShort: function (m, format) {
                if (!m) {
                    return monthsShortDot$1;
                } else if (/-MMM-/.test(format)) {
                    return monthsShort$2[m.month()];
                } else {
                    return monthsShortDot$1[m.month()];
                }
            },
            monthsRegex: monthsRegex$4,
            monthsShortRegex: monthsRegex$4,
            monthsStrictRegex: /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,
            monthsShortStrictRegex: /^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,
            monthsParse: monthsParse$3,
            longMonthsParse: monthsParse$3,
            shortMonthsParse: monthsParse$3,
            weekdays: 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
            weekdaysShort: 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
            weekdaysMin: 'do_lu_ma_mi_ju_vi_sá'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D [de] MMMM [de] YYYY',
                LLL: 'D [de] MMMM [de] YYYY H:mm',
                LLLL: 'dddd, D [de] MMMM [de] YYYY H:mm',
            },
            calendar: {
                sameDay: function () {
                    return '[hoy a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                nextDay: function () {
                    return '[mañana a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                nextWeek: function () {
                    return 'dddd [a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                lastDay: function () {
                    return '[ayer a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                lastWeek: function () {
                    return (
                        '[el] dddd [pasado a la' +
                        (this.hours() !== 1 ? 's' : '') +
                        '] LT'
                    );
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'en %s',
                past: 'hace %s',
                s: 'unos segundos',
                ss: '%d segundos',
                m: 'un minuto',
                mm: '%d minutos',
                h: 'una hora',
                hh: '%d horas',
                d: 'un día',
                dd: '%d días',
                w: 'una semana',
                ww: '%d semanas',
                M: 'un mes',
                MM: '%d meses',
                y: 'un año',
                yy: '%d años',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
            invalidDate: 'Fecha inválida',
        });
    
        //! moment.js locale configuration
    
        var monthsShortDot$2 = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split(
                '_'
            ),
            monthsShort$3 = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'),
            monthsParse$4 = [
                /^ene/i,
                /^feb/i,
                /^mar/i,
                /^abr/i,
                /^may/i,
                /^jun/i,
                /^jul/i,
                /^ago/i,
                /^sep/i,
                /^oct/i,
                /^nov/i,
                /^dic/i,
            ],
            monthsRegex$5 = /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;
    
        hooks.defineLocale('es-us', {
            months: 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split(
                '_'
            ),
            monthsShort: function (m, format) {
                if (!m) {
                    return monthsShortDot$2;
                } else if (/-MMM-/.test(format)) {
                    return monthsShort$3[m.month()];
                } else {
                    return monthsShortDot$2[m.month()];
                }
            },
            monthsRegex: monthsRegex$5,
            monthsShortRegex: monthsRegex$5,
            monthsStrictRegex: /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,
            monthsShortStrictRegex: /^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,
            monthsParse: monthsParse$4,
            longMonthsParse: monthsParse$4,
            shortMonthsParse: monthsParse$4,
            weekdays: 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
            weekdaysShort: 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
            weekdaysMin: 'do_lu_ma_mi_ju_vi_sá'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'MM/DD/YYYY',
                LL: 'D [de] MMMM [de] YYYY',
                LLL: 'D [de] MMMM [de] YYYY h:mm A',
                LLLL: 'dddd, D [de] MMMM [de] YYYY h:mm A',
            },
            calendar: {
                sameDay: function () {
                    return '[hoy a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                nextDay: function () {
                    return '[mañana a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                nextWeek: function () {
                    return 'dddd [a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                lastDay: function () {
                    return '[ayer a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                lastWeek: function () {
                    return (
                        '[el] dddd [pasado a la' +
                        (this.hours() !== 1 ? 's' : '') +
                        '] LT'
                    );
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'en %s',
                past: 'hace %s',
                s: 'unos segundos',
                ss: '%d segundos',
                m: 'un minuto',
                mm: '%d minutos',
                h: 'una hora',
                hh: '%d horas',
                d: 'un día',
                dd: '%d días',
                w: 'una semana',
                ww: '%d semanas',
                M: 'un mes',
                MM: '%d meses',
                y: 'un año',
                yy: '%d años',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var monthsShortDot$3 = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split(
                '_'
            ),
            monthsShort$4 = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'),
            monthsParse$5 = [
                /^ene/i,
                /^feb/i,
                /^mar/i,
                /^abr/i,
                /^may/i,
                /^jun/i,
                /^jul/i,
                /^ago/i,
                /^sep/i,
                /^oct/i,
                /^nov/i,
                /^dic/i,
            ],
            monthsRegex$6 = /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;
    
        hooks.defineLocale('es', {
            months: 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split(
                '_'
            ),
            monthsShort: function (m, format) {
                if (!m) {
                    return monthsShortDot$3;
                } else if (/-MMM-/.test(format)) {
                    return monthsShort$4[m.month()];
                } else {
                    return monthsShortDot$3[m.month()];
                }
            },
            monthsRegex: monthsRegex$6,
            monthsShortRegex: monthsRegex$6,
            monthsStrictRegex: /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,
            monthsShortStrictRegex: /^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,
            monthsParse: monthsParse$5,
            longMonthsParse: monthsParse$5,
            shortMonthsParse: monthsParse$5,
            weekdays: 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
            weekdaysShort: 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
            weekdaysMin: 'do_lu_ma_mi_ju_vi_sá'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D [de] MMMM [de] YYYY',
                LLL: 'D [de] MMMM [de] YYYY H:mm',
                LLLL: 'dddd, D [de] MMMM [de] YYYY H:mm',
            },
            calendar: {
                sameDay: function () {
                    return '[hoy a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                nextDay: function () {
                    return '[mañana a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                nextWeek: function () {
                    return 'dddd [a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                lastDay: function () {
                    return '[ayer a la' + (this.hours() !== 1 ? 's' : '') + '] LT';
                },
                lastWeek: function () {
                    return (
                        '[el] dddd [pasado a la' +
                        (this.hours() !== 1 ? 's' : '') +
                        '] LT'
                    );
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'en %s',
                past: 'hace %s',
                s: 'unos segundos',
                ss: '%d segundos',
                m: 'un minuto',
                mm: '%d minutos',
                h: 'una hora',
                hh: '%d horas',
                d: 'un día',
                dd: '%d días',
                w: 'una semana',
                ww: '%d semanas',
                M: 'un mes',
                MM: '%d meses',
                y: 'un año',
                yy: '%d años',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
            invalidDate: 'Fecha inválida',
        });
    
        //! moment.js locale configuration
    
        function processRelativeTime$3(number, withoutSuffix, key, isFuture) {
            var format = {
                s: ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
                ss: [number + 'sekundi', number + 'sekundit'],
                m: ['ühe minuti', 'üks minut'],
                mm: [number + ' minuti', number + ' minutit'],
                h: ['ühe tunni', 'tund aega', 'üks tund'],
                hh: [number + ' tunni', number + ' tundi'],
                d: ['ühe päeva', 'üks päev'],
                M: ['kuu aja', 'kuu aega', 'üks kuu'],
                MM: [number + ' kuu', number + ' kuud'],
                y: ['ühe aasta', 'aasta', 'üks aasta'],
                yy: [number + ' aasta', number + ' aastat'],
            };
            if (withoutSuffix) {
                return format[key][2] ? format[key][2] : format[key][1];
            }
            return isFuture ? format[key][0] : format[key][1];
        }
    
        hooks.defineLocale('et', {
            months: 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split(
                '_'
            ),
            monthsShort: 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split(
                '_'
            ),
            weekdays: 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split(
                '_'
            ),
            weekdaysShort: 'P_E_T_K_N_R_L'.split('_'),
            weekdaysMin: 'P_E_T_K_N_R_L'.split('_'),
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY H:mm',
                LLLL: 'dddd, D. MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[Täna,] LT',
                nextDay: '[Homme,] LT',
                nextWeek: '[Järgmine] dddd LT',
                lastDay: '[Eile,] LT',
                lastWeek: '[Eelmine] dddd LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s pärast',
                past: '%s tagasi',
                s: processRelativeTime$3,
                ss: processRelativeTime$3,
                m: processRelativeTime$3,
                mm: processRelativeTime$3,
                h: processRelativeTime$3,
                hh: processRelativeTime$3,
                d: processRelativeTime$3,
                dd: '%d päeva',
                M: processRelativeTime$3,
                MM: processRelativeTime$3,
                y: processRelativeTime$3,
                yy: processRelativeTime$3,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('eu', {
            months: 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split(
                '_'
            ),
            monthsShort: 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split(
                '_'
            ),
            weekdaysShort: 'ig._al._ar._az._og._ol._lr.'.split('_'),
            weekdaysMin: 'ig_al_ar_az_og_ol_lr'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY-MM-DD',
                LL: 'YYYY[ko] MMMM[ren] D[a]',
                LLL: 'YYYY[ko] MMMM[ren] D[a] HH:mm',
                LLLL: 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
                l: 'YYYY-M-D',
                ll: 'YYYY[ko] MMM D[a]',
                lll: 'YYYY[ko] MMM D[a] HH:mm',
                llll: 'ddd, YYYY[ko] MMM D[a] HH:mm',
            },
            calendar: {
                sameDay: '[gaur] LT[etan]',
                nextDay: '[bihar] LT[etan]',
                nextWeek: 'dddd LT[etan]',
                lastDay: '[atzo] LT[etan]',
                lastWeek: '[aurreko] dddd LT[etan]',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s barru',
                past: 'duela %s',
                s: 'segundo batzuk',
                ss: '%d segundo',
                m: 'minutu bat',
                mm: '%d minutu',
                h: 'ordu bat',
                hh: '%d ordu',
                d: 'egun bat',
                dd: '%d egun',
                M: 'hilabete bat',
                MM: '%d hilabete',
                y: 'urte bat',
                yy: '%d urte',
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$6 = {
                1: '۱',
                2: '۲',
                3: '۳',
                4: '۴',
                5: '۵',
                6: '۶',
                7: '۷',
                8: '۸',
                9: '۹',
                0: '۰',
            },
            numberMap$5 = {
                '۱': '1',
                '۲': '2',
                '۳': '3',
                '۴': '4',
                '۵': '5',
                '۶': '6',
                '۷': '7',
                '۸': '8',
                '۹': '9',
                '۰': '0',
            };
    
        hooks.defineLocale('fa', {
            months: 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split(
                '_'
            ),
            monthsShort: 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split(
                '_'
            ),
            weekdays: 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split(
                '_'
            ),
            weekdaysShort: 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split(
                '_'
            ),
            weekdaysMin: 'ی_د_س_چ_پ_ج_ش'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            meridiemParse: /قبل از ظهر|بعد از ظهر/,
            isPM: function (input) {
                return /بعد از ظهر/.test(input);
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'قبل از ظهر';
                } else {
                    return 'بعد از ظهر';
                }
            },
            calendar: {
                sameDay: '[امروز ساعت] LT',
                nextDay: '[فردا ساعت] LT',
                nextWeek: 'dddd [ساعت] LT',
                lastDay: '[دیروز ساعت] LT',
                lastWeek: 'dddd [پیش] [ساعت] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'در %s',
                past: '%s پیش',
                s: 'چند ثانیه',
                ss: '%d ثانیه',
                m: 'یک دقیقه',
                mm: '%d دقیقه',
                h: 'یک ساعت',
                hh: '%d ساعت',
                d: 'یک روز',
                dd: '%d روز',
                M: 'یک ماه',
                MM: '%d ماه',
                y: 'یک سال',
                yy: '%d سال',
            },
            preparse: function (string) {
                return string
                    .replace(/[۰-۹]/g, function (match) {
                        return numberMap$5[match];
                    })
                    .replace(/،/g, ',');
            },
            postformat: function (string) {
                return string
                    .replace(/\d/g, function (match) {
                        return symbolMap$6[match];
                    })
                    .replace(/,/g, '،');
            },
            dayOfMonthOrdinalParse: /\d{1,2}م/,
            ordinal: '%dم',
            week: {
                dow: 6, // Saturday is the first day of the week.
                doy: 12, // The week that contains Jan 12th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(
                ' '
            ),
            numbersFuture = [
                'nolla',
                'yhden',
                'kahden',
                'kolmen',
                'neljän',
                'viiden',
                'kuuden',
                numbersPast[7],
                numbersPast[8],
                numbersPast[9],
            ];
        function translate$2(number, withoutSuffix, key, isFuture) {
            var result = '';
            switch (key) {
                case 's':
                    return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
                case 'ss':
                    result = isFuture ? 'sekunnin' : 'sekuntia';
                    break;
                case 'm':
                    return isFuture ? 'minuutin' : 'minuutti';
                case 'mm':
                    result = isFuture ? 'minuutin' : 'minuuttia';
                    break;
                case 'h':
                    return isFuture ? 'tunnin' : 'tunti';
                case 'hh':
                    result = isFuture ? 'tunnin' : 'tuntia';
                    break;
                case 'd':
                    return isFuture ? 'päivän' : 'päivä';
                case 'dd':
                    result = isFuture ? 'päivän' : 'päivää';
                    break;
                case 'M':
                    return isFuture ? 'kuukauden' : 'kuukausi';
                case 'MM':
                    result = isFuture ? 'kuukauden' : 'kuukautta';
                    break;
                case 'y':
                    return isFuture ? 'vuoden' : 'vuosi';
                case 'yy':
                    result = isFuture ? 'vuoden' : 'vuotta';
                    break;
            }
            result = verbalNumber(number, isFuture) + ' ' + result;
            return result;
        }
        function verbalNumber(number, isFuture) {
            return number < 10
                ? isFuture
                    ? numbersFuture[number]
                    : numbersPast[number]
                : number;
        }
    
        hooks.defineLocale('fi', {
            months: 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split(
                '_'
            ),
            monthsShort: 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split(
                '_'
            ),
            weekdays: 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split(
                '_'
            ),
            weekdaysShort: 'su_ma_ti_ke_to_pe_la'.split('_'),
            weekdaysMin: 'su_ma_ti_ke_to_pe_la'.split('_'),
            longDateFormat: {
                LT: 'HH.mm',
                LTS: 'HH.mm.ss',
                L: 'DD.MM.YYYY',
                LL: 'Do MMMM[ta] YYYY',
                LLL: 'Do MMMM[ta] YYYY, [klo] HH.mm',
                LLLL: 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm',
                l: 'D.M.YYYY',
                ll: 'Do MMM YYYY',
                lll: 'Do MMM YYYY, [klo] HH.mm',
                llll: 'ddd, Do MMM YYYY, [klo] HH.mm',
            },
            calendar: {
                sameDay: '[tänään] [klo] LT',
                nextDay: '[huomenna] [klo] LT',
                nextWeek: 'dddd [klo] LT',
                lastDay: '[eilen] [klo] LT',
                lastWeek: '[viime] dddd[na] [klo] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s päästä',
                past: '%s sitten',
                s: translate$2,
                ss: translate$2,
                m: translate$2,
                mm: translate$2,
                h: translate$2,
                hh: translate$2,
                d: translate$2,
                dd: translate$2,
                M: translate$2,
                MM: translate$2,
                y: translate$2,
                yy: translate$2,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('fil', {
            months: 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split(
                '_'
            ),
            monthsShort: 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'),
            weekdays: 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split(
                '_'
            ),
            weekdaysShort: 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'),
            weekdaysMin: 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'MM/D/YYYY',
                LL: 'MMMM D, YYYY',
                LLL: 'MMMM D, YYYY HH:mm',
                LLLL: 'dddd, MMMM DD, YYYY HH:mm',
            },
            calendar: {
                sameDay: 'LT [ngayong araw]',
                nextDay: '[Bukas ng] LT',
                nextWeek: 'LT [sa susunod na] dddd',
                lastDay: 'LT [kahapon]',
                lastWeek: 'LT [noong nakaraang] dddd',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'sa loob ng %s',
                past: '%s ang nakalipas',
                s: 'ilang segundo',
                ss: '%d segundo',
                m: 'isang minuto',
                mm: '%d minuto',
                h: 'isang oras',
                hh: '%d oras',
                d: 'isang araw',
                dd: '%d araw',
                M: 'isang buwan',
                MM: '%d buwan',
                y: 'isang taon',
                yy: '%d taon',
            },
            dayOfMonthOrdinalParse: /\d{1,2}/,
            ordinal: function (number) {
                return number;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('fo', {
            months: 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split(
                '_'
            ),
            monthsShort: 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
            weekdays: 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split(
                '_'
            ),
            weekdaysShort: 'sun_mán_týs_mik_hós_frí_ley'.split('_'),
            weekdaysMin: 'su_má_tý_mi_hó_fr_le'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D. MMMM, YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Í dag kl.] LT',
                nextDay: '[Í morgin kl.] LT',
                nextWeek: 'dddd [kl.] LT',
                lastDay: '[Í gjár kl.] LT',
                lastWeek: '[síðstu] dddd [kl] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'um %s',
                past: '%s síðani',
                s: 'fá sekund',
                ss: '%d sekundir',
                m: 'ein minuttur',
                mm: '%d minuttir',
                h: 'ein tími',
                hh: '%d tímar',
                d: 'ein dagur',
                dd: '%d dagar',
                M: 'ein mánaður',
                MM: '%d mánaðir',
                y: 'eitt ár',
                yy: '%d ár',
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('fr-ca', {
            months: 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split(
                '_'
            ),
            monthsShort: 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
            weekdaysShort: 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
            weekdaysMin: 'di_lu_ma_me_je_ve_sa'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY-MM-DD',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Aujourd’hui à] LT',
                nextDay: '[Demain à] LT',
                nextWeek: 'dddd [à] LT',
                lastDay: '[Hier à] LT',
                lastWeek: 'dddd [dernier à] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'dans %s',
                past: 'il y a %s',
                s: 'quelques secondes',
                ss: '%d secondes',
                m: 'une minute',
                mm: '%d minutes',
                h: 'une heure',
                hh: '%d heures',
                d: 'un jour',
                dd: '%d jours',
                M: 'un mois',
                MM: '%d mois',
                y: 'un an',
                yy: '%d ans',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(er|e)/,
            ordinal: function (number, period) {
                switch (period) {
                    // Words with masculine grammatical gender: mois, trimestre, jour
                    default:
                    case 'M':
                    case 'Q':
                    case 'D':
                    case 'DDD':
                    case 'd':
                        return number + (number === 1 ? 'er' : 'e');
    
                    // Words with feminine grammatical gender: semaine
                    case 'w':
                    case 'W':
                        return number + (number === 1 ? 're' : 'e');
                }
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('fr-ch', {
            months: 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split(
                '_'
            ),
            monthsShort: 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
            weekdaysShort: 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
            weekdaysMin: 'di_lu_ma_me_je_ve_sa'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Aujourd’hui à] LT',
                nextDay: '[Demain à] LT',
                nextWeek: 'dddd [à] LT',
                lastDay: '[Hier à] LT',
                lastWeek: 'dddd [dernier à] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'dans %s',
                past: 'il y a %s',
                s: 'quelques secondes',
                ss: '%d secondes',
                m: 'une minute',
                mm: '%d minutes',
                h: 'une heure',
                hh: '%d heures',
                d: 'un jour',
                dd: '%d jours',
                M: 'un mois',
                MM: '%d mois',
                y: 'un an',
                yy: '%d ans',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(er|e)/,
            ordinal: function (number, period) {
                switch (period) {
                    // Words with masculine grammatical gender: mois, trimestre, jour
                    default:
                    case 'M':
                    case 'Q':
                    case 'D':
                    case 'DDD':
                    case 'd':
                        return number + (number === 1 ? 'er' : 'e');
    
                    // Words with feminine grammatical gender: semaine
                    case 'w':
                    case 'W':
                        return number + (number === 1 ? 're' : 'e');
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var monthsStrictRegex$1 = /^(janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,
            monthsShortStrictRegex$1 = /(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?)/i,
            monthsRegex$7 = /(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?|janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,
            monthsParse$6 = [
                /^janv/i,
                /^févr/i,
                /^mars/i,
                /^avr/i,
                /^mai/i,
                /^juin/i,
                /^juil/i,
                /^août/i,
                /^sept/i,
                /^oct/i,
                /^nov/i,
                /^déc/i,
            ];
    
        hooks.defineLocale('fr', {
            months: 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split(
                '_'
            ),
            monthsShort: 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split(
                '_'
            ),
            monthsRegex: monthsRegex$7,
            monthsShortRegex: monthsRegex$7,
            monthsStrictRegex: monthsStrictRegex$1,
            monthsShortStrictRegex: monthsShortStrictRegex$1,
            monthsParse: monthsParse$6,
            longMonthsParse: monthsParse$6,
            shortMonthsParse: monthsParse$6,
            weekdays: 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
            weekdaysShort: 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
            weekdaysMin: 'di_lu_ma_me_je_ve_sa'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Aujourd’hui à] LT',
                nextDay: '[Demain à] LT',
                nextWeek: 'dddd [à] LT',
                lastDay: '[Hier à] LT',
                lastWeek: 'dddd [dernier à] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'dans %s',
                past: 'il y a %s',
                s: 'quelques secondes',
                ss: '%d secondes',
                m: 'une minute',
                mm: '%d minutes',
                h: 'une heure',
                hh: '%d heures',
                d: 'un jour',
                dd: '%d jours',
                w: 'une semaine',
                ww: '%d semaines',
                M: 'un mois',
                MM: '%d mois',
                y: 'un an',
                yy: '%d ans',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(er|)/,
            ordinal: function (number, period) {
                switch (period) {
                    // TODO: Return 'e' when day of month > 1. Move this case inside
                    // block for masculine words below.
                    // See https://github.com/moment/moment/issues/3375
                    case 'D':
                        return number + (number === 1 ? 'er' : '');
    
                    // Words with masculine grammatical gender: mois, trimestre, jour
                    default:
                    case 'M':
                    case 'Q':
                    case 'DDD':
                    case 'd':
                        return number + (number === 1 ? 'er' : 'e');
    
                    // Words with feminine grammatical gender: semaine
                    case 'w':
                    case 'W':
                        return number + (number === 1 ? 're' : 'e');
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split(
                '_'
            ),
            monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split(
                '_'
            );
    
        hooks.defineLocale('fy', {
            months: 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split(
                '_'
            ),
            monthsShort: function (m, format) {
                if (!m) {
                    return monthsShortWithDots;
                } else if (/-MMM-/.test(format)) {
                    return monthsShortWithoutDots[m.month()];
                } else {
                    return monthsShortWithDots[m.month()];
                }
            },
            monthsParseExact: true,
            weekdays: 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split(
                '_'
            ),
            weekdaysShort: 'si._mo._ti._wo._to._fr._so.'.split('_'),
            weekdaysMin: 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD-MM-YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[hjoed om] LT',
                nextDay: '[moarn om] LT',
                nextWeek: 'dddd [om] LT',
                lastDay: '[juster om] LT',
                lastWeek: '[ôfrûne] dddd [om] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'oer %s',
                past: '%s lyn',
                s: 'in pear sekonden',
                ss: '%d sekonden',
                m: 'ien minút',
                mm: '%d minuten',
                h: 'ien oere',
                hh: '%d oeren',
                d: 'ien dei',
                dd: '%d dagen',
                M: 'ien moanne',
                MM: '%d moannen',
                y: 'ien jier',
                yy: '%d jierren',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
            ordinal: function (number) {
                return (
                    number +
                    (number === 1 || number === 8 || number >= 20 ? 'ste' : 'de')
                );
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var months$6 = [
                'Eanáir',
                'Feabhra',
                'Márta',
                'Aibreán',
                'Bealtaine',
                'Meitheamh',
                'Iúil',
                'Lúnasa',
                'Meán Fómhair',
                'Deireadh Fómhair',
                'Samhain',
                'Nollaig',
            ],
            monthsShort$5 = [
                'Ean',
                'Feabh',
                'Márt',
                'Aib',
                'Beal',
                'Meith',
                'Iúil',
                'Lún',
                'M.F.',
                'D.F.',
                'Samh',
                'Noll',
            ],
            weekdays$1 = [
                'Dé Domhnaigh',
                'Dé Luain',
                'Dé Máirt',
                'Dé Céadaoin',
                'Déardaoin',
                'Dé hAoine',
                'Dé Sathairn',
            ],
            weekdaysShort = ['Domh', 'Luan', 'Máirt', 'Céad', 'Déar', 'Aoine', 'Sath'],
            weekdaysMin = ['Do', 'Lu', 'Má', 'Cé', 'Dé', 'A', 'Sa'];
    
        hooks.defineLocale('ga', {
            months: months$6,
            monthsShort: monthsShort$5,
            monthsParseExact: true,
            weekdays: weekdays$1,
            weekdaysShort: weekdaysShort,
            weekdaysMin: weekdaysMin,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Inniu ag] LT',
                nextDay: '[Amárach ag] LT',
                nextWeek: 'dddd [ag] LT',
                lastDay: '[Inné ag] LT',
                lastWeek: 'dddd [seo caite] [ag] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'i %s',
                past: '%s ó shin',
                s: 'cúpla soicind',
                ss: '%d soicind',
                m: 'nóiméad',
                mm: '%d nóiméad',
                h: 'uair an chloig',
                hh: '%d uair an chloig',
                d: 'lá',
                dd: '%d lá',
                M: 'mí',
                MM: '%d míonna',
                y: 'bliain',
                yy: '%d bliain',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(d|na|mh)/,
            ordinal: function (number) {
                var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var months$7 = [
                'Am Faoilleach',
                'An Gearran',
                'Am Màrt',
                'An Giblean',
                'An Cèitean',
                'An t-Ògmhios',
                'An t-Iuchar',
                'An Lùnastal',
                'An t-Sultain',
                'An Dàmhair',
                'An t-Samhain',
                'An Dùbhlachd',
            ],
            monthsShort$6 = [
                'Faoi',
                'Gear',
                'Màrt',
                'Gibl',
                'Cèit',
                'Ògmh',
                'Iuch',
                'Lùn',
                'Sult',
                'Dàmh',
                'Samh',
                'Dùbh',
            ],
            weekdays$2 = [
                'Didòmhnaich',
                'Diluain',
                'Dimàirt',
                'Diciadain',
                'Diardaoin',
                'Dihaoine',
                'Disathairne',
            ],
            weekdaysShort$1 = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'],
            weekdaysMin$1 = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'];
    
        hooks.defineLocale('gd', {
            months: months$7,
            monthsShort: monthsShort$6,
            monthsParseExact: true,
            weekdays: weekdays$2,
            weekdaysShort: weekdaysShort$1,
            weekdaysMin: weekdaysMin$1,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[An-diugh aig] LT',
                nextDay: '[A-màireach aig] LT',
                nextWeek: 'dddd [aig] LT',
                lastDay: '[An-dè aig] LT',
                lastWeek: 'dddd [seo chaidh] [aig] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'ann an %s',
                past: 'bho chionn %s',
                s: 'beagan diogan',
                ss: '%d diogan',
                m: 'mionaid',
                mm: '%d mionaidean',
                h: 'uair',
                hh: '%d uairean',
                d: 'latha',
                dd: '%d latha',
                M: 'mìos',
                MM: '%d mìosan',
                y: 'bliadhna',
                yy: '%d bliadhna',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(d|na|mh)/,
            ordinal: function (number) {
                var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('gl', {
            months: 'xaneiro_febreiro_marzo_abril_maio_xuño_xullo_agosto_setembro_outubro_novembro_decembro'.split(
                '_'
            ),
            monthsShort: 'xan._feb._mar._abr._mai._xuñ._xul._ago._set._out._nov._dec.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'domingo_luns_martes_mércores_xoves_venres_sábado'.split('_'),
            weekdaysShort: 'dom._lun._mar._mér._xov._ven._sáb.'.split('_'),
            weekdaysMin: 'do_lu_ma_mé_xo_ve_sá'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D [de] MMMM [de] YYYY',
                LLL: 'D [de] MMMM [de] YYYY H:mm',
                LLLL: 'dddd, D [de] MMMM [de] YYYY H:mm',
            },
            calendar: {
                sameDay: function () {
                    return '[hoxe ' + (this.hours() !== 1 ? 'ás' : 'á') + '] LT';
                },
                nextDay: function () {
                    return '[mañá ' + (this.hours() !== 1 ? 'ás' : 'á') + '] LT';
                },
                nextWeek: function () {
                    return 'dddd [' + (this.hours() !== 1 ? 'ás' : 'a') + '] LT';
                },
                lastDay: function () {
                    return '[onte ' + (this.hours() !== 1 ? 'á' : 'a') + '] LT';
                },
                lastWeek: function () {
                    return (
                        '[o] dddd [pasado ' + (this.hours() !== 1 ? 'ás' : 'a') + '] LT'
                    );
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: function (str) {
                    if (str.indexOf('un') === 0) {
                        return 'n' + str;
                    }
                    return 'en ' + str;
                },
                past: 'hai %s',
                s: 'uns segundos',
                ss: '%d segundos',
                m: 'un minuto',
                mm: '%d minutos',
                h: 'unha hora',
                hh: '%d horas',
                d: 'un día',
                dd: '%d días',
                M: 'un mes',
                MM: '%d meses',
                y: 'un ano',
                yy: '%d anos',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function processRelativeTime$4(number, withoutSuffix, key, isFuture) {
            var format = {
                s: ['थोडया सॅकंडांनी', 'थोडे सॅकंड'],
                ss: [number + ' सॅकंडांनी', number + ' सॅकंड'],
                m: ['एका मिणटान', 'एक मिनूट'],
                mm: [number + ' मिणटांनी', number + ' मिणटां'],
                h: ['एका वरान', 'एक वर'],
                hh: [number + ' वरांनी', number + ' वरां'],
                d: ['एका दिसान', 'एक दीस'],
                dd: [number + ' दिसांनी', number + ' दीस'],
                M: ['एका म्हयन्यान', 'एक म्हयनो'],
                MM: [number + ' म्हयन्यानी', number + ' म्हयने'],
                y: ['एका वर्सान', 'एक वर्स'],
                yy: [number + ' वर्सांनी', number + ' वर्सां'],
            };
            return isFuture ? format[key][0] : format[key][1];
        }
    
        hooks.defineLocale('gom-deva', {
            months: {
                standalone: 'जानेवारी_फेब्रुवारी_मार्च_एप्रील_मे_जून_जुलय_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split(
                    '_'
                ),
                format: 'जानेवारीच्या_फेब्रुवारीच्या_मार्चाच्या_एप्रीलाच्या_मेयाच्या_जूनाच्या_जुलयाच्या_ऑगस्टाच्या_सप्टेंबराच्या_ऑक्टोबराच्या_नोव्हेंबराच्या_डिसेंबराच्या'.split(
                    '_'
                ),
                isFormat: /MMMM(\s)+D[oD]?/,
            },
            monthsShort: 'जाने._फेब्रु._मार्च_एप्री._मे_जून_जुल._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'आयतार_सोमार_मंगळार_बुधवार_बिरेस्तार_सुक्रार_शेनवार'.split('_'),
            weekdaysShort: 'आयत._सोम._मंगळ._बुध._ब्रेस्त._सुक्र._शेन.'.split('_'),
            weekdaysMin: 'आ_सो_मं_बु_ब्रे_सु_शे'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'A h:mm [वाजतां]',
                LTS: 'A h:mm:ss [वाजतां]',
                L: 'DD-MM-YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY A h:mm [वाजतां]',
                LLLL: 'dddd, MMMM Do, YYYY, A h:mm [वाजतां]',
                llll: 'ddd, D MMM YYYY, A h:mm [वाजतां]',
            },
            calendar: {
                sameDay: '[आयज] LT',
                nextDay: '[फाल्यां] LT',
                nextWeek: '[फुडलो] dddd[,] LT',
                lastDay: '[काल] LT',
                lastWeek: '[फाटलो] dddd[,] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s',
                past: '%s आदीं',
                s: processRelativeTime$4,
                ss: processRelativeTime$4,
                m: processRelativeTime$4,
                mm: processRelativeTime$4,
                h: processRelativeTime$4,
                hh: processRelativeTime$4,
                d: processRelativeTime$4,
                dd: processRelativeTime$4,
                M: processRelativeTime$4,
                MM: processRelativeTime$4,
                y: processRelativeTime$4,
                yy: processRelativeTime$4,
            },
            dayOfMonthOrdinalParse: /\d{1,2}(वेर)/,
            ordinal: function (number, period) {
                switch (period) {
                    // the ordinal 'वेर' only applies to day of the month
                    case 'D':
                        return number + 'वेर';
                    default:
                    case 'M':
                    case 'Q':
                    case 'DDD':
                    case 'd':
                    case 'w':
                    case 'W':
                        return number;
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week
                doy: 3, // The week that contains Jan 4th is the first week of the year (7 + 0 - 4)
            },
            meridiemParse: /राती|सकाळीं|दनपारां|सांजे/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'राती') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'सकाळीं') {
                    return hour;
                } else if (meridiem === 'दनपारां') {
                    return hour > 12 ? hour : hour + 12;
                } else if (meridiem === 'सांजे') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'राती';
                } else if (hour < 12) {
                    return 'सकाळीं';
                } else if (hour < 16) {
                    return 'दनपारां';
                } else if (hour < 20) {
                    return 'सांजे';
                } else {
                    return 'राती';
                }
            },
        });
    
        //! moment.js locale configuration
    
        function processRelativeTime$5(number, withoutSuffix, key, isFuture) {
            var format = {
                s: ['thoddea sekondamni', 'thodde sekond'],
                ss: [number + ' sekondamni', number + ' sekond'],
                m: ['eka mintan', 'ek minut'],
                mm: [number + ' mintamni', number + ' mintam'],
                h: ['eka voran', 'ek vor'],
                hh: [number + ' voramni', number + ' voram'],
                d: ['eka disan', 'ek dis'],
                dd: [number + ' disamni', number + ' dis'],
                M: ['eka mhoinean', 'ek mhoino'],
                MM: [number + ' mhoineamni', number + ' mhoine'],
                y: ['eka vorsan', 'ek voros'],
                yy: [number + ' vorsamni', number + ' vorsam'],
            };
            return isFuture ? format[key][0] : format[key][1];
        }
    
        hooks.defineLocale('gom-latn', {
            months: {
                standalone: 'Janer_Febrer_Mars_Abril_Mai_Jun_Julai_Agost_Setembr_Otubr_Novembr_Dezembr'.split(
                    '_'
                ),
                format: 'Janerachea_Febrerachea_Marsachea_Abrilachea_Maiachea_Junachea_Julaiachea_Agostachea_Setembrachea_Otubrachea_Novembrachea_Dezembrachea'.split(
                    '_'
                ),
                isFormat: /MMMM(\s)+D[oD]?/,
            },
            monthsShort: 'Jan._Feb._Mars_Abr._Mai_Jun_Jul._Ago._Set._Otu._Nov._Dez.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: "Aitar_Somar_Mongllar_Budhvar_Birestar_Sukrar_Son'var".split('_'),
            weekdaysShort: 'Ait._Som._Mon._Bud._Bre._Suk._Son.'.split('_'),
            weekdaysMin: 'Ai_Sm_Mo_Bu_Br_Su_Sn'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'A h:mm [vazta]',
                LTS: 'A h:mm:ss [vazta]',
                L: 'DD-MM-YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY A h:mm [vazta]',
                LLLL: 'dddd, MMMM Do, YYYY, A h:mm [vazta]',
                llll: 'ddd, D MMM YYYY, A h:mm [vazta]',
            },
            calendar: {
                sameDay: '[Aiz] LT',
                nextDay: '[Faleam] LT',
                nextWeek: '[Fuddlo] dddd[,] LT',
                lastDay: '[Kal] LT',
                lastWeek: '[Fattlo] dddd[,] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s',
                past: '%s adim',
                s: processRelativeTime$5,
                ss: processRelativeTime$5,
                m: processRelativeTime$5,
                mm: processRelativeTime$5,
                h: processRelativeTime$5,
                hh: processRelativeTime$5,
                d: processRelativeTime$5,
                dd: processRelativeTime$5,
                M: processRelativeTime$5,
                MM: processRelativeTime$5,
                y: processRelativeTime$5,
                yy: processRelativeTime$5,
            },
            dayOfMonthOrdinalParse: /\d{1,2}(er)/,
            ordinal: function (number, period) {
                switch (period) {
                    // the ordinal 'er' only applies to day of the month
                    case 'D':
                        return number + 'er';
                    default:
                    case 'M':
                    case 'Q':
                    case 'DDD':
                    case 'd':
                    case 'w':
                    case 'W':
                        return number;
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week
                doy: 3, // The week that contains Jan 4th is the first week of the year (7 + 0 - 4)
            },
            meridiemParse: /rati|sokallim|donparam|sanje/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'rati') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'sokallim') {
                    return hour;
                } else if (meridiem === 'donparam') {
                    return hour > 12 ? hour : hour + 12;
                } else if (meridiem === 'sanje') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'rati';
                } else if (hour < 12) {
                    return 'sokallim';
                } else if (hour < 16) {
                    return 'donparam';
                } else if (hour < 20) {
                    return 'sanje';
                } else {
                    return 'rati';
                }
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$7 = {
                1: '૧',
                2: '૨',
                3: '૩',
                4: '૪',
                5: '૫',
                6: '૬',
                7: '૭',
                8: '૮',
                9: '૯',
                0: '૦',
            },
            numberMap$6 = {
                '૧': '1',
                '૨': '2',
                '૩': '3',
                '૪': '4',
                '૫': '5',
                '૬': '6',
                '૭': '7',
                '૮': '8',
                '૯': '9',
                '૦': '0',
            };
    
        hooks.defineLocale('gu', {
            months: 'જાન્યુઆરી_ફેબ્રુઆરી_માર્ચ_એપ્રિલ_મે_જૂન_જુલાઈ_ઑગસ્ટ_સપ્ટેમ્બર_ઑક્ટ્બર_નવેમ્બર_ડિસેમ્બર'.split(
                '_'
            ),
            monthsShort: 'જાન્યુ._ફેબ્રુ._માર્ચ_એપ્રિ._મે_જૂન_જુલા._ઑગ._સપ્ટે._ઑક્ટ્._નવે._ડિસે.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'રવિવાર_સોમવાર_મંગળવાર_બુધ્વાર_ગુરુવાર_શુક્રવાર_શનિવાર'.split(
                '_'
            ),
            weekdaysShort: 'રવિ_સોમ_મંગળ_બુધ્_ગુરુ_શુક્ર_શનિ'.split('_'),
            weekdaysMin: 'ર_સો_મં_બુ_ગુ_શુ_શ'.split('_'),
            longDateFormat: {
                LT: 'A h:mm વાગ્યે',
                LTS: 'A h:mm:ss વાગ્યે',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm વાગ્યે',
                LLLL: 'dddd, D MMMM YYYY, A h:mm વાગ્યે',
            },
            calendar: {
                sameDay: '[આજ] LT',
                nextDay: '[કાલે] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[ગઇકાલે] LT',
                lastWeek: '[પાછલા] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s મા',
                past: '%s પહેલા',
                s: 'અમુક પળો',
                ss: '%d સેકંડ',
                m: 'એક મિનિટ',
                mm: '%d મિનિટ',
                h: 'એક કલાક',
                hh: '%d કલાક',
                d: 'એક દિવસ',
                dd: '%d દિવસ',
                M: 'એક મહિનો',
                MM: '%d મહિનો',
                y: 'એક વર્ષ',
                yy: '%d વર્ષ',
            },
            preparse: function (string) {
                return string.replace(/[૧૨૩૪૫૬૭૮૯૦]/g, function (match) {
                    return numberMap$6[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$7[match];
                });
            },
            // Gujarati notation for meridiems are quite fuzzy in practice. While there exists
            // a rigid notion of a 'Pahar' it is not used as rigidly in modern Gujarati.
            meridiemParse: /રાત|બપોર|સવાર|સાંજ/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'રાત') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'સવાર') {
                    return hour;
                } else if (meridiem === 'બપોર') {
                    return hour >= 10 ? hour : hour + 12;
                } else if (meridiem === 'સાંજ') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'રાત';
                } else if (hour < 10) {
                    return 'સવાર';
                } else if (hour < 17) {
                    return 'બપોર';
                } else if (hour < 20) {
                    return 'સાંજ';
                } else {
                    return 'રાત';
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('he', {
            months: 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split(
                '_'
            ),
            monthsShort: 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split(
                '_'
            ),
            weekdays: 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
            weekdaysShort: 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'),
            weekdaysMin: 'א_ב_ג_ד_ה_ו_ש'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D [ב]MMMM YYYY',
                LLL: 'D [ב]MMMM YYYY HH:mm',
                LLLL: 'dddd, D [ב]MMMM YYYY HH:mm',
                l: 'D/M/YYYY',
                ll: 'D MMM YYYY',
                lll: 'D MMM YYYY HH:mm',
                llll: 'ddd, D MMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[היום ב־]LT',
                nextDay: '[מחר ב־]LT',
                nextWeek: 'dddd [בשעה] LT',
                lastDay: '[אתמול ב־]LT',
                lastWeek: '[ביום] dddd [האחרון בשעה] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'בעוד %s',
                past: 'לפני %s',
                s: 'מספר שניות',
                ss: '%d שניות',
                m: 'דקה',
                mm: '%d דקות',
                h: 'שעה',
                hh: function (number) {
                    if (number === 2) {
                        return 'שעתיים';
                    }
                    return number + ' שעות';
                },
                d: 'יום',
                dd: function (number) {
                    if (number === 2) {
                        return 'יומיים';
                    }
                    return number + ' ימים';
                },
                M: 'חודש',
                MM: function (number) {
                    if (number === 2) {
                        return 'חודשיים';
                    }
                    return number + ' חודשים';
                },
                y: 'שנה',
                yy: function (number) {
                    if (number === 2) {
                        return 'שנתיים';
                    } else if (number % 10 === 0 && number !== 10) {
                        return number + ' שנה';
                    }
                    return number + ' שנים';
                },
            },
            meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,
            isPM: function (input) {
                return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input);
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 5) {
                    return 'לפנות בוקר';
                } else if (hour < 10) {
                    return 'בבוקר';
                } else if (hour < 12) {
                    return isLower ? 'לפנה"צ' : 'לפני הצהריים';
                } else if (hour < 18) {
                    return isLower ? 'אחה"צ' : 'אחרי הצהריים';
                } else {
                    return 'בערב';
                }
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$8 = {
                1: '१',
                2: '२',
                3: '३',
                4: '४',
                5: '५',
                6: '६',
                7: '७',
                8: '८',
                9: '९',
                0: '०',
            },
            numberMap$7 = {
                '१': '1',
                '२': '2',
                '३': '3',
                '४': '4',
                '५': '5',
                '६': '6',
                '७': '7',
                '८': '8',
                '९': '9',
                '०': '0',
            },
            monthsParse$7 = [
                /^जन/i,
                /^फ़र|फर/i,
                /^मार्च/i,
                /^अप्रै/i,
                /^मई/i,
                /^जून/i,
                /^जुल/i,
                /^अग/i,
                /^सितं|सित/i,
                /^अक्टू/i,
                /^नव|नवं/i,
                /^दिसं|दिस/i,
            ],
            shortMonthsParse = [
                /^जन/i,
                /^फ़र/i,
                /^मार्च/i,
                /^अप्रै/i,
                /^मई/i,
                /^जून/i,
                /^जुल/i,
                /^अग/i,
                /^सित/i,
                /^अक्टू/i,
                /^नव/i,
                /^दिस/i,
            ];
    
        hooks.defineLocale('hi', {
            months: {
                format: 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split(
                    '_'
                ),
                standalone: 'जनवरी_फरवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितंबर_अक्टूबर_नवंबर_दिसंबर'.split(
                    '_'
                ),
            },
            monthsShort: 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split(
                '_'
            ),
            weekdays: 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
            weekdaysShort: 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'),
            weekdaysMin: 'र_सो_मं_बु_गु_शु_श'.split('_'),
            longDateFormat: {
                LT: 'A h:mm बजे',
                LTS: 'A h:mm:ss बजे',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm बजे',
                LLLL: 'dddd, D MMMM YYYY, A h:mm बजे',
            },
    
            monthsParse: monthsParse$7,
            longMonthsParse: monthsParse$7,
            shortMonthsParse: shortMonthsParse,
    
            monthsRegex: /^(जनवरी|जन\.?|फ़रवरी|फरवरी|फ़र\.?|मार्च?|अप्रैल|अप्रै\.?|मई?|जून?|जुलाई|जुल\.?|अगस्त|अग\.?|सितम्बर|सितंबर|सित\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर|नव\.?|दिसम्बर|दिसंबर|दिस\.?)/i,
    
            monthsShortRegex: /^(जनवरी|जन\.?|फ़रवरी|फरवरी|फ़र\.?|मार्च?|अप्रैल|अप्रै\.?|मई?|जून?|जुलाई|जुल\.?|अगस्त|अग\.?|सितम्बर|सितंबर|सित\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर|नव\.?|दिसम्बर|दिसंबर|दिस\.?)/i,
    
            monthsStrictRegex: /^(जनवरी?|फ़रवरी|फरवरी?|मार्च?|अप्रैल?|मई?|जून?|जुलाई?|अगस्त?|सितम्बर|सितंबर|सित?\.?|अक्टूबर|अक्टू\.?|नवम्बर|नवंबर?|दिसम्बर|दिसंबर?)/i,
    
            monthsShortStrictRegex: /^(जन\.?|फ़र\.?|मार्च?|अप्रै\.?|मई?|जून?|जुल\.?|अग\.?|सित\.?|अक्टू\.?|नव\.?|दिस\.?)/i,
    
            calendar: {
                sameDay: '[आज] LT',
                nextDay: '[कल] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[कल] LT',
                lastWeek: '[पिछले] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s में',
                past: '%s पहले',
                s: 'कुछ ही क्षण',
                ss: '%d सेकंड',
                m: 'एक मिनट',
                mm: '%d मिनट',
                h: 'एक घंटा',
                hh: '%d घंटे',
                d: 'एक दिन',
                dd: '%d दिन',
                M: 'एक महीने',
                MM: '%d महीने',
                y: 'एक वर्ष',
                yy: '%d वर्ष',
            },
            preparse: function (string) {
                return string.replace(/[१२३४५६७८९०]/g, function (match) {
                    return numberMap$7[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$8[match];
                });
            },
            // Hindi notation for meridiems are quite fuzzy in practice. While there exists
            // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
            meridiemParse: /रात|सुबह|दोपहर|शाम/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'रात') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'सुबह') {
                    return hour;
                } else if (meridiem === 'दोपहर') {
                    return hour >= 10 ? hour : hour + 12;
                } else if (meridiem === 'शाम') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'रात';
                } else if (hour < 10) {
                    return 'सुबह';
                } else if (hour < 17) {
                    return 'दोपहर';
                } else if (hour < 20) {
                    return 'शाम';
                } else {
                    return 'रात';
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function translate$3(number, withoutSuffix, key) {
            var result = number + ' ';
            switch (key) {
                case 'ss':
                    if (number === 1) {
                        result += 'sekunda';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'sekunde';
                    } else {
                        result += 'sekundi';
                    }
                    return result;
                case 'm':
                    return withoutSuffix ? 'jedna minuta' : 'jedne minute';
                case 'mm':
                    if (number === 1) {
                        result += 'minuta';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'minute';
                    } else {
                        result += 'minuta';
                    }
                    return result;
                case 'h':
                    return withoutSuffix ? 'jedan sat' : 'jednog sata';
                case 'hh':
                    if (number === 1) {
                        result += 'sat';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'sata';
                    } else {
                        result += 'sati';
                    }
                    return result;
                case 'dd':
                    if (number === 1) {
                        result += 'dan';
                    } else {
                        result += 'dana';
                    }
                    return result;
                case 'MM':
                    if (number === 1) {
                        result += 'mjesec';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'mjeseca';
                    } else {
                        result += 'mjeseci';
                    }
                    return result;
                case 'yy':
                    if (number === 1) {
                        result += 'godina';
                    } else if (number === 2 || number === 3 || number === 4) {
                        result += 'godine';
                    } else {
                        result += 'godina';
                    }
                    return result;
            }
        }
    
        hooks.defineLocale('hr', {
            months: {
                format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split(
                    '_'
                ),
                standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split(
                    '_'
                ),
            },
            monthsShort: 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split(
                '_'
            ),
            weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
            weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'Do MMMM YYYY',
                LLL: 'Do MMMM YYYY H:mm',
                LLLL: 'dddd, Do MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[danas u] LT',
                nextDay: '[sutra u] LT',
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[u] [nedjelju] [u] LT';
                        case 3:
                            return '[u] [srijedu] [u] LT';
                        case 6:
                            return '[u] [subotu] [u] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[u] dddd [u] LT';
                    }
                },
                lastDay: '[jučer u] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[prošlu] [nedjelju] [u] LT';
                        case 3:
                            return '[prošlu] [srijedu] [u] LT';
                        case 6:
                            return '[prošle] [subote] [u] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[prošli] dddd [u] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'za %s',
                past: 'prije %s',
                s: 'par sekundi',
                ss: translate$3,
                m: translate$3,
                mm: translate$3,
                h: translate$3,
                hh: translate$3,
                d: 'dan',
                dd: translate$3,
                M: 'mjesec',
                MM: translate$3,
                y: 'godinu',
                yy: translate$3,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(
            ' '
        );
        function translate$4(number, withoutSuffix, key, isFuture) {
            var num = number;
            switch (key) {
                case 's':
                    return isFuture || withoutSuffix
                        ? 'néhány másodperc'
                        : 'néhány másodperce';
                case 'ss':
                    return num + (isFuture || withoutSuffix)
                        ? ' másodperc'
                        : ' másodperce';
                case 'm':
                    return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
                case 'mm':
                    return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
                case 'h':
                    return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
                case 'hh':
                    return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
                case 'd':
                    return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
                case 'dd':
                    return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
                case 'M':
                    return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
                case 'MM':
                    return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
                case 'y':
                    return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
                case 'yy':
                    return num + (isFuture || withoutSuffix ? ' év' : ' éve');
            }
            return '';
        }
        function week(isFuture) {
            return (
                (isFuture ? '' : '[múlt] ') +
                '[' +
                weekEndings[this.day()] +
                '] LT[-kor]'
            );
        }
    
        hooks.defineLocale('hu', {
            months: 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split(
                '_'
            ),
            monthsShort: 'jan._feb._márc._ápr._máj._jún._júl._aug._szept._okt._nov._dec.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'),
            weekdaysShort: 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'),
            weekdaysMin: 'v_h_k_sze_cs_p_szo'.split('_'),
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'YYYY.MM.DD.',
                LL: 'YYYY. MMMM D.',
                LLL: 'YYYY. MMMM D. H:mm',
                LLLL: 'YYYY. MMMM D., dddd H:mm',
            },
            meridiemParse: /de|du/i,
            isPM: function (input) {
                return input.charAt(1).toLowerCase() === 'u';
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours < 12) {
                    return isLower === true ? 'de' : 'DE';
                } else {
                    return isLower === true ? 'du' : 'DU';
                }
            },
            calendar: {
                sameDay: '[ma] LT[-kor]',
                nextDay: '[holnap] LT[-kor]',
                nextWeek: function () {
                    return week.call(this, true);
                },
                lastDay: '[tegnap] LT[-kor]',
                lastWeek: function () {
                    return week.call(this, false);
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s múlva',
                past: '%s',
                s: translate$4,
                ss: translate$4,
                m: translate$4,
                mm: translate$4,
                h: translate$4,
                hh: translate$4,
                d: translate$4,
                dd: translate$4,
                M: translate$4,
                MM: translate$4,
                y: translate$4,
                yy: translate$4,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('hy-am', {
            months: {
                format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split(
                    '_'
                ),
                standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split(
                    '_'
                ),
            },
            monthsShort: 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'),
            weekdays: 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split(
                '_'
            ),
            weekdaysShort: 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
            weekdaysMin: 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY թ.',
                LLL: 'D MMMM YYYY թ., HH:mm',
                LLLL: 'dddd, D MMMM YYYY թ., HH:mm',
            },
            calendar: {
                sameDay: '[այսօր] LT',
                nextDay: '[վաղը] LT',
                lastDay: '[երեկ] LT',
                nextWeek: function () {
                    return 'dddd [օրը ժամը] LT';
                },
                lastWeek: function () {
                    return '[անցած] dddd [օրը ժամը] LT';
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s հետո',
                past: '%s առաջ',
                s: 'մի քանի վայրկյան',
                ss: '%d վայրկյան',
                m: 'րոպե',
                mm: '%d րոպե',
                h: 'ժամ',
                hh: '%d ժամ',
                d: 'օր',
                dd: '%d օր',
                M: 'ամիս',
                MM: '%d ամիս',
                y: 'տարի',
                yy: '%d տարի',
            },
            meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,
            isPM: function (input) {
                return /^(ցերեկվա|երեկոյան)$/.test(input);
            },
            meridiem: function (hour) {
                if (hour < 4) {
                    return 'գիշերվա';
                } else if (hour < 12) {
                    return 'առավոտվա';
                } else if (hour < 17) {
                    return 'ցերեկվա';
                } else {
                    return 'երեկոյան';
                }
            },
            dayOfMonthOrdinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'DDD':
                    case 'w':
                    case 'W':
                    case 'DDDo':
                        if (number === 1) {
                            return number + '-ին';
                        }
                        return number + '-րդ';
                    default:
                        return number;
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('id', {
            months: 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Agt_Sep_Okt_Nov_Des'.split('_'),
            weekdays: 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'),
            weekdaysShort: 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'),
            weekdaysMin: 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
            longDateFormat: {
                LT: 'HH.mm',
                LTS: 'HH.mm.ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY [pukul] HH.mm',
                LLLL: 'dddd, D MMMM YYYY [pukul] HH.mm',
            },
            meridiemParse: /pagi|siang|sore|malam/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'pagi') {
                    return hour;
                } else if (meridiem === 'siang') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === 'sore' || meridiem === 'malam') {
                    return hour + 12;
                }
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours < 11) {
                    return 'pagi';
                } else if (hours < 15) {
                    return 'siang';
                } else if (hours < 19) {
                    return 'sore';
                } else {
                    return 'malam';
                }
            },
            calendar: {
                sameDay: '[Hari ini pukul] LT',
                nextDay: '[Besok pukul] LT',
                nextWeek: 'dddd [pukul] LT',
                lastDay: '[Kemarin pukul] LT',
                lastWeek: 'dddd [lalu pukul] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'dalam %s',
                past: '%s yang lalu',
                s: 'beberapa detik',
                ss: '%d detik',
                m: 'semenit',
                mm: '%d menit',
                h: 'sejam',
                hh: '%d jam',
                d: 'sehari',
                dd: '%d hari',
                M: 'sebulan',
                MM: '%d bulan',
                y: 'setahun',
                yy: '%d tahun',
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function plural$2(n) {
            if (n % 100 === 11) {
                return true;
            } else if (n % 10 === 1) {
                return false;
            }
            return true;
        }
        function translate$5(number, withoutSuffix, key, isFuture) {
            var result = number + ' ';
            switch (key) {
                case 's':
                    return withoutSuffix || isFuture
                        ? 'nokkrar sekúndur'
                        : 'nokkrum sekúndum';
                case 'ss':
                    if (plural$2(number)) {
                        return (
                            result +
                            (withoutSuffix || isFuture ? 'sekúndur' : 'sekúndum')
                        );
                    }
                    return result + 'sekúnda';
                case 'm':
                    return withoutSuffix ? 'mínúta' : 'mínútu';
                case 'mm':
                    if (plural$2(number)) {
                        return (
                            result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum')
                        );
                    } else if (withoutSuffix) {
                        return result + 'mínúta';
                    }
                    return result + 'mínútu';
                case 'hh':
                    if (plural$2(number)) {
                        return (
                            result +
                            (withoutSuffix || isFuture
                                ? 'klukkustundir'
                                : 'klukkustundum')
                        );
                    }
                    return result + 'klukkustund';
                case 'd':
                    if (withoutSuffix) {
                        return 'dagur';
                    }
                    return isFuture ? 'dag' : 'degi';
                case 'dd':
                    if (plural$2(number)) {
                        if (withoutSuffix) {
                            return result + 'dagar';
                        }
                        return result + (isFuture ? 'daga' : 'dögum');
                    } else if (withoutSuffix) {
                        return result + 'dagur';
                    }
                    return result + (isFuture ? 'dag' : 'degi');
                case 'M':
                    if (withoutSuffix) {
                        return 'mánuður';
                    }
                    return isFuture ? 'mánuð' : 'mánuði';
                case 'MM':
                    if (plural$2(number)) {
                        if (withoutSuffix) {
                            return result + 'mánuðir';
                        }
                        return result + (isFuture ? 'mánuði' : 'mánuðum');
                    } else if (withoutSuffix) {
                        return result + 'mánuður';
                    }
                    return result + (isFuture ? 'mánuð' : 'mánuði');
                case 'y':
                    return withoutSuffix || isFuture ? 'ár' : 'ári';
                case 'yy':
                    if (plural$2(number)) {
                        return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
                    }
                    return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
            }
        }
    
        hooks.defineLocale('is', {
            months: 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split(
                '_'
            ),
            monthsShort: 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'),
            weekdays: 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split(
                '_'
            ),
            weekdaysShort: 'sun_mán_þri_mið_fim_fös_lau'.split('_'),
            weekdaysMin: 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'),
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY [kl.] H:mm',
                LLLL: 'dddd, D. MMMM YYYY [kl.] H:mm',
            },
            calendar: {
                sameDay: '[í dag kl.] LT',
                nextDay: '[á morgun kl.] LT',
                nextWeek: 'dddd [kl.] LT',
                lastDay: '[í gær kl.] LT',
                lastWeek: '[síðasta] dddd [kl.] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'eftir %s',
                past: 'fyrir %s síðan',
                s: translate$5,
                ss: translate$5,
                m: translate$5,
                mm: translate$5,
                h: 'klukkustund',
                hh: translate$5,
                d: translate$5,
                dd: translate$5,
                M: translate$5,
                MM: translate$5,
                y: translate$5,
                yy: translate$5,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('it-ch', {
            months: 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split(
                '_'
            ),
            monthsShort: 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
            weekdays: 'domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato'.split(
                '_'
            ),
            weekdaysShort: 'dom_lun_mar_mer_gio_ven_sab'.split('_'),
            weekdaysMin: 'do_lu_ma_me_gi_ve_sa'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Oggi alle] LT',
                nextDay: '[Domani alle] LT',
                nextWeek: 'dddd [alle] LT',
                lastDay: '[Ieri alle] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[la scorsa] dddd [alle] LT';
                        default:
                            return '[lo scorso] dddd [alle] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: function (s) {
                    return (/^[0-9].+$/.test(s) ? 'tra' : 'in') + ' ' + s;
                },
                past: '%s fa',
                s: 'alcuni secondi',
                ss: '%d secondi',
                m: 'un minuto',
                mm: '%d minuti',
                h: "un'ora",
                hh: '%d ore',
                d: 'un giorno',
                dd: '%d giorni',
                M: 'un mese',
                MM: '%d mesi',
                y: 'un anno',
                yy: '%d anni',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('it', {
            months: 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split(
                '_'
            ),
            monthsShort: 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
            weekdays: 'domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato'.split(
                '_'
            ),
            weekdaysShort: 'dom_lun_mar_mer_gio_ven_sab'.split('_'),
            weekdaysMin: 'do_lu_ma_me_gi_ve_sa'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: function () {
                    return (
                        '[Oggi a' +
                        (this.hours() > 1 ? 'lle ' : this.hours() === 0 ? ' ' : "ll'") +
                        ']LT'
                    );
                },
                nextDay: function () {
                    return (
                        '[Domani a' +
                        (this.hours() > 1 ? 'lle ' : this.hours() === 0 ? ' ' : "ll'") +
                        ']LT'
                    );
                },
                nextWeek: function () {
                    return (
                        'dddd [a' +
                        (this.hours() > 1 ? 'lle ' : this.hours() === 0 ? ' ' : "ll'") +
                        ']LT'
                    );
                },
                lastDay: function () {
                    return (
                        '[Ieri a' +
                        (this.hours() > 1 ? 'lle ' : this.hours() === 0 ? ' ' : "ll'") +
                        ']LT'
                    );
                },
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return (
                                '[La scorsa] dddd [a' +
                                (this.hours() > 1
                                    ? 'lle '
                                    : this.hours() === 0
                                    ? ' '
                                    : "ll'") +
                                ']LT'
                            );
                        default:
                            return (
                                '[Lo scorso] dddd [a' +
                                (this.hours() > 1
                                    ? 'lle '
                                    : this.hours() === 0
                                    ? ' '
                                    : "ll'") +
                                ']LT'
                            );
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'tra %s',
                past: '%s fa',
                s: 'alcuni secondi',
                ss: '%d secondi',
                m: 'un minuto',
                mm: '%d minuti',
                h: "un'ora",
                hh: '%d ore',
                d: 'un giorno',
                dd: '%d giorni',
                w: 'una settimana',
                ww: '%d settimane',
                M: 'un mese',
                MM: '%d mesi',
                y: 'un anno',
                yy: '%d anni',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ja', {
            eras: [
                {
                    since: '2019-05-01',
                    offset: 1,
                    name: '令和',
                    narrow: '㋿',
                    abbr: 'R',
                },
                {
                    since: '1989-01-08',
                    until: '2019-04-30',
                    offset: 1,
                    name: '平成',
                    narrow: '㍻',
                    abbr: 'H',
                },
                {
                    since: '1926-12-25',
                    until: '1989-01-07',
                    offset: 1,
                    name: '昭和',
                    narrow: '㍼',
                    abbr: 'S',
                },
                {
                    since: '1912-07-30',
                    until: '1926-12-24',
                    offset: 1,
                    name: '大正',
                    narrow: '㍽',
                    abbr: 'T',
                },
                {
                    since: '1873-01-01',
                    until: '1912-07-29',
                    offset: 6,
                    name: '明治',
                    narrow: '㍾',
                    abbr: 'M',
                },
                {
                    since: '0001-01-01',
                    until: '1873-12-31',
                    offset: 1,
                    name: '西暦',
                    narrow: 'AD',
                    abbr: 'AD',
                },
                {
                    since: '0000-12-31',
                    until: -Infinity,
                    offset: 1,
                    name: '紀元前',
                    narrow: 'BC',
                    abbr: 'BC',
                },
            ],
            eraYearOrdinalRegex: /(元|\d+)年/,
            eraYearOrdinalParse: function (input, match) {
                return match[1] === '元' ? 1 : parseInt(match[1] || input, 10);
            },
            months: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
            monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split(
                '_'
            ),
            weekdays: '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
            weekdaysShort: '日_月_火_水_木_金_土'.split('_'),
            weekdaysMin: '日_月_火_水_木_金_土'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY/MM/DD',
                LL: 'YYYY年M月D日',
                LLL: 'YYYY年M月D日 HH:mm',
                LLLL: 'YYYY年M月D日 dddd HH:mm',
                l: 'YYYY/MM/DD',
                ll: 'YYYY年M月D日',
                lll: 'YYYY年M月D日 HH:mm',
                llll: 'YYYY年M月D日(ddd) HH:mm',
            },
            meridiemParse: /午前|午後/i,
            isPM: function (input) {
                return input === '午後';
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return '午前';
                } else {
                    return '午後';
                }
            },
            calendar: {
                sameDay: '[今日] LT',
                nextDay: '[明日] LT',
                nextWeek: function (now) {
                    if (now.week() !== this.week()) {
                        return '[来週]dddd LT';
                    } else {
                        return 'dddd LT';
                    }
                },
                lastDay: '[昨日] LT',
                lastWeek: function (now) {
                    if (this.week() !== now.week()) {
                        return '[先週]dddd LT';
                    } else {
                        return 'dddd LT';
                    }
                },
                sameElse: 'L',
            },
            dayOfMonthOrdinalParse: /\d{1,2}日/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'y':
                        return number === 1 ? '元年' : number + '年';
                    case 'd':
                    case 'D':
                    case 'DDD':
                        return number + '日';
                    default:
                        return number;
                }
            },
            relativeTime: {
                future: '%s後',
                past: '%s前',
                s: '数秒',
                ss: '%d秒',
                m: '1分',
                mm: '%d分',
                h: '1時間',
                hh: '%d時間',
                d: '1日',
                dd: '%d日',
                M: '1ヶ月',
                MM: '%dヶ月',
                y: '1年',
                yy: '%d年',
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('jv', {
            months: 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'),
            weekdays: 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'),
            weekdaysShort: 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'),
            weekdaysMin: 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'),
            longDateFormat: {
                LT: 'HH.mm',
                LTS: 'HH.mm.ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY [pukul] HH.mm',
                LLLL: 'dddd, D MMMM YYYY [pukul] HH.mm',
            },
            meridiemParse: /enjing|siyang|sonten|ndalu/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'enjing') {
                    return hour;
                } else if (meridiem === 'siyang') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === 'sonten' || meridiem === 'ndalu') {
                    return hour + 12;
                }
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours < 11) {
                    return 'enjing';
                } else if (hours < 15) {
                    return 'siyang';
                } else if (hours < 19) {
                    return 'sonten';
                } else {
                    return 'ndalu';
                }
            },
            calendar: {
                sameDay: '[Dinten puniko pukul] LT',
                nextDay: '[Mbenjang pukul] LT',
                nextWeek: 'dddd [pukul] LT',
                lastDay: '[Kala wingi pukul] LT',
                lastWeek: 'dddd [kepengker pukul] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'wonten ing %s',
                past: '%s ingkang kepengker',
                s: 'sawetawis detik',
                ss: '%d detik',
                m: 'setunggal menit',
                mm: '%d menit',
                h: 'setunggal jam',
                hh: '%d jam',
                d: 'sedinten',
                dd: '%d dinten',
                M: 'sewulan',
                MM: '%d wulan',
                y: 'setaun',
                yy: '%d taun',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ka', {
            months: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split(
                '_'
            ),
            monthsShort: 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'),
            weekdays: {
                standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split(
                    '_'
                ),
                format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split(
                    '_'
                ),
                isFormat: /(წინა|შემდეგ)/,
            },
            weekdaysShort: 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'),
            weekdaysMin: 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[დღეს] LT[-ზე]',
                nextDay: '[ხვალ] LT[-ზე]',
                lastDay: '[გუშინ] LT[-ზე]',
                nextWeek: '[შემდეგ] dddd LT[-ზე]',
                lastWeek: '[წინა] dddd LT-ზე',
                sameElse: 'L',
            },
            relativeTime: {
                future: function (s) {
                    return s.replace(/(წამ|წუთ|საათ|წელ|დღ|თვ)(ი|ე)/, function (
                        $0,
                        $1,
                        $2
                    ) {
                        return $2 === 'ი' ? $1 + 'ში' : $1 + $2 + 'ში';
                    });
                },
                past: function (s) {
                    if (/(წამი|წუთი|საათი|დღე|თვე)/.test(s)) {
                        return s.replace(/(ი|ე)$/, 'ის წინ');
                    }
                    if (/წელი/.test(s)) {
                        return s.replace(/წელი$/, 'წლის წინ');
                    }
                    return s;
                },
                s: 'რამდენიმე წამი',
                ss: '%d წამი',
                m: 'წუთი',
                mm: '%d წუთი',
                h: 'საათი',
                hh: '%d საათი',
                d: 'დღე',
                dd: '%d დღე',
                M: 'თვე',
                MM: '%d თვე',
                y: 'წელი',
                yy: '%d წელი',
            },
            dayOfMonthOrdinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,
            ordinal: function (number) {
                if (number === 0) {
                    return number;
                }
                if (number === 1) {
                    return number + '-ლი';
                }
                if (
                    number < 20 ||
                    (number <= 100 && number % 20 === 0) ||
                    number % 100 === 0
                ) {
                    return 'მე-' + number;
                }
                return number + '-ე';
            },
            week: {
                dow: 1,
                doy: 7,
            },
        });
    
        //! moment.js locale configuration
    
        var suffixes$1 = {
            0: '-ші',
            1: '-ші',
            2: '-ші',
            3: '-ші',
            4: '-ші',
            5: '-ші',
            6: '-шы',
            7: '-ші',
            8: '-ші',
            9: '-шы',
            10: '-шы',
            20: '-шы',
            30: '-шы',
            40: '-шы',
            50: '-ші',
            60: '-шы',
            70: '-ші',
            80: '-ші',
            90: '-шы',
            100: '-ші',
        };
    
        hooks.defineLocale('kk', {
            months: 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split(
                '_'
            ),
            monthsShort: 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'),
            weekdays: 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split(
                '_'
            ),
            weekdaysShort: 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'),
            weekdaysMin: 'жк_дй_сй_ср_бй_жм_сн'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Бүгін сағат] LT',
                nextDay: '[Ертең сағат] LT',
                nextWeek: 'dddd [сағат] LT',
                lastDay: '[Кеше сағат] LT',
                lastWeek: '[Өткен аптаның] dddd [сағат] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s ішінде',
                past: '%s бұрын',
                s: 'бірнеше секунд',
                ss: '%d секунд',
                m: 'бір минут',
                mm: '%d минут',
                h: 'бір сағат',
                hh: '%d сағат',
                d: 'бір күн',
                dd: '%d күн',
                M: 'бір ай',
                MM: '%d ай',
                y: 'бір жыл',
                yy: '%d жыл',
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(ші|шы)/,
            ordinal: function (number) {
                var a = number % 10,
                    b = number >= 100 ? 100 : null;
                return number + (suffixes$1[number] || suffixes$1[a] || suffixes$1[b]);
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$9 = {
                1: '១',
                2: '២',
                3: '៣',
                4: '៤',
                5: '៥',
                6: '៦',
                7: '៧',
                8: '៨',
                9: '៩',
                0: '០',
            },
            numberMap$8 = {
                '១': '1',
                '២': '2',
                '៣': '3',
                '៤': '4',
                '៥': '5',
                '៦': '6',
                '៧': '7',
                '៨': '8',
                '៩': '9',
                '០': '0',
            };
    
        hooks.defineLocale('km', {
            months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split(
                '_'
            ),
            monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split(
                '_'
            ),
            weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
            weekdaysShort: 'អា_ច_អ_ព_ព្រ_សុ_ស'.split('_'),
            weekdaysMin: 'អា_ច_អ_ព_ព្រ_សុ_ស'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            meridiemParse: /ព្រឹក|ល្ងាច/,
            isPM: function (input) {
                return input === 'ល្ងាច';
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'ព្រឹក';
                } else {
                    return 'ល្ងាច';
                }
            },
            calendar: {
                sameDay: '[ថ្ងៃនេះ ម៉ោង] LT',
                nextDay: '[ស្អែក ម៉ោង] LT',
                nextWeek: 'dddd [ម៉ោង] LT',
                lastDay: '[ម្សិលមិញ ម៉ោង] LT',
                lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%sទៀត',
                past: '%sមុន',
                s: 'ប៉ុន្មានវិនាទី',
                ss: '%d វិនាទី',
                m: 'មួយនាទី',
                mm: '%d នាទី',
                h: 'មួយម៉ោង',
                hh: '%d ម៉ោង',
                d: 'មួយថ្ងៃ',
                dd: '%d ថ្ងៃ',
                M: 'មួយខែ',
                MM: '%d ខែ',
                y: 'មួយឆ្នាំ',
                yy: '%d ឆ្នាំ',
            },
            dayOfMonthOrdinalParse: /ទី\d{1,2}/,
            ordinal: 'ទី%d',
            preparse: function (string) {
                return string.replace(/[១២៣៤៥៦៧៨៩០]/g, function (match) {
                    return numberMap$8[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$9[match];
                });
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$a = {
                1: '೧',
                2: '೨',
                3: '೩',
                4: '೪',
                5: '೫',
                6: '೬',
                7: '೭',
                8: '೮',
                9: '೯',
                0: '೦',
            },
            numberMap$9 = {
                '೧': '1',
                '೨': '2',
                '೩': '3',
                '೪': '4',
                '೫': '5',
                '೬': '6',
                '೭': '7',
                '೮': '8',
                '೯': '9',
                '೦': '0',
            };
    
        hooks.defineLocale('kn', {
            months: 'ಜನವರಿ_ಫೆಬ್ರವರಿ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬರ್_ಅಕ್ಟೋಬರ್_ನವೆಂಬರ್_ಡಿಸೆಂಬರ್'.split(
                '_'
            ),
            monthsShort: 'ಜನ_ಫೆಬ್ರ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂ_ಅಕ್ಟೋ_ನವೆಂ_ಡಿಸೆಂ'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'ಭಾನುವಾರ_ಸೋಮವಾರ_ಮಂಗಳವಾರ_ಬುಧವಾರ_ಗುರುವಾರ_ಶುಕ್ರವಾರ_ಶನಿವಾರ'.split(
                '_'
            ),
            weekdaysShort: 'ಭಾನು_ಸೋಮ_ಮಂಗಳ_ಬುಧ_ಗುರು_ಶುಕ್ರ_ಶನಿ'.split('_'),
            weekdaysMin: 'ಭಾ_ಸೋ_ಮಂ_ಬು_ಗು_ಶು_ಶ'.split('_'),
            longDateFormat: {
                LT: 'A h:mm',
                LTS: 'A h:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm',
                LLLL: 'dddd, D MMMM YYYY, A h:mm',
            },
            calendar: {
                sameDay: '[ಇಂದು] LT',
                nextDay: '[ನಾಳೆ] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[ನಿನ್ನೆ] LT',
                lastWeek: '[ಕೊನೆಯ] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s ನಂತರ',
                past: '%s ಹಿಂದೆ',
                s: 'ಕೆಲವು ಕ್ಷಣಗಳು',
                ss: '%d ಸೆಕೆಂಡುಗಳು',
                m: 'ಒಂದು ನಿಮಿಷ',
                mm: '%d ನಿಮಿಷ',
                h: 'ಒಂದು ಗಂಟೆ',
                hh: '%d ಗಂಟೆ',
                d: 'ಒಂದು ದಿನ',
                dd: '%d ದಿನ',
                M: 'ಒಂದು ತಿಂಗಳು',
                MM: '%d ತಿಂಗಳು',
                y: 'ಒಂದು ವರ್ಷ',
                yy: '%d ವರ್ಷ',
            },
            preparse: function (string) {
                return string.replace(/[೧೨೩೪೫೬೭೮೯೦]/g, function (match) {
                    return numberMap$9[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$a[match];
                });
            },
            meridiemParse: /ರಾತ್ರಿ|ಬೆಳಿಗ್ಗೆ|ಮಧ್ಯಾಹ್ನ|ಸಂಜೆ/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'ರಾತ್ರಿ') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'ಬೆಳಿಗ್ಗೆ') {
                    return hour;
                } else if (meridiem === 'ಮಧ್ಯಾಹ್ನ') {
                    return hour >= 10 ? hour : hour + 12;
                } else if (meridiem === 'ಸಂಜೆ') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'ರಾತ್ರಿ';
                } else if (hour < 10) {
                    return 'ಬೆಳಿಗ್ಗೆ';
                } else if (hour < 17) {
                    return 'ಮಧ್ಯಾಹ್ನ';
                } else if (hour < 20) {
                    return 'ಸಂಜೆ';
                } else {
                    return 'ರಾತ್ರಿ';
                }
            },
            dayOfMonthOrdinalParse: /\d{1,2}(ನೇ)/,
            ordinal: function (number) {
                return number + 'ನೇ';
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ko', {
            months: '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
            monthsShort: '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split(
                '_'
            ),
            weekdays: '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'),
            weekdaysShort: '일_월_화_수_목_금_토'.split('_'),
            weekdaysMin: '일_월_화_수_목_금_토'.split('_'),
            longDateFormat: {
                LT: 'A h:mm',
                LTS: 'A h:mm:ss',
                L: 'YYYY.MM.DD.',
                LL: 'YYYY년 MMMM D일',
                LLL: 'YYYY년 MMMM D일 A h:mm',
                LLLL: 'YYYY년 MMMM D일 dddd A h:mm',
                l: 'YYYY.MM.DD.',
                ll: 'YYYY년 MMMM D일',
                lll: 'YYYY년 MMMM D일 A h:mm',
                llll: 'YYYY년 MMMM D일 dddd A h:mm',
            },
            calendar: {
                sameDay: '오늘 LT',
                nextDay: '내일 LT',
                nextWeek: 'dddd LT',
                lastDay: '어제 LT',
                lastWeek: '지난주 dddd LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s 후',
                past: '%s 전',
                s: '몇 초',
                ss: '%d초',
                m: '1분',
                mm: '%d분',
                h: '한 시간',
                hh: '%d시간',
                d: '하루',
                dd: '%d일',
                M: '한 달',
                MM: '%d달',
                y: '일 년',
                yy: '%d년',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(일|월|주)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'DDD':
                        return number + '일';
                    case 'M':
                        return number + '월';
                    case 'w':
                    case 'W':
                        return number + '주';
                    default:
                        return number;
                }
            },
            meridiemParse: /오전|오후/,
            isPM: function (token) {
                return token === '오후';
            },
            meridiem: function (hour, minute, isUpper) {
                return hour < 12 ? '오전' : '오후';
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$b = {
                1: '١',
                2: '٢',
                3: '٣',
                4: '٤',
                5: '٥',
                6: '٦',
                7: '٧',
                8: '٨',
                9: '٩',
                0: '٠',
            },
            numberMap$a = {
                '١': '1',
                '٢': '2',
                '٣': '3',
                '٤': '4',
                '٥': '5',
                '٦': '6',
                '٧': '7',
                '٨': '8',
                '٩': '9',
                '٠': '0',
            },
            months$8 = [
                'کانونی دووەم',
                'شوبات',
                'ئازار',
                'نیسان',
                'ئایار',
                'حوزەیران',
                'تەمموز',
                'ئاب',
                'ئەیلوول',
                'تشرینی یەكەم',
                'تشرینی دووەم',
                'كانونی یەکەم',
            ];
    
        hooks.defineLocale('ku', {
            months: months$8,
            monthsShort: months$8,
            weekdays: 'یه‌كشه‌ممه‌_دووشه‌ممه‌_سێشه‌ممه‌_چوارشه‌ممه‌_پێنجشه‌ممه‌_هه‌ینی_شه‌ممه‌'.split(
                '_'
            ),
            weekdaysShort: 'یه‌كشه‌م_دووشه‌م_سێشه‌م_چوارشه‌م_پێنجشه‌م_هه‌ینی_شه‌ممه‌'.split(
                '_'
            ),
            weekdaysMin: 'ی_د_س_چ_پ_ه_ش'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            meridiemParse: /ئێواره‌|به‌یانی/,
            isPM: function (input) {
                return /ئێواره‌/.test(input);
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'به‌یانی';
                } else {
                    return 'ئێواره‌';
                }
            },
            calendar: {
                sameDay: '[ئه‌مرۆ كاتژمێر] LT',
                nextDay: '[به‌یانی كاتژمێر] LT',
                nextWeek: 'dddd [كاتژمێر] LT',
                lastDay: '[دوێنێ كاتژمێر] LT',
                lastWeek: 'dddd [كاتژمێر] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'له‌ %s',
                past: '%s',
                s: 'چه‌ند چركه‌یه‌ك',
                ss: 'چركه‌ %d',
                m: 'یه‌ك خوله‌ك',
                mm: '%d خوله‌ك',
                h: 'یه‌ك كاتژمێر',
                hh: '%d كاتژمێر',
                d: 'یه‌ك ڕۆژ',
                dd: '%d ڕۆژ',
                M: 'یه‌ك مانگ',
                MM: '%d مانگ',
                y: 'یه‌ك ساڵ',
                yy: '%d ساڵ',
            },
            preparse: function (string) {
                return string
                    .replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
                        return numberMap$a[match];
                    })
                    .replace(/،/g, ',');
            },
            postformat: function (string) {
                return string
                    .replace(/\d/g, function (match) {
                        return symbolMap$b[match];
                    })
                    .replace(/,/g, '،');
            },
            week: {
                dow: 6, // Saturday is the first day of the week.
                doy: 12, // The week that contains Jan 12th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var suffixes$2 = {
            0: '-чү',
            1: '-чи',
            2: '-чи',
            3: '-чү',
            4: '-чү',
            5: '-чи',
            6: '-чы',
            7: '-чи',
            8: '-чи',
            9: '-чу',
            10: '-чу',
            20: '-чы',
            30: '-чу',
            40: '-чы',
            50: '-чү',
            60: '-чы',
            70: '-чи',
            80: '-чи',
            90: '-чу',
            100: '-чү',
        };
    
        hooks.defineLocale('ky', {
            months: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split(
                '_'
            ),
            monthsShort: 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split(
                '_'
            ),
            weekdays: 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split(
                '_'
            ),
            weekdaysShort: 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'),
            weekdaysMin: 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Бүгүн саат] LT',
                nextDay: '[Эртең саат] LT',
                nextWeek: 'dddd [саат] LT',
                lastDay: '[Кечээ саат] LT',
                lastWeek: '[Өткөн аптанын] dddd [күнү] [саат] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s ичинде',
                past: '%s мурун',
                s: 'бирнече секунд',
                ss: '%d секунд',
                m: 'бир мүнөт',
                mm: '%d мүнөт',
                h: 'бир саат',
                hh: '%d саат',
                d: 'бир күн',
                dd: '%d күн',
                M: 'бир ай',
                MM: '%d ай',
                y: 'бир жыл',
                yy: '%d жыл',
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(чи|чы|чү|чу)/,
            ordinal: function (number) {
                var a = number % 10,
                    b = number >= 100 ? 100 : null;
                return number + (suffixes$2[number] || suffixes$2[a] || suffixes$2[b]);
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function processRelativeTime$6(number, withoutSuffix, key, isFuture) {
            var format = {
                m: ['eng Minutt', 'enger Minutt'],
                h: ['eng Stonn', 'enger Stonn'],
                d: ['een Dag', 'engem Dag'],
                M: ['ee Mount', 'engem Mount'],
                y: ['ee Joer', 'engem Joer'],
            };
            return withoutSuffix ? format[key][0] : format[key][1];
        }
        function processFutureTime(string) {
            var number = string.substr(0, string.indexOf(' '));
            if (eifelerRegelAppliesToNumber(number)) {
                return 'a ' + string;
            }
            return 'an ' + string;
        }
        function processPastTime(string) {
            var number = string.substr(0, string.indexOf(' '));
            if (eifelerRegelAppliesToNumber(number)) {
                return 'viru ' + string;
            }
            return 'virun ' + string;
        }
        /**
         * Returns true if the word before the given number loses the '-n' ending.
         * e.g. 'an 10 Deeg' but 'a 5 Deeg'
         *
         * @param number {integer}
         * @returns {boolean}
         */
        function eifelerRegelAppliesToNumber(number) {
            number = parseInt(number, 10);
            if (isNaN(number)) {
                return false;
            }
            if (number < 0) {
                // Negative Number --> always true
                return true;
            } else if (number < 10) {
                // Only 1 digit
                if (4 <= number && number <= 7) {
                    return true;
                }
                return false;
            } else if (number < 100) {
                // 2 digits
                var lastDigit = number % 10,
                    firstDigit = number / 10;
                if (lastDigit === 0) {
                    return eifelerRegelAppliesToNumber(firstDigit);
                }
                return eifelerRegelAppliesToNumber(lastDigit);
            } else if (number < 10000) {
                // 3 or 4 digits --> recursively check first digit
                while (number >= 10) {
                    number = number / 10;
                }
                return eifelerRegelAppliesToNumber(number);
            } else {
                // Anything larger than 4 digits: recursively check first n-3 digits
                number = number / 1000;
                return eifelerRegelAppliesToNumber(number);
            }
        }
    
        hooks.defineLocale('lb', {
            months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split(
                '_'
            ),
            monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split(
                '_'
            ),
            weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'),
            weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm [Auer]',
                LTS: 'H:mm:ss [Auer]',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY H:mm [Auer]',
                LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]',
            },
            calendar: {
                sameDay: '[Haut um] LT',
                sameElse: 'L',
                nextDay: '[Muer um] LT',
                nextWeek: 'dddd [um] LT',
                lastDay: '[Gëschter um] LT',
                lastWeek: function () {
                    // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
                    switch (this.day()) {
                        case 2:
                        case 4:
                            return '[Leschten] dddd [um] LT';
                        default:
                            return '[Leschte] dddd [um] LT';
                    }
                },
            },
            relativeTime: {
                future: processFutureTime,
                past: processPastTime,
                s: 'e puer Sekonnen',
                ss: '%d Sekonnen',
                m: processRelativeTime$6,
                mm: '%d Minutten',
                h: processRelativeTime$6,
                hh: '%d Stonnen',
                d: processRelativeTime$6,
                dd: '%d Deeg',
                M: processRelativeTime$6,
                MM: '%d Méint',
                y: processRelativeTime$6,
                yy: '%d Joer',
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('lo', {
            months: 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split(
                '_'
            ),
            monthsShort: 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split(
                '_'
            ),
            weekdays: 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
            weekdaysShort: 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
            weekdaysMin: 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'ວັນdddd D MMMM YYYY HH:mm',
            },
            meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/,
            isPM: function (input) {
                return input === 'ຕອນແລງ';
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'ຕອນເຊົ້າ';
                } else {
                    return 'ຕອນແລງ';
                }
            },
            calendar: {
                sameDay: '[ມື້ນີ້ເວລາ] LT',
                nextDay: '[ມື້ອື່ນເວລາ] LT',
                nextWeek: '[ວັນ]dddd[ໜ້າເວລາ] LT',
                lastDay: '[ມື້ວານນີ້ເວລາ] LT',
                lastWeek: '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'ອີກ %s',
                past: '%sຜ່ານມາ',
                s: 'ບໍ່ເທົ່າໃດວິນາທີ',
                ss: '%d ວິນາທີ',
                m: '1 ນາທີ',
                mm: '%d ນາທີ',
                h: '1 ຊົ່ວໂມງ',
                hh: '%d ຊົ່ວໂມງ',
                d: '1 ມື້',
                dd: '%d ມື້',
                M: '1 ເດືອນ',
                MM: '%d ເດືອນ',
                y: '1 ປີ',
                yy: '%d ປີ',
            },
            dayOfMonthOrdinalParse: /(ທີ່)\d{1,2}/,
            ordinal: function (number) {
                return 'ທີ່' + number;
            },
        });
    
        //! moment.js locale configuration
    
        var units = {
            ss: 'sekundė_sekundžių_sekundes',
            m: 'minutė_minutės_minutę',
            mm: 'minutės_minučių_minutes',
            h: 'valanda_valandos_valandą',
            hh: 'valandos_valandų_valandas',
            d: 'diena_dienos_dieną',
            dd: 'dienos_dienų_dienas',
            M: 'mėnuo_mėnesio_mėnesį',
            MM: 'mėnesiai_mėnesių_mėnesius',
            y: 'metai_metų_metus',
            yy: 'metai_metų_metus',
        };
        function translateSeconds(number, withoutSuffix, key, isFuture) {
            if (withoutSuffix) {
                return 'kelios sekundės';
            } else {
                return isFuture ? 'kelių sekundžių' : 'kelias sekundes';
            }
        }
        function translateSingular(number, withoutSuffix, key, isFuture) {
            return withoutSuffix
                ? forms(key)[0]
                : isFuture
                ? forms(key)[1]
                : forms(key)[2];
        }
        function special(number) {
            return number % 10 === 0 || (number > 10 && number < 20);
        }
        function forms(key) {
            return units[key].split('_');
        }
        function translate$6(number, withoutSuffix, key, isFuture) {
            var result = number + ' ';
            if (number === 1) {
                return (
                    result + translateSingular(number, withoutSuffix, key[0], isFuture)
                );
            } else if (withoutSuffix) {
                return result + (special(number) ? forms(key)[1] : forms(key)[0]);
            } else {
                if (isFuture) {
                    return result + forms(key)[1];
                } else {
                    return result + (special(number) ? forms(key)[1] : forms(key)[2]);
                }
            }
        }
        hooks.defineLocale('lt', {
            months: {
                format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split(
                    '_'
                ),
                standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split(
                    '_'
                ),
                isFormat: /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/,
            },
            monthsShort: 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'),
            weekdays: {
                format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split(
                    '_'
                ),
                standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split(
                    '_'
                ),
                isFormat: /dddd HH:mm/,
            },
            weekdaysShort: 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'),
            weekdaysMin: 'S_P_A_T_K_Pn_Š'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY-MM-DD',
                LL: 'YYYY [m.] MMMM D [d.]',
                LLL: 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
                LLLL: 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]',
                l: 'YYYY-MM-DD',
                ll: 'YYYY [m.] MMMM D [d.]',
                lll: 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
                llll: 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]',
            },
            calendar: {
                sameDay: '[Šiandien] LT',
                nextDay: '[Rytoj] LT',
                nextWeek: 'dddd LT',
                lastDay: '[Vakar] LT',
                lastWeek: '[Praėjusį] dddd LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'po %s',
                past: 'prieš %s',
                s: translateSeconds,
                ss: translate$6,
                m: translateSingular,
                mm: translate$6,
                h: translateSingular,
                hh: translate$6,
                d: translateSingular,
                dd: translate$6,
                M: translateSingular,
                MM: translate$6,
                y: translateSingular,
                yy: translate$6,
            },
            dayOfMonthOrdinalParse: /\d{1,2}-oji/,
            ordinal: function (number) {
                return number + '-oji';
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var units$1 = {
            ss: 'sekundes_sekundēm_sekunde_sekundes'.split('_'),
            m: 'minūtes_minūtēm_minūte_minūtes'.split('_'),
            mm: 'minūtes_minūtēm_minūte_minūtes'.split('_'),
            h: 'stundas_stundām_stunda_stundas'.split('_'),
            hh: 'stundas_stundām_stunda_stundas'.split('_'),
            d: 'dienas_dienām_diena_dienas'.split('_'),
            dd: 'dienas_dienām_diena_dienas'.split('_'),
            M: 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
            MM: 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
            y: 'gada_gadiem_gads_gadi'.split('_'),
            yy: 'gada_gadiem_gads_gadi'.split('_'),
        };
        /**
         * @param withoutSuffix boolean true = a length of time; false = before/after a period of time.
         */
        function format$1(forms, number, withoutSuffix) {
            if (withoutSuffix) {
                // E.g. "21 minūte", "3 minūtes".
                return number % 10 === 1 && number % 100 !== 11 ? forms[2] : forms[3];
            } else {
                // E.g. "21 minūtes" as in "pēc 21 minūtes".
                // E.g. "3 minūtēm" as in "pēc 3 minūtēm".
                return number % 10 === 1 && number % 100 !== 11 ? forms[0] : forms[1];
            }
        }
        function relativeTimeWithPlural$1(number, withoutSuffix, key) {
            return number + ' ' + format$1(units$1[key], number, withoutSuffix);
        }
        function relativeTimeWithSingular(number, withoutSuffix, key) {
            return format$1(units$1[key], number, withoutSuffix);
        }
        function relativeSeconds(number, withoutSuffix) {
            return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm';
        }
    
        hooks.defineLocale('lv', {
            months: 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split(
                '_'
            ),
            monthsShort: 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'),
            weekdays: 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split(
                '_'
            ),
            weekdaysShort: 'Sv_P_O_T_C_Pk_S'.split('_'),
            weekdaysMin: 'Sv_P_O_T_C_Pk_S'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY.',
                LL: 'YYYY. [gada] D. MMMM',
                LLL: 'YYYY. [gada] D. MMMM, HH:mm',
                LLLL: 'YYYY. [gada] D. MMMM, dddd, HH:mm',
            },
            calendar: {
                sameDay: '[Šodien pulksten] LT',
                nextDay: '[Rīt pulksten] LT',
                nextWeek: 'dddd [pulksten] LT',
                lastDay: '[Vakar pulksten] LT',
                lastWeek: '[Pagājušā] dddd [pulksten] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'pēc %s',
                past: 'pirms %s',
                s: relativeSeconds,
                ss: relativeTimeWithPlural$1,
                m: relativeTimeWithSingular,
                mm: relativeTimeWithPlural$1,
                h: relativeTimeWithSingular,
                hh: relativeTimeWithPlural$1,
                d: relativeTimeWithSingular,
                dd: relativeTimeWithPlural$1,
                M: relativeTimeWithSingular,
                MM: relativeTimeWithPlural$1,
                y: relativeTimeWithSingular,
                yy: relativeTimeWithPlural$1,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var translator = {
            words: {
                //Different grammatical cases
                ss: ['sekund', 'sekunda', 'sekundi'],
                m: ['jedan minut', 'jednog minuta'],
                mm: ['minut', 'minuta', 'minuta'],
                h: ['jedan sat', 'jednog sata'],
                hh: ['sat', 'sata', 'sati'],
                dd: ['dan', 'dana', 'dana'],
                MM: ['mjesec', 'mjeseca', 'mjeseci'],
                yy: ['godina', 'godine', 'godina'],
            },
            correctGrammaticalCase: function (number, wordKey) {
                return number === 1
                    ? wordKey[0]
                    : number >= 2 && number <= 4
                    ? wordKey[1]
                    : wordKey[2];
            },
            translate: function (number, withoutSuffix, key) {
                var wordKey = translator.words[key];
                if (key.length === 1) {
                    return withoutSuffix ? wordKey[0] : wordKey[1];
                } else {
                    return (
                        number +
                        ' ' +
                        translator.correctGrammaticalCase(number, wordKey)
                    );
                }
            },
        };
    
        hooks.defineLocale('me', {
            months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split(
                '_'
            ),
            monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split(
                '_'
            ),
            weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
            weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY H:mm',
                LLLL: 'dddd, D. MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[danas u] LT',
                nextDay: '[sjutra u] LT',
    
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[u] [nedjelju] [u] LT';
                        case 3:
                            return '[u] [srijedu] [u] LT';
                        case 6:
                            return '[u] [subotu] [u] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[u] dddd [u] LT';
                    }
                },
                lastDay: '[juče u] LT',
                lastWeek: function () {
                    var lastWeekDays = [
                        '[prošle] [nedjelje] [u] LT',
                        '[prošlog] [ponedjeljka] [u] LT',
                        '[prošlog] [utorka] [u] LT',
                        '[prošle] [srijede] [u] LT',
                        '[prošlog] [četvrtka] [u] LT',
                        '[prošlog] [petka] [u] LT',
                        '[prošle] [subote] [u] LT',
                    ];
                    return lastWeekDays[this.day()];
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'za %s',
                past: 'prije %s',
                s: 'nekoliko sekundi',
                ss: translator.translate,
                m: translator.translate,
                mm: translator.translate,
                h: translator.translate,
                hh: translator.translate,
                d: 'dan',
                dd: translator.translate,
                M: 'mjesec',
                MM: translator.translate,
                y: 'godinu',
                yy: translator.translate,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('mi', {
            months: 'Kohi-tāte_Hui-tanguru_Poutū-te-rangi_Paenga-whāwhā_Haratua_Pipiri_Hōngoingoi_Here-turi-kōkā_Mahuru_Whiringa-ā-nuku_Whiringa-ā-rangi_Hakihea'.split(
                '_'
            ),
            monthsShort: 'Kohi_Hui_Pou_Pae_Hara_Pipi_Hōngoi_Here_Mahu_Whi-nu_Whi-ra_Haki'.split(
                '_'
            ),
            monthsRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
            monthsStrictRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
            monthsShortRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
            monthsShortStrictRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,2}/i,
            weekdays: 'Rātapu_Mane_Tūrei_Wenerei_Tāite_Paraire_Hātarei'.split('_'),
            weekdaysShort: 'Ta_Ma_Tū_We_Tāi_Pa_Hā'.split('_'),
            weekdaysMin: 'Ta_Ma_Tū_We_Tāi_Pa_Hā'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY [i] HH:mm',
                LLLL: 'dddd, D MMMM YYYY [i] HH:mm',
            },
            calendar: {
                sameDay: '[i teie mahana, i] LT',
                nextDay: '[apopo i] LT',
                nextWeek: 'dddd [i] LT',
                lastDay: '[inanahi i] LT',
                lastWeek: 'dddd [whakamutunga i] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'i roto i %s',
                past: '%s i mua',
                s: 'te hēkona ruarua',
                ss: '%d hēkona',
                m: 'he meneti',
                mm: '%d meneti',
                h: 'te haora',
                hh: '%d haora',
                d: 'he ra',
                dd: '%d ra',
                M: 'he marama',
                MM: '%d marama',
                y: 'he tau',
                yy: '%d tau',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('mk', {
            months: 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split(
                '_'
            ),
            monthsShort: 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'),
            weekdays: 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split(
                '_'
            ),
            weekdaysShort: 'нед_пон_вто_сре_чет_пет_саб'.split('_'),
            weekdaysMin: 'нe_пo_вт_ср_че_пе_сa'.split('_'),
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'D.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY H:mm',
                LLLL: 'dddd, D MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[Денес во] LT',
                nextDay: '[Утре во] LT',
                nextWeek: '[Во] dddd [во] LT',
                lastDay: '[Вчера во] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                        case 3:
                        case 6:
                            return '[Изминатата] dddd [во] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[Изминатиот] dddd [во] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'за %s',
                past: 'пред %s',
                s: 'неколку секунди',
                ss: '%d секунди',
                m: 'една минута',
                mm: '%d минути',
                h: 'еден час',
                hh: '%d часа',
                d: 'еден ден',
                dd: '%d дена',
                M: 'еден месец',
                MM: '%d месеци',
                y: 'една година',
                yy: '%d години',
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
            ordinal: function (number) {
                var lastDigit = number % 10,
                    last2Digits = number % 100;
                if (number === 0) {
                    return number + '-ев';
                } else if (last2Digits === 0) {
                    return number + '-ен';
                } else if (last2Digits > 10 && last2Digits < 20) {
                    return number + '-ти';
                } else if (lastDigit === 1) {
                    return number + '-ви';
                } else if (lastDigit === 2) {
                    return number + '-ри';
                } else if (lastDigit === 7 || lastDigit === 8) {
                    return number + '-ми';
                } else {
                    return number + '-ти';
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ml', {
            months: 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split(
                '_'
            ),
            monthsShort: 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split(
                '_'
            ),
            weekdaysShort: 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'),
            weekdaysMin: 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'),
            longDateFormat: {
                LT: 'A h:mm -നു',
                LTS: 'A h:mm:ss -നു',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm -നു',
                LLLL: 'dddd, D MMMM YYYY, A h:mm -നു',
            },
            calendar: {
                sameDay: '[ഇന്ന്] LT',
                nextDay: '[നാളെ] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[ഇന്നലെ] LT',
                lastWeek: '[കഴിഞ്ഞ] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s കഴിഞ്ഞ്',
                past: '%s മുൻപ്',
                s: 'അൽപ നിമിഷങ്ങൾ',
                ss: '%d സെക്കൻഡ്',
                m: 'ഒരു മിനിറ്റ്',
                mm: '%d മിനിറ്റ്',
                h: 'ഒരു മണിക്കൂർ',
                hh: '%d മണിക്കൂർ',
                d: 'ഒരു ദിവസം',
                dd: '%d ദിവസം',
                M: 'ഒരു മാസം',
                MM: '%d മാസം',
                y: 'ഒരു വർഷം',
                yy: '%d വർഷം',
            },
            meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (
                    (meridiem === 'രാത്രി' && hour >= 4) ||
                    meridiem === 'ഉച്ച കഴിഞ്ഞ്' ||
                    meridiem === 'വൈകുന്നേരം'
                ) {
                    return hour + 12;
                } else {
                    return hour;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'രാത്രി';
                } else if (hour < 12) {
                    return 'രാവിലെ';
                } else if (hour < 17) {
                    return 'ഉച്ച കഴിഞ്ഞ്';
                } else if (hour < 20) {
                    return 'വൈകുന്നേരം';
                } else {
                    return 'രാത്രി';
                }
            },
        });
    
        //! moment.js locale configuration
    
        function translate$7(number, withoutSuffix, key, isFuture) {
            switch (key) {
                case 's':
                    return withoutSuffix ? 'хэдхэн секунд' : 'хэдхэн секундын';
                case 'ss':
                    return number + (withoutSuffix ? ' секунд' : ' секундын');
                case 'm':
                case 'mm':
                    return number + (withoutSuffix ? ' минут' : ' минутын');
                case 'h':
                case 'hh':
                    return number + (withoutSuffix ? ' цаг' : ' цагийн');
                case 'd':
                case 'dd':
                    return number + (withoutSuffix ? ' өдөр' : ' өдрийн');
                case 'M':
                case 'MM':
                    return number + (withoutSuffix ? ' сар' : ' сарын');
                case 'y':
                case 'yy':
                    return number + (withoutSuffix ? ' жил' : ' жилийн');
                default:
                    return number;
            }
        }
    
        hooks.defineLocale('mn', {
            months: 'Нэгдүгээр сар_Хоёрдугаар сар_Гуравдугаар сар_Дөрөвдүгээр сар_Тавдугаар сар_Зургадугаар сар_Долдугаар сар_Наймдугаар сар_Есдүгээр сар_Аравдугаар сар_Арван нэгдүгээр сар_Арван хоёрдугаар сар'.split(
                '_'
            ),
            monthsShort: '1 сар_2 сар_3 сар_4 сар_5 сар_6 сар_7 сар_8 сар_9 сар_10 сар_11 сар_12 сар'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'Ням_Даваа_Мягмар_Лхагва_Пүрэв_Баасан_Бямба'.split('_'),
            weekdaysShort: 'Ням_Дав_Мяг_Лха_Пүр_Баа_Бям'.split('_'),
            weekdaysMin: 'Ня_Да_Мя_Лх_Пү_Ба_Бя'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY-MM-DD',
                LL: 'YYYY оны MMMMын D',
                LLL: 'YYYY оны MMMMын D HH:mm',
                LLLL: 'dddd, YYYY оны MMMMын D HH:mm',
            },
            meridiemParse: /ҮӨ|ҮХ/i,
            isPM: function (input) {
                return input === 'ҮХ';
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'ҮӨ';
                } else {
                    return 'ҮХ';
                }
            },
            calendar: {
                sameDay: '[Өнөөдөр] LT',
                nextDay: '[Маргааш] LT',
                nextWeek: '[Ирэх] dddd LT',
                lastDay: '[Өчигдөр] LT',
                lastWeek: '[Өнгөрсөн] dddd LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s дараа',
                past: '%s өмнө',
                s: translate$7,
                ss: translate$7,
                m: translate$7,
                mm: translate$7,
                h: translate$7,
                hh: translate$7,
                d: translate$7,
                dd: translate$7,
                M: translate$7,
                MM: translate$7,
                y: translate$7,
                yy: translate$7,
            },
            dayOfMonthOrdinalParse: /\d{1,2} өдөр/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'DDD':
                        return number + ' өдөр';
                    default:
                        return number;
                }
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$c = {
                1: '१',
                2: '२',
                3: '३',
                4: '४',
                5: '५',
                6: '६',
                7: '७',
                8: '८',
                9: '९',
                0: '०',
            },
            numberMap$b = {
                '१': '1',
                '२': '2',
                '३': '3',
                '४': '4',
                '५': '5',
                '६': '6',
                '७': '7',
                '८': '8',
                '९': '9',
                '०': '0',
            };
    
        function relativeTimeMr(number, withoutSuffix, string, isFuture) {
            var output = '';
            if (withoutSuffix) {
                switch (string) {
                    case 's':
                        output = 'काही सेकंद';
                        break;
                    case 'ss':
                        output = '%d सेकंद';
                        break;
                    case 'm':
                        output = 'एक मिनिट';
                        break;
                    case 'mm':
                        output = '%d मिनिटे';
                        break;
                    case 'h':
                        output = 'एक तास';
                        break;
                    case 'hh':
                        output = '%d तास';
                        break;
                    case 'd':
                        output = 'एक दिवस';
                        break;
                    case 'dd':
                        output = '%d दिवस';
                        break;
                    case 'M':
                        output = 'एक महिना';
                        break;
                    case 'MM':
                        output = '%d महिने';
                        break;
                    case 'y':
                        output = 'एक वर्ष';
                        break;
                    case 'yy':
                        output = '%d वर्षे';
                        break;
                }
            } else {
                switch (string) {
                    case 's':
                        output = 'काही सेकंदां';
                        break;
                    case 'ss':
                        output = '%d सेकंदां';
                        break;
                    case 'm':
                        output = 'एका मिनिटा';
                        break;
                    case 'mm':
                        output = '%d मिनिटां';
                        break;
                    case 'h':
                        output = 'एका तासा';
                        break;
                    case 'hh':
                        output = '%d तासां';
                        break;
                    case 'd':
                        output = 'एका दिवसा';
                        break;
                    case 'dd':
                        output = '%d दिवसां';
                        break;
                    case 'M':
                        output = 'एका महिन्या';
                        break;
                    case 'MM':
                        output = '%d महिन्यां';
                        break;
                    case 'y':
                        output = 'एका वर्षा';
                        break;
                    case 'yy':
                        output = '%d वर्षां';
                        break;
                }
            }
            return output.replace(/%d/i, number);
        }
    
        hooks.defineLocale('mr', {
            months: 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split(
                '_'
            ),
            monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
            weekdaysShort: 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'),
            weekdaysMin: 'र_सो_मं_बु_गु_शु_श'.split('_'),
            longDateFormat: {
                LT: 'A h:mm वाजता',
                LTS: 'A h:mm:ss वाजता',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm वाजता',
                LLLL: 'dddd, D MMMM YYYY, A h:mm वाजता',
            },
            calendar: {
                sameDay: '[आज] LT',
                nextDay: '[उद्या] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[काल] LT',
                lastWeek: '[मागील] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%sमध्ये',
                past: '%sपूर्वी',
                s: relativeTimeMr,
                ss: relativeTimeMr,
                m: relativeTimeMr,
                mm: relativeTimeMr,
                h: relativeTimeMr,
                hh: relativeTimeMr,
                d: relativeTimeMr,
                dd: relativeTimeMr,
                M: relativeTimeMr,
                MM: relativeTimeMr,
                y: relativeTimeMr,
                yy: relativeTimeMr,
            },
            preparse: function (string) {
                return string.replace(/[१२३४५६७८९०]/g, function (match) {
                    return numberMap$b[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$c[match];
                });
            },
            meridiemParse: /पहाटे|सकाळी|दुपारी|सायंकाळी|रात्री/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'पहाटे' || meridiem === 'सकाळी') {
                    return hour;
                } else if (
                    meridiem === 'दुपारी' ||
                    meridiem === 'सायंकाळी' ||
                    meridiem === 'रात्री'
                ) {
                    return hour >= 12 ? hour : hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour >= 0 && hour < 6) {
                    return 'पहाटे';
                } else if (hour < 12) {
                    return 'सकाळी';
                } else if (hour < 17) {
                    return 'दुपारी';
                } else if (hour < 20) {
                    return 'सायंकाळी';
                } else {
                    return 'रात्री';
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ms-my', {
            months: 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
            weekdays: 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
            weekdaysShort: 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
            weekdaysMin: 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
            longDateFormat: {
                LT: 'HH.mm',
                LTS: 'HH.mm.ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY [pukul] HH.mm',
                LLLL: 'dddd, D MMMM YYYY [pukul] HH.mm',
            },
            meridiemParse: /pagi|tengahari|petang|malam/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'pagi') {
                    return hour;
                } else if (meridiem === 'tengahari') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === 'petang' || meridiem === 'malam') {
                    return hour + 12;
                }
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours < 11) {
                    return 'pagi';
                } else if (hours < 15) {
                    return 'tengahari';
                } else if (hours < 19) {
                    return 'petang';
                } else {
                    return 'malam';
                }
            },
            calendar: {
                sameDay: '[Hari ini pukul] LT',
                nextDay: '[Esok pukul] LT',
                nextWeek: 'dddd [pukul] LT',
                lastDay: '[Kelmarin pukul] LT',
                lastWeek: 'dddd [lepas pukul] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'dalam %s',
                past: '%s yang lepas',
                s: 'beberapa saat',
                ss: '%d saat',
                m: 'seminit',
                mm: '%d minit',
                h: 'sejam',
                hh: '%d jam',
                d: 'sehari',
                dd: '%d hari',
                M: 'sebulan',
                MM: '%d bulan',
                y: 'setahun',
                yy: '%d tahun',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ms', {
            months: 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
            weekdays: 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
            weekdaysShort: 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
            weekdaysMin: 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
            longDateFormat: {
                LT: 'HH.mm',
                LTS: 'HH.mm.ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY [pukul] HH.mm',
                LLLL: 'dddd, D MMMM YYYY [pukul] HH.mm',
            },
            meridiemParse: /pagi|tengahari|petang|malam/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'pagi') {
                    return hour;
                } else if (meridiem === 'tengahari') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === 'petang' || meridiem === 'malam') {
                    return hour + 12;
                }
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours < 11) {
                    return 'pagi';
                } else if (hours < 15) {
                    return 'tengahari';
                } else if (hours < 19) {
                    return 'petang';
                } else {
                    return 'malam';
                }
            },
            calendar: {
                sameDay: '[Hari ini pukul] LT',
                nextDay: '[Esok pukul] LT',
                nextWeek: 'dddd [pukul] LT',
                lastDay: '[Kelmarin pukul] LT',
                lastWeek: 'dddd [lepas pukul] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'dalam %s',
                past: '%s yang lepas',
                s: 'beberapa saat',
                ss: '%d saat',
                m: 'seminit',
                mm: '%d minit',
                h: 'sejam',
                hh: '%d jam',
                d: 'sehari',
                dd: '%d hari',
                M: 'sebulan',
                MM: '%d bulan',
                y: 'setahun',
                yy: '%d tahun',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('mt', {
            months: 'Jannar_Frar_Marzu_April_Mejju_Ġunju_Lulju_Awwissu_Settembru_Ottubru_Novembru_Diċembru'.split(
                '_'
            ),
            monthsShort: 'Jan_Fra_Mar_Apr_Mej_Ġun_Lul_Aww_Set_Ott_Nov_Diċ'.split('_'),
            weekdays: 'Il-Ħadd_It-Tnejn_It-Tlieta_L-Erbgħa_Il-Ħamis_Il-Ġimgħa_Is-Sibt'.split(
                '_'
            ),
            weekdaysShort: 'Ħad_Tne_Tli_Erb_Ħam_Ġim_Sib'.split('_'),
            weekdaysMin: 'Ħa_Tn_Tl_Er_Ħa_Ġi_Si'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Illum fil-]LT',
                nextDay: '[Għada fil-]LT',
                nextWeek: 'dddd [fil-]LT',
                lastDay: '[Il-bieraħ fil-]LT',
                lastWeek: 'dddd [li għadda] [fil-]LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'f’ %s',
                past: '%s ilu',
                s: 'ftit sekondi',
                ss: '%d sekondi',
                m: 'minuta',
                mm: '%d minuti',
                h: 'siegħa',
                hh: '%d siegħat',
                d: 'ġurnata',
                dd: '%d ġranet',
                M: 'xahar',
                MM: '%d xhur',
                y: 'sena',
                yy: '%d sni',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$d = {
                1: '၁',
                2: '၂',
                3: '၃',
                4: '၄',
                5: '၅',
                6: '၆',
                7: '၇',
                8: '၈',
                9: '၉',
                0: '၀',
            },
            numberMap$c = {
                '၁': '1',
                '၂': '2',
                '၃': '3',
                '၄': '4',
                '၅': '5',
                '၆': '6',
                '၇': '7',
                '၈': '8',
                '၉': '9',
                '၀': '0',
            };
    
        hooks.defineLocale('my', {
            months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split(
                '_'
            ),
            monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'),
            weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split(
                '_'
            ),
            weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
            weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
    
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[ယနေ.] LT [မှာ]',
                nextDay: '[မနက်ဖြန်] LT [မှာ]',
                nextWeek: 'dddd LT [မှာ]',
                lastDay: '[မနေ.က] LT [မှာ]',
                lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'လာမည့် %s မှာ',
                past: 'လွန်ခဲ့သော %s က',
                s: 'စက္ကန်.အနည်းငယ်',
                ss: '%d စက္ကန့်',
                m: 'တစ်မိနစ်',
                mm: '%d မိနစ်',
                h: 'တစ်နာရီ',
                hh: '%d နာရီ',
                d: 'တစ်ရက်',
                dd: '%d ရက်',
                M: 'တစ်လ',
                MM: '%d လ',
                y: 'တစ်နှစ်',
                yy: '%d နှစ်',
            },
            preparse: function (string) {
                return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) {
                    return numberMap$c[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$d[match];
                });
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('nb', {
            months: 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split(
                '_'
            ),
            monthsShort: 'jan._feb._mars_apr._mai_juni_juli_aug._sep._okt._nov._des.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
            weekdaysShort: 'sø._ma._ti._on._to._fr._lø.'.split('_'),
            weekdaysMin: 'sø_ma_ti_on_to_fr_lø'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY [kl.] HH:mm',
                LLLL: 'dddd D. MMMM YYYY [kl.] HH:mm',
            },
            calendar: {
                sameDay: '[i dag kl.] LT',
                nextDay: '[i morgen kl.] LT',
                nextWeek: 'dddd [kl.] LT',
                lastDay: '[i går kl.] LT',
                lastWeek: '[forrige] dddd [kl.] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'om %s',
                past: '%s siden',
                s: 'noen sekunder',
                ss: '%d sekunder',
                m: 'ett minutt',
                mm: '%d minutter',
                h: 'en time',
                hh: '%d timer',
                d: 'en dag',
                dd: '%d dager',
                w: 'en uke',
                ww: '%d uker',
                M: 'en måned',
                MM: '%d måneder',
                y: 'ett år',
                yy: '%d år',
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$e = {
                1: '१',
                2: '२',
                3: '३',
                4: '४',
                5: '५',
                6: '६',
                7: '७',
                8: '८',
                9: '९',
                0: '०',
            },
            numberMap$d = {
                '१': '1',
                '२': '2',
                '३': '3',
                '४': '4',
                '५': '5',
                '६': '6',
                '७': '7',
                '८': '8',
                '९': '9',
                '०': '0',
            };
    
        hooks.defineLocale('ne', {
            months: 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split(
                '_'
            ),
            monthsShort: 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split(
                '_'
            ),
            weekdaysShort: 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'),
            weekdaysMin: 'आ._सो._मं._बु._बि._शु._श.'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'Aको h:mm बजे',
                LTS: 'Aको h:mm:ss बजे',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, Aको h:mm बजे',
                LLLL: 'dddd, D MMMM YYYY, Aको h:mm बजे',
            },
            preparse: function (string) {
                return string.replace(/[१२३४५६७८९०]/g, function (match) {
                    return numberMap$d[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$e[match];
                });
            },
            meridiemParse: /राति|बिहान|दिउँसो|साँझ/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'राति') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'बिहान') {
                    return hour;
                } else if (meridiem === 'दिउँसो') {
                    return hour >= 10 ? hour : hour + 12;
                } else if (meridiem === 'साँझ') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 3) {
                    return 'राति';
                } else if (hour < 12) {
                    return 'बिहान';
                } else if (hour < 16) {
                    return 'दिउँसो';
                } else if (hour < 20) {
                    return 'साँझ';
                } else {
                    return 'राति';
                }
            },
            calendar: {
                sameDay: '[आज] LT',
                nextDay: '[भोलि] LT',
                nextWeek: '[आउँदो] dddd[,] LT',
                lastDay: '[हिजो] LT',
                lastWeek: '[गएको] dddd[,] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%sमा',
                past: '%s अगाडि',
                s: 'केही क्षण',
                ss: '%d सेकेण्ड',
                m: 'एक मिनेट',
                mm: '%d मिनेट',
                h: 'एक घण्टा',
                hh: '%d घण्टा',
                d: 'एक दिन',
                dd: '%d दिन',
                M: 'एक महिना',
                MM: '%d महिना',
                y: 'एक बर्ष',
                yy: '%d बर्ष',
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var monthsShortWithDots$1 = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split(
                '_'
            ),
            monthsShortWithoutDots$1 = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split(
                '_'
            ),
            monthsParse$8 = [
                /^jan/i,
                /^feb/i,
                /^maart|mrt.?$/i,
                /^apr/i,
                /^mei$/i,
                /^jun[i.]?$/i,
                /^jul[i.]?$/i,
                /^aug/i,
                /^sep/i,
                /^okt/i,
                /^nov/i,
                /^dec/i,
            ],
            monthsRegex$8 = /^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;
    
        hooks.defineLocale('nl-be', {
            months: 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split(
                '_'
            ),
            monthsShort: function (m, format) {
                if (!m) {
                    return monthsShortWithDots$1;
                } else if (/-MMM-/.test(format)) {
                    return monthsShortWithoutDots$1[m.month()];
                } else {
                    return monthsShortWithDots$1[m.month()];
                }
            },
    
            monthsRegex: monthsRegex$8,
            monthsShortRegex: monthsRegex$8,
            monthsStrictRegex: /^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,
            monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
    
            monthsParse: monthsParse$8,
            longMonthsParse: monthsParse$8,
            shortMonthsParse: monthsParse$8,
    
            weekdays: 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split(
                '_'
            ),
            weekdaysShort: 'zo._ma._di._wo._do._vr._za.'.split('_'),
            weekdaysMin: 'zo_ma_di_wo_do_vr_za'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[vandaag om] LT',
                nextDay: '[morgen om] LT',
                nextWeek: 'dddd [om] LT',
                lastDay: '[gisteren om] LT',
                lastWeek: '[afgelopen] dddd [om] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'over %s',
                past: '%s geleden',
                s: 'een paar seconden',
                ss: '%d seconden',
                m: 'één minuut',
                mm: '%d minuten',
                h: 'één uur',
                hh: '%d uur',
                d: 'één dag',
                dd: '%d dagen',
                M: 'één maand',
                MM: '%d maanden',
                y: 'één jaar',
                yy: '%d jaar',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
            ordinal: function (number) {
                return (
                    number +
                    (number === 1 || number === 8 || number >= 20 ? 'ste' : 'de')
                );
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var monthsShortWithDots$2 = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split(
                '_'
            ),
            monthsShortWithoutDots$2 = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split(
                '_'
            ),
            monthsParse$9 = [
                /^jan/i,
                /^feb/i,
                /^maart|mrt.?$/i,
                /^apr/i,
                /^mei$/i,
                /^jun[i.]?$/i,
                /^jul[i.]?$/i,
                /^aug/i,
                /^sep/i,
                /^okt/i,
                /^nov/i,
                /^dec/i,
            ],
            monthsRegex$9 = /^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;
    
        hooks.defineLocale('nl', {
            months: 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split(
                '_'
            ),
            monthsShort: function (m, format) {
                if (!m) {
                    return monthsShortWithDots$2;
                } else if (/-MMM-/.test(format)) {
                    return monthsShortWithoutDots$2[m.month()];
                } else {
                    return monthsShortWithDots$2[m.month()];
                }
            },
    
            monthsRegex: monthsRegex$9,
            monthsShortRegex: monthsRegex$9,
            monthsStrictRegex: /^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,
            monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
    
            monthsParse: monthsParse$9,
            longMonthsParse: monthsParse$9,
            shortMonthsParse: monthsParse$9,
    
            weekdays: 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split(
                '_'
            ),
            weekdaysShort: 'zo._ma._di._wo._do._vr._za.'.split('_'),
            weekdaysMin: 'zo_ma_di_wo_do_vr_za'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD-MM-YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[vandaag om] LT',
                nextDay: '[morgen om] LT',
                nextWeek: 'dddd [om] LT',
                lastDay: '[gisteren om] LT',
                lastWeek: '[afgelopen] dddd [om] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'over %s',
                past: '%s geleden',
                s: 'een paar seconden',
                ss: '%d seconden',
                m: 'één minuut',
                mm: '%d minuten',
                h: 'één uur',
                hh: '%d uur',
                d: 'één dag',
                dd: '%d dagen',
                w: 'één week',
                ww: '%d weken',
                M: 'één maand',
                MM: '%d maanden',
                y: 'één jaar',
                yy: '%d jaar',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
            ordinal: function (number) {
                return (
                    number +
                    (number === 1 || number === 8 || number >= 20 ? 'ste' : 'de')
                );
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('nn', {
            months: 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split(
                '_'
            ),
            monthsShort: 'jan._feb._mars_apr._mai_juni_juli_aug._sep._okt._nov._des.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'),
            weekdaysShort: 'su._må._ty._on._to._fr._lau.'.split('_'),
            weekdaysMin: 'su_må_ty_on_to_fr_la'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY [kl.] H:mm',
                LLLL: 'dddd D. MMMM YYYY [kl.] HH:mm',
            },
            calendar: {
                sameDay: '[I dag klokka] LT',
                nextDay: '[I morgon klokka] LT',
                nextWeek: 'dddd [klokka] LT',
                lastDay: '[I går klokka] LT',
                lastWeek: '[Føregåande] dddd [klokka] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'om %s',
                past: '%s sidan',
                s: 'nokre sekund',
                ss: '%d sekund',
                m: 'eit minutt',
                mm: '%d minutt',
                h: 'ein time',
                hh: '%d timar',
                d: 'ein dag',
                dd: '%d dagar',
                w: 'ei veke',
                ww: '%d veker',
                M: 'ein månad',
                MM: '%d månader',
                y: 'eit år',
                yy: '%d år',
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('oc-lnc', {
            months: {
                standalone: 'genièr_febrièr_març_abril_mai_junh_julhet_agost_setembre_octòbre_novembre_decembre'.split(
                    '_'
                ),
                format: "de genièr_de febrièr_de març_d'abril_de mai_de junh_de julhet_d'agost_de setembre_d'octòbre_de novembre_de decembre".split(
                    '_'
                ),
                isFormat: /D[oD]?(\s)+MMMM/,
            },
            monthsShort: 'gen._febr._març_abr._mai_junh_julh._ago._set._oct._nov._dec.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'dimenge_diluns_dimars_dimècres_dijòus_divendres_dissabte'.split(
                '_'
            ),
            weekdaysShort: 'dg._dl._dm._dc._dj._dv._ds.'.split('_'),
            weekdaysMin: 'dg_dl_dm_dc_dj_dv_ds'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM [de] YYYY',
                ll: 'D MMM YYYY',
                LLL: 'D MMMM [de] YYYY [a] H:mm',
                lll: 'D MMM YYYY, H:mm',
                LLLL: 'dddd D MMMM [de] YYYY [a] H:mm',
                llll: 'ddd D MMM YYYY, H:mm',
            },
            calendar: {
                sameDay: '[uèi a] LT',
                nextDay: '[deman a] LT',
                nextWeek: 'dddd [a] LT',
                lastDay: '[ièr a] LT',
                lastWeek: 'dddd [passat a] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: "d'aquí %s",
                past: 'fa %s',
                s: 'unas segondas',
                ss: '%d segondas',
                m: 'una minuta',
                mm: '%d minutas',
                h: 'una ora',
                hh: '%d oras',
                d: 'un jorn',
                dd: '%d jorns',
                M: 'un mes',
                MM: '%d meses',
                y: 'un an',
                yy: '%d ans',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(r|n|t|è|a)/,
            ordinal: function (number, period) {
                var output =
                    number === 1
                        ? 'r'
                        : number === 2
                        ? 'n'
                        : number === 3
                        ? 'r'
                        : number === 4
                        ? 't'
                        : 'è';
                if (period === 'w' || period === 'W') {
                    output = 'a';
                }
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4,
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$f = {
                1: '੧',
                2: '੨',
                3: '੩',
                4: '੪',
                5: '੫',
                6: '੬',
                7: '੭',
                8: '੮',
                9: '੯',
                0: '੦',
            },
            numberMap$e = {
                '੧': '1',
                '੨': '2',
                '੩': '3',
                '੪': '4',
                '੫': '5',
                '੬': '6',
                '੭': '7',
                '੮': '8',
                '੯': '9',
                '੦': '0',
            };
    
        hooks.defineLocale('pa-in', {
            // There are months name as per Nanakshahi Calendar but they are not used as rigidly in modern Punjabi.
            months: 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split(
                '_'
            ),
            monthsShort: 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split(
                '_'
            ),
            weekdays: 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split(
                '_'
            ),
            weekdaysShort: 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
            weekdaysMin: 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
            longDateFormat: {
                LT: 'A h:mm ਵਜੇ',
                LTS: 'A h:mm:ss ਵਜੇ',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm ਵਜੇ',
                LLLL: 'dddd, D MMMM YYYY, A h:mm ਵਜੇ',
            },
            calendar: {
                sameDay: '[ਅਜ] LT',
                nextDay: '[ਕਲ] LT',
                nextWeek: '[ਅਗਲਾ] dddd, LT',
                lastDay: '[ਕਲ] LT',
                lastWeek: '[ਪਿਛਲੇ] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s ਵਿੱਚ',
                past: '%s ਪਿਛਲੇ',
                s: 'ਕੁਝ ਸਕਿੰਟ',
                ss: '%d ਸਕਿੰਟ',
                m: 'ਇਕ ਮਿੰਟ',
                mm: '%d ਮਿੰਟ',
                h: 'ਇੱਕ ਘੰਟਾ',
                hh: '%d ਘੰਟੇ',
                d: 'ਇੱਕ ਦਿਨ',
                dd: '%d ਦਿਨ',
                M: 'ਇੱਕ ਮਹੀਨਾ',
                MM: '%d ਮਹੀਨੇ',
                y: 'ਇੱਕ ਸਾਲ',
                yy: '%d ਸਾਲ',
            },
            preparse: function (string) {
                return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) {
                    return numberMap$e[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$f[match];
                });
            },
            // Punjabi notation for meridiems are quite fuzzy in practice. While there exists
            // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi.
            meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'ਰਾਤ') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'ਸਵੇਰ') {
                    return hour;
                } else if (meridiem === 'ਦੁਪਹਿਰ') {
                    return hour >= 10 ? hour : hour + 12;
                } else if (meridiem === 'ਸ਼ਾਮ') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'ਰਾਤ';
                } else if (hour < 10) {
                    return 'ਸਵੇਰ';
                } else if (hour < 17) {
                    return 'ਦੁਪਹਿਰ';
                } else if (hour < 20) {
                    return 'ਸ਼ਾਮ';
                } else {
                    return 'ਰਾਤ';
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split(
                '_'
            ),
            monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split(
                '_'
            ),
            monthsParse$a = [
                /^sty/i,
                /^lut/i,
                /^mar/i,
                /^kwi/i,
                /^maj/i,
                /^cze/i,
                /^lip/i,
                /^sie/i,
                /^wrz/i,
                /^paź/i,
                /^lis/i,
                /^gru/i,
            ];
        function plural$3(n) {
            return n % 10 < 5 && n % 10 > 1 && ~~(n / 10) % 10 !== 1;
        }
        function translate$8(number, withoutSuffix, key) {
            var result = number + ' ';
            switch (key) {
                case 'ss':
                    return result + (plural$3(number) ? 'sekundy' : 'sekund');
                case 'm':
                    return withoutSuffix ? 'minuta' : 'minutę';
                case 'mm':
                    return result + (plural$3(number) ? 'minuty' : 'minut');
                case 'h':
                    return withoutSuffix ? 'godzina' : 'godzinę';
                case 'hh':
                    return result + (plural$3(number) ? 'godziny' : 'godzin');
                case 'ww':
                    return result + (plural$3(number) ? 'tygodnie' : 'tygodni');
                case 'MM':
                    return result + (plural$3(number) ? 'miesiące' : 'miesięcy');
                case 'yy':
                    return result + (plural$3(number) ? 'lata' : 'lat');
            }
        }
    
        hooks.defineLocale('pl', {
            months: function (momentToFormat, format) {
                if (!momentToFormat) {
                    return monthsNominative;
                } else if (/D MMMM/.test(format)) {
                    return monthsSubjective[momentToFormat.month()];
                } else {
                    return monthsNominative[momentToFormat.month()];
                }
            },
            monthsShort: 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'),
            monthsParse: monthsParse$a,
            longMonthsParse: monthsParse$a,
            shortMonthsParse: monthsParse$a,
            weekdays: 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split(
                '_'
            ),
            weekdaysShort: 'ndz_pon_wt_śr_czw_pt_sob'.split('_'),
            weekdaysMin: 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Dziś o] LT',
                nextDay: '[Jutro o] LT',
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[W niedzielę o] LT';
    
                        case 2:
                            return '[We wtorek o] LT';
    
                        case 3:
                            return '[W środę o] LT';
    
                        case 6:
                            return '[W sobotę o] LT';
    
                        default:
                            return '[W] dddd [o] LT';
                    }
                },
                lastDay: '[Wczoraj o] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[W zeszłą niedzielę o] LT';
                        case 3:
                            return '[W zeszłą środę o] LT';
                        case 6:
                            return '[W zeszłą sobotę o] LT';
                        default:
                            return '[W zeszły] dddd [o] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'za %s',
                past: '%s temu',
                s: 'kilka sekund',
                ss: translate$8,
                m: translate$8,
                mm: translate$8,
                h: translate$8,
                hh: translate$8,
                d: '1 dzień',
                dd: '%d dni',
                w: 'tydzień',
                ww: translate$8,
                M: 'miesiąc',
                MM: translate$8,
                y: 'rok',
                yy: translate$8,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('pt-br', {
            months: 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split(
                '_'
            ),
            monthsShort: 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
            weekdays: 'domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado'.split(
                '_'
            ),
            weekdaysShort: 'dom_seg_ter_qua_qui_sex_sáb'.split('_'),
            weekdaysMin: 'do_2ª_3ª_4ª_5ª_6ª_sá'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D [de] MMMM [de] YYYY',
                LLL: 'D [de] MMMM [de] YYYY [às] HH:mm',
                LLLL: 'dddd, D [de] MMMM [de] YYYY [às] HH:mm',
            },
            calendar: {
                sameDay: '[Hoje às] LT',
                nextDay: '[Amanhã às] LT',
                nextWeek: 'dddd [às] LT',
                lastDay: '[Ontem às] LT',
                lastWeek: function () {
                    return this.day() === 0 || this.day() === 6
                        ? '[Último] dddd [às] LT' // Saturday + Sunday
                        : '[Última] dddd [às] LT'; // Monday - Friday
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'em %s',
                past: 'há %s',
                s: 'poucos segundos',
                ss: '%d segundos',
                m: 'um minuto',
                mm: '%d minutos',
                h: 'uma hora',
                hh: '%d horas',
                d: 'um dia',
                dd: '%d dias',
                M: 'um mês',
                MM: '%d meses',
                y: 'um ano',
                yy: '%d anos',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            invalidDate: 'Data inválida',
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('pt', {
            months: 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split(
                '_'
            ),
            monthsShort: 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
            weekdays: 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split(
                '_'
            ),
            weekdaysShort: 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
            weekdaysMin: 'Do_2ª_3ª_4ª_5ª_6ª_Sá'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D [de] MMMM [de] YYYY',
                LLL: 'D [de] MMMM [de] YYYY HH:mm',
                LLLL: 'dddd, D [de] MMMM [de] YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Hoje às] LT',
                nextDay: '[Amanhã às] LT',
                nextWeek: 'dddd [às] LT',
                lastDay: '[Ontem às] LT',
                lastWeek: function () {
                    return this.day() === 0 || this.day() === 6
                        ? '[Último] dddd [às] LT' // Saturday + Sunday
                        : '[Última] dddd [às] LT'; // Monday - Friday
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'em %s',
                past: 'há %s',
                s: 'segundos',
                ss: '%d segundos',
                m: 'um minuto',
                mm: '%d minutos',
                h: 'uma hora',
                hh: '%d horas',
                d: 'um dia',
                dd: '%d dias',
                w: 'uma semana',
                ww: '%d semanas',
                M: 'um mês',
                MM: '%d meses',
                y: 'um ano',
                yy: '%d anos',
            },
            dayOfMonthOrdinalParse: /\d{1,2}º/,
            ordinal: '%dº',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function relativeTimeWithPlural$2(number, withoutSuffix, key) {
            var format = {
                    ss: 'secunde',
                    mm: 'minute',
                    hh: 'ore',
                    dd: 'zile',
                    ww: 'săptămâni',
                    MM: 'luni',
                    yy: 'ani',
                },
                separator = ' ';
            if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
                separator = ' de ';
            }
            return number + separator + format[key];
        }
    
        hooks.defineLocale('ro', {
            months: 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split(
                '_'
            ),
            monthsShort: 'ian._feb._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'),
            weekdaysShort: 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'),
            weekdaysMin: 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'),
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY H:mm',
                LLLL: 'dddd, D MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[azi la] LT',
                nextDay: '[mâine la] LT',
                nextWeek: 'dddd [la] LT',
                lastDay: '[ieri la] LT',
                lastWeek: '[fosta] dddd [la] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'peste %s',
                past: '%s în urmă',
                s: 'câteva secunde',
                ss: relativeTimeWithPlural$2,
                m: 'un minut',
                mm: relativeTimeWithPlural$2,
                h: 'o oră',
                hh: relativeTimeWithPlural$2,
                d: 'o zi',
                dd: relativeTimeWithPlural$2,
                w: 'o săptămână',
                ww: relativeTimeWithPlural$2,
                M: 'o lună',
                MM: relativeTimeWithPlural$2,
                y: 'un an',
                yy: relativeTimeWithPlural$2,
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function plural$4(word, num) {
            var forms = word.split('_');
            return num % 10 === 1 && num % 100 !== 11
                ? forms[0]
                : num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20)
                ? forms[1]
                : forms[2];
        }
        function relativeTimeWithPlural$3(number, withoutSuffix, key) {
            var format = {
                ss: withoutSuffix ? 'секунда_секунды_секунд' : 'секунду_секунды_секунд',
                mm: withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
                hh: 'час_часа_часов',
                dd: 'день_дня_дней',
                ww: 'неделя_недели_недель',
                MM: 'месяц_месяца_месяцев',
                yy: 'год_года_лет',
            };
            if (key === 'm') {
                return withoutSuffix ? 'минута' : 'минуту';
            } else {
                return number + ' ' + plural$4(format[key], +number);
            }
        }
        var monthsParse$b = [
            /^янв/i,
            /^фев/i,
            /^мар/i,
            /^апр/i,
            /^ма[йя]/i,
            /^июн/i,
            /^июл/i,
            /^авг/i,
            /^сен/i,
            /^окт/i,
            /^ноя/i,
            /^дек/i,
        ];
    
        // http://new.gramota.ru/spravka/rules/139-prop : § 103
        // Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637
        // CLDR data:          http://www.unicode.org/cldr/charts/28/summary/ru.html#1753
        hooks.defineLocale('ru', {
            months: {
                format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split(
                    '_'
                ),
                standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split(
                    '_'
                ),
            },
            monthsShort: {
                // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку?
                format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split(
                    '_'
                ),
                standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split(
                    '_'
                ),
            },
            weekdays: {
                standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split(
                    '_'
                ),
                format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split(
                    '_'
                ),
                isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?] ?dddd/,
            },
            weekdaysShort: 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
            weekdaysMin: 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
            monthsParse: monthsParse$b,
            longMonthsParse: monthsParse$b,
            shortMonthsParse: monthsParse$b,
    
            // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки
            monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
    
            // копия предыдущего
            monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
    
            // полные названия с падежами
            monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,
    
            // Выражение, которое соответствует только сокращённым формам
            monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY г.',
                LLL: 'D MMMM YYYY г., H:mm',
                LLLL: 'dddd, D MMMM YYYY г., H:mm',
            },
            calendar: {
                sameDay: '[Сегодня, в] LT',
                nextDay: '[Завтра, в] LT',
                lastDay: '[Вчера, в] LT',
                nextWeek: function (now) {
                    if (now.week() !== this.week()) {
                        switch (this.day()) {
                            case 0:
                                return '[В следующее] dddd, [в] LT';
                            case 1:
                            case 2:
                            case 4:
                                return '[В следующий] dddd, [в] LT';
                            case 3:
                            case 5:
                            case 6:
                                return '[В следующую] dddd, [в] LT';
                        }
                    } else {
                        if (this.day() === 2) {
                            return '[Во] dddd, [в] LT';
                        } else {
                            return '[В] dddd, [в] LT';
                        }
                    }
                },
                lastWeek: function (now) {
                    if (now.week() !== this.week()) {
                        switch (this.day()) {
                            case 0:
                                return '[В прошлое] dddd, [в] LT';
                            case 1:
                            case 2:
                            case 4:
                                return '[В прошлый] dddd, [в] LT';
                            case 3:
                            case 5:
                            case 6:
                                return '[В прошлую] dddd, [в] LT';
                        }
                    } else {
                        if (this.day() === 2) {
                            return '[Во] dddd, [в] LT';
                        } else {
                            return '[В] dddd, [в] LT';
                        }
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'через %s',
                past: '%s назад',
                s: 'несколько секунд',
                ss: relativeTimeWithPlural$3,
                m: relativeTimeWithPlural$3,
                mm: relativeTimeWithPlural$3,
                h: 'час',
                hh: relativeTimeWithPlural$3,
                d: 'день',
                dd: relativeTimeWithPlural$3,
                w: 'неделя',
                ww: relativeTimeWithPlural$3,
                M: 'месяц',
                MM: relativeTimeWithPlural$3,
                y: 'год',
                yy: relativeTimeWithPlural$3,
            },
            meridiemParse: /ночи|утра|дня|вечера/i,
            isPM: function (input) {
                return /^(дня|вечера)$/.test(input);
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'ночи';
                } else if (hour < 12) {
                    return 'утра';
                } else if (hour < 17) {
                    return 'дня';
                } else {
                    return 'вечера';
                }
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(й|го|я)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'M':
                    case 'd':
                    case 'DDD':
                        return number + '-й';
                    case 'D':
                        return number + '-го';
                    case 'w':
                    case 'W':
                        return number + '-я';
                    default:
                        return number;
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var months$9 = [
                'جنوري',
                'فيبروري',
                'مارچ',
                'اپريل',
                'مئي',
                'جون',
                'جولاءِ',
                'آگسٽ',
                'سيپٽمبر',
                'آڪٽوبر',
                'نومبر',
                'ڊسمبر',
            ],
            days$1 = ['آچر', 'سومر', 'اڱارو', 'اربع', 'خميس', 'جمع', 'ڇنڇر'];
    
        hooks.defineLocale('sd', {
            months: months$9,
            monthsShort: months$9,
            weekdays: days$1,
            weekdaysShort: days$1,
            weekdaysMin: days$1,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd، D MMMM YYYY HH:mm',
            },
            meridiemParse: /صبح|شام/,
            isPM: function (input) {
                return 'شام' === input;
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'صبح';
                }
                return 'شام';
            },
            calendar: {
                sameDay: '[اڄ] LT',
                nextDay: '[سڀاڻي] LT',
                nextWeek: 'dddd [اڳين هفتي تي] LT',
                lastDay: '[ڪالهه] LT',
                lastWeek: '[گزريل هفتي] dddd [تي] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s پوء',
                past: '%s اڳ',
                s: 'چند سيڪنڊ',
                ss: '%d سيڪنڊ',
                m: 'هڪ منٽ',
                mm: '%d منٽ',
                h: 'هڪ ڪلاڪ',
                hh: '%d ڪلاڪ',
                d: 'هڪ ڏينهن',
                dd: '%d ڏينهن',
                M: 'هڪ مهينو',
                MM: '%d مهينا',
                y: 'هڪ سال',
                yy: '%d سال',
            },
            preparse: function (string) {
                return string.replace(/،/g, ',');
            },
            postformat: function (string) {
                return string.replace(/,/g, '،');
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('se', {
            months: 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split(
                '_'
            ),
            monthsShort: 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split(
                '_'
            ),
            weekdays: 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split(
                '_'
            ),
            weekdaysShort: 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'),
            weekdaysMin: 's_v_m_g_d_b_L'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'MMMM D. [b.] YYYY',
                LLL: 'MMMM D. [b.] YYYY [ti.] HH:mm',
                LLLL: 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm',
            },
            calendar: {
                sameDay: '[otne ti] LT',
                nextDay: '[ihttin ti] LT',
                nextWeek: 'dddd [ti] LT',
                lastDay: '[ikte ti] LT',
                lastWeek: '[ovddit] dddd [ti] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s geažes',
                past: 'maŋit %s',
                s: 'moadde sekunddat',
                ss: '%d sekunddat',
                m: 'okta minuhta',
                mm: '%d minuhtat',
                h: 'okta diimmu',
                hh: '%d diimmut',
                d: 'okta beaivi',
                dd: '%d beaivvit',
                M: 'okta mánnu',
                MM: '%d mánut',
                y: 'okta jahki',
                yy: '%d jagit',
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        /*jshint -W100*/
        hooks.defineLocale('si', {
            months: 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split(
                '_'
            ),
            monthsShort: 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split(
                '_'
            ),
            weekdays: 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split(
                '_'
            ),
            weekdaysShort: 'ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන'.split('_'),
            weekdaysMin: 'ඉ_ස_අ_බ_බ්‍ර_සි_සෙ'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'a h:mm',
                LTS: 'a h:mm:ss',
                L: 'YYYY/MM/DD',
                LL: 'YYYY MMMM D',
                LLL: 'YYYY MMMM D, a h:mm',
                LLLL: 'YYYY MMMM D [වැනි] dddd, a h:mm:ss',
            },
            calendar: {
                sameDay: '[අද] LT[ට]',
                nextDay: '[හෙට] LT[ට]',
                nextWeek: 'dddd LT[ට]',
                lastDay: '[ඊයේ] LT[ට]',
                lastWeek: '[පසුගිය] dddd LT[ට]',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%sකින්',
                past: '%sකට පෙර',
                s: 'තත්පර කිහිපය',
                ss: 'තත්පර %d',
                m: 'මිනිත්තුව',
                mm: 'මිනිත්තු %d',
                h: 'පැය',
                hh: 'පැය %d',
                d: 'දිනය',
                dd: 'දින %d',
                M: 'මාසය',
                MM: 'මාස %d',
                y: 'වසර',
                yy: 'වසර %d',
            },
            dayOfMonthOrdinalParse: /\d{1,2} වැනි/,
            ordinal: function (number) {
                return number + ' වැනි';
            },
            meridiemParse: /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,
            isPM: function (input) {
                return input === 'ප.ව.' || input === 'පස් වරු';
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours > 11) {
                    return isLower ? 'ප.ව.' : 'පස් වරු';
                } else {
                    return isLower ? 'පෙ.ව.' : 'පෙර වරු';
                }
            },
        });
    
        //! moment.js locale configuration
    
        var months$a = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split(
                '_'
            ),
            monthsShort$7 = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_');
        function plural$5(n) {
            return n > 1 && n < 5;
        }
        function translate$9(number, withoutSuffix, key, isFuture) {
            var result = number + ' ';
            switch (key) {
                case 's': // a few seconds / in a few seconds / a few seconds ago
                    return withoutSuffix || isFuture ? 'pár sekúnd' : 'pár sekundami';
                case 'ss': // 9 seconds / in 9 seconds / 9 seconds ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$5(number) ? 'sekundy' : 'sekúnd');
                    } else {
                        return result + 'sekundami';
                    }
                case 'm': // a minute / in a minute / a minute ago
                    return withoutSuffix ? 'minúta' : isFuture ? 'minútu' : 'minútou';
                case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$5(number) ? 'minúty' : 'minút');
                    } else {
                        return result + 'minútami';
                    }
                case 'h': // an hour / in an hour / an hour ago
                    return withoutSuffix ? 'hodina' : isFuture ? 'hodinu' : 'hodinou';
                case 'hh': // 9 hours / in 9 hours / 9 hours ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$5(number) ? 'hodiny' : 'hodín');
                    } else {
                        return result + 'hodinami';
                    }
                case 'd': // a day / in a day / a day ago
                    return withoutSuffix || isFuture ? 'deň' : 'dňom';
                case 'dd': // 9 days / in 9 days / 9 days ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$5(number) ? 'dni' : 'dní');
                    } else {
                        return result + 'dňami';
                    }
                case 'M': // a month / in a month / a month ago
                    return withoutSuffix || isFuture ? 'mesiac' : 'mesiacom';
                case 'MM': // 9 months / in 9 months / 9 months ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$5(number) ? 'mesiace' : 'mesiacov');
                    } else {
                        return result + 'mesiacmi';
                    }
                case 'y': // a year / in a year / a year ago
                    return withoutSuffix || isFuture ? 'rok' : 'rokom';
                case 'yy': // 9 years / in 9 years / 9 years ago
                    if (withoutSuffix || isFuture) {
                        return result + (plural$5(number) ? 'roky' : 'rokov');
                    } else {
                        return result + 'rokmi';
                    }
            }
        }
    
        hooks.defineLocale('sk', {
            months: months$a,
            monthsShort: monthsShort$7,
            weekdays: 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'),
            weekdaysShort: 'ne_po_ut_st_št_pi_so'.split('_'),
            weekdaysMin: 'ne_po_ut_st_št_pi_so'.split('_'),
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY H:mm',
                LLLL: 'dddd D. MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[dnes o] LT',
                nextDay: '[zajtra o] LT',
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[v nedeľu o] LT';
                        case 1:
                        case 2:
                            return '[v] dddd [o] LT';
                        case 3:
                            return '[v stredu o] LT';
                        case 4:
                            return '[vo štvrtok o] LT';
                        case 5:
                            return '[v piatok o] LT';
                        case 6:
                            return '[v sobotu o] LT';
                    }
                },
                lastDay: '[včera o] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[minulú nedeľu o] LT';
                        case 1:
                        case 2:
                            return '[minulý] dddd [o] LT';
                        case 3:
                            return '[minulú stredu o] LT';
                        case 4:
                        case 5:
                            return '[minulý] dddd [o] LT';
                        case 6:
                            return '[minulú sobotu o] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'za %s',
                past: 'pred %s',
                s: translate$9,
                ss: translate$9,
                m: translate$9,
                mm: translate$9,
                h: translate$9,
                hh: translate$9,
                d: translate$9,
                dd: translate$9,
                M: translate$9,
                MM: translate$9,
                y: translate$9,
                yy: translate$9,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function processRelativeTime$7(number, withoutSuffix, key, isFuture) {
            var result = number + ' ';
            switch (key) {
                case 's':
                    return withoutSuffix || isFuture
                        ? 'nekaj sekund'
                        : 'nekaj sekundami';
                case 'ss':
                    if (number === 1) {
                        result += withoutSuffix ? 'sekundo' : 'sekundi';
                    } else if (number === 2) {
                        result += withoutSuffix || isFuture ? 'sekundi' : 'sekundah';
                    } else if (number < 5) {
                        result += withoutSuffix || isFuture ? 'sekunde' : 'sekundah';
                    } else {
                        result += 'sekund';
                    }
                    return result;
                case 'm':
                    return withoutSuffix ? 'ena minuta' : 'eno minuto';
                case 'mm':
                    if (number === 1) {
                        result += withoutSuffix ? 'minuta' : 'minuto';
                    } else if (number === 2) {
                        result += withoutSuffix || isFuture ? 'minuti' : 'minutama';
                    } else if (number < 5) {
                        result += withoutSuffix || isFuture ? 'minute' : 'minutami';
                    } else {
                        result += withoutSuffix || isFuture ? 'minut' : 'minutami';
                    }
                    return result;
                case 'h':
                    return withoutSuffix ? 'ena ura' : 'eno uro';
                case 'hh':
                    if (number === 1) {
                        result += withoutSuffix ? 'ura' : 'uro';
                    } else if (number === 2) {
                        result += withoutSuffix || isFuture ? 'uri' : 'urama';
                    } else if (number < 5) {
                        result += withoutSuffix || isFuture ? 'ure' : 'urami';
                    } else {
                        result += withoutSuffix || isFuture ? 'ur' : 'urami';
                    }
                    return result;
                case 'd':
                    return withoutSuffix || isFuture ? 'en dan' : 'enim dnem';
                case 'dd':
                    if (number === 1) {
                        result += withoutSuffix || isFuture ? 'dan' : 'dnem';
                    } else if (number === 2) {
                        result += withoutSuffix || isFuture ? 'dni' : 'dnevoma';
                    } else {
                        result += withoutSuffix || isFuture ? 'dni' : 'dnevi';
                    }
                    return result;
                case 'M':
                    return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem';
                case 'MM':
                    if (number === 1) {
                        result += withoutSuffix || isFuture ? 'mesec' : 'mesecem';
                    } else if (number === 2) {
                        result += withoutSuffix || isFuture ? 'meseca' : 'mesecema';
                    } else if (number < 5) {
                        result += withoutSuffix || isFuture ? 'mesece' : 'meseci';
                    } else {
                        result += withoutSuffix || isFuture ? 'mesecev' : 'meseci';
                    }
                    return result;
                case 'y':
                    return withoutSuffix || isFuture ? 'eno leto' : 'enim letom';
                case 'yy':
                    if (number === 1) {
                        result += withoutSuffix || isFuture ? 'leto' : 'letom';
                    } else if (number === 2) {
                        result += withoutSuffix || isFuture ? 'leti' : 'letoma';
                    } else if (number < 5) {
                        result += withoutSuffix || isFuture ? 'leta' : 'leti';
                    } else {
                        result += withoutSuffix || isFuture ? 'let' : 'leti';
                    }
                    return result;
            }
        }
    
        hooks.defineLocale('sl', {
            months: 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split(
                '_'
            ),
            monthsShort: 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'),
            weekdaysShort: 'ned._pon._tor._sre._čet._pet._sob.'.split('_'),
            weekdaysMin: 'ne_po_to_sr_če_pe_so'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD. MM. YYYY',
                LL: 'D. MMMM YYYY',
                LLL: 'D. MMMM YYYY H:mm',
                LLLL: 'dddd, D. MMMM YYYY H:mm',
            },
            calendar: {
                sameDay: '[danes ob] LT',
                nextDay: '[jutri ob] LT',
    
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[v] [nedeljo] [ob] LT';
                        case 3:
                            return '[v] [sredo] [ob] LT';
                        case 6:
                            return '[v] [soboto] [ob] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[v] dddd [ob] LT';
                    }
                },
                lastDay: '[včeraj ob] LT',
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[prejšnjo] [nedeljo] [ob] LT';
                        case 3:
                            return '[prejšnjo] [sredo] [ob] LT';
                        case 6:
                            return '[prejšnjo] [soboto] [ob] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[prejšnji] dddd [ob] LT';
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'čez %s',
                past: 'pred %s',
                s: processRelativeTime$7,
                ss: processRelativeTime$7,
                m: processRelativeTime$7,
                mm: processRelativeTime$7,
                h: processRelativeTime$7,
                hh: processRelativeTime$7,
                d: processRelativeTime$7,
                dd: processRelativeTime$7,
                M: processRelativeTime$7,
                MM: processRelativeTime$7,
                y: processRelativeTime$7,
                yy: processRelativeTime$7,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('sq', {
            months: 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split(
                '_'
            ),
            monthsShort: 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'),
            weekdays: 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split(
                '_'
            ),
            weekdaysShort: 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'),
            weekdaysMin: 'D_H_Ma_Më_E_P_Sh'.split('_'),
            weekdaysParseExact: true,
            meridiemParse: /PD|MD/,
            isPM: function (input) {
                return input.charAt(0) === 'M';
            },
            meridiem: function (hours, minutes, isLower) {
                return hours < 12 ? 'PD' : 'MD';
            },
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Sot në] LT',
                nextDay: '[Nesër në] LT',
                nextWeek: 'dddd [në] LT',
                lastDay: '[Dje në] LT',
                lastWeek: 'dddd [e kaluar në] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'në %s',
                past: '%s më parë',
                s: 'disa sekonda',
                ss: '%d sekonda',
                m: 'një minutë',
                mm: '%d minuta',
                h: 'një orë',
                hh: '%d orë',
                d: 'një ditë',
                dd: '%d ditë',
                M: 'një muaj',
                MM: '%d muaj',
                y: 'një vit',
                yy: '%d vite',
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var translator$1 = {
            words: {
                //Different grammatical cases
                ss: ['секунда', 'секунде', 'секунди'],
                m: ['један минут', 'једне минуте'],
                mm: ['минут', 'минуте', 'минута'],
                h: ['један сат', 'једног сата'],
                hh: ['сат', 'сата', 'сати'],
                dd: ['дан', 'дана', 'дана'],
                MM: ['месец', 'месеца', 'месеци'],
                yy: ['година', 'године', 'година'],
            },
            correctGrammaticalCase: function (number, wordKey) {
                return number === 1
                    ? wordKey[0]
                    : number >= 2 && number <= 4
                    ? wordKey[1]
                    : wordKey[2];
            },
            translate: function (number, withoutSuffix, key) {
                var wordKey = translator$1.words[key];
                if (key.length === 1) {
                    return withoutSuffix ? wordKey[0] : wordKey[1];
                } else {
                    return (
                        number +
                        ' ' +
                        translator$1.correctGrammaticalCase(number, wordKey)
                    );
                }
            },
        };
    
        hooks.defineLocale('sr-cyrl', {
            months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split(
                '_'
            ),
            monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'),
            weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'),
            weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'D. M. YYYY.',
                LL: 'D. MMMM YYYY.',
                LLL: 'D. MMMM YYYY. H:mm',
                LLLL: 'dddd, D. MMMM YYYY. H:mm',
            },
            calendar: {
                sameDay: '[данас у] LT',
                nextDay: '[сутра у] LT',
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[у] [недељу] [у] LT';
                        case 3:
                            return '[у] [среду] [у] LT';
                        case 6:
                            return '[у] [суботу] [у] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[у] dddd [у] LT';
                    }
                },
                lastDay: '[јуче у] LT',
                lastWeek: function () {
                    var lastWeekDays = [
                        '[прошле] [недеље] [у] LT',
                        '[прошлог] [понедељка] [у] LT',
                        '[прошлог] [уторка] [у] LT',
                        '[прошле] [среде] [у] LT',
                        '[прошлог] [четвртка] [у] LT',
                        '[прошлог] [петка] [у] LT',
                        '[прошле] [суботе] [у] LT',
                    ];
                    return lastWeekDays[this.day()];
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'за %s',
                past: 'пре %s',
                s: 'неколико секунди',
                ss: translator$1.translate,
                m: translator$1.translate,
                mm: translator$1.translate,
                h: translator$1.translate,
                hh: translator$1.translate,
                d: 'дан',
                dd: translator$1.translate,
                M: 'месец',
                MM: translator$1.translate,
                y: 'годину',
                yy: translator$1.translate,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 1st is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var translator$2 = {
            words: {
                //Different grammatical cases
                ss: ['sekunda', 'sekunde', 'sekundi'],
                m: ['jedan minut', 'jedne minute'],
                mm: ['minut', 'minute', 'minuta'],
                h: ['jedan sat', 'jednog sata'],
                hh: ['sat', 'sata', 'sati'],
                dd: ['dan', 'dana', 'dana'],
                MM: ['mesec', 'meseca', 'meseci'],
                yy: ['godina', 'godine', 'godina'],
            },
            correctGrammaticalCase: function (number, wordKey) {
                return number === 1
                    ? wordKey[0]
                    : number >= 2 && number <= 4
                    ? wordKey[1]
                    : wordKey[2];
            },
            translate: function (number, withoutSuffix, key) {
                var wordKey = translator$2.words[key];
                if (key.length === 1) {
                    return withoutSuffix ? wordKey[0] : wordKey[1];
                } else {
                    return (
                        number +
                        ' ' +
                        translator$2.correctGrammaticalCase(number, wordKey)
                    );
                }
            },
        };
    
        hooks.defineLocale('sr', {
            months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split(
                '_'
            ),
            monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split(
                '_'
            ),
            weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'),
            weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'D. M. YYYY.',
                LL: 'D. MMMM YYYY.',
                LLL: 'D. MMMM YYYY. H:mm',
                LLLL: 'dddd, D. MMMM YYYY. H:mm',
            },
            calendar: {
                sameDay: '[danas u] LT',
                nextDay: '[sutra u] LT',
                nextWeek: function () {
                    switch (this.day()) {
                        case 0:
                            return '[u] [nedelju] [u] LT';
                        case 3:
                            return '[u] [sredu] [u] LT';
                        case 6:
                            return '[u] [subotu] [u] LT';
                        case 1:
                        case 2:
                        case 4:
                        case 5:
                            return '[u] dddd [u] LT';
                    }
                },
                lastDay: '[juče u] LT',
                lastWeek: function () {
                    var lastWeekDays = [
                        '[prošle] [nedelje] [u] LT',
                        '[prošlog] [ponedeljka] [u] LT',
                        '[prošlog] [utorka] [u] LT',
                        '[prošle] [srede] [u] LT',
                        '[prošlog] [četvrtka] [u] LT',
                        '[prošlog] [petka] [u] LT',
                        '[prošle] [subote] [u] LT',
                    ];
                    return lastWeekDays[this.day()];
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'za %s',
                past: 'pre %s',
                s: 'nekoliko sekundi',
                ss: translator$2.translate,
                m: translator$2.translate,
                mm: translator$2.translate,
                h: translator$2.translate,
                hh: translator$2.translate,
                d: 'dan',
                dd: translator$2.translate,
                M: 'mesec',
                MM: translator$2.translate,
                y: 'godinu',
                yy: translator$2.translate,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ss', {
            months: "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split(
                '_'
            ),
            monthsShort: 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'),
            weekdays: 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split(
                '_'
            ),
            weekdaysShort: 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'),
            weekdaysMin: 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY h:mm A',
                LLLL: 'dddd, D MMMM YYYY h:mm A',
            },
            calendar: {
                sameDay: '[Namuhla nga] LT',
                nextDay: '[Kusasa nga] LT',
                nextWeek: 'dddd [nga] LT',
                lastDay: '[Itolo nga] LT',
                lastWeek: 'dddd [leliphelile] [nga] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'nga %s',
                past: 'wenteka nga %s',
                s: 'emizuzwana lomcane',
                ss: '%d mzuzwana',
                m: 'umzuzu',
                mm: '%d emizuzu',
                h: 'lihora',
                hh: '%d emahora',
                d: 'lilanga',
                dd: '%d emalanga',
                M: 'inyanga',
                MM: '%d tinyanga',
                y: 'umnyaka',
                yy: '%d iminyaka',
            },
            meridiemParse: /ekuseni|emini|entsambama|ebusuku/,
            meridiem: function (hours, minutes, isLower) {
                if (hours < 11) {
                    return 'ekuseni';
                } else if (hours < 15) {
                    return 'emini';
                } else if (hours < 19) {
                    return 'entsambama';
                } else {
                    return 'ebusuku';
                }
            },
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'ekuseni') {
                    return hour;
                } else if (meridiem === 'emini') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') {
                    if (hour === 0) {
                        return 0;
                    }
                    return hour + 12;
                }
            },
            dayOfMonthOrdinalParse: /\d{1,2}/,
            ordinal: '%d',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('sv', {
            months: 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split(
                '_'
            ),
            monthsShort: 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
            weekdays: 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'),
            weekdaysShort: 'sön_mån_tis_ons_tor_fre_lör'.split('_'),
            weekdaysMin: 'sö_må_ti_on_to_fr_lö'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY-MM-DD',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY [kl.] HH:mm',
                LLLL: 'dddd D MMMM YYYY [kl.] HH:mm',
                lll: 'D MMM YYYY HH:mm',
                llll: 'ddd D MMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Idag] LT',
                nextDay: '[Imorgon] LT',
                lastDay: '[Igår] LT',
                nextWeek: '[På] dddd LT',
                lastWeek: '[I] dddd[s] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'om %s',
                past: 'för %s sedan',
                s: 'några sekunder',
                ss: '%d sekunder',
                m: 'en minut',
                mm: '%d minuter',
                h: 'en timme',
                hh: '%d timmar',
                d: 'en dag',
                dd: '%d dagar',
                M: 'en månad',
                MM: '%d månader',
                y: 'ett år',
                yy: '%d år',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(\:e|\:a)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? ':e'
                            : b === 1
                            ? ':a'
                            : b === 2
                            ? ':a'
                            : b === 3
                            ? ':e'
                            : ':e';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('sw', {
            months: 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split(
                '_'
            ),
            monthsShort: 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'),
            weekdays: 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split(
                '_'
            ),
            weekdaysShort: 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'),
            weekdaysMin: 'J2_J3_J4_J5_Al_Ij_J1'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'hh:mm A',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[leo saa] LT',
                nextDay: '[kesho saa] LT',
                nextWeek: '[wiki ijayo] dddd [saat] LT',
                lastDay: '[jana] LT',
                lastWeek: '[wiki iliyopita] dddd [saat] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s baadaye',
                past: 'tokea %s',
                s: 'hivi punde',
                ss: 'sekunde %d',
                m: 'dakika moja',
                mm: 'dakika %d',
                h: 'saa limoja',
                hh: 'masaa %d',
                d: 'siku moja',
                dd: 'siku %d',
                M: 'mwezi mmoja',
                MM: 'miezi %d',
                y: 'mwaka mmoja',
                yy: 'miaka %d',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var symbolMap$g = {
                1: '௧',
                2: '௨',
                3: '௩',
                4: '௪',
                5: '௫',
                6: '௬',
                7: '௭',
                8: '௮',
                9: '௯',
                0: '௦',
            },
            numberMap$f = {
                '௧': '1',
                '௨': '2',
                '௩': '3',
                '௪': '4',
                '௫': '5',
                '௬': '6',
                '௭': '7',
                '௮': '8',
                '௯': '9',
                '௦': '0',
            };
    
        hooks.defineLocale('ta', {
            months: 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split(
                '_'
            ),
            monthsShort: 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split(
                '_'
            ),
            weekdays: 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split(
                '_'
            ),
            weekdaysShort: 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split(
                '_'
            ),
            weekdaysMin: 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, HH:mm',
                LLLL: 'dddd, D MMMM YYYY, HH:mm',
            },
            calendar: {
                sameDay: '[இன்று] LT',
                nextDay: '[நாளை] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[நேற்று] LT',
                lastWeek: '[கடந்த வாரம்] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s இல்',
                past: '%s முன்',
                s: 'ஒரு சில விநாடிகள்',
                ss: '%d விநாடிகள்',
                m: 'ஒரு நிமிடம்',
                mm: '%d நிமிடங்கள்',
                h: 'ஒரு மணி நேரம்',
                hh: '%d மணி நேரம்',
                d: 'ஒரு நாள்',
                dd: '%d நாட்கள்',
                M: 'ஒரு மாதம்',
                MM: '%d மாதங்கள்',
                y: 'ஒரு வருடம்',
                yy: '%d ஆண்டுகள்',
            },
            dayOfMonthOrdinalParse: /\d{1,2}வது/,
            ordinal: function (number) {
                return number + 'வது';
            },
            preparse: function (string) {
                return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
                    return numberMap$f[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$g[match];
                });
            },
            // refer http://ta.wikipedia.org/s/1er1
            meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,
            meridiem: function (hour, minute, isLower) {
                if (hour < 2) {
                    return ' யாமம்';
                } else if (hour < 6) {
                    return ' வைகறை'; // வைகறை
                } else if (hour < 10) {
                    return ' காலை'; // காலை
                } else if (hour < 14) {
                    return ' நண்பகல்'; // நண்பகல்
                } else if (hour < 18) {
                    return ' எற்பாடு'; // எற்பாடு
                } else if (hour < 22) {
                    return ' மாலை'; // மாலை
                } else {
                    return ' யாமம்';
                }
            },
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'யாமம்') {
                    return hour < 2 ? hour : hour + 12;
                } else if (meridiem === 'வைகறை' || meridiem === 'காலை') {
                    return hour;
                } else if (meridiem === 'நண்பகல்') {
                    return hour >= 10 ? hour : hour + 12;
                } else {
                    return hour + 12;
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('te', {
            months: 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జులై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split(
                '_'
            ),
            monthsShort: 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జులై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split(
                '_'
            ),
            weekdaysShort: 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'),
            weekdaysMin: 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'),
            longDateFormat: {
                LT: 'A h:mm',
                LTS: 'A h:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY, A h:mm',
                LLLL: 'dddd, D MMMM YYYY, A h:mm',
            },
            calendar: {
                sameDay: '[నేడు] LT',
                nextDay: '[రేపు] LT',
                nextWeek: 'dddd, LT',
                lastDay: '[నిన్న] LT',
                lastWeek: '[గత] dddd, LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s లో',
                past: '%s క్రితం',
                s: 'కొన్ని క్షణాలు',
                ss: '%d సెకన్లు',
                m: 'ఒక నిమిషం',
                mm: '%d నిమిషాలు',
                h: 'ఒక గంట',
                hh: '%d గంటలు',
                d: 'ఒక రోజు',
                dd: '%d రోజులు',
                M: 'ఒక నెల',
                MM: '%d నెలలు',
                y: 'ఒక సంవత్సరం',
                yy: '%d సంవత్సరాలు',
            },
            dayOfMonthOrdinalParse: /\d{1,2}వ/,
            ordinal: '%dవ',
            meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'రాత్రి') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'ఉదయం') {
                    return hour;
                } else if (meridiem === 'మధ్యాహ్నం') {
                    return hour >= 10 ? hour : hour + 12;
                } else if (meridiem === 'సాయంత్రం') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'రాత్రి';
                } else if (hour < 10) {
                    return 'ఉదయం';
                } else if (hour < 17) {
                    return 'మధ్యాహ్నం';
                } else if (hour < 20) {
                    return 'సాయంత్రం';
                } else {
                    return 'రాత్రి';
                }
            },
            week: {
                dow: 0, // Sunday is the first day of the week.
                doy: 6, // The week that contains Jan 6th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('tet', {
            months: 'Janeiru_Fevereiru_Marsu_Abril_Maiu_Juñu_Jullu_Agustu_Setembru_Outubru_Novembru_Dezembru'.split(
                '_'
            ),
            monthsShort: 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'),
            weekdays: 'Domingu_Segunda_Tersa_Kuarta_Kinta_Sesta_Sabadu'.split('_'),
            weekdaysShort: 'Dom_Seg_Ters_Kua_Kint_Sest_Sab'.split('_'),
            weekdaysMin: 'Do_Seg_Te_Ku_Ki_Ses_Sa'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Ohin iha] LT',
                nextDay: '[Aban iha] LT',
                nextWeek: 'dddd [iha] LT',
                lastDay: '[Horiseik iha] LT',
                lastWeek: 'dddd [semana kotuk] [iha] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'iha %s',
                past: '%s liuba',
                s: 'segundu balun',
                ss: 'segundu %d',
                m: 'minutu ida',
                mm: 'minutu %d',
                h: 'oras ida',
                hh: 'oras %d',
                d: 'loron ida',
                dd: 'loron %d',
                M: 'fulan ida',
                MM: 'fulan %d',
                y: 'tinan ida',
                yy: 'tinan %d',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var suffixes$3 = {
            0: '-ум',
            1: '-ум',
            2: '-юм',
            3: '-юм',
            4: '-ум',
            5: '-ум',
            6: '-ум',
            7: '-ум',
            8: '-ум',
            9: '-ум',
            10: '-ум',
            12: '-ум',
            13: '-ум',
            20: '-ум',
            30: '-юм',
            40: '-ум',
            50: '-ум',
            60: '-ум',
            70: '-ум',
            80: '-ум',
            90: '-ум',
            100: '-ум',
        };
    
        hooks.defineLocale('tg', {
            months: {
                format: 'январи_феврали_марти_апрели_майи_июни_июли_августи_сентябри_октябри_ноябри_декабри'.split(
                    '_'
                ),
                standalone: 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split(
                    '_'
                ),
            },
            monthsShort: 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'),
            weekdays: 'якшанбе_душанбе_сешанбе_чоршанбе_панҷшанбе_ҷумъа_шанбе'.split(
                '_'
            ),
            weekdaysShort: 'яшб_дшб_сшб_чшб_пшб_ҷум_шнб'.split('_'),
            weekdaysMin: 'яш_дш_сш_чш_пш_ҷм_шб'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Имрӯз соати] LT',
                nextDay: '[Фардо соати] LT',
                lastDay: '[Дирӯз соати] LT',
                nextWeek: 'dddd[и] [ҳафтаи оянда соати] LT',
                lastWeek: 'dddd[и] [ҳафтаи гузашта соати] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'баъди %s',
                past: '%s пеш',
                s: 'якчанд сония',
                m: 'як дақиқа',
                mm: '%d дақиқа',
                h: 'як соат',
                hh: '%d соат',
                d: 'як рӯз',
                dd: '%d рӯз',
                M: 'як моҳ',
                MM: '%d моҳ',
                y: 'як сол',
                yy: '%d сол',
            },
            meridiemParse: /шаб|субҳ|рӯз|бегоҳ/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'шаб') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'субҳ') {
                    return hour;
                } else if (meridiem === 'рӯз') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === 'бегоҳ') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'шаб';
                } else if (hour < 11) {
                    return 'субҳ';
                } else if (hour < 16) {
                    return 'рӯз';
                } else if (hour < 19) {
                    return 'бегоҳ';
                } else {
                    return 'шаб';
                }
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(ум|юм)/,
            ordinal: function (number) {
                var a = number % 10,
                    b = number >= 100 ? 100 : null;
                return number + (suffixes$3[number] || suffixes$3[a] || suffixes$3[b]);
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 1th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('th', {
            months: 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split(
                '_'
            ),
            monthsShort: 'ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'),
            weekdaysShort: 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference
            weekdaysMin: 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'H:mm',
                LTS: 'H:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY เวลา H:mm',
                LLLL: 'วันddddที่ D MMMM YYYY เวลา H:mm',
            },
            meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/,
            isPM: function (input) {
                return input === 'หลังเที่ยง';
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'ก่อนเที่ยง';
                } else {
                    return 'หลังเที่ยง';
                }
            },
            calendar: {
                sameDay: '[วันนี้ เวลา] LT',
                nextDay: '[พรุ่งนี้ เวลา] LT',
                nextWeek: 'dddd[หน้า เวลา] LT',
                lastDay: '[เมื่อวานนี้ เวลา] LT',
                lastWeek: '[วัน]dddd[ที่แล้ว เวลา] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'อีก %s',
                past: '%sที่แล้ว',
                s: 'ไม่กี่วินาที',
                ss: '%d วินาที',
                m: '1 นาที',
                mm: '%d นาที',
                h: '1 ชั่วโมง',
                hh: '%d ชั่วโมง',
                d: '1 วัน',
                dd: '%d วัน',
                w: '1 สัปดาห์',
                ww: '%d สัปดาห์',
                M: '1 เดือน',
                MM: '%d เดือน',
                y: '1 ปี',
                yy: '%d ปี',
            },
        });
    
        //! moment.js locale configuration
    
        var suffixes$4 = {
            1: "'inji",
            5: "'inji",
            8: "'inji",
            70: "'inji",
            80: "'inji",
            2: "'nji",
            7: "'nji",
            20: "'nji",
            50: "'nji",
            3: "'ünji",
            4: "'ünji",
            100: "'ünji",
            6: "'njy",
            9: "'unjy",
            10: "'unjy",
            30: "'unjy",
            60: "'ynjy",
            90: "'ynjy",
        };
    
        hooks.defineLocale('tk', {
            months: 'Ýanwar_Fewral_Mart_Aprel_Maý_Iýun_Iýul_Awgust_Sentýabr_Oktýabr_Noýabr_Dekabr'.split(
                '_'
            ),
            monthsShort: 'Ýan_Few_Mar_Apr_Maý_Iýn_Iýl_Awg_Sen_Okt_Noý_Dek'.split('_'),
            weekdays: 'Ýekşenbe_Duşenbe_Sişenbe_Çarşenbe_Penşenbe_Anna_Şenbe'.split(
                '_'
            ),
            weekdaysShort: 'Ýek_Duş_Siş_Çar_Pen_Ann_Şen'.split('_'),
            weekdaysMin: 'Ýk_Dş_Sş_Çr_Pn_An_Şn'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[bugün sagat] LT',
                nextDay: '[ertir sagat] LT',
                nextWeek: '[indiki] dddd [sagat] LT',
                lastDay: '[düýn] LT',
                lastWeek: '[geçen] dddd [sagat] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s soň',
                past: '%s öň',
                s: 'birnäçe sekunt',
                m: 'bir minut',
                mm: '%d minut',
                h: 'bir sagat',
                hh: '%d sagat',
                d: 'bir gün',
                dd: '%d gün',
                M: 'bir aý',
                MM: '%d aý',
                y: 'bir ýyl',
                yy: '%d ýyl',
            },
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'Do':
                    case 'DD':
                        return number;
                    default:
                        if (number === 0) {
                            // special case for zero
                            return number + "'unjy";
                        }
                        var a = number % 10,
                            b = (number % 100) - a,
                            c = number >= 100 ? 100 : null;
                        return number + (suffixes$4[a] || suffixes$4[b] || suffixes$4[c]);
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('tl-ph', {
            months: 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split(
                '_'
            ),
            monthsShort: 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'),
            weekdays: 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split(
                '_'
            ),
            weekdaysShort: 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'),
            weekdaysMin: 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'MM/D/YYYY',
                LL: 'MMMM D, YYYY',
                LLL: 'MMMM D, YYYY HH:mm',
                LLLL: 'dddd, MMMM DD, YYYY HH:mm',
            },
            calendar: {
                sameDay: 'LT [ngayong araw]',
                nextDay: '[Bukas ng] LT',
                nextWeek: 'LT [sa susunod na] dddd',
                lastDay: 'LT [kahapon]',
                lastWeek: 'LT [noong nakaraang] dddd',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'sa loob ng %s',
                past: '%s ang nakalipas',
                s: 'ilang segundo',
                ss: '%d segundo',
                m: 'isang minuto',
                mm: '%d minuto',
                h: 'isang oras',
                hh: '%d oras',
                d: 'isang araw',
                dd: '%d araw',
                M: 'isang buwan',
                MM: '%d buwan',
                y: 'isang taon',
                yy: '%d taon',
            },
            dayOfMonthOrdinalParse: /\d{1,2}/,
            ordinal: function (number) {
                return number;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_');
    
        function translateFuture(output) {
            var time = output;
            time =
                output.indexOf('jaj') !== -1
                    ? time.slice(0, -3) + 'leS'
                    : output.indexOf('jar') !== -1
                    ? time.slice(0, -3) + 'waQ'
                    : output.indexOf('DIS') !== -1
                    ? time.slice(0, -3) + 'nem'
                    : time + ' pIq';
            return time;
        }
    
        function translatePast(output) {
            var time = output;
            time =
                output.indexOf('jaj') !== -1
                    ? time.slice(0, -3) + 'Hu’'
                    : output.indexOf('jar') !== -1
                    ? time.slice(0, -3) + 'wen'
                    : output.indexOf('DIS') !== -1
                    ? time.slice(0, -3) + 'ben'
                    : time + ' ret';
            return time;
        }
    
        function translate$a(number, withoutSuffix, string, isFuture) {
            var numberNoun = numberAsNoun(number);
            switch (string) {
                case 'ss':
                    return numberNoun + ' lup';
                case 'mm':
                    return numberNoun + ' tup';
                case 'hh':
                    return numberNoun + ' rep';
                case 'dd':
                    return numberNoun + ' jaj';
                case 'MM':
                    return numberNoun + ' jar';
                case 'yy':
                    return numberNoun + ' DIS';
            }
        }
    
        function numberAsNoun(number) {
            var hundred = Math.floor((number % 1000) / 100),
                ten = Math.floor((number % 100) / 10),
                one = number % 10,
                word = '';
            if (hundred > 0) {
                word += numbersNouns[hundred] + 'vatlh';
            }
            if (ten > 0) {
                word += (word !== '' ? ' ' : '') + numbersNouns[ten] + 'maH';
            }
            if (one > 0) {
                word += (word !== '' ? ' ' : '') + numbersNouns[one];
            }
            return word === '' ? 'pagh' : word;
        }
    
        hooks.defineLocale('tlh', {
            months: 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split(
                '_'
            ),
            monthsShort: 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split(
                '_'
            ),
            weekdaysShort: 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split(
                '_'
            ),
            weekdaysMin: 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split(
                '_'
            ),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[DaHjaj] LT',
                nextDay: '[wa’leS] LT',
                nextWeek: 'LLL',
                lastDay: '[wa’Hu’] LT',
                lastWeek: 'LLL',
                sameElse: 'L',
            },
            relativeTime: {
                future: translateFuture,
                past: translatePast,
                s: 'puS lup',
                ss: translate$a,
                m: 'wa’ tup',
                mm: translate$a,
                h: 'wa’ rep',
                hh: translate$a,
                d: 'wa’ jaj',
                dd: translate$a,
                M: 'wa’ jar',
                MM: translate$a,
                y: 'wa’ DIS',
                yy: translate$a,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var suffixes$5 = {
            1: "'inci",
            5: "'inci",
            8: "'inci",
            70: "'inci",
            80: "'inci",
            2: "'nci",
            7: "'nci",
            20: "'nci",
            50: "'nci",
            3: "'üncü",
            4: "'üncü",
            100: "'üncü",
            6: "'ncı",
            9: "'uncu",
            10: "'uncu",
            30: "'uncu",
            60: "'ıncı",
            90: "'ıncı",
        };
    
        hooks.defineLocale('tr', {
            months: 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split(
                '_'
            ),
            monthsShort: 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
            weekdays: 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split(
                '_'
            ),
            weekdaysShort: 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
            weekdaysMin: 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
            meridiem: function (hours, minutes, isLower) {
                if (hours < 12) {
                    return isLower ? 'öö' : 'ÖÖ';
                } else {
                    return isLower ? 'ös' : 'ÖS';
                }
            },
            meridiemParse: /öö|ÖÖ|ös|ÖS/,
            isPM: function (input) {
                return input === 'ös' || input === 'ÖS';
            },
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[bugün saat] LT',
                nextDay: '[yarın saat] LT',
                nextWeek: '[gelecek] dddd [saat] LT',
                lastDay: '[dün] LT',
                lastWeek: '[geçen] dddd [saat] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s sonra',
                past: '%s önce',
                s: 'birkaç saniye',
                ss: '%d saniye',
                m: 'bir dakika',
                mm: '%d dakika',
                h: 'bir saat',
                hh: '%d saat',
                d: 'bir gün',
                dd: '%d gün',
                w: 'bir hafta',
                ww: '%d hafta',
                M: 'bir ay',
                MM: '%d ay',
                y: 'bir yıl',
                yy: '%d yıl',
            },
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'Do':
                    case 'DD':
                        return number;
                    default:
                        if (number === 0) {
                            // special case for zero
                            return number + "'ıncı";
                        }
                        var a = number % 10,
                            b = (number % 100) - a,
                            c = number >= 100 ? 100 : null;
                        return number + (suffixes$5[a] || suffixes$5[b] || suffixes$5[c]);
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        // After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals.
        // This is currently too difficult (maybe even impossible) to add.
        hooks.defineLocale('tzl', {
            months: 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split(
                '_'
            ),
            monthsShort: 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'),
            weekdays: 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'),
            weekdaysShort: 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'),
            weekdaysMin: 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'),
            longDateFormat: {
                LT: 'HH.mm',
                LTS: 'HH.mm.ss',
                L: 'DD.MM.YYYY',
                LL: 'D. MMMM [dallas] YYYY',
                LLL: 'D. MMMM [dallas] YYYY HH.mm',
                LLLL: 'dddd, [li] D. MMMM [dallas] YYYY HH.mm',
            },
            meridiemParse: /d\'o|d\'a/i,
            isPM: function (input) {
                return "d'o" === input.toLowerCase();
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours > 11) {
                    return isLower ? "d'o" : "D'O";
                } else {
                    return isLower ? "d'a" : "D'A";
                }
            },
            calendar: {
                sameDay: '[oxhi à] LT',
                nextDay: '[demà à] LT',
                nextWeek: 'dddd [à] LT',
                lastDay: '[ieiri à] LT',
                lastWeek: '[sür el] dddd [lasteu à] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'osprei %s',
                past: 'ja%s',
                s: processRelativeTime$8,
                ss: processRelativeTime$8,
                m: processRelativeTime$8,
                mm: processRelativeTime$8,
                h: processRelativeTime$8,
                hh: processRelativeTime$8,
                d: processRelativeTime$8,
                dd: processRelativeTime$8,
                M: processRelativeTime$8,
                MM: processRelativeTime$8,
                y: processRelativeTime$8,
                yy: processRelativeTime$8,
            },
            dayOfMonthOrdinalParse: /\d{1,2}\./,
            ordinal: '%d.',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        function processRelativeTime$8(number, withoutSuffix, key, isFuture) {
            var format = {
                s: ['viensas secunds', "'iensas secunds"],
                ss: [number + ' secunds', '' + number + ' secunds'],
                m: ["'n míut", "'iens míut"],
                mm: [number + ' míuts', '' + number + ' míuts'],
                h: ["'n þora", "'iensa þora"],
                hh: [number + ' þoras', '' + number + ' þoras'],
                d: ["'n ziua", "'iensa ziua"],
                dd: [number + ' ziuas', '' + number + ' ziuas'],
                M: ["'n mes", "'iens mes"],
                MM: [number + ' mesen', '' + number + ' mesen'],
                y: ["'n ar", "'iens ar"],
                yy: [number + ' ars', '' + number + ' ars'],
            };
            return isFuture
                ? format[key][0]
                : withoutSuffix
                ? format[key][0]
                : format[key][1];
        }
    
        //! moment.js locale configuration
    
        hooks.defineLocale('tzm-latn', {
            months: 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split(
                '_'
            ),
            monthsShort: 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split(
                '_'
            ),
            weekdays: 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
            weekdaysShort: 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
            weekdaysMin: 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[asdkh g] LT',
                nextDay: '[aska g] LT',
                nextWeek: 'dddd [g] LT',
                lastDay: '[assant g] LT',
                lastWeek: 'dddd [g] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'dadkh s yan %s',
                past: 'yan %s',
                s: 'imik',
                ss: '%d imik',
                m: 'minuḍ',
                mm: '%d minuḍ',
                h: 'saɛa',
                hh: '%d tassaɛin',
                d: 'ass',
                dd: '%d ossan',
                M: 'ayowr',
                MM: '%d iyyirn',
                y: 'asgas',
                yy: '%d isgasn',
            },
            week: {
                dow: 6, // Saturday is the first day of the week.
                doy: 12, // The week that contains Jan 12th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('tzm', {
            months: 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split(
                '_'
            ),
            monthsShort: 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split(
                '_'
            ),
            weekdays: 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
            weekdaysShort: 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
            weekdaysMin: 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[ⴰⵙⴷⵅ ⴴ] LT',
                nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
                nextWeek: 'dddd [ⴴ] LT',
                lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
                lastWeek: 'dddd [ⴴ] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s',
                past: 'ⵢⴰⵏ %s',
                s: 'ⵉⵎⵉⴽ',
                ss: '%d ⵉⵎⵉⴽ',
                m: 'ⵎⵉⵏⵓⴺ',
                mm: '%d ⵎⵉⵏⵓⴺ',
                h: 'ⵙⴰⵄⴰ',
                hh: '%d ⵜⴰⵙⵙⴰⵄⵉⵏ',
                d: 'ⴰⵙⵙ',
                dd: '%d oⵙⵙⴰⵏ',
                M: 'ⴰⵢoⵓⵔ',
                MM: '%d ⵉⵢⵢⵉⵔⵏ',
                y: 'ⴰⵙⴳⴰⵙ',
                yy: '%d ⵉⵙⴳⴰⵙⵏ',
            },
            week: {
                dow: 6, // Saturday is the first day of the week.
                doy: 12, // The week that contains Jan 12th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('ug-cn', {
            months: 'يانۋار_فېۋرال_مارت_ئاپرېل_ماي_ئىيۇن_ئىيۇل_ئاۋغۇست_سېنتەبىر_ئۆكتەبىر_نويابىر_دېكابىر'.split(
                '_'
            ),
            monthsShort: 'يانۋار_فېۋرال_مارت_ئاپرېل_ماي_ئىيۇن_ئىيۇل_ئاۋغۇست_سېنتەبىر_ئۆكتەبىر_نويابىر_دېكابىر'.split(
                '_'
            ),
            weekdays: 'يەكشەنبە_دۈشەنبە_سەيشەنبە_چارشەنبە_پەيشەنبە_جۈمە_شەنبە'.split(
                '_'
            ),
            weekdaysShort: 'يە_دۈ_سە_چا_پە_جۈ_شە'.split('_'),
            weekdaysMin: 'يە_دۈ_سە_چا_پە_جۈ_شە'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY-MM-DD',
                LL: 'YYYY-يىلىM-ئاينىڭD-كۈنى',
                LLL: 'YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm',
                LLLL: 'dddd، YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm',
            },
            meridiemParse: /يېرىم كېچە|سەھەر|چۈشتىن بۇرۇن|چۈش|چۈشتىن كېيىن|كەچ/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (
                    meridiem === 'يېرىم كېچە' ||
                    meridiem === 'سەھەر' ||
                    meridiem === 'چۈشتىن بۇرۇن'
                ) {
                    return hour;
                } else if (meridiem === 'چۈشتىن كېيىن' || meridiem === 'كەچ') {
                    return hour + 12;
                } else {
                    return hour >= 11 ? hour : hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                var hm = hour * 100 + minute;
                if (hm < 600) {
                    return 'يېرىم كېچە';
                } else if (hm < 900) {
                    return 'سەھەر';
                } else if (hm < 1130) {
                    return 'چۈشتىن بۇرۇن';
                } else if (hm < 1230) {
                    return 'چۈش';
                } else if (hm < 1800) {
                    return 'چۈشتىن كېيىن';
                } else {
                    return 'كەچ';
                }
            },
            calendar: {
                sameDay: '[بۈگۈن سائەت] LT',
                nextDay: '[ئەتە سائەت] LT',
                nextWeek: '[كېلەركى] dddd [سائەت] LT',
                lastDay: '[تۆنۈگۈن] LT',
                lastWeek: '[ئالدىنقى] dddd [سائەت] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s كېيىن',
                past: '%s بۇرۇن',
                s: 'نەچچە سېكونت',
                ss: '%d سېكونت',
                m: 'بىر مىنۇت',
                mm: '%d مىنۇت',
                h: 'بىر سائەت',
                hh: '%d سائەت',
                d: 'بىر كۈن',
                dd: '%d كۈن',
                M: 'بىر ئاي',
                MM: '%d ئاي',
                y: 'بىر يىل',
                yy: '%d يىل',
            },
    
            dayOfMonthOrdinalParse: /\d{1,2}(-كۈنى|-ئاي|-ھەپتە)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'DDD':
                        return number + '-كۈنى';
                    case 'w':
                    case 'W':
                        return number + '-ھەپتە';
                    default:
                        return number;
                }
            },
            preparse: function (string) {
                return string.replace(/،/g, ',');
            },
            postformat: function (string) {
                return string.replace(/,/g, '،');
            },
            week: {
                // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 1st is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        function plural$6(word, num) {
            var forms = word.split('_');
            return num % 10 === 1 && num % 100 !== 11
                ? forms[0]
                : num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20)
                ? forms[1]
                : forms[2];
        }
        function relativeTimeWithPlural$4(number, withoutSuffix, key) {
            var format = {
                ss: withoutSuffix ? 'секунда_секунди_секунд' : 'секунду_секунди_секунд',
                mm: withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин',
                hh: withoutSuffix ? 'година_години_годин' : 'годину_години_годин',
                dd: 'день_дні_днів',
                MM: 'місяць_місяці_місяців',
                yy: 'рік_роки_років',
            };
            if (key === 'm') {
                return withoutSuffix ? 'хвилина' : 'хвилину';
            } else if (key === 'h') {
                return withoutSuffix ? 'година' : 'годину';
            } else {
                return number + ' ' + plural$6(format[key], +number);
            }
        }
        function weekdaysCaseReplace(m, format) {
            var weekdays = {
                    nominative: 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split(
                        '_'
                    ),
                    accusative: 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split(
                        '_'
                    ),
                    genitive: 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split(
                        '_'
                    ),
                },
                nounCase;
    
            if (m === true) {
                return weekdays['nominative']
                    .slice(1, 7)
                    .concat(weekdays['nominative'].slice(0, 1));
            }
            if (!m) {
                return weekdays['nominative'];
            }
    
            nounCase = /(\[[ВвУу]\]) ?dddd/.test(format)
                ? 'accusative'
                : /\[?(?:минулої|наступної)? ?\] ?dddd/.test(format)
                ? 'genitive'
                : 'nominative';
            return weekdays[nounCase][m.day()];
        }
        function processHoursFunction(str) {
            return function () {
                return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
            };
        }
    
        hooks.defineLocale('uk', {
            months: {
                format: 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split(
                    '_'
                ),
                standalone: 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split(
                    '_'
                ),
            },
            monthsShort: 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split(
                '_'
            ),
            weekdays: weekdaysCaseReplace,
            weekdaysShort: 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
            weekdaysMin: 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD.MM.YYYY',
                LL: 'D MMMM YYYY р.',
                LLL: 'D MMMM YYYY р., HH:mm',
                LLLL: 'dddd, D MMMM YYYY р., HH:mm',
            },
            calendar: {
                sameDay: processHoursFunction('[Сьогодні '),
                nextDay: processHoursFunction('[Завтра '),
                lastDay: processHoursFunction('[Вчора '),
                nextWeek: processHoursFunction('[У] dddd ['),
                lastWeek: function () {
                    switch (this.day()) {
                        case 0:
                        case 3:
                        case 5:
                        case 6:
                            return processHoursFunction('[Минулої] dddd [').call(this);
                        case 1:
                        case 2:
                        case 4:
                            return processHoursFunction('[Минулого] dddd [').call(this);
                    }
                },
                sameElse: 'L',
            },
            relativeTime: {
                future: 'за %s',
                past: '%s тому',
                s: 'декілька секунд',
                ss: relativeTimeWithPlural$4,
                m: relativeTimeWithPlural$4,
                mm: relativeTimeWithPlural$4,
                h: 'годину',
                hh: relativeTimeWithPlural$4,
                d: 'день',
                dd: relativeTimeWithPlural$4,
                M: 'місяць',
                MM: relativeTimeWithPlural$4,
                y: 'рік',
                yy: relativeTimeWithPlural$4,
            },
            // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
            meridiemParse: /ночі|ранку|дня|вечора/,
            isPM: function (input) {
                return /^(дня|вечора)$/.test(input);
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 4) {
                    return 'ночі';
                } else if (hour < 12) {
                    return 'ранку';
                } else if (hour < 17) {
                    return 'дня';
                } else {
                    return 'вечора';
                }
            },
            dayOfMonthOrdinalParse: /\d{1,2}-(й|го)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'M':
                    case 'd':
                    case 'DDD':
                    case 'w':
                    case 'W':
                        return number + '-й';
                    case 'D':
                        return number + '-го';
                    default:
                        return number;
                }
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        var months$b = [
                'جنوری',
                'فروری',
                'مارچ',
                'اپریل',
                'مئی',
                'جون',
                'جولائی',
                'اگست',
                'ستمبر',
                'اکتوبر',
                'نومبر',
                'دسمبر',
            ],
            days$2 = ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'ہفتہ'];
    
        hooks.defineLocale('ur', {
            months: months$b,
            monthsShort: months$b,
            weekdays: days$2,
            weekdaysShort: days$2,
            weekdaysMin: days$2,
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd، D MMMM YYYY HH:mm',
            },
            meridiemParse: /صبح|شام/,
            isPM: function (input) {
                return 'شام' === input;
            },
            meridiem: function (hour, minute, isLower) {
                if (hour < 12) {
                    return 'صبح';
                }
                return 'شام';
            },
            calendar: {
                sameDay: '[آج بوقت] LT',
                nextDay: '[کل بوقت] LT',
                nextWeek: 'dddd [بوقت] LT',
                lastDay: '[گذشتہ روز بوقت] LT',
                lastWeek: '[گذشتہ] dddd [بوقت] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s بعد',
                past: '%s قبل',
                s: 'چند سیکنڈ',
                ss: '%d سیکنڈ',
                m: 'ایک منٹ',
                mm: '%d منٹ',
                h: 'ایک گھنٹہ',
                hh: '%d گھنٹے',
                d: 'ایک دن',
                dd: '%d دن',
                M: 'ایک ماہ',
                MM: '%d ماہ',
                y: 'ایک سال',
                yy: '%d سال',
            },
            preparse: function (string) {
                return string.replace(/،/g, ',');
            },
            postformat: function (string) {
                return string.replace(/,/g, '،');
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('uz-latn', {
            months: 'Yanvar_Fevral_Mart_Aprel_May_Iyun_Iyul_Avgust_Sentabr_Oktabr_Noyabr_Dekabr'.split(
                '_'
            ),
            monthsShort: 'Yan_Fev_Mar_Apr_May_Iyun_Iyul_Avg_Sen_Okt_Noy_Dek'.split('_'),
            weekdays: 'Yakshanba_Dushanba_Seshanba_Chorshanba_Payshanba_Juma_Shanba'.split(
                '_'
            ),
            weekdaysShort: 'Yak_Dush_Sesh_Chor_Pay_Jum_Shan'.split('_'),
            weekdaysMin: 'Ya_Du_Se_Cho_Pa_Ju_Sha'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'D MMMM YYYY, dddd HH:mm',
            },
            calendar: {
                sameDay: '[Bugun soat] LT [da]',
                nextDay: '[Ertaga] LT [da]',
                nextWeek: 'dddd [kuni soat] LT [da]',
                lastDay: '[Kecha soat] LT [da]',
                lastWeek: "[O'tgan] dddd [kuni soat] LT [da]",
                sameElse: 'L',
            },
            relativeTime: {
                future: 'Yaqin %s ichida',
                past: 'Bir necha %s oldin',
                s: 'soniya',
                ss: '%d soniya',
                m: 'bir daqiqa',
                mm: '%d daqiqa',
                h: 'bir soat',
                hh: '%d soat',
                d: 'bir kun',
                dd: '%d kun',
                M: 'bir oy',
                MM: '%d oy',
                y: 'bir yil',
                yy: '%d yil',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 7th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('uz', {
            months: 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split(
                '_'
            ),
            monthsShort: 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'),
            weekdays: 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'),
            weekdaysShort: 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'),
            weekdaysMin: 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'D MMMM YYYY, dddd HH:mm',
            },
            calendar: {
                sameDay: '[Бугун соат] LT [да]',
                nextDay: '[Эртага] LT [да]',
                nextWeek: 'dddd [куни соат] LT [да]',
                lastDay: '[Кеча соат] LT [да]',
                lastWeek: '[Утган] dddd [куни соат] LT [да]',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'Якин %s ичида',
                past: 'Бир неча %s олдин',
                s: 'фурсат',
                ss: '%d фурсат',
                m: 'бир дакика',
                mm: '%d дакика',
                h: 'бир соат',
                hh: '%d соат',
                d: 'бир кун',
                dd: '%d кун',
                M: 'бир ой',
                MM: '%d ой',
                y: 'бир йил',
                yy: '%d йил',
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 7, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('vi', {
            months: 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split(
                '_'
            ),
            monthsShort: 'Thg 01_Thg 02_Thg 03_Thg 04_Thg 05_Thg 06_Thg 07_Thg 08_Thg 09_Thg 10_Thg 11_Thg 12'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split(
                '_'
            ),
            weekdaysShort: 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
            weekdaysMin: 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
            weekdaysParseExact: true,
            meridiemParse: /sa|ch/i,
            isPM: function (input) {
                return /^ch$/i.test(input);
            },
            meridiem: function (hours, minutes, isLower) {
                if (hours < 12) {
                    return isLower ? 'sa' : 'SA';
                } else {
                    return isLower ? 'ch' : 'CH';
                }
            },
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM [năm] YYYY',
                LLL: 'D MMMM [năm] YYYY HH:mm',
                LLLL: 'dddd, D MMMM [năm] YYYY HH:mm',
                l: 'DD/M/YYYY',
                ll: 'D MMM YYYY',
                lll: 'D MMM YYYY HH:mm',
                llll: 'ddd, D MMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[Hôm nay lúc] LT',
                nextDay: '[Ngày mai lúc] LT',
                nextWeek: 'dddd [tuần tới lúc] LT',
                lastDay: '[Hôm qua lúc] LT',
                lastWeek: 'dddd [tuần trước lúc] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: '%s tới',
                past: '%s trước',
                s: 'vài giây',
                ss: '%d giây',
                m: 'một phút',
                mm: '%d phút',
                h: 'một giờ',
                hh: '%d giờ',
                d: 'một ngày',
                dd: '%d ngày',
                w: 'một tuần',
                ww: '%d tuần',
                M: 'một tháng',
                MM: '%d tháng',
                y: 'một năm',
                yy: '%d năm',
            },
            dayOfMonthOrdinalParse: /\d{1,2}/,
            ordinal: function (number) {
                return number;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('x-pseudo', {
            months: 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split(
                '_'
            ),
            monthsShort: 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split(
                '_'
            ),
            monthsParseExact: true,
            weekdays: 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split(
                '_'
            ),
            weekdaysShort: 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'),
            weekdaysMin: 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'),
            weekdaysParseExact: true,
            longDateFormat: {
                LT: 'HH:mm',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY HH:mm',
                LLLL: 'dddd, D MMMM YYYY HH:mm',
            },
            calendar: {
                sameDay: '[T~ódá~ý át] LT',
                nextDay: '[T~ómó~rró~w át] LT',
                nextWeek: 'dddd [át] LT',
                lastDay: '[Ý~ést~érdá~ý át] LT',
                lastWeek: '[L~ást] dddd [át] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'í~ñ %s',
                past: '%s á~gó',
                s: 'á ~féw ~sécó~ñds',
                ss: '%d s~écóñ~ds',
                m: 'á ~míñ~úté',
                mm: '%d m~íñú~tés',
                h: 'á~ñ hó~úr',
                hh: '%d h~óúrs',
                d: 'á ~dáý',
                dd: '%d d~áýs',
                M: 'á ~móñ~th',
                MM: '%d m~óñt~hs',
                y: 'á ~ýéár',
                yy: '%d ý~éárs',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
            ordinal: function (number) {
                var b = number % 10,
                    output =
                        ~~((number % 100) / 10) === 1
                            ? 'th'
                            : b === 1
                            ? 'st'
                            : b === 2
                            ? 'nd'
                            : b === 3
                            ? 'rd'
                            : 'th';
                return number + output;
            },
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('yo', {
            months: 'Sẹ́rẹ́_Èrèlè_Ẹrẹ̀nà_Ìgbé_Èbibi_Òkùdu_Agẹmo_Ògún_Owewe_Ọ̀wàrà_Bélú_Ọ̀pẹ̀̀'.split(
                '_'
            ),
            monthsShort: 'Sẹ́r_Èrl_Ẹrn_Ìgb_Èbi_Òkù_Agẹ_Ògú_Owe_Ọ̀wà_Bél_Ọ̀pẹ̀̀'.split('_'),
            weekdays: 'Àìkú_Ajé_Ìsẹ́gun_Ọjọ́rú_Ọjọ́bọ_Ẹtì_Àbámẹ́ta'.split('_'),
            weekdaysShort: 'Àìk_Ajé_Ìsẹ́_Ọjr_Ọjb_Ẹtì_Àbá'.split('_'),
            weekdaysMin: 'Àì_Aj_Ìs_Ọr_Ọb_Ẹt_Àb'.split('_'),
            longDateFormat: {
                LT: 'h:mm A',
                LTS: 'h:mm:ss A',
                L: 'DD/MM/YYYY',
                LL: 'D MMMM YYYY',
                LLL: 'D MMMM YYYY h:mm A',
                LLLL: 'dddd, D MMMM YYYY h:mm A',
            },
            calendar: {
                sameDay: '[Ònì ni] LT',
                nextDay: '[Ọ̀la ni] LT',
                nextWeek: "dddd [Ọsẹ̀ tón'bọ] [ni] LT",
                lastDay: '[Àna ni] LT',
                lastWeek: 'dddd [Ọsẹ̀ tólọ́] [ni] LT',
                sameElse: 'L',
            },
            relativeTime: {
                future: 'ní %s',
                past: '%s kọjá',
                s: 'ìsẹjú aayá die',
                ss: 'aayá %d',
                m: 'ìsẹjú kan',
                mm: 'ìsẹjú %d',
                h: 'wákati kan',
                hh: 'wákati %d',
                d: 'ọjọ́ kan',
                dd: 'ọjọ́ %d',
                M: 'osù kan',
                MM: 'osù %d',
                y: 'ọdún kan',
                yy: 'ọdún %d',
            },
            dayOfMonthOrdinalParse: /ọjọ́\s\d{1,2}/,
            ordinal: 'ọjọ́ %d',
            week: {
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('zh-cn', {
            months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split(
                '_'
            ),
            monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split(
                '_'
            ),
            weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
            weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'),
            weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY/MM/DD',
                LL: 'YYYY年M月D日',
                LLL: 'YYYY年M月D日Ah点mm分',
                LLLL: 'YYYY年M月D日ddddAh点mm分',
                l: 'YYYY/M/D',
                ll: 'YYYY年M月D日',
                lll: 'YYYY年M月D日 HH:mm',
                llll: 'YYYY年M月D日dddd HH:mm',
            },
            meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
                    return hour;
                } else if (meridiem === '下午' || meridiem === '晚上') {
                    return hour + 12;
                } else {
                    // '中午'
                    return hour >= 11 ? hour : hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                var hm = hour * 100 + minute;
                if (hm < 600) {
                    return '凌晨';
                } else if (hm < 900) {
                    return '早上';
                } else if (hm < 1130) {
                    return '上午';
                } else if (hm < 1230) {
                    return '中午';
                } else if (hm < 1800) {
                    return '下午';
                } else {
                    return '晚上';
                }
            },
            calendar: {
                sameDay: '[今天]LT',
                nextDay: '[明天]LT',
                nextWeek: function (now) {
                    if (now.week() !== this.week()) {
                        return '[下]dddLT';
                    } else {
                        return '[本]dddLT';
                    }
                },
                lastDay: '[昨天]LT',
                lastWeek: function (now) {
                    if (this.week() !== now.week()) {
                        return '[上]dddLT';
                    } else {
                        return '[本]dddLT';
                    }
                },
                sameElse: 'L',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(日|月|周)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'DDD':
                        return number + '日';
                    case 'M':
                        return number + '月';
                    case 'w':
                    case 'W':
                        return number + '周';
                    default:
                        return number;
                }
            },
            relativeTime: {
                future: '%s后',
                past: '%s前',
                s: '几秒',
                ss: '%d 秒',
                m: '1 分钟',
                mm: '%d 分钟',
                h: '1 小时',
                hh: '%d 小时',
                d: '1 天',
                dd: '%d 天',
                w: '1 周',
                ww: '%d 周',
                M: '1 个月',
                MM: '%d 个月',
                y: '1 年',
                yy: '%d 年',
            },
            week: {
                // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
                dow: 1, // Monday is the first day of the week.
                doy: 4, // The week that contains Jan 4th is the first week of the year.
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('zh-hk', {
            months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split(
                '_'
            ),
            monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split(
                '_'
            ),
            weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
            weekdaysShort: '週日_週一_週二_週三_週四_週五_週六'.split('_'),
            weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY/MM/DD',
                LL: 'YYYY年M月D日',
                LLL: 'YYYY年M月D日 HH:mm',
                LLLL: 'YYYY年M月D日dddd HH:mm',
                l: 'YYYY/M/D',
                ll: 'YYYY年M月D日',
                lll: 'YYYY年M月D日 HH:mm',
                llll: 'YYYY年M月D日dddd HH:mm',
            },
            meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
                    return hour;
                } else if (meridiem === '中午') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === '下午' || meridiem === '晚上') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                var hm = hour * 100 + minute;
                if (hm < 600) {
                    return '凌晨';
                } else if (hm < 900) {
                    return '早上';
                } else if (hm < 1200) {
                    return '上午';
                } else if (hm === 1200) {
                    return '中午';
                } else if (hm < 1800) {
                    return '下午';
                } else {
                    return '晚上';
                }
            },
            calendar: {
                sameDay: '[今天]LT',
                nextDay: '[明天]LT',
                nextWeek: '[下]ddddLT',
                lastDay: '[昨天]LT',
                lastWeek: '[上]ddddLT',
                sameElse: 'L',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(日|月|週)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'DDD':
                        return number + '日';
                    case 'M':
                        return number + '月';
                    case 'w':
                    case 'W':
                        return number + '週';
                    default:
                        return number;
                }
            },
            relativeTime: {
                future: '%s後',
                past: '%s前',
                s: '幾秒',
                ss: '%d 秒',
                m: '1 分鐘',
                mm: '%d 分鐘',
                h: '1 小時',
                hh: '%d 小時',
                d: '1 天',
                dd: '%d 天',
                M: '1 個月',
                MM: '%d 個月',
                y: '1 年',
                yy: '%d 年',
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('zh-mo', {
            months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split(
                '_'
            ),
            monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split(
                '_'
            ),
            weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
            weekdaysShort: '週日_週一_週二_週三_週四_週五_週六'.split('_'),
            weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'DD/MM/YYYY',
                LL: 'YYYY年M月D日',
                LLL: 'YYYY年M月D日 HH:mm',
                LLLL: 'YYYY年M月D日dddd HH:mm',
                l: 'D/M/YYYY',
                ll: 'YYYY年M月D日',
                lll: 'YYYY年M月D日 HH:mm',
                llll: 'YYYY年M月D日dddd HH:mm',
            },
            meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
                    return hour;
                } else if (meridiem === '中午') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === '下午' || meridiem === '晚上') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                var hm = hour * 100 + minute;
                if (hm < 600) {
                    return '凌晨';
                } else if (hm < 900) {
                    return '早上';
                } else if (hm < 1130) {
                    return '上午';
                } else if (hm < 1230) {
                    return '中午';
                } else if (hm < 1800) {
                    return '下午';
                } else {
                    return '晚上';
                }
            },
            calendar: {
                sameDay: '[今天] LT',
                nextDay: '[明天] LT',
                nextWeek: '[下]dddd LT',
                lastDay: '[昨天] LT',
                lastWeek: '[上]dddd LT',
                sameElse: 'L',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(日|月|週)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'DDD':
                        return number + '日';
                    case 'M':
                        return number + '月';
                    case 'w':
                    case 'W':
                        return number + '週';
                    default:
                        return number;
                }
            },
            relativeTime: {
                future: '%s內',
                past: '%s前',
                s: '幾秒',
                ss: '%d 秒',
                m: '1 分鐘',
                mm: '%d 分鐘',
                h: '1 小時',
                hh: '%d 小時',
                d: '1 天',
                dd: '%d 天',
                M: '1 個月',
                MM: '%d 個月',
                y: '1 年',
                yy: '%d 年',
            },
        });
    
        //! moment.js locale configuration
    
        hooks.defineLocale('zh-tw', {
            months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split(
                '_'
            ),
            monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split(
                '_'
            ),
            weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
            weekdaysShort: '週日_週一_週二_週三_週四_週五_週六'.split('_'),
            weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
            longDateFormat: {
                LT: 'HH:mm',
                LTS: 'HH:mm:ss',
                L: 'YYYY/MM/DD',
                LL: 'YYYY年M月D日',
                LLL: 'YYYY年M月D日 HH:mm',
                LLLL: 'YYYY年M月D日dddd HH:mm',
                l: 'YYYY/M/D',
                ll: 'YYYY年M月D日',
                lll: 'YYYY年M月D日 HH:mm',
                llll: 'YYYY年M月D日dddd HH:mm',
            },
            meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
            meridiemHour: function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
                    return hour;
                } else if (meridiem === '中午') {
                    return hour >= 11 ? hour : hour + 12;
                } else if (meridiem === '下午' || meridiem === '晚上') {
                    return hour + 12;
                }
            },
            meridiem: function (hour, minute, isLower) {
                var hm = hour * 100 + minute;
                if (hm < 600) {
                    return '凌晨';
                } else if (hm < 900) {
                    return '早上';
                } else if (hm < 1130) {
                    return '上午';
                } else if (hm < 1230) {
                    return '中午';
                } else if (hm < 1800) {
                    return '下午';
                } else {
                    return '晚上';
                }
            },
            calendar: {
                sameDay: '[今天] LT',
                nextDay: '[明天] LT',
                nextWeek: '[下]dddd LT',
                lastDay: '[昨天] LT',
                lastWeek: '[上]dddd LT',
                sameElse: 'L',
            },
            dayOfMonthOrdinalParse: /\d{1,2}(日|月|週)/,
            ordinal: function (number, period) {
                switch (period) {
                    case 'd':
                    case 'D':
                    case 'DDD':
                        return number + '日';
                    case 'M':
                        return number + '月';
                    case 'w':
                    case 'W':
                        return number + '週';
                    default:
                        return number;
                }
            },
            relativeTime: {
                future: '%s後',
                past: '%s前',
                s: '幾秒',
                ss: '%d 秒',
                m: '1 分鐘',
                mm: '%d 分鐘',
                h: '1 小時',
                hh: '%d 小時',
                d: '1 天',
                dd: '%d 天',
                M: '1 個月',
                MM: '%d 個月',
                y: '1 年',
                yy: '%d 年',
            },
        });
    
        hooks.locale('en');
    
        return hooks;
    
    })));
    
    !function(t,e){"use strict";"object"==typeof module&&module.exports?module.exports=e(require("moment")):"function"==typeof define&&define.amd?define(["moment"],e):e(t.moment)}(this,function(s){"use strict";void 0===s.version&&s.default&&(s=s.default);var e,i={},f={},u={},a={},c={};s&&"string"==typeof s.version||D("Moment Timezone requires Moment.js. See https://momentjs.com/timezone/docs/#/use-it/browser/");var t=s.version.split("."),n=+t[0],o=+t[1];function l(t){return 96<t?t-87:64<t?t-29:t-48}function r(t){var e=0,n=t.split("."),o=n[0],r=n[1]||"",s=1,i=0,f=1;for(45===t.charCodeAt(0)&&(f=-(e=1));e<o.length;e++)i=60*i+l(o.charCodeAt(e));for(e=0;e<r.length;e++)s/=60,i+=l(r.charCodeAt(e))*s;return i*f}function h(t){for(var e=0;e<t.length;e++)t[e]=r(t[e])}function p(t,e){for(var n=[],o=0;o<e.length;o++)n[o]=t[e[o]];return n}function m(t){var e=t.split("|"),n=e[2].split(" "),o=e[3].split(""),r=e[4].split(" ");return h(n),h(o),h(r),function(t,e){for(var n=0;n<e;n++)t[n]=Math.round((t[n-1]||0)+6e4*t[n]);t[e-1]=1/0}(r,o.length),{name:e[0],abbrs:p(e[1].split(" "),o),offsets:p(n,o),untils:r,population:0|e[5]}}function d(t){t&&this._set(m(t))}function z(t,e){this.name=t,this.zones=e}function v(t){var e=t.toTimeString(),n=e.match(/\([a-z ]+\)/i);"GMT"===(n=n&&n[0]?(n=n[0].match(/[A-Z]/g))?n.join(""):void 0:(n=e.match(/[A-Z]{3,5}/g))?n[0]:void 0)&&(n=void 0),this.at=+t,this.abbr=n,this.offset=t.getTimezoneOffset()}function b(t){this.zone=t,this.offsetScore=0,this.abbrScore=0}function g(){for(var t,e,n=(new Date).getFullYear()-2,o=new v(new Date(n,0,1)),r=[o],s=1;s<48;s++)(e=new v(new Date(n,s,1))).offset!==o.offset&&(t=function(t,e){for(var n,o;o=6e4*((e.at-t.at)/12e4|0);)(n=new v(new Date(t.at+o))).offset===t.offset?t=n:e=n;return t}(o,e),r.push(t),r.push(new v(new Date(t.at+6e4)))),o=e;for(s=0;s<4;s++)r.push(new v(new Date(n+s,0,1))),r.push(new v(new Date(n+s,6,1)));return r}function _(t,e){return t.offsetScore!==e.offsetScore?t.offsetScore-e.offsetScore:t.abbrScore!==e.abbrScore?t.abbrScore-e.abbrScore:t.zone.population!==e.zone.population?e.zone.population-t.zone.population:e.zone.name.localeCompare(t.zone.name)}function w(){try{var t=Intl.DateTimeFormat().resolvedOptions().timeZone;if(t&&3<t.length){var e=a[y(t)];if(e)return e;D("Moment Timezone found "+t+" from the Intl api, but did not have that data loaded.")}}catch(t){}for(var n,o,r=g(),s=r.length,i=function(t){for(var e,n,o=t.length,r={},s=[],i=0;i<o;i++)for(e in n=c[t[i].offset]||{})n.hasOwnProperty(e)&&(r[e]=!0);for(i in r)r.hasOwnProperty(i)&&s.push(a[i]);return s}(r),f=[],u=0;u<i.length;u++){for(n=new b(S(i[u])),o=0;o<s;o++)n.scoreOffsetAt(r[o]);f.push(n)}return f.sort(_),0<f.length?f[0].zone.name:void 0}function y(t){return(t||"").toLowerCase().replace(/\//g,"_")}function O(t){var e,n,o,r;for("string"==typeof t&&(t=[t]),e=0;e<t.length;e++)r=y(n=(o=t[e].split("|"))[0]),i[r]=t[e],a[r]=n,function(t,e){var n,o;for(h(e),n=0;n<e.length;n++)o=e[n],c[o]=c[o]||{},c[o][t]=!0}(r,o[2].split(" "))}function S(t,e){t=y(t);var n,o=i[t];return o instanceof d?o:"string"==typeof o?(o=new d(o),i[t]=o):f[t]&&e!==S&&(n=S(f[t],S))?((o=i[t]=new d)._set(n),o.name=a[t],o):null}function M(t){var e,n,o,r;for("string"==typeof t&&(t=[t]),e=0;e<t.length;e++)o=y((n=t[e].split("|"))[0]),r=y(n[1]),f[o]=r,a[o]=n[0],f[r]=o,a[r]=n[1]}function j(t){return j.didShowError||(j.didShowError=!0,D("moment.tz.zoneExists('"+t+"') has been deprecated in favor of !moment.tz.zone('"+t+"')")),!!S(t)}function A(t){var e="X"===t._f||"x"===t._f;return!(!t._a||void 0!==t._tzm||e)}function D(t){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(t)}function T(t){var e=Array.prototype.slice.call(arguments,0,-1),n=arguments[arguments.length-1],o=S(n),r=s.utc.apply(null,e);return o&&!s.isMoment(t)&&A(r)&&r.add(o.parse(r),"minutes"),r.tz(n),r}(n<2||2==n&&o<6)&&D("Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js "+s.version+". See momentjs.com"),d.prototype={_set:function(t){this.name=t.name,this.abbrs=t.abbrs,this.untils=t.untils,this.offsets=t.offsets,this.population=t.population},_index:function(t){for(var e=+t,n=this.untils,o=0;o<n.length;o++)if(e<n[o])return o},countries:function(){var e=this.name;return Object.keys(u).filter(function(t){return-1!==u[t].zones.indexOf(e)})},parse:function(t){for(var e,n,o,r=+t,s=this.offsets,i=this.untils,f=i.length-1,u=0;u<f;u++)if(e=s[u],n=s[u+1],o=s[u?u-1:u],e<n&&T.moveAmbiguousForward?e=n:o<e&&T.moveInvalidForward&&(e=o),r<i[u]-6e4*e)return s[u];return s[f]},abbr:function(t){return this.abbrs[this._index(t)]},offset:function(t){return D("zone.offset has been deprecated in favor of zone.utcOffset"),this.offsets[this._index(t)]},utcOffset:function(t){return this.offsets[this._index(t)]}},b.prototype.scoreOffsetAt=function(t){this.offsetScore+=Math.abs(this.zone.utcOffset(t.at)-t.offset),this.zone.abbr(t.at).replace(/[^A-Z]/g,"")!==t.abbr&&this.abbrScore++},T.version="0.5.32",T.dataVersion="",T._zones=i,T._links=f,T._names=a,T._countries=u,T.add=O,T.link=M,T.load=function(t){O(t.zones),M(t.links),function(t){var e,n,o,r;if(t&&t.length)for(e=0;e<t.length;e++)n=(r=t[e].split("|"))[0].toUpperCase(),o=r[1].split(" "),u[n]=new z(n,o)}(t.countries),T.dataVersion=t.version},T.zone=S,T.zoneExists=j,T.guess=function(t){return e&&!t||(e=w()),e},T.names=function(){var t,e=[];for(t in a)a.hasOwnProperty(t)&&(i[t]||i[f[t]])&&a[t]&&e.push(a[t]);return e.sort()},T.Zone=d,T.unpack=m,T.unpackBase60=r,T.needsOffset=A,T.moveInvalidForward=!0,T.moveAmbiguousForward=!1,T.countries=function(){return Object.keys(u)},T.zonesForCountry=function(t,e){var n;if(n=(n=t).toUpperCase(),!(t=u[n]||null))return null;var o=t.zones.sort();return e?o.map(function(t){return{name:t,offset:S(t).utcOffset(new Date)}}):o};var x,C=s.fn;function Z(t){return function(){return this._z?this._z.abbr(this):t.call(this)}}function k(t){return function(){return this._z=null,t.apply(this,arguments)}}s.tz=T,s.defaultZone=null,s.updateOffset=function(t,e){var n,o,r=s.defaultZone;void 0===t._z&&(r&&A(t)&&!t._isUTC&&(t._d=s.utc(t._a)._d,t.utc().add(r.parse(t),"minutes")),t._z=r),t._z&&(o=t._z.utcOffset(t),Math.abs(o)<16&&(o/=60),void 0!==t.utcOffset?(n=t._z,t.utcOffset(-o,e),t._z=n):t.zone(o,e))},C.tz=function(t,e){if(t){if("string"!=typeof t)throw new Error("Time zone name must be a string, got "+t+" ["+typeof t+"]");return this._z=S(t),this._z?s.updateOffset(this,e):D("Moment Timezone has no data for "+t+". See http://momentjs.com/timezone/docs/#/data-loading/."),this}if(this._z)return this._z.name},C.zoneName=Z(C.zoneName),C.zoneAbbr=Z(C.zoneAbbr),C.utc=k(C.utc),C.local=k(C.local),C.utcOffset=(x=C.utcOffset,function(){return 0<arguments.length&&(this._z=null),x.apply(this,arguments)}),s.tz.setDefault=function(t){return(n<2||2==n&&o<9)&&D("Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js "+s.version+"."),s.defaultZone=t?S(t):null,s};var F=s.momentProperties;return"[object Array]"===Object.prototype.toString.call(F)?(F.push("_z"),F.push("_a")):F&&(F._z=null),s});
    var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
    
    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
    
    // ReSharper disable once InconsistentNaming
    var DateTimePicker = function ($, moment) {
        function escapeRegExp(text) {
            return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
        }
    
        function isValidDate(date) {
            return Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime());
        }
    
        function isValidDateTimeStr(str) {
            return isValidDate(new Date(str));
        }
    
        // ReSharper disable InconsistentNaming
        var trim = function trim(str) {
            return str.replace(/(^\s+)|(\s+$)/g, '');
        },
            NAME = 'datetimepicker',
            DATA_KEY = '' + NAME,
            EVENT_KEY = '.' + DATA_KEY,
            DATA_API_KEY = '.data-api',
            Selector = {
            DATA_TOGGLE: '[data-toggle="' + DATA_KEY + '"]'
        },
            ClassName = {
            INPUT: NAME + '-input'
        },
            Event = {
            CHANGE: 'change' + EVENT_KEY,
            BLUR: 'blur' + EVENT_KEY,
            KEYUP: 'keyup' + EVENT_KEY,
            KEYDOWN: 'keydown' + EVENT_KEY,
            FOCUS: 'focus' + EVENT_KEY,
            CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
            //emitted
            UPDATE: 'update' + EVENT_KEY,
            ERROR: 'error' + EVENT_KEY,
            HIDE: 'hide' + EVENT_KEY,
            SHOW: 'show' + EVENT_KEY
        },
            DatePickerModes = [{
            CLASS_NAME: 'days',
            NAV_FUNCTION: 'M',
            NAV_STEP: 1
        }, {
            CLASS_NAME: 'months',
            NAV_FUNCTION: 'y',
            NAV_STEP: 1
        }, {
            CLASS_NAME: 'years',
            NAV_FUNCTION: 'y',
            NAV_STEP: 10
        }, {
            CLASS_NAME: 'decades',
            NAV_FUNCTION: 'y',
            NAV_STEP: 100
        }],
            KeyMap = {
            'up': 38,
            38: 'up',
            'down': 40,
            40: 'down',
            'left': 37,
            37: 'left',
            'right': 39,
            39: 'right',
            'tab': 9,
            9: 'tab',
            'escape': 27,
            27: 'escape',
            'enter': 13,
            13: 'enter',
            'pageUp': 33,
            33: 'pageUp',
            'pageDown': 34,
            34: 'pageDown',
            'shift': 16,
            16: 'shift',
            'control': 17,
            17: 'control',
            'space': 32,
            32: 'space',
            't': 84,
            84: 't',
            'delete': 46,
            46: 'delete'
        },
            ViewModes = ['times', 'days', 'months', 'years', 'decades'],
            keyState = {},
            keyPressHandled = {},
            optionsSortMap = {
            timeZone: -39,
            format: -38,
            dayViewHeaderFormat: -37,
            extraFormats: -36,
            stepping: -35,
            minDate: -34,
            maxDate: -33,
            useCurrent: -32,
            collapse: -31,
            locale: -30,
            defaultDate: -29,
            disabledDates: -28,
            enabledDates: -27,
            icons: -26,
            tooltips: -25,
            useStrict: -24,
            sideBySide: -23,
            daysOfWeekDisabled: -22,
            calendarWeeks: -21,
            viewMode: -20,
            toolbarPlacement: -19,
            buttons: -18,
            widgetPositioning: -17,
            widgetParent: -16,
            ignoreReadonly: -15,
            keepOpen: -14,
            focusOnShow: -13,
            inline: -12,
            keepInvalid: -11,
            keyBinds: -10,
            debug: -9,
            allowInputToggle: -8,
            disabledTimeIntervals: -7,
            disabledHours: -6,
            enabledHours: -5,
            viewDate: -4,
            allowMultidate: -3,
            multidateSeparator: -2,
            updateOnlyThroughDateOption: -1,
            date: 1
        },
            defaultFeatherIcons = {
            time: 'clock',
            date: 'calendar',
            up: 'arrow-up',
            down: 'arrow-down',
            previous: 'arrow-left',
            next: 'arrow-right',
            today: 'arrow-down-circle',
            clear: 'trash-2',
            close: 'x'
        };
    
        function optionsSortFn(optionKeyA, optionKeyB) {
            if (optionsSortMap[optionKeyA] && optionsSortMap[optionKeyB]) {
                if (optionsSortMap[optionKeyA] < 0 && optionsSortMap[optionKeyB] < 0) {
                    return Math.abs(optionsSortMap[optionKeyB]) - Math.abs(optionsSortMap[optionKeyA]);
                } else if (optionsSortMap[optionKeyA] < 0) {
                    return -1;
                } else if (optionsSortMap[optionKeyB] < 0) {
                    return 1;
                }
                return optionsSortMap[optionKeyA] - optionsSortMap[optionKeyB];
            } else if (optionsSortMap[optionKeyA]) {
                return optionsSortMap[optionKeyA];
            } else if (optionsSortMap[optionKeyB]) {
                return optionsSortMap[optionKeyB];
            }
            return 0;
        }
    
        var Default = {
            timeZone: '',
            format: false,
            dayViewHeaderFormat: 'MMMM YYYY',
            extraFormats: false,
            stepping: 1,
            minDate: false,
            maxDate: false,
            useCurrent: true,
            collapse: true,
            locale: moment.locale(),
            defaultDate: false,
            disabledDates: false,
            enabledDates: false,
            icons: {
                type: 'class',
                time: 'fa fa-clock-o',
                date: 'fa fa-calendar',
                up: 'fa fa-arrow-up',
                down: 'fa fa-arrow-down',
                previous: 'fa fa-chevron-left',
                next: 'fa fa-chevron-right',
                today: 'fa fa-calendar-check-o',
                clear: 'fa fa-trash',
                close: 'fa fa-times'
            },
            tooltips: {
                today: 'Go to today',
                clear: 'Clear selection',
                close: 'Close the picker',
                selectMonth: 'Select Month',
                prevMonth: 'Previous Month',
                nextMonth: 'Next Month',
                selectYear: 'Select Year',
                prevYear: 'Previous Year',
                nextYear: 'Next Year',
                selectDecade: 'Select Decade',
                prevDecade: 'Previous Decade',
                nextDecade: 'Next Decade',
                prevCentury: 'Previous Century',
                nextCentury: 'Next Century',
                pickHour: 'Pick Hour',
                incrementHour: 'Increment Hour',
                decrementHour: 'Decrement Hour',
                pickMinute: 'Pick Minute',
                incrementMinute: 'Increment Minute',
                decrementMinute: 'Decrement Minute',
                pickSecond: 'Pick Second',
                incrementSecond: 'Increment Second',
                decrementSecond: 'Decrement Second',
                togglePeriod: 'Toggle Period',
                selectTime: 'Select Time',
                selectDate: 'Select Date'
            },
            useStrict: false,
            sideBySide: false,
            daysOfWeekDisabled: false,
            calendarWeeks: false,
            viewMode: 'days',
            toolbarPlacement: 'default',
            buttons: {
                showToday: false,
                showClear: false,
                showClose: false
            },
            widgetPositioning: {
                horizontal: 'auto',
                vertical: 'auto'
            },
            widgetParent: null,
            readonly: false,
            ignoreReadonly: false,
            keepOpen: false,
            focusOnShow: true,
            inline: false,
            keepInvalid: false,
            keyBinds: {
                up: function up() {
                    if (!this.widget) {
                        return false;
                    }
                    var d = this._dates[0] || this.getMoment();
                    if (this.widget.find('.datepicker').is(':visible')) {
                        this.date(d.clone().subtract(7, 'd'));
                    } else {
                        this.date(d.clone().add(this.stepping(), 'm'));
                    }
                    return true;
                },
                down: function down() {
                    if (!this.widget) {
                        this.show();
                        return false;
                    }
                    var d = this._dates[0] || this.getMoment();
                    if (this.widget.find('.datepicker').is(':visible')) {
                        this.date(d.clone().add(7, 'd'));
                    } else {
                        this.date(d.clone().subtract(this.stepping(), 'm'));
                    }
                    return true;
                },
                'control up': function controlUp() {
                    if (!this.widget) {
                        return false;
                    }
                    var d = this._dates[0] || this.getMoment();
                    if (this.widget.find('.datepicker').is(':visible')) {
                        this.date(d.clone().subtract(1, 'y'));
                    } else {
                        this.date(d.clone().add(1, 'h'));
                    }
                    return true;
                },
                'control down': function controlDown() {
                    if (!this.widget) {
                        return false;
                    }
                    var d = this._dates[0] || this.getMoment();
                    if (this.widget.find('.datepicker').is(':visible')) {
                        this.date(d.clone().add(1, 'y'));
                    } else {
                        this.date(d.clone().subtract(1, 'h'));
                    }
                    return true;
                },
                left: function left() {
                    if (!this.widget) {
                        return false;
                    }
                    var d = this._dates[0] || this.getMoment();
                    if (this.widget.find('.datepicker').is(':visible')) {
                        this.date(d.clone().subtract(1, 'd'));
                    }
                    return true;
                },
                right: function right() {
                    if (!this.widget) {
                        return false;
                    }
                    var d = this._dates[0] || this.getMoment();
                    if (this.widget.find('.datepicker').is(':visible')) {
                        this.date(d.clone().add(1, 'd'));
                    }
                    return true;
                },
                pageUp: function pageUp() {
                    if (!this.widget) {
                        return false;
                    }
                    var d = this._dates[0] || this.getMoment();
                    if (this.widget.find('.datepicker').is(':visible')) {
                        this.date(d.clone().subtract(1, 'M'));
                    }
                    return true;
                },
                pageDown: function pageDown() {
                    if (!this.widget) {
                        return false;
                    }
                    var d = this._dates[0] || this.getMoment();
                    if (this.widget.find('.datepicker').is(':visible')) {
                        this.date(d.clone().add(1, 'M'));
                    }
                    return true;
                },
                enter: function enter() {
                    if (!this.widget) {
                        return false;
                    }
                    this.hide();
                    return true;
                },
                escape: function escape() {
                    if (!this.widget) {
                        return false;
                    }
                    this.hide();
                    return true;
                },
                'control space': function controlSpace() {
                    if (!this.widget) {
                        return false;
                    }
                    if (this.widget.find('.timepicker').is(':visible')) {
                        this.widget.find('.btn[data-action="togglePeriod"]').click();
                    }
                    return true;
                },
                t: function t() {
                    if (!this.widget) {
                        return false;
                    }
                    this.date(this.getMoment());
                    return true;
                },
                'delete': function _delete() {
                    if (!this.widget) {
                        return false;
                    }
                    this.clear();
                    return true;
                }
            },
            debug: false,
            allowInputToggle: false,
            disabledTimeIntervals: false,
            disabledHours: false,
            enabledHours: false,
            viewDate: false,
            allowMultidate: false,
            multidateSeparator: ', ',
            updateOnlyThroughDateOption: false,
            promptTimeOnDateChange: false,
            promptTimeOnDateChangeTransitionDelay: 200
        };
    
        // ReSharper restore InconsistentNaming
    
        // ReSharper disable once DeclarationHides
        // ReSharper disable once InconsistentNaming
    
        var DateTimePicker = function () {
            /** @namespace eData.dateOptions */
            /** @namespace moment.tz */
    
            function DateTimePicker(element, options) {
                _classCallCheck(this, DateTimePicker);
    
                this._options = this._getOptions(options);
                this._element = element;
                this._dates = [];
                this._datesFormatted = [];
                this._viewDate = null;
                this.unset = true;
                this.component = false;
                this.widget = false;
                this.use24Hours = null;
                this.actualFormat = null;
                this.parseFormats = null;
                this.currentViewMode = null;
                this.MinViewModeNumber = 0;
                this.isInitFormatting = false;
                this.isInit = false;
                this.isDateUpdateThroughDateOptionFromClientCode = false;
                this.hasInitDate = false;
                this.initDate = void 0;
                this._notifyChangeEventContext = void 0;
                this._currentPromptTimeTimeout = null;
    
                this._int();
            }
    
            /**
             * @return {string}
             */
    
    
            //private
    
            DateTimePicker.prototype._int = function _int() {
                this.isInit = true;
                var targetInput = this._element.data('target-input');
                if (this._element.is('input')) {
                    this.input = this._element;
                } else if (targetInput !== undefined) {
                    if (targetInput === 'nearest') {
                        this.input = this._element.find('input');
                    } else {
                        this.input = $(targetInput);
                    }
                }
    
                this._dates = [];
                this._dates[0] = this.getMoment();
                this._viewDate = this.getMoment().clone();
    
                $.extend(true, this._options, this._dataToOptions());
    
                this.hasInitDate = false;
                this.initDate = void 0;
                this.options(this._options);
    
                this.isInitFormatting = true;
                this._initFormatting();
                this.isInitFormatting = false;
    
                if (this.input !== undefined && this.input.is('input') && this.input.val().trim().length !== 0) {
                    this._setValue(this._parseInputDate(this.input.val().trim()), 0);
                } else if (this._options.defaultDate && this.input !== undefined && this.input.attr('placeholder') === undefined) {
                    this._setValue(this._options.defaultDate, 0);
                }
                if (this.hasInitDate) {
                    this.date(this.initDate);
                }
    
                if (this._options.inline) {
                    this.show();
                }
                this.isInit = false;
            };
    
            DateTimePicker.prototype._update = function _update() {
                if (!this.widget) {
                    return;
                }
                this._fillDate();
                this._fillTime();
            };
    
            DateTimePicker.prototype._setValue = function _setValue(targetMoment, index) {
                var noIndex = typeof index === 'undefined',
                    isClear = !targetMoment && noIndex,
                    isDateUpdateThroughDateOptionFromClientCode = this.isDateUpdateThroughDateOptionFromClientCode,
                    isNotAllowedProgrammaticUpdate = !this.isInit && this._options.updateOnlyThroughDateOption && !isDateUpdateThroughDateOptionFromClientCode;
                var outpValue = '',
                    isInvalid = false,
                    oldDate = this.unset ? null : this._dates[index];
                if (!oldDate && !this.unset && noIndex && isClear) {
                    oldDate = this._dates[this._dates.length - 1];
                }
    
                // case of calling setValue(null or false)
                if (!targetMoment) {
                    if (isNotAllowedProgrammaticUpdate) {
                        this._notifyEvent({
                            type: DateTimePicker.Event.CHANGE,
                            date: targetMoment,
                            oldDate: oldDate,
                            isClear: isClear,
                            isInvalid: isInvalid,
                            isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
                            isInit: this.isInit
                        });
                        return;
                    }
                    if (!this._options.allowMultidate || this._dates.length === 1 || isClear) {
                        this.unset = true;
                        this._dates = [];
                        this._datesFormatted = [];
                    } else {
                        outpValue = '' + this._element.data('date') + this._options.multidateSeparator;
                        outpValue = oldDate && outpValue.replace('' + oldDate.format(this.actualFormat) + this._options.multidateSeparator, '').replace('' + this._options.multidateSeparator + this._options.multidateSeparator, '').replace(new RegExp(escapeRegExp(this._options.multidateSeparator) + '\\s*$'), '') || '';
                        this._dates.splice(index, 1);
                        this._datesFormatted.splice(index, 1);
                    }
                    outpValue = trim(outpValue);
                    if (this.input !== undefined) {
                        this.input.val(outpValue);
                        this.input.trigger('input');
                    }
                    this._element.data('date', outpValue);
                    this._notifyEvent({
                        type: DateTimePicker.Event.CHANGE,
                        date: false,
                        oldDate: oldDate,
                        isClear: isClear,
                        isInvalid: isInvalid,
                        isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
                        isInit: this.isInit
                    });
                    this._update();
                    return;
                }
    
                targetMoment = targetMoment.clone().locale(this._options.locale);
    
                if (this._hasTimeZone()) {
                    targetMoment.tz(this._options.timeZone);
                }
    
                if (this._options.stepping !== 1) {
                    targetMoment.minutes(Math.round(targetMoment.minutes() / this._options.stepping) * this._options.stepping).seconds(0);
                }
    
                if (this._isValid(targetMoment)) {
                    if (isNotAllowedProgrammaticUpdate) {
                        this._notifyEvent({
                            type: DateTimePicker.Event.CHANGE,
                            date: targetMoment.clone(),
                            oldDate: oldDate,
                            isClear: isClear,
                            isInvalid: isInvalid,
                            isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
                            isInit: this.isInit
                        });
                        return;
                    }
                    this._dates[index] = targetMoment;
                    this._datesFormatted[index] = targetMoment.format('YYYY-MM-DD');
                    this._viewDate = targetMoment.clone();
                    if (this._options.allowMultidate && this._dates.length > 1) {
                        for (var i = 0; i < this._dates.length; i++) {
                            outpValue += '' + this._dates[i].format(this.actualFormat) + this._options.multidateSeparator;
                        }
                        outpValue = outpValue.replace(new RegExp(this._options.multidateSeparator + '\\s*$'), '');
                    } else {
                        outpValue = this._dates[index].format(this.actualFormat);
                    }
                    outpValue = trim(outpValue);
                    if (this.input !== undefined) {
                        this.input.val(outpValue);
                        this.input.trigger('input');
                    }
                    this._element.data('date', outpValue);
    
                    this.unset = false;
                    this._update();
                    this._notifyEvent({
                        type: DateTimePicker.Event.CHANGE,
                        date: this._dates[index].clone(),
                        oldDate: oldDate,
                        isClear: isClear,
                        isInvalid: isInvalid,
                        isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
                        isInit: this.isInit
                    });
                } else {
                    isInvalid = true;
                    if (!this._options.keepInvalid) {
                        if (this.input !== undefined) {
                            this.input.val('' + (this.unset ? '' : this._dates[index].format(this.actualFormat)));
                            this.input.trigger('input');
                        }
                    } else {
                        this._notifyEvent({
                            type: DateTimePicker.Event.CHANGE,
                            date: targetMoment,
                            oldDate: oldDate,
                            isClear: isClear,
                            isInvalid: isInvalid,
                            isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
                            isInit: this.isInit
                        });
                    }
                    this._notifyEvent({
                        type: DateTimePicker.Event.ERROR,
                        date: targetMoment,
                        oldDate: oldDate
                    });
                }
            };
    
            DateTimePicker.prototype._change = function _change(e) {
                var val = $(e.target).val().trim(),
                    parsedDate = val ? this._parseInputDate(val) : null;
                this._setValue(parsedDate, 0);
                e.stopImmediatePropagation();
                return false;
            };
    
            //noinspection JSMethodCanBeStatic
    
    
            DateTimePicker.prototype._getOptions = function _getOptions(options) {
                options = $.extend(true, {}, Default, options && options.icons && options.icons.type === 'feather' ? {
                    icons: defaultFeatherIcons
                } : {}, options);
                return options;
            };
    
            DateTimePicker.prototype._hasTimeZone = function _hasTimeZone() {
                return moment.tz !== undefined && this._options.timeZone !== undefined && this._options.timeZone !== null && this._options.timeZone !== '';
            };
    
            DateTimePicker.prototype._isEnabled = function _isEnabled(granularity) {
                if (typeof granularity !== 'string' || granularity.length > 1) {
                    throw new TypeError('isEnabled expects a single character string parameter');
                }
                switch (granularity) {
                    case 'y':
                        return this.actualFormat.indexOf('Y') !== -1;
                    case 'M':
                        return this.actualFormat.indexOf('M') !== -1;
                    case 'd':
                        return this.actualFormat.toLowerCase().indexOf('d') !== -1;
                    case 'h':
                    case 'H':
                        return this.actualFormat.toLowerCase().indexOf('h') !== -1;
                    case 'm':
                        return this.actualFormat.indexOf('m') !== -1;
                    case 's':
                        return this.actualFormat.indexOf('s') !== -1;
                    case 'a':
                    case 'A':
                        return this.actualFormat.toLowerCase().indexOf('a') !== -1;
                    default:
                        return false;
                }
            };
    
            DateTimePicker.prototype._hasTime = function _hasTime() {
                return this._isEnabled('h') || this._isEnabled('m') || this._isEnabled('s');
            };
    
            DateTimePicker.prototype._hasDate = function _hasDate() {
                return this._isEnabled('y') || this._isEnabled('M') || this._isEnabled('d');
            };
    
            DateTimePicker.prototype._dataToOptions = function _dataToOptions() {
                var eData = this._element.data();
                var dataOptions = {};
    
                if (eData.dateOptions && eData.dateOptions instanceof Object) {
                    dataOptions = $.extend(true, dataOptions, eData.dateOptions);
                }
    
                $.each(this._options, function (key) {
                    var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); //todo data api key
                    if (eData[attributeName] !== undefined) {
                        dataOptions[key] = eData[attributeName];
                    } else {
                        delete dataOptions[key];
                    }
                });
                return dataOptions;
            };
    
            DateTimePicker.prototype._format = function _format() {
                return this._options.format || 'YYYY-MM-DD HH:mm';
            };
    
            DateTimePicker.prototype._areSameDates = function _areSameDates(a, b) {
                var format = this._format();
                return a && b && (a.isSame(b) || moment(a.format(format), format).isSame(moment(b.format(format), format)));
            };
    
            DateTimePicker.prototype._notifyEvent = function _notifyEvent(e) {
                if (e.type === DateTimePicker.Event.CHANGE) {
                    this._notifyChangeEventContext = this._notifyChangeEventContext || 0;
                    this._notifyChangeEventContext++;
                    if (e.date && this._areSameDates(e.date, e.oldDate) || !e.isClear && !e.date && !e.oldDate || this._notifyChangeEventContext > 1) {
                        this._notifyChangeEventContext = void 0;
                        return;
                    }
                    this._handlePromptTimeIfNeeded(e);
                }
                this._element.trigger(e);
                this._notifyChangeEventContext = void 0;
            };
    
            DateTimePicker.prototype._handlePromptTimeIfNeeded = function _handlePromptTimeIfNeeded(e) {
                if (this._options.promptTimeOnDateChange) {
                    if (!e.oldDate && this._options.useCurrent) {
                        // First time ever. If useCurrent option is set to true (default), do nothing
                        // because the first date is selected automatically.
                        return;
                    } else if (e.oldDate && e.date && (e.oldDate.format('YYYY-MM-DD') === e.date.format('YYYY-MM-DD') || e.oldDate.format('YYYY-MM-DD') !== e.date.format('YYYY-MM-DD') && e.oldDate.format('HH:mm:ss') !== e.date.format('HH:mm:ss'))) {
                        // Date didn't change (time did) or date changed because time did.
                        return;
                    }
    
                    var that = this;
                    clearTimeout(this._currentPromptTimeTimeout);
                    this._currentPromptTimeTimeout = setTimeout(function () {
                        if (that.widget) {
                            that.widget.find('[data-action="togglePicker"]').click();
                        }
                    }, this._options.promptTimeOnDateChangeTransitionDelay);
                }
            };
    
            DateTimePicker.prototype._viewUpdate = function _viewUpdate(e) {
                if (e === 'y') {
                    e = 'YYYY';
                }
                this._notifyEvent({
                    type: DateTimePicker.Event.UPDATE,
                    change: e,
                    viewDate: this._viewDate.clone()
                });
            };
    
            DateTimePicker.prototype._showMode = function _showMode(dir) {
                if (!this.widget) {
                    return;
                }
                if (dir) {
                    this.currentViewMode = Math.max(this.MinViewModeNumber, Math.min(3, this.currentViewMode + dir));
                }
                this.widget.find('.datepicker > div').hide().filter('.datepicker-' + DatePickerModes[this.currentViewMode].CLASS_NAME).show();
            };
    
            DateTimePicker.prototype._isInDisabledDates = function _isInDisabledDates(testDate) {
                return this._options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
            };
    
            DateTimePicker.prototype._isInEnabledDates = function _isInEnabledDates(testDate) {
                return this._options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
            };
    
            DateTimePicker.prototype._isInDisabledHours = function _isInDisabledHours(testDate) {
                return this._options.disabledHours[testDate.format('H')] === true;
            };
    
            DateTimePicker.prototype._isInEnabledHours = function _isInEnabledHours(testDate) {
                return this._options.enabledHours[testDate.format('H')] === true;
            };
    
            DateTimePicker.prototype._isValid = function _isValid(targetMoment, granularity) {
                if (!targetMoment || !targetMoment.isValid()) {
                    return false;
                }
                if (this._options.disabledDates && granularity === 'd' && this._isInDisabledDates(targetMoment)) {
                    return false;
                }
                if (this._options.enabledDates && granularity === 'd' && !this._isInEnabledDates(targetMoment)) {
                    return false;
                }
                if (this._options.minDate && targetMoment.isBefore(this._options.minDate, granularity)) {
                    return false;
                }
                if (this._options.maxDate && targetMoment.isAfter(this._options.maxDate, granularity)) {
                    return false;
                }
                if (this._options.daysOfWeekDisabled && granularity === 'd' && this._options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
                    return false;
                }
                if (this._options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && this._isInDisabledHours(targetMoment)) {
                    return false;
                }
                if (this._options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !this._isInEnabledHours(targetMoment)) {
                    return false;
                }
                if (this._options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
                    var found = false;
                    $.each(this._options.disabledTimeIntervals, function () {
                        if (targetMoment.isBetween(this[0], this[1])) {
                            found = true;
                            return false;
                        }
                    });
                    if (found) {
                        return false;
                    }
                }
                return true;
            };
    
            DateTimePicker.prototype._parseInputDate = function _parseInputDate(inputDate) {
                var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
                    _ref$isPickerShow = _ref.isPickerShow,
                    isPickerShow = _ref$isPickerShow === undefined ? false : _ref$isPickerShow;
    
                if (this._options.parseInputDate === undefined || isPickerShow) {
                    if (!moment.isMoment(inputDate)) {
                        inputDate = this.getMoment(inputDate);
                    }
                } else {
                    inputDate = this._options.parseInputDate(inputDate);
                }
                //inputDate.locale(this.options.locale);
                return inputDate;
            };
    
            DateTimePicker.prototype._keydown = function _keydown(e) {
                var handler = null,
                    index = void 0,
                    index2 = void 0,
                    keyBindKeys = void 0,
                    allModifiersPressed = void 0;
                var pressedKeys = [],
                    pressedModifiers = {},
                    currentKey = e.which,
                    pressed = 'p';
    
                keyState[currentKey] = pressed;
    
                for (index in keyState) {
                    if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
                        pressedKeys.push(index);
                        if (parseInt(index, 10) !== currentKey) {
                            pressedModifiers[index] = true;
                        }
                    }
                }
    
                for (index in this._options.keyBinds) {
                    if (this._options.keyBinds.hasOwnProperty(index) && typeof this._options.keyBinds[index] === 'function') {
                        keyBindKeys = index.split(' ');
                        if (keyBindKeys.length === pressedKeys.length && KeyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
                            allModifiersPressed = true;
                            for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
                                if (!(KeyMap[keyBindKeys[index2]] in pressedModifiers)) {
                                    allModifiersPressed = false;
                                    break;
                                }
                            }
                            if (allModifiersPressed) {
                                handler = this._options.keyBinds[index];
                                break;
                            }
                        }
                    }
                }
    
                if (handler) {
                    if (handler.call(this)) {
                        e.stopPropagation();
                        e.preventDefault();
                    }
                }
            };
    
            //noinspection JSMethodCanBeStatic,SpellCheckingInspection
    
    
            DateTimePicker.prototype._keyup = function _keyup(e) {
                keyState[e.which] = 'r';
                if (keyPressHandled[e.which]) {
                    keyPressHandled[e.which] = false;
                    e.stopPropagation();
                    e.preventDefault();
                }
            };
    
            DateTimePicker.prototype._indexGivenDates = function _indexGivenDates(givenDatesArray) {
                // Store given enabledDates and disabledDates as keys.
                // This way we can check their existence in O(1) time instead of looping through whole array.
                // (for example: options.enabledDates['2014-02-27'] === true)
                var givenDatesIndexed = {},
                    self = this;
                $.each(givenDatesArray, function () {
                    var dDate = self._parseInputDate(this);
                    if (dDate.isValid()) {
                        givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
                    }
                });
                return Object.keys(givenDatesIndexed).length ? givenDatesIndexed : false;
            };
    
            DateTimePicker.prototype._indexGivenHours = function _indexGivenHours(givenHoursArray) {
                // Store given enabledHours and disabledHours as keys.
                // This way we can check their existence in O(1) time instead of looping through whole array.
                // (for example: options.enabledHours['2014-02-27'] === true)
                var givenHoursIndexed = {};
                $.each(givenHoursArray, function () {
                    givenHoursIndexed[this] = true;
                });
                return Object.keys(givenHoursIndexed).length ? givenHoursIndexed : false;
            };
    
            DateTimePicker.prototype._initFormatting = function _initFormatting() {
                var format = this._options.format || 'L LT',
                    self = this;
    
                this.actualFormat = format.replace(/(\[[^\[]*])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
                    return (self.isInitFormatting && self._options.date === null ? self.getMoment() : self._dates[0]).localeData().longDateFormat(formatInput) || formatInput; //todo taking the first date should be ok
                });
    
                this.parseFormats = this._options.extraFormats ? this._options.extraFormats.slice() : [];
                if (this.parseFormats.indexOf(format) < 0 && this.parseFormats.indexOf(this.actualFormat) < 0) {
                    this.parseFormats.push(this.actualFormat);
                }
    
                this.use24Hours = this.actualFormat.toLowerCase().indexOf('a') < 1 && this.actualFormat.replace(/\[.*?]/g, '').indexOf('h') < 1;
    
                if (this._isEnabled('y')) {
                    this.MinViewModeNumber = 2;
                }
                if (this._isEnabled('M')) {
                    this.MinViewModeNumber = 1;
                }
                if (this._isEnabled('d')) {
                    this.MinViewModeNumber = 0;
                }
    
                this.currentViewMode = Math.max(this.MinViewModeNumber, this.currentViewMode);
    
                if (!this.unset) {
                    this._setValue(this._dates[0], 0);
                }
            };
    
            DateTimePicker.prototype._getLastPickedDate = function _getLastPickedDate() {
                var lastPickedDate = this._dates[this._getLastPickedDateIndex()];
                if (!lastPickedDate && this._options.allowMultidate) {
                    lastPickedDate = moment(new Date());
                }
                return lastPickedDate;
            };
    
            DateTimePicker.prototype._getLastPickedDateIndex = function _getLastPickedDateIndex() {
                return this._dates.length - 1;
            };
    
            //public
    
    
            DateTimePicker.prototype.getMoment = function getMoment(d) {
                var returnMoment = void 0;
    
                if (d === undefined || d === null) {
                    // TODO: Should this use format?
                    returnMoment = moment().clone().locale(this._options.locale);
                } else if (this._hasTimeZone()) {
                    // There is a string to parse and a default time zone
                    // parse with the tz function which takes a default time zone if it is not in the format string
                    returnMoment = moment.tz(d, this.parseFormats, this._options.locale, this._options.useStrict, this._options.timeZone);
                } else {
                    returnMoment = moment(d, this.parseFormats, this._options.locale, this._options.useStrict);
                }
    
                if (this._hasTimeZone()) {
                    returnMoment.tz(this._options.timeZone);
                }
    
                return returnMoment;
            };
    
            DateTimePicker.prototype.toggle = function toggle() {
                return this.widget ? this.hide() : this.show();
            };
    
            DateTimePicker.prototype.readonly = function readonly(_readonly) {
                if (arguments.length === 0) {
                    return this._options.readonly;
                }
                if (typeof _readonly !== 'boolean') {
                    throw new TypeError('readonly() expects a boolean parameter');
                }
                this._options.readonly = _readonly;
                if (this.input !== undefined) {
                    this.input.prop('readonly', this._options.readonly);
                }
                if (this.widget) {
                    this.hide();
                    this.show();
                }
            };
    
            DateTimePicker.prototype.ignoreReadonly = function ignoreReadonly(_ignoreReadonly) {
                if (arguments.length === 0) {
                    return this._options.ignoreReadonly;
                }
                if (typeof _ignoreReadonly !== 'boolean') {
                    throw new TypeError('ignoreReadonly() expects a boolean parameter');
                }
                this._options.ignoreReadonly = _ignoreReadonly;
            };
    
            DateTimePicker.prototype.options = function options(newOptions) {
                if (arguments.length === 0) {
                    return $.extend(true, {}, this._options);
                }
    
                if (!(newOptions instanceof Object)) {
                    throw new TypeError('options() this.options parameter should be an object');
                }
                $.extend(true, this._options, newOptions);
                var self = this,
                    optionsKeys = Object.keys(this._options).sort(optionsSortFn);
                $.each(optionsKeys, function (i, key) {
                    var value = self._options[key];
                    if (self[key] !== undefined) {
                        if (self.isInit && key === 'date') {
                            self.hasInitDate = true;
                            self.initDate = value;
                            return;
                        }
                        self[key](value);
                    }
                });
            };
    
            DateTimePicker.prototype.date = function date(newDate, index) {
                index = index || 0;
                if (arguments.length === 0) {
                    if (this.unset) {
                        return null;
                    }
                    if (this._options.allowMultidate) {
                        return this._dates.join(this._options.multidateSeparator);
                    } else {
                        return this._dates[index].clone();
                    }
                }
    
                if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
                    throw new TypeError('date() parameter must be one of [null, string, moment or Date]');
                }
    
                if (typeof newDate === 'string' && isValidDateTimeStr(newDate)) {
                    newDate = new Date(newDate);
                }
    
                this._setValue(newDate === null ? null : this._parseInputDate(newDate), index);
            };
    
            DateTimePicker.prototype.updateOnlyThroughDateOption = function updateOnlyThroughDateOption(_updateOnlyThroughDateOption) {
                if (typeof _updateOnlyThroughDateOption !== 'boolean') {
                    throw new TypeError('updateOnlyThroughDateOption() expects a boolean parameter');
                }
    
                this._options.updateOnlyThroughDateOption = _updateOnlyThroughDateOption;
            };
    
            DateTimePicker.prototype.format = function format(newFormat) {
                if (arguments.length === 0) {
                    return this._options.format;
                }
    
                if (typeof newFormat !== 'string' && (typeof newFormat !== 'boolean' || newFormat !== false)) {
                    throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat);
                }
    
                this._options.format = newFormat;
                if (this.actualFormat) {
                    this._initFormatting(); // reinitialize formatting
                }
            };
    
            DateTimePicker.prototype.timeZone = function timeZone(newZone) {
                if (arguments.length === 0) {
                    return this._options.timeZone;
                }
    
                if (typeof newZone !== 'string') {
                    throw new TypeError('newZone() expects a string parameter');
                }
    
                this._options.timeZone = newZone;
            };
    
            DateTimePicker.prototype.dayViewHeaderFormat = function dayViewHeaderFormat(newFormat) {
                if (arguments.length === 0) {
                    return this._options.dayViewHeaderFormat;
                }
    
                if (typeof newFormat !== 'string') {
                    throw new TypeError('dayViewHeaderFormat() expects a string parameter');
                }
    
                this._options.dayViewHeaderFormat = newFormat;
            };
    
            DateTimePicker.prototype.extraFormats = function extraFormats(formats) {
                if (arguments.length === 0) {
                    return this._options.extraFormats;
                }
    
                if (formats !== false && !(formats instanceof Array)) {
                    throw new TypeError('extraFormats() expects an array or false parameter');
                }
    
                this._options.extraFormats = formats;
                if (this.parseFormats) {
                    this._initFormatting(); // reinit formatting
                }
            };
    
            DateTimePicker.prototype.disabledDates = function disabledDates(dates) {
                if (arguments.length === 0) {
                    return this._options.disabledDates ? $.extend({}, this._options.disabledDates) : this._options.disabledDates;
                }
    
                if (!dates) {
                    this._options.disabledDates = false;
                    this._update();
                    return true;
                }
                if (!(dates instanceof Array)) {
                    throw new TypeError('disabledDates() expects an array parameter');
                }
                this._options.disabledDates = this._indexGivenDates(dates);
                this._options.enabledDates = false;
                this._update();
            };
    
            DateTimePicker.prototype.enabledDates = function enabledDates(dates) {
                if (arguments.length === 0) {
                    return this._options.enabledDates ? $.extend({}, this._options.enabledDates) : this._options.enabledDates;
                }
    
                if (!dates) {
                    this._options.enabledDates = false;
                    this._update();
                    return true;
                }
                if (!(dates instanceof Array)) {
                    throw new TypeError('enabledDates() expects an array parameter');
                }
                this._options.enabledDates = this._indexGivenDates(dates);
                this._options.disabledDates = false;
                this._update();
            };
    
            DateTimePicker.prototype.daysOfWeekDisabled = function daysOfWeekDisabled(_daysOfWeekDisabled) {
                if (arguments.length === 0) {
                    return this._options.daysOfWeekDisabled.splice(0);
                }
    
                if (typeof _daysOfWeekDisabled === 'boolean' && !_daysOfWeekDisabled) {
                    this._options.daysOfWeekDisabled = false;
                    this._update();
                    return true;
                }
    
                if (!(_daysOfWeekDisabled instanceof Array)) {
                    throw new TypeError('daysOfWeekDisabled() expects an array parameter');
                }
                this._options.daysOfWeekDisabled = _daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
                    currentValue = parseInt(currentValue, 10);
                    if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {
                        return previousValue;
                    }
                    if (previousValue.indexOf(currentValue) === -1) {
                        previousValue.push(currentValue);
                    }
                    return previousValue;
                }, []).sort();
                if (this._options.useCurrent && !this._options.keepInvalid) {
                    for (var i = 0; i < this._dates.length; i++) {
                        var tries = 0;
                        while (!this._isValid(this._dates[i], 'd')) {
                            this._dates[i].add(1, 'd');
                            if (tries === 31) {
                                throw 'Tried 31 times to find a valid date';
                            }
                            tries++;
                        }
                        this._setValue(this._dates[i], i);
                    }
                }
                this._update();
            };
    
            DateTimePicker.prototype.maxDate = function maxDate(_maxDate) {
                if (arguments.length === 0) {
                    return this._options.maxDate ? this._options.maxDate.clone() : this._options.maxDate;
                }
    
                if (typeof _maxDate === 'boolean' && _maxDate === false) {
                    this._options.maxDate = false;
                    this._update();
                    return true;
                }
    
                if (typeof _maxDate === 'string') {
                    if (_maxDate === 'now' || _maxDate === 'moment') {
                        _maxDate = this.getMoment();
                    }
                }
    
                var parsedDate = this._parseInputDate(_maxDate);
    
                if (!parsedDate.isValid()) {
                    throw new TypeError('maxDate() Could not parse date parameter: ' + _maxDate);
                }
                if (this._options.minDate && parsedDate.isBefore(this._options.minDate)) {
                    throw new TypeError('maxDate() date parameter is before this.options.minDate: ' + parsedDate.format(this.actualFormat));
                }
                this._options.maxDate = parsedDate;
                for (var i = 0; i < this._dates.length; i++) {
                    if (this._options.useCurrent && !this._options.keepInvalid && this._dates[i].isAfter(_maxDate)) {
                        this._setValue(this._options.maxDate, i);
                    }
                }
                if (this._viewDate.isAfter(parsedDate)) {
                    this._viewDate = parsedDate.clone().subtract(this._options.stepping, 'm');
                }
                this._update();
            };
    
            DateTimePicker.prototype.minDate = function minDate(_minDate) {
                if (arguments.length === 0) {
                    return this._options.minDate ? this._options.minDate.clone() : this._options.minDate;
                }
    
                if (typeof _minDate === 'boolean' && _minDate === false) {
                    this._options.minDate = false;
                    this._update();
                    return true;
                }
    
                if (typeof _minDate === 'string') {
                    if (_minDate === 'now' || _minDate === 'moment') {
                        _minDate = this.getMoment();
                    }
                }
    
                var parsedDate = this._parseInputDate(_minDate);
    
                if (!parsedDate.isValid()) {
                    throw new TypeError('minDate() Could not parse date parameter: ' + _minDate);
                }
                if (this._options.maxDate && parsedDate.isAfter(this._options.maxDate)) {
                    throw new TypeError('minDate() date parameter is after this.options.maxDate: ' + parsedDate.format(this.actualFormat));
                }
                this._options.minDate = parsedDate;
                for (var i = 0; i < this._dates.length; i++) {
                    if (this._options.useCurrent && !this._options.keepInvalid && this._dates[i].isBefore(_minDate)) {
                        this._setValue(this._options.minDate, i);
                    }
                }
                if (this._viewDate.isBefore(parsedDate)) {
                    this._viewDate = parsedDate.clone().add(this._options.stepping, 'm');
                }
                this._update();
            };
    
            DateTimePicker.prototype.defaultDate = function defaultDate(_defaultDate) {
                if (arguments.length === 0) {
                    return this._options.defaultDate ? this._options.defaultDate.clone() : this._options.defaultDate;
                }
                if (!_defaultDate) {
                    this._options.defaultDate = false;
                    return true;
                }
    
                if (typeof _defaultDate === 'string') {
                    if (_defaultDate === 'now' || _defaultDate === 'moment') {
                        _defaultDate = this.getMoment();
                    } else {
                        _defaultDate = this.getMoment(_defaultDate);
                    }
                }
    
                var parsedDate = this._parseInputDate(_defaultDate);
                if (!parsedDate.isValid()) {
                    throw new TypeError('defaultDate() Could not parse date parameter: ' + _defaultDate);
                }
                if (!this._isValid(parsedDate)) {
                    throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
                }
    
                this._options.defaultDate = parsedDate;
    
                if (this._options.defaultDate && this._options.inline || this.input !== undefined && this.input.val().trim() === '') {
                    this._setValue(this._options.defaultDate, 0);
                }
            };
    
            DateTimePicker.prototype.locale = function locale(_locale) {
                if (arguments.length === 0) {
                    return this._options.locale;
                }
    
                if (!moment.localeData(_locale)) {
                    throw new TypeError('locale() locale ' + _locale + ' is not loaded from moment locales!');
                }
    
                this._options.locale = _locale;
    
                for (var i = 0; i < this._dates.length; i++) {
                    this._dates[i].locale(this._options.locale);
                }
                this._viewDate.locale(this._options.locale);
    
                if (this.actualFormat) {
                    this._initFormatting(); // reinitialize formatting
                }
                if (this.widget) {
                    this.hide();
                    this.show();
                }
            };
    
            DateTimePicker.prototype.stepping = function stepping(_stepping) {
                if (arguments.length === 0) {
                    return this._options.stepping;
                }
    
                _stepping = parseInt(_stepping, 10);
                if (isNaN(_stepping) || _stepping < 1) {
                    _stepping = 1;
                }
                this._options.stepping = _stepping;
            };
    
            DateTimePicker.prototype.useCurrent = function useCurrent(_useCurrent) {
                var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];
                if (arguments.length === 0) {
                    return this._options.useCurrent;
                }
    
                if (typeof _useCurrent !== 'boolean' && typeof _useCurrent !== 'string') {
                    throw new TypeError('useCurrent() expects a boolean or string parameter');
                }
                if (typeof _useCurrent === 'string' && useCurrentOptions.indexOf(_useCurrent.toLowerCase()) === -1) {
                    throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', '));
                }
                this._options.useCurrent = _useCurrent;
            };
    
            DateTimePicker.prototype.collapse = function collapse(_collapse) {
                if (arguments.length === 0) {
                    return this._options.collapse;
                }
    
                if (typeof _collapse !== 'boolean') {
                    throw new TypeError('collapse() expects a boolean parameter');
                }
                if (this._options.collapse === _collapse) {
                    return true;
                }
                this._options.collapse = _collapse;
                if (this.widget) {
                    this.hide();
                    this.show();
                }
            };
    
            DateTimePicker.prototype.icons = function icons(_icons) {
                if (arguments.length === 0) {
                    return $.extend({}, this._options.icons);
                }
    
                if (!(_icons instanceof Object)) {
                    throw new TypeError('icons() expects parameter to be an Object');
                }
    
                $.extend(this._options.icons, _icons);
    
                if (this.widget) {
                    this.hide();
                    this.show();
                }
            };
    
            DateTimePicker.prototype.tooltips = function tooltips(_tooltips) {
                if (arguments.length === 0) {
                    return $.extend({}, this._options.tooltips);
                }
    
                if (!(_tooltips instanceof Object)) {
                    throw new TypeError('tooltips() expects parameter to be an Object');
                }
                $.extend(this._options.tooltips, _tooltips);
                if (this.widget) {
                    this.hide();
                    this.show();
                }
            };
    
            DateTimePicker.prototype.useStrict = function useStrict(_useStrict) {
                if (arguments.length === 0) {
                    return this._options.useStrict;
                }
    
                if (typeof _useStrict !== 'boolean') {
                    throw new TypeError('useStrict() expects a boolean parameter');
                }
                this._options.useStrict = _useStrict;
            };
    
            DateTimePicker.prototype.sideBySide = function sideBySide(_sideBySide) {
                if (arguments.length === 0) {
                    return this._options.sideBySide;
                }
    
                if (typeof _sideBySide !== 'boolean') {
                    throw new TypeError('sideBySide() expects a boolean parameter');
                }
                this._options.sideBySide = _sideBySide;
                if (this.widget) {
                    this.hide();
                    this.show();
                }
            };
    
            DateTimePicker.prototype.viewMode = function viewMode(_viewMode) {
                if (arguments.length === 0) {
                    return this._options.viewMode;
                }
    
                if (typeof _viewMode !== 'string') {
                    throw new TypeError('viewMode() expects a string parameter');
                }
    
                if (DateTimePicker.ViewModes.indexOf(_viewMode) === -1) {
                    throw new TypeError('viewMode() parameter must be one of (' + DateTimePicker.ViewModes.join(', ') + ') value');
                }
    
                this._options.viewMode = _viewMode;
                this.currentViewMode = Math.max(DateTimePicker.ViewModes.indexOf(_viewMode) - 1, this.MinViewModeNumber);
    
                this._showMode();
            };
    
            DateTimePicker.prototype.calendarWeeks = function calendarWeeks(_calendarWeeks) {
                if (arguments.length === 0) {
                    return this._options.calendarWeeks;
                }
    
                if (typeof _calendarWeeks !== 'boolean') {
                    throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
                }
    
                this._options.calendarWeeks = _calendarWeeks;
                this._update();
            };
    
            DateTimePicker.prototype.buttons = function buttons(_buttons) {
                if (arguments.length === 0) {
                    return $.extend({}, this._options.buttons);
                }
    
                if (!(_buttons instanceof Object)) {
                    throw new TypeError('buttons() expects parameter to be an Object');
                }
    
                $.extend(this._options.buttons, _buttons);
    
                if (typeof this._options.buttons.showToday !== 'boolean') {
                    throw new TypeError('buttons.showToday expects a boolean parameter');
                }
                if (typeof this._options.buttons.showClear !== 'boolean') {
                    throw new TypeError('buttons.showClear expects a boolean parameter');
                }
                if (typeof this._options.buttons.showClose !== 'boolean') {
                    throw new TypeError('buttons.showClose expects a boolean parameter');
                }
    
                if (this.widget) {
                    this.hide();
                    this.show();
                }
            };
    
            DateTimePicker.prototype.keepOpen = function keepOpen(_keepOpen) {
                if (arguments.length === 0) {
                    return this._options.keepOpen;
                }
    
                if (typeof _keepOpen !== 'boolean') {
                    throw new TypeError('keepOpen() expects a boolean parameter');
                }
    
                this._options.keepOpen = _keepOpen;
            };
    
            DateTimePicker.prototype.focusOnShow = function focusOnShow(_focusOnShow) {
                if (arguments.length === 0) {
                    return this._options.focusOnShow;
                }
    
                if (typeof _focusOnShow !== 'boolean') {
                    throw new TypeError('focusOnShow() expects a boolean parameter');
                }
    
                this._options.focusOnShow = _focusOnShow;
            };
    
            DateTimePicker.prototype.inline = function inline(_inline) {
                if (arguments.length === 0) {
                    return this._options.inline;
                }
    
                if (typeof _inline !== 'boolean') {
                    throw new TypeError('inline() expects a boolean parameter');
                }
    
                this._options.inline = _inline;
            };
    
            DateTimePicker.prototype.clear = function clear() {
                this._setValue(null); //todo
            };
    
            DateTimePicker.prototype.keyBinds = function keyBinds(_keyBinds) {
                if (arguments.length === 0) {
                    return this._options.keyBinds;
                }
    
                this._options.keyBinds = _keyBinds;
            };
    
            DateTimePicker.prototype.debug = function debug(_debug) {
                if (typeof _debug !== 'boolean') {
                    throw new TypeError('debug() expects a boolean parameter');
                }
    
                this._options.debug = _debug;
            };
    
            DateTimePicker.prototype.allowInputToggle = function allowInputToggle(_allowInputToggle) {
                if (arguments.length === 0) {
                    return this._options.allowInputToggle;
                }
    
                if (typeof _allowInputToggle !== 'boolean') {
                    throw new TypeError('allowInputToggle() expects a boolean parameter');
                }
    
                this._options.allowInputToggle = _allowInputToggle;
            };
    
            DateTimePicker.prototype.keepInvalid = function keepInvalid(_keepInvalid) {
                if (arguments.length === 0) {
                    return this._options.keepInvalid;
                }
    
                if (typeof _keepInvalid !== 'boolean') {
                    throw new TypeError('keepInvalid() expects a boolean parameter');
                }
                this._options.keepInvalid = _keepInvalid;
            };
    
            DateTimePicker.prototype.datepickerInput = function datepickerInput(_datepickerInput) {
                if (arguments.length === 0) {
                    return this._options.datepickerInput;
                }
    
                if (typeof _datepickerInput !== 'string') {
                    throw new TypeError('datepickerInput() expects a string parameter');
                }
    
                this._options.datepickerInput = _datepickerInput;
            };
    
            DateTimePicker.prototype.parseInputDate = function parseInputDate(_parseInputDate2) {
                if (arguments.length === 0) {
                    return this._options.parseInputDate;
                }
    
                if (typeof _parseInputDate2 !== 'function') {
                    throw new TypeError('parseInputDate() should be as function');
                }
    
                this._options.parseInputDate = _parseInputDate2;
            };
    
            DateTimePicker.prototype.disabledTimeIntervals = function disabledTimeIntervals(_disabledTimeIntervals) {
                if (arguments.length === 0) {
                    return this._options.disabledTimeIntervals ? $.extend({}, this._options.disabledTimeIntervals) : this._options.disabledTimeIntervals;
                }
    
                if (!_disabledTimeIntervals) {
                    this._options.disabledTimeIntervals = false;
                    this._update();
                    return true;
                }
                if (!(_disabledTimeIntervals instanceof Array)) {
                    throw new TypeError('disabledTimeIntervals() expects an array parameter');
                }
                this._options.disabledTimeIntervals = _disabledTimeIntervals;
                this._update();
            };
    
            DateTimePicker.prototype.disabledHours = function disabledHours(hours) {
                if (arguments.length === 0) {
                    return this._options.disabledHours ? $.extend({}, this._options.disabledHours) : this._options.disabledHours;
                }
    
                if (!hours) {
                    this._options.disabledHours = false;
                    this._update();
                    return true;
                }
                if (!(hours instanceof Array)) {
                    throw new TypeError('disabledHours() expects an array parameter');
                }
                this._options.disabledHours = this._indexGivenHours(hours);
                this._options.enabledHours = false;
                if (this._options.useCurrent && !this._options.keepInvalid) {
                    for (var i = 0; i < this._dates.length; i++) {
                        var tries = 0;
                        while (!this._isValid(this._dates[i], 'h')) {
                            this._dates[i].add(1, 'h');
                            if (tries === 24) {
                                throw 'Tried 24 times to find a valid date';
                            }
                            tries++;
                        }
                        this._setValue(this._dates[i], i);
                    }
                }
                this._update();
            };
    
            DateTimePicker.prototype.enabledHours = function enabledHours(hours) {
                if (arguments.length === 0) {
                    return this._options.enabledHours ? $.extend({}, this._options.enabledHours) : this._options.enabledHours;
                }
    
                if (!hours) {
                    this._options.enabledHours = false;
                    this._update();
                    return true;
                }
                if (!(hours instanceof Array)) {
                    throw new TypeError('enabledHours() expects an array parameter');
                }
                this._options.enabledHours = this._indexGivenHours(hours);
                this._options.disabledHours = false;
                if (this._options.useCurrent && !this._options.keepInvalid) {
                    for (var i = 0; i < this._dates.length; i++) {
                        var tries = 0;
                        while (!this._isValid(this._dates[i], 'h')) {
                            this._dates[i].add(1, 'h');
                            if (tries === 24) {
                                throw 'Tried 24 times to find a valid date';
                            }
                            tries++;
                        }
                        this._setValue(this._dates[i], i);
                    }
                }
                this._update();
            };
    
            DateTimePicker.prototype.viewDate = function viewDate(newDate) {
                if (arguments.length === 0) {
                    return this._viewDate.clone();
                }
    
                if (!newDate) {
                    this._viewDate = (this._dates[0] || this.getMoment()).clone();
                    return true;
                }
    
                if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
                    throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
                }
    
                this._viewDate = this._parseInputDate(newDate);
                this._update();
                this._viewUpdate(DatePickerModes[this.currentViewMode] && DatePickerModes[this.currentViewMode].NAV_FUNCTION);
            };
    
            DateTimePicker.prototype._fillDate = function _fillDate() {};
    
            DateTimePicker.prototype._useFeatherIcons = function _useFeatherIcons() {
                return this._options.icons.type === 'feather';
            };
    
            DateTimePicker.prototype.allowMultidate = function allowMultidate(_allowMultidate) {
                if (typeof _allowMultidate !== 'boolean') {
                    throw new TypeError('allowMultidate() expects a boolean parameter');
                }
    
                this._options.allowMultidate = _allowMultidate;
            };
    
            DateTimePicker.prototype.multidateSeparator = function multidateSeparator(_multidateSeparator) {
                if (arguments.length === 0) {
                    return this._options.multidateSeparator;
                }
    
                if (typeof _multidateSeparator !== 'string') {
                    throw new TypeError('multidateSeparator expects a string parameter');
                }
    
                this._options.multidateSeparator = _multidateSeparator;
            };
    
            _createClass(DateTimePicker, null, [{
                key: 'NAME',
                get: function get() {
                    return NAME;
                }
    
                /**
                 * @return {string}
                 */
    
            }, {
                key: 'DATA_KEY',
                get: function get() {
                    return DATA_KEY;
                }
    
                /**
                 * @return {string}
                 */
    
            }, {
                key: 'EVENT_KEY',
                get: function get() {
                    return EVENT_KEY;
                }
    
                /**
                 * @return {string}
                 */
    
            }, {
                key: 'DATA_API_KEY',
                get: function get() {
                    return DATA_API_KEY;
                }
            }, {
                key: 'DatePickerModes',
                get: function get() {
                    return DatePickerModes;
                }
            }, {
                key: 'ViewModes',
                get: function get() {
                    return ViewModes;
                }
            }, {
                key: 'Event',
                get: function get() {
                    return Event;
                }
            }, {
                key: 'Selector',
                get: function get() {
                    return Selector;
                }
            }, {
                key: 'Default',
                get: function get() {
                    return Default;
                },
                set: function set(value) {
                    Default = value;
                }
            }, {
                key: 'ClassName',
                get: function get() {
                    return ClassName;
                }
            }]);
    
            return DateTimePicker;
        }();
    
        return DateTimePicker;
    }(jQuery, moment);
    
    /*!@preserve
     * Tempus Dominus Bootstrap4 v5.39.0 (https://tempusdominus.github.io/bootstrap-4/)
     * Copyright 2016-2020 Jonathan Peterson and contributors
     * Licensed under MIT (https://github.com/tempusdominus/bootstrap-3/blob/master/LICENSE)
     */
    
    if (typeof jQuery === 'undefined') {
      throw new Error('Tempus Dominus Bootstrap4\'s requires jQuery. jQuery must be included before Tempus Dominus Bootstrap4\'s JavaScript.');
    }
    
    +function ($) {
      var version = $.fn.jquery.split(' ')[0].split('.');
      if ((version[0] < 2 && version[1] < 9) || (version[0] === 1 && version[1] === 9 && version[2] < 1) || (version[0] >= 4)) {
        throw new Error('Tempus Dominus Bootstrap4\'s requires at least jQuery v3.0.0 but less than v4.0.0');
      }
    }(jQuery);
    
    
    if (typeof moment === 'undefined') {
      throw new Error('Tempus Dominus Bootstrap4\'s requires moment.js. Moment.js must be included before Tempus Dominus Bootstrap4\'s JavaScript.');
    }
    
    var version = moment.version.split('.')
    if ((version[0] <= 2 && version[1] < 17) || (version[0] >= 3)) {
      throw new Error('Tempus Dominus Bootstrap4\'s requires at least moment.js v2.17.0 but less than v3.0.0');
    }
    
    +function () {
    
    function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
    
    function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
    
    function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
    
    // ReSharper disable once InconsistentNaming
    var DateTimePicker = function ($, moment) {
      function escapeRegExp(text) {
        return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
      }
    
      function isValidDate(date) {
        return Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime());
      }
    
      function isValidDateTimeStr(str) {
        return isValidDate(new Date(str));
      } // ReSharper disable InconsistentNaming
    
    
      var trim = function trim(str) {
        return str.replace(/(^\s+)|(\s+$)/g, '');
      },
          NAME = 'datetimepicker',
          DATA_KEY = "" + NAME,
          EVENT_KEY = "." + DATA_KEY,
          DATA_API_KEY = '.data-api',
          Selector = {
        DATA_TOGGLE: "[data-toggle=\"" + DATA_KEY + "\"]"
      },
          ClassName = {
        INPUT: NAME + "-input"
      },
          Event = {
        CHANGE: "change" + EVENT_KEY,
        BLUR: "blur" + EVENT_KEY,
        KEYUP: "keyup" + EVENT_KEY,
        KEYDOWN: "keydown" + EVENT_KEY,
        FOCUS: "focus" + EVENT_KEY,
        CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY,
        //emitted
        UPDATE: "update" + EVENT_KEY,
        ERROR: "error" + EVENT_KEY,
        HIDE: "hide" + EVENT_KEY,
        SHOW: "show" + EVENT_KEY
      },
          DatePickerModes = [{
        CLASS_NAME: 'days',
        NAV_FUNCTION: 'M',
        NAV_STEP: 1
      }, {
        CLASS_NAME: 'months',
        NAV_FUNCTION: 'y',
        NAV_STEP: 1
      }, {
        CLASS_NAME: 'years',
        NAV_FUNCTION: 'y',
        NAV_STEP: 10
      }, {
        CLASS_NAME: 'decades',
        NAV_FUNCTION: 'y',
        NAV_STEP: 100
      }],
          KeyMap = {
        'up': 38,
        38: 'up',
        'down': 40,
        40: 'down',
        'left': 37,
        37: 'left',
        'right': 39,
        39: 'right',
        'tab': 9,
        9: 'tab',
        'escape': 27,
        27: 'escape',
        'enter': 13,
        13: 'enter',
        'pageUp': 33,
        33: 'pageUp',
        'pageDown': 34,
        34: 'pageDown',
        'shift': 16,
        16: 'shift',
        'control': 17,
        17: 'control',
        'space': 32,
        32: 'space',
        't': 84,
        84: 't',
        'delete': 46,
        46: 'delete'
      },
          ViewModes = ['times', 'days', 'months', 'years', 'decades'],
          keyState = {},
          keyPressHandled = {},
          optionsSortMap = {
        timeZone: -39,
        format: -38,
        dayViewHeaderFormat: -37,
        extraFormats: -36,
        stepping: -35,
        minDate: -34,
        maxDate: -33,
        useCurrent: -32,
        collapse: -31,
        locale: -30,
        defaultDate: -29,
        disabledDates: -28,
        enabledDates: -27,
        icons: -26,
        tooltips: -25,
        useStrict: -24,
        sideBySide: -23,
        daysOfWeekDisabled: -22,
        calendarWeeks: -21,
        viewMode: -20,
        toolbarPlacement: -19,
        buttons: -18,
        widgetPositioning: -17,
        widgetParent: -16,
        ignoreReadonly: -15,
        keepOpen: -14,
        focusOnShow: -13,
        inline: -12,
        keepInvalid: -11,
        keyBinds: -10,
        debug: -9,
        allowInputToggle: -8,
        disabledTimeIntervals: -7,
        disabledHours: -6,
        enabledHours: -5,
        viewDate: -4,
        allowMultidate: -3,
        multidateSeparator: -2,
        updateOnlyThroughDateOption: -1,
        date: 1
      },
          defaultFeatherIcons = {
        time: 'clock',
        date: 'calendar',
        up: 'arrow-up',
        down: 'arrow-down',
        previous: 'arrow-left',
        next: 'arrow-right',
        today: 'arrow-down-circle',
        clear: 'trash-2',
        close: 'x'
      };
    
      function optionsSortFn(optionKeyA, optionKeyB) {
        if (optionsSortMap[optionKeyA] && optionsSortMap[optionKeyB]) {
          if (optionsSortMap[optionKeyA] < 0 && optionsSortMap[optionKeyB] < 0) {
            return Math.abs(optionsSortMap[optionKeyB]) - Math.abs(optionsSortMap[optionKeyA]);
          } else if (optionsSortMap[optionKeyA] < 0) {
            return -1;
          } else if (optionsSortMap[optionKeyB] < 0) {
            return 1;
          }
    
          return optionsSortMap[optionKeyA] - optionsSortMap[optionKeyB];
        } else if (optionsSortMap[optionKeyA]) {
          return optionsSortMap[optionKeyA];
        } else if (optionsSortMap[optionKeyB]) {
          return optionsSortMap[optionKeyB];
        }
    
        return 0;
      }
    
      var Default = {
        timeZone: '',
        format: false,
        dayViewHeaderFormat: 'MMMM YYYY',
        extraFormats: false,
        stepping: 1,
        minDate: false,
        maxDate: false,
        useCurrent: true,
        collapse: true,
        locale: moment.locale(),
        defaultDate: false,
        disabledDates: false,
        enabledDates: false,
        icons: {
          type: 'class',
          time: 'fa fa-clock-o',
          date: 'fa fa-calendar',
          up: 'fa fa-arrow-up',
          down: 'fa fa-arrow-down',
          previous: 'fa fa-chevron-left',
          next: 'fa fa-chevron-right',
          today: 'fa fa-calendar-check-o',
          clear: 'fa fa-trash',
          close: 'fa fa-times'
        },
        tooltips: {
          today: 'Go to today',
          clear: 'Clear selection',
          close: 'Close the picker',
          selectMonth: 'Select Month',
          prevMonth: 'Previous Month',
          nextMonth: 'Next Month',
          selectYear: 'Select Year',
          prevYear: 'Previous Year',
          nextYear: 'Next Year',
          selectDecade: 'Select Decade',
          prevDecade: 'Previous Decade',
          nextDecade: 'Next Decade',
          prevCentury: 'Previous Century',
          nextCentury: 'Next Century',
          pickHour: 'Pick Hour',
          incrementHour: 'Increment Hour',
          decrementHour: 'Decrement Hour',
          pickMinute: 'Pick Minute',
          incrementMinute: 'Increment Minute',
          decrementMinute: 'Decrement Minute',
          pickSecond: 'Pick Second',
          incrementSecond: 'Increment Second',
          decrementSecond: 'Decrement Second',
          togglePeriod: 'Toggle Period',
          selectTime: 'Select Time',
          selectDate: 'Select Date'
        },
        useStrict: false,
        sideBySide: false,
        daysOfWeekDisabled: false,
        calendarWeeks: false,
        viewMode: 'days',
        toolbarPlacement: 'default',
        buttons: {
          showToday: false,
          showClear: false,
          showClose: false
        },
        widgetPositioning: {
          horizontal: 'auto',
          vertical: 'auto'
        },
        widgetParent: null,
        readonly: false,
        ignoreReadonly: false,
        keepOpen: false,
        focusOnShow: true,
        inline: false,
        keepInvalid: false,
        keyBinds: {
          up: function up() {
            if (!this.widget) {
              return false;
            }
    
            var d = this._dates[0] || this.getMoment();
    
            if (this.widget.find('.datepicker').is(':visible')) {
              this.date(d.clone().subtract(7, 'd'));
            } else {
              this.date(d.clone().add(this.stepping(), 'm'));
            }
    
            return true;
          },
          down: function down() {
            if (!this.widget) {
              this.show();
              return false;
            }
    
            var d = this._dates[0] || this.getMoment();
    
            if (this.widget.find('.datepicker').is(':visible')) {
              this.date(d.clone().add(7, 'd'));
            } else {
              this.date(d.clone().subtract(this.stepping(), 'm'));
            }
    
            return true;
          },
          'control up': function controlUp() {
            if (!this.widget) {
              return false;
            }
    
            var d = this._dates[0] || this.getMoment();
    
            if (this.widget.find('.datepicker').is(':visible')) {
              this.date(d.clone().subtract(1, 'y'));
            } else {
              this.date(d.clone().add(1, 'h'));
            }
    
            return true;
          },
          'control down': function controlDown() {
            if (!this.widget) {
              return false;
            }
    
            var d = this._dates[0] || this.getMoment();
    
            if (this.widget.find('.datepicker').is(':visible')) {
              this.date(d.clone().add(1, 'y'));
            } else {
              this.date(d.clone().subtract(1, 'h'));
            }
    
            return true;
          },
          left: function left() {
            if (!this.widget) {
              return false;
            }
    
            var d = this._dates[0] || this.getMoment();
    
            if (this.widget.find('.datepicker').is(':visible')) {
              this.date(d.clone().subtract(1, 'd'));
            }
    
            return true;
          },
          right: function right() {
            if (!this.widget) {
              return false;
            }
    
            var d = this._dates[0] || this.getMoment();
    
            if (this.widget.find('.datepicker').is(':visible')) {
              this.date(d.clone().add(1, 'd'));
            }
    
            return true;
          },
          pageUp: function pageUp() {
            if (!this.widget) {
              return false;
            }
    
            var d = this._dates[0] || this.getMoment();
    
            if (this.widget.find('.datepicker').is(':visible')) {
              this.date(d.clone().subtract(1, 'M'));
            }
    
            return true;
          },
          pageDown: function pageDown() {
            if (!this.widget) {
              return false;
            }
    
            var d = this._dates[0] || this.getMoment();
    
            if (this.widget.find('.datepicker').is(':visible')) {
              this.date(d.clone().add(1, 'M'));
            }
    
            return true;
          },
          enter: function enter() {
            if (!this.widget) {
              return false;
            }
    
            this.hide();
            return true;
          },
          escape: function escape() {
            if (!this.widget) {
              return false;
            }
    
            this.hide();
            return true;
          },
          'control space': function controlSpace() {
            if (!this.widget) {
              return false;
            }
    
            if (this.widget.find('.timepicker').is(':visible')) {
              this.widget.find('.btn[data-action="togglePeriod"]').click();
            }
    
            return true;
          },
          t: function t() {
            if (!this.widget) {
              return false;
            }
    
            this.date(this.getMoment());
            return true;
          },
          'delete': function _delete() {
            if (!this.widget) {
              return false;
            }
    
            this.clear();
            return true;
          }
        },
        debug: false,
        allowInputToggle: false,
        disabledTimeIntervals: false,
        disabledHours: false,
        enabledHours: false,
        viewDate: false,
        allowMultidate: false,
        multidateSeparator: ', ',
        updateOnlyThroughDateOption: false,
        promptTimeOnDateChange: false,
        promptTimeOnDateChangeTransitionDelay: 200
      }; // ReSharper restore InconsistentNaming
      // ReSharper disable once DeclarationHides
      // ReSharper disable once InconsistentNaming
    
      var DateTimePicker = /*#__PURE__*/function () {
        /** @namespace eData.dateOptions */
    
        /** @namespace moment.tz */
        function DateTimePicker(element, options) {
          this._options = this._getOptions(options);
          this._element = element;
          this._dates = [];
          this._datesFormatted = [];
          this._viewDate = null;
          this.unset = true;
          this.component = false;
          this.widget = false;
          this.use24Hours = null;
          this.actualFormat = null;
          this.parseFormats = null;
          this.currentViewMode = null;
          this.MinViewModeNumber = 0;
          this.isInitFormatting = false;
          this.isInit = false;
          this.isDateUpdateThroughDateOptionFromClientCode = false;
          this.hasInitDate = false;
          this.initDate = void 0;
          this._notifyChangeEventContext = void 0;
          this._currentPromptTimeTimeout = null;
    
          this._int();
        }
        /**
         * @return {string}
         */
    
    
        var _proto = DateTimePicker.prototype;
    
        //private
        _proto._int = function _int() {
          this.isInit = true;
    
          var targetInput = this._element.data('target-input');
    
          if (this._element.is('input')) {
            this.input = this._element;
          } else if (targetInput !== undefined) {
            if (targetInput === 'nearest') {
              this.input = this._element.find('input');
            } else {
              this.input = $(targetInput);
            }
          }
    
          this._dates = [];
          this._dates[0] = this.getMoment();
          this._viewDate = this.getMoment().clone();
          $.extend(true, this._options, this._dataToOptions());
          this.hasInitDate = false;
          this.initDate = void 0;
          this.options(this._options);
          this.isInitFormatting = true;
    
          this._initFormatting();
    
          this.isInitFormatting = false;
    
          if (this.input !== undefined && this.input.is('input') && this.input.val().trim().length !== 0) {
            this._setValue(this._parseInputDate(this.input.val().trim()), 0);
          } else if (this._options.defaultDate && this.input !== undefined && this.input.attr('placeholder') === undefined) {
            this._setValue(this._options.defaultDate, 0);
          }
    
          if (this.hasInitDate) {
            this.date(this.initDate);
          }
    
          if (this._options.inline) {
            this.show();
          }
    
          this.isInit = false;
        };
    
        _proto._update = function _update() {
          if (!this.widget) {
            return;
          }
    
          this._fillDate();
    
          this._fillTime();
        };
    
        _proto._setValue = function _setValue(targetMoment, index) {
          var noIndex = typeof index === 'undefined',
              isClear = !targetMoment && noIndex,
              isDateUpdateThroughDateOptionFromClientCode = this.isDateUpdateThroughDateOptionFromClientCode,
              isNotAllowedProgrammaticUpdate = !this.isInit && this._options.updateOnlyThroughDateOption && !isDateUpdateThroughDateOptionFromClientCode;
          var outpValue = '',
              isInvalid = false,
              oldDate = this.unset ? null : this._dates[index];
    
          if (!oldDate && !this.unset && noIndex && isClear) {
            oldDate = this._dates[this._dates.length - 1];
          } // case of calling setValue(null or false)
    
    
          if (!targetMoment) {
            if (isNotAllowedProgrammaticUpdate) {
              this._notifyEvent({
                type: DateTimePicker.Event.CHANGE,
                date: targetMoment,
                oldDate: oldDate,
                isClear: isClear,
                isInvalid: isInvalid,
                isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
                isInit: this.isInit
              });
    
              return;
            }
    
            if (!this._options.allowMultidate || this._dates.length === 1 || isClear) {
              this.unset = true;
              this._dates = [];
              this._datesFormatted = [];
            } else {
              outpValue = "" + this._element.data('date') + this._options.multidateSeparator;
              outpValue = oldDate && outpValue.replace("" + oldDate.format(this.actualFormat) + this._options.multidateSeparator, '').replace("" + this._options.multidateSeparator + this._options.multidateSeparator, '').replace(new RegExp(escapeRegExp(this._options.multidateSeparator) + "\\s*$"), '') || '';
    
              this._dates.splice(index, 1);
    
              this._datesFormatted.splice(index, 1);
            }
    
            outpValue = trim(outpValue);
    
            if (this.input !== undefined) {
              this.input.val(outpValue);
              this.input.trigger('input');
            }
    
            this._element.data('date', outpValue);
    
            this._notifyEvent({
              type: DateTimePicker.Event.CHANGE,
              date: false,
              oldDate: oldDate,
              isClear: isClear,
              isInvalid: isInvalid,
              isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
              isInit: this.isInit
            });
    
            this._update();
    
            return;
          }
    
          targetMoment = targetMoment.clone().locale(this._options.locale);
    
          if (this._hasTimeZone()) {
            targetMoment.tz(this._options.timeZone);
          }
    
          if (this._options.stepping !== 1) {
            targetMoment.minutes(Math.round(targetMoment.minutes() / this._options.stepping) * this._options.stepping).seconds(0);
          }
    
          if (this._isValid(targetMoment)) {
            if (isNotAllowedProgrammaticUpdate) {
              this._notifyEvent({
                type: DateTimePicker.Event.CHANGE,
                date: targetMoment.clone(),
                oldDate: oldDate,
                isClear: isClear,
                isInvalid: isInvalid,
                isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
                isInit: this.isInit
              });
    
              return;
            }
    
            this._dates[index] = targetMoment;
            this._datesFormatted[index] = targetMoment.format('YYYY-MM-DD');
            this._viewDate = targetMoment.clone();
    
            if (this._options.allowMultidate && this._dates.length > 1) {
              for (var i = 0; i < this._dates.length; i++) {
                outpValue += "" + this._dates[i].format(this.actualFormat) + this._options.multidateSeparator;
              }
    
              outpValue = outpValue.replace(new RegExp(this._options.multidateSeparator + "\\s*$"), '');
            } else {
              outpValue = this._dates[index].format(this.actualFormat);
            }
    
            outpValue = trim(outpValue);
    
            if (this.input !== undefined) {
              this.input.val(outpValue);
              this.input.trigger('input');
            }
    
            this._element.data('date', outpValue);
    
            this.unset = false;
    
            this._update();
    
            this._notifyEvent({
              type: DateTimePicker.Event.CHANGE,
              date: this._dates[index].clone(),
              oldDate: oldDate,
              isClear: isClear,
              isInvalid: isInvalid,
              isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
              isInit: this.isInit
            });
          } else {
            isInvalid = true;
    
            if (!this._options.keepInvalid) {
              if (this.input !== undefined) {
                this.input.val("" + (this.unset ? '' : this._dates[index].format(this.actualFormat)));
                this.input.trigger('input');
              }
            } else {
              this._notifyEvent({
                type: DateTimePicker.Event.CHANGE,
                date: targetMoment,
                oldDate: oldDate,
                isClear: isClear,
                isInvalid: isInvalid,
                isDateUpdateThroughDateOptionFromClientCode: isDateUpdateThroughDateOptionFromClientCode,
                isInit: this.isInit
              });
            }
    
            this._notifyEvent({
              type: DateTimePicker.Event.ERROR,
              date: targetMoment,
              oldDate: oldDate
            });
          }
        };
    
        _proto._change = function _change(e) {
          var val = $(e.target).val().trim(),
              parsedDate = val ? this._parseInputDate(val) : null;
    
          this._setValue(parsedDate, 0);
    
          e.stopImmediatePropagation();
          return false;
        } //noinspection JSMethodCanBeStatic
        ;
    
        _proto._getOptions = function _getOptions(options) {
          options = $.extend(true, {}, Default, options && options.icons && options.icons.type === 'feather' ? {
            icons: defaultFeatherIcons
          } : {}, options);
          return options;
        };
    
        _proto._hasTimeZone = function _hasTimeZone() {
          return moment.tz !== undefined && this._options.timeZone !== undefined && this._options.timeZone !== null && this._options.timeZone !== '';
        };
    
        _proto._isEnabled = function _isEnabled(granularity) {
          if (typeof granularity !== 'string' || granularity.length > 1) {
            throw new TypeError('isEnabled expects a single character string parameter');
          }
    
          switch (granularity) {
            case 'y':
              return this.actualFormat.indexOf('Y') !== -1;
    
            case 'M':
              return this.actualFormat.indexOf('M') !== -1;
    
            case 'd':
              return this.actualFormat.toLowerCase().indexOf('d') !== -1;
    
            case 'h':
            case 'H':
              return this.actualFormat.toLowerCase().indexOf('h') !== -1;
    
            case 'm':
              return this.actualFormat.indexOf('m') !== -1;
    
            case 's':
              return this.actualFormat.indexOf('s') !== -1;
    
            case 'a':
            case 'A':
              return this.actualFormat.toLowerCase().indexOf('a') !== -1;
    
            default:
              return false;
          }
        };
    
        _proto._hasTime = function _hasTime() {
          return this._isEnabled('h') || this._isEnabled('m') || this._isEnabled('s');
        };
    
        _proto._hasDate = function _hasDate() {
          return this._isEnabled('y') || this._isEnabled('M') || this._isEnabled('d');
        };
    
        _proto._dataToOptions = function _dataToOptions() {
          var eData = this._element.data();
    
          var dataOptions = {};
    
          if (eData.dateOptions && eData.dateOptions instanceof Object) {
            dataOptions = $.extend(true, dataOptions, eData.dateOptions);
          }
    
          $.each(this._options, function (key) {
            var attributeName = "date" + key.charAt(0).toUpperCase() + key.slice(1); //todo data api key
    
            if (eData[attributeName] !== undefined) {
              dataOptions[key] = eData[attributeName];
            } else {
              delete dataOptions[key];
            }
          });
          return dataOptions;
        };
    
        _proto._format = function _format() {
          return this._options.format || 'YYYY-MM-DD HH:mm';
        };
    
        _proto._areSameDates = function _areSameDates(a, b) {
          var format = this._format();
    
          return a && b && (a.isSame(b) || moment(a.format(format), format).isSame(moment(b.format(format), format)));
        };
    
        _proto._notifyEvent = function _notifyEvent(e) {
          if (e.type === DateTimePicker.Event.CHANGE) {
            this._notifyChangeEventContext = this._notifyChangeEventContext || 0;
            this._notifyChangeEventContext++;
    
            if (e.date && this._areSameDates(e.date, e.oldDate) || !e.isClear && !e.date && !e.oldDate || this._notifyChangeEventContext > 1) {
              this._notifyChangeEventContext = void 0;
              return;
            }
    
            this._handlePromptTimeIfNeeded(e);
          }
    
          this._element.trigger(e);
    
          this._notifyChangeEventContext = void 0;
        };
    
        _proto._handlePromptTimeIfNeeded = function _handlePromptTimeIfNeeded(e) {
          if (this._options.promptTimeOnDateChange) {
            if (!e.oldDate && this._options.useCurrent) {
              // First time ever. If useCurrent option is set to true (default), do nothing
              // because the first date is selected automatically.
              return;
            } else if (e.oldDate && e.date && (e.oldDate.format('YYYY-MM-DD') === e.date.format('YYYY-MM-DD') || e.oldDate.format('YYYY-MM-DD') !== e.date.format('YYYY-MM-DD') && e.oldDate.format('HH:mm:ss') !== e.date.format('HH:mm:ss'))) {
              // Date didn't change (time did) or date changed because time did.
              return;
            }
    
            var that = this;
            clearTimeout(this._currentPromptTimeTimeout);
            this._currentPromptTimeTimeout = setTimeout(function () {
              if (that.widget) {
                that.widget.find('[data-action="togglePicker"]').click();
              }
            }, this._options.promptTimeOnDateChangeTransitionDelay);
          }
        };
    
        _proto._viewUpdate = function _viewUpdate(e) {
          if (e === 'y') {
            e = 'YYYY';
          }
    
          this._notifyEvent({
            type: DateTimePicker.Event.UPDATE,
            change: e,
            viewDate: this._viewDate.clone()
          });
        };
    
        _proto._showMode = function _showMode(dir) {
          if (!this.widget) {
            return;
          }
    
          if (dir) {
            this.currentViewMode = Math.max(this.MinViewModeNumber, Math.min(3, this.currentViewMode + dir));
          }
    
          this.widget.find('.datepicker > div').hide().filter(".datepicker-" + DatePickerModes[this.currentViewMode].CLASS_NAME).show();
        };
    
        _proto._isInDisabledDates = function _isInDisabledDates(testDate) {
          return this._options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
        };
    
        _proto._isInEnabledDates = function _isInEnabledDates(testDate) {
          return this._options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
        };
    
        _proto._isInDisabledHours = function _isInDisabledHours(testDate) {
          return this._options.disabledHours[testDate.format('H')] === true;
        };
    
        _proto._isInEnabledHours = function _isInEnabledHours(testDate) {
          return this._options.enabledHours[testDate.format('H')] === true;
        };
    
        _proto._isValid = function _isValid(targetMoment, granularity) {
          if (!targetMoment || !targetMoment.isValid()) {
            return false;
          }
    
          if (this._options.disabledDates && granularity === 'd' && this._isInDisabledDates(targetMoment)) {
            return false;
          }
    
          if (this._options.enabledDates && granularity === 'd' && !this._isInEnabledDates(targetMoment)) {
            return false;
          }
    
          if (this._options.minDate && targetMoment.isBefore(this._options.minDate, granularity)) {
            return false;
          }
    
          if (this._options.maxDate && targetMoment.isAfter(this._options.maxDate, granularity)) {
            return false;
          }
    
          if (this._options.daysOfWeekDisabled && granularity === 'd' && this._options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
            return false;
          }
    
          if (this._options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && this._isInDisabledHours(targetMoment)) {
            return false;
          }
    
          if (this._options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !this._isInEnabledHours(targetMoment)) {
            return false;
          }
    
          if (this._options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
            var found = false;
            $.each(this._options.disabledTimeIntervals, function () {
              if (targetMoment.isBetween(this[0], this[1])) {
                found = true;
                return false;
              }
            });
    
            if (found) {
              return false;
            }
          }
    
          return true;
        };
    
        _proto._parseInputDate = function _parseInputDate(inputDate, _temp) {
          var _ref = _temp === void 0 ? {} : _temp,
              _ref$isPickerShow = _ref.isPickerShow,
              isPickerShow = _ref$isPickerShow === void 0 ? false : _ref$isPickerShow;
    
          if (this._options.parseInputDate === undefined || isPickerShow) {
            if (!moment.isMoment(inputDate)) {
              inputDate = this.getMoment(inputDate);
            }
          } else {
            inputDate = this._options.parseInputDate(inputDate);
          } //inputDate.locale(this.options.locale);
    
    
          return inputDate;
        };
    
        _proto._keydown = function _keydown(e) {
          var handler = null,
              index,
              index2,
              keyBindKeys,
              allModifiersPressed;
          var pressedKeys = [],
              pressedModifiers = {},
              currentKey = e.which,
              pressed = 'p';
          keyState[currentKey] = pressed;
    
          for (index in keyState) {
            if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
              pressedKeys.push(index);
    
              if (parseInt(index, 10) !== currentKey) {
                pressedModifiers[index] = true;
              }
            }
          }
    
          for (index in this._options.keyBinds) {
            if (this._options.keyBinds.hasOwnProperty(index) && typeof this._options.keyBinds[index] === 'function') {
              keyBindKeys = index.split(' ');
    
              if (keyBindKeys.length === pressedKeys.length && KeyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
                allModifiersPressed = true;
    
                for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
                  if (!(KeyMap[keyBindKeys[index2]] in pressedModifiers)) {
                    allModifiersPressed = false;
                    break;
                  }
                }
    
                if (allModifiersPressed) {
                  handler = this._options.keyBinds[index];
                  break;
                }
              }
            }
          }
    
          if (handler) {
            if (handler.call(this)) {
              e.stopPropagation();
              e.preventDefault();
            }
          }
        } //noinspection JSMethodCanBeStatic,SpellCheckingInspection
        ;
    
        _proto._keyup = function _keyup(e) {
          keyState[e.which] = 'r';
    
          if (keyPressHandled[e.which]) {
            keyPressHandled[e.which] = false;
            e.stopPropagation();
            e.preventDefault();
          }
        };
    
        _proto._indexGivenDates = function _indexGivenDates(givenDatesArray) {
          // Store given enabledDates and disabledDates as keys.
          // This way we can check their existence in O(1) time instead of looping through whole array.
          // (for example: options.enabledDates['2014-02-27'] === true)
          var givenDatesIndexed = {},
              self = this;
          $.each(givenDatesArray, function () {
            var dDate = self._parseInputDate(this);
    
            if (dDate.isValid()) {
              givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
            }
          });
          return Object.keys(givenDatesIndexed).length ? givenDatesIndexed : false;
        };
    
        _proto._indexGivenHours = function _indexGivenHours(givenHoursArray) {
          // Store given enabledHours and disabledHours as keys.
          // This way we can check their existence in O(1) time instead of looping through whole array.
          // (for example: options.enabledHours['2014-02-27'] === true)
          var givenHoursIndexed = {};
          $.each(givenHoursArray, function () {
            givenHoursIndexed[this] = true;
          });
          return Object.keys(givenHoursIndexed).length ? givenHoursIndexed : false;
        };
    
        _proto._initFormatting = function _initFormatting() {
          var format = this._options.format || 'L LT',
              self = this;
          this.actualFormat = format.replace(/(\[[^\[]*])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
            return (self.isInitFormatting && self._options.date === null ? self.getMoment() : self._dates[0]).localeData().longDateFormat(formatInput) || formatInput; //todo taking the first date should be ok
          });
          this.parseFormats = this._options.extraFormats ? this._options.extraFormats.slice() : [];
    
          if (this.parseFormats.indexOf(format) < 0 && this.parseFormats.indexOf(this.actualFormat) < 0) {
            this.parseFormats.push(this.actualFormat);
          }
    
          this.use24Hours = this.actualFormat.toLowerCase().indexOf('a') < 1 && this.actualFormat.replace(/\[.*?]/g, '').indexOf('h') < 1;
    
          if (this._isEnabled('y')) {
            this.MinViewModeNumber = 2;
          }
    
          if (this._isEnabled('M')) {
            this.MinViewModeNumber = 1;
          }
    
          if (this._isEnabled('d')) {
            this.MinViewModeNumber = 0;
          }
    
          this.currentViewMode = Math.max(this.MinViewModeNumber, this.currentViewMode);
    
          if (!this.unset) {
            this._setValue(this._dates[0], 0);
          }
        };
    
        _proto._getLastPickedDate = function _getLastPickedDate() {
          var lastPickedDate = this._dates[this._getLastPickedDateIndex()];
    
          if (!lastPickedDate && this._options.allowMultidate) {
            lastPickedDate = moment(new Date());
          }
    
          return lastPickedDate;
        };
    
        _proto._getLastPickedDateIndex = function _getLastPickedDateIndex() {
          return this._dates.length - 1;
        } //public
        ;
    
        _proto.getMoment = function getMoment(d) {
          var returnMoment;
    
          if (d === undefined || d === null) {
            // TODO: Should this use format?
            returnMoment = moment().clone().locale(this._options.locale);
          } else if (this._hasTimeZone()) {
            // There is a string to parse and a default time zone
            // parse with the tz function which takes a default time zone if it is not in the format string
            returnMoment = moment.tz(d, this.parseFormats, this._options.locale, this._options.useStrict, this._options.timeZone);
          } else {
            returnMoment = moment(d, this.parseFormats, this._options.locale, this._options.useStrict);
          }
    
          if (this._hasTimeZone()) {
            returnMoment.tz(this._options.timeZone);
          }
    
          return returnMoment;
        };
    
        _proto.toggle = function toggle() {
          return this.widget ? this.hide() : this.show();
        };
    
        _proto.readonly = function readonly(_readonly) {
          if (arguments.length === 0) {
            return this._options.readonly;
          }
    
          if (typeof _readonly !== 'boolean') {
            throw new TypeError('readonly() expects a boolean parameter');
          }
    
          this._options.readonly = _readonly;
    
          if (this.input !== undefined) {
            this.input.prop('readonly', this._options.readonly);
          }
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto.ignoreReadonly = function ignoreReadonly(_ignoreReadonly) {
          if (arguments.length === 0) {
            return this._options.ignoreReadonly;
          }
    
          if (typeof _ignoreReadonly !== 'boolean') {
            throw new TypeError('ignoreReadonly() expects a boolean parameter');
          }
    
          this._options.ignoreReadonly = _ignoreReadonly;
        };
    
        _proto.options = function options(newOptions) {
          if (arguments.length === 0) {
            return $.extend(true, {}, this._options);
          }
    
          if (!(newOptions instanceof Object)) {
            throw new TypeError('options() this.options parameter should be an object');
          }
    
          $.extend(true, this._options, newOptions);
          var self = this,
              optionsKeys = Object.keys(this._options).sort(optionsSortFn);
          $.each(optionsKeys, function (i, key) {
            var value = self._options[key];
    
            if (self[key] !== undefined) {
              if (self.isInit && key === 'date') {
                self.hasInitDate = true;
                self.initDate = value;
                return;
              }
    
              self[key](value);
            }
          });
        };
    
        _proto.date = function date(newDate, index) {
          index = index || 0;
    
          if (arguments.length === 0) {
            if (this.unset) {
              return null;
            }
    
            if (this._options.allowMultidate) {
              return this._dates.join(this._options.multidateSeparator);
            } else {
              return this._dates[index].clone();
            }
          }
    
          if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
            throw new TypeError('date() parameter must be one of [null, string, moment or Date]');
          }
    
          if (typeof newDate === 'string' && isValidDateTimeStr(newDate)) {
            newDate = new Date(newDate);
          }
    
          this._setValue(newDate === null ? null : this._parseInputDate(newDate), index);
        };
    
        _proto.updateOnlyThroughDateOption = function updateOnlyThroughDateOption(_updateOnlyThroughDateOption) {
          if (typeof _updateOnlyThroughDateOption !== 'boolean') {
            throw new TypeError('updateOnlyThroughDateOption() expects a boolean parameter');
          }
    
          this._options.updateOnlyThroughDateOption = _updateOnlyThroughDateOption;
        };
    
        _proto.format = function format(newFormat) {
          if (arguments.length === 0) {
            return this._options.format;
          }
    
          if (typeof newFormat !== 'string' && (typeof newFormat !== 'boolean' || newFormat !== false)) {
            throw new TypeError("format() expects a string or boolean:false parameter " + newFormat);
          }
    
          this._options.format = newFormat;
    
          if (this.actualFormat) {
            this._initFormatting(); // reinitialize formatting
    
          }
        };
    
        _proto.timeZone = function timeZone(newZone) {
          if (arguments.length === 0) {
            return this._options.timeZone;
          }
    
          if (typeof newZone !== 'string') {
            throw new TypeError('newZone() expects a string parameter');
          }
    
          this._options.timeZone = newZone;
        };
    
        _proto.dayViewHeaderFormat = function dayViewHeaderFormat(newFormat) {
          if (arguments.length === 0) {
            return this._options.dayViewHeaderFormat;
          }
    
          if (typeof newFormat !== 'string') {
            throw new TypeError('dayViewHeaderFormat() expects a string parameter');
          }
    
          this._options.dayViewHeaderFormat = newFormat;
        };
    
        _proto.extraFormats = function extraFormats(formats) {
          if (arguments.length === 0) {
            return this._options.extraFormats;
          }
    
          if (formats !== false && !(formats instanceof Array)) {
            throw new TypeError('extraFormats() expects an array or false parameter');
          }
    
          this._options.extraFormats = formats;
    
          if (this.parseFormats) {
            this._initFormatting(); // reinit formatting
    
          }
        };
    
        _proto.disabledDates = function disabledDates(dates) {
          if (arguments.length === 0) {
            return this._options.disabledDates ? $.extend({}, this._options.disabledDates) : this._options.disabledDates;
          }
    
          if (!dates) {
            this._options.disabledDates = false;
    
            this._update();
    
            return true;
          }
    
          if (!(dates instanceof Array)) {
            throw new TypeError('disabledDates() expects an array parameter');
          }
    
          this._options.disabledDates = this._indexGivenDates(dates);
          this._options.enabledDates = false;
    
          this._update();
        };
    
        _proto.enabledDates = function enabledDates(dates) {
          if (arguments.length === 0) {
            return this._options.enabledDates ? $.extend({}, this._options.enabledDates) : this._options.enabledDates;
          }
    
          if (!dates) {
            this._options.enabledDates = false;
    
            this._update();
    
            return true;
          }
    
          if (!(dates instanceof Array)) {
            throw new TypeError('enabledDates() expects an array parameter');
          }
    
          this._options.enabledDates = this._indexGivenDates(dates);
          this._options.disabledDates = false;
    
          this._update();
        };
    
        _proto.daysOfWeekDisabled = function daysOfWeekDisabled(_daysOfWeekDisabled) {
          if (arguments.length === 0) {
            return this._options.daysOfWeekDisabled.splice(0);
          }
    
          if (typeof _daysOfWeekDisabled === 'boolean' && !_daysOfWeekDisabled) {
            this._options.daysOfWeekDisabled = false;
    
            this._update();
    
            return true;
          }
    
          if (!(_daysOfWeekDisabled instanceof Array)) {
            throw new TypeError('daysOfWeekDisabled() expects an array parameter');
          }
    
          this._options.daysOfWeekDisabled = _daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
            currentValue = parseInt(currentValue, 10);
    
            if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {
              return previousValue;
            }
    
            if (previousValue.indexOf(currentValue) === -1) {
              previousValue.push(currentValue);
            }
    
            return previousValue;
          }, []).sort();
    
          if (this._options.useCurrent && !this._options.keepInvalid) {
            for (var i = 0; i < this._dates.length; i++) {
              var tries = 0;
    
              while (!this._isValid(this._dates[i], 'd')) {
                this._dates[i].add(1, 'd');
    
                if (tries === 31) {
                  throw 'Tried 31 times to find a valid date';
                }
    
                tries++;
              }
    
              this._setValue(this._dates[i], i);
            }
          }
    
          this._update();
        };
    
        _proto.maxDate = function maxDate(_maxDate) {
          if (arguments.length === 0) {
            return this._options.maxDate ? this._options.maxDate.clone() : this._options.maxDate;
          }
    
          if (typeof _maxDate === 'boolean' && _maxDate === false) {
            this._options.maxDate = false;
    
            this._update();
    
            return true;
          }
    
          if (typeof _maxDate === 'string') {
            if (_maxDate === 'now' || _maxDate === 'moment') {
              _maxDate = this.getMoment();
            }
          }
    
          var parsedDate = this._parseInputDate(_maxDate);
    
          if (!parsedDate.isValid()) {
            throw new TypeError("maxDate() Could not parse date parameter: " + _maxDate);
          }
    
          if (this._options.minDate && parsedDate.isBefore(this._options.minDate)) {
            throw new TypeError("maxDate() date parameter is before this.options.minDate: " + parsedDate.format(this.actualFormat));
          }
    
          this._options.maxDate = parsedDate;
    
          for (var i = 0; i < this._dates.length; i++) {
            if (this._options.useCurrent && !this._options.keepInvalid && this._dates[i].isAfter(_maxDate)) {
              this._setValue(this._options.maxDate, i);
            }
          }
    
          if (this._viewDate.isAfter(parsedDate)) {
            this._viewDate = parsedDate.clone().subtract(this._options.stepping, 'm');
          }
    
          this._update();
        };
    
        _proto.minDate = function minDate(_minDate) {
          if (arguments.length === 0) {
            return this._options.minDate ? this._options.minDate.clone() : this._options.minDate;
          }
    
          if (typeof _minDate === 'boolean' && _minDate === false) {
            this._options.minDate = false;
    
            this._update();
    
            return true;
          }
    
          if (typeof _minDate === 'string') {
            if (_minDate === 'now' || _minDate === 'moment') {
              _minDate = this.getMoment();
            }
          }
    
          var parsedDate = this._parseInputDate(_minDate);
    
          if (!parsedDate.isValid()) {
            throw new TypeError("minDate() Could not parse date parameter: " + _minDate);
          }
    
          if (this._options.maxDate && parsedDate.isAfter(this._options.maxDate)) {
            throw new TypeError("minDate() date parameter is after this.options.maxDate: " + parsedDate.format(this.actualFormat));
          }
    
          this._options.minDate = parsedDate;
    
          for (var i = 0; i < this._dates.length; i++) {
            if (this._options.useCurrent && !this._options.keepInvalid && this._dates[i].isBefore(_minDate)) {
              this._setValue(this._options.minDate, i);
            }
          }
    
          if (this._viewDate.isBefore(parsedDate)) {
            this._viewDate = parsedDate.clone().add(this._options.stepping, 'm');
          }
    
          this._update();
        };
    
        _proto.defaultDate = function defaultDate(_defaultDate) {
          if (arguments.length === 0) {
            return this._options.defaultDate ? this._options.defaultDate.clone() : this._options.defaultDate;
          }
    
          if (!_defaultDate) {
            this._options.defaultDate = false;
            return true;
          }
    
          if (typeof _defaultDate === 'string') {
            if (_defaultDate === 'now' || _defaultDate === 'moment') {
              _defaultDate = this.getMoment();
            } else {
              _defaultDate = this.getMoment(_defaultDate);
            }
          }
    
          var parsedDate = this._parseInputDate(_defaultDate);
    
          if (!parsedDate.isValid()) {
            throw new TypeError("defaultDate() Could not parse date parameter: " + _defaultDate);
          }
    
          if (!this._isValid(parsedDate)) {
            throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
          }
    
          this._options.defaultDate = parsedDate;
    
          if (this._options.defaultDate && this._options.inline || this.input !== undefined && this.input.val().trim() === '') {
            this._setValue(this._options.defaultDate, 0);
          }
        };
    
        _proto.locale = function locale(_locale) {
          if (arguments.length === 0) {
            return this._options.locale;
          }
    
          if (!moment.localeData(_locale)) {
            throw new TypeError("locale() locale " + _locale + " is not loaded from moment locales!");
          }
    
          this._options.locale = _locale;
    
          for (var i = 0; i < this._dates.length; i++) {
            this._dates[i].locale(this._options.locale);
          }
    
          this._viewDate.locale(this._options.locale);
    
          if (this.actualFormat) {
            this._initFormatting(); // reinitialize formatting
    
          }
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto.stepping = function stepping(_stepping) {
          if (arguments.length === 0) {
            return this._options.stepping;
          }
    
          _stepping = parseInt(_stepping, 10);
    
          if (isNaN(_stepping) || _stepping < 1) {
            _stepping = 1;
          }
    
          this._options.stepping = _stepping;
        };
    
        _proto.useCurrent = function useCurrent(_useCurrent) {
          var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];
    
          if (arguments.length === 0) {
            return this._options.useCurrent;
          }
    
          if (typeof _useCurrent !== 'boolean' && typeof _useCurrent !== 'string') {
            throw new TypeError('useCurrent() expects a boolean or string parameter');
          }
    
          if (typeof _useCurrent === 'string' && useCurrentOptions.indexOf(_useCurrent.toLowerCase()) === -1) {
            throw new TypeError("useCurrent() expects a string parameter of " + useCurrentOptions.join(', '));
          }
    
          this._options.useCurrent = _useCurrent;
        };
    
        _proto.collapse = function collapse(_collapse) {
          if (arguments.length === 0) {
            return this._options.collapse;
          }
    
          if (typeof _collapse !== 'boolean') {
            throw new TypeError('collapse() expects a boolean parameter');
          }
    
          if (this._options.collapse === _collapse) {
            return true;
          }
    
          this._options.collapse = _collapse;
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto.icons = function icons(_icons) {
          if (arguments.length === 0) {
            return $.extend({}, this._options.icons);
          }
    
          if (!(_icons instanceof Object)) {
            throw new TypeError('icons() expects parameter to be an Object');
          }
    
          $.extend(this._options.icons, _icons);
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto.tooltips = function tooltips(_tooltips) {
          if (arguments.length === 0) {
            return $.extend({}, this._options.tooltips);
          }
    
          if (!(_tooltips instanceof Object)) {
            throw new TypeError('tooltips() expects parameter to be an Object');
          }
    
          $.extend(this._options.tooltips, _tooltips);
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto.useStrict = function useStrict(_useStrict) {
          if (arguments.length === 0) {
            return this._options.useStrict;
          }
    
          if (typeof _useStrict !== 'boolean') {
            throw new TypeError('useStrict() expects a boolean parameter');
          }
    
          this._options.useStrict = _useStrict;
        };
    
        _proto.sideBySide = function sideBySide(_sideBySide) {
          if (arguments.length === 0) {
            return this._options.sideBySide;
          }
    
          if (typeof _sideBySide !== 'boolean') {
            throw new TypeError('sideBySide() expects a boolean parameter');
          }
    
          this._options.sideBySide = _sideBySide;
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto.viewMode = function viewMode(_viewMode) {
          if (arguments.length === 0) {
            return this._options.viewMode;
          }
    
          if (typeof _viewMode !== 'string') {
            throw new TypeError('viewMode() expects a string parameter');
          }
    
          if (DateTimePicker.ViewModes.indexOf(_viewMode) === -1) {
            throw new TypeError("viewMode() parameter must be one of (" + DateTimePicker.ViewModes.join(', ') + ") value");
          }
    
          this._options.viewMode = _viewMode;
          this.currentViewMode = Math.max(DateTimePicker.ViewModes.indexOf(_viewMode) - 1, this.MinViewModeNumber);
    
          this._showMode();
        };
    
        _proto.calendarWeeks = function calendarWeeks(_calendarWeeks) {
          if (arguments.length === 0) {
            return this._options.calendarWeeks;
          }
    
          if (typeof _calendarWeeks !== 'boolean') {
            throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
          }
    
          this._options.calendarWeeks = _calendarWeeks;
    
          this._update();
        };
    
        _proto.buttons = function buttons(_buttons) {
          if (arguments.length === 0) {
            return $.extend({}, this._options.buttons);
          }
    
          if (!(_buttons instanceof Object)) {
            throw new TypeError('buttons() expects parameter to be an Object');
          }
    
          $.extend(this._options.buttons, _buttons);
    
          if (typeof this._options.buttons.showToday !== 'boolean') {
            throw new TypeError('buttons.showToday expects a boolean parameter');
          }
    
          if (typeof this._options.buttons.showClear !== 'boolean') {
            throw new TypeError('buttons.showClear expects a boolean parameter');
          }
    
          if (typeof this._options.buttons.showClose !== 'boolean') {
            throw new TypeError('buttons.showClose expects a boolean parameter');
          }
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto.keepOpen = function keepOpen(_keepOpen) {
          if (arguments.length === 0) {
            return this._options.keepOpen;
          }
    
          if (typeof _keepOpen !== 'boolean') {
            throw new TypeError('keepOpen() expects a boolean parameter');
          }
    
          this._options.keepOpen = _keepOpen;
        };
    
        _proto.focusOnShow = function focusOnShow(_focusOnShow) {
          if (arguments.length === 0) {
            return this._options.focusOnShow;
          }
    
          if (typeof _focusOnShow !== 'boolean') {
            throw new TypeError('focusOnShow() expects a boolean parameter');
          }
    
          this._options.focusOnShow = _focusOnShow;
        };
    
        _proto.inline = function inline(_inline) {
          if (arguments.length === 0) {
            return this._options.inline;
          }
    
          if (typeof _inline !== 'boolean') {
            throw new TypeError('inline() expects a boolean parameter');
          }
    
          this._options.inline = _inline;
        };
    
        _proto.clear = function clear() {
          this._setValue(null); //todo
    
        };
    
        _proto.keyBinds = function keyBinds(_keyBinds) {
          if (arguments.length === 0) {
            return this._options.keyBinds;
          }
    
          this._options.keyBinds = _keyBinds;
        };
    
        _proto.debug = function debug(_debug) {
          if (typeof _debug !== 'boolean') {
            throw new TypeError('debug() expects a boolean parameter');
          }
    
          this._options.debug = _debug;
        };
    
        _proto.allowInputToggle = function allowInputToggle(_allowInputToggle) {
          if (arguments.length === 0) {
            return this._options.allowInputToggle;
          }
    
          if (typeof _allowInputToggle !== 'boolean') {
            throw new TypeError('allowInputToggle() expects a boolean parameter');
          }
    
          this._options.allowInputToggle = _allowInputToggle;
        };
    
        _proto.keepInvalid = function keepInvalid(_keepInvalid) {
          if (arguments.length === 0) {
            return this._options.keepInvalid;
          }
    
          if (typeof _keepInvalid !== 'boolean') {
            throw new TypeError('keepInvalid() expects a boolean parameter');
          }
    
          this._options.keepInvalid = _keepInvalid;
        };
    
        _proto.datepickerInput = function datepickerInput(_datepickerInput) {
          if (arguments.length === 0) {
            return this._options.datepickerInput;
          }
    
          if (typeof _datepickerInput !== 'string') {
            throw new TypeError('datepickerInput() expects a string parameter');
          }
    
          this._options.datepickerInput = _datepickerInput;
        };
    
        _proto.parseInputDate = function parseInputDate(_parseInputDate2) {
          if (arguments.length === 0) {
            return this._options.parseInputDate;
          }
    
          if (typeof _parseInputDate2 !== 'function') {
            throw new TypeError('parseInputDate() should be as function');
          }
    
          this._options.parseInputDate = _parseInputDate2;
        };
    
        _proto.disabledTimeIntervals = function disabledTimeIntervals(_disabledTimeIntervals) {
          if (arguments.length === 0) {
            return this._options.disabledTimeIntervals ? $.extend({}, this._options.disabledTimeIntervals) : this._options.disabledTimeIntervals;
          }
    
          if (!_disabledTimeIntervals) {
            this._options.disabledTimeIntervals = false;
    
            this._update();
    
            return true;
          }
    
          if (!(_disabledTimeIntervals instanceof Array)) {
            throw new TypeError('disabledTimeIntervals() expects an array parameter');
          }
    
          this._options.disabledTimeIntervals = _disabledTimeIntervals;
    
          this._update();
        };
    
        _proto.disabledHours = function disabledHours(hours) {
          if (arguments.length === 0) {
            return this._options.disabledHours ? $.extend({}, this._options.disabledHours) : this._options.disabledHours;
          }
    
          if (!hours) {
            this._options.disabledHours = false;
    
            this._update();
    
            return true;
          }
    
          if (!(hours instanceof Array)) {
            throw new TypeError('disabledHours() expects an array parameter');
          }
    
          this._options.disabledHours = this._indexGivenHours(hours);
          this._options.enabledHours = false;
    
          if (this._options.useCurrent && !this._options.keepInvalid) {
            for (var i = 0; i < this._dates.length; i++) {
              var tries = 0;
    
              while (!this._isValid(this._dates[i], 'h')) {
                this._dates[i].add(1, 'h');
    
                if (tries === 24) {
                  throw 'Tried 24 times to find a valid date';
                }
    
                tries++;
              }
    
              this._setValue(this._dates[i], i);
            }
          }
    
          this._update();
        };
    
        _proto.enabledHours = function enabledHours(hours) {
          if (arguments.length === 0) {
            return this._options.enabledHours ? $.extend({}, this._options.enabledHours) : this._options.enabledHours;
          }
    
          if (!hours) {
            this._options.enabledHours = false;
    
            this._update();
    
            return true;
          }
    
          if (!(hours instanceof Array)) {
            throw new TypeError('enabledHours() expects an array parameter');
          }
    
          this._options.enabledHours = this._indexGivenHours(hours);
          this._options.disabledHours = false;
    
          if (this._options.useCurrent && !this._options.keepInvalid) {
            for (var i = 0; i < this._dates.length; i++) {
              var tries = 0;
    
              while (!this._isValid(this._dates[i], 'h')) {
                this._dates[i].add(1, 'h');
    
                if (tries === 24) {
                  throw 'Tried 24 times to find a valid date';
                }
    
                tries++;
              }
    
              this._setValue(this._dates[i], i);
            }
          }
    
          this._update();
        };
    
        _proto.viewDate = function viewDate(newDate) {
          if (arguments.length === 0) {
            return this._viewDate.clone();
          }
    
          if (!newDate) {
            this._viewDate = (this._dates[0] || this.getMoment()).clone();
            return true;
          }
    
          if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
            throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
          }
    
          this._viewDate = this._parseInputDate(newDate);
    
          this._update();
    
          this._viewUpdate(DatePickerModes[this.currentViewMode] && DatePickerModes[this.currentViewMode].NAV_FUNCTION);
        };
    
        _proto._fillDate = function _fillDate() {};
    
        _proto._useFeatherIcons = function _useFeatherIcons() {
          return this._options.icons.type === 'feather';
        };
    
        _proto.allowMultidate = function allowMultidate(_allowMultidate) {
          if (typeof _allowMultidate !== 'boolean') {
            throw new TypeError('allowMultidate() expects a boolean parameter');
          }
    
          this._options.allowMultidate = _allowMultidate;
        };
    
        _proto.multidateSeparator = function multidateSeparator(_multidateSeparator) {
          if (arguments.length === 0) {
            return this._options.multidateSeparator;
          }
    
          if (typeof _multidateSeparator !== 'string') {
            throw new TypeError('multidateSeparator expects a string parameter');
          }
    
          this._options.multidateSeparator = _multidateSeparator;
        };
    
        _createClass(DateTimePicker, null, [{
          key: "NAME",
          get: function get() {
            return NAME;
          }
          /**
           * @return {string}
           */
    
        }, {
          key: "DATA_KEY",
          get: function get() {
            return DATA_KEY;
          }
          /**
           * @return {string}
           */
    
        }, {
          key: "EVENT_KEY",
          get: function get() {
            return EVENT_KEY;
          }
          /**
           * @return {string}
           */
    
        }, {
          key: "DATA_API_KEY",
          get: function get() {
            return DATA_API_KEY;
          }
        }, {
          key: "DatePickerModes",
          get: function get() {
            return DatePickerModes;
          }
        }, {
          key: "ViewModes",
          get: function get() {
            return ViewModes;
          }
        }, {
          key: "Event",
          get: function get() {
            return Event;
          }
        }, {
          key: "Selector",
          get: function get() {
            return Selector;
          }
        }, {
          key: "Default",
          get: function get() {
            return Default;
          },
          set: function set(value) {
            Default = value;
          }
        }, {
          key: "ClassName",
          get: function get() {
            return ClassName;
          }
        }]);
    
        return DateTimePicker;
      }();
    
      return DateTimePicker;
    }(jQuery, moment); //noinspection JSUnusedGlobalSymbols
    
    /* global DateTimePicker */
    
    /* global feather */
    
    
    var TempusDominusBootstrap4 = function ($) {
      // eslint-disable-line no-unused-vars
      // ReSharper disable once InconsistentNaming
      var JQUERY_NO_CONFLICT = $.fn[DateTimePicker.NAME],
          verticalModes = ['top', 'bottom', 'auto'],
          horizontalModes = ['left', 'right', 'auto'],
          toolbarPlacements = ['default', 'top', 'bottom'],
          getSelectorFromElement = function getSelectorFromElement($element) {
        var selector = $element.data('target'),
            $selector;
    
        if (!selector) {
          selector = $element.attr('href') || '';
          selector = /^#[a-z]/i.test(selector) ? selector : null;
        }
    
        $selector = $(selector);
    
        if ($selector.length === 0) {
          return $element;
        }
    
        if (!$selector.data(DateTimePicker.DATA_KEY)) {
          $.extend({}, $selector.data(), $(this).data());
        }
    
        return $selector;
      }; // ReSharper disable once InconsistentNaming
    
    
      var TempusDominusBootstrap4 = /*#__PURE__*/function (_DateTimePicker) {
        _inheritsLoose(TempusDominusBootstrap4, _DateTimePicker);
    
        function TempusDominusBootstrap4(element, options) {
          var _this;
    
          _this = _DateTimePicker.call(this, element, options) || this;
    
          _this._init();
    
          return _this;
        }
    
        var _proto2 = TempusDominusBootstrap4.prototype;
    
        _proto2._init = function _init() {
          if (this._element.hasClass('input-group')) {
            var datepickerButton = this._element.find('.datepickerbutton');
    
            if (datepickerButton.length === 0) {
              this.component = this._element.find('[data-toggle="datetimepicker"]');
            } else {
              this.component = datepickerButton;
            }
          }
        };
    
        _proto2._iconTag = function _iconTag(iconName) {
          if (typeof feather !== 'undefined' && this._useFeatherIcons() && feather.icons[iconName]) {
            return $('<span>').html(feather.icons[iconName].toSvg());
          } else {
            return $('<span>').addClass(iconName);
          }
        };
    
        _proto2._getDatePickerTemplate = function _getDatePickerTemplate() {
          var headTemplate = $('<thead>').append($('<tr>').append($('<th>').addClass('prev').attr('data-action', 'previous').append(this._iconTag(this._options.icons.previous))).append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', "" + (this._options.calendarWeeks ? '6' : '5'))).append($('<th>').addClass('next').attr('data-action', 'next').append(this._iconTag(this._options.icons.next)))),
              contTemplate = $('<tbody>').append($('<tr>').append($('<td>').attr('colspan', "" + (this._options.calendarWeeks ? '8' : '7'))));
          return [$('<div>').addClass('datepicker-days').append($('<table>').addClass('table table-sm').append(headTemplate).append($('<tbody>'))), $('<div>').addClass('datepicker-months').append($('<table>').addClass('table-condensed').append(headTemplate.clone()).append(contTemplate.clone())), $('<div>').addClass('datepicker-years').append($('<table>').addClass('table-condensed').append(headTemplate.clone()).append(contTemplate.clone())), $('<div>').addClass('datepicker-decades').append($('<table>').addClass('table-condensed').append(headTemplate.clone()).append(contTemplate.clone()))];
        };
    
        _proto2._getTimePickerMainTemplate = function _getTimePickerMainTemplate() {
          var topRow = $('<tr>'),
              middleRow = $('<tr>'),
              bottomRow = $('<tr>');
    
          if (this._isEnabled('h')) {
            topRow.append($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'title': this._options.tooltips.incrementHour
            }).addClass('btn').attr('data-action', 'incrementHours').append(this._iconTag(this._options.icons.up))));
            middleRow.append($('<td>').append($('<span>').addClass('timepicker-hour').attr({
              'data-time-component': 'hours',
              'title': this._options.tooltips.pickHour
            }).attr('data-action', 'showHours')));
            bottomRow.append($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'title': this._options.tooltips.decrementHour
            }).addClass('btn').attr('data-action', 'decrementHours').append(this._iconTag(this._options.icons.down))));
          }
    
          if (this._isEnabled('m')) {
            if (this._isEnabled('h')) {
              topRow.append($('<td>').addClass('separator'));
              middleRow.append($('<td>').addClass('separator').html(':'));
              bottomRow.append($('<td>').addClass('separator'));
            }
    
            topRow.append($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'title': this._options.tooltips.incrementMinute
            }).addClass('btn').attr('data-action', 'incrementMinutes').append(this._iconTag(this._options.icons.up))));
            middleRow.append($('<td>').append($('<span>').addClass('timepicker-minute').attr({
              'data-time-component': 'minutes',
              'title': this._options.tooltips.pickMinute
            }).attr('data-action', 'showMinutes')));
            bottomRow.append($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'title': this._options.tooltips.decrementMinute
            }).addClass('btn').attr('data-action', 'decrementMinutes').append(this._iconTag(this._options.icons.down))));
          }
    
          if (this._isEnabled('s')) {
            if (this._isEnabled('m')) {
              topRow.append($('<td>').addClass('separator'));
              middleRow.append($('<td>').addClass('separator').html(':'));
              bottomRow.append($('<td>').addClass('separator'));
            }
    
            topRow.append($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'title': this._options.tooltips.incrementSecond
            }).addClass('btn').attr('data-action', 'incrementSeconds').append(this._iconTag(this._options.icons.up))));
            middleRow.append($('<td>').append($('<span>').addClass('timepicker-second').attr({
              'data-time-component': 'seconds',
              'title': this._options.tooltips.pickSecond
            }).attr('data-action', 'showSeconds')));
            bottomRow.append($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'title': this._options.tooltips.decrementSecond
            }).addClass('btn').attr('data-action', 'decrementSeconds').append(this._iconTag(this._options.icons.down))));
          }
    
          if (!this.use24Hours) {
            topRow.append($('<td>').addClass('separator'));
            middleRow.append($('<td>').append($('<button>').addClass('btn btn-primary').attr({
              'data-action': 'togglePeriod',
              tabindex: '-1',
              'title': this._options.tooltips.togglePeriod
            })));
            bottomRow.append($('<td>').addClass('separator'));
          }
    
          return $('<div>').addClass('timepicker-picker').append($('<table>').addClass('table-condensed').append([topRow, middleRow, bottomRow]));
        };
    
        _proto2._getTimePickerTemplate = function _getTimePickerTemplate() {
          var hoursView = $('<div>').addClass('timepicker-hours').append($('<table>').addClass('table-condensed')),
              minutesView = $('<div>').addClass('timepicker-minutes').append($('<table>').addClass('table-condensed')),
              secondsView = $('<div>').addClass('timepicker-seconds').append($('<table>').addClass('table-condensed')),
              ret = [this._getTimePickerMainTemplate()];
    
          if (this._isEnabled('h')) {
            ret.push(hoursView);
          }
    
          if (this._isEnabled('m')) {
            ret.push(minutesView);
          }
    
          if (this._isEnabled('s')) {
            ret.push(secondsView);
          }
    
          return ret;
        };
    
        _proto2._getToolbar = function _getToolbar() {
          var row = [];
    
          if (this._options.buttons.showToday) {
            row.push($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'data-action': 'today',
              'title': this._options.tooltips.today
            }).append(this._iconTag(this._options.icons.today))));
          }
    
          if (!this._options.sideBySide && this._options.collapse && this._hasDate() && this._hasTime()) {
            var title, icon;
    
            if (this._options.viewMode === 'times') {
              title = this._options.tooltips.selectDate;
              icon = this._options.icons.date;
            } else {
              title = this._options.tooltips.selectTime;
              icon = this._options.icons.time;
            }
    
            row.push($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'data-action': 'togglePicker',
              'title': title
            }).append(this._iconTag(icon))));
          }
    
          if (this._options.buttons.showClear) {
            row.push($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'data-action': 'clear',
              'title': this._options.tooltips.clear
            }).append(this._iconTag(this._options.icons.clear))));
          }
    
          if (this._options.buttons.showClose) {
            row.push($('<td>').append($('<a>').attr({
              href: '#',
              tabindex: '-1',
              'data-action': 'close',
              'title': this._options.tooltips.close
            }).append(this._iconTag(this._options.icons.close))));
          }
    
          return row.length === 0 ? '' : $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
        };
    
        _proto2._getTemplate = function _getTemplate() {
          var template = $('<div>').addClass(("bootstrap-datetimepicker-widget dropdown-menu " + (this._options.calendarWeeks ? 'tempusdominus-bootstrap-datetimepicker-widget-with-calendar-weeks' : '') + " " + ((this._useFeatherIcons() ? 'tempusdominus-bootstrap-datetimepicker-widget-with-feather-icons' : '') + " ")).trim()),
              dateView = $('<div>').addClass('datepicker').append(this._getDatePickerTemplate()),
              timeView = $('<div>').addClass('timepicker').append(this._getTimePickerTemplate()),
              content = $('<ul>').addClass('list-unstyled'),
              toolbar = $('<li>').addClass(("picker-switch" + (this._options.collapse ? ' accordion-toggle' : '') + " " + ("" + (this._useFeatherIcons() ? 'picker-switch-with-feathers-icons' : ''))).trim()).append(this._getToolbar());
    
          if (this._options.inline) {
            template.removeClass('dropdown-menu');
          }
    
          if (this.use24Hours) {
            template.addClass('usetwentyfour');
          }
    
          if (this.input !== undefined && this.input.prop('readonly') || this._options.readonly) {
            template.addClass('bootstrap-datetimepicker-widget-readonly');
          }
    
          if (this._isEnabled('s') && !this.use24Hours) {
            template.addClass('wider');
          }
    
          if (this._options.sideBySide && this._hasDate() && this._hasTime()) {
            template.addClass('timepicker-sbs');
    
            if (this._options.toolbarPlacement === 'top') {
              template.append(toolbar);
            }
    
            template.append($('<div>').addClass('row').append(dateView.addClass('col-md-6')).append(timeView.addClass('col-md-6')));
    
            if (this._options.toolbarPlacement === 'bottom' || this._options.toolbarPlacement === 'default') {
              template.append(toolbar);
            }
    
            return template;
          }
    
          if (this._options.toolbarPlacement === 'top') {
            content.append(toolbar);
          }
    
          if (this._hasDate()) {
            content.append($('<li>').addClass(this._options.collapse && this._hasTime() ? 'collapse' : '').addClass(this._options.collapse && this._hasTime() && this._options.viewMode === 'times' ? '' : 'show').append(dateView));
          }
    
          if (this._options.toolbarPlacement === 'default') {
            content.append(toolbar);
          }
    
          if (this._hasTime()) {
            content.append($('<li>').addClass(this._options.collapse && this._hasDate() ? 'collapse' : '').addClass(this._options.collapse && this._hasDate() && this._options.viewMode === 'times' ? 'show' : '').append(timeView));
          }
    
          if (this._options.toolbarPlacement === 'bottom') {
            content.append(toolbar);
          }
    
          return template.append(content);
        };
    
        _proto2._place = function _place(e) {
          var self = e && e.data && e.data.picker || this,
              vertical = self._options.widgetPositioning.vertical,
              horizontal = self._options.widgetPositioning.horizontal,
              parent;
          var position = (self.component && self.component.length ? self.component : self._element).position(),
              offset = (self.component && self.component.length ? self.component : self._element).offset();
    
          if (self._options.widgetParent) {
            parent = self._options.widgetParent.append(self.widget);
          } else if (self._element.is('input')) {
            parent = self._element.after(self.widget).parent();
          } else if (self._options.inline) {
            parent = self._element.append(self.widget);
            return;
          } else {
            parent = self._element;
    
            self._element.children().first().after(self.widget);
          } // Top and bottom logic
    
    
          if (vertical === 'auto') {
            //noinspection JSValidateTypes
            if (offset.top + self.widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() && self.widget.height() + self._element.outerHeight() < offset.top) {
              vertical = 'top';
            } else {
              vertical = 'bottom';
            }
          } // Left and right logic
    
    
          if (horizontal === 'auto') {
            if (parent.width() < offset.left + self.widget.outerWidth() / 2 && offset.left + self.widget.outerWidth() > $(window).width()) {
              horizontal = 'right';
            } else {
              horizontal = 'left';
            }
          }
    
          if (vertical === 'top') {
            self.widget.addClass('top').removeClass('bottom');
          } else {
            self.widget.addClass('bottom').removeClass('top');
          }
    
          if (horizontal === 'right') {
            self.widget.addClass('float-right');
          } else {
            self.widget.removeClass('float-right');
          } // find the first parent element that has a relative css positioning
    
    
          if (parent.css('position') !== 'relative') {
            parent = parent.parents().filter(function () {
              return $(this).css('position') === 'relative';
            }).first();
          }
    
          if (parent.length === 0) {
            throw new Error('datetimepicker component should be placed within a relative positioned container');
          }
    
          self.widget.css({
            top: vertical === 'top' ? 'auto' : position.top + self._element.outerHeight() + 'px',
            bottom: vertical === 'top' ? parent.outerHeight() - (parent === self._element ? 0 : position.top) + 'px' : 'auto',
            left: horizontal === 'left' ? (parent === self._element ? 0 : position.left) + 'px' : 'auto',
            right: horizontal === 'left' ? 'auto' : parent.outerWidth() - self._element.outerWidth() - (parent === self._element ? 0 : position.left) + 'px'
          });
        };
    
        _proto2._fillDow = function _fillDow() {
          var row = $('<tr>'),
              currentDate = this._viewDate.clone().startOf('w').startOf('d');
    
          if (this._options.calendarWeeks === true) {
            row.append($('<th>').addClass('cw').text('#'));
          }
    
          while (currentDate.isBefore(this._viewDate.clone().endOf('w'))) {
            row.append($('<th>').addClass('dow').text(currentDate.format('dd')));
            currentDate.add(1, 'd');
          }
    
          this.widget.find('.datepicker-days thead').append(row);
        };
    
        _proto2._fillMonths = function _fillMonths() {
          var spans = [],
              monthsShort = this._viewDate.clone().startOf('y').startOf('d');
    
          while (monthsShort.isSame(this._viewDate, 'y')) {
            spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
            monthsShort.add(1, 'M');
          }
    
          this.widget.find('.datepicker-months td').empty().append(spans);
        };
    
        _proto2._updateMonths = function _updateMonths() {
          var monthsView = this.widget.find('.datepicker-months'),
              monthsViewHeader = monthsView.find('th'),
              months = monthsView.find('tbody').find('span'),
              self = this,
              lastPickedDate = this._getLastPickedDate();
    
          monthsViewHeader.eq(0).find('span').attr('title', this._options.tooltips.prevYear);
          monthsViewHeader.eq(1).attr('title', this._options.tooltips.selectYear);
          monthsViewHeader.eq(2).find('span').attr('title', this._options.tooltips.nextYear);
          monthsView.find('.disabled').removeClass('disabled');
    
          if (!this._isValid(this._viewDate.clone().subtract(1, 'y'), 'y')) {
            monthsViewHeader.eq(0).addClass('disabled');
          }
    
          monthsViewHeader.eq(1).text(this._viewDate.year());
    
          if (!this._isValid(this._viewDate.clone().add(1, 'y'), 'y')) {
            monthsViewHeader.eq(2).addClass('disabled');
          }
    
          months.removeClass('active');
    
          if (lastPickedDate && lastPickedDate.isSame(this._viewDate, 'y') && !this.unset) {
            months.eq(lastPickedDate.month()).addClass('active');
          }
    
          months.each(function (index) {
            if (!self._isValid(self._viewDate.clone().month(index), 'M')) {
              $(this).addClass('disabled');
            }
          });
        };
    
        _proto2._getStartEndYear = function _getStartEndYear(factor, year) {
          var step = factor / 10,
              startYear = Math.floor(year / factor) * factor,
              endYear = startYear + step * 9,
              focusValue = Math.floor(year / step) * step;
          return [startYear, endYear, focusValue];
        };
    
        _proto2._updateYears = function _updateYears() {
          var yearsView = this.widget.find('.datepicker-years'),
              yearsViewHeader = yearsView.find('th'),
              yearCaps = this._getStartEndYear(10, this._viewDate.year()),
              startYear = this._viewDate.clone().year(yearCaps[0]),
              endYear = this._viewDate.clone().year(yearCaps[1]);
    
          var html = '';
          yearsViewHeader.eq(0).find('span').attr('title', this._options.tooltips.prevDecade);
          yearsViewHeader.eq(1).attr('title', this._options.tooltips.selectDecade);
          yearsViewHeader.eq(2).find('span').attr('title', this._options.tooltips.nextDecade);
          yearsView.find('.disabled').removeClass('disabled');
    
          if (this._options.minDate && this._options.minDate.isAfter(startYear, 'y')) {
            yearsViewHeader.eq(0).addClass('disabled');
          }
    
          yearsViewHeader.eq(1).text(startYear.year() + "-" + endYear.year());
    
          if (this._options.maxDate && this._options.maxDate.isBefore(endYear, 'y')) {
            yearsViewHeader.eq(2).addClass('disabled');
          }
    
          html += "<span data-action=\"selectYear\" class=\"year old" + (!this._isValid(startYear, 'y') ? ' disabled' : '') + "\">" + (startYear.year() - 1) + "</span>";
    
          while (!startYear.isAfter(endYear, 'y')) {
            html += "<span data-action=\"selectYear\" class=\"year" + (startYear.isSame(this._getLastPickedDate(), 'y') && !this.unset ? ' active' : '') + (!this._isValid(startYear, 'y') ? ' disabled' : '') + "\">" + startYear.year() + "</span>";
            startYear.add(1, 'y');
          }
    
          html += "<span data-action=\"selectYear\" class=\"year old" + (!this._isValid(startYear, 'y') ? ' disabled' : '') + "\">" + startYear.year() + "</span>";
          yearsView.find('td').html(html);
        };
    
        _proto2._updateDecades = function _updateDecades() {
          var decadesView = this.widget.find('.datepicker-decades'),
              decadesViewHeader = decadesView.find('th'),
              yearCaps = this._getStartEndYear(100, this._viewDate.year()),
              startDecade = this._viewDate.clone().year(yearCaps[0]),
              endDecade = this._viewDate.clone().year(yearCaps[1]),
              lastPickedDate = this._getLastPickedDate();
    
          var minDateDecade = false,
              maxDateDecade = false,
              endDecadeYear,
              html = '';
          decadesViewHeader.eq(0).find('span').attr('title', this._options.tooltips.prevCentury);
          decadesViewHeader.eq(2).find('span').attr('title', this._options.tooltips.nextCentury);
          decadesView.find('.disabled').removeClass('disabled');
    
          if (startDecade.year() === 0 || this._options.minDate && this._options.minDate.isAfter(startDecade, 'y')) {
            decadesViewHeader.eq(0).addClass('disabled');
          }
    
          decadesViewHeader.eq(1).text(startDecade.year() + "-" + endDecade.year());
    
          if (this._options.maxDate && this._options.maxDate.isBefore(endDecade, 'y')) {
            decadesViewHeader.eq(2).addClass('disabled');
          }
    
          if (startDecade.year() - 10 < 0) {
            html += '<span>&nbsp;</span>';
          } else {
            html += "<span data-action=\"selectDecade\" class=\"decade old\" data-selection=\"" + (startDecade.year() + 6) + "\">" + (startDecade.year() - 10) + "</span>";
          }
    
          while (!startDecade.isAfter(endDecade, 'y')) {
            endDecadeYear = startDecade.year() + 11;
            minDateDecade = this._options.minDate && this._options.minDate.isAfter(startDecade, 'y') && this._options.minDate.year() <= endDecadeYear;
            maxDateDecade = this._options.maxDate && this._options.maxDate.isAfter(startDecade, 'y') && this._options.maxDate.year() <= endDecadeYear;
            html += "<span data-action=\"selectDecade\" class=\"decade" + (lastPickedDate && lastPickedDate.isAfter(startDecade) && lastPickedDate.year() <= endDecadeYear ? ' active' : '') + (!this._isValid(startDecade, 'y') && !minDateDecade && !maxDateDecade ? ' disabled' : '') + "\" data-selection=\"" + (startDecade.year() + 6) + "\">" + startDecade.year() + "</span>";
            startDecade.add(10, 'y');
          }
    
          html += "<span data-action=\"selectDecade\" class=\"decade old\" data-selection=\"" + (startDecade.year() + 6) + "\">" + startDecade.year() + "</span>";
          decadesView.find('td').html(html);
        };
    
        _proto2._fillDate = function _fillDate() {
          _DateTimePicker.prototype._fillDate.call(this);
    
          var daysView = this.widget.find('.datepicker-days'),
              daysViewHeader = daysView.find('th'),
              html = [];
          var currentDate, row, clsName, i;
    
          if (!this._hasDate()) {
            return;
          }
    
          daysViewHeader.eq(0).find('span').attr('title', this._options.tooltips.prevMonth);
          daysViewHeader.eq(1).attr('title', this._options.tooltips.selectMonth);
          daysViewHeader.eq(2).find('span').attr('title', this._options.tooltips.nextMonth);
          daysView.find('.disabled').removeClass('disabled');
          daysViewHeader.eq(1).text(this._viewDate.format(this._options.dayViewHeaderFormat));
    
          if (!this._isValid(this._viewDate.clone().subtract(1, 'M'), 'M')) {
            daysViewHeader.eq(0).addClass('disabled');
          }
    
          if (!this._isValid(this._viewDate.clone().add(1, 'M'), 'M')) {
            daysViewHeader.eq(2).addClass('disabled');
          }
    
          currentDate = this._viewDate.clone().startOf('M').startOf('w').startOf('d');
    
          for (i = 0; i < 42; i++) {
            //always display 42 days (should show 6 weeks)
            if (currentDate.weekday() === 0) {
              row = $('<tr>');
    
              if (this._options.calendarWeeks) {
                row.append("<td class=\"cw\">" + currentDate.week() + "</td>");
              }
    
              html.push(row);
            }
    
            clsName = '';
    
            if (currentDate.isBefore(this._viewDate, 'M')) {
              clsName += ' old';
            }
    
            if (currentDate.isAfter(this._viewDate, 'M')) {
              clsName += ' new';
            }
    
            if (this._options.allowMultidate) {
              var index = this._datesFormatted.indexOf(currentDate.format('YYYY-MM-DD'));
    
              if (index !== -1) {
                if (currentDate.isSame(this._datesFormatted[index], 'd') && !this.unset) {
                  clsName += ' active';
                }
              }
            } else {
              if (currentDate.isSame(this._getLastPickedDate(), 'd') && !this.unset) {
                clsName += ' active';
              }
            }
    
            if (!this._isValid(currentDate, 'd')) {
              clsName += ' disabled';
            }
    
            if (currentDate.isSame(this.getMoment(), 'd')) {
              clsName += ' today';
            }
    
            if (currentDate.day() === 0 || currentDate.day() === 6) {
              clsName += ' weekend';
            }
    
            row.append("<td data-action=\"selectDay\" data-day=\"" + currentDate.format('L') + "\" class=\"day" + clsName + "\">" + currentDate.date() + "</td>");
            currentDate.add(1, 'd');
          }
    
          $('body').addClass('tempusdominus-bootstrap-datetimepicker-widget-day-click');
          $('body').append('<div class="tempusdominus-bootstrap-datetimepicker-widget-day-click-glass-panel"></div>');
          daysView.find('tbody').empty().append(html);
          $('body').find('.tempusdominus-bootstrap-datetimepicker-widget-day-click-glass-panel').remove();
          $('body').removeClass('tempusdominus-bootstrap-datetimepicker-widget-day-click');
    
          this._updateMonths();
    
          this._updateYears();
    
          this._updateDecades();
        };
    
        _proto2._fillHours = function _fillHours() {
          var table = this.widget.find('.timepicker-hours table'),
              currentHour = this._viewDate.clone().startOf('d'),
              html = [];
    
          var row = $('<tr>');
    
          if (this._viewDate.hour() > 11 && !this.use24Hours) {
            currentHour.hour(12);
          }
    
          while (currentHour.isSame(this._viewDate, 'd') && (this.use24Hours || this._viewDate.hour() < 12 && currentHour.hour() < 12 || this._viewDate.hour() > 11)) {
            if (currentHour.hour() % 4 === 0) {
              row = $('<tr>');
              html.push(row);
            }
    
            row.append("<td data-action=\"selectHour\" class=\"hour" + (!this._isValid(currentHour, 'h') ? ' disabled' : '') + "\">" + currentHour.format(this.use24Hours ? 'HH' : 'hh') + "</td>");
            currentHour.add(1, 'h');
          }
    
          table.empty().append(html);
        };
    
        _proto2._fillMinutes = function _fillMinutes() {
          var table = this.widget.find('.timepicker-minutes table'),
              currentMinute = this._viewDate.clone().startOf('h'),
              html = [],
              step = this._options.stepping === 1 ? 5 : this._options.stepping;
    
          var row = $('<tr>');
    
          while (this._viewDate.isSame(currentMinute, 'h')) {
            if (currentMinute.minute() % (step * 4) === 0) {
              row = $('<tr>');
              html.push(row);
            }
    
            row.append("<td data-action=\"selectMinute\" class=\"minute" + (!this._isValid(currentMinute, 'm') ? ' disabled' : '') + "\">" + currentMinute.format('mm') + "</td>");
            currentMinute.add(step, 'm');
          }
    
          table.empty().append(html);
        };
    
        _proto2._fillSeconds = function _fillSeconds() {
          var table = this.widget.find('.timepicker-seconds table'),
              currentSecond = this._viewDate.clone().startOf('m'),
              html = [];
    
          var row = $('<tr>');
    
          while (this._viewDate.isSame(currentSecond, 'm')) {
            if (currentSecond.second() % 20 === 0) {
              row = $('<tr>');
              html.push(row);
            }
    
            row.append("<td data-action=\"selectSecond\" class=\"second" + (!this._isValid(currentSecond, 's') ? ' disabled' : '') + "\">" + currentSecond.format('ss') + "</td>");
            currentSecond.add(5, 's');
          }
    
          table.empty().append(html);
        };
    
        _proto2._fillTime = function _fillTime() {
          var toggle, newDate;
    
          var timeComponents = this.widget.find('.timepicker span[data-time-component]'),
              lastPickedDate = this._getLastPickedDate();
    
          if (!this.use24Hours) {
            toggle = this.widget.find('.timepicker [data-action=togglePeriod]');
            newDate = lastPickedDate ? lastPickedDate.clone().add(lastPickedDate.hours() >= 12 ? -12 : 12, 'h') : void 0;
            lastPickedDate && toggle.text(lastPickedDate.format('A'));
    
            if (this._isValid(newDate, 'h')) {
              toggle.removeClass('disabled');
            } else {
              toggle.addClass('disabled');
            }
          }
    
          lastPickedDate && timeComponents.filter('[data-time-component=hours]').text(lastPickedDate.format("" + (this.use24Hours ? 'HH' : 'hh')));
          lastPickedDate && timeComponents.filter('[data-time-component=minutes]').text(lastPickedDate.format('mm'));
          lastPickedDate && timeComponents.filter('[data-time-component=seconds]').text(lastPickedDate.format('ss'));
    
          this._fillHours();
    
          this._fillMinutes();
    
          this._fillSeconds();
        };
    
        _proto2._doAction = function _doAction(e, action) {
          var lastPicked = this._getLastPickedDate();
    
          if ($(e.currentTarget).is('.disabled')) {
            return false;
          }
    
          action = action || $(e.currentTarget).data('action');
    
          switch (action) {
            case 'next':
              {
                var navFnc = DateTimePicker.DatePickerModes[this.currentViewMode].NAV_FUNCTION;
    
                this._viewDate.add(DateTimePicker.DatePickerModes[this.currentViewMode].NAV_STEP, navFnc);
    
                this._fillDate();
    
                this._viewUpdate(navFnc);
    
                break;
              }
    
            case 'previous':
              {
                var _navFnc = DateTimePicker.DatePickerModes[this.currentViewMode].NAV_FUNCTION;
    
                this._viewDate.subtract(DateTimePicker.DatePickerModes[this.currentViewMode].NAV_STEP, _navFnc);
    
                this._fillDate();
    
                this._viewUpdate(_navFnc);
    
                break;
              }
    
            case 'pickerSwitch':
              this._showMode(1);
    
              break;
    
            case 'selectMonth':
              {
                var month = $(e.target).closest('tbody').find('span').index($(e.target));
    
                this._viewDate.month(month);
    
                if (this.currentViewMode === this.MinViewModeNumber) {
                  this._setValue(lastPicked.clone().year(this._viewDate.year()).month(this._viewDate.month()), this._getLastPickedDateIndex());
    
                  if (!this._options.inline) {
                    this.hide();
                  }
                } else {
                  this._showMode(-1);
    
                  this._fillDate();
                }
    
                this._viewUpdate('M');
    
                break;
              }
    
            case 'selectYear':
              {
                var year = parseInt($(e.target).text(), 10) || 0;
    
                this._viewDate.year(year);
    
                if (this.currentViewMode === this.MinViewModeNumber) {
                  this._setValue(lastPicked.clone().year(this._viewDate.year()), this._getLastPickedDateIndex());
    
                  if (!this._options.inline) {
                    this.hide();
                  }
                } else {
                  this._showMode(-1);
    
                  this._fillDate();
                }
    
                this._viewUpdate('YYYY');
    
                break;
              }
    
            case 'selectDecade':
              {
                var _year = parseInt($(e.target).data('selection'), 10) || 0;
    
                this._viewDate.year(_year);
    
                if (this.currentViewMode === this.MinViewModeNumber) {
                  this._setValue(lastPicked.clone().year(this._viewDate.year()), this._getLastPickedDateIndex());
    
                  if (!this._options.inline) {
                    this.hide();
                  }
                } else {
                  this._showMode(-1);
    
                  this._fillDate();
                }
    
                this._viewUpdate('YYYY');
    
                break;
              }
    
            case 'selectDay':
              {
                var day = this._viewDate.clone();
    
                if ($(e.target).is('.old')) {
                  day.subtract(1, 'M');
                }
    
                if ($(e.target).is('.new')) {
                  day.add(1, 'M');
                }
    
                var selectDate = day.date(parseInt($(e.target).text(), 10)),
                    index = 0;
    
                if (this._options.allowMultidate) {
                  index = this._datesFormatted.indexOf(selectDate.format('YYYY-MM-DD'));
    
                  if (index !== -1) {
                    this._setValue(null, index); //deselect multidate
    
                  } else {
                    this._setValue(selectDate, this._getLastPickedDateIndex() + 1);
                  }
                } else {
                  this._setValue(selectDate, this._getLastPickedDateIndex());
                }
    
                if (!this._hasTime() && !this._options.keepOpen && !this._options.inline && !this._options.allowMultidate) {
                  this.hide();
                }
    
                break;
              }
    
            case 'incrementHours':
              {
                if (!lastPicked) {
                  break;
                }
    
                var newDate = lastPicked.clone().add(1, 'h');
    
                if (this._isValid(newDate, 'h')) {
                  if (this._getLastPickedDateIndex() < 0) {
                    this.date(newDate);
                  }
    
                  this._setValue(newDate, this._getLastPickedDateIndex());
                }
    
                break;
              }
    
            case 'incrementMinutes':
              {
                if (!lastPicked) {
                  break;
                }
    
                var _newDate = lastPicked.clone().add(this._options.stepping, 'm');
    
                if (this._isValid(_newDate, 'm')) {
                  if (this._getLastPickedDateIndex() < 0) {
                    this.date(_newDate);
                  }
    
                  this._setValue(_newDate, this._getLastPickedDateIndex());
                }
    
                break;
              }
    
            case 'incrementSeconds':
              {
                if (!lastPicked) {
                  break;
                }
    
                var _newDate2 = lastPicked.clone().add(1, 's');
    
                if (this._isValid(_newDate2, 's')) {
                  if (this._getLastPickedDateIndex() < 0) {
                    this.date(_newDate2);
                  }
    
                  this._setValue(_newDate2, this._getLastPickedDateIndex());
                }
    
                break;
              }
    
            case 'decrementHours':
              {
                if (!lastPicked) {
                  break;
                }
    
                var _newDate3 = lastPicked.clone().subtract(1, 'h');
    
                if (this._isValid(_newDate3, 'h')) {
                  if (this._getLastPickedDateIndex() < 0) {
                    this.date(_newDate3);
                  }
    
                  this._setValue(_newDate3, this._getLastPickedDateIndex());
                }
    
                break;
              }
    
            case 'decrementMinutes':
              {
                if (!lastPicked) {
                  break;
                }
    
                var _newDate4 = lastPicked.clone().subtract(this._options.stepping, 'm');
    
                if (this._isValid(_newDate4, 'm')) {
                  if (this._getLastPickedDateIndex() < 0) {
                    this.date(_newDate4);
                  }
    
                  this._setValue(_newDate4, this._getLastPickedDateIndex());
                }
    
                break;
              }
    
            case 'decrementSeconds':
              {
                if (!lastPicked) {
                  break;
                }
    
                var _newDate5 = lastPicked.clone().subtract(1, 's');
    
                if (this._isValid(_newDate5, 's')) {
                  if (this._getLastPickedDateIndex() < 0) {
                    this.date(_newDate5);
                  }
    
                  this._setValue(_newDate5, this._getLastPickedDateIndex());
                }
    
                break;
              }
    
            case 'togglePeriod':
              {
                this._setValue(lastPicked.clone().add(lastPicked.hours() >= 12 ? -12 : 12, 'h'), this._getLastPickedDateIndex());
    
                break;
              }
    
            case 'togglePicker':
              {
                var $this = $(e.target),
                    $link = $this.closest('a'),
                    $parent = $this.closest('ul'),
                    expanded = $parent.find('.show'),
                    closed = $parent.find('.collapse:not(.show)'),
                    $span = $this.is('span') ? $this : $this.find('span');
                var collapseData, inactiveIcon, iconTest;
    
                if (expanded && expanded.length) {
                  collapseData = expanded.data('collapse');
    
                  if (collapseData && collapseData.transitioning) {
                    return true;
                  }
    
                  if (expanded.collapse) {
                    // if collapse plugin is available through bootstrap.js then use it
                    expanded.collapse('hide');
                    closed.collapse('show');
                  } else {
                    // otherwise just toggle in class on the two views
                    expanded.removeClass('show');
                    closed.addClass('show');
                  }
    
                  if (this._useFeatherIcons()) {
                    $link.toggleClass(this._options.icons.time + ' ' + this._options.icons.date);
                    inactiveIcon = $link.hasClass(this._options.icons.time) ? this._options.icons.date : this._options.icons.time;
                    $link.html(this._iconTag(inactiveIcon));
                  } else {
                    $span.toggleClass(this._options.icons.time + ' ' + this._options.icons.date);
                  }
    
                  if (this._useFeatherIcons()) {
                    iconTest = $link.hasClass(this._options.icons.date);
                  } else {
                    iconTest = $span.hasClass(this._options.icons.date);
                  }
    
                  if (iconTest) {
                    $link.attr('title', this._options.tooltips.selectDate);
                  } else {
                    $link.attr('title', this._options.tooltips.selectTime);
                  }
                }
              }
              break;
    
            case 'showPicker':
              this.widget.find('.timepicker > div:not(.timepicker-picker)').hide();
              this.widget.find('.timepicker .timepicker-picker').show();
              break;
    
            case 'showHours':
              this.widget.find('.timepicker .timepicker-picker').hide();
              this.widget.find('.timepicker .timepicker-hours').show();
              break;
    
            case 'showMinutes':
              this.widget.find('.timepicker .timepicker-picker').hide();
              this.widget.find('.timepicker .timepicker-minutes').show();
              break;
    
            case 'showSeconds':
              this.widget.find('.timepicker .timepicker-picker').hide();
              this.widget.find('.timepicker .timepicker-seconds').show();
              break;
    
            case 'selectHour':
              {
                var hour = parseInt($(e.target).text(), 10);
    
                if (!this.use24Hours) {
                  if (lastPicked.hours() >= 12) {
                    if (hour !== 12) {
                      hour += 12;
                    }
                  } else {
                    if (hour === 12) {
                      hour = 0;
                    }
                  }
                }
    
                this._setValue(lastPicked.clone().hours(hour), this._getLastPickedDateIndex());
    
                if (!this._isEnabled('a') && !this._isEnabled('m') && !this._options.keepOpen && !this._options.inline) {
                  this.hide();
                } else {
                  this._doAction(e, 'showPicker');
                }
    
                break;
              }
    
            case 'selectMinute':
              this._setValue(lastPicked.clone().minutes(parseInt($(e.target).text(), 10)), this._getLastPickedDateIndex());
    
              if (!this._isEnabled('a') && !this._isEnabled('s') && !this._options.keepOpen && !this._options.inline) {
                this.hide();
              } else {
                this._doAction(e, 'showPicker');
              }
    
              break;
    
            case 'selectSecond':
              this._setValue(lastPicked.clone().seconds(parseInt($(e.target).text(), 10)), this._getLastPickedDateIndex());
    
              if (!this._isEnabled('a') && !this._options.keepOpen && !this._options.inline) {
                this.hide();
              } else {
                this._doAction(e, 'showPicker');
              }
    
              break;
    
            case 'clear':
              this.clear();
              break;
    
            case 'close':
              this.hide();
              break;
    
            case 'today':
              {
                var todaysDate = this.getMoment();
    
                if (this._isValid(todaysDate, 'd')) {
                  this._setValue(todaysDate, this._getLastPickedDateIndex());
                }
    
                break;
              }
          }
    
          return false;
        } //public
        ;
    
        _proto2.hide = function hide() {
          var transitioning = false;
    
          if (!this.widget) {
            return;
          } // Ignore event if in the middle of a picker transition
    
    
          this.widget.find('.collapse').each(function () {
            var collapseData = $(this).data('collapse');
    
            if (collapseData && collapseData.transitioning) {
              transitioning = true;
              return false;
            }
    
            return true;
          });
    
          if (transitioning) {
            return;
          }
    
          if (this.component && this.component.hasClass('btn')) {
            this.component.toggleClass('active');
          }
    
          this.widget.hide();
          $(window).off('resize', this._place);
          this.widget.off('click', '[data-action]');
          this.widget.off('mousedown', false);
          this.widget.remove();
          this.widget = false;
    
          if (this.input !== undefined && this.input.val() !== undefined && this.input.val().trim().length !== 0) {
            this._setValue(this._parseInputDate(this.input.val().trim(), {
              isPickerShow: false
            }), 0);
          }
    
          var lastPickedDate = this._getLastPickedDate();
    
          this._notifyEvent({
            type: DateTimePicker.Event.HIDE,
            date: this.unset ? null : lastPickedDate ? lastPickedDate.clone() : void 0
          });
    
          if (this.input !== undefined) {
            this.input.blur();
          }
    
          this._viewDate = lastPickedDate ? lastPickedDate.clone() : this.getMoment();
        };
    
        _proto2.show = function show() {
          var currentMoment,
              shouldUseCurrentIfUnset = false;
          var useCurrentGranularity = {
            'year': function year(m) {
              return m.month(0).date(1).hours(0).seconds(0).minutes(0);
            },
            'month': function month(m) {
              return m.date(1).hours(0).seconds(0).minutes(0);
            },
            'day': function day(m) {
              return m.hours(0).seconds(0).minutes(0);
            },
            'hour': function hour(m) {
              return m.seconds(0).minutes(0);
            },
            'minute': function minute(m) {
              return m.seconds(0);
            }
          };
    
          if (this.input !== undefined) {
            if (this.input.prop('disabled') || !this._options.ignoreReadonly && this.input.prop('readonly') || this.widget) {
              return;
            }
    
            if (this.input.val() !== undefined && this.input.val().trim().length !== 0) {
              this._setValue(this._parseInputDate(this.input.val().trim(), {
                isPickerShow: true
              }), 0);
            } else {
              shouldUseCurrentIfUnset = true;
            }
          } else {
            shouldUseCurrentIfUnset = true;
          }
    
          if (shouldUseCurrentIfUnset && this.unset && this._options.useCurrent) {
            currentMoment = this.getMoment();
    
            if (typeof this._options.useCurrent === 'string') {
              currentMoment = useCurrentGranularity[this._options.useCurrent](currentMoment);
            }
    
            this._setValue(currentMoment, 0);
          }
    
          this.widget = this._getTemplate();
    
          this._fillDow();
    
          this._fillMonths();
    
          this.widget.find('.timepicker-hours').hide();
          this.widget.find('.timepicker-minutes').hide();
          this.widget.find('.timepicker-seconds').hide();
    
          this._update();
    
          this._showMode();
    
          $(window).on('resize', {
            picker: this
          }, this._place);
          this.widget.on('click', '[data-action]', $.proxy(this._doAction, this)); // this handles clicks on the widget
    
          this.widget.on('mousedown', false);
    
          if (this.component && this.component.hasClass('btn')) {
            this.component.toggleClass('active');
          }
    
          this._place();
    
          this.widget.show();
    
          if (this.input !== undefined && this._options.focusOnShow && !this.input.is(':focus')) {
            this.input.focus();
          }
    
          this._notifyEvent({
            type: DateTimePicker.Event.SHOW
          });
        };
    
        _proto2.destroy = function destroy() {
          this.hide(); //todo doc off?
    
          this._element.removeData(DateTimePicker.DATA_KEY);
    
          this._element.removeData('date');
        };
    
        _proto2.disable = function disable() {
          this.hide();
    
          if (this.component && this.component.hasClass('btn')) {
            this.component.addClass('disabled');
          }
    
          if (this.input !== undefined) {
            this.input.prop('disabled', true); //todo disable this/comp if input is null
          }
        };
    
        _proto2.enable = function enable() {
          if (this.component && this.component.hasClass('btn')) {
            this.component.removeClass('disabled');
          }
    
          if (this.input !== undefined) {
            this.input.prop('disabled', false); //todo enable comp/this if input is null
          }
        };
    
        _proto2.toolbarPlacement = function toolbarPlacement(_toolbarPlacement) {
          if (arguments.length === 0) {
            return this._options.toolbarPlacement;
          }
    
          if (typeof _toolbarPlacement !== 'string') {
            throw new TypeError('toolbarPlacement() expects a string parameter');
          }
    
          if (toolbarPlacements.indexOf(_toolbarPlacement) === -1) {
            throw new TypeError("toolbarPlacement() parameter must be one of (" + toolbarPlacements.join(', ') + ") value");
          }
    
          this._options.toolbarPlacement = _toolbarPlacement;
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto2.widgetPositioning = function widgetPositioning(_widgetPositioning) {
          if (arguments.length === 0) {
            return $.extend({}, this._options.widgetPositioning);
          }
    
          if ({}.toString.call(_widgetPositioning) !== '[object Object]') {
            throw new TypeError('widgetPositioning() expects an object variable');
          }
    
          if (_widgetPositioning.horizontal) {
            if (typeof _widgetPositioning.horizontal !== 'string') {
              throw new TypeError('widgetPositioning() horizontal variable must be a string');
            }
    
            _widgetPositioning.horizontal = _widgetPositioning.horizontal.toLowerCase();
    
            if (horizontalModes.indexOf(_widgetPositioning.horizontal) === -1) {
              throw new TypeError("widgetPositioning() expects horizontal parameter to be one of (" + horizontalModes.join(', ') + ")");
            }
    
            this._options.widgetPositioning.horizontal = _widgetPositioning.horizontal;
          }
    
          if (_widgetPositioning.vertical) {
            if (typeof _widgetPositioning.vertical !== 'string') {
              throw new TypeError('widgetPositioning() vertical variable must be a string');
            }
    
            _widgetPositioning.vertical = _widgetPositioning.vertical.toLowerCase();
    
            if (verticalModes.indexOf(_widgetPositioning.vertical) === -1) {
              throw new TypeError("widgetPositioning() expects vertical parameter to be one of (" + verticalModes.join(', ') + ")");
            }
    
            this._options.widgetPositioning.vertical = _widgetPositioning.vertical;
          }
    
          this._update();
        };
    
        _proto2.widgetParent = function widgetParent(_widgetParent) {
          if (arguments.length === 0) {
            return this._options.widgetParent;
          }
    
          if (typeof _widgetParent === 'string') {
            _widgetParent = $(_widgetParent);
          }
    
          if (_widgetParent !== null && typeof _widgetParent !== 'string' && !(_widgetParent instanceof $)) {
            throw new TypeError('widgetParent() expects a string or a jQuery object parameter');
          }
    
          this._options.widgetParent = _widgetParent;
    
          if (this.widget) {
            this.hide();
            this.show();
          }
        };
    
        _proto2.setMultiDate = function setMultiDate(multiDateArray) {
          var dateFormat = this._options.format;
          this.clear();
    
          for (var index = 0; index < multiDateArray.length; index++) {
            var date = moment(multiDateArray[index], dateFormat);
    
            this._setValue(date, index);
          }
        } //static
        ;
    
        TempusDominusBootstrap4._jQueryHandleThis = function _jQueryHandleThis(me, option, argument) {
          var data = $(me).data(DateTimePicker.DATA_KEY);
    
          if (typeof option === 'object') {
            $.extend({}, DateTimePicker.Default, option);
          }
    
          if (!data) {
            data = new TempusDominusBootstrap4($(me), option);
            $(me).data(DateTimePicker.DATA_KEY, data);
          }
    
          if (typeof option === 'string') {
            if (data[option] === undefined) {
              throw new Error("No method named \"" + option + "\"");
            }
    
            if (argument === undefined) {
              return data[option]();
            } else {
              if (option === 'date') {
                data.isDateUpdateThroughDateOptionFromClientCode = true;
              }
    
              var ret = data[option](argument);
              data.isDateUpdateThroughDateOptionFromClientCode = false;
              return ret;
            }
          }
        };
    
        TempusDominusBootstrap4._jQueryInterface = function _jQueryInterface(option, argument) {
          if (this.length === 1) {
            return TempusDominusBootstrap4._jQueryHandleThis(this[0], option, argument);
          }
    
          return this.each(function () {
            TempusDominusBootstrap4._jQueryHandleThis(this, option, argument);
          });
        };
    
        return TempusDominusBootstrap4;
      }(DateTimePicker);
      /**
      * ------------------------------------------------------------------------
      * jQuery
      * ------------------------------------------------------------------------
      */
    
    
      $(document).on(DateTimePicker.Event.CLICK_DATA_API, DateTimePicker.Selector.DATA_TOGGLE, function () {
        var $originalTarget = $(this),
            $target = getSelectorFromElement($originalTarget),
            config = $target.data(DateTimePicker.DATA_KEY);
    
        if ($target.length === 0) {
          return;
        }
    
        if (config._options.allowInputToggle && $originalTarget.is('input[data-toggle="datetimepicker"]')) {
          return;
        }
    
        TempusDominusBootstrap4._jQueryInterface.call($target, 'toggle');
      }).on(DateTimePicker.Event.CHANGE, "." + DateTimePicker.ClassName.INPUT, function (event) {
        var $target = getSelectorFromElement($(this));
    
        if ($target.length === 0 || event.isInit) {
          return;
        }
    
        TempusDominusBootstrap4._jQueryInterface.call($target, '_change', event);
      }).on(DateTimePicker.Event.BLUR, "." + DateTimePicker.ClassName.INPUT, function (event) {
        var $target = getSelectorFromElement($(this)),
            config = $target.data(DateTimePicker.DATA_KEY);
    
        if ($target.length === 0) {
          return;
        }
    
        if (config._options.debug || window.debug) {
          return;
        }
    
        TempusDominusBootstrap4._jQueryInterface.call($target, 'hide', event);
      }).on(DateTimePicker.Event.KEYDOWN, "." + DateTimePicker.ClassName.INPUT, function (event) {
        var $target = getSelectorFromElement($(this));
    
        if ($target.length === 0) {
          return;
        }
    
        TempusDominusBootstrap4._jQueryInterface.call($target, '_keydown', event);
      }).on(DateTimePicker.Event.KEYUP, "." + DateTimePicker.ClassName.INPUT, function (event) {
        var $target = getSelectorFromElement($(this));
    
        if ($target.length === 0) {
          return;
        }
    
        TempusDominusBootstrap4._jQueryInterface.call($target, '_keyup', event);
      }).on(DateTimePicker.Event.FOCUS, "." + DateTimePicker.ClassName.INPUT, function (event) {
        var $target = getSelectorFromElement($(this)),
            config = $target.data(DateTimePicker.DATA_KEY);
    
        if ($target.length === 0) {
          return;
        }
    
        if (!config._options.allowInputToggle) {
          return;
        }
    
        TempusDominusBootstrap4._jQueryInterface.call($target, 'show', event);
      });
      $.fn[DateTimePicker.NAME] = TempusDominusBootstrap4._jQueryInterface;
      $.fn[DateTimePicker.NAME].Constructor = TempusDominusBootstrap4;
    
      $.fn[DateTimePicker.NAME].noConflict = function () {
        $.fn[DateTimePicker.NAME] = JQUERY_NO_CONFLICT;
        return TempusDominusBootstrap4._jQueryInterface;
      };
    
      return TempusDominusBootstrap4;
    }(jQuery);
    
    }();
    
    /*!
     * dist/jquery.inputmask
     * https://github.com/RobinHerbots/Inputmask
     * Copyright (c) 2010 - 2020 Robin Herbots
     * Licensed under the MIT license
     * Version: 5.0.5-beta.0
     */
    !function webpackUniversalModuleDefinition(root, factory) {
        if ("object" == typeof exports && "object" == typeof module) module.exports = factory(require("jquery")); else if ("function" == typeof define && define.amd) define([ "jquery" ], factory); else {
            var a = "object" == typeof exports ? factory(require("jquery")) : factory(root.jQuery);
            for (var i in a) ("object" == typeof exports ? exports : root)[i] = a[i];
        }
    }(window, function(__WEBPACK_EXTERNAL_MODULE__8__) {
        return modules = [ function(module) {
            module.exports = JSON.parse('{"BACKSPACE":8,"BACKSPACE_SAFARI":127,"DELETE":46,"DOWN":40,"END":35,"ENTER":13,"ESCAPE":27,"HOME":36,"INSERT":45,"LEFT":37,"PAGE_DOWN":34,"PAGE_UP":33,"RIGHT":39,"SPACE":32,"TAB":9,"UP":38,"X":88,"CONTROL":17,"KEY_229":229}');
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.default = void 0, __webpack_require__(9);
            var _mask = __webpack_require__(10), _inputmask = _interopRequireDefault(__webpack_require__(12)), _window = _interopRequireDefault(__webpack_require__(13)), _maskLexer = __webpack_require__(17), _validationTests = __webpack_require__(3), _positioning = __webpack_require__(2), _validation = __webpack_require__(4), _inputHandling = __webpack_require__(5), _eventruler = __webpack_require__(11), _definitions = _interopRequireDefault(__webpack_require__(18)), _defaults = _interopRequireDefault(__webpack_require__(19));
            function _typeof(obj) {
                return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                    return typeof obj;
                } : function _typeof(obj) {
                    return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
                }, _typeof(obj);
            }
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            var document = _window.default.document, dataKey = "_inputmask_opts";
            function Inputmask(alias, options, internal) {
                if (!(this instanceof Inputmask)) return new Inputmask(alias, options, internal);
                this.dependencyLib = _inputmask.default, this.el = void 0, this.events = {}, this.maskset = void 0, 
                !0 !== internal && ("[object Object]" === Object.prototype.toString.call(alias) ? options = alias : (options = options || {}, 
                alias && (options.alias = alias)), this.opts = _inputmask.default.extend(!0, {}, this.defaults, options), 
                this.noMasksCache = options && void 0 !== options.definitions, this.userOptions = options || {}, 
                resolveAlias(this.opts.alias, options, this.opts)), this.refreshValue = !1, this.undoValue = void 0, 
                this.$el = void 0, this.skipKeyPressEvent = !1, this.skipInputEvent = !1, this.validationEvent = !1, 
                this.ignorable = !1, this.maxLength, this.mouseEnter = !1, this.originalPlaceholder = void 0, 
                this.isComposing = !1;
            }
            function resolveAlias(aliasStr, options, opts) {
                var aliasDefinition = Inputmask.prototype.aliases[aliasStr];
                return aliasDefinition ? (aliasDefinition.alias && resolveAlias(aliasDefinition.alias, void 0, opts), 
                _inputmask.default.extend(!0, opts, aliasDefinition), _inputmask.default.extend(!0, opts, options), 
                !0) : (null === opts.mask && (opts.mask = aliasStr), !1);
            }
            function importAttributeOptions(npt, opts, userOptions, dataAttribute) {
                function importOption(option, optionData) {
                    var attrOption = "" === dataAttribute ? option : dataAttribute + "-" + option;
                    optionData = void 0 !== optionData ? optionData : npt.getAttribute(attrOption), 
                    null !== optionData && ("string" == typeof optionData && (0 === option.indexOf("on") ? optionData = _window.default[optionData] : "false" === optionData ? optionData = !1 : "true" === optionData && (optionData = !0)), 
                    userOptions[option] = optionData);
                }
                if (!0 === opts.importDataAttributes) {
                    var attrOptions = npt.getAttribute(dataAttribute), option, dataoptions, optionData, p;
                    if (attrOptions && "" !== attrOptions && (attrOptions = attrOptions.replace(/'/g, '"'), 
                    dataoptions = JSON.parse("{" + attrOptions + "}")), dataoptions) for (p in optionData = void 0, 
                    dataoptions) if ("alias" === p.toLowerCase()) {
                        optionData = dataoptions[p];
                        break;
                    }
                    for (option in importOption("alias", optionData), userOptions.alias && resolveAlias(userOptions.alias, userOptions, opts), 
                    opts) {
                        if (dataoptions) for (p in optionData = void 0, dataoptions) if (p.toLowerCase() === option.toLowerCase()) {
                            optionData = dataoptions[p];
                            break;
                        }
                        importOption(option, optionData);
                    }
                }
                return _inputmask.default.extend(!0, opts, userOptions), "rtl" !== npt.dir && !opts.rightAlign || (npt.style.textAlign = "right"), 
                "rtl" !== npt.dir && !opts.numericInput || (npt.dir = "ltr", npt.removeAttribute("dir"), 
                opts.isRTL = !0), Object.keys(userOptions).length;
            }
            Inputmask.prototype = {
                dataAttribute: "data-inputmask",
                defaults: _defaults.default,
                definitions: _definitions.default,
                aliases: {},
                masksCache: {},
                get isRTL() {
                    return this.opts.isRTL || this.opts.numericInput;
                },
                mask: function mask(elems) {
                    var that = this;
                    return "string" == typeof elems && (elems = document.getElementById(elems) || document.querySelectorAll(elems)), 
                    elems = elems.nodeName ? [ elems ] : elems, elems.forEach(function(el, ndx) {
                        var scopedOpts = _inputmask.default.extend(!0, {}, that.opts);
                        if (importAttributeOptions(el, scopedOpts, _inputmask.default.extend(!0, {}, that.userOptions), that.dataAttribute)) {
                            var maskset = (0, _maskLexer.generateMaskSet)(scopedOpts, that.noMasksCache);
                            void 0 !== maskset && (void 0 !== el.inputmask && (el.inputmask.opts.autoUnmask = !0, 
                            el.inputmask.remove()), el.inputmask = new Inputmask(void 0, void 0, !0), el.inputmask.opts = scopedOpts, 
                            el.inputmask.noMasksCache = that.noMasksCache, el.inputmask.userOptions = _inputmask.default.extend(!0, {}, that.userOptions), 
                            el.inputmask.el = el, el.inputmask.$el = (0, _inputmask.default)(el), el.inputmask.maskset = maskset, 
                            _inputmask.default.data(el, dataKey, that.userOptions), _mask.mask.call(el.inputmask));
                        }
                    }), elems && elems[0] && elems[0].inputmask || this;
                },
                option: function option(options, noremask) {
                    return "string" == typeof options ? this.opts[options] : "object" === _typeof(options) ? (_inputmask.default.extend(this.userOptions, options), 
                    this.el && !0 !== noremask && this.mask(this.el), this) : void 0;
                },
                unmaskedvalue: function unmaskedvalue(value) {
                    if (this.maskset = this.maskset || (0, _maskLexer.generateMaskSet)(this.opts, this.noMasksCache), 
                    void 0 === this.el || void 0 !== value) {
                        var valueBuffer = ("function" == typeof this.opts.onBeforeMask && this.opts.onBeforeMask.call(this, value, this.opts) || value).split("");
                        _inputHandling.checkVal.call(this, void 0, !1, !1, valueBuffer), "function" == typeof this.opts.onBeforeWrite && this.opts.onBeforeWrite.call(this, void 0, _positioning.getBuffer.call(this), 0, this.opts);
                    }
                    return _inputHandling.unmaskedvalue.call(this, this.el);
                },
                remove: function remove() {
                    if (this.el) {
                        _inputmask.default.data(this.el, dataKey, null);
                        var cv = this.opts.autoUnmask ? (0, _inputHandling.unmaskedvalue)(this.el) : this._valueGet(this.opts.autoUnmask), valueProperty;
                        cv !== _positioning.getBufferTemplate.call(this).join("") ? this._valueSet(cv, this.opts.autoUnmask) : this._valueSet(""), 
                        _eventruler.EventRuler.off(this.el), Object.getOwnPropertyDescriptor && Object.getPrototypeOf ? (valueProperty = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this.el), "value"), 
                        valueProperty && this.__valueGet && Object.defineProperty(this.el, "value", {
                            get: this.__valueGet,
                            set: this.__valueSet,
                            configurable: !0
                        })) : document.__lookupGetter__ && this.el.__lookupGetter__("value") && this.__valueGet && (this.el.__defineGetter__("value", this.__valueGet), 
                        this.el.__defineSetter__("value", this.__valueSet)), this.el.inputmask = void 0;
                    }
                    return this.el;
                },
                getemptymask: function getemptymask() {
                    return this.maskset = this.maskset || (0, _maskLexer.generateMaskSet)(this.opts, this.noMasksCache), 
                    _positioning.getBufferTemplate.call(this).join("");
                },
                hasMaskedValue: function hasMaskedValue() {
                    return !this.opts.autoUnmask;
                },
                isComplete: function isComplete() {
                    return this.maskset = this.maskset || (0, _maskLexer.generateMaskSet)(this.opts, this.noMasksCache), 
                    _validation.isComplete.call(this, _positioning.getBuffer.call(this));
                },
                getmetadata: function getmetadata() {
                    if (this.maskset = this.maskset || (0, _maskLexer.generateMaskSet)(this.opts, this.noMasksCache), 
                    Array.isArray(this.maskset.metadata)) {
                        var maskTarget = _validationTests.getMaskTemplate.call(this, !0, 0, !1).join("");
                        return this.maskset.metadata.forEach(function(mtdt) {
                            return mtdt.mask !== maskTarget || (maskTarget = mtdt, !1);
                        }), maskTarget;
                    }
                    return this.maskset.metadata;
                },
                isValid: function isValid(value) {
                    if (this.maskset = this.maskset || (0, _maskLexer.generateMaskSet)(this.opts, this.noMasksCache), 
                    value) {
                        var valueBuffer = ("function" == typeof this.opts.onBeforeMask && this.opts.onBeforeMask.call(this, value, this.opts) || value).split("");
                        _inputHandling.checkVal.call(this, void 0, !0, !1, valueBuffer);
                    } else value = this.isRTL ? _positioning.getBuffer.call(this).slice().reverse().join("") : _positioning.getBuffer.call(this).join("");
                    for (var buffer = _positioning.getBuffer.call(this), rl = _positioning.determineLastRequiredPosition.call(this), lmib = buffer.length - 1; rl < lmib && !_positioning.isMask.call(this, lmib); lmib--) ;
                    return buffer.splice(rl, lmib + 1 - rl), _validation.isComplete.call(this, buffer) && value === (this.isRTL ? _positioning.getBuffer.call(this).slice().reverse().join("") : _positioning.getBuffer.call(this).join(""));
                },
                format: function format(value, metadata) {
                    this.maskset = this.maskset || (0, _maskLexer.generateMaskSet)(this.opts, this.noMasksCache);
                    var valueBuffer = ("function" == typeof this.opts.onBeforeMask && this.opts.onBeforeMask.call(this, value, this.opts) || value).split("");
                    _inputHandling.checkVal.call(this, void 0, !0, !1, valueBuffer);
                    var formattedValue = this.isRTL ? _positioning.getBuffer.call(this).slice().reverse().join("") : _positioning.getBuffer.call(this).join("");
                    return metadata ? {
                        value: formattedValue,
                        metadata: this.getmetadata()
                    } : formattedValue;
                },
                setValue: function setValue(value) {
                    this.el && (0, _inputmask.default)(this.el).trigger("setvalue", [ value ]);
                },
                analyseMask: _maskLexer.analyseMask
            }, Inputmask.extendDefaults = function(options) {
                _inputmask.default.extend(!0, Inputmask.prototype.defaults, options);
            }, Inputmask.extendDefinitions = function(definition) {
                _inputmask.default.extend(!0, Inputmask.prototype.definitions, definition);
            }, Inputmask.extendAliases = function(alias) {
                _inputmask.default.extend(!0, Inputmask.prototype.aliases, alias);
            }, Inputmask.format = function(value, options, metadata) {
                return Inputmask(options).format(value, metadata);
            }, Inputmask.unmask = function(value, options) {
                return Inputmask(options).unmaskedvalue(value);
            }, Inputmask.isValid = function(value, options) {
                return Inputmask(options).isValid(value);
            }, Inputmask.remove = function(elems) {
                "string" == typeof elems && (elems = document.getElementById(elems) || document.querySelectorAll(elems)), 
                elems = elems.nodeName ? [ elems ] : elems, elems.forEach(function(el) {
                    el.inputmask && el.inputmask.remove();
                });
            }, Inputmask.setValue = function(elems, value) {
                "string" == typeof elems && (elems = document.getElementById(elems) || document.querySelectorAll(elems)), 
                elems = elems.nodeName ? [ elems ] : elems, elems.forEach(function(el) {
                    el.inputmask ? el.inputmask.setValue(value) : (0, _inputmask.default)(el).trigger("setvalue", [ value ]);
                });
            }, Inputmask.dependencyLib = _inputmask.default, _window.default.Inputmask = Inputmask;
            var _default = Inputmask;
            exports.default = _default;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.caret = caret, exports.determineLastRequiredPosition = determineLastRequiredPosition, 
            exports.determineNewCaretPosition = determineNewCaretPosition, exports.getBuffer = getBuffer, 
            exports.getBufferTemplate = getBufferTemplate, exports.getLastValidPosition = getLastValidPosition, 
            exports.isMask = isMask, exports.resetMaskSet = resetMaskSet, exports.seekNext = seekNext, 
            exports.seekPrevious = seekPrevious, exports.translatePosition = translatePosition;
            var _validationTests = __webpack_require__(3), _validation = __webpack_require__(4), _mask = __webpack_require__(10);
            function caret(input, begin, end, notranslate, isDelete) {
                var inputmask = this, opts = this.opts, range;
                if (void 0 === begin) return "selectionStart" in input && "selectionEnd" in input ? (begin = input.selectionStart, 
                end = input.selectionEnd) : window.getSelection ? (range = window.getSelection().getRangeAt(0), 
                range.commonAncestorContainer.parentNode !== input && range.commonAncestorContainer !== input || (begin = range.startOffset, 
                end = range.endOffset)) : document.selection && document.selection.createRange && (range = document.selection.createRange(), 
                begin = 0 - range.duplicate().moveStart("character", -input.inputmask._valueGet().length), 
                end = begin + range.text.length), {
                    begin: notranslate ? begin : translatePosition.call(this, begin),
                    end: notranslate ? end : translatePosition.call(this, end)
                };
                if (Array.isArray(begin) && (end = this.isRTL ? begin[0] : begin[1], begin = this.isRTL ? begin[1] : begin[0]), 
                void 0 !== begin.begin && (end = this.isRTL ? begin.begin : begin.end, begin = this.isRTL ? begin.end : begin.begin), 
                "number" == typeof begin) {
                    begin = notranslate ? begin : translatePosition.call(this, begin), end = notranslate ? end : translatePosition.call(this, end), 
                    end = "number" == typeof end ? end : begin;
                    var scrollCalc = parseInt(((input.ownerDocument.defaultView || window).getComputedStyle ? (input.ownerDocument.defaultView || window).getComputedStyle(input, null) : input.currentStyle).fontSize) * end;
                    if (input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0, input.inputmask.caretPos = {
                        begin: begin,
                        end: end
                    }, opts.insertModeVisual && !1 === opts.insertMode && begin === end && (isDelete || end++), 
                    input === (input.inputmask.shadowRoot || document).activeElement) if ("setSelectionRange" in input) input.setSelectionRange(begin, end); else if (window.getSelection) {
                        if (range = document.createRange(), void 0 === input.firstChild || null === input.firstChild) {
                            var textNode = document.createTextNode("");
                            input.appendChild(textNode);
                        }
                        range.setStart(input.firstChild, begin < input.inputmask._valueGet().length ? begin : input.inputmask._valueGet().length), 
                        range.setEnd(input.firstChild, end < input.inputmask._valueGet().length ? end : input.inputmask._valueGet().length), 
                        range.collapse(!0);
                        var sel = window.getSelection();
                        sel.removeAllRanges(), sel.addRange(range);
                    } else input.createTextRange && (range = input.createTextRange(), range.collapse(!0), 
                    range.moveEnd("character", end), range.moveStart("character", begin), range.select());
                }
            }
            function determineLastRequiredPosition(returnDefinition) {
                var inputmask = this, maskset = this.maskset, $ = this.dependencyLib, buffer = _validationTests.getMaskTemplate.call(this, !0, getLastValidPosition.call(this), !0, !0), bl = buffer.length, pos, lvp = getLastValidPosition.call(this), positions = {}, lvTest = maskset.validPositions[lvp], ndxIntlzr = void 0 !== lvTest ? lvTest.locator.slice() : void 0, testPos;
                for (pos = lvp + 1; pos < buffer.length; pos++) testPos = _validationTests.getTestTemplate.call(this, pos, ndxIntlzr, pos - 1), 
                ndxIntlzr = testPos.locator.slice(), positions[pos] = $.extend(!0, {}, testPos);
                var lvTestAlt = lvTest && void 0 !== lvTest.alternation ? lvTest.locator[lvTest.alternation] : void 0;
                for (pos = bl - 1; lvp < pos && (testPos = positions[pos], (testPos.match.optionality || testPos.match.optionalQuantifier && testPos.match.newBlockMarker || lvTestAlt && (lvTestAlt !== positions[pos].locator[lvTest.alternation] && 1 != testPos.match.static || !0 === testPos.match.static && testPos.locator[lvTest.alternation] && _validation.checkAlternationMatch.call(this, testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.toString().split(",")) && "" !== _validationTests.getTests.call(this, pos)[0].def)) && buffer[pos] === _validationTests.getPlaceholder.call(this, pos, testPos.match)); pos--) bl--;
                return returnDefinition ? {
                    l: bl,
                    def: positions[bl] ? positions[bl].match : void 0
                } : bl;
            }
            function determineNewCaretPosition(selectedCaret, tabbed) {
                var inputmask = this, maskset = this.maskset, opts = this.opts;
                function doRadixFocus(clickPos) {
                    if ("" !== opts.radixPoint && 0 !== opts.digits) {
                        var vps = maskset.validPositions;
                        if (void 0 === vps[clickPos] || vps[clickPos].input === _validationTests.getPlaceholder.call(inputmask, clickPos)) {
                            if (clickPos < seekNext.call(inputmask, -1)) return !0;
                            var radixPos = getBuffer.call(inputmask).indexOf(opts.radixPoint);
                            if (-1 !== radixPos) {
                                for (var vp in vps) if (vps[vp] && radixPos < vp && vps[vp].input !== _validationTests.getPlaceholder.call(inputmask, vp)) return !1;
                                return !0;
                            }
                        }
                    }
                    return !1;
                }
                if (tabbed && (inputmask.isRTL ? selectedCaret.end = selectedCaret.begin : selectedCaret.begin = selectedCaret.end), 
                selectedCaret.begin === selectedCaret.end) {
                    switch (opts.positionCaretOnClick) {
                      case "none":
                        break;
    
                      case "select":
                        selectedCaret = {
                            begin: 0,
                            end: getBuffer.call(inputmask).length
                        };
                        break;
    
                      case "ignore":
                        selectedCaret.end = selectedCaret.begin = seekNext.call(inputmask, getLastValidPosition.call(inputmask));
                        break;
    
                      case "radixFocus":
                        if (doRadixFocus(selectedCaret.begin)) {
                            var radixPos = getBuffer.call(inputmask).join("").indexOf(opts.radixPoint);
                            selectedCaret.end = selectedCaret.begin = opts.numericInput ? seekNext.call(inputmask, radixPos) : radixPos;
                            break;
                        }
    
                      default:
                        var clickPosition = selectedCaret.begin, lvclickPosition = getLastValidPosition.call(inputmask, clickPosition, !0), lastPosition = seekNext.call(inputmask, -1 !== lvclickPosition || isMask.call(inputmask, 0) ? lvclickPosition : -1);
                        if (clickPosition <= lastPosition) selectedCaret.end = selectedCaret.begin = isMask.call(inputmask, clickPosition, !1, !0) ? clickPosition : seekNext.call(inputmask, clickPosition); else {
                            var lvp = maskset.validPositions[lvclickPosition], tt = _validationTests.getTestTemplate.call(inputmask, lastPosition, lvp ? lvp.match.locator : void 0, lvp), placeholder = _validationTests.getPlaceholder.call(inputmask, lastPosition, tt.match);
                            if ("" !== placeholder && getBuffer.call(inputmask)[lastPosition] !== placeholder && !0 !== tt.match.optionalQuantifier && !0 !== tt.match.newBlockMarker || !isMask.call(inputmask, lastPosition, opts.keepStatic, !0) && tt.match.def === placeholder) {
                                var newPos = seekNext.call(inputmask, lastPosition);
                                (newPos <= clickPosition || clickPosition === lastPosition) && (lastPosition = newPos);
                            }
                            selectedCaret.end = selectedCaret.begin = lastPosition;
                        }
                    }
                    return selectedCaret;
                }
            }
            function getBuffer(noCache) {
                var inputmask = this, maskset = this.maskset;
                return void 0 !== maskset.buffer && !0 !== noCache || (maskset.buffer = _validationTests.getMaskTemplate.call(this, !0, getLastValidPosition.call(this), !0), 
                void 0 === maskset._buffer && (maskset._buffer = maskset.buffer.slice())), maskset.buffer;
            }
            function getBufferTemplate() {
                var inputmask = this, maskset = this.maskset;
                return void 0 === maskset._buffer && (maskset._buffer = _validationTests.getMaskTemplate.call(this, !1, 1), 
                void 0 === maskset.buffer && (maskset.buffer = maskset._buffer.slice())), maskset._buffer;
            }
            function getLastValidPosition(closestTo, strict, validPositions) {
                var maskset = this.maskset, before = -1, after = -1, valids = validPositions || maskset.validPositions;
                for (var posNdx in void 0 === closestTo && (closestTo = -1), valids) {
                    var psNdx = parseInt(posNdx);
                    valids[psNdx] && (strict || !0 !== valids[psNdx].generatedInput) && (psNdx <= closestTo && (before = psNdx), 
                    closestTo <= psNdx && (after = psNdx));
                }
                return -1 === before || before == closestTo ? after : -1 == after ? before : closestTo - before < after - closestTo ? before : after;
            }
            function isMask(pos, strict, fuzzy) {
                var inputmask = this, maskset = this.maskset, test = _validationTests.getTestTemplate.call(this, pos).match;
                if ("" === test.def && (test = _validationTests.getTest.call(this, pos).match), 
                !0 !== test.static) return test.fn;
                if (!0 === fuzzy && void 0 !== maskset.validPositions[pos] && !0 !== maskset.validPositions[pos].generatedInput) return !0;
                if (!0 !== strict && -1 < pos) {
                    if (fuzzy) {
                        var tests = _validationTests.getTests.call(this, pos);
                        return tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0);
                    }
                    var testTemplate = _validationTests.determineTestTemplate.call(this, pos, _validationTests.getTests.call(this, pos)), testPlaceHolder = _validationTests.getPlaceholder.call(this, pos, testTemplate.match);
                    return testTemplate.match.def !== testPlaceHolder;
                }
                return !1;
            }
            function resetMaskSet(soft) {
                var maskset = this.maskset;
                maskset.buffer = void 0, !0 !== soft && (maskset.validPositions = {}, maskset.p = 0);
            }
            function seekNext(pos, newBlock, fuzzy) {
                var inputmask = this;
                void 0 === fuzzy && (fuzzy = !0);
                for (var position = pos + 1; "" !== _validationTests.getTest.call(this, position).match.def && (!0 === newBlock && (!0 !== _validationTests.getTest.call(this, position).match.newBlockMarker || !isMask.call(this, position, void 0, !0)) || !0 !== newBlock && !isMask.call(this, position, void 0, fuzzy)); ) position++;
                return position;
            }
            function seekPrevious(pos, newBlock) {
                var inputmask = this, position = pos - 1;
                if (pos <= 0) return 0;
                for (;0 < position && (!0 === newBlock && (!0 !== _validationTests.getTest.call(this, position).match.newBlockMarker || !isMask.call(this, position, void 0, !0)) || !0 !== newBlock && !isMask.call(this, position, void 0, !0)); ) position--;
                return position;
            }
            function translatePosition(pos) {
                var inputmask = this, opts = this.opts, el = this.el;
                return !this.isRTL || "number" != typeof pos || opts.greedy && "" === opts.placeholder || !el || (pos = this._valueGet().length - pos), 
                pos;
            }
        }, function(module, exports, __webpack_require__) {
            "use strict";
            function getLocator(tst, align) {
                var locator = (null != tst.alternation ? tst.mloc[getDecisionTaker(tst)] : tst.locator).join("");
                if ("" !== locator) for (;locator.length < align; ) locator += "0";
                return locator;
            }
            function getDecisionTaker(tst) {
                var decisionTaker = tst.locator[tst.alternation];
                return "string" == typeof decisionTaker && 0 < decisionTaker.length && (decisionTaker = decisionTaker.split(",")[0]), 
                void 0 !== decisionTaker ? decisionTaker.toString() : "";
            }
            function getPlaceholder(pos, test, returnPL) {
                var inputmask = this, opts = this.opts, maskset = this.maskset;
                if (test = test || getTest.call(this, pos).match, void 0 !== test.placeholder || !0 === returnPL) return "function" == typeof test.placeholder ? test.placeholder(opts) : test.placeholder;
                if (!0 !== test.static) return opts.placeholder.charAt(pos % opts.placeholder.length);
                if (-1 < pos && void 0 === maskset.validPositions[pos]) {
                    var tests = getTests.call(this, pos), staticAlternations = [], prevTest;
                    if (tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0)) for (var i = 0; i < tests.length; i++) if ("" !== tests[i].match.def && !0 !== tests[i].match.optionality && !0 !== tests[i].match.optionalQuantifier && (!0 === tests[i].match.static || void 0 === prevTest || !1 !== tests[i].match.fn.test(prevTest.match.def, maskset, pos, !0, opts)) && (staticAlternations.push(tests[i]), 
                    !0 === tests[i].match.static && (prevTest = tests[i]), 1 < staticAlternations.length && /[0-9a-bA-Z]/.test(staticAlternations[0].match.def))) return opts.placeholder.charAt(pos % opts.placeholder.length);
                }
                return test.def;
            }
            function getMaskTemplate(baseOnInput, minimalPos, includeMode, noJit, clearOptionalTail) {
                var inputmask = this, opts = this.opts, maskset = this.maskset, greedy = opts.greedy;
                clearOptionalTail && (opts.greedy = !1), minimalPos = minimalPos || 0;
                var maskTemplate = [], ndxIntlzr, pos = 0, test, testPos, jitRenderStatic;
                do {
                    if (!0 === baseOnInput && maskset.validPositions[pos]) testPos = clearOptionalTail && !0 === maskset.validPositions[pos].match.optionality && void 0 === maskset.validPositions[pos + 1] && (!0 === maskset.validPositions[pos].generatedInput || maskset.validPositions[pos].input == opts.skipOptionalPartCharacter && 0 < pos) ? determineTestTemplate.call(this, pos, getTests.call(this, pos, ndxIntlzr, pos - 1)) : maskset.validPositions[pos], 
                    test = testPos.match, ndxIntlzr = testPos.locator.slice(), maskTemplate.push(!0 === includeMode ? testPos.input : !1 === includeMode ? test.nativeDef : getPlaceholder.call(this, pos, test)); else {
                        testPos = getTestTemplate.call(this, pos, ndxIntlzr, pos - 1), test = testPos.match, 
                        ndxIntlzr = testPos.locator.slice();
                        var jitMasking = !0 !== noJit && (!1 !== opts.jitMasking ? opts.jitMasking : test.jit);
                        jitRenderStatic = jitRenderStatic && test.static && test.def !== opts.groupSeparator && null === test.fn || maskset.validPositions[pos - 1] && test.static && test.def !== opts.groupSeparator && null === test.fn, 
                        jitRenderStatic || !1 === jitMasking || void 0 === jitMasking || "number" == typeof jitMasking && isFinite(jitMasking) && pos < jitMasking ? maskTemplate.push(!1 === includeMode ? test.nativeDef : getPlaceholder.call(this, pos, test)) : jitRenderStatic = !1;
                    }
                    pos++;
                } while ((void 0 === this.maxLength || pos < this.maxLength) && (!0 !== test.static || "" !== test.def) || pos < minimalPos);
                return "" === maskTemplate[maskTemplate.length - 1] && maskTemplate.pop(), !1 === includeMode && void 0 !== maskset.maskLength || (maskset.maskLength = pos - 1), 
                opts.greedy = greedy, maskTemplate;
            }
            function getTestTemplate(pos, ndxIntlzr, tstPs) {
                var inputmask = this, maskset = this.maskset;
                return maskset.validPositions[pos] || determineTestTemplate.call(this, pos, getTests.call(this, pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs));
            }
            function determineTestTemplate(pos, tests) {
                var inputmask = this, opts = this.opts;
                pos = 0 < pos ? pos - 1 : 0;
                for (var altTest = getTest.call(this, pos), targetLocator = getLocator(altTest), tstLocator, closest, bestMatch, ndx = 0; ndx < tests.length; ndx++) {
                    var tst = tests[ndx];
                    tstLocator = getLocator(tst, targetLocator.length);
                    var distance = Math.abs(tstLocator - targetLocator);
                    (void 0 === closest || "" !== tstLocator && distance < closest || bestMatch && !opts.greedy && bestMatch.match.optionality && "master" === bestMatch.match.newBlockMarker && (!tst.match.optionality || !tst.match.newBlockMarker) || bestMatch && bestMatch.match.optionalQuantifier && !tst.match.optionalQuantifier) && (closest = distance, 
                    bestMatch = tst);
                }
                return bestMatch;
            }
            function getTest(pos, tests) {
                var inputmask = this, maskset = this.maskset;
                return maskset.validPositions[pos] ? maskset.validPositions[pos] : (tests || getTests.call(this, pos))[0];
            }
            function getTests(pos, ndxIntlzr, tstPs) {
                var inputmask = this, $ = this.dependencyLib, maskset = this.maskset, opts = this.opts, el = this.el, maskTokens = maskset.maskToken, testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [ 0 ], matches = [], insertStop = !1, latestMatch, cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : "";
                function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) {
                    function handleMatch(match, loopNdx, quantifierRecurse) {
                        function isFirstMatch(latestMatch, tokenGroup) {
                            var firstMatch = 0 === tokenGroup.matches.indexOf(latestMatch);
                            return firstMatch || tokenGroup.matches.every(function(match, ndx) {
                                return !0 === match.isQuantifier ? firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]) : Object.prototype.hasOwnProperty.call(match, "matches") && (firstMatch = isFirstMatch(latestMatch, match)), 
                                !firstMatch;
                            }), firstMatch;
                        }
                        function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {
                            var bestMatch, indexPos;
                            if ((maskset.tests[pos] || maskset.validPositions[pos]) && (maskset.tests[pos] || [ maskset.validPositions[pos] ]).every(function(lmnt, ndx) {
                                if (lmnt.mloc[alternateNdx]) return bestMatch = lmnt, !1;
                                var alternation = void 0 !== targetAlternation ? targetAlternation : lmnt.alternation, ndxPos = void 0 !== lmnt.locator[alternation] ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1;
                                return (void 0 === indexPos || ndxPos < indexPos) && -1 !== ndxPos && (bestMatch = lmnt, 
                                indexPos = ndxPos), !0;
                            }), bestMatch) {
                                var bestMatchAltIndex = bestMatch.locator[bestMatch.alternation], locator = bestMatch.mloc[alternateNdx] || bestMatch.mloc[bestMatchAltIndex] || bestMatch.locator;
                                return locator.slice((void 0 !== targetAlternation ? targetAlternation : bestMatch.alternation) + 1);
                            }
                            return void 0 !== targetAlternation ? resolveNdxInitializer(pos, alternateNdx) : void 0;
                        }
                        function isSubsetOf(source, target) {
                            function expand(pattern) {
                                for (var expanded = [], start = -1, end, i = 0, l = pattern.length; i < l; i++) if ("-" === pattern.charAt(i)) for (end = pattern.charCodeAt(i + 1); ++start < end; ) expanded.push(String.fromCharCode(start)); else start = pattern.charCodeAt(i), 
                                expanded.push(pattern.charAt(i));
                                return expanded.join("");
                            }
                            return source.match.def === target.match.nativeDef || !(!(opts.regex || source.match.fn instanceof RegExp && target.match.fn instanceof RegExp) || !0 === source.match.static || !0 === target.match.static) && -1 !== expand(target.match.fn.toString().replace(/[[\]/]/g, "")).indexOf(expand(source.match.fn.toString().replace(/[[\]/]/g, "")));
                        }
                        function staticCanMatchDefinition(source, target) {
                            return !0 === source.match.static && !0 !== target.match.static && target.match.fn.test(source.match.def, maskset, pos, !1, opts, !1);
                        }
                        function setMergeLocators(targetMatch, altMatch) {
                            var alternationNdx = targetMatch.alternation, shouldMerge = void 0 === altMatch || alternationNdx === altMatch.alternation && -1 === targetMatch.locator[alternationNdx].toString().indexOf(altMatch.locator[alternationNdx]);
                            if (!shouldMerge && alternationNdx > altMatch.alternation) for (var i = altMatch.alternation; i < alternationNdx; i++) if (targetMatch.locator[i] !== altMatch.locator[i]) {
                                alternationNdx = i, shouldMerge = !0;
                                break;
                            }
                            if (shouldMerge) {
                                targetMatch.mloc = targetMatch.mloc || {};
                                var locNdx = targetMatch.locator[alternationNdx];
                                if (void 0 !== locNdx) {
                                    if ("string" == typeof locNdx && (locNdx = locNdx.split(",")[0]), void 0 === targetMatch.mloc[locNdx] && (targetMatch.mloc[locNdx] = targetMatch.locator.slice()), 
                                    void 0 !== altMatch) {
                                        for (var ndx in altMatch.mloc) "string" == typeof ndx && (ndx = ndx.split(",")[0]), 
                                        void 0 === targetMatch.mloc[ndx] && (targetMatch.mloc[ndx] = altMatch.mloc[ndx]);
                                        targetMatch.locator[alternationNdx] = Object.keys(targetMatch.mloc).join(",");
                                    }
                                    return !0;
                                }
                                targetMatch.alternation = void 0;
                            }
                            return !1;
                        }
                        function isSameLevel(targetMatch, altMatch) {
                            if (targetMatch.locator.length !== altMatch.locator.length) return !1;
                            for (var locNdx = targetMatch.alternation + 1; locNdx < targetMatch.locator.length; locNdx++) if (targetMatch.locator[locNdx] !== altMatch.locator[locNdx]) return !1;
                            return !0;
                        }
                        if (testPos > pos + opts._maxTestPos) throw "Inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + maskset.mask;
                        if (testPos === pos && void 0 === match.matches) return matches.push({
                            match: match,
                            locator: loopNdx.reverse(),
                            cd: cacheDependency,
                            mloc: {}
                        }), !0;
                        if (void 0 !== match.matches) {
                            if (match.isGroup && quantifierRecurse !== match) {
                                if (match = handleMatch(maskToken.matches[maskToken.matches.indexOf(match) + 1], loopNdx, quantifierRecurse), 
                                match) return !0;
                            } else if (match.isOptional) {
                                var optionalToken = match, mtchsNdx = matches.length;
                                if (match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse), 
                                match) {
                                    if (matches.forEach(function(mtch, ndx) {
                                        mtchsNdx <= ndx && (mtch.match.optionality = !0);
                                    }), latestMatch = matches[matches.length - 1].match, void 0 !== quantifierRecurse || !isFirstMatch(latestMatch, optionalToken)) return !0;
                                    insertStop = !0, testPos = pos;
                                }
                            } else if (match.isAlternator) {
                                var alternateToken = match, malternateMatches = [], maltMatches, currentMatches = matches.slice(), loopNdxCnt = loopNdx.length, altIndex = 0 < ndxInitializer.length ? ndxInitializer.shift() : -1;
                                if (-1 === altIndex || "string" == typeof altIndex) {
                                    var currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr = [], amndx;
                                    if ("string" == typeof altIndex) altIndexArr = altIndex.split(","); else for (amndx = 0; amndx < alternateToken.matches.length; amndx++) altIndexArr.push(amndx.toString());
                                    if (void 0 !== maskset.excludes[pos]) {
                                        for (var altIndexArrClone = altIndexArr.slice(), i = 0, exl = maskset.excludes[pos].length; i < exl; i++) {
                                            var excludeSet = maskset.excludes[pos][i].toString().split(":");
                                            loopNdx.length == excludeSet[1] && altIndexArr.splice(altIndexArr.indexOf(excludeSet[0]), 1);
                                        }
                                        0 === altIndexArr.length && (delete maskset.excludes[pos], altIndexArr = altIndexArrClone);
                                    }
                                    (!0 === opts.keepStatic || isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic) && (altIndexArr = altIndexArr.slice(0, 1));
                                    for (var unMatchedAlternation = !1, ndx = 0; ndx < altIndexArr.length; ndx++) {
                                        amndx = parseInt(altIndexArr[ndx]), matches = [], ndxInitializer = "string" == typeof altIndex && resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice(), 
                                        alternateToken.matches[amndx] && handleMatch(alternateToken.matches[amndx], [ amndx ].concat(loopNdx), quantifierRecurse) ? match = !0 : 0 === ndx && (unMatchedAlternation = !0), 
                                        maltMatches = matches.slice(), testPos = currentPos, matches = [];
                                        for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
                                            var altMatch = maltMatches[ndx1], dropMatch = !1;
                                            altMatch.match.jit = altMatch.match.jit || unMatchedAlternation, altMatch.alternation = altMatch.alternation || loopNdxCnt, 
                                            setMergeLocators(altMatch);
                                            for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
                                                var altMatch2 = malternateMatches[ndx2];
                                                if ("string" != typeof altIndex || void 0 !== altMatch.alternation && altIndexArr.includes(altMatch.locator[altMatch.alternation].toString())) {
                                                    if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {
                                                        dropMatch = !0, setMergeLocators(altMatch2, altMatch);
                                                        break;
                                                    }
                                                    if (isSubsetOf(altMatch, altMatch2)) {
                                                        setMergeLocators(altMatch, altMatch2) && (dropMatch = !0, malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch));
                                                        break;
                                                    }
                                                    if (isSubsetOf(altMatch2, altMatch)) {
                                                        setMergeLocators(altMatch2, altMatch);
                                                        break;
                                                    }
                                                    if (staticCanMatchDefinition(altMatch, altMatch2)) {
                                                        isSameLevel(altMatch, altMatch2) || void 0 !== el.inputmask.userOptions.keepStatic ? setMergeLocators(altMatch, altMatch2) && (dropMatch = !0, 
                                                        malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch)) : opts.keepStatic = !0;
                                                        break;
                                                    }
                                                }
                                            }
                                            dropMatch || malternateMatches.push(altMatch);
                                        }
                                    }
                                    matches = currentMatches.concat(malternateMatches), testPos = pos, insertStop = 0 < matches.length, 
                                    match = 0 < malternateMatches.length, ndxInitializer = ndxInitializerClone.slice();
                                } else match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [ altIndex ].concat(loopNdx), quantifierRecurse);
                                if (match) return !0;
                            } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[maskToken.matches.indexOf(match) - 1]) for (var qt = match, qndx = 0 < ndxInitializer.length ? ndxInitializer.shift() : 0; qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max) && testPos <= pos; qndx++) {
                                var tokenGroup = maskToken.matches[maskToken.matches.indexOf(qt) - 1];
                                if (match = handleMatch(tokenGroup, [ qndx ].concat(loopNdx), tokenGroup), match) {
                                    if (latestMatch = matches[matches.length - 1].match, latestMatch.optionalQuantifier = qndx >= qt.quantifier.min, 
                                    latestMatch.jit = (qndx || 1) * tokenGroup.matches.indexOf(latestMatch) >= qt.quantifier.jit, 
                                    latestMatch.optionalQuantifier && isFirstMatch(latestMatch, tokenGroup)) {
                                        insertStop = !0, testPos = pos;
                                        break;
                                    }
                                    return latestMatch.jit && (maskset.jitOffset[pos] = tokenGroup.matches.length - tokenGroup.matches.indexOf(latestMatch)), 
                                    !0;
                                }
                            } else if (match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse), 
                            match) return !0;
                        } else testPos++;
                    }
                    for (var tndx = 0 < ndxInitializer.length ? ndxInitializer.shift() : 0; tndx < maskToken.matches.length; tndx++) if (!0 !== maskToken.matches[tndx].isQuantifier) {
                        var match = handleMatch(maskToken.matches[tndx], [ tndx ].concat(loopNdx), quantifierRecurse);
                        if (match && testPos === pos) return match;
                        if (pos < testPos) break;
                    }
                }
                function mergeLocators(pos, tests) {
                    var locator = [], alternation;
                    return Array.isArray(tests) || (tests = [ tests ]), 0 < tests.length && (void 0 === tests[0].alternation || !0 === opts.keepStatic ? (locator = determineTestTemplate.call(inputmask, pos, tests.slice()).locator.slice(), 
                    0 === locator.length && (locator = tests[0].locator.slice())) : tests.forEach(function(tst) {
                        "" !== tst.def && (0 === locator.length ? (alternation = tst.alternation, locator = tst.locator.slice()) : tst.locator[alternation] && -1 === locator[alternation].toString().indexOf(tst.locator[alternation]) && (locator[alternation] += "," + tst.locator[alternation]));
                    })), locator;
                }
                if (-1 < pos && (void 0 === inputmask.maxLength || pos < inputmask.maxLength)) {
                    if (void 0 === ndxIntlzr) {
                        for (var previousPos = pos - 1, test; void 0 === (test = maskset.validPositions[previousPos] || maskset.tests[previousPos]) && -1 < previousPos; ) previousPos--;
                        void 0 !== test && -1 < previousPos && (ndxInitializer = mergeLocators(previousPos, test), 
                        cacheDependency = ndxInitializer.join(""), testPos = previousPos);
                    }
                    if (maskset.tests[pos] && maskset.tests[pos][0].cd === cacheDependency) return maskset.tests[pos];
                    for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length; mtndx++) {
                        var match = resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [ mtndx ]);
                        if (match && testPos === pos || pos < testPos) break;
                    }
                }
                return 0 !== matches.length && !insertStop || matches.push({
                    match: {
                        fn: null,
                        static: !0,
                        optionality: !1,
                        casing: null,
                        def: "",
                        placeholder: ""
                    },
                    locator: [],
                    mloc: {},
                    cd: cacheDependency
                }), void 0 !== ndxIntlzr && maskset.tests[pos] ? $.extend(!0, [], matches) : (maskset.tests[pos] = $.extend(!0, [], matches), 
                maskset.tests[pos]);
            }
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.determineTestTemplate = determineTestTemplate, exports.getDecisionTaker = getDecisionTaker, 
            exports.getMaskTemplate = getMaskTemplate, exports.getPlaceholder = getPlaceholder, 
            exports.getTest = getTest, exports.getTests = getTests, exports.getTestTemplate = getTestTemplate;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.alternate = alternate, exports.checkAlternationMatch = checkAlternationMatch, 
            exports.isComplete = isComplete, exports.isValid = isValid, exports.refreshFromBuffer = refreshFromBuffer, 
            exports.revalidateMask = revalidateMask, exports.handleRemove = handleRemove;
            var _validationTests = __webpack_require__(3), _keycode = _interopRequireDefault(__webpack_require__(0)), _positioning = __webpack_require__(2), _eventhandlers = __webpack_require__(6);
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            function alternate(maskPos, c, strict, fromIsValid, rAltPos, selection) {
                var inputmask = this, $ = this.dependencyLib, opts = this.opts, maskset = this.maskset, validPsClone = $.extend(!0, {}, maskset.validPositions), tstClone = $.extend(!0, {}, maskset.tests), lastAlt, alternation, isValidRslt = !1, returnRslt = !1, altPos, prevAltPos, i, validPos, decisionPos, lAltPos = void 0 !== rAltPos ? rAltPos : _positioning.getLastValidPosition.call(this), nextPos, input, begin, end;
                if (selection && (begin = selection.begin, end = selection.end, selection.begin > selection.end && (begin = selection.end, 
                end = selection.begin)), -1 === lAltPos && void 0 === rAltPos) lastAlt = 0, prevAltPos = _validationTests.getTest.call(this, lastAlt), 
                alternation = prevAltPos.alternation; else for (;0 <= lAltPos; lAltPos--) if (altPos = maskset.validPositions[lAltPos], 
                altPos && void 0 !== altPos.alternation) {
                    if (prevAltPos && prevAltPos.locator[altPos.alternation] !== altPos.locator[altPos.alternation]) break;
                    lastAlt = lAltPos, alternation = maskset.validPositions[lastAlt].alternation, prevAltPos = altPos;
                }
                if (void 0 !== alternation) {
                    decisionPos = parseInt(lastAlt), maskset.excludes[decisionPos] = maskset.excludes[decisionPos] || [], 
                    !0 !== maskPos && maskset.excludes[decisionPos].push((0, _validationTests.getDecisionTaker)(prevAltPos) + ":" + prevAltPos.alternation);
                    var validInputs = [], resultPos = -1;
                    for (i = decisionPos; i < _positioning.getLastValidPosition.call(this, void 0, !0) + 1; i++) -1 === resultPos && maskPos <= i && void 0 !== c && (validInputs.push(c), 
                    resultPos = validInputs.length - 1), validPos = maskset.validPositions[i], validPos && !0 !== validPos.generatedInput && (void 0 === selection || i < begin || end <= i) && validInputs.push(validPos.input), 
                    delete maskset.validPositions[i];
                    for (-1 === resultPos && void 0 !== c && (validInputs.push(c), resultPos = validInputs.length - 1); void 0 !== maskset.excludes[decisionPos] && maskset.excludes[decisionPos].length < 10; ) {
                        for (maskset.tests = {}, _positioning.resetMaskSet.call(this, !0), isValidRslt = !0, 
                        i = 0; i < validInputs.length && (nextPos = isValidRslt.caret || _positioning.getLastValidPosition.call(this, void 0, !0) + 1, 
                        input = validInputs[i], isValidRslt = isValid.call(this, nextPos, input, !1, fromIsValid, !0)); i++) i === resultPos && (returnRslt = isValidRslt), 
                        1 == maskPos && isValidRslt && (returnRslt = {
                            caretPos: i
                        });
                        if (isValidRslt) break;
                        if (_positioning.resetMaskSet.call(this), prevAltPos = _validationTests.getTest.call(this, decisionPos), 
                        maskset.validPositions = $.extend(!0, {}, validPsClone), maskset.tests = $.extend(!0, {}, tstClone), 
                        !maskset.excludes[decisionPos]) {
                            returnRslt = alternate.call(this, maskPos, c, strict, fromIsValid, decisionPos - 1, selection);
                            break;
                        }
                        var decisionTaker = (0, _validationTests.getDecisionTaker)(prevAltPos);
                        if (-1 !== maskset.excludes[decisionPos].indexOf(decisionTaker + ":" + prevAltPos.alternation)) {
                            returnRslt = alternate.call(this, maskPos, c, strict, fromIsValid, decisionPos - 1, selection);
                            break;
                        }
                        for (maskset.excludes[decisionPos].push(decisionTaker + ":" + prevAltPos.alternation), 
                        i = decisionPos; i < _positioning.getLastValidPosition.call(this, void 0, !0) + 1; i++) delete maskset.validPositions[i];
                    }
                }
                return returnRslt && !1 === opts.keepStatic || delete maskset.excludes[decisionPos], 
                returnRslt;
            }
            function casing(elem, test, pos) {
                var opts = this.opts, maskset = this.maskset;
                switch (opts.casing || test.casing) {
                  case "upper":
                    elem = elem.toUpperCase();
                    break;
    
                  case "lower":
                    elem = elem.toLowerCase();
                    break;
    
                  case "title":
                    var posBefore = maskset.validPositions[pos - 1];
                    elem = 0 === pos || posBefore && posBefore.input === String.fromCharCode(_keycode.default.SPACE) ? elem.toUpperCase() : elem.toLowerCase();
                    break;
    
                  default:
                    if ("function" == typeof opts.casing) {
                        var args = Array.prototype.slice.call(arguments);
                        args.push(maskset.validPositions), elem = opts.casing.apply(this, args);
                    }
                }
                return elem;
            }
            function checkAlternationMatch(altArr1, altArr2, na) {
                for (var opts = this.opts, altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), isMatch = !1, naArr = void 0 !== na ? na.split(",") : [], naNdx, i = 0; i < naArr.length; i++) -1 !== (naNdx = altArr1.indexOf(naArr[i])) && altArr1.splice(naNdx, 1);
                for (var alndx = 0; alndx < altArr1.length; alndx++) if (altArrC.includes(altArr1[alndx])) {
                    isMatch = !0;
                    break;
                }
                return isMatch;
            }
            function handleRemove(input, k, pos, strict, fromIsValid) {
                var inputmask = this, maskset = this.maskset, opts = this.opts;
                if ((opts.numericInput || this.isRTL) && (k === _keycode.default.BACKSPACE ? k = _keycode.default.DELETE : k === _keycode.default.DELETE && (k = _keycode.default.BACKSPACE), 
                this.isRTL)) {
                    var pend = pos.end;
                    pos.end = pos.begin, pos.begin = pend;
                }
                var lvp = _positioning.getLastValidPosition.call(this, void 0, !0), offset;
                if (pos.end >= _positioning.getBuffer.call(this).length && lvp >= pos.end && (pos.end = lvp + 1), 
                k === _keycode.default.BACKSPACE ? pos.end - pos.begin < 1 && (pos.begin = _positioning.seekPrevious.call(this, pos.begin)) : k === _keycode.default.DELETE && pos.begin === pos.end && (pos.end = _positioning.isMask.call(this, pos.end, !0, !0) ? pos.end + 1 : _positioning.seekNext.call(this, pos.end) + 1), 
                !1 !== (offset = revalidateMask.call(this, pos))) {
                    if (!0 !== strict && !1 !== opts.keepStatic || null !== opts.regex && -1 !== _validationTests.getTest.call(this, pos.begin).match.def.indexOf("|")) {
                        var result = alternate.call(this, !0);
                        if (result) {
                            var newPos = void 0 !== result.caret ? result.caret : result.pos ? _positioning.seekNext.call(this, result.pos.begin ? result.pos.begin : result.pos) : _positioning.getLastValidPosition.call(this, -1, !0);
                            (k !== _keycode.default.DELETE || pos.begin > newPos) && pos.begin;
                        }
                    }
                    !0 !== strict && (maskset.p = k === _keycode.default.DELETE ? pos.begin + offset : pos.begin);
                }
            }
            function isComplete(buffer) {
                var inputmask = this, opts = this.opts, maskset = this.maskset;
                if ("function" == typeof opts.isComplete) return opts.isComplete(buffer, opts);
                if ("*" !== opts.repeat) {
                    var complete = !1, lrp = _positioning.determineLastRequiredPosition.call(this, !0), aml = _positioning.seekPrevious.call(this, lrp.l);
                    if (void 0 === lrp.def || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) {
                        complete = !0;
                        for (var i = 0; i <= aml; i++) {
                            var test = _validationTests.getTestTemplate.call(this, i).match;
                            if (!0 !== test.static && void 0 === maskset.validPositions[i] && !0 !== test.optionality && !0 !== test.optionalQuantifier || !0 === test.static && buffer[i] !== _validationTests.getPlaceholder.call(this, i, test)) {
                                complete = !1;
                                break;
                            }
                        }
                    }
                    return complete;
                }
            }
            function isValid(pos, c, strict, fromIsValid, fromAlternate, validateOnly, fromCheckval) {
                var inputmask = this, $ = this.dependencyLib, opts = this.opts, el = inputmask.el, maskset = inputmask.maskset;
                function isSelection(posObj) {
                    return inputmask.isRTL ? 1 < posObj.begin - posObj.end || posObj.begin - posObj.end == 1 : 1 < posObj.end - posObj.begin || posObj.end - posObj.begin == 1;
                }
                strict = !0 === strict;
                var maskPos = pos;
                function processCommandObject(commandObj) {
                    if (void 0 !== commandObj) {
                        if (void 0 !== commandObj.remove && (Array.isArray(commandObj.remove) || (commandObj.remove = [ commandObj.remove ]), 
                        commandObj.remove.sort(function(a, b) {
                            return b.pos - a.pos;
                        }).forEach(function(lmnt) {
                            revalidateMask.call(inputmask, {
                                begin: lmnt,
                                end: lmnt + 1
                            });
                        }), commandObj.remove = void 0), void 0 !== commandObj.insert && (Array.isArray(commandObj.insert) || (commandObj.insert = [ commandObj.insert ]), 
                        commandObj.insert.sort(function(a, b) {
                            return a.pos - b.pos;
                        }).forEach(function(lmnt) {
                            "" !== lmnt.c && isValid.call(inputmask, lmnt.pos, lmnt.c, void 0 === lmnt.strict || lmnt.strict, void 0 !== lmnt.fromIsValid ? lmnt.fromIsValid : fromIsValid);
                        }), commandObj.insert = void 0), commandObj.refreshFromBuffer && commandObj.buffer) {
                            var refresh = commandObj.refreshFromBuffer;
                            refreshFromBuffer.call(inputmask, !0 === refresh ? refresh : refresh.start, refresh.end, commandObj.buffer), 
                            commandObj.refreshFromBuffer = void 0;
                        }
                        void 0 !== commandObj.rewritePosition && (maskPos = commandObj.rewritePosition, 
                        commandObj = !0);
                    }
                    return commandObj;
                }
                function _isValid(position, c, strict) {
                    var rslt = !1;
                    return _validationTests.getTests.call(inputmask, position).every(function(tst, ndx) {
                        var test = tst.match;
                        if (_positioning.getBuffer.call(inputmask, !0), rslt = null != test.fn ? test.fn.test(c, maskset, position, strict, opts, isSelection(pos)) : (c === test.def || c === opts.skipOptionalPartCharacter) && "" !== test.def && {
                            c: _validationTests.getPlaceholder.call(inputmask, position, test, !0) || test.def,
                            pos: position
                        }, !1 === rslt) return !0;
                        var elem = void 0 !== rslt.c ? rslt.c : c, validatedPos = position;
                        return elem = elem === opts.skipOptionalPartCharacter && !0 === test.static ? _validationTests.getPlaceholder.call(inputmask, position, test, !0) || test.def : elem, 
                        rslt = processCommandObject(rslt), !0 !== rslt && void 0 !== rslt.pos && rslt.pos !== position && (validatedPos = rslt.pos), 
                        !0 !== rslt && void 0 === rslt.pos && void 0 === rslt.c || !1 === revalidateMask.call(inputmask, pos, $.extend({}, tst, {
                            input: casing.call(inputmask, elem, test, validatedPos)
                        }), fromIsValid, validatedPos) && (rslt = !1), !1;
                    }), rslt;
                }
                void 0 !== pos.begin && (maskPos = inputmask.isRTL ? pos.end : pos.begin);
                var result = !0, positionsClone = $.extend(!0, {}, maskset.validPositions);
                if (!1 === opts.keepStatic && void 0 !== maskset.excludes[maskPos] && !0 !== fromAlternate && !0 !== fromIsValid) for (var i = maskPos; i < (inputmask.isRTL ? pos.begin : pos.end); i++) void 0 !== maskset.excludes[i] && (maskset.excludes[i] = void 0, 
                delete maskset.tests[i]);
                if ("function" == typeof opts.preValidation && !0 !== fromIsValid && !0 !== validateOnly && (result = opts.preValidation.call(el, _positioning.getBuffer.call(inputmask), maskPos, c, isSelection(pos), opts, maskset, pos, strict || fromAlternate), 
                result = processCommandObject(result)), !0 === result) {
                    if (void 0 === inputmask.maxLength || maskPos < inputmask.maxLength) {
                        if (result = _isValid(maskPos, c, strict), (!strict || !0 === fromIsValid) && !1 === result && !0 !== validateOnly) {
                            var currentPosValid = maskset.validPositions[maskPos];
                            if (!currentPosValid || !0 !== currentPosValid.match.static || currentPosValid.match.def !== c && c !== opts.skipOptionalPartCharacter) {
                                if (opts.insertMode || void 0 === maskset.validPositions[_positioning.seekNext.call(inputmask, maskPos)] || pos.end > maskPos) {
                                    var skip = !1;
                                    if (maskset.jitOffset[maskPos] && void 0 === maskset.validPositions[_positioning.seekNext.call(inputmask, maskPos)] && (result = isValid.call(inputmask, maskPos + maskset.jitOffset[maskPos], c, !0), 
                                    !1 !== result && (!0 !== fromAlternate && (result.caret = maskPos), skip = !0)), 
                                    pos.end > maskPos && (maskset.validPositions[maskPos] = void 0), !skip && !_positioning.isMask.call(inputmask, maskPos, opts.keepStatic && 0 === maskPos)) for (var nPos = maskPos + 1, snPos = _positioning.seekNext.call(inputmask, maskPos, !1, 0 !== maskPos); nPos <= snPos; nPos++) if (result = _isValid(nPos, c, strict), 
                                    !1 !== result) {
                                        result = trackbackPositions.call(inputmask, maskPos, void 0 !== result.pos ? result.pos : nPos) || result, 
                                        maskPos = nPos;
                                        break;
                                    }
                                }
                            } else result = {
                                caret: _positioning.seekNext.call(inputmask, maskPos)
                            };
                        }
                    } else result = !1;
                    !1 !== result || !opts.keepStatic || !isComplete.call(inputmask, _positioning.getBuffer.call(inputmask)) && 0 !== maskPos || strict || !0 === fromAlternate ? isSelection(pos) && maskset.tests[maskPos] && 1 < maskset.tests[maskPos].length && opts.keepStatic && !strict && !0 !== fromAlternate && (result = alternate.call(inputmask, !0)) : result = alternate.call(inputmask, maskPos, c, strict, fromIsValid, void 0, pos), 
                    !0 === result && (result = {
                        pos: maskPos
                    });
                }
                if ("function" == typeof opts.postValidation && !0 !== fromIsValid && !0 !== validateOnly) {
                    var postResult = opts.postValidation.call(el, _positioning.getBuffer.call(inputmask, !0), void 0 !== pos.begin ? inputmask.isRTL ? pos.end : pos.begin : pos, c, result, opts, maskset, strict, fromCheckval);
                    void 0 !== postResult && (result = !0 === postResult ? result : postResult);
                }
                result && void 0 === result.pos && (result.pos = maskPos), !1 === result || !0 === validateOnly ? (_positioning.resetMaskSet.call(inputmask, !0), 
                maskset.validPositions = $.extend(!0, {}, positionsClone)) : trackbackPositions.call(inputmask, void 0, maskPos, !0);
                var endResult = processCommandObject(result);
                return endResult;
            }
            function positionCanMatchDefinition(pos, testDefinition, opts) {
                for (var inputmask = this, maskset = this.maskset, valid = !1, tests = _validationTests.getTests.call(this, pos), tndx = 0; tndx < tests.length; tndx++) {
                    if (tests[tndx].match && (!(tests[tndx].match.nativeDef !== testDefinition.match[opts.shiftPositions ? "def" : "nativeDef"] || opts.shiftPositions && testDefinition.match.static) || tests[tndx].match.nativeDef === testDefinition.match.nativeDef)) {
                        valid = !0;
                        break;
                    }
                    if (tests[tndx].match && tests[tndx].match.def === testDefinition.match.nativeDef) {
                        valid = void 0;
                        break;
                    }
                }
                return !1 === valid && void 0 !== maskset.jitOffset[pos] && (valid = positionCanMatchDefinition.call(this, pos + maskset.jitOffset[pos], testDefinition, opts)), 
                valid;
            }
            function refreshFromBuffer(start, end, buffer) {
                var inputmask = this, maskset = this.maskset, opts = this.opts, $ = this.dependencyLib, el = this.el, i, p, skipOptionalPartCharacter = opts.skipOptionalPartCharacter, bffr = this.isRTL ? buffer.slice().reverse() : buffer;
                if (opts.skipOptionalPartCharacter = "", !0 === start) _positioning.resetMaskSet.call(this), 
                maskset.tests = {}, start = 0, end = buffer.length, p = _positioning.determineNewCaretPosition.call(this, {
                    begin: 0,
                    end: 0
                }, !1).begin; else {
                    for (i = start; i < end; i++) delete maskset.validPositions[i];
                    p = start;
                }
                var keypress = new $.Event("keypress");
                for (i = start; i < end; i++) {
                    keypress.which = bffr[i].toString().charCodeAt(0), this.ignorable = !1;
                    var valResult = _eventhandlers.EventHandlers.keypressEvent.call(el, keypress, !0, !1, !1, p);
                    !1 !== valResult && (p = valResult.forwardPosition);
                }
                opts.skipOptionalPartCharacter = skipOptionalPartCharacter;
            }
            function trackbackPositions(originalPos, newPos, fillOnly) {
                var inputmask = this, maskset = this.maskset, $ = this.dependencyLib;
                if (void 0 === originalPos) for (originalPos = newPos - 1; 0 < originalPos && !maskset.validPositions[originalPos]; originalPos--) ;
                for (var ps = originalPos; ps < newPos; ps++) if (void 0 === maskset.validPositions[ps] && !_positioning.isMask.call(this, ps, !0)) {
                    var vp = 0 == ps ? _validationTests.getTest.call(this, ps) : maskset.validPositions[ps - 1];
                    if (vp) {
                        var tests = _validationTests.getTests.call(this, ps).slice();
                        "" === tests[tests.length - 1].match.def && tests.pop();
                        var bestMatch = _validationTests.determineTestTemplate.call(this, ps, tests), np;
                        if (bestMatch && (!0 !== bestMatch.match.jit || "master" === bestMatch.match.newBlockMarker && (np = maskset.validPositions[ps + 1]) && !0 === np.match.optionalQuantifier) && (bestMatch = $.extend({}, bestMatch, {
                            input: _validationTests.getPlaceholder.call(this, ps, bestMatch.match, !0) || bestMatch.match.def
                        }), bestMatch.generatedInput = !0, revalidateMask.call(this, ps, bestMatch, !0), 
                        !0 !== fillOnly)) {
                            var cvpInput = maskset.validPositions[newPos].input;
                            return maskset.validPositions[newPos] = void 0, isValid.call(this, newPos, cvpInput, !0, !0);
                        }
                    }
                }
            }
            function revalidateMask(pos, validTest, fromIsValid, validatedPos) {
                var inputmask = this, maskset = this.maskset, opts = this.opts, $ = this.dependencyLib;
                function IsEnclosedStatic(pos, valids, selection) {
                    var posMatch = valids[pos];
                    if (void 0 === posMatch || !0 !== posMatch.match.static || !0 === posMatch.match.optionality || void 0 !== valids[0] && void 0 !== valids[0].alternation) return !1;
                    var prevMatch = selection.begin <= pos - 1 ? valids[pos - 1] && !0 === valids[pos - 1].match.static && valids[pos - 1] : valids[pos - 1], nextMatch = selection.end > pos + 1 ? valids[pos + 1] && !0 === valids[pos + 1].match.static && valids[pos + 1] : valids[pos + 1];
                    return prevMatch && nextMatch;
                }
                var offset = 0, begin = void 0 !== pos.begin ? pos.begin : pos, end = void 0 !== pos.end ? pos.end : pos;
                if (pos.begin > pos.end && (begin = pos.end, end = pos.begin), validatedPos = void 0 !== validatedPos ? validatedPos : begin, 
                begin !== end || opts.insertMode && void 0 !== maskset.validPositions[validatedPos] && void 0 === fromIsValid || void 0 === validTest) {
                    var positionsClone = $.extend(!0, {}, maskset.validPositions), lvp = _positioning.getLastValidPosition.call(this, void 0, !0), i;
                    for (maskset.p = begin, i = lvp; begin <= i; i--) delete maskset.validPositions[i], 
                    void 0 === validTest && delete maskset.tests[i + 1];
                    var valid = !0, j = validatedPos, posMatch = j, t, canMatch;
                    for (validTest && (maskset.validPositions[validatedPos] = $.extend(!0, {}, validTest), 
                    posMatch++, j++), i = validTest ? end : end - 1; i <= lvp; i++) {
                        if (void 0 !== (t = positionsClone[i]) && !0 !== t.generatedInput && (end <= i || begin <= i && IsEnclosedStatic(i, positionsClone, {
                            begin: begin,
                            end: end
                        }))) {
                            for (;"" !== _validationTests.getTest.call(this, posMatch).match.def; ) {
                                if (!1 !== (canMatch = positionCanMatchDefinition.call(this, posMatch, t, opts)) || "+" === t.match.def) {
                                    "+" === t.match.def && _positioning.getBuffer.call(this, !0);
                                    var result = isValid.call(this, posMatch, t.input, "+" !== t.match.def, "+" !== t.match.def);
                                    if (valid = !1 !== result, j = (result.pos || posMatch) + 1, !valid && canMatch) break;
                                } else valid = !1;
                                if (valid) {
                                    void 0 === validTest && t.match.static && i === pos.begin && offset++;
                                    break;
                                }
                                if (!valid && posMatch > maskset.maskLength) break;
                                posMatch++;
                            }
                            "" == _validationTests.getTest.call(this, posMatch).match.def && (valid = !1), posMatch = j;
                        }
                        if (!valid) break;
                    }
                    if (!valid) return maskset.validPositions = $.extend(!0, {}, positionsClone), _positioning.resetMaskSet.call(this, !0), 
                    !1;
                } else validTest && _validationTests.getTest.call(this, validatedPos).match.cd === validTest.match.cd && (maskset.validPositions[validatedPos] = $.extend(!0, {}, validTest));
                return _positioning.resetMaskSet.call(this, !0), offset;
            }
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.applyInputValue = applyInputValue, exports.clearOptionalTail = clearOptionalTail, 
            exports.checkVal = checkVal, exports.HandleNativePlaceholder = HandleNativePlaceholder, 
            exports.unmaskedvalue = unmaskedvalue, exports.writeBuffer = writeBuffer;
            var _keycode = _interopRequireDefault(__webpack_require__(0)), _validationTests = __webpack_require__(3), _positioning = __webpack_require__(2), _validation = __webpack_require__(4), _environment = __webpack_require__(7), _eventhandlers = __webpack_require__(6);
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            function applyInputValue(input, value) {
                var inputmask = input ? input.inputmask : this, opts = inputmask.opts;
                input.inputmask.refreshValue = !1, "function" == typeof opts.onBeforeMask && (value = opts.onBeforeMask.call(inputmask, value, opts) || value), 
                value = value.toString().split(""), checkVal(input, !0, !1, value), inputmask.undoValue = _positioning.getBuffer.call(inputmask).join(""), 
                (opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === _positioning.getBufferTemplate.call(inputmask).join("") && -1 === _positioning.getLastValidPosition.call(inputmask) && input.inputmask._valueSet("");
            }
            function clearOptionalTail(buffer) {
                var inputmask = this;
                buffer.length = 0;
                for (var template = _validationTests.getMaskTemplate.call(this, !0, 0, !0, void 0, !0), lmnt; void 0 !== (lmnt = template.shift()); ) buffer.push(lmnt);
                return buffer;
            }
            function checkVal(input, writeOut, strict, nptvl, initiatingEvent) {
                var inputmask = input ? input.inputmask : this, maskset = inputmask.maskset, opts = inputmask.opts, $ = inputmask.dependencyLib, inputValue = nptvl.slice(), charCodes = "", initialNdx = -1, result = void 0, skipOptionalPartCharacter = opts.skipOptionalPartCharacter;
                function isTemplateMatch(ndx, charCodes) {
                    for (var targetTemplate = _validationTests.getMaskTemplate.call(inputmask, !0, 0).slice(ndx, _positioning.seekNext.call(inputmask, ndx)).join("").replace(/'/g, ""), charCodeNdx = targetTemplate.indexOf(charCodes); 0 < charCodeNdx && " " === targetTemplate[charCodeNdx - 1]; ) charCodeNdx--;
                    var match = 0 === charCodeNdx && !_positioning.isMask.call(inputmask, ndx) && (_validationTests.getTest.call(inputmask, ndx).match.nativeDef === charCodes.charAt(0) || !0 === _validationTests.getTest.call(inputmask, ndx).match.static && _validationTests.getTest.call(inputmask, ndx).match.nativeDef === "'" + charCodes.charAt(0) || " " === _validationTests.getTest.call(inputmask, ndx).match.nativeDef && (_validationTests.getTest.call(inputmask, ndx + 1).match.nativeDef === charCodes.charAt(0) || !0 === _validationTests.getTest.call(inputmask, ndx + 1).match.static && _validationTests.getTest.call(inputmask, ndx + 1).match.nativeDef === "'" + charCodes.charAt(0)));
                    if (!match && 0 < charCodeNdx && !_positioning.isMask.call(inputmask, ndx, !1, !0)) {
                        var nextPos = _positioning.seekNext.call(inputmask, ndx);
                        inputmask.caretPos.begin < nextPos && (inputmask.caretPos = {
                            begin: nextPos
                        });
                    }
                    return match;
                }
                opts.skipOptionalPartCharacter = "", _positioning.resetMaskSet.call(inputmask), 
                maskset.tests = {}, initialNdx = opts.radixPoint ? _positioning.determineNewCaretPosition.call(inputmask, {
                    begin: 0,
                    end: 0
                }).begin : 0, maskset.p = initialNdx, inputmask.caretPos = {
                    begin: initialNdx
                };
                var staticMatches = [], prevCaretPos = inputmask.caretPos;
                if (inputValue.forEach(function(charCode, ndx) {
                    if (void 0 !== charCode) if (void 0 === maskset.validPositions[ndx] && inputValue[ndx] === _validationTests.getPlaceholder.call(inputmask, ndx) && _positioning.isMask.call(inputmask, ndx, !0) && !1 === _validation.isValid.call(inputmask, ndx, inputValue[ndx], !0, void 0, void 0, !0)) maskset.p++; else {
                        var keypress = new $.Event("_checkval");
                        keypress.which = charCode.toString().charCodeAt(0), charCodes += charCode;
                        var lvp = _positioning.getLastValidPosition.call(inputmask, void 0, !0);
                        isTemplateMatch(initialNdx, charCodes) ? result = _eventhandlers.EventHandlers.keypressEvent.call(input || inputmask, keypress, !0, !1, strict, lvp + 1) : (result = _eventhandlers.EventHandlers.keypressEvent.call(input || inputmask, keypress, !0, !1, strict, inputmask.caretPos.begin), 
                        result && (initialNdx = inputmask.caretPos.begin + 1, charCodes = "")), result ? (void 0 !== result.pos && maskset.validPositions[result.pos] && !0 === maskset.validPositions[result.pos].match.static && void 0 === maskset.validPositions[result.pos].alternation && (staticMatches.push(result.pos), 
                        inputmask.isRTL || (result.forwardPosition = result.pos + 1)), writeBuffer.call(inputmask, void 0, _positioning.getBuffer.call(inputmask), result.forwardPosition, keypress, !1), 
                        inputmask.caretPos = {
                            begin: result.forwardPosition,
                            end: result.forwardPosition
                        }, prevCaretPos = inputmask.caretPos) : inputmask.caretPos = prevCaretPos;
                    }
                }), 0 < staticMatches.length) {
                    var sndx, validPos, nextValid = _positioning.seekNext.call(inputmask, -1, void 0, !1);
                    if (!_validation.isComplete.call(inputmask, _positioning.getBuffer.call(inputmask)) && staticMatches.length <= nextValid || _validation.isComplete.call(inputmask, _positioning.getBuffer.call(inputmask)) && 0 < staticMatches.length && staticMatches.length !== nextValid && 0 === staticMatches[0]) for (var nextSndx = nextValid; void 0 !== (sndx = staticMatches.shift()); ) {
                        var keypress = new $.Event("_checkval");
                        if (validPos = maskset.validPositions[sndx], validPos.generatedInput = !0, keypress.which = validPos.input.charCodeAt(0), 
                        result = _eventhandlers.EventHandlers.keypressEvent.call(input, keypress, !0, !1, strict, nextSndx), 
                        result && void 0 !== result.pos && result.pos !== sndx && maskset.validPositions[result.pos] && !0 === maskset.validPositions[result.pos].match.static) staticMatches.push(result.pos); else if (!result) break;
                        nextSndx++;
                    }
                }
                writeOut && writeBuffer.call(inputmask, input, _positioning.getBuffer.call(inputmask), result ? result.forwardPosition : inputmask.caretPos.begin, initiatingEvent || new $.Event("checkval"), initiatingEvent && "input" === initiatingEvent.type && inputmask.undoValue !== _positioning.getBuffer.call(inputmask).join("")), 
                opts.skipOptionalPartCharacter = skipOptionalPartCharacter;
            }
            function HandleNativePlaceholder(npt, value) {
                var inputmask = npt ? npt.inputmask : this;
                if (_environment.ie) {
                    if (npt.inputmask._valueGet() !== value && (npt.placeholder !== value || "" === npt.placeholder)) {
                        var buffer = _positioning.getBuffer.call(inputmask).slice(), nptValue = npt.inputmask._valueGet();
                        if (nptValue !== value) {
                            var lvp = _positioning.getLastValidPosition.call(inputmask);
                            -1 === lvp && nptValue === _positioning.getBufferTemplate.call(inputmask).join("") ? buffer = [] : -1 !== lvp && clearOptionalTail.call(inputmask, buffer), 
                            writeBuffer(npt, buffer);
                        }
                    }
                } else npt.placeholder !== value && (npt.placeholder = value, "" === npt.placeholder && npt.removeAttribute("placeholder"));
            }
            function unmaskedvalue(input) {
                var inputmask = input ? input.inputmask : this, opts = inputmask.opts, maskset = inputmask.maskset;
                if (input) {
                    if (void 0 === input.inputmask) return input.value;
                    input.inputmask && input.inputmask.refreshValue && applyInputValue(input, input.inputmask._valueGet(!0));
                }
                var umValue = [], vps = maskset.validPositions;
                for (var pndx in vps) vps[pndx] && vps[pndx].match && (1 != vps[pndx].match.static || Array.isArray(maskset.metadata) && !0 !== vps[pndx].generatedInput) && umValue.push(vps[pndx].input);
                var unmaskedValue = 0 === umValue.length ? "" : (inputmask.isRTL ? umValue.reverse() : umValue).join("");
                if ("function" == typeof opts.onUnMask) {
                    var bufferValue = (inputmask.isRTL ? _positioning.getBuffer.call(inputmask).slice().reverse() : _positioning.getBuffer.call(inputmask)).join("");
                    unmaskedValue = opts.onUnMask.call(inputmask, bufferValue, unmaskedValue, opts);
                }
                return unmaskedValue;
            }
            function writeBuffer(input, buffer, caretPos, event, triggerEvents) {
                var inputmask = input ? input.inputmask : this, opts = inputmask.opts, $ = inputmask.dependencyLib;
                if (event && "function" == typeof opts.onBeforeWrite) {
                    var result = opts.onBeforeWrite.call(inputmask, event, buffer, caretPos, opts);
                    if (result) {
                        if (result.refreshFromBuffer) {
                            var refresh = result.refreshFromBuffer;
                            _validation.refreshFromBuffer.call(inputmask, !0 === refresh ? refresh : refresh.start, refresh.end, result.buffer || buffer), 
                            buffer = _positioning.getBuffer.call(inputmask, !0);
                        }
                        void 0 !== caretPos && (caretPos = void 0 !== result.caret ? result.caret : caretPos);
                    }
                }
                if (void 0 !== input && (input.inputmask._valueSet(buffer.join("")), void 0 === caretPos || void 0 !== event && "blur" === event.type || _positioning.caret.call(inputmask, input, caretPos, void 0, void 0, void 0 !== event && "keydown" === event.type && (event.keyCode === _keycode.default.DELETE || event.keyCode === _keycode.default.BACKSPACE)), 
                !0 === triggerEvents)) {
                    var $input = $(input), nptVal = input.inputmask._valueGet();
                    input.inputmask.skipInputEvent = !0, $input.trigger("input"), setTimeout(function() {
                        nptVal === _positioning.getBufferTemplate.call(inputmask).join("") ? $input.trigger("cleared") : !0 === _validation.isComplete.call(inputmask, buffer) && $input.trigger("complete");
                    }, 0);
                }
            }
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.EventHandlers = void 0;
            var _positioning = __webpack_require__(2), _keycode = _interopRequireDefault(__webpack_require__(0)), _environment = __webpack_require__(7), _validation = __webpack_require__(4), _inputHandling = __webpack_require__(5), _validationTests = __webpack_require__(3);
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            var EventHandlers = {
                keydownEvent: function keydownEvent(e) {
                    var inputmask = this.inputmask, opts = inputmask.opts, $ = inputmask.dependencyLib, maskset = inputmask.maskset, input = this, $input = $(input), k = e.keyCode, pos = _positioning.caret.call(inputmask, input), kdResult = opts.onKeyDown.call(this, e, _positioning.getBuffer.call(inputmask), pos, opts);
                    if (void 0 !== kdResult) return kdResult;
                    if (k === _keycode.default.BACKSPACE || k === _keycode.default.DELETE || _environment.iphone && k === _keycode.default.BACKSPACE_SAFARI || e.ctrlKey && k === _keycode.default.X && !("oncut" in input)) e.preventDefault(), 
                    _validation.handleRemove.call(inputmask, input, k, pos), (0, _inputHandling.writeBuffer)(input, _positioning.getBuffer.call(inputmask, !0), maskset.p, e, input.inputmask._valueGet() !== _positioning.getBuffer.call(inputmask).join("")); else if (k === _keycode.default.END || k === _keycode.default.PAGE_DOWN) {
                        e.preventDefault();
                        var caretPos = _positioning.seekNext.call(inputmask, _positioning.getLastValidPosition.call(inputmask));
                        _positioning.caret.call(inputmask, input, e.shiftKey ? pos.begin : caretPos, caretPos, !0);
                    } else k === _keycode.default.HOME && !e.shiftKey || k === _keycode.default.PAGE_UP ? (e.preventDefault(), 
                    _positioning.caret.call(inputmask, input, 0, e.shiftKey ? pos.begin : 0, !0)) : (opts.undoOnEscape && k === _keycode.default.ESCAPE || 90 === k && e.ctrlKey) && !0 !== e.altKey ? ((0, 
                    _inputHandling.checkVal)(input, !0, !1, inputmask.undoValue.split("")), $input.trigger("click")) : !0 === opts.tabThrough && k === _keycode.default.TAB ? !0 === e.shiftKey ? (pos.end = _positioning.seekPrevious.call(inputmask, pos.end, !0), 
                    !0 === _validationTests.getTest.call(inputmask, pos.end - 1).match.static && pos.end--, 
                    pos.begin = _positioning.seekPrevious.call(inputmask, pos.end, !0), 0 <= pos.begin && 0 < pos.end && (e.preventDefault(), 
                    _positioning.caret.call(inputmask, input, pos.begin, pos.end))) : (pos.begin = _positioning.seekNext.call(inputmask, pos.begin, !0), 
                    pos.end = _positioning.seekNext.call(inputmask, pos.begin, !0), pos.end < maskset.maskLength && pos.end--, 
                    pos.begin <= maskset.maskLength && (e.preventDefault(), _positioning.caret.call(inputmask, input, pos.begin, pos.end))) : e.shiftKey || opts.insertModeVisual && !1 === opts.insertMode && (k === _keycode.default.RIGHT ? setTimeout(function() {
                        var caretPos = _positioning.caret.call(inputmask, input);
                        _positioning.caret.call(inputmask, input, caretPos.begin);
                    }, 0) : k === _keycode.default.LEFT && setTimeout(function() {
                        var caretPos_begin = _positioning.translatePosition.call(inputmask, input.inputmask.caretPos.begin), caretPos_end = _positioning.translatePosition.call(inputmask, input.inputmask.caretPos.end);
                        inputmask.isRTL ? _positioning.caret.call(inputmask, input, caretPos_begin + (caretPos_begin === maskset.maskLength ? 0 : 1)) : _positioning.caret.call(inputmask, input, caretPos_begin - (0 === caretPos_begin ? 0 : 1));
                    }, 0));
                    inputmask.ignorable = opts.ignorables.includes(k);
                },
                keypressEvent: function keypressEvent(e, checkval, writeOut, strict, ndx) {
                    var inputmask = this.inputmask || this, opts = inputmask.opts, $ = inputmask.dependencyLib, maskset = inputmask.maskset, input = inputmask.el, $input = $(input), k = e.which || e.charCode || e.keyCode;
                    if (!(!0 === checkval || e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || inputmask.ignorable)) return k === _keycode.default.ENTER && inputmask.undoValue !== _positioning.getBuffer.call(inputmask).join("") && (inputmask.undoValue = _positioning.getBuffer.call(inputmask).join(""), 
                    setTimeout(function() {
                        $input.trigger("change");
                    }, 0)), inputmask.skipInputEvent = !0, !0;
                    if (k) {
                        44 !== k && 46 !== k || 3 !== e.location || "" === opts.radixPoint || (k = opts.radixPoint.charCodeAt(0));
                        var pos = checkval ? {
                            begin: ndx,
                            end: ndx
                        } : _positioning.caret.call(inputmask, input), forwardPosition, c = String.fromCharCode(k);
                        maskset.writeOutBuffer = !0;
                        var valResult = _validation.isValid.call(inputmask, pos, c, strict, void 0, void 0, void 0, checkval);
                        if (!1 !== valResult && (_positioning.resetMaskSet.call(inputmask, !0), forwardPosition = void 0 !== valResult.caret ? valResult.caret : _positioning.seekNext.call(inputmask, valResult.pos.begin ? valResult.pos.begin : valResult.pos), 
                        maskset.p = forwardPosition), forwardPosition = opts.numericInput && void 0 === valResult.caret ? _positioning.seekPrevious.call(inputmask, forwardPosition) : forwardPosition, 
                        !1 !== writeOut && (setTimeout(function() {
                            opts.onKeyValidation.call(input, k, valResult);
                        }, 0), maskset.writeOutBuffer && !1 !== valResult)) {
                            var buffer = _positioning.getBuffer.call(inputmask);
                            (0, _inputHandling.writeBuffer)(input, buffer, forwardPosition, e, !0 !== checkval);
                        }
                        if (e.preventDefault(), checkval) return !1 !== valResult && (valResult.forwardPosition = forwardPosition), 
                        valResult;
                    }
                },
                keyupEvent: function keyupEvent(e) {
                    var inputmask = this.inputmask;
                    !inputmask.isComposing || e.keyCode !== _keycode.default.KEY_229 && e.keyCode !== _keycode.default.ENTER || inputmask.$el.trigger("input");
                },
                pasteEvent: function pasteEvent(e) {
                    var inputmask = this.inputmask, opts = inputmask.opts, input = this, inputValue = inputmask._valueGet(!0), caretPos = _positioning.caret.call(inputmask, this), tempValue;
                    inputmask.isRTL && (tempValue = caretPos.end, caretPos.end = caretPos.begin, caretPos.begin = tempValue);
                    var valueBeforeCaret = inputValue.substr(0, caretPos.begin), valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length);
                    if (valueBeforeCaret == (inputmask.isRTL ? _positioning.getBufferTemplate.call(inputmask).slice().reverse() : _positioning.getBufferTemplate.call(inputmask)).slice(0, caretPos.begin).join("") && (valueBeforeCaret = ""), 
                    valueAfterCaret == (inputmask.isRTL ? _positioning.getBufferTemplate.call(inputmask).slice().reverse() : _positioning.getBufferTemplate.call(inputmask)).slice(caretPos.end).join("") && (valueAfterCaret = ""), 
                    window.clipboardData && window.clipboardData.getData) inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret; else {
                        if (!e.clipboardData || !e.clipboardData.getData) return !0;
                        inputValue = valueBeforeCaret + e.clipboardData.getData("text/plain") + valueAfterCaret;
                    }
                    var pasteValue = inputValue;
                    if ("function" == typeof opts.onBeforePaste) {
                        if (pasteValue = opts.onBeforePaste.call(inputmask, inputValue, opts), !1 === pasteValue) return e.preventDefault();
                        pasteValue = pasteValue || inputValue;
                    }
                    return (0, _inputHandling.checkVal)(this, !0, !1, pasteValue.toString().split(""), e), 
                    e.preventDefault();
                },
                inputFallBackEvent: function inputFallBackEvent(e) {
                    var inputmask = this.inputmask, opts = inputmask.opts, $ = inputmask.dependencyLib;
                    function ieMobileHandler(input, inputValue, caretPos) {
                        if (_environment.iemobile) {
                            var inputChar = inputValue.replace(_positioning.getBuffer.call(inputmask).join(""), "");
                            if (1 === inputChar.length) {
                                var iv = inputValue.split("");
                                iv.splice(caretPos.begin, 0, inputChar), inputValue = iv.join("");
                            }
                        }
                        return inputValue;
                    }
                    function analyseChanges(inputValue, buffer, caretPos) {
                        for (var frontPart = inputValue.substr(0, caretPos.begin).split(""), backPart = inputValue.substr(caretPos.begin).split(""), frontBufferPart = buffer.substr(0, caretPos.begin).split(""), backBufferPart = buffer.substr(caretPos.begin).split(""), fpl = frontPart.length >= frontBufferPart.length ? frontPart.length : frontBufferPart.length, bpl = backPart.length >= backBufferPart.length ? backPart.length : backBufferPart.length, bl, i, action = "", data = [], marker = "~", placeholder; frontPart.length < fpl; ) frontPart.push("~");
                        for (;frontBufferPart.length < fpl; ) frontBufferPart.push("~");
                        for (;backPart.length < bpl; ) backPart.unshift("~");
                        for (;backBufferPart.length < bpl; ) backBufferPart.unshift("~");
                        var newBuffer = frontPart.concat(backPart), oldBuffer = frontBufferPart.concat(backBufferPart);
                        for (i = 0, bl = newBuffer.length; i < bl; i++) switch (placeholder = _validationTests.getPlaceholder.call(inputmask, _positioning.translatePosition.call(inputmask, i)), 
                        action) {
                          case "insertText":
                            oldBuffer[i - 1] === newBuffer[i] && caretPos.begin == newBuffer.length - 1 && data.push(newBuffer[i]), 
                            i = bl;
                            break;
    
                          case "insertReplacementText":
                            "~" === newBuffer[i] ? caretPos.end++ : i = bl;
                            break;
    
                          case "deleteContentBackward":
                            "~" === newBuffer[i] ? caretPos.end++ : i = bl;
                            break;
    
                          default:
                            newBuffer[i] !== oldBuffer[i] && ("~" !== newBuffer[i + 1] && newBuffer[i + 1] !== placeholder && void 0 !== newBuffer[i + 1] || (oldBuffer[i] !== placeholder || "~" !== oldBuffer[i + 1]) && "~" !== oldBuffer[i] ? "~" === oldBuffer[i + 1] && oldBuffer[i] === newBuffer[i + 1] ? (action = "insertText", 
                            data.push(newBuffer[i]), caretPos.begin--, caretPos.end--) : newBuffer[i] !== placeholder && "~" !== newBuffer[i] && ("~" === newBuffer[i + 1] || oldBuffer[i] !== newBuffer[i] && oldBuffer[i + 1] === newBuffer[i + 1]) ? (action = "insertReplacementText", 
                            data.push(newBuffer[i]), caretPos.begin--) : "~" === newBuffer[i] ? (action = "deleteContentBackward", 
                            !_positioning.isMask.call(inputmask, _positioning.translatePosition.call(inputmask, i), !0) && oldBuffer[i] !== opts.radixPoint || caretPos.end++) : i = bl : (action = "insertText", 
                            data.push(newBuffer[i]), caretPos.begin--, caretPos.end--));
                            break;
                        }
                        return {
                            action: action,
                            data: data,
                            caret: caretPos
                        };
                    }
                    var input = this, inputValue = input.inputmask._valueGet(!0), buffer = (inputmask.isRTL ? _positioning.getBuffer.call(inputmask).slice().reverse() : _positioning.getBuffer.call(inputmask)).join(""), caretPos = _positioning.caret.call(inputmask, input, void 0, void 0, !0);
                    if (buffer !== inputValue) {
                        inputValue = ieMobileHandler(input, inputValue, caretPos);
                        var changes = analyseChanges(inputValue, buffer, caretPos);
                        switch ((input.inputmask.shadowRoot || document).activeElement !== input && input.focus(), 
                        (0, _inputHandling.writeBuffer)(input, _positioning.getBuffer.call(inputmask)), 
                        _positioning.caret.call(inputmask, input, caretPos.begin, caretPos.end, !0), changes.action) {
                          case "insertText":
                          case "insertReplacementText":
                            changes.data.forEach(function(entry, ndx) {
                                var keypress = new $.Event("keypress");
                                keypress.which = entry.charCodeAt(0), inputmask.ignorable = !1, EventHandlers.keypressEvent.call(input, keypress);
                            }), setTimeout(function() {
                                inputmask.$el.trigger("keyup");
                            }, 0);
                            break;
    
                          case "deleteContentBackward":
                            var keydown = new $.Event("keydown");
                            keydown.keyCode = _keycode.default.BACKSPACE, EventHandlers.keydownEvent.call(input, keydown);
                            break;
    
                          default:
                            (0, _inputHandling.applyInputValue)(input, inputValue);
                            break;
                        }
                        e.preventDefault();
                    }
                },
                compositionendEvent: function compositionendEvent(e) {
                    var inputmask = this.inputmask;
                    inputmask.isComposing = !1, inputmask.$el.trigger("input");
                },
                setValueEvent: function setValueEvent(e, argument_1, argument_2) {
                    var inputmask = this.inputmask, input = this, value = e && e.detail ? e.detail[0] : argument_1;
                    void 0 === value && (value = this.inputmask._valueGet(!0)), (0, _inputHandling.applyInputValue)(this, value), 
                    (e.detail && void 0 !== e.detail[1] || void 0 !== argument_2) && _positioning.caret.call(inputmask, this, e.detail ? e.detail[1] : argument_2);
                },
                focusEvent: function focusEvent(e) {
                    var inputmask = this.inputmask, opts = inputmask.opts, input = this, nptValue = this.inputmask._valueGet();
                    opts.showMaskOnFocus && nptValue !== _positioning.getBuffer.call(inputmask).join("") && (0, 
                    _inputHandling.writeBuffer)(this, _positioning.getBuffer.call(inputmask), _positioning.seekNext.call(inputmask, _positioning.getLastValidPosition.call(inputmask))), 
                    !0 !== opts.positionCaretOnTab || !1 !== inputmask.mouseEnter || _validation.isComplete.call(inputmask, _positioning.getBuffer.call(inputmask)) && -1 !== _positioning.getLastValidPosition.call(inputmask) || EventHandlers.clickEvent.apply(this, [ e, !0 ]), 
                    inputmask.undoValue = _positioning.getBuffer.call(inputmask).join("");
                },
                invalidEvent: function invalidEvent(e) {
                    this.inputmask.validationEvent = !0;
                },
                mouseleaveEvent: function mouseleaveEvent() {
                    var inputmask = this.inputmask, opts = inputmask.opts, input = this;
                    inputmask.mouseEnter = !1, opts.clearMaskOnLostFocus && (this.inputmask.shadowRoot || document).activeElement !== this && (0, 
                    _inputHandling.HandleNativePlaceholder)(this, inputmask.originalPlaceholder);
                },
                clickEvent: function clickEvent(e, tabbed) {
                    var inputmask = this.inputmask, input = this;
                    if ((this.inputmask.shadowRoot || document).activeElement === this) {
                        var newCaretPosition = _positioning.determineNewCaretPosition.call(inputmask, _positioning.caret.call(inputmask, this), tabbed);
                        void 0 !== newCaretPosition && _positioning.caret.call(inputmask, this, newCaretPosition);
                    }
                },
                cutEvent: function cutEvent(e) {
                    var inputmask = this.inputmask, maskset = inputmask.maskset, input = this, pos = _positioning.caret.call(inputmask, this), clipboardData = window.clipboardData || e.clipboardData, clipData = inputmask.isRTL ? _positioning.getBuffer.call(inputmask).slice(pos.end, pos.begin) : _positioning.getBuffer.call(inputmask).slice(pos.begin, pos.end);
                    clipboardData.setData("text", inputmask.isRTL ? clipData.reverse().join("") : clipData.join("")), 
                    document.execCommand && document.execCommand("copy"), _validation.handleRemove.call(inputmask, this, _keycode.default.DELETE, pos), 
                    (0, _inputHandling.writeBuffer)(this, _positioning.getBuffer.call(inputmask), maskset.p, e, inputmask.undoValue !== _positioning.getBuffer.call(inputmask).join(""));
                },
                blurEvent: function blurEvent(e) {
                    var inputmask = this.inputmask, opts = inputmask.opts, $ = inputmask.dependencyLib, $input = $(this), input = this;
                    if (this.inputmask) {
                        (0, _inputHandling.HandleNativePlaceholder)(this, inputmask.originalPlaceholder);
                        var nptValue = this.inputmask._valueGet(), buffer = _positioning.getBuffer.call(inputmask).slice();
                        "" !== nptValue && (opts.clearMaskOnLostFocus && (-1 === _positioning.getLastValidPosition.call(inputmask) && nptValue === _positioning.getBufferTemplate.call(inputmask).join("") ? buffer = [] : _inputHandling.clearOptionalTail.call(inputmask, buffer)), 
                        !1 === _validation.isComplete.call(inputmask, buffer) && (setTimeout(function() {
                            $input.trigger("incomplete");
                        }, 0), opts.clearIncomplete && (_positioning.resetMaskSet.call(inputmask), buffer = opts.clearMaskOnLostFocus ? [] : _positioning.getBufferTemplate.call(inputmask).slice())), 
                        (0, _inputHandling.writeBuffer)(this, buffer, void 0, e)), inputmask.undoValue !== _positioning.getBuffer.call(inputmask).join("") && (inputmask.undoValue = _positioning.getBuffer.call(inputmask).join(""), 
                        $input.trigger("change"));
                    }
                },
                mouseenterEvent: function mouseenterEvent() {
                    var inputmask = this.inputmask, opts = inputmask.opts, input = this;
                    inputmask.mouseEnter = !0, (this.inputmask.shadowRoot || document).activeElement !== this && (null == inputmask.originalPlaceholder && this.placeholder !== inputmask.originalPlaceholder && (inputmask.originalPlaceholder = this.placeholder), 
                    opts.showMaskOnHover && (0, _inputHandling.HandleNativePlaceholder)(this, (inputmask.isRTL ? _positioning.getBufferTemplate.call(inputmask).slice().reverse() : _positioning.getBufferTemplate.call(inputmask)).join("")));
                },
                submitEvent: function submitEvent() {
                    var inputmask = this.inputmask, opts = inputmask.opts;
                    inputmask.undoValue !== _positioning.getBuffer.call(inputmask).join("") && inputmask.$el.trigger("change"), 
                    opts.clearMaskOnLostFocus && -1 === _positioning.getLastValidPosition.call(inputmask) && inputmask._valueGet && inputmask._valueGet() === _positioning.getBufferTemplate.call(inputmask).join("") && inputmask._valueSet(""), 
                    opts.clearIncomplete && !1 === _validation.isComplete.call(inputmask, _positioning.getBuffer.call(inputmask)) && inputmask._valueSet(""), 
                    opts.removeMaskOnSubmit && (inputmask._valueSet(inputmask.unmaskedvalue(), !0), 
                    setTimeout(function() {
                        (0, _inputHandling.writeBuffer)(inputmask.el, _positioning.getBuffer.call(inputmask));
                    }, 0));
                },
                resetEvent: function resetEvent() {
                    var inputmask = this.inputmask;
                    inputmask.refreshValue = !0, setTimeout(function() {
                        (0, _inputHandling.applyInputValue)(inputmask.el, inputmask._valueGet(!0));
                    }, 0);
                }
            };
            exports.EventHandlers = EventHandlers;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.iphone = exports.iemobile = exports.mobile = exports.ie = exports.ua = void 0;
            var ua = window.navigator && window.navigator.userAgent || "", ie = 0 < ua.indexOf("MSIE ") || 0 < ua.indexOf("Trident/"), mobile = "ontouchstart" in window, iemobile = /iemobile/i.test(ua), iphone = /iphone/i.test(ua) && !iemobile;
            exports.iphone = iphone, exports.iemobile = iemobile, exports.mobile = mobile, exports.ie = ie, 
            exports.ua = ua;
        }, function(module, exports) {
            module.exports = __WEBPACK_EXTERNAL_MODULE__8__;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            function _typeof(obj) {
                return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                    return typeof obj;
                } : function _typeof(obj) {
                    return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
                }, _typeof(obj);
            }
            "function" != typeof Object.getPrototypeOf && (Object.getPrototypeOf = "object" === _typeof("test".__proto__) ? function(object) {
                return object.__proto__;
            } : function(object) {
                return object.constructor.prototype;
            });
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.mask = mask, __webpack_require__(9);
            var _keycode = _interopRequireDefault(__webpack_require__(0)), _positioning = __webpack_require__(2), _inputHandling = __webpack_require__(5), _eventruler = __webpack_require__(11), _environment = __webpack_require__(7), _validation = __webpack_require__(4), _eventhandlers = __webpack_require__(6);
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            function mask() {
                var inputmask = this, opts = this.opts, el = this.el, $ = this.dependencyLib;
                function isElementTypeSupported(input, opts) {
                    function patchValueProperty(npt) {
                        var valueGet, valueSet;
                        function patchValhook(type) {
                            if ($.valHooks && (void 0 === $.valHooks[type] || !0 !== $.valHooks[type].inputmaskpatch)) {
                                var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function(elem) {
                                    return elem.value;
                                }, valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function(elem, value) {
                                    return elem.value = value, elem;
                                };
                                $.valHooks[type] = {
                                    get: function get(elem) {
                                        if (elem.inputmask) {
                                            if (elem.inputmask.opts.autoUnmask) return elem.inputmask.unmaskedvalue();
                                            var result = valhookGet(elem);
                                            return -1 !== _positioning.getLastValidPosition.call(inputmask, void 0, void 0, elem.inputmask.maskset.validPositions) || !0 !== opts.nullable ? result : "";
                                        }
                                        return valhookGet(elem);
                                    },
                                    set: function set(elem, value) {
                                        var result = valhookSet(elem, value);
                                        return elem.inputmask && (0, _inputHandling.applyInputValue)(elem, value), result;
                                    },
                                    inputmaskpatch: !0
                                };
                            }
                        }
                        function getter() {
                            return this.inputmask ? this.inputmask.opts.autoUnmask ? this.inputmask.unmaskedvalue() : -1 !== _positioning.getLastValidPosition.call(inputmask) || !0 !== opts.nullable ? (this.inputmask.shadowRoot || document.activeElement) === this && opts.clearMaskOnLostFocus ? (inputmask.isRTL ? _inputHandling.clearOptionalTail.call(inputmask, _positioning.getBuffer.call(inputmask).slice()).reverse() : _inputHandling.clearOptionalTail.call(inputmask, _positioning.getBuffer.call(inputmask).slice())).join("") : valueGet.call(this) : "" : valueGet.call(this);
                        }
                        function setter(value) {
                            valueSet.call(this, value), this.inputmask && (0, _inputHandling.applyInputValue)(this, value);
                        }
                        function installNativeValueSetFallback(npt) {
                            _eventruler.EventRuler.on(npt, "mouseenter", function() {
                                var input = this, value = this.inputmask._valueGet(!0);
                                value !== (inputmask.isRTL ? _positioning.getBuffer.call(inputmask).reverse() : _positioning.getBuffer.call(inputmask)).join("") && (0, 
                                _inputHandling.applyInputValue)(this, value);
                            });
                        }
                        if (!npt.inputmask.__valueGet) {
                            if (!0 !== opts.noValuePatching) {
                                if (Object.getOwnPropertyDescriptor) {
                                    var valueProperty = Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt), "value") : void 0;
                                    valueProperty && valueProperty.get && valueProperty.set ? (valueGet = valueProperty.get, 
                                    valueSet = valueProperty.set, Object.defineProperty(npt, "value", {
                                        get: getter,
                                        set: setter,
                                        configurable: !0
                                    })) : "input" !== npt.tagName.toLowerCase() && (valueGet = function valueGet() {
                                        return this.textContent;
                                    }, valueSet = function valueSet(value) {
                                        this.textContent = value;
                                    }, Object.defineProperty(npt, "value", {
                                        get: getter,
                                        set: setter,
                                        configurable: !0
                                    }));
                                } else document.__lookupGetter__ && npt.__lookupGetter__("value") && (valueGet = npt.__lookupGetter__("value"), 
                                valueSet = npt.__lookupSetter__("value"), npt.__defineGetter__("value", getter), 
                                npt.__defineSetter__("value", setter));
                                npt.inputmask.__valueGet = valueGet, npt.inputmask.__valueSet = valueSet;
                            }
                            npt.inputmask._valueGet = function(overruleRTL) {
                                return inputmask.isRTL && !0 !== overruleRTL ? valueGet.call(this.el).split("").reverse().join("") : valueGet.call(this.el);
                            }, npt.inputmask._valueSet = function(value, overruleRTL) {
                                valueSet.call(this.el, null == value ? "" : !0 !== overruleRTL && inputmask.isRTL ? value.split("").reverse().join("") : value);
                            }, void 0 === valueGet && (valueGet = function valueGet() {
                                return this.value;
                            }, valueSet = function valueSet(value) {
                                this.value = value;
                            }, patchValhook(npt.type), installNativeValueSetFallback(npt));
                        }
                    }
                    "textarea" !== input.tagName.toLowerCase() && opts.ignorables.push(_keycode.default.ENTER);
                    var elementType = input.getAttribute("type"), isSupported = "input" === input.tagName.toLowerCase() && opts.supportsInputType.includes(elementType) || input.isContentEditable || "textarea" === input.tagName.toLowerCase();
                    if (!isSupported) if ("input" === input.tagName.toLowerCase()) {
                        var el = document.createElement("input");
                        el.setAttribute("type", elementType), isSupported = "text" === el.type, el = null;
                    } else isSupported = "partial";
                    return !1 !== isSupported ? patchValueProperty(input) : input.inputmask = void 0, 
                    isSupported;
                }
                _eventruler.EventRuler.off(el);
                var isSupported = isElementTypeSupported(el, opts);
                if (!1 !== isSupported) {
                    inputmask.originalPlaceholder = el.placeholder, inputmask.maxLength = void 0 !== el ? el.maxLength : void 0, 
                    -1 === inputmask.maxLength && (inputmask.maxLength = void 0), "inputMode" in el && null === el.getAttribute("inputmode") && (el.inputMode = opts.inputmode, 
                    el.setAttribute("inputmode", opts.inputmode)), !0 === isSupported && (opts.showMaskOnFocus = opts.showMaskOnFocus && -1 === [ "cc-number", "cc-exp" ].indexOf(el.autocomplete), 
                    _environment.iphone && (opts.insertModeVisual = !1), _eventruler.EventRuler.on(el, "submit", _eventhandlers.EventHandlers.submitEvent), 
                    _eventruler.EventRuler.on(el, "reset", _eventhandlers.EventHandlers.resetEvent), 
                    _eventruler.EventRuler.on(el, "blur", _eventhandlers.EventHandlers.blurEvent), _eventruler.EventRuler.on(el, "focus", _eventhandlers.EventHandlers.focusEvent), 
                    _eventruler.EventRuler.on(el, "invalid", _eventhandlers.EventHandlers.invalidEvent), 
                    _eventruler.EventRuler.on(el, "click", _eventhandlers.EventHandlers.clickEvent), 
                    _eventruler.EventRuler.on(el, "mouseleave", _eventhandlers.EventHandlers.mouseleaveEvent), 
                    _eventruler.EventRuler.on(el, "mouseenter", _eventhandlers.EventHandlers.mouseenterEvent), 
                    _eventruler.EventRuler.on(el, "paste", _eventhandlers.EventHandlers.pasteEvent), 
                    _eventruler.EventRuler.on(el, "cut", _eventhandlers.EventHandlers.cutEvent), _eventruler.EventRuler.on(el, "complete", opts.oncomplete), 
                    _eventruler.EventRuler.on(el, "incomplete", opts.onincomplete), _eventruler.EventRuler.on(el, "cleared", opts.oncleared), 
                    !0 !== opts.inputEventOnly && (_eventruler.EventRuler.on(el, "keydown", _eventhandlers.EventHandlers.keydownEvent), 
                    _eventruler.EventRuler.on(el, "keypress", _eventhandlers.EventHandlers.keypressEvent), 
                    _eventruler.EventRuler.on(el, "keyup", _eventhandlers.EventHandlers.keyupEvent)), 
                    (_environment.mobile || opts.inputEventOnly) && el.removeAttribute("maxLength"), 
                    _eventruler.EventRuler.on(el, "input", _eventhandlers.EventHandlers.inputFallBackEvent), 
                    _eventruler.EventRuler.on(el, "compositionend", _eventhandlers.EventHandlers.compositionendEvent)), 
                    _eventruler.EventRuler.on(el, "setvalue", _eventhandlers.EventHandlers.setValueEvent), 
                    inputmask.undoValue = _positioning.getBufferTemplate.call(inputmask).join("");
                    var activeElement = (el.inputmask.shadowRoot || document).activeElement;
                    if ("" !== el.inputmask._valueGet(!0) || !1 === opts.clearMaskOnLostFocus || activeElement === el) {
                        (0, _inputHandling.applyInputValue)(el, el.inputmask._valueGet(!0), opts);
                        var buffer = _positioning.getBuffer.call(inputmask).slice();
                        !1 === _validation.isComplete.call(inputmask, buffer) && opts.clearIncomplete && _positioning.resetMaskSet.call(inputmask), 
                        opts.clearMaskOnLostFocus && activeElement !== el && (-1 === _positioning.getLastValidPosition.call(inputmask) ? buffer = [] : _inputHandling.clearOptionalTail.call(inputmask, buffer)), 
                        (!1 === opts.clearMaskOnLostFocus || opts.showMaskOnFocus && activeElement === el || "" !== el.inputmask._valueGet(!0)) && (0, 
                        _inputHandling.writeBuffer)(el, buffer), activeElement === el && _positioning.caret.call(inputmask, el, _positioning.seekNext.call(inputmask, _positioning.getLastValidPosition.call(inputmask)));
                    }
                }
            }
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.EventRuler = void 0;
            var _inputmask = _interopRequireDefault(__webpack_require__(1)), _keycode = _interopRequireDefault(__webpack_require__(0)), _positioning = __webpack_require__(2), _inputHandling = __webpack_require__(5);
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            var EventRuler = {
                on: function on(input, eventName, eventHandler) {
                    var $ = input.inputmask.dependencyLib, ev = function ev(e) {
                        e.originalEvent && (e = e.originalEvent || e, arguments[0] = e);
                        var that = this, args, inputmask = that.inputmask, opts = inputmask ? inputmask.opts : void 0, $ = inputmask.dependencyLib;
                        if (void 0 === inputmask && "FORM" !== this.nodeName) {
                            var imOpts = $.data(that, "_inputmask_opts");
                            $(that).off(), imOpts && new _inputmask.default(imOpts).mask(that);
                        } else {
                            if ("setvalue" === e.type || "FORM" === this.nodeName || !(that.disabled || that.readOnly && !("keydown" === e.type && e.ctrlKey && 67 === e.keyCode || !1 === opts.tabThrough && e.keyCode === _keycode.default.TAB))) {
                                switch (e.type) {
                                  case "input":
                                    if (!0 === inputmask.skipInputEvent || e.inputType && "insertCompositionText" === e.inputType) return inputmask.skipInputEvent = !1, 
                                    e.preventDefault();
                                    break;
    
                                  case "keydown":
                                    inputmask.skipKeyPressEvent = !1, inputmask.skipInputEvent = inputmask.isComposing = e.keyCode === _keycode.default.KEY_229;
                                    break;
    
                                  case "keyup":
                                  case "compositionend":
                                    inputmask.isComposing && (inputmask.skipInputEvent = !1);
                                    break;
    
                                  case "keypress":
                                    if (!0 === inputmask.skipKeyPressEvent) return e.preventDefault();
                                    inputmask.skipKeyPressEvent = !0;
                                    break;
    
                                  case "click":
                                  case "focus":
                                    return inputmask.validationEvent ? (inputmask.validationEvent = !1, input.blur(), 
                                    (0, _inputHandling.HandleNativePlaceholder)(input, (inputmask.isRTL ? _positioning.getBufferTemplate.call(inputmask).slice().reverse() : _positioning.getBufferTemplate.call(inputmask)).join("")), 
                                    setTimeout(function() {
                                        input.focus();
                                    }, 3e3)) : (args = arguments, setTimeout(function() {
                                        input.inputmask && eventHandler.apply(that, args);
                                    }, 0)), !1;
                                }
                                var returnVal = eventHandler.apply(that, arguments);
                                return !1 === returnVal && (e.preventDefault(), e.stopPropagation()), returnVal;
                            }
                            e.preventDefault();
                        }
                    };
                    input.inputmask.events[eventName] = input.inputmask.events[eventName] || [], input.inputmask.events[eventName].push(ev), 
                    [ "submit", "reset" ].includes(eventName) ? null !== input.form && $(input.form).on(eventName, ev.bind(input)) : $(input).on(eventName, ev);
                },
                off: function off(input, event) {
                    if (input.inputmask && input.inputmask.events) {
                        var $ = input.inputmask.dependencyLib, events = input.inputmask.events;
                        for (var eventName in event && (events = [], events[event] = input.inputmask.events[event]), 
                        events) {
                            for (var evArr = events[eventName]; 0 < evArr.length; ) {
                                var ev = evArr.pop();
                                [ "submit", "reset" ].includes(eventName) ? null !== input.form && $(input.form).off(eventName, ev) : $(input).off(eventName, ev);
                            }
                            delete input.inputmask.events[eventName];
                        }
                    }
                }
            };
            exports.EventRuler = EventRuler;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.default = void 0;
            var _jquery = _interopRequireDefault(__webpack_require__(8));
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            if (void 0 === _jquery.default) throw "jQuery not loaded!";
            var _default = _jquery.default;
            exports.default = _default;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.default = void 0;
            var _default = "undefined" != typeof window ? window : new (eval("require('jsdom').JSDOM"))("").window;
            exports.default = _default;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.default = _default;
            var escapeRegexRegex = new RegExp("(\\" + [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^" ].join("|\\") + ")", "gim");
            function _default(str) {
                return str.replace(escapeRegexRegex, "\\$1");
            }
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.default = void 0, __webpack_require__(16), __webpack_require__(20), 
            __webpack_require__(21), __webpack_require__(22);
            var _inputmask2 = _interopRequireDefault(__webpack_require__(1));
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            var _default = _inputmask2.default;
            exports.default = _default;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            var _inputmask = _interopRequireDefault(__webpack_require__(1));
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            _inputmask.default.extendDefinitions({
                A: {
                    validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
                    casing: "upper"
                },
                "&": {
                    validator: "[0-9A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
                    casing: "upper"
                },
                "#": {
                    validator: "[0-9A-Fa-f]",
                    casing: "upper"
                }
            });
            var ipValidatorRegex = new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]");
            function ipValidator(chrs, maskset, pos, strict, opts) {
                return chrs = -1 < pos - 1 && "." !== maskset.buffer[pos - 1] ? (chrs = maskset.buffer[pos - 1] + chrs, 
                -1 < pos - 2 && "." !== maskset.buffer[pos - 2] ? maskset.buffer[pos - 2] + chrs : "0" + chrs) : "00" + chrs, 
                ipValidatorRegex.test(chrs);
            }
            _inputmask.default.extendAliases({
                cssunit: {
                    regex: "[+-]?[0-9]+\\.?([0-9]+)?(px|em|rem|ex|%|in|cm|mm|pt|pc)"
                },
                url: {
                    regex: "(https?|ftp)://.*",
                    autoUnmask: !1,
                    keepStatic: !1,
                    tabThrough: !0
                },
                ip: {
                    mask: "i[i[i]].j[j[j]].k[k[k]].l[l[l]]",
                    definitions: {
                        i: {
                            validator: ipValidator
                        },
                        j: {
                            validator: ipValidator
                        },
                        k: {
                            validator: ipValidator
                        },
                        l: {
                            validator: ipValidator
                        }
                    },
                    onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                        return maskedValue;
                    },
                    inputmode: "numeric"
                },
                email: {
                    mask: "*{1,64}[.*{1,64}][.*{1,64}][.*{1,63}]@-{1,63}.-{1,63}[.-{1,63}][.-{1,63}]",
                    greedy: !1,
                    casing: "lower",
                    onBeforePaste: function onBeforePaste(pastedValue, opts) {
                        return pastedValue = pastedValue.toLowerCase(), pastedValue.replace("mailto:", "");
                    },
                    definitions: {
                        "*": {
                            validator: "[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5!#$%&'*+/=?^_`{|}~-]"
                        },
                        "-": {
                            validator: "[0-9A-Za-z-]"
                        }
                    },
                    onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                        return maskedValue;
                    },
                    inputmode: "email"
                },
                mac: {
                    mask: "##:##:##:##:##:##"
                },
                vin: {
                    mask: "V{13}9{4}",
                    definitions: {
                        V: {
                            validator: "[A-HJ-NPR-Za-hj-npr-z\\d]",
                            casing: "upper"
                        }
                    },
                    clearIncomplete: !0,
                    autoUnmask: !0
                },
                ssn: {
                    mask: "999-99-9999",
                    postValidation: function postValidation(buffer, pos, c, currentResult, opts, maskset, strict) {
                        return /^(?!219-09-9999|078-05-1120)(?!666|000|9.{2}).{3}-(?!00).{2}-(?!0{4}).{4}$/.test(buffer.join(""));
                    }
                }
            });
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.generateMaskSet = generateMaskSet, exports.analyseMask = analyseMask;
            var _inputmask = _interopRequireDefault(__webpack_require__(12));
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            function generateMaskSet(opts, nocache) {
                var ms;
                function generateMask(mask, metadata, opts) {
                    var regexMask = !1, masksetDefinition, maskdefKey;
                    if (null !== mask && "" !== mask || (regexMask = null !== opts.regex, mask = regexMask ? (mask = opts.regex, 
                    mask.replace(/^(\^)(.*)(\$)$/, "$2")) : (regexMask = !0, ".*")), 1 === mask.length && !1 === opts.greedy && 0 !== opts.repeat && (opts.placeholder = ""), 
                    0 < opts.repeat || "*" === opts.repeat || "+" === opts.repeat) {
                        var repeatStart = "*" === opts.repeat ? 0 : "+" === opts.repeat ? 1 : opts.repeat;
                        mask = opts.groupmarker[0] + mask + opts.groupmarker[1] + opts.quantifiermarker[0] + repeatStart + "," + opts.repeat + opts.quantifiermarker[1];
                    }
                    return maskdefKey = regexMask ? "regex_" + opts.regex : opts.numericInput ? mask.split("").reverse().join("") : mask, 
                    !1 !== opts.keepStatic && (maskdefKey = "ks_" + maskdefKey), void 0 === Inputmask.prototype.masksCache[maskdefKey] || !0 === nocache ? (masksetDefinition = {
                        mask: mask,
                        maskToken: Inputmask.prototype.analyseMask(mask, regexMask, opts),
                        validPositions: {},
                        _buffer: void 0,
                        buffer: void 0,
                        tests: {},
                        excludes: {},
                        metadata: metadata,
                        maskLength: void 0,
                        jitOffset: {}
                    }, !0 !== nocache && (Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition, 
                    masksetDefinition = _inputmask.default.extend(!0, {}, Inputmask.prototype.masksCache[maskdefKey]))) : masksetDefinition = _inputmask.default.extend(!0, {}, Inputmask.prototype.masksCache[maskdefKey]), 
                    masksetDefinition;
                }
                if ("function" == typeof opts.mask && (opts.mask = opts.mask(opts)), Array.isArray(opts.mask)) {
                    if (1 < opts.mask.length) {
                        null === opts.keepStatic && (opts.keepStatic = !0);
                        var altMask = opts.groupmarker[0];
                        return (opts.isRTL ? opts.mask.reverse() : opts.mask).forEach(function(msk) {
                            1 < altMask.length && (altMask += opts.groupmarker[1] + opts.alternatormarker + opts.groupmarker[0]), 
                            void 0 !== msk.mask && "function" != typeof msk.mask ? altMask += msk.mask : altMask += msk;
                        }), altMask += opts.groupmarker[1], generateMask(altMask, opts.mask, opts);
                    }
                    opts.mask = opts.mask.pop();
                }
                return null === opts.keepStatic && (opts.keepStatic = !1), ms = opts.mask && void 0 !== opts.mask.mask && "function" != typeof opts.mask.mask ? generateMask(opts.mask.mask, opts.mask, opts) : generateMask(opts.mask, opts.mask, opts), 
                ms;
            }
            function analyseMask(mask, regexMask, opts) {
                var tokenizer = /(?:[?*+]|\{[0-9+*]+(?:,[0-9+*]*)?(?:\|[0-9+*]*)?\})|[^.?*+^${[]()|\\]+|./g, regexTokenizer = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, escaped = !1, currentToken = new MaskToken(), match, m, openenings = [], maskTokens = [], openingToken, currentOpeningToken, alternator, lastMatch, closeRegexGroup = !1;
                function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) {
                    this.matches = [], this.openGroup = isGroup || !1, this.alternatorGroup = !1, this.isGroup = isGroup || !1, 
                    this.isOptional = isOptional || !1, this.isQuantifier = isQuantifier || !1, this.isAlternator = isAlternator || !1, 
                    this.quantifier = {
                        min: 1,
                        max: 1
                    };
                }
                function insertTestDefinition(mtoken, element, position) {
                    position = void 0 !== position ? position : mtoken.matches.length;
                    var prevMatch = mtoken.matches[position - 1];
                    if (regexMask) 0 === element.indexOf("[") || escaped && /\\d|\\s|\\w]/i.test(element) || "." === element ? mtoken.matches.splice(position++, 0, {
                        fn: new RegExp(element, opts.casing ? "i" : ""),
                        static: !1,
                        optionality: !1,
                        newBlockMarker: void 0 === prevMatch ? "master" : prevMatch.def !== element,
                        casing: null,
                        def: element,
                        placeholder: void 0,
                        nativeDef: element
                    }) : (escaped && (element = element[element.length - 1]), element.split("").forEach(function(lmnt, ndx) {
                        prevMatch = mtoken.matches[position - 1], mtoken.matches.splice(position++, 0, {
                            fn: /[a-z]/i.test(opts.staticDefinitionSymbol || lmnt) ? new RegExp("[" + (opts.staticDefinitionSymbol || lmnt) + "]", opts.casing ? "i" : "") : null,
                            static: !0,
                            optionality: !1,
                            newBlockMarker: void 0 === prevMatch ? "master" : prevMatch.def !== lmnt && !0 !== prevMatch.static,
                            casing: null,
                            def: opts.staticDefinitionSymbol || lmnt,
                            placeholder: void 0 !== opts.staticDefinitionSymbol ? lmnt : void 0,
                            nativeDef: (escaped ? "'" : "") + lmnt
                        });
                    })), escaped = !1; else {
                        var maskdef = opts.definitions && opts.definitions[element] || opts.usePrototypeDefinitions && Inputmask.prototype.definitions[element];
                        maskdef && !escaped ? mtoken.matches.splice(position++, 0, {
                            fn: maskdef.validator ? "string" == typeof maskdef.validator ? new RegExp(maskdef.validator, opts.casing ? "i" : "") : new function() {
                                this.test = maskdef.validator;
                            }() : new RegExp("."),
                            static: maskdef.static || !1,
                            optionality: !1,
                            newBlockMarker: void 0 === prevMatch ? "master" : prevMatch.def !== (maskdef.definitionSymbol || element),
                            casing: maskdef.casing,
                            def: maskdef.definitionSymbol || element,
                            placeholder: maskdef.placeholder,
                            nativeDef: element,
                            generated: maskdef.generated
                        }) : (mtoken.matches.splice(position++, 0, {
                            fn: /[a-z]/i.test(opts.staticDefinitionSymbol || element) ? new RegExp("[" + (opts.staticDefinitionSymbol || element) + "]", opts.casing ? "i" : "") : null,
                            static: !0,
                            optionality: !1,
                            newBlockMarker: void 0 === prevMatch ? "master" : prevMatch.def !== element && !0 !== prevMatch.static,
                            casing: null,
                            def: opts.staticDefinitionSymbol || element,
                            placeholder: void 0 !== opts.staticDefinitionSymbol ? element : void 0,
                            nativeDef: (escaped ? "'" : "") + element
                        }), escaped = !1);
                    }
                }
                function verifyGroupMarker(maskToken) {
                    maskToken && maskToken.matches && maskToken.matches.forEach(function(token, ndx) {
                        var nextToken = maskToken.matches[ndx + 1];
                        (void 0 === nextToken || void 0 === nextToken.matches || !1 === nextToken.isQuantifier) && token && token.isGroup && (token.isGroup = !1, 
                        regexMask || (insertTestDefinition(token, opts.groupmarker[0], 0), !0 !== token.openGroup && insertTestDefinition(token, opts.groupmarker[1]))), 
                        verifyGroupMarker(token);
                    });
                }
                function defaultCase() {
                    if (0 < openenings.length) {
                        if (currentOpeningToken = openenings[openenings.length - 1], insertTestDefinition(currentOpeningToken, m), 
                        currentOpeningToken.isAlternator) {
                            alternator = openenings.pop();
                            for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup && (alternator.matches[mndx].isGroup = !1);
                            0 < openenings.length ? (currentOpeningToken = openenings[openenings.length - 1], 
                            currentOpeningToken.matches.push(alternator)) : currentToken.matches.push(alternator);
                        }
                    } else insertTestDefinition(currentToken, m);
                }
                function reverseTokens(maskToken) {
                    function reverseStatic(st) {
                        return st === opts.optionalmarker[0] ? st = opts.optionalmarker[1] : st === opts.optionalmarker[1] ? st = opts.optionalmarker[0] : st === opts.groupmarker[0] ? st = opts.groupmarker[1] : st === opts.groupmarker[1] && (st = opts.groupmarker[0]), 
                        st;
                    }
                    for (var match in maskToken.matches = maskToken.matches.reverse(), maskToken.matches) if (Object.prototype.hasOwnProperty.call(maskToken.matches, match)) {
                        var intMatch = parseInt(match);
                        if (maskToken.matches[match].isQuantifier && maskToken.matches[intMatch + 1] && maskToken.matches[intMatch + 1].isGroup) {
                            var qt = maskToken.matches[match];
                            maskToken.matches.splice(match, 1), maskToken.matches.splice(intMatch + 1, 0, qt);
                        }
                        void 0 !== maskToken.matches[match].matches ? maskToken.matches[match] = reverseTokens(maskToken.matches[match]) : maskToken.matches[match] = reverseStatic(maskToken.matches[match]);
                    }
                    return maskToken;
                }
                function groupify(matches) {
                    var groupToken = new MaskToken(!0);
                    return groupToken.openGroup = !1, groupToken.matches = matches, groupToken;
                }
                function closeGroup() {
                    if (openingToken = openenings.pop(), openingToken.openGroup = !1, void 0 !== openingToken) if (0 < openenings.length) {
                        if (currentOpeningToken = openenings[openenings.length - 1], currentOpeningToken.matches.push(openingToken), 
                        currentOpeningToken.isAlternator) {
                            alternator = openenings.pop();
                            for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup = !1, 
                            alternator.matches[mndx].alternatorGroup = !1;
                            0 < openenings.length ? (currentOpeningToken = openenings[openenings.length - 1], 
                            currentOpeningToken.matches.push(alternator)) : currentToken.matches.push(alternator);
                        }
                    } else currentToken.matches.push(openingToken); else defaultCase();
                }
                function groupQuantifier(matches) {
                    var lastMatch = matches.pop();
                    return lastMatch.isQuantifier && (lastMatch = groupify([ matches.pop(), lastMatch ])), 
                    lastMatch;
                }
                for (regexMask && (opts.optionalmarker[0] = void 0, opts.optionalmarker[1] = void 0); match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask); ) {
                    if (m = match[0], regexMask) switch (m.charAt(0)) {
                      case "?":
                        m = "{0,1}";
                        break;
    
                      case "+":
                      case "*":
                        m = "{" + m + "}";
                        break;
    
                      case "|":
                        if (0 === openenings.length) {
                            var altRegexGroup = groupify(currentToken.matches);
                            altRegexGroup.openGroup = !0, openenings.push(altRegexGroup), currentToken.matches = [], 
                            closeRegexGroup = !0;
                        }
                        break;
                    }
                    if (escaped) defaultCase(); else switch (m.charAt(0)) {
                      case "$":
                      case "^":
                        regexMask || defaultCase();
                        break;
    
                      case "(?=":
                        break;
    
                      case "(?!":
                        break;
    
                      case "(?<=":
                        break;
    
                      case "(?<!":
                        break;
    
                      case opts.escapeChar:
                        escaped = !0, regexMask && defaultCase();
                        break;
    
                      case opts.optionalmarker[1]:
                      case opts.groupmarker[1]:
                        closeGroup();
                        break;
    
                      case opts.optionalmarker[0]:
                        openenings.push(new MaskToken(!1, !0));
                        break;
    
                      case opts.groupmarker[0]:
                        openenings.push(new MaskToken(!0));
                        break;
    
                      case opts.quantifiermarker[0]:
                        var quantifier = new MaskToken(!1, !1, !0);
                        m = m.replace(/[{}]/g, "");
                        var mqj = m.split("|"), mq = mqj[0].split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = 1 === mq.length ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
                        "*" !== mq0 && "+" !== mq0 || (mq0 = "*" === mq1 ? 0 : 1), quantifier.quantifier = {
                            min: mq0,
                            max: mq1,
                            jit: mqj[1]
                        };
                        var matches = 0 < openenings.length ? openenings[openenings.length - 1].matches : currentToken.matches;
                        if (match = matches.pop(), match.isAlternator) {
                            matches.push(match), matches = match.matches;
                            var groupToken = new MaskToken(!0), tmpMatch = matches.pop();
                            matches.push(groupToken), matches = groupToken.matches, match = tmpMatch;
                        }
                        match.isGroup || (match = groupify([ match ])), matches.push(match), matches.push(quantifier);
                        break;
    
                      case opts.alternatormarker:
                        if (0 < openenings.length) {
                            currentOpeningToken = openenings[openenings.length - 1];
                            var subToken = currentOpeningToken.matches[currentOpeningToken.matches.length - 1];
                            lastMatch = currentOpeningToken.openGroup && (void 0 === subToken.matches || !1 === subToken.isGroup && !1 === subToken.isAlternator) ? openenings.pop() : groupQuantifier(currentOpeningToken.matches);
                        } else lastMatch = groupQuantifier(currentToken.matches);
                        if (lastMatch.isAlternator) openenings.push(lastMatch); else if (lastMatch.alternatorGroup ? (alternator = openenings.pop(), 
                        lastMatch.alternatorGroup = !1) : alternator = new MaskToken(!1, !1, !1, !0), alternator.matches.push(lastMatch), 
                        openenings.push(alternator), lastMatch.openGroup) {
                            lastMatch.openGroup = !1;
                            var alternatorGroup = new MaskToken(!0);
                            alternatorGroup.alternatorGroup = !0, openenings.push(alternatorGroup);
                        }
                        break;
    
                      default:
                        defaultCase();
                    }
                }
                for (closeRegexGroup && closeGroup(); 0 < openenings.length; ) openingToken = openenings.pop(), 
                currentToken.matches.push(openingToken);
                return 0 < currentToken.matches.length && (verifyGroupMarker(currentToken), maskTokens.push(currentToken)), 
                (opts.numericInput || opts.isRTL) && reverseTokens(maskTokens[0]), maskTokens;
            }
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.default = void 0;
            var _default = {
                9: {
                    validator: "[0-9\uff10-\uff19]",
                    definitionSymbol: "*"
                },
                a: {
                    validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
                    definitionSymbol: "*"
                },
                "*": {
                    validator: "[0-9\uff10-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]"
                }
            };
            exports.default = _default;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.default = void 0;
            var _default = {
                _maxTestPos: 500,
                placeholder: "_",
                optionalmarker: [ "[", "]" ],
                quantifiermarker: [ "{", "}" ],
                groupmarker: [ "(", ")" ],
                alternatormarker: "|",
                escapeChar: "\\",
                mask: null,
                regex: null,
                oncomplete: function oncomplete() {},
                onincomplete: function onincomplete() {},
                oncleared: function oncleared() {},
                repeat: 0,
                greedy: !1,
                autoUnmask: !1,
                removeMaskOnSubmit: !1,
                clearMaskOnLostFocus: !0,
                insertMode: !0,
                insertModeVisual: !0,
                clearIncomplete: !1,
                alias: null,
                onKeyDown: function onKeyDown() {},
                onBeforeMask: null,
                onBeforePaste: function onBeforePaste(pastedValue, opts) {
                    return "function" == typeof opts.onBeforeMask ? opts.onBeforeMask.call(this, pastedValue, opts) : pastedValue;
                },
                onBeforeWrite: null,
                onUnMask: null,
                showMaskOnFocus: !0,
                showMaskOnHover: !0,
                onKeyValidation: function onKeyValidation() {},
                skipOptionalPartCharacter: " ",
                numericInput: !1,
                rightAlign: !1,
                undoOnEscape: !0,
                radixPoint: "",
                _radixDance: !1,
                groupSeparator: "",
                keepStatic: null,
                positionCaretOnTab: !0,
                tabThrough: !1,
                supportsInputType: [ "text", "tel", "url", "password", "search" ],
                ignorables: [ 8, 9, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, 229 ],
                isComplete: null,
                preValidation: null,
                postValidation: null,
                staticDefinitionSymbol: void 0,
                jitMasking: !1,
                nullable: !0,
                inputEventOnly: !1,
                noValuePatching: !1,
                positionCaretOnClick: "lvp",
                casing: null,
                inputmode: "text",
                importDataAttributes: !0,
                shiftPositions: !0,
                usePrototypeDefinitions: !0
            };
            exports.default = _default;
        }, function(module, exports, __webpack_require__) {
            "use strict";
            var _inputmask = _interopRequireDefault(__webpack_require__(1)), _keycode = _interopRequireDefault(__webpack_require__(0)), _escapeRegex = _interopRequireDefault(__webpack_require__(14));
            function _typeof(obj) {
                return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                    return typeof obj;
                } : function _typeof(obj) {
                    return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
                }, _typeof(obj);
            }
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            var $ = _inputmask.default.dependencyLib, currentYear = new Date().getFullYear(), formatCode = {
                d: [ "[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", Date.prototype.getDate ],
                dd: [ "0[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", function() {
                    return pad(Date.prototype.getDate.call(this), 2);
                } ],
                ddd: [ "" ],
                dddd: [ "" ],
                m: [ "[1-9]|1[012]", Date.prototype.setMonth, "month", function() {
                    return Date.prototype.getMonth.call(this) + 1;
                } ],
                mm: [ "0[1-9]|1[012]", Date.prototype.setMonth, "month", function() {
                    return pad(Date.prototype.getMonth.call(this) + 1, 2);
                } ],
                mmm: [ "" ],
                mmmm: [ "" ],
                yy: [ "[0-9]{2}", Date.prototype.setFullYear, "year", function() {
                    return pad(Date.prototype.getFullYear.call(this), 2);
                } ],
                yyyy: [ "[0-9]{4}", Date.prototype.setFullYear, "year", function() {
                    return pad(Date.prototype.getFullYear.call(this), 4);
                } ],
                h: [ "[1-9]|1[0-2]", Date.prototype.setHours, "hours", Date.prototype.getHours ],
                hh: [ "0[1-9]|1[0-2]", Date.prototype.setHours, "hours", function() {
                    return pad(Date.prototype.getHours.call(this), 2);
                } ],
                hx: [ function(x) {
                    return "[0-9]{".concat(x, "}");
                }, Date.prototype.setHours, "hours", function(x) {
                    return Date.prototype.getHours;
                } ],
                H: [ "1?[0-9]|2[0-3]", Date.prototype.setHours, "hours", Date.prototype.getHours ],
                HH: [ "0[0-9]|1[0-9]|2[0-3]", Date.prototype.setHours, "hours", function() {
                    return pad(Date.prototype.getHours.call(this), 2);
                } ],
                Hx: [ function(x) {
                    return "[0-9]{".concat(x, "}");
                }, Date.prototype.setHours, "hours", function(x) {
                    return function() {
                        return pad(Date.prototype.getHours.call(this), x);
                    };
                } ],
                M: [ "[1-5]?[0-9]", Date.prototype.setMinutes, "minutes", Date.prototype.getMinutes ],
                MM: [ "0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]", Date.prototype.setMinutes, "minutes", function() {
                    return pad(Date.prototype.getMinutes.call(this), 2);
                } ],
                s: [ "[1-5]?[0-9]", Date.prototype.setSeconds, "seconds", Date.prototype.getSeconds ],
                ss: [ "0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]", Date.prototype.setSeconds, "seconds", function() {
                    return pad(Date.prototype.getSeconds.call(this), 2);
                } ],
                l: [ "[0-9]{3}", Date.prototype.setMilliseconds, "milliseconds", function() {
                    return pad(Date.prototype.getMilliseconds.call(this), 3);
                } ],
                L: [ "[0-9]{2}", Date.prototype.setMilliseconds, "milliseconds", function() {
                    return pad(Date.prototype.getMilliseconds.call(this), 2);
                } ],
                t: [ "[ap]" ],
                tt: [ "[ap]m" ],
                T: [ "[AP]" ],
                TT: [ "[AP]M" ],
                Z: [ "" ],
                o: [ "" ],
                S: [ "" ]
            }, formatAlias = {
                isoDate: "yyyy-mm-dd",
                isoTime: "HH:MM:ss",
                isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
                isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
            };
            function formatcode(match) {
                var dynMatches = new RegExp("\\d+$").exec(match[0]);
                if (dynMatches && void 0 !== dynMatches[0]) {
                    var fcode = formatCode[match[0][0] + "x"].slice("");
                    return fcode[0] = fcode[0](dynMatches[0]), fcode[3] = fcode[3](dynMatches[0]), fcode;
                }
                if (formatCode[match[0]]) return formatCode[match[0]];
            }
            function getTokenizer(opts) {
                if (!opts.tokenizer) {
                    var tokens = [], dyntokens = [];
                    for (var ndx in formatCode) if (/\.*x$/.test(ndx)) {
                        var dynToken = ndx[0] + "\\d+";
                        -1 === dyntokens.indexOf(dynToken) && dyntokens.push(dynToken);
                    } else -1 === tokens.indexOf(ndx[0]) && tokens.push(ndx[0]);
                    opts.tokenizer = "(" + (0 < dyntokens.length ? dyntokens.join("|") + "|" : "") + tokens.join("+|") + ")+?|.", 
                    opts.tokenizer = new RegExp(opts.tokenizer, "g");
                }
                return opts.tokenizer;
            }
            function prefillYear(dateParts, currentResult, opts) {
                if (dateParts.year !== dateParts.rawyear) {
                    var crrntyear = currentYear.toString(), enteredPart = dateParts.rawyear.replace(/[^0-9]/g, ""), currentYearPart = crrntyear.slice(0, enteredPart.length), currentYearNextPart = crrntyear.slice(enteredPart.length);
                    if (2 === enteredPart.length && enteredPart === currentYearPart) {
                        var entryCurrentYear = new Date(currentYear, dateParts.month - 1, dateParts.day);
                        dateParts.day == entryCurrentYear.getDate() && (!opts.max || opts.max.date.getTime() >= entryCurrentYear.getTime()) && (dateParts.date.setFullYear(currentYear), 
                        dateParts.year = crrntyear, currentResult.insert = [ {
                            pos: currentResult.pos + 1,
                            c: currentYearNextPart[0]
                        }, {
                            pos: currentResult.pos + 2,
                            c: currentYearNextPart[1]
                        } ]);
                    }
                }
                return currentResult;
            }
            function isValidDate(dateParts, currentResult, opts) {
                if (!isFinite(dateParts.rawday) || "29" == dateParts.day && !isFinite(dateParts.rawyear) || new Date(dateParts.date.getFullYear(), isFinite(dateParts.rawmonth) ? dateParts.month : dateParts.date.getMonth() + 1, 0).getDate() >= dateParts.day) return currentResult;
                if ("29" == dateParts.day) {
                    var tokenMatch = getTokenMatch(currentResult.pos, opts);
                    if ("yyyy" === tokenMatch.targetMatch[0] && currentResult.pos - tokenMatch.targetMatchIndex == 2) return currentResult.remove = currentResult.pos + 1, 
                    currentResult;
                }
                return !1;
            }
            function isDateInRange(dateParts, result, opts, maskset, fromCheckval) {
                if (!result) return result;
                if (opts.min) {
                    if (dateParts.rawyear) {
                        var rawYear = dateParts.rawyear.replace(/[^0-9]/g, ""), minYear = opts.min.year.substr(0, rawYear.length), maxYear;
                        if (rawYear < minYear) {
                            var tokenMatch = getTokenMatch(result.pos, opts);
                            if (rawYear = dateParts.rawyear.substr(0, result.pos - tokenMatch.targetMatchIndex + 1), 
                            minYear = opts.min.year.substr(0, rawYear.length), minYear <= rawYear) return result.remove = tokenMatch.targetMatchIndex + rawYear.length, 
                            result;
                            if (rawYear = "yyyy" === tokenMatch.targetMatch[0] ? dateParts.rawyear.substr(1, 1) : dateParts.rawyear.substr(0, 1), 
                            minYear = opts.min.year.substr(2, 1), maxYear = opts.max ? opts.max.year.substr(2, 1) : rawYear, 
                            1 === rawYear.length && minYear <= rawYear <= maxYear && !0 !== fromCheckval) return "yyyy" === tokenMatch.targetMatch[0] ? (result.insert = [ {
                                pos: result.pos + 1,
                                c: rawYear,
                                strict: !0
                            } ], result.caret = result.pos + 2, maskset.validPositions[result.pos].input = opts.min.year[1]) : (result.insert = [ {
                                pos: result.pos + 1,
                                c: opts.min.year[1],
                                strict: !0
                            }, {
                                pos: result.pos + 2,
                                c: rawYear,
                                strict: !0
                            } ], result.caret = result.pos + 3, maskset.validPositions[result.pos].input = opts.min.year[0]), 
                            result;
                            result = !1;
                        }
                    }
                    result && dateParts.year && dateParts.year === dateParts.rawyear && opts.min.date.getTime() == opts.min.date.getTime() && (result = opts.min.date.getTime() <= dateParts.date.getTime());
                }
                return result && opts.max && opts.max.date.getTime() == opts.max.date.getTime() && (result = opts.max.date.getTime() >= dateParts.date.getTime()), 
                result;
            }
            function parse(format, dateObjValue, opts, raw) {
                var mask = "", match, fcode;
                for (getTokenizer(opts).lastIndex = 0; match = getTokenizer(opts).exec(format); ) if (void 0 === dateObjValue) if (fcode = formatcode(match)) mask += "(" + fcode[0] + ")"; else switch (match[0]) {
                  case "[":
                    mask += "(";
                    break;
    
                  case "]":
                    mask += ")?";
                    break;
    
                  default:
                    mask += (0, _escapeRegex.default)(match[0]);
                } else if (fcode = formatcode(match)) if (!0 !== raw && fcode[3]) {
                    var getFn = fcode[3];
                    mask += getFn.call(dateObjValue.date);
                } else fcode[2] ? mask += dateObjValue["raw" + fcode[2]] : mask += match[0]; else mask += match[0];
                return mask;
            }
            function pad(val, len) {
                for (val = String(val), len = len || 2; val.length < len; ) val = "0" + val;
                return val;
            }
            function analyseMask(maskString, format, opts) {
                var dateObj = {
                    date: new Date(1, 0, 1)
                }, targetProp, mask = maskString, match, dateOperation;
                function setValue(dateObj, value, opts) {
                    dateObj[targetProp] = value.replace(/[^0-9]/g, "0"), dateObj["raw" + targetProp] = value, 
                    void 0 !== dateOperation && dateOperation.call(dateObj.date, "month" == targetProp ? parseInt(dateObj[targetProp]) - 1 : dateObj[targetProp]);
                }
                if ("string" == typeof mask) {
                    for (getTokenizer(opts).lastIndex = 0; match = getTokenizer(opts).exec(format); ) {
                        var dynMatches = new RegExp("\\d+$").exec(match[0]), fcode = dynMatches ? match[0][0] + "x" : match[0], value = void 0;
                        if (dynMatches) {
                            var lastIndex = getTokenizer(opts).lastIndex, tokanMatch = getTokenMatch(match.index, opts);
                            getTokenizer(opts).lastIndex = lastIndex, value = mask.slice(0, mask.indexOf(tokanMatch.nextMatch[0]));
                        } else value = mask.slice(0, fcode.length);
                        Object.prototype.hasOwnProperty.call(formatCode, fcode) && (targetProp = formatCode[fcode][2], 
                        dateOperation = formatCode[fcode][1], setValue(dateObj, value, opts)), mask = mask.slice(value.length);
                    }
                    return dateObj;
                }
                if (mask && "object" === _typeof(mask) && Object.prototype.hasOwnProperty.call(mask, "date")) return mask;
            }
            function importDate(dateObj, opts) {
                return parse(opts.inputFormat, {
                    date: dateObj
                }, opts);
            }
            function getTokenMatch(pos, opts) {
                var calcPos = 0, targetMatch, match, matchLength = 0;
                for (getTokenizer(opts).lastIndex = 0; match = getTokenizer(opts).exec(opts.inputFormat); ) {
                    var dynMatches = new RegExp("\\d+$").exec(match[0]);
                    if (matchLength = dynMatches ? parseInt(dynMatches[0]) : match[0].length, calcPos += matchLength, 
                    pos <= calcPos) {
                        targetMatch = match, match = getTokenizer(opts).exec(opts.inputFormat);
                        break;
                    }
                }
                return {
                    targetMatchIndex: calcPos - matchLength,
                    nextMatch: match,
                    targetMatch: targetMatch
                };
            }
            _inputmask.default.extendAliases({
                datetime: {
                    mask: function mask(opts) {
                        return opts.numericInput = !1, formatCode.S = opts.i18n.ordinalSuffix.join("|"), 
                        opts.inputFormat = formatAlias[opts.inputFormat] || opts.inputFormat, opts.displayFormat = formatAlias[opts.displayFormat] || opts.displayFormat || opts.inputFormat, 
                        opts.outputFormat = formatAlias[opts.outputFormat] || opts.outputFormat || opts.inputFormat, 
                        opts.placeholder = "" !== opts.placeholder ? opts.placeholder : opts.inputFormat.replace(/[[\]]/, ""), 
                        opts.regex = parse(opts.inputFormat, void 0, opts), opts.min = analyseMask(opts.min, opts.inputFormat, opts), 
                        opts.max = analyseMask(opts.max, opts.inputFormat, opts), null;
                    },
                    placeholder: "",
                    inputFormat: "isoDateTime",
                    displayFormat: void 0,
                    outputFormat: void 0,
                    min: null,
                    max: null,
                    skipOptionalPartCharacter: "",
                    i18n: {
                        dayNames: [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ],
                        monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
                        ordinalSuffix: [ "st", "nd", "rd", "th" ]
                    },
                    preValidation: function preValidation(buffer, pos, c, isSelection, opts, maskset, caretPos, strict) {
                        if (strict) return !0;
                        if (isNaN(c) && buffer[pos] !== c) {
                            var tokenMatch = getTokenMatch(pos, opts);
                            if (tokenMatch.nextMatch && tokenMatch.nextMatch[0] === c && 1 < tokenMatch.targetMatch[0].length) {
                                var validator = formatCode[tokenMatch.targetMatch[0]][0];
                                if (new RegExp(validator).test("0" + buffer[pos - 1])) return buffer[pos] = buffer[pos - 1], 
                                buffer[pos - 1] = "0", {
                                    fuzzy: !0,
                                    buffer: buffer,
                                    refreshFromBuffer: {
                                        start: pos - 1,
                                        end: pos + 1
                                    },
                                    pos: pos + 1
                                };
                            }
                        }
                        return !0;
                    },
                    postValidation: function postValidation(buffer, pos, c, currentResult, opts, maskset, strict, fromCheckval) {
                        if (strict) return !0;
                        var tokenMatch, validator;
                        if (!1 === currentResult) return tokenMatch = getTokenMatch(pos + 1, opts), tokenMatch.targetMatch && tokenMatch.targetMatchIndex === pos && 1 < tokenMatch.targetMatch[0].length && void 0 !== formatCode[tokenMatch.targetMatch[0]] && (validator = formatCode[tokenMatch.targetMatch[0]][0], 
                        new RegExp(validator).test("0" + c)) ? {
                            insert: [ {
                                pos: pos,
                                c: "0"
                            }, {
                                pos: pos + 1,
                                c: c
                            } ],
                            pos: pos + 1
                        } : currentResult;
                        if (currentResult.fuzzy && (buffer = currentResult.buffer, pos = currentResult.pos), 
                        tokenMatch = getTokenMatch(pos, opts), tokenMatch.targetMatch && tokenMatch.targetMatch[0] && void 0 !== formatCode[tokenMatch.targetMatch[0]]) {
                            validator = formatCode[tokenMatch.targetMatch[0]][0];
                            var part = buffer.slice(tokenMatch.targetMatchIndex, tokenMatch.targetMatchIndex + tokenMatch.targetMatch[0].length);
                            !1 === new RegExp(validator).test(part.join("")) && 2 === tokenMatch.targetMatch[0].length && maskset.validPositions[tokenMatch.targetMatchIndex] && maskset.validPositions[tokenMatch.targetMatchIndex + 1] && (maskset.validPositions[tokenMatch.targetMatchIndex + 1].input = "0");
                        }
                        var result = currentResult, dateParts = analyseMask(buffer.join(""), opts.inputFormat, opts);
                        return result && dateParts.date.getTime() == dateParts.date.getTime() && (result = prefillYear(dateParts, result, opts), 
                        result = isValidDate(dateParts, result, opts), result = isDateInRange(dateParts, result, opts, maskset, fromCheckval)), 
                        pos && result && currentResult.pos !== pos ? {
                            buffer: parse(opts.inputFormat, dateParts, opts).split(""),
                            refreshFromBuffer: {
                                start: pos,
                                end: currentResult.pos
                            }
                        } : result;
                    },
                    onKeyDown: function onKeyDown(e, buffer, caretPos, opts) {
                        var input = this;
                        e.ctrlKey && e.keyCode === _keycode.default.RIGHT && (this.inputmask._valueSet(importDate(new Date(), opts)), 
                        $(this).trigger("setvalue"));
                    },
                    onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                        return unmaskedValue ? parse(opts.outputFormat, analyseMask(maskedValue, opts.inputFormat, opts), opts, !0) : unmaskedValue;
                    },
                    casing: function casing(elem, test, pos, validPositions) {
                        return 0 == test.nativeDef.indexOf("[ap]") ? elem.toLowerCase() : 0 == test.nativeDef.indexOf("[AP]") ? elem.toUpperCase() : elem;
                    },
                    onBeforeMask: function onBeforeMask(initialValue, opts) {
                        return "[object Date]" === Object.prototype.toString.call(initialValue) && (initialValue = importDate(initialValue, opts)), 
                        initialValue;
                    },
                    insertMode: !1,
                    shiftPositions: !1,
                    keepStatic: !1,
                    inputmode: "numeric"
                }
            });
        }, function(module, exports, __webpack_require__) {
            "use strict";
            var _inputmask = _interopRequireDefault(__webpack_require__(1)), _keycode = _interopRequireDefault(__webpack_require__(0)), _escapeRegex = _interopRequireDefault(__webpack_require__(14));
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            var $ = _inputmask.default.dependencyLib;
            function autoEscape(txt, opts) {
                for (var escapedTxt = "", i = 0; i < txt.length; i++) _inputmask.default.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker[0] === txt.charAt(i) || opts.optionalmarker[1] === txt.charAt(i) || opts.quantifiermarker[0] === txt.charAt(i) || opts.quantifiermarker[1] === txt.charAt(i) || opts.groupmarker[0] === txt.charAt(i) || opts.groupmarker[1] === txt.charAt(i) || opts.alternatormarker === txt.charAt(i) ? escapedTxt += "\\" + txt.charAt(i) : escapedTxt += txt.charAt(i);
                return escapedTxt;
            }
            function alignDigits(buffer, digits, opts, force) {
                if (0 < buffer.length && 0 < digits && (!opts.digitsOptional || force)) {
                    var radixPosition = buffer.indexOf(opts.radixPoint), negationBack = !1;
                    opts.negationSymbol.back === buffer[buffer.length - 1] && (negationBack = !0, buffer.length--), 
                    -1 === radixPosition && (buffer.push(opts.radixPoint), radixPosition = buffer.length - 1);
                    for (var i = 1; i <= digits; i++) isFinite(buffer[radixPosition + i]) || (buffer[radixPosition + i] = "0");
                }
                return negationBack && buffer.push(opts.negationSymbol.back), buffer;
            }
            function findValidator(symbol, maskset) {
                var posNdx = 0;
                if ("+" === symbol) {
                    for (posNdx in maskset.validPositions) ;
                    posNdx = parseInt(posNdx);
                }
                for (var tstNdx in maskset.tests) if (tstNdx = parseInt(tstNdx), posNdx <= tstNdx) for (var ndx = 0, ndxl = maskset.tests[tstNdx].length; ndx < ndxl; ndx++) if ((void 0 === maskset.validPositions[tstNdx] || "-" === symbol) && maskset.tests[tstNdx][ndx].match.def === symbol) return tstNdx + (void 0 !== maskset.validPositions[tstNdx] && "-" !== symbol ? 1 : 0);
                return posNdx;
            }
            function findValid(symbol, maskset) {
                var ret = -1;
                for (var ndx in maskset.validPositions) {
                    var tst = maskset.validPositions[ndx];
                    if (tst && tst.match.def === symbol) {
                        ret = parseInt(ndx);
                        break;
                    }
                }
                return ret;
            }
            function parseMinMaxOptions(opts) {
                void 0 === opts.parseMinMaxOptions && (null !== opts.min && (opts.min = opts.min.toString().replace(new RegExp((0, 
                _escapeRegex.default)(opts.groupSeparator), "g"), ""), "," === opts.radixPoint && (opts.min = opts.min.replace(opts.radixPoint, ".")), 
                opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN, isNaN(opts.min) && (opts.min = Number.MIN_VALUE)), 
                null !== opts.max && (opts.max = opts.max.toString().replace(new RegExp((0, _escapeRegex.default)(opts.groupSeparator), "g"), ""), 
                "," === opts.radixPoint && (opts.max = opts.max.replace(opts.radixPoint, ".")), 
                opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN, isNaN(opts.max) && (opts.max = Number.MAX_VALUE)), 
                opts.parseMinMaxOptions = "done");
            }
            function genMask(opts) {
                opts.repeat = 0, opts.groupSeparator === opts.radixPoint && opts.digits && "0" !== opts.digits && ("." === opts.radixPoint ? opts.groupSeparator = "," : "," === opts.radixPoint ? opts.groupSeparator = "." : opts.groupSeparator = ""), 
                " " === opts.groupSeparator && (opts.skipOptionalPartCharacter = void 0), 1 < opts.placeholder.length && (opts.placeholder = opts.placeholder.charAt(0)), 
                "radixFocus" === opts.positionCaretOnClick && "" === opts.placeholder && (opts.positionCaretOnClick = "lvp");
                var decimalDef = "0", radixPointDef = opts.radixPoint;
                !0 === opts.numericInput && void 0 === opts.__financeInput ? (decimalDef = "1", 
                opts.positionCaretOnClick = "radixFocus" === opts.positionCaretOnClick ? "lvp" : opts.positionCaretOnClick, 
                opts.digitsOptional = !1, isNaN(opts.digits) && (opts.digits = 2), opts._radixDance = !1, 
                radixPointDef = "," === opts.radixPoint ? "?" : "!", "" !== opts.radixPoint && void 0 === opts.definitions[radixPointDef] && (opts.definitions[radixPointDef] = {}, 
                opts.definitions[radixPointDef].validator = "[" + opts.radixPoint + "]", opts.definitions[radixPointDef].placeholder = opts.radixPoint, 
                opts.definitions[radixPointDef].static = !0, opts.definitions[radixPointDef].generated = !0)) : (opts.__financeInput = !1, 
                opts.numericInput = !0);
                var mask = "[+]", altMask;
                if (mask += autoEscape(opts.prefix, opts), "" !== opts.groupSeparator ? (void 0 === opts.definitions[opts.groupSeparator] && (opts.definitions[opts.groupSeparator] = {}, 
                opts.definitions[opts.groupSeparator].validator = "[" + opts.groupSeparator + "]", 
                opts.definitions[opts.groupSeparator].placeholder = opts.groupSeparator, opts.definitions[opts.groupSeparator].static = !0, 
                opts.definitions[opts.groupSeparator].generated = !0), mask += opts._mask(opts)) : mask += "9{+}", 
                void 0 !== opts.digits && 0 !== opts.digits) {
                    var dq = opts.digits.toString().split(",");
                    isFinite(dq[0]) && dq[1] && isFinite(dq[1]) ? mask += radixPointDef + decimalDef + "{" + opts.digits + "}" : (isNaN(opts.digits) || 0 < parseInt(opts.digits)) && (opts.digitsOptional ? (altMask = mask + radixPointDef + decimalDef + "{0," + opts.digits + "}", 
                    opts.keepStatic = !0) : mask += radixPointDef + decimalDef + "{" + opts.digits + "}");
                }
                return mask += autoEscape(opts.suffix, opts), mask += "[-]", altMask && (mask = [ altMask + autoEscape(opts.suffix, opts) + "[-]", mask ]), 
                opts.greedy = !1, parseMinMaxOptions(opts), mask;
            }
            function hanndleRadixDance(pos, c, radixPos, maskset, opts) {
                return opts._radixDance && opts.numericInput && c !== opts.negationSymbol.back && pos <= radixPos && (0 < radixPos || c == opts.radixPoint) && (void 0 === maskset.validPositions[pos - 1] || maskset.validPositions[pos - 1].input !== opts.negationSymbol.back) && (pos -= 1), 
                pos;
            }
            function decimalValidator(chrs, maskset, pos, strict, opts) {
                var radixPos = maskset.buffer ? maskset.buffer.indexOf(opts.radixPoint) : -1, result = -1 !== radixPos && new RegExp("[0-9\uff11-\uff19]").test(chrs);
                return opts._radixDance && result && null == maskset.validPositions[radixPos] ? {
                    insert: {
                        pos: radixPos === pos ? radixPos + 1 : radixPos,
                        c: opts.radixPoint
                    },
                    pos: pos
                } : result;
            }
            function checkForLeadingZeroes(buffer, opts) {
                var numberMatches = new RegExp("(^" + ("" !== opts.negationSymbol.front ? (0, _escapeRegex.default)(opts.negationSymbol.front) + "?" : "") + (0, 
                _escapeRegex.default)(opts.prefix) + ")(.*)(" + (0, _escapeRegex.default)(opts.suffix) + ("" != opts.negationSymbol.back ? (0, 
                _escapeRegex.default)(opts.negationSymbol.back) + "?" : "") + "$)").exec(buffer.slice().reverse().join("")), number = numberMatches ? numberMatches[2] : "", leadingzeroes = !1;
                return number && (number = number.split(opts.radixPoint.charAt(0))[0], leadingzeroes = new RegExp("^[0" + opts.groupSeparator + "]*").exec(number)), 
                !(!leadingzeroes || !(1 < leadingzeroes[0].length || 0 < leadingzeroes[0].length && leadingzeroes[0].length < number.length)) && leadingzeroes;
            }
            _inputmask.default.extendAliases({
                numeric: {
                    mask: genMask,
                    _mask: function _mask(opts) {
                        return "(" + opts.groupSeparator + "999){+|1}";
                    },
                    digits: "*",
                    digitsOptional: !0,
                    enforceDigitsOnBlur: !1,
                    radixPoint: ".",
                    positionCaretOnClick: "radixFocus",
                    _radixDance: !0,
                    groupSeparator: "",
                    allowMinus: !0,
                    negationSymbol: {
                        front: "-",
                        back: ""
                    },
                    prefix: "",
                    suffix: "",
                    min: null,
                    max: null,
                    SetMaxOnOverflow: !1,
                    step: 1,
                    inputType: "text",
                    unmaskAsNumber: !1,
                    roundingFN: Math.round,
                    inputmode: "numeric",
                    shortcuts: {
                        k: "000",
                        m: "000000"
                    },
                    placeholder: "0",
                    greedy: !1,
                    rightAlign: !0,
                    insertMode: !0,
                    autoUnmask: !1,
                    skipOptionalPartCharacter: "",
                    definitions: {
                        0: {
                            validator: decimalValidator
                        },
                        1: {
                            validator: decimalValidator,
                            definitionSymbol: "9"
                        },
                        "+": {
                            validator: function validator(chrs, maskset, pos, strict, opts) {
                                return opts.allowMinus && ("-" === chrs || chrs === opts.negationSymbol.front);
                            }
                        },
                        "-": {
                            validator: function validator(chrs, maskset, pos, strict, opts) {
                                return opts.allowMinus && chrs === opts.negationSymbol.back;
                            }
                        }
                    },
                    preValidation: function preValidation(buffer, pos, c, isSelection, opts, maskset, caretPos, strict) {
                        if (!1 !== opts.__financeInput && c === opts.radixPoint) return !1;
                        var pattern;
                        if (pattern = opts.shortcuts && opts.shortcuts[c]) {
                            if (1 < pattern.length) for (var inserts = [], i = 0; i < pattern.length; i++) inserts.push({
                                pos: pos + i,
                                c: pattern[i],
                                strict: !1
                            });
                            return {
                                insert: inserts
                            };
                        }
                        var radixPos = buffer.indexOf(opts.radixPoint), initPos = pos;
                        if (pos = hanndleRadixDance(pos, c, radixPos, maskset, opts), "-" === c || c === opts.negationSymbol.front) {
                            if (!0 !== opts.allowMinus) return !1;
                            var isNegative = !1, front = findValid("+", maskset), back = findValid("-", maskset);
                            return -1 !== front && (isNegative = [ front, back ]), !1 !== isNegative ? {
                                remove: isNegative,
                                caret: initPos - opts.negationSymbol.front.length
                            } : {
                                insert: [ {
                                    pos: findValidator("+", maskset),
                                    c: opts.negationSymbol.front,
                                    fromIsValid: !0
                                }, {
                                    pos: findValidator("-", maskset),
                                    c: opts.negationSymbol.back,
                                    fromIsValid: void 0
                                } ],
                                caret: initPos + opts.negationSymbol.back.length
                            };
                        }
                        if (c === opts.groupSeparator) return {
                            caret: initPos
                        };
                        if (strict) return !0;
                        if (-1 !== radixPos && !0 === opts._radixDance && !1 === isSelection && c === opts.radixPoint && void 0 !== opts.digits && (isNaN(opts.digits) || 0 < parseInt(opts.digits)) && radixPos !== pos) return {
                            caret: opts._radixDance && pos === radixPos - 1 ? radixPos + 1 : radixPos
                        };
                        if (!1 === opts.__financeInput) if (isSelection) {
                            if (opts.digitsOptional) return {
                                rewritePosition: caretPos.end
                            };
                            if (!opts.digitsOptional) {
                                if (caretPos.begin > radixPos && caretPos.end <= radixPos) return c === opts.radixPoint ? {
                                    insert: {
                                        pos: radixPos + 1,
                                        c: "0",
                                        fromIsValid: !0
                                    },
                                    rewritePosition: radixPos
                                } : {
                                    rewritePosition: radixPos + 1
                                };
                                if (caretPos.begin < radixPos) return {
                                    rewritePosition: caretPos.begin - 1
                                };
                            }
                        } else if (!opts.showMaskOnHover && !opts.showMaskOnFocus && !opts.digitsOptional && 0 < opts.digits && "" === this.inputmask.__valueGet.call(this)) return {
                            rewritePosition: radixPos
                        };
                        return {
                            rewritePosition: pos
                        };
                    },
                    postValidation: function postValidation(buffer, pos, c, currentResult, opts, maskset, strict) {
                        if (!1 === currentResult) return currentResult;
                        if (strict) return !0;
                        if (null !== opts.min || null !== opts.max) {
                            var unmasked = opts.onUnMask(buffer.slice().reverse().join(""), void 0, $.extend({}, opts, {
                                unmaskAsNumber: !0
                            }));
                            if (null !== opts.min && unmasked < opts.min && (unmasked.toString().length > opts.min.toString().length || unmasked < 0)) return !1;
                            if (null !== opts.max && unmasked > opts.max) return !!opts.SetMaxOnOverflow && {
                                refreshFromBuffer: !0,
                                buffer: alignDigits(opts.max.toString().replace(".", opts.radixPoint).split(""), opts.digits, opts).reverse()
                            };
                        }
                        return currentResult;
                    },
                    onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                        if ("" === unmaskedValue && !0 === opts.nullable) return unmaskedValue;
                        var processValue = maskedValue.replace(opts.prefix, "");
                        return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp((0, 
                        _escapeRegex.default)(opts.groupSeparator), "g"), ""), "" !== opts.placeholder.charAt(0) && (processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0")), 
                        opts.unmaskAsNumber ? ("" !== opts.radixPoint && -1 !== processValue.indexOf(opts.radixPoint) && (processValue = processValue.replace(_escapeRegex.default.call(this, opts.radixPoint), ".")), 
                        processValue = processValue.replace(new RegExp("^" + (0, _escapeRegex.default)(opts.negationSymbol.front)), "-"), 
                        processValue = processValue.replace(new RegExp((0, _escapeRegex.default)(opts.negationSymbol.back) + "$"), ""), 
                        Number(processValue)) : processValue;
                    },
                    isComplete: function isComplete(buffer, opts) {
                        var maskedValue = (opts.numericInput ? buffer.slice().reverse() : buffer).join("");
                        return maskedValue = maskedValue.replace(new RegExp("^" + (0, _escapeRegex.default)(opts.negationSymbol.front)), "-"), 
                        maskedValue = maskedValue.replace(new RegExp((0, _escapeRegex.default)(opts.negationSymbol.back) + "$"), ""), 
                        maskedValue = maskedValue.replace(opts.prefix, ""), maskedValue = maskedValue.replace(opts.suffix, ""), 
                        maskedValue = maskedValue.replace(new RegExp((0, _escapeRegex.default)(opts.groupSeparator) + "([0-9]{3})", "g"), "$1"), 
                        "," === opts.radixPoint && (maskedValue = maskedValue.replace((0, _escapeRegex.default)(opts.radixPoint), ".")), 
                        isFinite(maskedValue);
                    },
                    onBeforeMask: function onBeforeMask(initialValue, opts) {
                        var radixPoint = opts.radixPoint || ",";
                        isFinite(opts.digits) && (opts.digits = parseInt(opts.digits)), "number" != typeof initialValue && "number" !== opts.inputType || "" === radixPoint || (initialValue = initialValue.toString().replace(".", radixPoint));
                        var isNagtive = "-" === initialValue.charAt(0) || initialValue.charAt(0) === opts.negationSymbol.front, valueParts = initialValue.split(radixPoint), integerPart = valueParts[0].replace(/[^\-0-9]/g, ""), decimalPart = 1 < valueParts.length ? valueParts[1].replace(/[^0-9]/g, "") : "", forceDigits = 1 < valueParts.length;
                        initialValue = integerPart + ("" !== decimalPart ? radixPoint + decimalPart : decimalPart);
                        var digits = 0;
                        if ("" !== radixPoint && (digits = opts.digitsOptional ? opts.digits < decimalPart.length ? opts.digits : decimalPart.length : opts.digits, 
                        "" !== decimalPart || !opts.digitsOptional)) {
                            var digitsFactor = Math.pow(10, digits || 1);
                            initialValue = initialValue.replace((0, _escapeRegex.default)(radixPoint), "."), 
                            isNaN(parseFloat(initialValue)) || (initialValue = (opts.roundingFN(parseFloat(initialValue) * digitsFactor) / digitsFactor).toFixed(digits)), 
                            initialValue = initialValue.toString().replace(".", radixPoint);
                        }
                        if (0 === opts.digits && -1 !== initialValue.indexOf(radixPoint) && (initialValue = initialValue.substring(0, initialValue.indexOf(radixPoint))), 
                        null !== opts.min || null !== opts.max) {
                            var numberValue = initialValue.toString().replace(radixPoint, ".");
                            null !== opts.min && numberValue < opts.min ? initialValue = opts.min.toString().replace(".", radixPoint) : null !== opts.max && numberValue > opts.max && (initialValue = opts.max.toString().replace(".", radixPoint));
                        }
                        return isNagtive && "-" !== initialValue.charAt(0) && (initialValue = "-" + initialValue), 
                        alignDigits(initialValue.toString().split(""), digits, opts, forceDigits).join("");
                    },
                    onBeforeWrite: function onBeforeWrite(e, buffer, caretPos, opts) {
                        function stripBuffer(buffer, stripRadix) {
                            if (!1 !== opts.__financeInput || stripRadix) {
                                var position = buffer.indexOf(opts.radixPoint);
                                -1 !== position && buffer.splice(position, 1);
                            }
                            if ("" !== opts.groupSeparator) for (;-1 !== (position = buffer.indexOf(opts.groupSeparator)); ) buffer.splice(position, 1);
                            return buffer;
                        }
                        var result, leadingzeroes = checkForLeadingZeroes(buffer, opts);
                        if (leadingzeroes) for (var caretNdx = buffer.join("").lastIndexOf(leadingzeroes[0].split("").reverse().join("")) - (leadingzeroes[0] == leadingzeroes.input ? 0 : 1), offset = leadingzeroes[0] == leadingzeroes.input ? 1 : 0, i = leadingzeroes[0].length - offset; 0 < i; i--) delete this.maskset.validPositions[caretNdx + i], 
                        delete buffer[caretNdx + i];
                        if (e) switch (e.type) {
                          case "blur":
                          case "checkval":
                            if (null !== opts.min) {
                                var unmasked = opts.onUnMask(buffer.slice().reverse().join(""), void 0, $.extend({}, opts, {
                                    unmaskAsNumber: !0
                                }));
                                if (null !== opts.min && unmasked < opts.min) return {
                                    refreshFromBuffer: !0,
                                    buffer: alignDigits(opts.min.toString().replace(".", opts.radixPoint).split(""), opts.digits, opts).reverse()
                                };
                            }
                            if (buffer[buffer.length - 1] === opts.negationSymbol.front) {
                                var nmbrMtchs = new RegExp("(^" + ("" != opts.negationSymbol.front ? (0, _escapeRegex.default)(opts.negationSymbol.front) + "?" : "") + (0, 
                                _escapeRegex.default)(opts.prefix) + ")(.*)(" + (0, _escapeRegex.default)(opts.suffix) + ("" != opts.negationSymbol.back ? (0, 
                                _escapeRegex.default)(opts.negationSymbol.back) + "?" : "") + "$)").exec(stripBuffer(buffer.slice(), !0).reverse().join("")), number = nmbrMtchs ? nmbrMtchs[2] : "";
                                0 == number && (result = {
                                    refreshFromBuffer: !0,
                                    buffer: [ 0 ]
                                });
                            } else "" !== opts.radixPoint && buffer[0] === opts.radixPoint && (result && result.buffer ? result.buffer.shift() : (buffer.shift(), 
                            result = {
                                refreshFromBuffer: !0,
                                buffer: stripBuffer(buffer)
                            }));
                            if (opts.enforceDigitsOnBlur) {
                                result = result || {};
                                var bffr = result && result.buffer || buffer.slice().reverse();
                                result.refreshFromBuffer = !0, result.buffer = alignDigits(bffr, opts.digits, opts, !0).reverse();
                            }
                        }
                        return result;
                    },
                    onKeyDown: function onKeyDown(e, buffer, caretPos, opts) {
                        var $input = $(this), bffr;
                        if (e.ctrlKey) switch (e.keyCode) {
                          case _keycode.default.UP:
                            return this.inputmask.__valueSet.call(this, parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step)), 
                            $input.trigger("setvalue"), !1;
    
                          case _keycode.default.DOWN:
                            return this.inputmask.__valueSet.call(this, parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step)), 
                            $input.trigger("setvalue"), !1;
                        }
                        if (!e.shiftKey && (e.keyCode === _keycode.default.DELETE || e.keyCode === _keycode.default.BACKSPACE || e.keyCode === _keycode.default.BACKSPACE_SAFARI) && caretPos.begin !== buffer.length) {
                            if (buffer[e.keyCode === _keycode.default.DELETE ? caretPos.begin - 1 : caretPos.end] === opts.negationSymbol.front) return bffr = buffer.slice().reverse(), 
                            "" !== opts.negationSymbol.front && bffr.shift(), "" !== opts.negationSymbol.back && bffr.pop(), 
                            $input.trigger("setvalue", [ bffr.join(""), caretPos.begin ]), !1;
                            if (!0 === opts._radixDance) {
                                var radixPos = buffer.indexOf(opts.radixPoint);
                                if (opts.digitsOptional) {
                                    if (0 === radixPos) return bffr = buffer.slice().reverse(), bffr.pop(), $input.trigger("setvalue", [ bffr.join(""), caretPos.begin >= bffr.length ? bffr.length : caretPos.begin ]), 
                                    !1;
                                } else if (-1 !== radixPos && (caretPos.begin < radixPos || caretPos.end < radixPos || e.keyCode === _keycode.default.DELETE && caretPos.begin === radixPos)) return caretPos.begin !== caretPos.end || e.keyCode !== _keycode.default.BACKSPACE && e.keyCode !== _keycode.default.BACKSPACE_SAFARI || caretPos.begin++, 
                                bffr = buffer.slice().reverse(), bffr.splice(bffr.length - caretPos.begin, caretPos.begin - caretPos.end + 1), 
                                bffr = alignDigits(bffr, opts.digits, opts).join(""), $input.trigger("setvalue", [ bffr, caretPos.begin >= bffr.length ? radixPos + 1 : caretPos.begin ]), 
                                !1;
                            }
                        }
                    }
                },
                currency: {
                    prefix: "",
                    groupSeparator: ",",
                    alias: "numeric",
                    digits: 2,
                    digitsOptional: !1
                },
                decimal: {
                    alias: "numeric"
                },
                integer: {
                    alias: "numeric",
                    digits: 0
                },
                percentage: {
                    alias: "numeric",
                    min: 0,
                    max: 100,
                    suffix: " %",
                    digits: 0,
                    allowMinus: !1
                },
                indianns: {
                    alias: "numeric",
                    _mask: function _mask(opts) {
                        return "(" + opts.groupSeparator + "99){*|1}(" + opts.groupSeparator + "999){1|1}";
                    },
                    groupSeparator: ",",
                    radixPoint: ".",
                    placeholder: "0",
                    digits: 2,
                    digitsOptional: !1
                }
            });
        }, function(module, exports, __webpack_require__) {
            "use strict";
            var _window = _interopRequireDefault(__webpack_require__(13)), _inputmask = _interopRequireDefault(__webpack_require__(1));
            function _typeof(obj) {
                return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                    return typeof obj;
                } : function _typeof(obj) {
                    return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
                }, _typeof(obj);
            }
            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
            }
            function _inherits(subClass, superClass) {
                if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function");
                subClass.prototype = Object.create(superClass && superClass.prototype, {
                    constructor: {
                        value: subClass,
                        writable: !0,
                        configurable: !0
                    }
                }), superClass && _setPrototypeOf(subClass, superClass);
            }
            function _createSuper(Derived) {
                var hasNativeReflectConstruct = _isNativeReflectConstruct();
                return function _createSuperInternal() {
                    var Super = _getPrototypeOf(Derived), result;
                    if (hasNativeReflectConstruct) {
                        var NewTarget = _getPrototypeOf(this).constructor;
                        result = Reflect.construct(Super, arguments, NewTarget);
                    } else result = Super.apply(this, arguments);
                    return _possibleConstructorReturn(this, result);
                };
            }
            function _possibleConstructorReturn(self, call) {
                return !call || "object" !== _typeof(call) && "function" != typeof call ? _assertThisInitialized(self) : call;
            }
            function _assertThisInitialized(self) {
                if (void 0 === self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
                return self;
            }
            function _wrapNativeSuper(Class) {
                var _cache = "function" == typeof Map ? new Map() : void 0;
                return _wrapNativeSuper = function _wrapNativeSuper(Class) {
                    if (null === Class || !_isNativeFunction(Class)) return Class;
                    if ("function" != typeof Class) throw new TypeError("Super expression must either be null or a function");
                    if ("undefined" != typeof _cache) {
                        if (_cache.has(Class)) return _cache.get(Class);
                        _cache.set(Class, Wrapper);
                    }
                    function Wrapper() {
                        return _construct(Class, arguments, _getPrototypeOf(this).constructor);
                    }
                    return Wrapper.prototype = Object.create(Class.prototype, {
                        constructor: {
                            value: Wrapper,
                            enumerable: !1,
                            writable: !0,
                            configurable: !0
                        }
                    }), _setPrototypeOf(Wrapper, Class);
                }, _wrapNativeSuper(Class);
            }
            function _construct(Parent, args, Class) {
                return _construct = _isNativeReflectConstruct() ? Reflect.construct : function _construct(Parent, args, Class) {
                    var a = [ null ];
                    a.push.apply(a, args);
                    var Constructor = Function.bind.apply(Parent, a), instance = new Constructor();
                    return Class && _setPrototypeOf(instance, Class.prototype), instance;
                }, _construct.apply(null, arguments);
            }
            function _isNativeReflectConstruct() {
                if ("undefined" == typeof Reflect || !Reflect.construct) return !1;
                if (Reflect.construct.sham) return !1;
                if ("function" == typeof Proxy) return !0;
                try {
                    return Date.prototype.toString.call(Reflect.construct(Date, [], function() {})), 
                    !0;
                } catch (e) {
                    return !1;
                }
            }
            function _isNativeFunction(fn) {
                return -1 !== Function.toString.call(fn).indexOf("[native code]");
            }
            function _setPrototypeOf(o, p) {
                return _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
                    return o.__proto__ = p, o;
                }, _setPrototypeOf(o, p);
            }
            function _getPrototypeOf(o) {
                return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
                    return o.__proto__ || Object.getPrototypeOf(o);
                }, _getPrototypeOf(o);
            }
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            var document = _window.default.document;
            if (document && document.head && document.head.attachShadow && _window.default.customElements && void 0 === _window.default.customElements.get("input-mask")) {
                var InputmaskElement = function(_HTMLElement) {
                    _inherits(InputmaskElement, _HTMLElement);
                    var _super = _createSuper(InputmaskElement);
                    function InputmaskElement() {
                        var _this;
                        _classCallCheck(this, InputmaskElement), _this = _super.call(this);
                        var attributeNames = _this.getAttributeNames(), shadow = _this.attachShadow({
                            mode: "closed"
                        }), input = document.createElement("input");
                        for (var attr in input.type = "text", shadow.appendChild(input), attributeNames) Object.prototype.hasOwnProperty.call(attributeNames, attr) && input.setAttribute(attributeNames[attr], _this.getAttribute(attributeNames[attr]));
                        var im = new _inputmask.default();
                        return im.dataAttribute = "", im.mask(input), input.inputmask.shadowRoot = shadow, 
                        _this;
                    }
                    return InputmaskElement;
                }(_wrapNativeSuper(HTMLElement));
                _window.default.customElements.define("input-mask", InputmaskElement);
            }
        }, function(module, exports, __webpack_require__) {
            "use strict";
            var _jquery = _interopRequireDefault(__webpack_require__(8)), _inputmask = _interopRequireDefault(__webpack_require__(1));
            function _typeof(obj) {
                return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                    return typeof obj;
                } : function _typeof(obj) {
                    return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
                }, _typeof(obj);
            }
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            void 0 === _jquery.default.fn.inputmask && (_jquery.default.fn.inputmask = function(fn, options) {
                var nptmask, input = this[0];
                if (void 0 === options && (options = {}), "string" == typeof fn) switch (fn) {
                  case "unmaskedvalue":
                    return input && input.inputmask ? input.inputmask.unmaskedvalue() : (0, _jquery.default)(input).val();
    
                  case "remove":
                    return this.each(function() {
                        this.inputmask && this.inputmask.remove();
                    });
    
                  case "getemptymask":
                    return input && input.inputmask ? input.inputmask.getemptymask() : "";
    
                  case "hasMaskedValue":
                    return !(!input || !input.inputmask) && input.inputmask.hasMaskedValue();
    
                  case "isComplete":
                    return !input || !input.inputmask || input.inputmask.isComplete();
    
                  case "getmetadata":
                    return input && input.inputmask ? input.inputmask.getmetadata() : void 0;
    
                  case "setvalue":
                    _inputmask.default.setValue(input, options);
                    break;
    
                  case "option":
                    if ("string" != typeof options) return this.each(function() {
                        if (void 0 !== this.inputmask) return this.inputmask.option(options);
                    });
                    if (input && void 0 !== input.inputmask) return input.inputmask.option(options);
                    break;
    
                  default:
                    return options.alias = fn, nptmask = new _inputmask.default(options), this.each(function() {
                        nptmask.mask(this);
                    });
                } else {
                    if (Array.isArray(fn)) return options.alias = fn, nptmask = new _inputmask.default(options), 
                    this.each(function() {
                        nptmask.mask(this);
                    });
                    if ("object" == _typeof(fn)) return nptmask = new _inputmask.default(fn), void 0 === fn.mask && void 0 === fn.alias ? this.each(function() {
                        if (void 0 !== this.inputmask) return this.inputmask.option(fn);
                        nptmask.mask(this);
                    }) : this.each(function() {
                        nptmask.mask(this);
                    });
                    if (void 0 === fn) return this.each(function() {
                        nptmask = new _inputmask.default(options), nptmask.mask(this);
                    });
                }
            });
        }, function(module, exports, __webpack_require__) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: !0
            }), exports.default = void 0;
            var _bundle = _interopRequireDefault(__webpack_require__(15));
            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {
                    default: obj
                };
            }
            __webpack_require__(23);
            var _default = _bundle.default;
            exports.default = _default;
        } ], installedModules = {}, __webpack_require__.m = modules, __webpack_require__.c = installedModules, 
        __webpack_require__.d = function(exports, name, getter) {
            __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
                enumerable: !0,
                get: getter
            });
        }, __webpack_require__.r = function(exports) {
            "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(exports, Symbol.toStringTag, {
                value: "Module"
            }), Object.defineProperty(exports, "__esModule", {
                value: !0
            });
        }, __webpack_require__.t = function(value, mode) {
            if (1 & mode && (value = __webpack_require__(value)), 8 & mode) return value;
            if (4 & mode && "object" == typeof value && value && value.__esModule) return value;
            var ns = Object.create(null);
            if (__webpack_require__.r(ns), Object.defineProperty(ns, "default", {
                enumerable: !0,
                value: value
            }), 2 & mode && "string" != typeof value) for (var key in value) __webpack_require__.d(ns, key, function(key) {
                return value[key];
            }.bind(null, key));
            return ns;
        }, __webpack_require__.n = function(module) {
            var getter = module && module.__esModule ? function getDefault() {
                return module.default;
            } : function getModuleExports() {
                return module;
            };
            return __webpack_require__.d(getter, "a", getter), getter;
        }, __webpack_require__.o = function(object, property) {
            return Object.prototype.hasOwnProperty.call(object, property);
        }, __webpack_require__.p = "", __webpack_require__(__webpack_require__.s = 24);
        function __webpack_require__(moduleId) {
            if (installedModules[moduleId]) return installedModules[moduleId].exports;
            var module = installedModules[moduleId] = {
                i: moduleId,
                l: !1,
                exports: {}
            };
            return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
            module.l = !0, module.exports;
        }
        var modules, installedModules;
    });
    ( function( factory ) {
    	if ( typeof define === "function" && define.amd ) {
    
    		// AMD. Register as an anonymous module.
    		define( [ "jquery" ], factory );
    	} else {
    
    		// Browser globals
    		factory( jQuery );
    	}
    } ( function( $ ) {
    
    $.ui = $.ui || {};
    
    return $.ui.version = "1.12.1";
    
    } ) );
    
    /*!
     * jQuery UI Position 1.12.1
     * http://jqueryui.com
     *
     * Copyright jQuery Foundation and other contributors
     * Released under the MIT license.
     * http://jquery.org/license
     *
     * http://api.jqueryui.com/position/
     */
    
    //>>label: Position
    //>>group: Core
    //>>description: Positions elements relative to other elements.
    //>>docs: http://api.jqueryui.com/position/
    //>>demos: http://jqueryui.com/position/
    
    ( function( factory ) {
    	if ( typeof define === "function" && define.amd ) {
    
    		// AMD. Register as an anonymous module.
    		define( [ "jquery", "./version" ], factory );
    	} else {
    
    		// Browser globals
    		factory( jQuery );
    	}
    }( function( $ ) {
    ( function() {
    var cachedScrollbarWidth,
    	max = Math.max,
    	abs = Math.abs,
    	rhorizontal = /left|center|right/,
    	rvertical = /top|center|bottom/,
    	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
    	rposition = /^\w+/,
    	rpercent = /%$/,
    	_position = $.fn.position;
    
    function getOffsets( offsets, width, height ) {
    	return [
    		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
    		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
    	];
    }
    
    function parseCss( element, property ) {
    	return parseInt( $.css( element, property ), 10 ) || 0;
    }
    
    function getDimensions( elem ) {
    	var raw = elem[ 0 ];
    	if ( raw.nodeType === 9 ) {
    		return {
    			width: elem.width(),
    			height: elem.height(),
    			offset: { top: 0, left: 0 }
    		};
    	}
    	if ( $.isWindow( raw ) ) {
    		return {
    			width: elem.width(),
    			height: elem.height(),
    			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
    		};
    	}
    	if ( raw.preventDefault ) {
    		return {
    			width: 0,
    			height: 0,
    			offset: { top: raw.pageY, left: raw.pageX }
    		};
    	}
    	return {
    		width: elem.outerWidth(),
    		height: elem.outerHeight(),
    		offset: elem.offset()
    	};
    }
    
    $.position = {
    	scrollbarWidth: function() {
    		if ( cachedScrollbarWidth !== undefined ) {
    			return cachedScrollbarWidth;
    		}
    		var w1, w2,
    			div = $( "<div " +
    				"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
    				"<div style='height:100px;width:auto;'></div></div>" ),
    			innerDiv = div.children()[ 0 ];
    
    		$( "body" ).append( div );
    		w1 = innerDiv.offsetWidth;
    		div.css( "overflow", "scroll" );
    
    		w2 = innerDiv.offsetWidth;
    
    		if ( w1 === w2 ) {
    			w2 = div[ 0 ].clientWidth;
    		}
    
    		div.remove();
    
    		return ( cachedScrollbarWidth = w1 - w2 );
    	},
    	getScrollInfo: function( within ) {
    		var overflowX = within.isWindow || within.isDocument ? "" :
    				within.element.css( "overflow-x" ),
    			overflowY = within.isWindow || within.isDocument ? "" :
    				within.element.css( "overflow-y" ),
    			hasOverflowX = overflowX === "scroll" ||
    				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
    			hasOverflowY = overflowY === "scroll" ||
    				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
    		return {
    			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
    			height: hasOverflowX ? $.position.scrollbarWidth() : 0
    		};
    	},
    	getWithinInfo: function( element ) {
    		var withinElement = $( element || window ),
    			isWindow = $.isWindow( withinElement[ 0 ] ),
    			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
    			hasOffset = !isWindow && !isDocument;
    		return {
    			element: withinElement,
    			isWindow: isWindow,
    			isDocument: isDocument,
    			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
    			scrollLeft: withinElement.scrollLeft(),
    			scrollTop: withinElement.scrollTop(),
    			width: withinElement.outerWidth(),
    			height: withinElement.outerHeight()
    		};
    	}
    };
    
    $.fn.position = function( options ) {
    	if ( !options || !options.of ) {
    		return _position.apply( this, arguments );
    	}
    
    	// Make a copy, we don't want to modify arguments
    	options = $.extend( {}, options );
    
    	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
    		target = $( options.of ),
    		within = $.position.getWithinInfo( options.within ),
    		scrollInfo = $.position.getScrollInfo( within ),
    		collision = ( options.collision || "flip" ).split( " " ),
    		offsets = {};
    
    	dimensions = getDimensions( target );
    	if ( target[ 0 ].preventDefault ) {
    
    		// Force left top to allow flipping
    		options.at = "left top";
    	}
    	targetWidth = dimensions.width;
    	targetHeight = dimensions.height;
    	targetOffset = dimensions.offset;
    
    	// Clone to reuse original targetOffset later
    	basePosition = $.extend( {}, targetOffset );
    
    	// Force my and at to have valid horizontal and vertical positions
    	// if a value is missing or invalid, it will be converted to center
    	$.each( [ "my", "at" ], function() {
    		var pos = ( options[ this ] || "" ).split( " " ),
    			horizontalOffset,
    			verticalOffset;
    
    		if ( pos.length === 1 ) {
    			pos = rhorizontal.test( pos[ 0 ] ) ?
    				pos.concat( [ "center" ] ) :
    				rvertical.test( pos[ 0 ] ) ?
    					[ "center" ].concat( pos ) :
    					[ "center", "center" ];
    		}
    		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
    		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
    
    		// Calculate offsets
    		horizontalOffset = roffset.exec( pos[ 0 ] );
    		verticalOffset = roffset.exec( pos[ 1 ] );
    		offsets[ this ] = [
    			horizontalOffset ? horizontalOffset[ 0 ] : 0,
    			verticalOffset ? verticalOffset[ 0 ] : 0
    		];
    
    		// Reduce to just the positions without the offsets
    		options[ this ] = [
    			rposition.exec( pos[ 0 ] )[ 0 ],
    			rposition.exec( pos[ 1 ] )[ 0 ]
    		];
    	} );
    
    	// Normalize collision option
    	if ( collision.length === 1 ) {
    		collision[ 1 ] = collision[ 0 ];
    	}
    
    	if ( options.at[ 0 ] === "right" ) {
    		basePosition.left += targetWidth;
    	} else if ( options.at[ 0 ] === "center" ) {
    		basePosition.left += targetWidth / 2;
    	}
    
    	if ( options.at[ 1 ] === "bottom" ) {
    		basePosition.top += targetHeight;
    	} else if ( options.at[ 1 ] === "center" ) {
    		basePosition.top += targetHeight / 2;
    	}
    
    	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
    	basePosition.left += atOffset[ 0 ];
    	basePosition.top += atOffset[ 1 ];
    
    	return this.each( function() {
    		var collisionPosition, using,
    			elem = $( this ),
    			elemWidth = elem.outerWidth(),
    			elemHeight = elem.outerHeight(),
    			marginLeft = parseCss( this, "marginLeft" ),
    			marginTop = parseCss( this, "marginTop" ),
    			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
    				scrollInfo.width,
    			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
    				scrollInfo.height,
    			position = $.extend( {}, basePosition ),
    			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
    
    		if ( options.my[ 0 ] === "right" ) {
    			position.left -= elemWidth;
    		} else if ( options.my[ 0 ] === "center" ) {
    			position.left -= elemWidth / 2;
    		}
    
    		if ( options.my[ 1 ] === "bottom" ) {
    			position.top -= elemHeight;
    		} else if ( options.my[ 1 ] === "center" ) {
    			position.top -= elemHeight / 2;
    		}
    
    		position.left += myOffset[ 0 ];
    		position.top += myOffset[ 1 ];
    
    		collisionPosition = {
    			marginLeft: marginLeft,
    			marginTop: marginTop
    		};
    
    		$.each( [ "left", "top" ], function( i, dir ) {
    			if ( $.ui.position[ collision[ i ] ] ) {
    				$.ui.position[ collision[ i ] ][ dir ]( position, {
    					targetWidth: targetWidth,
    					targetHeight: targetHeight,
    					elemWidth: elemWidth,
    					elemHeight: elemHeight,
    					collisionPosition: collisionPosition,
    					collisionWidth: collisionWidth,
    					collisionHeight: collisionHeight,
    					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
    					my: options.my,
    					at: options.at,
    					within: within,
    					elem: elem
    				} );
    			}
    		} );
    
    		if ( options.using ) {
    
    			// Adds feedback as second argument to using callback, if present
    			using = function( props ) {
    				var left = targetOffset.left - position.left,
    					right = left + targetWidth - elemWidth,
    					top = targetOffset.top - position.top,
    					bottom = top + targetHeight - elemHeight,
    					feedback = {
    						target: {
    							element: target,
    							left: targetOffset.left,
    							top: targetOffset.top,
    							width: targetWidth,
    							height: targetHeight
    						},
    						element: {
    							element: elem,
    							left: position.left,
    							top: position.top,
    							width: elemWidth,
    							height: elemHeight
    						},
    						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
    						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
    					};
    				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
    					feedback.horizontal = "center";
    				}
    				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
    					feedback.vertical = "middle";
    				}
    				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
    					feedback.important = "horizontal";
    				} else {
    					feedback.important = "vertical";
    				}
    				options.using.call( this, props, feedback );
    			};
    		}
    
    		elem.offset( $.extend( position, { using: using } ) );
    	} );
    };
    
    $.ui.position = {
    	fit: {
    		left: function( position, data ) {
    			var within = data.within,
    				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
    				outerWidth = within.width,
    				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
    				overLeft = withinOffset - collisionPosLeft,
    				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
    				newOverRight;
    
    			// Element is wider than within
    			if ( data.collisionWidth > outerWidth ) {
    
    				// Element is initially over the left side of within
    				if ( overLeft > 0 && overRight <= 0 ) {
    					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
    						withinOffset;
    					position.left += overLeft - newOverRight;
    
    				// Element is initially over right side of within
    				} else if ( overRight > 0 && overLeft <= 0 ) {
    					position.left = withinOffset;
    
    				// Element is initially over both left and right sides of within
    				} else {
    					if ( overLeft > overRight ) {
    						position.left = withinOffset + outerWidth - data.collisionWidth;
    					} else {
    						position.left = withinOffset;
    					}
    				}
    
    			// Too far left -> align with left edge
    			} else if ( overLeft > 0 ) {
    				position.left += overLeft;
    
    			// Too far right -> align with right edge
    			} else if ( overRight > 0 ) {
    				position.left -= overRight;
    
    			// Adjust based on position and margin
    			} else {
    				position.left = max( position.left - collisionPosLeft, position.left );
    			}
    		},
    		top: function( position, data ) {
    			var within = data.within,
    				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
    				outerHeight = data.within.height,
    				collisionPosTop = position.top - data.collisionPosition.marginTop,
    				overTop = withinOffset - collisionPosTop,
    				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
    				newOverBottom;
    
    			// Element is taller than within
    			if ( data.collisionHeight > outerHeight ) {
    
    				// Element is initially over the top of within
    				if ( overTop > 0 && overBottom <= 0 ) {
    					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
    						withinOffset;
    					position.top += overTop - newOverBottom;
    
    				// Element is initially over bottom of within
    				} else if ( overBottom > 0 && overTop <= 0 ) {
    					position.top = withinOffset;
    
    				// Element is initially over both top and bottom of within
    				} else {
    					if ( overTop > overBottom ) {
    						position.top = withinOffset + outerHeight - data.collisionHeight;
    					} else {
    						position.top = withinOffset;
    					}
    				}
    
    			// Too far up -> align with top
    			} else if ( overTop > 0 ) {
    				position.top += overTop;
    
    			// Too far down -> align with bottom edge
    			} else if ( overBottom > 0 ) {
    				position.top -= overBottom;
    
    			// Adjust based on position and margin
    			} else {
    				position.top = max( position.top - collisionPosTop, position.top );
    			}
    		}
    	},
    	flip: {
    		left: function( position, data ) {
    			var within = data.within,
    				withinOffset = within.offset.left + within.scrollLeft,
    				outerWidth = within.width,
    				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
    				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
    				overLeft = collisionPosLeft - offsetLeft,
    				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
    				myOffset = data.my[ 0 ] === "left" ?
    					-data.elemWidth :
    					data.my[ 0 ] === "right" ?
    						data.elemWidth :
    						0,
    				atOffset = data.at[ 0 ] === "left" ?
    					data.targetWidth :
    					data.at[ 0 ] === "right" ?
    						-data.targetWidth :
    						0,
    				offset = -2 * data.offset[ 0 ],
    				newOverRight,
    				newOverLeft;
    
    			if ( overLeft < 0 ) {
    				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
    					outerWidth - withinOffset;
    				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
    					position.left += myOffset + atOffset + offset;
    				}
    			} else if ( overRight > 0 ) {
    				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
    					atOffset + offset - offsetLeft;
    				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
    					position.left += myOffset + atOffset + offset;
    				}
    			}
    		},
    		top: function( position, data ) {
    			var within = data.within,
    				withinOffset = within.offset.top + within.scrollTop,
    				outerHeight = within.height,
    				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
    				collisionPosTop = position.top - data.collisionPosition.marginTop,
    				overTop = collisionPosTop - offsetTop,
    				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
    				top = data.my[ 1 ] === "top",
    				myOffset = top ?
    					-data.elemHeight :
    					data.my[ 1 ] === "bottom" ?
    						data.elemHeight :
    						0,
    				atOffset = data.at[ 1 ] === "top" ?
    					data.targetHeight :
    					data.at[ 1 ] === "bottom" ?
    						-data.targetHeight :
    						0,
    				offset = -2 * data.offset[ 1 ],
    				newOverTop,
    				newOverBottom;
    			if ( overTop < 0 ) {
    				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
    					outerHeight - withinOffset;
    				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
    					position.top += myOffset + atOffset + offset;
    				}
    			} else if ( overBottom > 0 ) {
    				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
    					offset - offsetTop;
    				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
    					position.top += myOffset + atOffset + offset;
    				}
    			}
    		}
    	},
    	flipfit: {
    		left: function() {
    			$.ui.position.flip.left.apply( this, arguments );
    			$.ui.position.fit.left.apply( this, arguments );
    		},
    		top: function() {
    			$.ui.position.flip.top.apply( this, arguments );
    			$.ui.position.fit.top.apply( this, arguments );
    		}
    	}
    };
    
    } )();
    
    return $.ui.position;
    
    } ) );
    
    ;/*! showdown v 1.9.1 - 02-11-2019 */
    (function(){
    /**
     * Created by Tivie on 13-07-2015.
     */
    
    function getDefaultOpts (simple) {
      'use strict';
    
      var defaultOptions = {
        omitExtraWLInCodeBlocks: {
          defaultValue: false,
          describe: 'Omit the default extra whiteline added to code blocks',
          type: 'boolean'
        },
        noHeaderId: {
          defaultValue: false,
          describe: 'Turn on/off generated header id',
          type: 'boolean'
        },
        prefixHeaderId: {
          defaultValue: false,
          describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix',
          type: 'string'
        },
        rawPrefixHeaderId: {
          defaultValue: false,
          describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',
          type: 'boolean'
        },
        ghCompatibleHeaderId: {
          defaultValue: false,
          describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
          type: 'boolean'
        },
        rawHeaderId: {
          defaultValue: false,
          describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
          type: 'boolean'
        },
        headerLevelStart: {
          defaultValue: false,
          describe: 'The header blocks level start',
          type: 'integer'
        },
        parseImgDimensions: {
          defaultValue: false,
          describe: 'Turn on/off image dimension parsing',
          type: 'boolean'
        },
        simplifiedAutoLink: {
          defaultValue: false,
          describe: 'Turn on/off GFM autolink style',
          type: 'boolean'
        },
        excludeTrailingPunctuationFromURLs: {
          defaultValue: false,
          describe: 'Excludes trailing punctuation from links generated with autoLinking',
          type: 'boolean'
        },
        literalMidWordUnderscores: {
          defaultValue: false,
          describe: 'Parse midword underscores as literal underscores',
          type: 'boolean'
        },
        literalMidWordAsterisks: {
          defaultValue: false,
          describe: 'Parse midword asterisks as literal asterisks',
          type: 'boolean'
        },
        strikethrough: {
          defaultValue: false,
          describe: 'Turn on/off strikethrough support',
          type: 'boolean'
        },
        tables: {
          defaultValue: false,
          describe: 'Turn on/off tables support',
          type: 'boolean'
        },
        tablesHeaderId: {
          defaultValue: false,
          describe: 'Add an id to table headers',
          type: 'boolean'
        },
        ghCodeBlocks: {
          defaultValue: true,
          describe: 'Turn on/off GFM fenced code blocks support',
          type: 'boolean'
        },
        tasklists: {
          defaultValue: false,
          describe: 'Turn on/off GFM tasklist support',
          type: 'boolean'
        },
        smoothLivePreview: {
          defaultValue: false,
          describe: 'Prevents weird effects in live previews due to incomplete input',
          type: 'boolean'
        },
        smartIndentationFix: {
          defaultValue: false,
          description: 'Tries to smartly fix indentation in es6 strings',
          type: 'boolean'
        },
        disableForced4SpacesIndentedSublists: {
          defaultValue: false,
          description: 'Disables the requirement of indenting nested sublists by 4 spaces',
          type: 'boolean'
        },
        simpleLineBreaks: {
          defaultValue: false,
          description: 'Parses simple line breaks as <br> (GFM Style)',
          type: 'boolean'
        },
        requireSpaceBeforeHeadingText: {
          defaultValue: false,
          description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
          type: 'boolean'
        },
        ghMentions: {
          defaultValue: false,
          description: 'Enables github @mentions',
          type: 'boolean'
        },
        ghMentionsLink: {
          defaultValue: 'https://github.com/{u}',
          description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
          type: 'string'
        },
        encodeEmails: {
          defaultValue: true,
          description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
          type: 'boolean'
        },
        openLinksInNewWindow: {
          defaultValue: false,
          description: 'Open all links in new windows',
          type: 'boolean'
        },
        backslashEscapesHTMLTags: {
          defaultValue: false,
          description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
          type: 'boolean'
        },
        emoji: {
          defaultValue: false,
          description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
          type: 'boolean'
        },
        underline: {
          defaultValue: false,
          description: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `<em>` and `<strong>`',
          type: 'boolean'
        },
        completeHTMLDocument: {
          defaultValue: false,
          description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
          type: 'boolean'
        },
        metadata: {
          defaultValue: false,
          description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
          type: 'boolean'
        },
        splitAdjacentBlockquotes: {
          defaultValue: false,
          description: 'Split adjacent blockquote blocks',
          type: 'boolean'
        }
      };
      if (simple === false) {
        return JSON.parse(JSON.stringify(defaultOptions));
      }
      var ret = {};
      for (var opt in defaultOptions) {
        if (defaultOptions.hasOwnProperty(opt)) {
          ret[opt] = defaultOptions[opt].defaultValue;
        }
      }
      return ret;
    }
    
    function allOptionsOn () {
      'use strict';
      var options = getDefaultOpts(true),
          ret = {};
      for (var opt in options) {
        if (options.hasOwnProperty(opt)) {
          ret[opt] = true;
        }
      }
      return ret;
    }
    
    /**
     * Created by Tivie on 06-01-2015.
     */
    
    // Private properties
    var showdown = {},
        parsers = {},
        extensions = {},
        globalOptions = getDefaultOpts(true),
        setFlavor = 'vanilla',
        flavor = {
          github: {
            omitExtraWLInCodeBlocks:              true,
            simplifiedAutoLink:                   true,
            excludeTrailingPunctuationFromURLs:   true,
            literalMidWordUnderscores:            true,
            strikethrough:                        true,
            tables:                               true,
            tablesHeaderId:                       true,
            ghCodeBlocks:                         true,
            tasklists:                            true,
            disableForced4SpacesIndentedSublists: true,
            simpleLineBreaks:                     true,
            requireSpaceBeforeHeadingText:        true,
            ghCompatibleHeaderId:                 true,
            ghMentions:                           true,
            backslashEscapesHTMLTags:             true,
            emoji:                                true,
            splitAdjacentBlockquotes:             true
          },
          original: {
            noHeaderId:                           true,
            ghCodeBlocks:                         false
          },
          ghost: {
            omitExtraWLInCodeBlocks:              true,
            parseImgDimensions:                   true,
            simplifiedAutoLink:                   true,
            excludeTrailingPunctuationFromURLs:   true,
            literalMidWordUnderscores:            true,
            strikethrough:                        true,
            tables:                               true,
            tablesHeaderId:                       true,
            ghCodeBlocks:                         true,
            tasklists:                            true,
            smoothLivePreview:                    true,
            simpleLineBreaks:                     true,
            requireSpaceBeforeHeadingText:        true,
            ghMentions:                           false,
            encodeEmails:                         true
          },
          vanilla: getDefaultOpts(true),
          allOn: allOptionsOn()
        };
    
    /**
     * helper namespace
     * @type {{}}
     */
    showdown.helper = {};
    
    /**
     * TODO LEGACY SUPPORT CODE
     * @type {{}}
     */
    showdown.extensions = {};
    
    /**
     * Set a global option
     * @static
     * @param {string} key
     * @param {*} value
     * @returns {showdown}
     */
    showdown.setOption = function (key, value) {
      'use strict';
      globalOptions[key] = value;
      return this;
    };
    
    /**
     * Get a global option
     * @static
     * @param {string} key
     * @returns {*}
     */
    showdown.getOption = function (key) {
      'use strict';
      return globalOptions[key];
    };
    
    /**
     * Get the global options
     * @static
     * @returns {{}}
     */
    showdown.getOptions = function () {
      'use strict';
      return globalOptions;
    };
    
    /**
     * Reset global options to the default values
     * @static
     */
    showdown.resetOptions = function () {
      'use strict';
      globalOptions = getDefaultOpts(true);
    };
    
    /**
     * Set the flavor showdown should use as default
     * @param {string} name
     */
    showdown.setFlavor = function (name) {
      'use strict';
      if (!flavor.hasOwnProperty(name)) {
        throw Error(name + ' flavor was not found');
      }
      showdown.resetOptions();
      var preset = flavor[name];
      setFlavor = name;
      for (var option in preset) {
        if (preset.hasOwnProperty(option)) {
          globalOptions[option] = preset[option];
        }
      }
    };
    
    /**
     * Get the currently set flavor
     * @returns {string}
     */
    showdown.getFlavor = function () {
      'use strict';
      return setFlavor;
    };
    
    /**
     * Get the options of a specified flavor. Returns undefined if the flavor was not found
     * @param {string} name Name of the flavor
     * @returns {{}|undefined}
     */
    showdown.getFlavorOptions = function (name) {
      'use strict';
      if (flavor.hasOwnProperty(name)) {
        return flavor[name];
      }
    };
    
    /**
     * Get the default options
     * @static
     * @param {boolean} [simple=true]
     * @returns {{}}
     */
    showdown.getDefaultOptions = function (simple) {
      'use strict';
      return getDefaultOpts(simple);
    };
    
    /**
     * Get or set a subParser
     *
     * subParser(name)       - Get a registered subParser
     * subParser(name, func) - Register a subParser
     * @static
     * @param {string} name
     * @param {function} [func]
     * @returns {*}
     */
    showdown.subParser = function (name, func) {
      'use strict';
      if (showdown.helper.isString(name)) {
        if (typeof func !== 'undefined') {
          parsers[name] = func;
        } else {
          if (parsers.hasOwnProperty(name)) {
            return parsers[name];
          } else {
            throw Error('SubParser named ' + name + ' not registered!');
          }
        }
      }
    };
    
    /**
     * Gets or registers an extension
     * @static
     * @param {string} name
     * @param {object|function=} ext
     * @returns {*}
     */
    showdown.extension = function (name, ext) {
      'use strict';
    
      if (!showdown.helper.isString(name)) {
        throw Error('Extension \'name\' must be a string');
      }
    
      name = showdown.helper.stdExtName(name);
    
      // Getter
      if (showdown.helper.isUndefined(ext)) {
        if (!extensions.hasOwnProperty(name)) {
          throw Error('Extension named ' + name + ' is not registered!');
        }
        return extensions[name];
    
        // Setter
      } else {
        // Expand extension if it's wrapped in a function
        if (typeof ext === 'function') {
          ext = ext();
        }
    
        // Ensure extension is an array
        if (!showdown.helper.isArray(ext)) {
          ext = [ext];
        }
    
        var validExtension = validate(ext, name);
    
        if (validExtension.valid) {
          extensions[name] = ext;
        } else {
          throw Error(validExtension.error);
        }
      }
    };
    
    /**
     * Gets all extensions registered
     * @returns {{}}
     */
    showdown.getAllExtensions = function () {
      'use strict';
      return extensions;
    };
    
    /**
     * Remove an extension
     * @param {string} name
     */
    showdown.removeExtension = function (name) {
      'use strict';
      delete extensions[name];
    };
    
    /**
     * Removes all extensions
     */
    showdown.resetExtensions = function () {
      'use strict';
      extensions = {};
    };
    
    /**
     * Validate extension
     * @param {array} extension
     * @param {string} name
     * @returns {{valid: boolean, error: string}}
     */
    function validate (extension, name) {
      'use strict';
    
      var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
          ret = {
            valid: true,
            error: ''
          };
    
      if (!showdown.helper.isArray(extension)) {
        extension = [extension];
      }
    
      for (var i = 0; i < extension.length; ++i) {
        var baseMsg = errMsg + ' sub-extension ' + i + ': ',
            ext = extension[i];
        if (typeof ext !== 'object') {
          ret.valid = false;
          ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
          return ret;
        }
    
        if (!showdown.helper.isString(ext.type)) {
          ret.valid = false;
          ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
          return ret;
        }
    
        var type = ext.type = ext.type.toLowerCase();
    
        // normalize extension type
        if (type === 'language') {
          type = ext.type = 'lang';
        }
    
        if (type === 'html') {
          type = ext.type = 'output';
        }
    
        if (type !== 'lang' && type !== 'output' && type !== 'listener') {
          ret.valid = false;
          ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
          return ret;
        }
    
        if (type === 'listener') {
          if (showdown.helper.isUndefined(ext.listeners)) {
            ret.valid = false;
            ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
            return ret;
          }
        } else {
          if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
            ret.valid = false;
            ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
            return ret;
          }
        }
    
        if (ext.listeners) {
          if (typeof ext.listeners !== 'object') {
            ret.valid = false;
            ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
            return ret;
          }
          for (var ln in ext.listeners) {
            if (ext.listeners.hasOwnProperty(ln)) {
              if (typeof ext.listeners[ln] !== 'function') {
                ret.valid = false;
                ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
                  ' must be a function but ' + typeof ext.listeners[ln] + ' given';
                return ret;
              }
            }
          }
        }
    
        if (ext.filter) {
          if (typeof ext.filter !== 'function') {
            ret.valid = false;
            ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
            return ret;
          }
        } else if (ext.regex) {
          if (showdown.helper.isString(ext.regex)) {
            ext.regex = new RegExp(ext.regex, 'g');
          }
          if (!(ext.regex instanceof RegExp)) {
            ret.valid = false;
            ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
            return ret;
          }
          if (showdown.helper.isUndefined(ext.replace)) {
            ret.valid = false;
            ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
            return ret;
          }
        }
      }
      return ret;
    }
    
    /**
     * Validate extension
     * @param {object} ext
     * @returns {boolean}
     */
    showdown.validateExtension = function (ext) {
      'use strict';
    
      var validateExtension = validate(ext, null);
      if (!validateExtension.valid) {
        console.warn(validateExtension.error);
        return false;
      }
      return true;
    };
    
    /**
     * showdownjs helper functions
     */
    
    if (!showdown.hasOwnProperty('helper')) {
      showdown.helper = {};
    }
    
    /**
     * Check if var is string
     * @static
     * @param {string} a
     * @returns {boolean}
     */
    showdown.helper.isString = function (a) {
      'use strict';
      return (typeof a === 'string' || a instanceof String);
    };
    
    /**
     * Check if var is a function
     * @static
     * @param {*} a
     * @returns {boolean}
     */
    showdown.helper.isFunction = function (a) {
      'use strict';
      var getType = {};
      return a && getType.toString.call(a) === '[object Function]';
    };
    
    /**
     * isArray helper function
     * @static
     * @param {*} a
     * @returns {boolean}
     */
    showdown.helper.isArray = function (a) {
      'use strict';
      return Array.isArray(a);
    };
    
    /**
     * Check if value is undefined
     * @static
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
     */
    showdown.helper.isUndefined = function (value) {
      'use strict';
      return typeof value === 'undefined';
    };
    
    /**
     * ForEach helper function
     * Iterates over Arrays and Objects (own properties only)
     * @static
     * @param {*} obj
     * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object
     */
    showdown.helper.forEach = function (obj, callback) {
      'use strict';
      // check if obj is defined
      if (showdown.helper.isUndefined(obj)) {
        throw new Error('obj param is required');
      }
    
      if (showdown.helper.isUndefined(callback)) {
        throw new Error('callback param is required');
      }
    
      if (!showdown.helper.isFunction(callback)) {
        throw new Error('callback param must be a function/closure');
      }
    
      if (typeof obj.forEach === 'function') {
        obj.forEach(callback);
      } else if (showdown.helper.isArray(obj)) {
        for (var i = 0; i < obj.length; i++) {
          callback(obj[i], i, obj);
        }
      } else if (typeof (obj) === 'object') {
        for (var prop in obj) {
          if (obj.hasOwnProperty(prop)) {
            callback(obj[prop], prop, obj);
          }
        }
      } else {
        throw new Error('obj does not seem to be an array or an iterable object');
      }
    };
    
    /**
     * Standardidize extension name
     * @static
     * @param {string} s extension name
     * @returns {string}
     */
    showdown.helper.stdExtName = function (s) {
      'use strict';
      return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase();
    };
    
    function escapeCharactersCallback (wholeMatch, m1) {
      'use strict';
      var charCodeToEscape = m1.charCodeAt(0);
      return '¨E' + charCodeToEscape + 'E';
    }
    
    /**
     * Callback used to escape characters when passing through String.replace
     * @static
     * @param {string} wholeMatch
     * @param {string} m1
     * @returns {string}
     */
    showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
    
    /**
     * Escape characters in a string
     * @static
     * @param {string} text
     * @param {string} charsToEscape
     * @param {boolean} afterBackslash
     * @returns {XML|string|void|*}
     */
    showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) {
      'use strict';
      // First we have to escape the escape characters so that
      // we can build a character class out of them
      var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
    
      if (afterBackslash) {
        regexString = '\\\\' + regexString;
      }
    
      var regex = new RegExp(regexString, 'g');
      text = text.replace(regex, escapeCharactersCallback);
    
      return text;
    };
    
    /**
     * Unescape HTML entities
     * @param txt
     * @returns {string}
     */
    showdown.helper.unescapeHTMLEntities = function (txt) {
      'use strict';
    
      return txt
        .replace(/&quot;/g, '"')
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
    };
    
    var rgxFindMatchPos = function (str, left, right, flags) {
      'use strict';
      var f = flags || '',
          g = f.indexOf('g') > -1,
          x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
          l = new RegExp(left, f.replace(/g/g, '')),
          pos = [],
          t, s, m, start, end;
    
      do {
        t = 0;
        while ((m = x.exec(str))) {
          if (l.test(m[0])) {
            if (!(t++)) {
              s = x.lastIndex;
              start = s - m[0].length;
            }
          } else if (t) {
            if (!--t) {
              end = m.index + m[0].length;
              var obj = {
                left: {start: start, end: s},
                match: {start: s, end: m.index},
                right: {start: m.index, end: end},
                wholeMatch: {start: start, end: end}
              };
              pos.push(obj);
              if (!g) {
                return pos;
              }
            }
          }
        }
      } while (t && (x.lastIndex = s));
    
      return pos;
    };
    
    /**
     * matchRecursiveRegExp
     *
     * (c) 2007 Steven Levithan <stevenlevithan.com>
     * MIT License
     *
     * Accepts a string to search, a left and right format delimiter
     * as regex patterns, and optional regex flags. Returns an array
     * of matches, allowing nested instances of left/right delimiters.
     * Use the "g" flag to return all matches, otherwise only the
     * first is returned. Be careful to ensure that the left and
     * right format delimiters produce mutually exclusive matches.
     * Backreferences are not supported within the right delimiter
     * due to how it is internally combined with the left delimiter.
     * When matching strings whose format delimiters are unbalanced
     * to the left or right, the output is intentionally as a
     * conventional regex library with recursion support would
     * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
     * "<" and ">" as the delimiters (both strings contain a single,
     * balanced instance of "<x>").
     *
     * examples:
     * matchRecursiveRegExp("test", "\\(", "\\)")
     * returns: []
     * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
     * returns: ["t<<e>><s>", ""]
     * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
     * returns: ["test"]
     */
    showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
      'use strict';
    
      var matchPos = rgxFindMatchPos (str, left, right, flags),
          results = [];
    
      for (var i = 0; i < matchPos.length; ++i) {
        results.push([
          str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
          str.slice(matchPos[i].match.start, matchPos[i].match.end),
          str.slice(matchPos[i].left.start, matchPos[i].left.end),
          str.slice(matchPos[i].right.start, matchPos[i].right.end)
        ]);
      }
      return results;
    };
    
    /**
     *
     * @param {string} str
     * @param {string|function} replacement
     * @param {string} left
     * @param {string} right
     * @param {string} flags
     * @returns {string}
     */
    showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
      'use strict';
    
      if (!showdown.helper.isFunction(replacement)) {
        var repStr = replacement;
        replacement = function () {
          return repStr;
        };
      }
    
      var matchPos = rgxFindMatchPos(str, left, right, flags),
          finalStr = str,
          lng = matchPos.length;
    
      if (lng > 0) {
        var bits = [];
        if (matchPos[0].wholeMatch.start !== 0) {
          bits.push(str.slice(0, matchPos[0].wholeMatch.start));
        }
        for (var i = 0; i < lng; ++i) {
          bits.push(
            replacement(
              str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
              str.slice(matchPos[i].match.start, matchPos[i].match.end),
              str.slice(matchPos[i].left.start, matchPos[i].left.end),
              str.slice(matchPos[i].right.start, matchPos[i].right.end)
            )
          );
          if (i < lng - 1) {
            bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
          }
        }
        if (matchPos[lng - 1].wholeMatch.end < str.length) {
          bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
        }
        finalStr = bits.join('');
      }
      return finalStr;
    };
    
    /**
     * Returns the index within the passed String object of the first occurrence of the specified regex,
     * starting the search at fromIndex. Returns -1 if the value is not found.
     *
     * @param {string} str string to search
     * @param {RegExp} regex Regular expression to search
     * @param {int} [fromIndex = 0] Index to start the search
     * @returns {Number}
     * @throws InvalidArgumentError
     */
    showdown.helper.regexIndexOf = function (str, regex, fromIndex) {
      'use strict';
      if (!showdown.helper.isString(str)) {
        throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
      }
      if (regex instanceof RegExp === false) {
        throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp';
      }
      var indexOf = str.substring(fromIndex || 0).search(regex);
      return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf;
    };
    
    /**
     * Splits the passed string object at the defined index, and returns an array composed of the two substrings
     * @param {string} str string to split
     * @param {int} index index to split string at
     * @returns {[string,string]}
     * @throws InvalidArgumentError
     */
    showdown.helper.splitAtIndex = function (str, index) {
      'use strict';
      if (!showdown.helper.isString(str)) {
        throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
      }
      return [str.substring(0, index), str.substring(index)];
    };
    
    /**
     * Obfuscate an e-mail address through the use of Character Entities,
     * transforming ASCII characters into their equivalent decimal or hex entities.
     *
     * Since it has a random component, subsequent calls to this function produce different results
     *
     * @param {string} mail
     * @returns {string}
     */
    showdown.helper.encodeEmailAddress = function (mail) {
      'use strict';
      var encode = [
        function (ch) {
          return '&#' + ch.charCodeAt(0) + ';';
        },
        function (ch) {
          return '&#x' + ch.charCodeAt(0).toString(16) + ';';
        },
        function (ch) {
          return ch;
        }
      ];
    
      mail = mail.replace(/./g, function (ch) {
        if (ch === '@') {
          // this *must* be encoded. I insist.
          ch = encode[Math.floor(Math.random() * 2)](ch);
        } else {
          var r = Math.random();
          // roughly 10% raw, 45% hex, 45% dec
          ch = (
            r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
          );
        }
        return ch;
      });
    
      return mail;
    };
    
    /**
     *
     * @param str
     * @param targetLength
     * @param padString
     * @returns {string}
     */
    showdown.helper.padEnd = function padEnd (str, targetLength, padString) {
      'use strict';
      /*jshint bitwise: false*/
      // eslint-disable-next-line space-infix-ops
      targetLength = targetLength>>0; //floor if number or convert non-number to 0;
      /*jshint bitwise: true*/
      padString = String(padString || ' ');
      if (str.length > targetLength) {
        return String(str);
      } else {
        targetLength = targetLength - str.length;
        if (targetLength > padString.length) {
          padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
        }
        return String(str) + padString.slice(0,targetLength);
      }
    };
    
    /**
     * POLYFILLS
     */
    // use this instead of builtin is undefined for IE8 compatibility
    if (typeof console === 'undefined') {
      console = {
        warn: function (msg) {
          'use strict';
          alert(msg);
        },
        log: function (msg) {
          'use strict';
          alert(msg);
        },
        error: function (msg) {
          'use strict';
          throw msg;
        }
      };
    }
    
    /**
     * Common regexes.
     * We declare some common regexes to improve performance
     */
    showdown.helper.regexes = {
      asteriskDashAndColon: /([*_:~])/g
    };
    
    /**
     * EMOJIS LIST
     */
    showdown.helper.emojis = {
      '+1':'\ud83d\udc4d',
      '-1':'\ud83d\udc4e',
      '100':'\ud83d\udcaf',
      '1234':'\ud83d\udd22',
      '1st_place_medal':'\ud83e\udd47',
      '2nd_place_medal':'\ud83e\udd48',
      '3rd_place_medal':'\ud83e\udd49',
      '8ball':'\ud83c\udfb1',
      'a':'\ud83c\udd70\ufe0f',
      'ab':'\ud83c\udd8e',
      'abc':'\ud83d\udd24',
      'abcd':'\ud83d\udd21',
      'accept':'\ud83c\ude51',
      'aerial_tramway':'\ud83d\udea1',
      'airplane':'\u2708\ufe0f',
      'alarm_clock':'\u23f0',
      'alembic':'\u2697\ufe0f',
      'alien':'\ud83d\udc7d',
      'ambulance':'\ud83d\ude91',
      'amphora':'\ud83c\udffa',
      'anchor':'\u2693\ufe0f',
      'angel':'\ud83d\udc7c',
      'anger':'\ud83d\udca2',
      'angry':'\ud83d\ude20',
      'anguished':'\ud83d\ude27',
      'ant':'\ud83d\udc1c',
      'apple':'\ud83c\udf4e',
      'aquarius':'\u2652\ufe0f',
      'aries':'\u2648\ufe0f',
      'arrow_backward':'\u25c0\ufe0f',
      'arrow_double_down':'\u23ec',
      'arrow_double_up':'\u23eb',
      'arrow_down':'\u2b07\ufe0f',
      'arrow_down_small':'\ud83d\udd3d',
      'arrow_forward':'\u25b6\ufe0f',
      'arrow_heading_down':'\u2935\ufe0f',
      'arrow_heading_up':'\u2934\ufe0f',
      'arrow_left':'\u2b05\ufe0f',
      'arrow_lower_left':'\u2199\ufe0f',
      'arrow_lower_right':'\u2198\ufe0f',
      'arrow_right':'\u27a1\ufe0f',
      'arrow_right_hook':'\u21aa\ufe0f',
      'arrow_up':'\u2b06\ufe0f',
      'arrow_up_down':'\u2195\ufe0f',
      'arrow_up_small':'\ud83d\udd3c',
      'arrow_upper_left':'\u2196\ufe0f',
      'arrow_upper_right':'\u2197\ufe0f',
      'arrows_clockwise':'\ud83d\udd03',
      'arrows_counterclockwise':'\ud83d\udd04',
      'art':'\ud83c\udfa8',
      'articulated_lorry':'\ud83d\ude9b',
      'artificial_satellite':'\ud83d\udef0',
      'astonished':'\ud83d\ude32',
      'athletic_shoe':'\ud83d\udc5f',
      'atm':'\ud83c\udfe7',
      'atom_symbol':'\u269b\ufe0f',
      'avocado':'\ud83e\udd51',
      'b':'\ud83c\udd71\ufe0f',
      'baby':'\ud83d\udc76',
      'baby_bottle':'\ud83c\udf7c',
      'baby_chick':'\ud83d\udc24',
      'baby_symbol':'\ud83d\udebc',
      'back':'\ud83d\udd19',
      'bacon':'\ud83e\udd53',
      'badminton':'\ud83c\udff8',
      'baggage_claim':'\ud83d\udec4',
      'baguette_bread':'\ud83e\udd56',
      'balance_scale':'\u2696\ufe0f',
      'balloon':'\ud83c\udf88',
      'ballot_box':'\ud83d\uddf3',
      'ballot_box_with_check':'\u2611\ufe0f',
      'bamboo':'\ud83c\udf8d',
      'banana':'\ud83c\udf4c',
      'bangbang':'\u203c\ufe0f',
      'bank':'\ud83c\udfe6',
      'bar_chart':'\ud83d\udcca',
      'barber':'\ud83d\udc88',
      'baseball':'\u26be\ufe0f',
      'basketball':'\ud83c\udfc0',
      'basketball_man':'\u26f9\ufe0f',
      'basketball_woman':'\u26f9\ufe0f&zwj;\u2640\ufe0f',
      'bat':'\ud83e\udd87',
      'bath':'\ud83d\udec0',
      'bathtub':'\ud83d\udec1',
      'battery':'\ud83d\udd0b',
      'beach_umbrella':'\ud83c\udfd6',
      'bear':'\ud83d\udc3b',
      'bed':'\ud83d\udecf',
      'bee':'\ud83d\udc1d',
      'beer':'\ud83c\udf7a',
      'beers':'\ud83c\udf7b',
      'beetle':'\ud83d\udc1e',
      'beginner':'\ud83d\udd30',
      'bell':'\ud83d\udd14',
      'bellhop_bell':'\ud83d\udece',
      'bento':'\ud83c\udf71',
      'biking_man':'\ud83d\udeb4',
      'bike':'\ud83d\udeb2',
      'biking_woman':'\ud83d\udeb4&zwj;\u2640\ufe0f',
      'bikini':'\ud83d\udc59',
      'biohazard':'\u2623\ufe0f',
      'bird':'\ud83d\udc26',
      'birthday':'\ud83c\udf82',
      'black_circle':'\u26ab\ufe0f',
      'black_flag':'\ud83c\udff4',
      'black_heart':'\ud83d\udda4',
      'black_joker':'\ud83c\udccf',
      'black_large_square':'\u2b1b\ufe0f',
      'black_medium_small_square':'\u25fe\ufe0f',
      'black_medium_square':'\u25fc\ufe0f',
      'black_nib':'\u2712\ufe0f',
      'black_small_square':'\u25aa\ufe0f',
      'black_square_button':'\ud83d\udd32',
      'blonde_man':'\ud83d\udc71',
      'blonde_woman':'\ud83d\udc71&zwj;\u2640\ufe0f',
      'blossom':'\ud83c\udf3c',
      'blowfish':'\ud83d\udc21',
      'blue_book':'\ud83d\udcd8',
      'blue_car':'\ud83d\ude99',
      'blue_heart':'\ud83d\udc99',
      'blush':'\ud83d\ude0a',
      'boar':'\ud83d\udc17',
      'boat':'\u26f5\ufe0f',
      'bomb':'\ud83d\udca3',
      'book':'\ud83d\udcd6',
      'bookmark':'\ud83d\udd16',
      'bookmark_tabs':'\ud83d\udcd1',
      'books':'\ud83d\udcda',
      'boom':'\ud83d\udca5',
      'boot':'\ud83d\udc62',
      'bouquet':'\ud83d\udc90',
      'bowing_man':'\ud83d\ude47',
      'bow_and_arrow':'\ud83c\udff9',
      'bowing_woman':'\ud83d\ude47&zwj;\u2640\ufe0f',
      'bowling':'\ud83c\udfb3',
      'boxing_glove':'\ud83e\udd4a',
      'boy':'\ud83d\udc66',
      'bread':'\ud83c\udf5e',
      'bride_with_veil':'\ud83d\udc70',
      'bridge_at_night':'\ud83c\udf09',
      'briefcase':'\ud83d\udcbc',
      'broken_heart':'\ud83d\udc94',
      'bug':'\ud83d\udc1b',
      'building_construction':'\ud83c\udfd7',
      'bulb':'\ud83d\udca1',
      'bullettrain_front':'\ud83d\ude85',
      'bullettrain_side':'\ud83d\ude84',
      'burrito':'\ud83c\udf2f',
      'bus':'\ud83d\ude8c',
      'business_suit_levitating':'\ud83d\udd74',
      'busstop':'\ud83d\ude8f',
      'bust_in_silhouette':'\ud83d\udc64',
      'busts_in_silhouette':'\ud83d\udc65',
      'butterfly':'\ud83e\udd8b',
      'cactus':'\ud83c\udf35',
      'cake':'\ud83c\udf70',
      'calendar':'\ud83d\udcc6',
      'call_me_hand':'\ud83e\udd19',
      'calling':'\ud83d\udcf2',
      'camel':'\ud83d\udc2b',
      'camera':'\ud83d\udcf7',
      'camera_flash':'\ud83d\udcf8',
      'camping':'\ud83c\udfd5',
      'cancer':'\u264b\ufe0f',
      'candle':'\ud83d\udd6f',
      'candy':'\ud83c\udf6c',
      'canoe':'\ud83d\udef6',
      'capital_abcd':'\ud83d\udd20',
      'capricorn':'\u2651\ufe0f',
      'car':'\ud83d\ude97',
      'card_file_box':'\ud83d\uddc3',
      'card_index':'\ud83d\udcc7',
      'card_index_dividers':'\ud83d\uddc2',
      'carousel_horse':'\ud83c\udfa0',
      'carrot':'\ud83e\udd55',
      'cat':'\ud83d\udc31',
      'cat2':'\ud83d\udc08',
      'cd':'\ud83d\udcbf',
      'chains':'\u26d3',
      'champagne':'\ud83c\udf7e',
      'chart':'\ud83d\udcb9',
      'chart_with_downwards_trend':'\ud83d\udcc9',
      'chart_with_upwards_trend':'\ud83d\udcc8',
      'checkered_flag':'\ud83c\udfc1',
      'cheese':'\ud83e\uddc0',
      'cherries':'\ud83c\udf52',
      'cherry_blossom':'\ud83c\udf38',
      'chestnut':'\ud83c\udf30',
      'chicken':'\ud83d\udc14',
      'children_crossing':'\ud83d\udeb8',
      'chipmunk':'\ud83d\udc3f',
      'chocolate_bar':'\ud83c\udf6b',
      'christmas_tree':'\ud83c\udf84',
      'church':'\u26ea\ufe0f',
      'cinema':'\ud83c\udfa6',
      'circus_tent':'\ud83c\udfaa',
      'city_sunrise':'\ud83c\udf07',
      'city_sunset':'\ud83c\udf06',
      'cityscape':'\ud83c\udfd9',
      'cl':'\ud83c\udd91',
      'clamp':'\ud83d\udddc',
      'clap':'\ud83d\udc4f',
      'clapper':'\ud83c\udfac',
      'classical_building':'\ud83c\udfdb',
      'clinking_glasses':'\ud83e\udd42',
      'clipboard':'\ud83d\udccb',
      'clock1':'\ud83d\udd50',
      'clock10':'\ud83d\udd59',
      'clock1030':'\ud83d\udd65',
      'clock11':'\ud83d\udd5a',
      'clock1130':'\ud83d\udd66',
      'clock12':'\ud83d\udd5b',
      'clock1230':'\ud83d\udd67',
      'clock130':'\ud83d\udd5c',
      'clock2':'\ud83d\udd51',
      'clock230':'\ud83d\udd5d',
      'clock3':'\ud83d\udd52',
      'clock330':'\ud83d\udd5e',
      'clock4':'\ud83d\udd53',
      'clock430':'\ud83d\udd5f',
      'clock5':'\ud83d\udd54',
      'clock530':'\ud83d\udd60',
      'clock6':'\ud83d\udd55',
      'clock630':'\ud83d\udd61',
      'clock7':'\ud83d\udd56',
      'clock730':'\ud83d\udd62',
      'clock8':'\ud83d\udd57',
      'clock830':'\ud83d\udd63',
      'clock9':'\ud83d\udd58',
      'clock930':'\ud83d\udd64',
      'closed_book':'\ud83d\udcd5',
      'closed_lock_with_key':'\ud83d\udd10',
      'closed_umbrella':'\ud83c\udf02',
      'cloud':'\u2601\ufe0f',
      'cloud_with_lightning':'\ud83c\udf29',
      'cloud_with_lightning_and_rain':'\u26c8',
      'cloud_with_rain':'\ud83c\udf27',
      'cloud_with_snow':'\ud83c\udf28',
      'clown_face':'\ud83e\udd21',
      'clubs':'\u2663\ufe0f',
      'cocktail':'\ud83c\udf78',
      'coffee':'\u2615\ufe0f',
      'coffin':'\u26b0\ufe0f',
      'cold_sweat':'\ud83d\ude30',
      'comet':'\u2604\ufe0f',
      'computer':'\ud83d\udcbb',
      'computer_mouse':'\ud83d\uddb1',
      'confetti_ball':'\ud83c\udf8a',
      'confounded':'\ud83d\ude16',
      'confused':'\ud83d\ude15',
      'congratulations':'\u3297\ufe0f',
      'construction':'\ud83d\udea7',
      'construction_worker_man':'\ud83d\udc77',
      'construction_worker_woman':'\ud83d\udc77&zwj;\u2640\ufe0f',
      'control_knobs':'\ud83c\udf9b',
      'convenience_store':'\ud83c\udfea',
      'cookie':'\ud83c\udf6a',
      'cool':'\ud83c\udd92',
      'policeman':'\ud83d\udc6e',
      'copyright':'\u00a9\ufe0f',
      'corn':'\ud83c\udf3d',
      'couch_and_lamp':'\ud83d\udecb',
      'couple':'\ud83d\udc6b',
      'couple_with_heart_woman_man':'\ud83d\udc91',
      'couple_with_heart_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc68',
      'couple_with_heart_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc69',
      'couplekiss_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc68',
      'couplekiss_man_woman':'\ud83d\udc8f',
      'couplekiss_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc69',
      'cow':'\ud83d\udc2e',
      'cow2':'\ud83d\udc04',
      'cowboy_hat_face':'\ud83e\udd20',
      'crab':'\ud83e\udd80',
      'crayon':'\ud83d\udd8d',
      'credit_card':'\ud83d\udcb3',
      'crescent_moon':'\ud83c\udf19',
      'cricket':'\ud83c\udfcf',
      'crocodile':'\ud83d\udc0a',
      'croissant':'\ud83e\udd50',
      'crossed_fingers':'\ud83e\udd1e',
      'crossed_flags':'\ud83c\udf8c',
      'crossed_swords':'\u2694\ufe0f',
      'crown':'\ud83d\udc51',
      'cry':'\ud83d\ude22',
      'crying_cat_face':'\ud83d\ude3f',
      'crystal_ball':'\ud83d\udd2e',
      'cucumber':'\ud83e\udd52',
      'cupid':'\ud83d\udc98',
      'curly_loop':'\u27b0',
      'currency_exchange':'\ud83d\udcb1',
      'curry':'\ud83c\udf5b',
      'custard':'\ud83c\udf6e',
      'customs':'\ud83d\udec3',
      'cyclone':'\ud83c\udf00',
      'dagger':'\ud83d\udde1',
      'dancer':'\ud83d\udc83',
      'dancing_women':'\ud83d\udc6f',
      'dancing_men':'\ud83d\udc6f&zwj;\u2642\ufe0f',
      'dango':'\ud83c\udf61',
      'dark_sunglasses':'\ud83d\udd76',
      'dart':'\ud83c\udfaf',
      'dash':'\ud83d\udca8',
      'date':'\ud83d\udcc5',
      'deciduous_tree':'\ud83c\udf33',
      'deer':'\ud83e\udd8c',
      'department_store':'\ud83c\udfec',
      'derelict_house':'\ud83c\udfda',
      'desert':'\ud83c\udfdc',
      'desert_island':'\ud83c\udfdd',
      'desktop_computer':'\ud83d\udda5',
      'male_detective':'\ud83d\udd75\ufe0f',
      'diamond_shape_with_a_dot_inside':'\ud83d\udca0',
      'diamonds':'\u2666\ufe0f',
      'disappointed':'\ud83d\ude1e',
      'disappointed_relieved':'\ud83d\ude25',
      'dizzy':'\ud83d\udcab',
      'dizzy_face':'\ud83d\ude35',
      'do_not_litter':'\ud83d\udeaf',
      'dog':'\ud83d\udc36',
      'dog2':'\ud83d\udc15',
      'dollar':'\ud83d\udcb5',
      'dolls':'\ud83c\udf8e',
      'dolphin':'\ud83d\udc2c',
      'door':'\ud83d\udeaa',
      'doughnut':'\ud83c\udf69',
      'dove':'\ud83d\udd4a',
      'dragon':'\ud83d\udc09',
      'dragon_face':'\ud83d\udc32',
      'dress':'\ud83d\udc57',
      'dromedary_camel':'\ud83d\udc2a',
      'drooling_face':'\ud83e\udd24',
      'droplet':'\ud83d\udca7',
      'drum':'\ud83e\udd41',
      'duck':'\ud83e\udd86',
      'dvd':'\ud83d\udcc0',
      'e-mail':'\ud83d\udce7',
      'eagle':'\ud83e\udd85',
      'ear':'\ud83d\udc42',
      'ear_of_rice':'\ud83c\udf3e',
      'earth_africa':'\ud83c\udf0d',
      'earth_americas':'\ud83c\udf0e',
      'earth_asia':'\ud83c\udf0f',
      'egg':'\ud83e\udd5a',
      'eggplant':'\ud83c\udf46',
      'eight_pointed_black_star':'\u2734\ufe0f',
      'eight_spoked_asterisk':'\u2733\ufe0f',
      'electric_plug':'\ud83d\udd0c',
      'elephant':'\ud83d\udc18',
      'email':'\u2709\ufe0f',
      'end':'\ud83d\udd1a',
      'envelope_with_arrow':'\ud83d\udce9',
      'euro':'\ud83d\udcb6',
      'european_castle':'\ud83c\udff0',
      'european_post_office':'\ud83c\udfe4',
      'evergreen_tree':'\ud83c\udf32',
      'exclamation':'\u2757\ufe0f',
      'expressionless':'\ud83d\ude11',
      'eye':'\ud83d\udc41',
      'eye_speech_bubble':'\ud83d\udc41&zwj;\ud83d\udde8',
      'eyeglasses':'\ud83d\udc53',
      'eyes':'\ud83d\udc40',
      'face_with_head_bandage':'\ud83e\udd15',
      'face_with_thermometer':'\ud83e\udd12',
      'fist_oncoming':'\ud83d\udc4a',
      'factory':'\ud83c\udfed',
      'fallen_leaf':'\ud83c\udf42',
      'family_man_woman_boy':'\ud83d\udc6a',
      'family_man_boy':'\ud83d\udc68&zwj;\ud83d\udc66',
      'family_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
      'family_man_girl':'\ud83d\udc68&zwj;\ud83d\udc67',
      'family_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
      'family_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
      'family_man_man_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66',
      'family_man_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
      'family_man_man_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67',
      'family_man_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
      'family_man_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
      'family_man_woman_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
      'family_man_woman_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
      'family_man_woman_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
      'family_man_woman_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
      'family_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc66',
      'family_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
      'family_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc67',
      'family_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
      'family_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
      'family_woman_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66',
      'family_woman_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
      'family_woman_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
      'family_woman_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
      'family_woman_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
      'fast_forward':'\u23e9',
      'fax':'\ud83d\udce0',
      'fearful':'\ud83d\ude28',
      'feet':'\ud83d\udc3e',
      'female_detective':'\ud83d\udd75\ufe0f&zwj;\u2640\ufe0f',
      'ferris_wheel':'\ud83c\udfa1',
      'ferry':'\u26f4',
      'field_hockey':'\ud83c\udfd1',
      'file_cabinet':'\ud83d\uddc4',
      'file_folder':'\ud83d\udcc1',
      'film_projector':'\ud83d\udcfd',
      'film_strip':'\ud83c\udf9e',
      'fire':'\ud83d\udd25',
      'fire_engine':'\ud83d\ude92',
      'fireworks':'\ud83c\udf86',
      'first_quarter_moon':'\ud83c\udf13',
      'first_quarter_moon_with_face':'\ud83c\udf1b',
      'fish':'\ud83d\udc1f',
      'fish_cake':'\ud83c\udf65',
      'fishing_pole_and_fish':'\ud83c\udfa3',
      'fist_raised':'\u270a',
      'fist_left':'\ud83e\udd1b',
      'fist_right':'\ud83e\udd1c',
      'flags':'\ud83c\udf8f',
      'flashlight':'\ud83d\udd26',
      'fleur_de_lis':'\u269c\ufe0f',
      'flight_arrival':'\ud83d\udeec',
      'flight_departure':'\ud83d\udeeb',
      'floppy_disk':'\ud83d\udcbe',
      'flower_playing_cards':'\ud83c\udfb4',
      'flushed':'\ud83d\ude33',
      'fog':'\ud83c\udf2b',
      'foggy':'\ud83c\udf01',
      'football':'\ud83c\udfc8',
      'footprints':'\ud83d\udc63',
      'fork_and_knife':'\ud83c\udf74',
      'fountain':'\u26f2\ufe0f',
      'fountain_pen':'\ud83d\udd8b',
      'four_leaf_clover':'\ud83c\udf40',
      'fox_face':'\ud83e\udd8a',
      'framed_picture':'\ud83d\uddbc',
      'free':'\ud83c\udd93',
      'fried_egg':'\ud83c\udf73',
      'fried_shrimp':'\ud83c\udf64',
      'fries':'\ud83c\udf5f',
      'frog':'\ud83d\udc38',
      'frowning':'\ud83d\ude26',
      'frowning_face':'\u2639\ufe0f',
      'frowning_man':'\ud83d\ude4d&zwj;\u2642\ufe0f',
      'frowning_woman':'\ud83d\ude4d',
      'middle_finger':'\ud83d\udd95',
      'fuelpump':'\u26fd\ufe0f',
      'full_moon':'\ud83c\udf15',
      'full_moon_with_face':'\ud83c\udf1d',
      'funeral_urn':'\u26b1\ufe0f',
      'game_die':'\ud83c\udfb2',
      'gear':'\u2699\ufe0f',
      'gem':'\ud83d\udc8e',
      'gemini':'\u264a\ufe0f',
      'ghost':'\ud83d\udc7b',
      'gift':'\ud83c\udf81',
      'gift_heart':'\ud83d\udc9d',
      'girl':'\ud83d\udc67',
      'globe_with_meridians':'\ud83c\udf10',
      'goal_net':'\ud83e\udd45',
      'goat':'\ud83d\udc10',
      'golf':'\u26f3\ufe0f',
      'golfing_man':'\ud83c\udfcc\ufe0f',
      'golfing_woman':'\ud83c\udfcc\ufe0f&zwj;\u2640\ufe0f',
      'gorilla':'\ud83e\udd8d',
      'grapes':'\ud83c\udf47',
      'green_apple':'\ud83c\udf4f',
      'green_book':'\ud83d\udcd7',
      'green_heart':'\ud83d\udc9a',
      'green_salad':'\ud83e\udd57',
      'grey_exclamation':'\u2755',
      'grey_question':'\u2754',
      'grimacing':'\ud83d\ude2c',
      'grin':'\ud83d\ude01',
      'grinning':'\ud83d\ude00',
      'guardsman':'\ud83d\udc82',
      'guardswoman':'\ud83d\udc82&zwj;\u2640\ufe0f',
      'guitar':'\ud83c\udfb8',
      'gun':'\ud83d\udd2b',
      'haircut_woman':'\ud83d\udc87',
      'haircut_man':'\ud83d\udc87&zwj;\u2642\ufe0f',
      'hamburger':'\ud83c\udf54',
      'hammer':'\ud83d\udd28',
      'hammer_and_pick':'\u2692',
      'hammer_and_wrench':'\ud83d\udee0',
      'hamster':'\ud83d\udc39',
      'hand':'\u270b',
      'handbag':'\ud83d\udc5c',
      'handshake':'\ud83e\udd1d',
      'hankey':'\ud83d\udca9',
      'hatched_chick':'\ud83d\udc25',
      'hatching_chick':'\ud83d\udc23',
      'headphones':'\ud83c\udfa7',
      'hear_no_evil':'\ud83d\ude49',
      'heart':'\u2764\ufe0f',
      'heart_decoration':'\ud83d\udc9f',
      'heart_eyes':'\ud83d\ude0d',
      'heart_eyes_cat':'\ud83d\ude3b',
      'heartbeat':'\ud83d\udc93',
      'heartpulse':'\ud83d\udc97',
      'hearts':'\u2665\ufe0f',
      'heavy_check_mark':'\u2714\ufe0f',
      'heavy_division_sign':'\u2797',
      'heavy_dollar_sign':'\ud83d\udcb2',
      'heavy_heart_exclamation':'\u2763\ufe0f',
      'heavy_minus_sign':'\u2796',
      'heavy_multiplication_x':'\u2716\ufe0f',
      'heavy_plus_sign':'\u2795',
      'helicopter':'\ud83d\ude81',
      'herb':'\ud83c\udf3f',
      'hibiscus':'\ud83c\udf3a',
      'high_brightness':'\ud83d\udd06',
      'high_heel':'\ud83d\udc60',
      'hocho':'\ud83d\udd2a',
      'hole':'\ud83d\udd73',
      'honey_pot':'\ud83c\udf6f',
      'horse':'\ud83d\udc34',
      'horse_racing':'\ud83c\udfc7',
      'hospital':'\ud83c\udfe5',
      'hot_pepper':'\ud83c\udf36',
      'hotdog':'\ud83c\udf2d',
      'hotel':'\ud83c\udfe8',
      'hotsprings':'\u2668\ufe0f',
      'hourglass':'\u231b\ufe0f',
      'hourglass_flowing_sand':'\u23f3',
      'house':'\ud83c\udfe0',
      'house_with_garden':'\ud83c\udfe1',
      'houses':'\ud83c\udfd8',
      'hugs':'\ud83e\udd17',
      'hushed':'\ud83d\ude2f',
      'ice_cream':'\ud83c\udf68',
      'ice_hockey':'\ud83c\udfd2',
      'ice_skate':'\u26f8',
      'icecream':'\ud83c\udf66',
      'id':'\ud83c\udd94',
      'ideograph_advantage':'\ud83c\ude50',
      'imp':'\ud83d\udc7f',
      'inbox_tray':'\ud83d\udce5',
      'incoming_envelope':'\ud83d\udce8',
      'tipping_hand_woman':'\ud83d\udc81',
      'information_source':'\u2139\ufe0f',
      'innocent':'\ud83d\ude07',
      'interrobang':'\u2049\ufe0f',
      'iphone':'\ud83d\udcf1',
      'izakaya_lantern':'\ud83c\udfee',
      'jack_o_lantern':'\ud83c\udf83',
      'japan':'\ud83d\uddfe',
      'japanese_castle':'\ud83c\udfef',
      'japanese_goblin':'\ud83d\udc7a',
      'japanese_ogre':'\ud83d\udc79',
      'jeans':'\ud83d\udc56',
      'joy':'\ud83d\ude02',
      'joy_cat':'\ud83d\ude39',
      'joystick':'\ud83d\udd79',
      'kaaba':'\ud83d\udd4b',
      'key':'\ud83d\udd11',
      'keyboard':'\u2328\ufe0f',
      'keycap_ten':'\ud83d\udd1f',
      'kick_scooter':'\ud83d\udef4',
      'kimono':'\ud83d\udc58',
      'kiss':'\ud83d\udc8b',
      'kissing':'\ud83d\ude17',
      'kissing_cat':'\ud83d\ude3d',
      'kissing_closed_eyes':'\ud83d\ude1a',
      'kissing_heart':'\ud83d\ude18',
      'kissing_smiling_eyes':'\ud83d\ude19',
      'kiwi_fruit':'\ud83e\udd5d',
      'koala':'\ud83d\udc28',
      'koko':'\ud83c\ude01',
      'label':'\ud83c\udff7',
      'large_blue_circle':'\ud83d\udd35',
      'large_blue_diamond':'\ud83d\udd37',
      'large_orange_diamond':'\ud83d\udd36',
      'last_quarter_moon':'\ud83c\udf17',
      'last_quarter_moon_with_face':'\ud83c\udf1c',
      'latin_cross':'\u271d\ufe0f',
      'laughing':'\ud83d\ude06',
      'leaves':'\ud83c\udf43',
      'ledger':'\ud83d\udcd2',
      'left_luggage':'\ud83d\udec5',
      'left_right_arrow':'\u2194\ufe0f',
      'leftwards_arrow_with_hook':'\u21a9\ufe0f',
      'lemon':'\ud83c\udf4b',
      'leo':'\u264c\ufe0f',
      'leopard':'\ud83d\udc06',
      'level_slider':'\ud83c\udf9a',
      'libra':'\u264e\ufe0f',
      'light_rail':'\ud83d\ude88',
      'link':'\ud83d\udd17',
      'lion':'\ud83e\udd81',
      'lips':'\ud83d\udc44',
      'lipstick':'\ud83d\udc84',
      'lizard':'\ud83e\udd8e',
      'lock':'\ud83d\udd12',
      'lock_with_ink_pen':'\ud83d\udd0f',
      'lollipop':'\ud83c\udf6d',
      'loop':'\u27bf',
      'loud_sound':'\ud83d\udd0a',
      'loudspeaker':'\ud83d\udce2',
      'love_hotel':'\ud83c\udfe9',
      'love_letter':'\ud83d\udc8c',
      'low_brightness':'\ud83d\udd05',
      'lying_face':'\ud83e\udd25',
      'm':'\u24c2\ufe0f',
      'mag':'\ud83d\udd0d',
      'mag_right':'\ud83d\udd0e',
      'mahjong':'\ud83c\udc04\ufe0f',
      'mailbox':'\ud83d\udceb',
      'mailbox_closed':'\ud83d\udcea',
      'mailbox_with_mail':'\ud83d\udcec',
      'mailbox_with_no_mail':'\ud83d\udced',
      'man':'\ud83d\udc68',
      'man_artist':'\ud83d\udc68&zwj;\ud83c\udfa8',
      'man_astronaut':'\ud83d\udc68&zwj;\ud83d\ude80',
      'man_cartwheeling':'\ud83e\udd38&zwj;\u2642\ufe0f',
      'man_cook':'\ud83d\udc68&zwj;\ud83c\udf73',
      'man_dancing':'\ud83d\udd7a',
      'man_facepalming':'\ud83e\udd26&zwj;\u2642\ufe0f',
      'man_factory_worker':'\ud83d\udc68&zwj;\ud83c\udfed',
      'man_farmer':'\ud83d\udc68&zwj;\ud83c\udf3e',
      'man_firefighter':'\ud83d\udc68&zwj;\ud83d\ude92',
      'man_health_worker':'\ud83d\udc68&zwj;\u2695\ufe0f',
      'man_in_tuxedo':'\ud83e\udd35',
      'man_judge':'\ud83d\udc68&zwj;\u2696\ufe0f',
      'man_juggling':'\ud83e\udd39&zwj;\u2642\ufe0f',
      'man_mechanic':'\ud83d\udc68&zwj;\ud83d\udd27',
      'man_office_worker':'\ud83d\udc68&zwj;\ud83d\udcbc',
      'man_pilot':'\ud83d\udc68&zwj;\u2708\ufe0f',
      'man_playing_handball':'\ud83e\udd3e&zwj;\u2642\ufe0f',
      'man_playing_water_polo':'\ud83e\udd3d&zwj;\u2642\ufe0f',
      'man_scientist':'\ud83d\udc68&zwj;\ud83d\udd2c',
      'man_shrugging':'\ud83e\udd37&zwj;\u2642\ufe0f',
      'man_singer':'\ud83d\udc68&zwj;\ud83c\udfa4',
      'man_student':'\ud83d\udc68&zwj;\ud83c\udf93',
      'man_teacher':'\ud83d\udc68&zwj;\ud83c\udfeb',
      'man_technologist':'\ud83d\udc68&zwj;\ud83d\udcbb',
      'man_with_gua_pi_mao':'\ud83d\udc72',
      'man_with_turban':'\ud83d\udc73',
      'tangerine':'\ud83c\udf4a',
      'mans_shoe':'\ud83d\udc5e',
      'mantelpiece_clock':'\ud83d\udd70',
      'maple_leaf':'\ud83c\udf41',
      'martial_arts_uniform':'\ud83e\udd4b',
      'mask':'\ud83d\ude37',
      'massage_woman':'\ud83d\udc86',
      'massage_man':'\ud83d\udc86&zwj;\u2642\ufe0f',
      'meat_on_bone':'\ud83c\udf56',
      'medal_military':'\ud83c\udf96',
      'medal_sports':'\ud83c\udfc5',
      'mega':'\ud83d\udce3',
      'melon':'\ud83c\udf48',
      'memo':'\ud83d\udcdd',
      'men_wrestling':'\ud83e\udd3c&zwj;\u2642\ufe0f',
      'menorah':'\ud83d\udd4e',
      'mens':'\ud83d\udeb9',
      'metal':'\ud83e\udd18',
      'metro':'\ud83d\ude87',
      'microphone':'\ud83c\udfa4',
      'microscope':'\ud83d\udd2c',
      'milk_glass':'\ud83e\udd5b',
      'milky_way':'\ud83c\udf0c',
      'minibus':'\ud83d\ude90',
      'minidisc':'\ud83d\udcbd',
      'mobile_phone_off':'\ud83d\udcf4',
      'money_mouth_face':'\ud83e\udd11',
      'money_with_wings':'\ud83d\udcb8',
      'moneybag':'\ud83d\udcb0',
      'monkey':'\ud83d\udc12',
      'monkey_face':'\ud83d\udc35',
      'monorail':'\ud83d\ude9d',
      'moon':'\ud83c\udf14',
      'mortar_board':'\ud83c\udf93',
      'mosque':'\ud83d\udd4c',
      'motor_boat':'\ud83d\udee5',
      'motor_scooter':'\ud83d\udef5',
      'motorcycle':'\ud83c\udfcd',
      'motorway':'\ud83d\udee3',
      'mount_fuji':'\ud83d\uddfb',
      'mountain':'\u26f0',
      'mountain_biking_man':'\ud83d\udeb5',
      'mountain_biking_woman':'\ud83d\udeb5&zwj;\u2640\ufe0f',
      'mountain_cableway':'\ud83d\udea0',
      'mountain_railway':'\ud83d\ude9e',
      'mountain_snow':'\ud83c\udfd4',
      'mouse':'\ud83d\udc2d',
      'mouse2':'\ud83d\udc01',
      'movie_camera':'\ud83c\udfa5',
      'moyai':'\ud83d\uddff',
      'mrs_claus':'\ud83e\udd36',
      'muscle':'\ud83d\udcaa',
      'mushroom':'\ud83c\udf44',
      'musical_keyboard':'\ud83c\udfb9',
      'musical_note':'\ud83c\udfb5',
      'musical_score':'\ud83c\udfbc',
      'mute':'\ud83d\udd07',
      'nail_care':'\ud83d\udc85',
      'name_badge':'\ud83d\udcdb',
      'national_park':'\ud83c\udfde',
      'nauseated_face':'\ud83e\udd22',
      'necktie':'\ud83d\udc54',
      'negative_squared_cross_mark':'\u274e',
      'nerd_face':'\ud83e\udd13',
      'neutral_face':'\ud83d\ude10',
      'new':'\ud83c\udd95',
      'new_moon':'\ud83c\udf11',
      'new_moon_with_face':'\ud83c\udf1a',
      'newspaper':'\ud83d\udcf0',
      'newspaper_roll':'\ud83d\uddde',
      'next_track_button':'\u23ed',
      'ng':'\ud83c\udd96',
      'no_good_man':'\ud83d\ude45&zwj;\u2642\ufe0f',
      'no_good_woman':'\ud83d\ude45',
      'night_with_stars':'\ud83c\udf03',
      'no_bell':'\ud83d\udd15',
      'no_bicycles':'\ud83d\udeb3',
      'no_entry':'\u26d4\ufe0f',
      'no_entry_sign':'\ud83d\udeab',
      'no_mobile_phones':'\ud83d\udcf5',
      'no_mouth':'\ud83d\ude36',
      'no_pedestrians':'\ud83d\udeb7',
      'no_smoking':'\ud83d\udead',
      'non-potable_water':'\ud83d\udeb1',
      'nose':'\ud83d\udc43',
      'notebook':'\ud83d\udcd3',
      'notebook_with_decorative_cover':'\ud83d\udcd4',
      'notes':'\ud83c\udfb6',
      'nut_and_bolt':'\ud83d\udd29',
      'o':'\u2b55\ufe0f',
      'o2':'\ud83c\udd7e\ufe0f',
      'ocean':'\ud83c\udf0a',
      'octopus':'\ud83d\udc19',
      'oden':'\ud83c\udf62',
      'office':'\ud83c\udfe2',
      'oil_drum':'\ud83d\udee2',
      'ok':'\ud83c\udd97',
      'ok_hand':'\ud83d\udc4c',
      'ok_man':'\ud83d\ude46&zwj;\u2642\ufe0f',
      'ok_woman':'\ud83d\ude46',
      'old_key':'\ud83d\udddd',
      'older_man':'\ud83d\udc74',
      'older_woman':'\ud83d\udc75',
      'om':'\ud83d\udd49',
      'on':'\ud83d\udd1b',
      'oncoming_automobile':'\ud83d\ude98',
      'oncoming_bus':'\ud83d\ude8d',
      'oncoming_police_car':'\ud83d\ude94',
      'oncoming_taxi':'\ud83d\ude96',
      'open_file_folder':'\ud83d\udcc2',
      'open_hands':'\ud83d\udc50',
      'open_mouth':'\ud83d\ude2e',
      'open_umbrella':'\u2602\ufe0f',
      'ophiuchus':'\u26ce',
      'orange_book':'\ud83d\udcd9',
      'orthodox_cross':'\u2626\ufe0f',
      'outbox_tray':'\ud83d\udce4',
      'owl':'\ud83e\udd89',
      'ox':'\ud83d\udc02',
      'package':'\ud83d\udce6',
      'page_facing_up':'\ud83d\udcc4',
      'page_with_curl':'\ud83d\udcc3',
      'pager':'\ud83d\udcdf',
      'paintbrush':'\ud83d\udd8c',
      'palm_tree':'\ud83c\udf34',
      'pancakes':'\ud83e\udd5e',
      'panda_face':'\ud83d\udc3c',
      'paperclip':'\ud83d\udcce',
      'paperclips':'\ud83d\udd87',
      'parasol_on_ground':'\u26f1',
      'parking':'\ud83c\udd7f\ufe0f',
      'part_alternation_mark':'\u303d\ufe0f',
      'partly_sunny':'\u26c5\ufe0f',
      'passenger_ship':'\ud83d\udef3',
      'passport_control':'\ud83d\udec2',
      'pause_button':'\u23f8',
      'peace_symbol':'\u262e\ufe0f',
      'peach':'\ud83c\udf51',
      'peanuts':'\ud83e\udd5c',
      'pear':'\ud83c\udf50',
      'pen':'\ud83d\udd8a',
      'pencil2':'\u270f\ufe0f',
      'penguin':'\ud83d\udc27',
      'pensive':'\ud83d\ude14',
      'performing_arts':'\ud83c\udfad',
      'persevere':'\ud83d\ude23',
      'person_fencing':'\ud83e\udd3a',
      'pouting_woman':'\ud83d\ude4e',
      'phone':'\u260e\ufe0f',
      'pick':'\u26cf',
      'pig':'\ud83d\udc37',
      'pig2':'\ud83d\udc16',
      'pig_nose':'\ud83d\udc3d',
      'pill':'\ud83d\udc8a',
      'pineapple':'\ud83c\udf4d',
      'ping_pong':'\ud83c\udfd3',
      'pisces':'\u2653\ufe0f',
      'pizza':'\ud83c\udf55',
      'place_of_worship':'\ud83d\uded0',
      'plate_with_cutlery':'\ud83c\udf7d',
      'play_or_pause_button':'\u23ef',
      'point_down':'\ud83d\udc47',
      'point_left':'\ud83d\udc48',
      'point_right':'\ud83d\udc49',
      'point_up':'\u261d\ufe0f',
      'point_up_2':'\ud83d\udc46',
      'police_car':'\ud83d\ude93',
      'policewoman':'\ud83d\udc6e&zwj;\u2640\ufe0f',
      'poodle':'\ud83d\udc29',
      'popcorn':'\ud83c\udf7f',
      'post_office':'\ud83c\udfe3',
      'postal_horn':'\ud83d\udcef',
      'postbox':'\ud83d\udcee',
      'potable_water':'\ud83d\udeb0',
      'potato':'\ud83e\udd54',
      'pouch':'\ud83d\udc5d',
      'poultry_leg':'\ud83c\udf57',
      'pound':'\ud83d\udcb7',
      'rage':'\ud83d\ude21',
      'pouting_cat':'\ud83d\ude3e',
      'pouting_man':'\ud83d\ude4e&zwj;\u2642\ufe0f',
      'pray':'\ud83d\ude4f',
      'prayer_beads':'\ud83d\udcff',
      'pregnant_woman':'\ud83e\udd30',
      'previous_track_button':'\u23ee',
      'prince':'\ud83e\udd34',
      'princess':'\ud83d\udc78',
      'printer':'\ud83d\udda8',
      'purple_heart':'\ud83d\udc9c',
      'purse':'\ud83d\udc5b',
      'pushpin':'\ud83d\udccc',
      'put_litter_in_its_place':'\ud83d\udeae',
      'question':'\u2753',
      'rabbit':'\ud83d\udc30',
      'rabbit2':'\ud83d\udc07',
      'racehorse':'\ud83d\udc0e',
      'racing_car':'\ud83c\udfce',
      'radio':'\ud83d\udcfb',
      'radio_button':'\ud83d\udd18',
      'radioactive':'\u2622\ufe0f',
      'railway_car':'\ud83d\ude83',
      'railway_track':'\ud83d\udee4',
      'rainbow':'\ud83c\udf08',
      'rainbow_flag':'\ud83c\udff3\ufe0f&zwj;\ud83c\udf08',
      'raised_back_of_hand':'\ud83e\udd1a',
      'raised_hand_with_fingers_splayed':'\ud83d\udd90',
      'raised_hands':'\ud83d\ude4c',
      'raising_hand_woman':'\ud83d\ude4b',
      'raising_hand_man':'\ud83d\ude4b&zwj;\u2642\ufe0f',
      'ram':'\ud83d\udc0f',
      'ramen':'\ud83c\udf5c',
      'rat':'\ud83d\udc00',
      'record_button':'\u23fa',
      'recycle':'\u267b\ufe0f',
      'red_circle':'\ud83d\udd34',
      'registered':'\u00ae\ufe0f',
      'relaxed':'\u263a\ufe0f',
      'relieved':'\ud83d\ude0c',
      'reminder_ribbon':'\ud83c\udf97',
      'repeat':'\ud83d\udd01',
      'repeat_one':'\ud83d\udd02',
      'rescue_worker_helmet':'\u26d1',
      'restroom':'\ud83d\udebb',
      'revolving_hearts':'\ud83d\udc9e',
      'rewind':'\u23ea',
      'rhinoceros':'\ud83e\udd8f',
      'ribbon':'\ud83c\udf80',
      'rice':'\ud83c\udf5a',
      'rice_ball':'\ud83c\udf59',
      'rice_cracker':'\ud83c\udf58',
      'rice_scene':'\ud83c\udf91',
      'right_anger_bubble':'\ud83d\uddef',
      'ring':'\ud83d\udc8d',
      'robot':'\ud83e\udd16',
      'rocket':'\ud83d\ude80',
      'rofl':'\ud83e\udd23',
      'roll_eyes':'\ud83d\ude44',
      'roller_coaster':'\ud83c\udfa2',
      'rooster':'\ud83d\udc13',
      'rose':'\ud83c\udf39',
      'rosette':'\ud83c\udff5',
      'rotating_light':'\ud83d\udea8',
      'round_pushpin':'\ud83d\udccd',
      'rowing_man':'\ud83d\udea3',
      'rowing_woman':'\ud83d\udea3&zwj;\u2640\ufe0f',
      'rugby_football':'\ud83c\udfc9',
      'running_man':'\ud83c\udfc3',
      'running_shirt_with_sash':'\ud83c\udfbd',
      'running_woman':'\ud83c\udfc3&zwj;\u2640\ufe0f',
      'sa':'\ud83c\ude02\ufe0f',
      'sagittarius':'\u2650\ufe0f',
      'sake':'\ud83c\udf76',
      'sandal':'\ud83d\udc61',
      'santa':'\ud83c\udf85',
      'satellite':'\ud83d\udce1',
      'saxophone':'\ud83c\udfb7',
      'school':'\ud83c\udfeb',
      'school_satchel':'\ud83c\udf92',
      'scissors':'\u2702\ufe0f',
      'scorpion':'\ud83e\udd82',
      'scorpius':'\u264f\ufe0f',
      'scream':'\ud83d\ude31',
      'scream_cat':'\ud83d\ude40',
      'scroll':'\ud83d\udcdc',
      'seat':'\ud83d\udcba',
      'secret':'\u3299\ufe0f',
      'see_no_evil':'\ud83d\ude48',
      'seedling':'\ud83c\udf31',
      'selfie':'\ud83e\udd33',
      'shallow_pan_of_food':'\ud83e\udd58',
      'shamrock':'\u2618\ufe0f',
      'shark':'\ud83e\udd88',
      'shaved_ice':'\ud83c\udf67',
      'sheep':'\ud83d\udc11',
      'shell':'\ud83d\udc1a',
      'shield':'\ud83d\udee1',
      'shinto_shrine':'\u26e9',
      'ship':'\ud83d\udea2',
      'shirt':'\ud83d\udc55',
      'shopping':'\ud83d\udecd',
      'shopping_cart':'\ud83d\uded2',
      'shower':'\ud83d\udebf',
      'shrimp':'\ud83e\udd90',
      'signal_strength':'\ud83d\udcf6',
      'six_pointed_star':'\ud83d\udd2f',
      'ski':'\ud83c\udfbf',
      'skier':'\u26f7',
      'skull':'\ud83d\udc80',
      'skull_and_crossbones':'\u2620\ufe0f',
      'sleeping':'\ud83d\ude34',
      'sleeping_bed':'\ud83d\udecc',
      'sleepy':'\ud83d\ude2a',
      'slightly_frowning_face':'\ud83d\ude41',
      'slightly_smiling_face':'\ud83d\ude42',
      'slot_machine':'\ud83c\udfb0',
      'small_airplane':'\ud83d\udee9',
      'small_blue_diamond':'\ud83d\udd39',
      'small_orange_diamond':'\ud83d\udd38',
      'small_red_triangle':'\ud83d\udd3a',
      'small_red_triangle_down':'\ud83d\udd3b',
      'smile':'\ud83d\ude04',
      'smile_cat':'\ud83d\ude38',
      'smiley':'\ud83d\ude03',
      'smiley_cat':'\ud83d\ude3a',
      'smiling_imp':'\ud83d\ude08',
      'smirk':'\ud83d\ude0f',
      'smirk_cat':'\ud83d\ude3c',
      'smoking':'\ud83d\udeac',
      'snail':'\ud83d\udc0c',
      'snake':'\ud83d\udc0d',
      'sneezing_face':'\ud83e\udd27',
      'snowboarder':'\ud83c\udfc2',
      'snowflake':'\u2744\ufe0f',
      'snowman':'\u26c4\ufe0f',
      'snowman_with_snow':'\u2603\ufe0f',
      'sob':'\ud83d\ude2d',
      'soccer':'\u26bd\ufe0f',
      'soon':'\ud83d\udd1c',
      'sos':'\ud83c\udd98',
      'sound':'\ud83d\udd09',
      'space_invader':'\ud83d\udc7e',
      'spades':'\u2660\ufe0f',
      'spaghetti':'\ud83c\udf5d',
      'sparkle':'\u2747\ufe0f',
      'sparkler':'\ud83c\udf87',
      'sparkles':'\u2728',
      'sparkling_heart':'\ud83d\udc96',
      'speak_no_evil':'\ud83d\ude4a',
      'speaker':'\ud83d\udd08',
      'speaking_head':'\ud83d\udde3',
      'speech_balloon':'\ud83d\udcac',
      'speedboat':'\ud83d\udea4',
      'spider':'\ud83d\udd77',
      'spider_web':'\ud83d\udd78',
      'spiral_calendar':'\ud83d\uddd3',
      'spiral_notepad':'\ud83d\uddd2',
      'spoon':'\ud83e\udd44',
      'squid':'\ud83e\udd91',
      'stadium':'\ud83c\udfdf',
      'star':'\u2b50\ufe0f',
      'star2':'\ud83c\udf1f',
      'star_and_crescent':'\u262a\ufe0f',
      'star_of_david':'\u2721\ufe0f',
      'stars':'\ud83c\udf20',
      'station':'\ud83d\ude89',
      'statue_of_liberty':'\ud83d\uddfd',
      'steam_locomotive':'\ud83d\ude82',
      'stew':'\ud83c\udf72',
      'stop_button':'\u23f9',
      'stop_sign':'\ud83d\uded1',
      'stopwatch':'\u23f1',
      'straight_ruler':'\ud83d\udccf',
      'strawberry':'\ud83c\udf53',
      'stuck_out_tongue':'\ud83d\ude1b',
      'stuck_out_tongue_closed_eyes':'\ud83d\ude1d',
      'stuck_out_tongue_winking_eye':'\ud83d\ude1c',
      'studio_microphone':'\ud83c\udf99',
      'stuffed_flatbread':'\ud83e\udd59',
      'sun_behind_large_cloud':'\ud83c\udf25',
      'sun_behind_rain_cloud':'\ud83c\udf26',
      'sun_behind_small_cloud':'\ud83c\udf24',
      'sun_with_face':'\ud83c\udf1e',
      'sunflower':'\ud83c\udf3b',
      'sunglasses':'\ud83d\ude0e',
      'sunny':'\u2600\ufe0f',
      'sunrise':'\ud83c\udf05',
      'sunrise_over_mountains':'\ud83c\udf04',
      'surfing_man':'\ud83c\udfc4',
      'surfing_woman':'\ud83c\udfc4&zwj;\u2640\ufe0f',
      'sushi':'\ud83c\udf63',
      'suspension_railway':'\ud83d\ude9f',
      'sweat':'\ud83d\ude13',
      'sweat_drops':'\ud83d\udca6',
      'sweat_smile':'\ud83d\ude05',
      'sweet_potato':'\ud83c\udf60',
      'swimming_man':'\ud83c\udfca',
      'swimming_woman':'\ud83c\udfca&zwj;\u2640\ufe0f',
      'symbols':'\ud83d\udd23',
      'synagogue':'\ud83d\udd4d',
      'syringe':'\ud83d\udc89',
      'taco':'\ud83c\udf2e',
      'tada':'\ud83c\udf89',
      'tanabata_tree':'\ud83c\udf8b',
      'taurus':'\u2649\ufe0f',
      'taxi':'\ud83d\ude95',
      'tea':'\ud83c\udf75',
      'telephone_receiver':'\ud83d\udcde',
      'telescope':'\ud83d\udd2d',
      'tennis':'\ud83c\udfbe',
      'tent':'\u26fa\ufe0f',
      'thermometer':'\ud83c\udf21',
      'thinking':'\ud83e\udd14',
      'thought_balloon':'\ud83d\udcad',
      'ticket':'\ud83c\udfab',
      'tickets':'\ud83c\udf9f',
      'tiger':'\ud83d\udc2f',
      'tiger2':'\ud83d\udc05',
      'timer_clock':'\u23f2',
      'tipping_hand_man':'\ud83d\udc81&zwj;\u2642\ufe0f',
      'tired_face':'\ud83d\ude2b',
      'tm':'\u2122\ufe0f',
      'toilet':'\ud83d\udebd',
      'tokyo_tower':'\ud83d\uddfc',
      'tomato':'\ud83c\udf45',
      'tongue':'\ud83d\udc45',
      'top':'\ud83d\udd1d',
      'tophat':'\ud83c\udfa9',
      'tornado':'\ud83c\udf2a',
      'trackball':'\ud83d\uddb2',
      'tractor':'\ud83d\ude9c',
      'traffic_light':'\ud83d\udea5',
      'train':'\ud83d\ude8b',
      'train2':'\ud83d\ude86',
      'tram':'\ud83d\ude8a',
      'triangular_flag_on_post':'\ud83d\udea9',
      'triangular_ruler':'\ud83d\udcd0',
      'trident':'\ud83d\udd31',
      'triumph':'\ud83d\ude24',
      'trolleybus':'\ud83d\ude8e',
      'trophy':'\ud83c\udfc6',
      'tropical_drink':'\ud83c\udf79',
      'tropical_fish':'\ud83d\udc20',
      'truck':'\ud83d\ude9a',
      'trumpet':'\ud83c\udfba',
      'tulip':'\ud83c\udf37',
      'tumbler_glass':'\ud83e\udd43',
      'turkey':'\ud83e\udd83',
      'turtle':'\ud83d\udc22',
      'tv':'\ud83d\udcfa',
      'twisted_rightwards_arrows':'\ud83d\udd00',
      'two_hearts':'\ud83d\udc95',
      'two_men_holding_hands':'\ud83d\udc6c',
      'two_women_holding_hands':'\ud83d\udc6d',
      'u5272':'\ud83c\ude39',
      'u5408':'\ud83c\ude34',
      'u55b6':'\ud83c\ude3a',
      'u6307':'\ud83c\ude2f\ufe0f',
      'u6708':'\ud83c\ude37\ufe0f',
      'u6709':'\ud83c\ude36',
      'u6e80':'\ud83c\ude35',
      'u7121':'\ud83c\ude1a\ufe0f',
      'u7533':'\ud83c\ude38',
      'u7981':'\ud83c\ude32',
      'u7a7a':'\ud83c\ude33',
      'umbrella':'\u2614\ufe0f',
      'unamused':'\ud83d\ude12',
      'underage':'\ud83d\udd1e',
      'unicorn':'\ud83e\udd84',
      'unlock':'\ud83d\udd13',
      'up':'\ud83c\udd99',
      'upside_down_face':'\ud83d\ude43',
      'v':'\u270c\ufe0f',
      'vertical_traffic_light':'\ud83d\udea6',
      'vhs':'\ud83d\udcfc',
      'vibration_mode':'\ud83d\udcf3',
      'video_camera':'\ud83d\udcf9',
      'video_game':'\ud83c\udfae',
      'violin':'\ud83c\udfbb',
      'virgo':'\u264d\ufe0f',
      'volcano':'\ud83c\udf0b',
      'volleyball':'\ud83c\udfd0',
      'vs':'\ud83c\udd9a',
      'vulcan_salute':'\ud83d\udd96',
      'walking_man':'\ud83d\udeb6',
      'walking_woman':'\ud83d\udeb6&zwj;\u2640\ufe0f',
      'waning_crescent_moon':'\ud83c\udf18',
      'waning_gibbous_moon':'\ud83c\udf16',
      'warning':'\u26a0\ufe0f',
      'wastebasket':'\ud83d\uddd1',
      'watch':'\u231a\ufe0f',
      'water_buffalo':'\ud83d\udc03',
      'watermelon':'\ud83c\udf49',
      'wave':'\ud83d\udc4b',
      'wavy_dash':'\u3030\ufe0f',
      'waxing_crescent_moon':'\ud83c\udf12',
      'wc':'\ud83d\udebe',
      'weary':'\ud83d\ude29',
      'wedding':'\ud83d\udc92',
      'weight_lifting_man':'\ud83c\udfcb\ufe0f',
      'weight_lifting_woman':'\ud83c\udfcb\ufe0f&zwj;\u2640\ufe0f',
      'whale':'\ud83d\udc33',
      'whale2':'\ud83d\udc0b',
      'wheel_of_dharma':'\u2638\ufe0f',
      'wheelchair':'\u267f\ufe0f',
      'white_check_mark':'\u2705',
      'white_circle':'\u26aa\ufe0f',
      'white_flag':'\ud83c\udff3\ufe0f',
      'white_flower':'\ud83d\udcae',
      'white_large_square':'\u2b1c\ufe0f',
      'white_medium_small_square':'\u25fd\ufe0f',
      'white_medium_square':'\u25fb\ufe0f',
      'white_small_square':'\u25ab\ufe0f',
      'white_square_button':'\ud83d\udd33',
      'wilted_flower':'\ud83e\udd40',
      'wind_chime':'\ud83c\udf90',
      'wind_face':'\ud83c\udf2c',
      'wine_glass':'\ud83c\udf77',
      'wink':'\ud83d\ude09',
      'wolf':'\ud83d\udc3a',
      'woman':'\ud83d\udc69',
      'woman_artist':'\ud83d\udc69&zwj;\ud83c\udfa8',
      'woman_astronaut':'\ud83d\udc69&zwj;\ud83d\ude80',
      'woman_cartwheeling':'\ud83e\udd38&zwj;\u2640\ufe0f',
      'woman_cook':'\ud83d\udc69&zwj;\ud83c\udf73',
      'woman_facepalming':'\ud83e\udd26&zwj;\u2640\ufe0f',
      'woman_factory_worker':'\ud83d\udc69&zwj;\ud83c\udfed',
      'woman_farmer':'\ud83d\udc69&zwj;\ud83c\udf3e',
      'woman_firefighter':'\ud83d\udc69&zwj;\ud83d\ude92',
      'woman_health_worker':'\ud83d\udc69&zwj;\u2695\ufe0f',
      'woman_judge':'\ud83d\udc69&zwj;\u2696\ufe0f',
      'woman_juggling':'\ud83e\udd39&zwj;\u2640\ufe0f',
      'woman_mechanic':'\ud83d\udc69&zwj;\ud83d\udd27',
      'woman_office_worker':'\ud83d\udc69&zwj;\ud83d\udcbc',
      'woman_pilot':'\ud83d\udc69&zwj;\u2708\ufe0f',
      'woman_playing_handball':'\ud83e\udd3e&zwj;\u2640\ufe0f',
      'woman_playing_water_polo':'\ud83e\udd3d&zwj;\u2640\ufe0f',
      'woman_scientist':'\ud83d\udc69&zwj;\ud83d\udd2c',
      'woman_shrugging':'\ud83e\udd37&zwj;\u2640\ufe0f',
      'woman_singer':'\ud83d\udc69&zwj;\ud83c\udfa4',
      'woman_student':'\ud83d\udc69&zwj;\ud83c\udf93',
      'woman_teacher':'\ud83d\udc69&zwj;\ud83c\udfeb',
      'woman_technologist':'\ud83d\udc69&zwj;\ud83d\udcbb',
      'woman_with_turban':'\ud83d\udc73&zwj;\u2640\ufe0f',
      'womans_clothes':'\ud83d\udc5a',
      'womans_hat':'\ud83d\udc52',
      'women_wrestling':'\ud83e\udd3c&zwj;\u2640\ufe0f',
      'womens':'\ud83d\udeba',
      'world_map':'\ud83d\uddfa',
      'worried':'\ud83d\ude1f',
      'wrench':'\ud83d\udd27',
      'writing_hand':'\u270d\ufe0f',
      'x':'\u274c',
      'yellow_heart':'\ud83d\udc9b',
      'yen':'\ud83d\udcb4',
      'yin_yang':'\u262f\ufe0f',
      'yum':'\ud83d\ude0b',
      'zap':'\u26a1\ufe0f',
      'zipper_mouth_face':'\ud83e\udd10',
      'zzz':'\ud83d\udca4',
    
      /* special emojis :P */
      'octocat':  '<img alt=":octocat:" height="20" width="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">',
      'showdown': '<span style="font-family: \'Anonymous Pro\', monospace; text-decoration: underline; text-decoration-style: dashed; text-decoration-color: #3e8b8a;text-underline-position: under;">S</span>'
    };
    
    /**
     * Created by Estevao on 31-05-2015.
     */
    
    /**
     * Showdown Converter class
     * @class
     * @param {object} [converterOptions]
     * @returns {Converter}
     */
    showdown.Converter = function (converterOptions) {
      'use strict';
    
      var
          /**
           * Options used by this converter
           * @private
           * @type {{}}
           */
          options = {},
    
          /**
           * Language extensions used by this converter
           * @private
           * @type {Array}
           */
          langExtensions = [],
    
          /**
           * Output modifiers extensions used by this converter
           * @private
           * @type {Array}
           */
          outputModifiers = [],
    
          /**
           * Event listeners
           * @private
           * @type {{}}
           */
          listeners = {},
    
          /**
           * The flavor set in this converter
           */
          setConvFlavor = setFlavor,
    
          /**
           * Metadata of the document
           * @type {{parsed: {}, raw: string, format: string}}
           */
          metadata = {
            parsed: {},
            raw: '',
            format: ''
          };
    
      _constructor();
    
      /**
       * Converter constructor
       * @private
       */
      function _constructor () {
        converterOptions = converterOptions || {};
    
        for (var gOpt in globalOptions) {
          if (globalOptions.hasOwnProperty(gOpt)) {
            options[gOpt] = globalOptions[gOpt];
          }
        }
    
        // Merge options
        if (typeof converterOptions === 'object') {
          for (var opt in converterOptions) {
            if (converterOptions.hasOwnProperty(opt)) {
              options[opt] = converterOptions[opt];
            }
          }
        } else {
          throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
          ' was passed instead.');
        }
    
        if (options.extensions) {
          showdown.helper.forEach(options.extensions, _parseExtension);
        }
      }
    
      /**
       * Parse extension
       * @param {*} ext
       * @param {string} [name='']
       * @private
       */
      function _parseExtension (ext, name) {
    
        name = name || null;
        // If it's a string, the extension was previously loaded
        if (showdown.helper.isString(ext)) {
          ext = showdown.helper.stdExtName(ext);
          name = ext;
    
          // LEGACY_SUPPORT CODE
          if (showdown.extensions[ext]) {
            console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
              'Please inform the developer that the extension should be updated!');
            legacyExtensionLoading(showdown.extensions[ext], ext);
            return;
            // END LEGACY SUPPORT CODE
    
          } else if (!showdown.helper.isUndefined(extensions[ext])) {
            ext = extensions[ext];
    
          } else {
            throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
          }
        }
    
        if (typeof ext === 'function') {
          ext = ext();
        }
    
        if (!showdown.helper.isArray(ext)) {
          ext = [ext];
        }
    
        var validExt = validate(ext, name);
        if (!validExt.valid) {
          throw Error(validExt.error);
        }
    
        for (var i = 0; i < ext.length; ++i) {
          switch (ext[i].type) {
    
            case 'lang':
              langExtensions.push(ext[i]);
              break;
    
            case 'output':
              outputModifiers.push(ext[i]);
              break;
          }
          if (ext[i].hasOwnProperty('listeners')) {
            for (var ln in ext[i].listeners) {
              if (ext[i].listeners.hasOwnProperty(ln)) {
                listen(ln, ext[i].listeners[ln]);
              }
            }
          }
        }
    
      }
    
      /**
       * LEGACY_SUPPORT
       * @param {*} ext
       * @param {string} name
       */
      function legacyExtensionLoading (ext, name) {
        if (typeof ext === 'function') {
          ext = ext(new showdown.Converter());
        }
        if (!showdown.helper.isArray(ext)) {
          ext = [ext];
        }
        var valid = validate(ext, name);
    
        if (!valid.valid) {
          throw Error(valid.error);
        }
    
        for (var i = 0; i < ext.length; ++i) {
          switch (ext[i].type) {
            case 'lang':
              langExtensions.push(ext[i]);
              break;
            case 'output':
              outputModifiers.push(ext[i]);
              break;
            default:// should never reach here
              throw Error('Extension loader error: Type unrecognized!!!');
          }
        }
      }
    
      /**
       * Listen to an event
       * @param {string} name
       * @param {function} callback
       */
      function listen (name, callback) {
        if (!showdown.helper.isString(name)) {
          throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
        }
    
        if (typeof callback !== 'function') {
          throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
        }
    
        if (!listeners.hasOwnProperty(name)) {
          listeners[name] = [];
        }
        listeners[name].push(callback);
      }
    
      function rTrimInputText (text) {
        var rsp = text.match(/^\s*/)[0].length,
            rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
        return text.replace(rgx, '');
      }
    
      /**
       * Dispatch an event
       * @private
       * @param {string} evtName Event name
       * @param {string} text Text
       * @param {{}} options Converter Options
       * @param {{}} globals
       * @returns {string}
       */
      this._dispatch = function dispatch (evtName, text, options, globals) {
        if (listeners.hasOwnProperty(evtName)) {
          for (var ei = 0; ei < listeners[evtName].length; ++ei) {
            var nText = listeners[evtName][ei](evtName, text, this, options, globals);
            if (nText && typeof nText !== 'undefined') {
              text = nText;
            }
          }
        }
        return text;
      };
    
      /**
       * Listen to an event
       * @param {string} name
       * @param {function} callback
       * @returns {showdown.Converter}
       */
      this.listen = function (name, callback) {
        listen(name, callback);
        return this;
      };
    
      /**
       * Converts a markdown string into HTML
       * @param {string} text
       * @returns {*}
       */
      this.makeHtml = function (text) {
        //check if text is not falsy
        if (!text) {
          return text;
        }
    
        var globals = {
          gHtmlBlocks:     [],
          gHtmlMdBlocks:   [],
          gHtmlSpans:      [],
          gUrls:           {},
          gTitles:         {},
          gDimensions:     {},
          gListLevel:      0,
          hashLinkCounts:  {},
          langExtensions:  langExtensions,
          outputModifiers: outputModifiers,
          converter:       this,
          ghCodeBlocks:    [],
          metadata: {
            parsed: {},
            raw: '',
            format: ''
          }
        };
    
        // This lets us use ¨ trema as an escape char to avoid md5 hashes
        // The choice of character is arbitrary; anything that isn't
        // magic in Markdown will work.
        text = text.replace(/¨/g, '¨T');
    
        // Replace $ with ¨D
        // RegExp interprets $ as a special character
        // when it's in a replacement string
        text = text.replace(/\$/g, '¨D');
    
        // Standardize line endings
        text = text.replace(/\r\n/g, '\n'); // DOS to Unix
        text = text.replace(/\r/g, '\n'); // Mac to Unix
    
        // Stardardize line spaces
        text = text.replace(/\u00A0/g, '&nbsp;');
    
        if (options.smartIndentationFix) {
          text = rTrimInputText(text);
        }
    
        // Make sure text begins and ends with a couple of newlines:
        text = '\n\n' + text + '\n\n';
    
        // detab
        text = showdown.subParser('detab')(text, options, globals);
    
        /**
         * Strip any lines consisting only of spaces and tabs.
         * This makes subsequent regexs easier to write, because we can
         * match consecutive blank lines with /\n+/ instead of something
         * contorted like /[ \t]*\n+/
         */
        text = text.replace(/^[ \t]+$/mg, '');
    
        //run languageExtensions
        showdown.helper.forEach(langExtensions, function (ext) {
          text = showdown.subParser('runExtension')(ext, text, options, globals);
        });
    
        // run the sub parsers
        text = showdown.subParser('metadata')(text, options, globals);
        text = showdown.subParser('hashPreCodeTags')(text, options, globals);
        text = showdown.subParser('githubCodeBlocks')(text, options, globals);
        text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
        text = showdown.subParser('hashCodeTags')(text, options, globals);
        text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
        text = showdown.subParser('blockGamut')(text, options, globals);
        text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
        text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
    
        // attacklab: Restore dollar signs
        text = text.replace(/¨D/g, '$$');
    
        // attacklab: Restore tremas
        text = text.replace(/¨T/g, '¨');
    
        // render a complete html document instead of a partial if the option is enabled
        text = showdown.subParser('completeHTMLDocument')(text, options, globals);
    
        // Run output modifiers
        showdown.helper.forEach(outputModifiers, function (ext) {
          text = showdown.subParser('runExtension')(ext, text, options, globals);
        });
    
        // update metadata
        metadata = globals.metadata;
        return text;
      };
    
      /**
       * Converts an HTML string into a markdown string
       * @param src
       * @param [HTMLParser] A WHATWG DOM and HTML parser, such as JSDOM. If none is supplied, window.document will be used.
       * @returns {string}
       */
      this.makeMarkdown = this.makeMd = function (src, HTMLParser) {
    
        // replace \r\n with \n
        src = src.replace(/\r\n/g, '\n');
        src = src.replace(/\r/g, '\n'); // old macs
    
        // due to an edge case, we need to find this: > <
        // to prevent removing of non silent white spaces
        // ex: <em>this is</em> <strong>sparta</strong>
        src = src.replace(/>[ \t]+</, '>¨NBSP;<');
    
        if (!HTMLParser) {
          if (window && window.document) {
            HTMLParser = window.document;
          } else {
            throw new Error('HTMLParser is undefined. If in a webworker or nodejs environment, you need to provide a WHATWG DOM and HTML such as JSDOM');
          }
        }
    
        var doc = HTMLParser.createElement('div');
        doc.innerHTML = src;
    
        var globals = {
          preList: substitutePreCodeTags(doc)
        };
    
        // remove all newlines and collapse spaces
        clean(doc);
    
        // some stuff, like accidental reference links must now be escaped
        // TODO
        // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/);
    
        var nodes = doc.childNodes,
            mdDoc = '';
    
        for (var i = 0; i < nodes.length; i++) {
          mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals);
        }
    
        function clean (node) {
          for (var n = 0; n < node.childNodes.length; ++n) {
            var child = node.childNodes[n];
            if (child.nodeType === 3) {
              if (!/\S/.test(child.nodeValue)) {
                node.removeChild(child);
                --n;
              } else {
                child.nodeValue = child.nodeValue.split('\n').join(' ');
                child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1');
              }
            } else if (child.nodeType === 1) {
              clean(child);
            }
          }
        }
    
        // find all pre tags and replace contents with placeholder
        // we need this so that we can remove all indentation from html
        // to ease up parsing
        function substitutePreCodeTags (doc) {
    
          var pres = doc.querySelectorAll('pre'),
              presPH = [];
    
          for (var i = 0; i < pres.length; ++i) {
    
            if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') {
              var content = pres[i].firstChild.innerHTML.trim(),
                  language = pres[i].firstChild.getAttribute('data-language') || '';
    
              // if data-language attribute is not defined, then we look for class language-*
              if (language === '') {
                var classes = pres[i].firstChild.className.split(' ');
                for (var c = 0; c < classes.length; ++c) {
                  var matches = classes[c].match(/^language-(.+)$/);
                  if (matches !== null) {
                    language = matches[1];
                    break;
                  }
                }
              }
    
              // unescape html entities in content
              content = showdown.helper.unescapeHTMLEntities(content);
    
              presPH.push(content);
              pres[i].outerHTML = '<precode language="' + language + '" precodenum="' + i.toString() + '"></precode>';
            } else {
              presPH.push(pres[i].innerHTML);
              pres[i].innerHTML = '';
              pres[i].setAttribute('prenum', i.toString());
            }
          }
          return presPH;
        }
    
        return mdDoc;
      };
    
      /**
       * Set an option of this Converter instance
       * @param {string} key
       * @param {*} value
       */
      this.setOption = function (key, value) {
        options[key] = value;
      };
    
      /**
       * Get the option of this Converter instance
       * @param {string} key
       * @returns {*}
       */
      this.getOption = function (key) {
        return options[key];
      };
    
      /**
       * Get the options of this Converter instance
       * @returns {{}}
       */
      this.getOptions = function () {
        return options;
      };
    
      /**
       * Add extension to THIS converter
       * @param {{}} extension
       * @param {string} [name=null]
       */
      this.addExtension = function (extension, name) {
        name = name || null;
        _parseExtension(extension, name);
      };
    
      /**
       * Use a global registered extension with THIS converter
       * @param {string} extensionName Name of the previously registered extension
       */
      this.useExtension = function (extensionName) {
        _parseExtension(extensionName);
      };
    
      /**
       * Set the flavor THIS converter should use
       * @param {string} name
       */
      this.setFlavor = function (name) {
        if (!flavor.hasOwnProperty(name)) {
          throw Error(name + ' flavor was not found');
        }
        var preset = flavor[name];
        setConvFlavor = name;
        for (var option in preset) {
          if (preset.hasOwnProperty(option)) {
            options[option] = preset[option];
          }
        }
      };
    
      /**
       * Get the currently set flavor of this converter
       * @returns {string}
       */
      this.getFlavor = function () {
        return setConvFlavor;
      };
    
      /**
       * Remove an extension from THIS converter.
       * Note: This is a costly operation. It's better to initialize a new converter
       * and specify the extensions you wish to use
       * @param {Array} extension
       */
      this.removeExtension = function (extension) {
        if (!showdown.helper.isArray(extension)) {
          extension = [extension];
        }
        for (var a = 0; a < extension.length; ++a) {
          var ext = extension[a];
          for (var i = 0; i < langExtensions.length; ++i) {
            if (langExtensions[i] === ext) {
              langExtensions[i].splice(i, 1);
            }
          }
          for (var ii = 0; ii < outputModifiers.length; ++i) {
            if (outputModifiers[ii] === ext) {
              outputModifiers[ii].splice(i, 1);
            }
          }
        }
      };
    
      /**
       * Get all extension of THIS converter
       * @returns {{language: Array, output: Array}}
       */
      this.getAllExtensions = function () {
        return {
          language: langExtensions,
          output: outputModifiers
        };
      };
    
      /**
       * Get the metadata of the previously parsed document
       * @param raw
       * @returns {string|{}}
       */
      this.getMetadata = function (raw) {
        if (raw) {
          return metadata.raw;
        } else {
          return metadata.parsed;
        }
      };
    
      /**
       * Get the metadata format of the previously parsed document
       * @returns {string}
       */
      this.getMetadataFormat = function () {
        return metadata.format;
      };
    
      /**
       * Private: set a single key, value metadata pair
       * @param {string} key
       * @param {string} value
       */
      this._setMetadataPair = function (key, value) {
        metadata.parsed[key] = value;
      };
    
      /**
       * Private: set metadata format
       * @param {string} format
       */
      this._setMetadataFormat = function (format) {
        metadata.format = format;
      };
    
      /**
       * Private: set metadata raw text
       * @param {string} raw
       */
      this._setMetadataRaw = function (raw) {
        metadata.raw = raw;
      };
    };
    
    /**
     * Turn Markdown link shortcuts into XHTML <a> tags.
     */
    showdown.subParser('anchors', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('anchors.before', text, options, globals);
    
      var writeAnchorTag = function (wholeMatch, linkText, linkId, url, m5, m6, title) {
        if (showdown.helper.isUndefined(title)) {
          title = '';
        }
        linkId = linkId.toLowerCase();
    
        // Special case for explicit empty url
        if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
          url = '';
        } else if (!url) {
          if (!linkId) {
            // lower-case and turn embedded newlines into spaces
            linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
          }
          url = '#' + linkId;
    
          if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
            url = globals.gUrls[linkId];
            if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
              title = globals.gTitles[linkId];
            }
          } else {
            return wholeMatch;
          }
        }
    
        //url = showdown.helper.escapeCharacters(url, '*_', false); // replaced line to improve performance
        url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
    
        var result = '<a href="' + url + '"';
    
        if (title !== '' && title !== null) {
          title = title.replace(/"/g, '&quot;');
          //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance
          title = title.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
          result += ' title="' + title + '"';
        }
    
        // optionLinksInNewWindow only applies
        // to external links. Hash links (#) open in same page
        if (options.openLinksInNewWindow && !/^#/.test(url)) {
          // escaped _
          result += ' rel="noopener noreferrer" target="¨E95Eblank"';
        }
    
        result += '>' + linkText + '</a>';
    
        return result;
      };
    
      // First, handle reference-style links: [link text] [id]
      text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g, writeAnchorTag);
    
      // Next, inline-style links: [link text](url "optional title")
      // cases with crazy urls like ./image/cat1).png
      text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
        writeAnchorTag);
    
      // normal cases
      text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
        writeAnchorTag);
    
      // handle reference-style shortcuts: [link text]
      // These must come last in case you've also got [link test][1]
      // or [link test](/foo)
      text = text.replace(/\[([^\[\]]+)]()()()()()/g, writeAnchorTag);
    
      // Lastly handle GithubMentions if option is enabled
      if (options.ghMentions) {
        text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function (wm, st, escape, mentions, username) {
          if (escape === '\\') {
            return st + mentions;
          }
    
          //check if options.ghMentionsLink is a string
          if (!showdown.helper.isString(options.ghMentionsLink)) {
            throw new Error('ghMentionsLink option must be a string');
          }
          var lnk = options.ghMentionsLink.replace(/\{u}/g, username),
              target = '';
          if (options.openLinksInNewWindow) {
            target = ' rel="noopener noreferrer" target="¨E95Eblank"';
          }
          return st + '<a href="' + lnk + '"' + target + '>' + mentions + '</a>';
        });
      }
    
      text = globals.converter._dispatch('anchors.after', text, options, globals);
      return text;
    });
    
    // url allowed chars [a-z\d_.~:/?#[]@!$&'()*+,;=-]
    
    var simpleURLRegex  = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi,
        simpleURLRegex2 = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi,
        delimUrlRegex   = /()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi,
        simpleMailRegex = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi,
        delimMailRegex  = /<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
    
        replaceLink = function (options) {
          'use strict';
          return function (wm, leadingMagicChars, link, m2, m3, trailingPunctuation, trailingMagicChars) {
            link = link.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
            var lnkTxt = link,
                append = '',
                target = '',
                lmc    = leadingMagicChars || '',
                tmc    = trailingMagicChars || '';
            if (/^www\./i.test(link)) {
              link = link.replace(/^www\./i, 'http://www.');
            }
            if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) {
              append = trailingPunctuation;
            }
            if (options.openLinksInNewWindow) {
              target = ' rel="noopener noreferrer" target="¨E95Eblank"';
            }
            return lmc + '<a href="' + link + '"' + target + '>' + lnkTxt + '</a>' + append + tmc;
          };
        },
    
        replaceMail = function (options, globals) {
          'use strict';
          return function (wholeMatch, b, mail) {
            var href = 'mailto:';
            b = b || '';
            mail = showdown.subParser('unescapeSpecialChars')(mail, options, globals);
            if (options.encodeEmails) {
              href = showdown.helper.encodeEmailAddress(href + mail);
              mail = showdown.helper.encodeEmailAddress(mail);
            } else {
              href = href + mail;
            }
            return b + '<a href="' + href + '">' + mail + '</a>';
          };
        };
    
    showdown.subParser('autoLinks', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('autoLinks.before', text, options, globals);
    
      text = text.replace(delimUrlRegex, replaceLink(options));
      text = text.replace(delimMailRegex, replaceMail(options, globals));
    
      text = globals.converter._dispatch('autoLinks.after', text, options, globals);
    
      return text;
    });
    
    showdown.subParser('simplifiedAutoLinks', function (text, options, globals) {
      'use strict';
    
      if (!options.simplifiedAutoLink) {
        return text;
      }
    
      text = globals.converter._dispatch('simplifiedAutoLinks.before', text, options, globals);
    
      if (options.excludeTrailingPunctuationFromURLs) {
        text = text.replace(simpleURLRegex2, replaceLink(options));
      } else {
        text = text.replace(simpleURLRegex, replaceLink(options));
      }
      text = text.replace(simpleMailRegex, replaceMail(options, globals));
    
      text = globals.converter._dispatch('simplifiedAutoLinks.after', text, options, globals);
    
      return text;
    });
    
    /**
     * These are all the transformations that form block-level
     * tags like paragraphs, headers, and list items.
     */
    showdown.subParser('blockGamut', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('blockGamut.before', text, options, globals);
    
      // we parse blockquotes first so that we can have headings and hrs
      // inside blockquotes
      text = showdown.subParser('blockQuotes')(text, options, globals);
      text = showdown.subParser('headers')(text, options, globals);
    
      // Do Horizontal Rules:
      text = showdown.subParser('horizontalRule')(text, options, globals);
    
      text = showdown.subParser('lists')(text, options, globals);
      text = showdown.subParser('codeBlocks')(text, options, globals);
      text = showdown.subParser('tables')(text, options, globals);
    
      // We already ran _HashHTMLBlocks() before, in Markdown(), but that
      // was to escape raw HTML in the original Markdown source. This time,
      // we're escaping the markup we've just created, so that we don't wrap
      // <p> tags around block-level tags.
      text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
      text = showdown.subParser('paragraphs')(text, options, globals);
    
      text = globals.converter._dispatch('blockGamut.after', text, options, globals);
    
      return text;
    });
    
    showdown.subParser('blockQuotes', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('blockQuotes.before', text, options, globals);
    
      // add a couple extra lines after the text and endtext mark
      text = text + '\n\n';
    
      var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;
    
      if (options.splitAdjacentBlockquotes) {
        rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm;
      }
    
      text = text.replace(rgx, function (bq) {
        // attacklab: hack around Konqueror 3.5.4 bug:
        // "----------bug".replace(/^-/g,"") == "bug"
        bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting
    
        // attacklab: clean up hack
        bq = bq.replace(/¨0/g, '');
    
        bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
        bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
        bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
    
        bq = bq.replace(/(^|\n)/g, '$1  ');
        // These leading spaces screw with <pre> content, so we need to fix that:
        bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
          var pre = m1;
          // attacklab: hack around Konqueror 3.5.4 bug:
          pre = pre.replace(/^  /mg, '¨0');
          pre = pre.replace(/¨0/g, '');
          return pre;
        });
    
        return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
      });
    
      text = globals.converter._dispatch('blockQuotes.after', text, options, globals);
      return text;
    });
    
    /**
     * Process Markdown `<pre><code>` blocks.
     */
    showdown.subParser('codeBlocks', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
    
      // sentinel workarounds for lack of \A and \Z, safari\khtml bug
      text += '¨0';
    
      var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
      text = text.replace(pattern, function (wholeMatch, m1, m2) {
        var codeblock = m1,
            nextChar = m2,
            end = '\n';
    
        codeblock = showdown.subParser('outdent')(codeblock, options, globals);
        codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
        codeblock = showdown.subParser('detab')(codeblock, options, globals);
        codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
        codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
    
        if (options.omitExtraWLInCodeBlocks) {
          end = '';
        }
    
        codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
    
        return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
      });
    
      // strip sentinel
      text = text.replace(/¨0/, '');
    
      text = globals.converter._dispatch('codeBlocks.after', text, options, globals);
      return text;
    });
    
    /**
     *
     *   *  Backtick quotes are used for <code></code> spans.
     *
     *   *  You can use multiple backticks as the delimiters if you want to
     *     include literal backticks in the code span. So, this input:
     *
     *         Just type ``foo `bar` baz`` at the prompt.
     *
     *       Will translate to:
     *
     *         <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
     *
     *    There's no arbitrary limit to the number of backticks you
     *    can use as delimters. If you need three consecutive backticks
     *    in your code, use four for delimiters, etc.
     *
     *  *  You can use spaces to get literal backticks at the edges:
     *
     *         ... type `` `bar` `` ...
     *
     *       Turns to:
     *
     *         ... type <code>`bar`</code> ...
     */
    showdown.subParser('codeSpans', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('codeSpans.before', text, options, globals);
    
      if (typeof text === 'undefined') {
        text = '';
      }
      text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
        function (wholeMatch, m1, m2, m3) {
          var c = m3;
          c = c.replace(/^([ \t]*)/g, '');	// leading whitespace
          c = c.replace(/[ \t]*$/g, '');	// trailing whitespace
          c = showdown.subParser('encodeCode')(c, options, globals);
          c = m1 + '<code>' + c + '</code>';
          c = showdown.subParser('hashHTMLSpans')(c, options, globals);
          return c;
        }
      );
    
      text = globals.converter._dispatch('codeSpans.after', text, options, globals);
      return text;
    });
    
    /**
     * Create a full HTML document from the processed markdown
     */
    showdown.subParser('completeHTMLDocument', function (text, options, globals) {
      'use strict';
    
      if (!options.completeHTMLDocument) {
        return text;
      }
    
      text = globals.converter._dispatch('completeHTMLDocument.before', text, options, globals);
    
      var doctype = 'html',
          doctypeParsed = '<!DOCTYPE HTML>\n',
          title = '',
          charset = '<meta charset="utf-8">\n',
          lang = '',
          metadata = '';
    
      if (typeof globals.metadata.parsed.doctype !== 'undefined') {
        doctypeParsed = '<!DOCTYPE ' +  globals.metadata.parsed.doctype + '>\n';
        doctype = globals.metadata.parsed.doctype.toString().toLowerCase();
        if (doctype === 'html' || doctype === 'html5') {
          charset = '<meta charset="utf-8">';
        }
      }
    
      for (var meta in globals.metadata.parsed) {
        if (globals.metadata.parsed.hasOwnProperty(meta)) {
          switch (meta.toLowerCase()) {
            case 'doctype':
              break;
    
            case 'title':
              title = '<title>' +  globals.metadata.parsed.title + '</title>\n';
              break;
    
            case 'charset':
              if (doctype === 'html' || doctype === 'html5') {
                charset = '<meta charset="' + globals.metadata.parsed.charset + '">\n';
              } else {
                charset = '<meta name="charset" content="' + globals.metadata.parsed.charset + '">\n';
              }
              break;
    
            case 'language':
            case 'lang':
              lang = ' lang="' + globals.metadata.parsed[meta] + '"';
              metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
              break;
    
            default:
              metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
          }
        }
      }
    
      text = doctypeParsed + '<html' + lang + '>\n<head>\n' + title + charset + metadata + '</head>\n<body>\n' + text.trim() + '\n</body>\n</html>';
    
      text = globals.converter._dispatch('completeHTMLDocument.after', text, options, globals);
      return text;
    });
    
    /**
     * Convert all tabs to spaces
     */
    showdown.subParser('detab', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('detab.before', text, options, globals);
    
      // expand first n-1 tabs
      text = text.replace(/\t(?=\t)/g, '    '); // g_tab_width
    
      // replace the nth with two sentinels
      text = text.replace(/\t/g, '¨A¨B');
    
      // use the sentinel to anchor our regex so it doesn't explode
      text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) {
        var leadingText = m1,
            numSpaces = 4 - leadingText.length % 4;  // g_tab_width
    
        // there *must* be a better way to do this:
        for (var i = 0; i < numSpaces; i++) {
          leadingText += ' ';
        }
    
        return leadingText;
      });
    
      // clean up sentinels
      text = text.replace(/¨A/g, '    ');  // g_tab_width
      text = text.replace(/¨B/g, '');
    
      text = globals.converter._dispatch('detab.after', text, options, globals);
      return text;
    });
    
    showdown.subParser('ellipsis', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('ellipsis.before', text, options, globals);
    
      text = text.replace(/\.\.\./g, '…');
    
      text = globals.converter._dispatch('ellipsis.after', text, options, globals);
    
      return text;
    });
    
    /**
     * Turn emoji codes into emojis
     *
     * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis
     */
    showdown.subParser('emoji', function (text, options, globals) {
      'use strict';
    
      if (!options.emoji) {
        return text;
      }
    
      text = globals.converter._dispatch('emoji.before', text, options, globals);
    
      var emojiRgx = /:([\S]+?):/g;
    
      text = text.replace(emojiRgx, function (wm, emojiCode) {
        if (showdown.helper.emojis.hasOwnProperty(emojiCode)) {
          return showdown.helper.emojis[emojiCode];
        }
        return wm;
      });
    
      text = globals.converter._dispatch('emoji.after', text, options, globals);
    
      return text;
    });
    
    /**
     * Smart processing for ampersands and angle brackets that need to be encoded.
     */
    showdown.subParser('encodeAmpsAndAngles', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('encodeAmpsAndAngles.before', text, options, globals);
    
      // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
      // http://bumppo.net/projects/amputator/
      text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
    
      // Encode naked <'s
      text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');
    
      // Encode <
      text = text.replace(/</g, '&lt;');
    
      // Encode >
      text = text.replace(/>/g, '&gt;');
    
      text = globals.converter._dispatch('encodeAmpsAndAngles.after', text, options, globals);
      return text;
    });
    
    /**
     * Returns the string, with after processing the following backslash escape sequences.
     *
     * attacklab: The polite way to do this is with the new escapeCharacters() function:
     *
     *    text = escapeCharacters(text,"\\",true);
     *    text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
     *
     * ...but we're sidestepping its use of the (slow) RegExp constructor
     * as an optimization for Firefox.  This function gets called a LOT.
     */
    showdown.subParser('encodeBackslashEscapes', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('encodeBackslashEscapes.before', text, options, globals);
    
      text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
      text = text.replace(/\\([`*_{}\[\]()>#+.!~=|-])/g, showdown.helper.escapeCharactersCallback);
    
      text = globals.converter._dispatch('encodeBackslashEscapes.after', text, options, globals);
      return text;
    });
    
    /**
     * Encode/escape certain characters inside Markdown code runs.
     * The point is that in code, these characters are literals,
     * and lose their special Markdown meanings.
     */
    showdown.subParser('encodeCode', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('encodeCode.before', text, options, globals);
    
      // Encode all ampersands; HTML entities are not
      // entities within a Markdown code span.
      text = text
        .replace(/&/g, '&amp;')
      // Do the angle bracket song and dance:
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
      // Now, escape characters that are magic in Markdown:
        .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback);
    
      text = globals.converter._dispatch('encodeCode.after', text, options, globals);
      return text;
    });
    
    /**
     * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they
     * don't conflict with their use in Markdown for code, italics and strong.
     */
    showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.before', text, options, globals);
    
      // Build a regex to find HTML tags.
      var tags     = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,
          comments = /<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi;
    
      text = text.replace(tags, function (wholeMatch) {
        return wholeMatch
          .replace(/(.)<\/?code>(?=.)/g, '$1`')
          .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
      });
    
      text = text.replace(comments, function (wholeMatch) {
        return wholeMatch
          .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
      });
    
      text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.after', text, options, globals);
      return text;
    });
    
    /**
     * Handle github codeblocks prior to running HashHTML so that
     * HTML contained within the codeblock gets escaped properly
     * Example:
     * ```ruby
     *     def hello_world(x)
     *       puts "Hello, #{x}"
     *     end
     * ```
     */
    showdown.subParser('githubCodeBlocks', function (text, options, globals) {
      'use strict';
    
      // early exit if option is not enabled
      if (!options.ghCodeBlocks) {
        return text;
      }
    
      text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
    
      text += '¨0';
    
      text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) {
        var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
    
        // First parse the github code block
        codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
        codeblock = showdown.subParser('detab')(codeblock, options, globals);
        codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
        codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
    
        codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
    
        codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
    
        // Since GHCodeblocks can be false positives, we need to
        // store the primitive text and the parsed text in a global var,
        // and then return a token
        return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
      });
    
      // attacklab: strip sentinel
      text = text.replace(/¨0/, '');
    
      return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
    });
    
    showdown.subParser('hashBlock', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('hashBlock.before', text, options, globals);
      text = text.replace(/(^\n+|\n+$)/g, '');
      text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
      text = globals.converter._dispatch('hashBlock.after', text, options, globals);
      return text;
    });
    
    /**
     * Hash and escape <code> elements that should not be parsed as markdown
     */
    showdown.subParser('hashCodeTags', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('hashCodeTags.before', text, options, globals);
    
      var repFunc = function (wholeMatch, match, left, right) {
        var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
        return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C';
      };
    
      // Hash naked <code>
      text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '<code\\b[^>]*>', '</code>', 'gim');
    
      text = globals.converter._dispatch('hashCodeTags.after', text, options, globals);
      return text;
    });
    
    showdown.subParser('hashElement', function (text, options, globals) {
      'use strict';
    
      return function (wholeMatch, m1) {
        var blockText = m1;
    
        // Undo double lines
        blockText = blockText.replace(/\n\n/g, '\n');
        blockText = blockText.replace(/^\n/, '');
    
        // strip trailing blank lines
        blockText = blockText.replace(/\n+$/g, '');
    
        // Replace the element text with a marker ("¨KxK" where x is its key)
        blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
    
        return blockText;
      };
    });
    
    showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('hashHTMLBlocks.before', text, options, globals);
    
      var blockTags = [
            'pre',
            'div',
            'h1',
            'h2',
            'h3',
            'h4',
            'h5',
            'h6',
            'blockquote',
            'table',
            'dl',
            'ol',
            'ul',
            'script',
            'noscript',
            'form',
            'fieldset',
            'iframe',
            'math',
            'style',
            'section',
            'header',
            'footer',
            'nav',
            'article',
            'aside',
            'address',
            'audio',
            'canvas',
            'figure',
            'hgroup',
            'output',
            'video',
            'p'
          ],
          repFunc = function (wholeMatch, match, left, right) {
            var txt = wholeMatch;
            // check if this html element is marked as markdown
            // if so, it's contents should be parsed as markdown
            if (left.search(/\bmarkdown\b/) !== -1) {
              txt = left + globals.converter.makeHtml(match) + right;
            }
            return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
          };
    
      if (options.backslashEscapesHTMLTags) {
        // encode backslash escaped HTML tags
        text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) {
          return '&lt;' + inside + '&gt;';
        });
      }
    
      // hash HTML Blocks
      for (var i = 0; i < blockTags.length; ++i) {
    
        var opTagPos,
            rgx1     = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'),
            patLeft  = '<' + blockTags[i] + '\\b[^>]*>',
            patRight = '</' + blockTags[i] + '>';
        // 1. Look for the first position of the first opening HTML tag in the text
        while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) {
    
          // if the HTML tag is \ escaped, we need to escape it and break
    
    
          //2. Split the text in that position
          var subTexts = showdown.helper.splitAtIndex(text, opTagPos),
              //3. Match recursively
              newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im');
    
          // prevent an infinite loop
          if (newSubText1 === subTexts[1]) {
            break;
          }
          text = subTexts[0].concat(newSubText1);
        }
      }
      // HR SPECIAL CASE
      text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
        showdown.subParser('hashElement')(text, options, globals));
    
      // Special case for standalone HTML comments
      text = showdown.helper.replaceRecursiveRegExp(text, function (txt) {
        return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
      }, '^ {0,3}<!--', '-->', 'gm');
    
      // PHP and ASP-style processor instructions (<?...?> and <%...%>)
      text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
        showdown.subParser('hashElement')(text, options, globals));
    
      text = globals.converter._dispatch('hashHTMLBlocks.after', text, options, globals);
      return text;
    });
    
    /**
     * Hash span elements that should not be parsed as markdown
     */
    showdown.subParser('hashHTMLSpans', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('hashHTMLSpans.before', text, options, globals);
    
      function hashHTMLSpan (html) {
        return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C';
      }
    
      // Hash Self Closing tags
      text = text.replace(/<[^>]+?\/>/gi, function (wm) {
        return hashHTMLSpan(wm);
      });
    
      // Hash tags without properties
      text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) {
        return hashHTMLSpan(wm);
      });
    
      // Hash tags with properties
      text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) {
        return hashHTMLSpan(wm);
      });
    
      // Hash self closing tags without />
      text = text.replace(/<[^>]+?>/gi, function (wm) {
        return hashHTMLSpan(wm);
      });
    
      /*showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');*/
    
      text = globals.converter._dispatch('hashHTMLSpans.after', text, options, globals);
      return text;
    });
    
    /**
     * Unhash HTML spans
     */
    showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
    
      for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
        var repText = globals.gHtmlSpans[i],
            // limiter to prevent infinite loop (assume 10 as limit for recurse)
            limit = 0;
    
        while (/¨C(\d+)C/.test(repText)) {
          var num = RegExp.$1;
          repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
          if (limit === 10) {
            console.error('maximum nesting of 10 spans reached!!!');
            break;
          }
          ++limit;
        }
        text = text.replace('¨C' + i + 'C', repText);
      }
    
      text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
      return text;
    });
    
    /**
     * Hash and escape <pre><code> elements that should not be parsed as markdown
     */
    showdown.subParser('hashPreCodeTags', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('hashPreCodeTags.before', text, options, globals);
    
      var repFunc = function (wholeMatch, match, left, right) {
        // encode html entities
        var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
        return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
      };
    
      // Hash <pre><code>
      text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim');
    
      text = globals.converter._dispatch('hashPreCodeTags.after', text, options, globals);
      return text;
    });
    
    showdown.subParser('headers', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('headers.before', text, options, globals);
    
      var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
    
          // Set text-style headers:
          //	Header 1
          //	========
          //
          //	Header 2
          //	--------
          //
          setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
          setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
    
      text = text.replace(setextRegexH1, function (wholeMatch, m1) {
    
        var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
            hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
            hLevel = headerLevelStart,
            hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
        return showdown.subParser('hashBlock')(hashBlock, options, globals);
      });
    
      text = text.replace(setextRegexH2, function (matchFound, m1) {
        var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
            hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
            hLevel = headerLevelStart + 1,
            hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
        return showdown.subParser('hashBlock')(hashBlock, options, globals);
      });
    
      // atx-style headers:
      //  # Header 1
      //  ## Header 2
      //  ## Header 2 with closing hashes ##
      //  ...
      //  ###### Header 6
      //
      var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
    
      text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
        var hText = m2;
        if (options.customizedHeaderId) {
          hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
        }
    
        var span = showdown.subParser('spanGamut')(hText, options, globals),
            hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
            hLevel = headerLevelStart - 1 + m1.length,
            header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
    
        return showdown.subParser('hashBlock')(header, options, globals);
      });
    
      function headerId (m) {
        var title,
            prefix;
    
        // It is separate from other options to allow combining prefix and customized
        if (options.customizedHeaderId) {
          var match = m.match(/\{([^{]+?)}\s*$/);
          if (match && match[1]) {
            m = match[1];
          }
        }
    
        title = m;
    
        // Prefix id to prevent causing inadvertent pre-existing style matches.
        if (showdown.helper.isString(options.prefixHeaderId)) {
          prefix = options.prefixHeaderId;
        } else if (options.prefixHeaderId === true) {
          prefix = 'section-';
        } else {
          prefix = '';
        }
    
        if (!options.rawPrefixHeaderId) {
          title = prefix + title;
        }
    
        if (options.ghCompatibleHeaderId) {
          title = title
            .replace(/ /g, '-')
            // replace previously escaped chars (&, ¨ and $)
            .replace(/&amp;/g, '')
            .replace(/¨T/g, '')
            .replace(/¨D/g, '')
            // replace rest of the chars (&~$ are repeated as they might have been escaped)
            // borrowed from github's redcarpet (some they should produce similar results)
            .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
            .toLowerCase();
        } else if (options.rawHeaderId) {
          title = title
            .replace(/ /g, '-')
            // replace previously escaped chars (&, ¨ and $)
            .replace(/&amp;/g, '&')
            .replace(/¨T/g, '¨')
            .replace(/¨D/g, '$')
            // replace " and '
            .replace(/["']/g, '-')
            .toLowerCase();
        } else {
          title = title
            .replace(/[^\w]/g, '')
            .toLowerCase();
        }
    
        if (options.rawPrefixHeaderId) {
          title = prefix + title;
        }
    
        if (globals.hashLinkCounts[title]) {
          title = title + '-' + (globals.hashLinkCounts[title]++);
        } else {
          globals.hashLinkCounts[title] = 1;
        }
        return title;
      }
    
      text = globals.converter._dispatch('headers.after', text, options, globals);
      return text;
    });
    
    /**
     * Turn Markdown link shortcuts into XHTML <a> tags.
     */
    showdown.subParser('horizontalRule', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('horizontalRule.before', text, options, globals);
    
      var key = showdown.subParser('hashBlock')('<hr />', options, globals);
      text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key);
      text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key);
      text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key);
    
      text = globals.converter._dispatch('horizontalRule.after', text, options, globals);
      return text;
    });
    
    /**
     * Turn Markdown image shortcuts into <img> tags.
     */
    showdown.subParser('images', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('images.before', text, options, globals);
    
      var inlineRegExp      = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
          crazyRegExp       = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
          base64RegExp      = /!\[([^\]]*?)][ \t]*()\([ \t]?<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
          referenceRegExp   = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
          refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
    
      function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
        url = url.replace(/\s/g, '');
        return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
      }
    
      function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
    
        var gUrls   = globals.gUrls,
            gTitles = globals.gTitles,
            gDims   = globals.gDimensions;
    
        linkId = linkId.toLowerCase();
    
        if (!title) {
          title = '';
        }
        // Special case for explicit empty url
        if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
          url = '';
    
        } else if (url === '' || url === null) {
          if (linkId === '' || linkId === null) {
            // lower-case and turn embedded newlines into spaces
            linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
          }
          url = '#' + linkId;
    
          if (!showdown.helper.isUndefined(gUrls[linkId])) {
            url = gUrls[linkId];
            if (!showdown.helper.isUndefined(gTitles[linkId])) {
              title = gTitles[linkId];
            }
            if (!showdown.helper.isUndefined(gDims[linkId])) {
              width = gDims[linkId].width;
              height = gDims[linkId].height;
            }
          } else {
            return wholeMatch;
          }
        }
    
        altText = altText
          .replace(/"/g, '&quot;')
        //altText = showdown.helper.escapeCharacters(altText, '*_', false);
          .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
        //url = showdown.helper.escapeCharacters(url, '*_', false);
        url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
        var result = '<img src="' + url + '" alt="' + altText + '"';
    
        if (title && showdown.helper.isString(title)) {
          title = title
            .replace(/"/g, '&quot;')
          //title = showdown.helper.escapeCharacters(title, '*_', false);
            .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
          result += ' title="' + title + '"';
        }
    
        if (width && height) {
          width  = (width === '*') ? 'auto' : width;
          height = (height === '*') ? 'auto' : height;
    
          result += ' width="' + width + '"';
          result += ' height="' + height + '"';
        }
    
        result += ' />';
    
        return result;
      }
    
      // First, handle reference-style labeled images: ![alt text][id]
      text = text.replace(referenceRegExp, writeImageTag);
    
      // Next, handle inline images:  ![alt text](url =<width>x<height> "optional title")
    
      // base64 encoded images
      text = text.replace(base64RegExp, writeImageTagBase64);
    
      // cases with crazy urls like ./image/cat1).png
      text = text.replace(crazyRegExp, writeImageTag);
    
      // normal cases
      text = text.replace(inlineRegExp, writeImageTag);
    
      // handle reference-style shortcuts: ![img text]
      text = text.replace(refShortcutRegExp, writeImageTag);
    
      text = globals.converter._dispatch('images.after', text, options, globals);
      return text;
    });
    
    showdown.subParser('italicsAndBold', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('italicsAndBold.before', text, options, globals);
    
      // it's faster to have 3 separate regexes for each case than have just one
      // because of backtracing, in some cases, it could lead to an exponential effect
      // called "catastrophic backtrace". Ominous!
    
      function parseInside (txt, left, right) {
        /*
        if (options.simplifiedAutoLink) {
          txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
        }
        */
        return left + txt + right;
      }
    
      // Parse underscores
      if (options.literalMidWordUnderscores) {
        text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
          return parseInside (txt, '<strong><em>', '</em></strong>');
        });
        text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
          return parseInside (txt, '<strong>', '</strong>');
        });
        text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) {
          return parseInside (txt, '<em>', '</em>');
        });
      } else {
        text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
          return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
        });
        text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
          return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
        });
        text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) {
          // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it)
          return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
        });
      }
    
      // Now parse asterisks
      if (options.literalMidWordAsterisks) {
        text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) {
          return parseInside (txt, lead + '<strong><em>', '</em></strong>');
        });
        text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g, function (wm, lead, txt) {
          return parseInside (txt, lead + '<strong>', '</strong>');
        });
        text = text.replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g, function (wm, lead, txt) {
          return parseInside (txt, lead + '<em>', '</em>');
        });
      } else {
        text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {
          return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
        });
        text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) {
          return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
        });
        text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) {
          // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it)
          return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
        });
      }
    
    
      text = globals.converter._dispatch('italicsAndBold.after', text, options, globals);
      return text;
    });
    
    /**
     * Form HTML ordered (numbered) and unordered (bulleted) lists.
     */
    showdown.subParser('lists', function (text, options, globals) {
      'use strict';
    
      /**
       * Process the contents of a single ordered or unordered list, splitting it
       * into individual list items.
       * @param {string} listStr
       * @param {boolean} trimTrailing
       * @returns {string}
       */
      function processListItems (listStr, trimTrailing) {
        // The $g_list_level global keeps track of when we're inside a list.
        // Each time we enter a list, we increment it; when we leave a list,
        // we decrement. If it's zero, we're not in a list anymore.
        //
        // We do this because when we're not inside a list, we want to treat
        // something like this:
        //
        //    I recommend upgrading to version
        //    8. Oops, now this line is treated
        //    as a sub-list.
        //
        // As a single paragraph, despite the fact that the second line starts
        // with a digit-period-space sequence.
        //
        // Whereas when we're inside a list (or sub-list), that line will be
        // treated as the start of a sub-list. What a kludge, huh? This is
        // an aspect of Markdown's syntax that's hard to parse perfectly
        // without resorting to mind-reading. Perhaps the solution is to
        // change the syntax rules such that sub-lists must start with a
        // starting cardinal number; e.g. "1." or "a.".
        globals.gListLevel++;
    
        // trim trailing blank lines:
        listStr = listStr.replace(/\n{2,}$/, '\n');
    
        // attacklab: add sentinel to emulate \z
        listStr += '¨0';
    
        var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
            isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr));
    
        // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation,
        // which is a syntax breaking change
        // activating this option reverts to old behavior
        if (options.disableForced4SpacesIndentedSublists) {
          rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
        }
    
        listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
          checked = (checked && checked.trim() !== '');
    
          var item = showdown.subParser('outdent')(m4, options, globals),
              bulletStyle = '';
    
          // Support for github tasklists
          if (taskbtn && options.tasklists) {
            bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
            item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
              var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
              if (checked) {
                otp += ' checked';
              }
              otp += '>';
              return otp;
            });
          }
    
          // ISSUE #312
          // This input: - - - a
          // causes trouble to the parser, since it interprets it as:
          // <ul><li><li><li>a</li></li></li></ul>
          // instead of:
          // <ul><li>- - a</li></ul>
          // So, to prevent it, we will put a marker (¨A)in the beginning of the line
          // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser
          item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) {
            return '¨A' + wm2;
          });
    
          // m1 - Leading line or
          // Has a double return (multi paragraph) or
          // Has sublist
          if (m1 || (item.search(/\n{2,}/) > -1)) {
            item = showdown.subParser('githubCodeBlocks')(item, options, globals);
            item = showdown.subParser('blockGamut')(item, options, globals);
          } else {
            // Recursion for sub-lists:
            item = showdown.subParser('lists')(item, options, globals);
            item = item.replace(/\n$/, ''); // chomp(item)
            item = showdown.subParser('hashHTMLBlocks')(item, options, globals);
    
            // Colapse double linebreaks
            item = item.replace(/\n\n+/g, '\n\n');
            if (isParagraphed) {
              item = showdown.subParser('paragraphs')(item, options, globals);
            } else {
              item = showdown.subParser('spanGamut')(item, options, globals);
            }
          }
    
          // now we need to remove the marker (¨A)
          item = item.replace('¨A', '');
          // we can finally wrap the line in list item tags
          item =  '<li' + bulletStyle + '>' + item + '</li>\n';
    
          return item;
        });
    
        // attacklab: strip sentinel
        listStr = listStr.replace(/¨0/g, '');
    
        globals.gListLevel--;
    
        if (trimTrailing) {
          listStr = listStr.replace(/\s+$/, '');
        }
    
        return listStr;
      }
    
      function styleStartNumber (list, listType) {
        // check if ol and starts by a number different than 1
        if (listType === 'ol') {
          var res = list.match(/^ *(\d+)\./);
          if (res && res[1] !== '1') {
            return ' start="' + res[1] + '"';
          }
        }
        return '';
      }
    
      /**
       * Check and parse consecutive lists (better fix for issue #142)
       * @param {string} list
       * @param {string} listType
       * @param {boolean} trimTrailing
       * @returns {string}
       */
      function parseConsecutiveLists (list, listType, trimTrailing) {
        // check if we caught 2 or more consecutive lists by mistake
        // we use the counterRgx, meaning if listType is UL we look for OL and vice versa
        var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm,
            ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm,
            counterRxg = (listType === 'ul') ? olRgx : ulRgx,
            result = '';
    
        if (list.search(counterRxg) !== -1) {
          (function parseCL (txt) {
            var pos = txt.search(counterRxg),
                style = styleStartNumber(list, listType);
            if (pos !== -1) {
              // slice
              result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n';
    
              // invert counterType and listType
              listType = (listType === 'ul') ? 'ol' : 'ul';
              counterRxg = (listType === 'ul') ? olRgx : ulRgx;
    
              //recurse
              parseCL(txt.slice(pos));
            } else {
              result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n';
            }
          })(list);
        } else {
          var style = styleStartNumber(list, listType);
          result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n';
        }
    
        return result;
      }
    
      /** Start of list parsing **/
      text = globals.converter._dispatch('lists.before', text, options, globals);
      // add sentinel to hack around khtml/safari bug:
      // http://bugs.webkit.org/show_bug.cgi?id=11231
      text += '¨0';
    
      if (globals.gListLevel) {
        text = text.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
          function (wholeMatch, list, m2) {
            var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
            return parseConsecutiveLists(list, listType, true);
          }
        );
      } else {
        text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
          function (wholeMatch, m1, list, m3) {
            var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
            return parseConsecutiveLists(list, listType, false);
          }
        );
      }
    
      // strip sentinel
      text = text.replace(/¨0/, '');
      text = globals.converter._dispatch('lists.after', text, options, globals);
      return text;
    });
    
    /**
     * Parse metadata at the top of the document
     */
    showdown.subParser('metadata', function (text, options, globals) {
      'use strict';
    
      if (!options.metadata) {
        return text;
      }
    
      text = globals.converter._dispatch('metadata.before', text, options, globals);
    
      function parseMetadataContents (content) {
        // raw is raw so it's not changed in any way
        globals.metadata.raw = content;
    
        // escape chars forbidden in html attributes
        // double quotes
        content = content
          // ampersand first
          .replace(/&/g, '&amp;')
          // double quotes
          .replace(/"/g, '&quot;');
    
        content = content.replace(/\n {4}/g, ' ');
        content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) {
          globals.metadata.parsed[key] = value;
          return '';
        });
      }
    
      text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) {
        parseMetadataContents(content);
        return '¨M';
      });
    
      text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) {
        if (format) {
          globals.metadata.format = format;
        }
        parseMetadataContents(content);
        return '¨M';
      });
    
      text = text.replace(/¨M/g, '');
    
      text = globals.converter._dispatch('metadata.after', text, options, globals);
      return text;
    });
    
    /**
     * Remove one level of line-leading tabs or spaces
     */
    showdown.subParser('outdent', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('outdent.before', text, options, globals);
    
      // attacklab: hack around Konqueror 3.5.4 bug:
      // "----------bug".replace(/^-/g,"") == "bug"
      text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width
    
      // attacklab: clean up hack
      text = text.replace(/¨0/g, '');
    
      text = globals.converter._dispatch('outdent.after', text, options, globals);
      return text;
    });
    
    /**
     *
     */
    showdown.subParser('paragraphs', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('paragraphs.before', text, options, globals);
      // Strip leading and trailing lines:
      text = text.replace(/^\n+/g, '');
      text = text.replace(/\n+$/g, '');
    
      var grafs = text.split(/\n{2,}/g),
          grafsOut = [],
          end = grafs.length; // Wrap <p> tags
    
      for (var i = 0; i < end; i++) {
        var str = grafs[i];
        // if this is an HTML marker, copy it
        if (str.search(/¨(K|G)(\d+)\1/g) >= 0) {
          grafsOut.push(str);
    
        // test for presence of characters to prevent empty lines being parsed
        // as paragraphs (resulting in undesired extra empty paragraphs)
        } else if (str.search(/\S/) >= 0) {
          str = showdown.subParser('spanGamut')(str, options, globals);
          str = str.replace(/^([ \t]*)/g, '<p>');
          str += '</p>';
          grafsOut.push(str);
        }
      }
    
      /** Unhashify HTML blocks */
      end = grafsOut.length;
      for (i = 0; i < end; i++) {
        var blockText = '',
            grafsOutIt = grafsOut[i],
            codeFlag = false;
        // if this is a marker for an html block...
        // use RegExp.test instead of string.search because of QML bug
        while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) {
          var delim = RegExp.$1,
              num   = RegExp.$2;
    
          if (delim === 'K') {
            blockText = globals.gHtmlBlocks[num];
          } else {
            // we need to check if ghBlock is a false positive
            if (codeFlag) {
              // use encoded version of all text
              blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text, options, globals);
            } else {
              blockText = globals.ghCodeBlocks[num].codeblock;
            }
          }
          blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
    
          grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText);
          // Check if grafsOutIt is a pre->code
          if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
            codeFlag = true;
          }
        }
        grafsOut[i] = grafsOutIt;
      }
      text = grafsOut.join('\n');
      // Strip leading and trailing lines:
      text = text.replace(/^\n+/g, '');
      text = text.replace(/\n+$/g, '');
      return globals.converter._dispatch('paragraphs.after', text, options, globals);
    });
    
    /**
     * Run extension
     */
    showdown.subParser('runExtension', function (ext, text, options, globals) {
      'use strict';
    
      if (ext.filter) {
        text = ext.filter(text, globals.converter, options);
    
      } else if (ext.regex) {
        // TODO remove this when old extension loading mechanism is deprecated
        var re = ext.regex;
        if (!(re instanceof RegExp)) {
          re = new RegExp(re, 'g');
        }
        text = text.replace(re, ext.replace);
      }
    
      return text;
    });
    
    /**
     * These are all the transformations that occur *within* block-level
     * tags like paragraphs, headers, and list items.
     */
    showdown.subParser('spanGamut', function (text, options, globals) {
      'use strict';
    
      text = globals.converter._dispatch('spanGamut.before', text, options, globals);
      text = showdown.subParser('codeSpans')(text, options, globals);
      text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
      text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
    
      // Process anchor and image tags. Images must come first,
      // because ![foo][f] looks like an anchor.
      text = showdown.subParser('images')(text, options, globals);
      text = showdown.subParser('anchors')(text, options, globals);
    
      // Make links out of things like `<http://example.com/>`
      // Must come after anchors, because you can use < and >
      // delimiters in inline links like [this](<url>).
      text = showdown.subParser('autoLinks')(text, options, globals);
      text = showdown.subParser('simplifiedAutoLinks')(text, options, globals);
      text = showdown.subParser('emoji')(text, options, globals);
      text = showdown.subParser('underline')(text, options, globals);
      text = showdown.subParser('italicsAndBold')(text, options, globals);
      text = showdown.subParser('strikethrough')(text, options, globals);
      text = showdown.subParser('ellipsis')(text, options, globals);
    
      // we need to hash HTML tags inside spans
      text = showdown.subParser('hashHTMLSpans')(text, options, globals);
    
      // now we encode amps and angles
      text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
    
      // Do hard breaks
      if (options.simpleLineBreaks) {
        // GFM style hard breaks
        // only add line breaks if the text does not contain a block (special case for lists)
        if (!/\n\n¨K/.test(text)) {
          text = text.replace(/\n+/g, '<br />\n');
        }
      } else {
        // Vanilla hard breaks
        text = text.replace(/  +\n/g, '<br />\n');
      }
    
      text = globals.converter._dispatch('spanGamut.after', text, options, globals);
      return text;
    });
    
    showdown.subParser('strikethrough', function (text, options, globals) {
      'use strict';
    
      function parseInside (txt) {
        if (options.simplifiedAutoLink) {
          txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
        }
        return '<del>' + txt + '</del>';
      }
    
      if (options.strikethrough) {
        text = globals.converter._dispatch('strikethrough.before', text, options, globals);
        text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return parseInside(txt); });
        text = globals.converter._dispatch('strikethrough.after', text, options, globals);
      }
    
      return text;
    });
    
    /**
     * Strips link definitions from text, stores the URLs and titles in
     * hash references.
     * Link defs are in the form: ^[id]: url "optional title"
     */
    showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
      'use strict';
    
      var regex       = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,
          base64Regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm;
    
      // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
      text += '¨0';
    
      var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
        linkId = linkId.toLowerCase();
        if (url.match(/^data:.+?\/.+?;base64,/)) {
          // remove newlines
          globals.gUrls[linkId] = url.replace(/\s/g, '');
        } else {
          globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals);  // Link IDs are case-insensitive
        }
    
        if (blankLines) {
          // Oops, found blank lines, so it's not a title.
          // Put back the parenthetical statement we stole.
          return blankLines + title;
    
        } else {
          if (title) {
            globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
          }
          if (options.parseImgDimensions && width && height) {
            globals.gDimensions[linkId] = {
              width:  width,
              height: height
            };
          }
        }
        // Completely remove the definition from the text
        return '';
      };
    
      // first we try to find base64 link references
      text = text.replace(base64Regex, replaceFunc);
    
      text = text.replace(regex, replaceFunc);
    
      // attacklab: strip sentinel
      text = text.replace(/¨0/, '');
    
      return text;
    });
    
    showdown.subParser('tables', function (text, options, globals) {
      'use strict';
    
      if (!options.tables) {
        return text;
      }
    
      var tableRgx       = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
          //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
          singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm;
    
      function parseStyles (sLine) {
        if (/^:[ \t]*--*$/.test(sLine)) {
          return ' style="text-align:left;"';
        } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
          return ' style="text-align:right;"';
        } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
          return ' style="text-align:center;"';
        } else {
          return '';
        }
      }
    
      function parseHeaders (header, style) {
        var id = '';
        header = header.trim();
        // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility
        if (options.tablesHeaderId || options.tableHeaderId) {
          id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
        }
        header = showdown.subParser('spanGamut')(header, options, globals);
    
        return '<th' + id + style + '>' + header + '</th>\n';
      }
    
      function parseCells (cell, style) {
        var subText = showdown.subParser('spanGamut')(cell, options, globals);
        return '<td' + style + '>' + subText + '</td>\n';
      }
    
      function buildTable (headers, cells) {
        var tb = '<table>\n<thead>\n<tr>\n',
            tblLgn = headers.length;
    
        for (var i = 0; i < tblLgn; ++i) {
          tb += headers[i];
        }
        tb += '</tr>\n</thead>\n<tbody>\n';
    
        for (i = 0; i < cells.length; ++i) {
          tb += '<tr>\n';
          for (var ii = 0; ii < tblLgn; ++ii) {
            tb += cells[i][ii];
          }
          tb += '</tr>\n';
        }
        tb += '</tbody>\n</table>\n';
        return tb;
      }
    
      function parseTable (rawTable) {
        var i, tableLines = rawTable.split('\n');
    
        for (i = 0; i < tableLines.length; ++i) {
          // strip wrong first and last column if wrapped tables are used
          if (/^ {0,3}\|/.test(tableLines[i])) {
            tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, '');
          }
          if (/\|[ \t]*$/.test(tableLines[i])) {
            tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
          }
          // parse code spans first, but we only support one line code spans
          tableLines[i] = showdown.subParser('codeSpans')(tableLines[i], options, globals);
        }
    
        var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
            rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
            rawCells = [],
            headers = [],
            styles = [],
            cells = [];
    
        tableLines.shift();
        tableLines.shift();
    
        for (i = 0; i < tableLines.length; ++i) {
          if (tableLines[i].trim() === '') {
            continue;
          }
          rawCells.push(
            tableLines[i]
              .split('|')
              .map(function (s) {
                return s.trim();
              })
          );
        }
    
        if (rawHeaders.length < rawStyles.length) {
          return rawTable;
        }
    
        for (i = 0; i < rawStyles.length; ++i) {
          styles.push(parseStyles(rawStyles[i]));
        }
    
        for (i = 0; i < rawHeaders.length; ++i) {
          if (showdown.helper.isUndefined(styles[i])) {
            styles[i] = '';
          }
          headers.push(parseHeaders(rawHeaders[i], styles[i]));
        }
    
        for (i = 0; i < rawCells.length; ++i) {
          var row = [];
          for (var ii = 0; ii < headers.length; ++ii) {
            if (showdown.helper.isUndefined(rawCells[i][ii])) {
    
            }
            row.push(parseCells(rawCells[i][ii], styles[ii]));
          }
          cells.push(row);
        }
    
        return buildTable(headers, cells);
      }
    
      text = globals.converter._dispatch('tables.before', text, options, globals);
    
      // find escaped pipe characters
      text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
    
      // parse multi column tables
      text = text.replace(tableRgx, parseTable);
    
      // parse one column tables
      text = text.replace(singeColTblRgx, parseTable);
    
      text = globals.converter._dispatch('tables.after', text, options, globals);
    
      return text;
    });
    
    showdown.subParser('underline', function (text, options, globals) {
      'use strict';
    
      if (!options.underline) {
        return text;
      }
    
      text = globals.converter._dispatch('underline.before', text, options, globals);
    
      if (options.literalMidWordUnderscores) {
        text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
          return '<u>' + txt + '</u>';
        });
        text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
          return '<u>' + txt + '</u>';
        });
      } else {
        text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
          return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
        });
        text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
          return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
        });
      }
    
      // escape remaining underscores to prevent them being parsed by italic and bold
      text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback);
    
      text = globals.converter._dispatch('underline.after', text, options, globals);
    
      return text;
    });
    
    /**
     * Swap back in all the special characters we've hidden.
     */
    showdown.subParser('unescapeSpecialChars', function (text, options, globals) {
      'use strict';
      text = globals.converter._dispatch('unescapeSpecialChars.before', text, options, globals);
    
      text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) {
        var charCodeToReplace = parseInt(m1);
        return String.fromCharCode(charCodeToReplace);
      });
    
      text = globals.converter._dispatch('unescapeSpecialChars.after', text, options, globals);
      return text;
    });
    
    showdown.subParser('makeMarkdown.blockquote', function (node, globals) {
      'use strict';
    
      var txt = '';
      if (node.hasChildNodes()) {
        var children = node.childNodes,
            childrenLength = children.length;
    
        for (var i = 0; i < childrenLength; ++i) {
          var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals);
    
          if (innerTxt === '') {
            continue;
          }
          txt += innerTxt;
        }
      }
      // cleanup
      txt = txt.trim();
      txt = '> ' + txt.split('\n').join('\n> ');
      return txt;
    });
    
    showdown.subParser('makeMarkdown.codeBlock', function (node, globals) {
      'use strict';
    
      var lang = node.getAttribute('language'),
          num  = node.getAttribute('precodenum');
      return '```' + lang + '\n' + globals.preList[num] + '\n```';
    });
    
    showdown.subParser('makeMarkdown.codeSpan', function (node) {
      'use strict';
    
      return '`' + node.innerHTML + '`';
    });
    
    showdown.subParser('makeMarkdown.emphasis', function (node, globals) {
      'use strict';
    
      var txt = '';
      if (node.hasChildNodes()) {
        txt += '*';
        var children = node.childNodes,
            childrenLength = children.length;
        for (var i = 0; i < childrenLength; ++i) {
          txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
        }
        txt += '*';
      }
      return txt;
    });
    
    showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) {
      'use strict';
    
      var headerMark = new Array(headerLevel + 1).join('#'),
          txt = '';
    
      if (node.hasChildNodes()) {
        txt = headerMark + ' ';
        var children = node.childNodes,
            childrenLength = children.length;
    
        for (var i = 0; i < childrenLength; ++i) {
          txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
        }
      }
      return txt;
    });
    
    showdown.subParser('makeMarkdown.hr', function () {
      'use strict';
    
      return '---';
    });
    
    showdown.subParser('makeMarkdown.image', function (node) {
      'use strict';
    
      var txt = '';
      if (node.hasAttribute('src')) {
        txt += '![' + node.getAttribute('alt') + '](';
        txt += '<' + node.getAttribute('src') + '>';
        if (node.hasAttribute('width') && node.hasAttribute('height')) {
          txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
        }
    
        if (node.hasAttribute('title')) {
          txt += ' "' + node.getAttribute('title') + '"';
        }
        txt += ')';
      }
      return txt;
    });
    
    showdown.subParser('makeMarkdown.links', function (node, globals) {
      'use strict';
    
      var txt = '';
      if (node.hasChildNodes() && node.hasAttribute('href')) {
        var children = node.childNodes,
            childrenLength = children.length;
        txt = '[';
        for (var i = 0; i < childrenLength; ++i) {
          txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
        }
        txt += '](';
        txt += '<' + node.getAttribute('href') + '>';
        if (node.hasAttribute('title')) {
          txt += ' "' + node.getAttribute('title') + '"';
        }
        txt += ')';
      }
      return txt;
    });
    
    showdown.subParser('makeMarkdown.list', function (node, globals, type) {
      'use strict';
    
      var txt = '';
      if (!node.hasChildNodes()) {
        return '';
      }
      var listItems       = node.childNodes,
          listItemsLenght = listItems.length,
          listNum = node.getAttribute('start') || 1;
    
      for (var i = 0; i < listItemsLenght; ++i) {
        if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
          continue;
        }
    
        // define the bullet to use in list
        var bullet = '';
        if (type === 'ol') {
          bullet = listNum.toString() + '. ';
        } else {
          bullet = '- ';
        }
    
        // parse list item
        txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals);
        ++listNum;
      }
    
      // add comment at the end to prevent consecutive lists to be parsed as one
      txt += '\n<!-- -->\n';
      return txt.trim();
    });
    
    showdown.subParser('makeMarkdown.listItem', function (node, globals) {
      'use strict';
    
      var listItemTxt = '';
    
      var children = node.childNodes,
          childrenLenght = children.length;
    
      for (var i = 0; i < childrenLenght; ++i) {
        listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals);
      }
      // if it's only one liner, we need to add a newline at the end
      if (!/\n$/.test(listItemTxt)) {
        listItemTxt += '\n';
      } else {
        // it's multiparagraph, so we need to indent
        listItemTxt = listItemTxt
          .split('\n')
          .join('\n    ')
          .replace(/^ {4}$/gm, '')
          .replace(/\n\n+/g, '\n\n');
      }
    
      return listItemTxt;
    });
    
    
    
    showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) {
      'use strict';
    
      spansOnly = spansOnly || false;
    
      var txt = '';
    
      // edge case of text without wrapper paragraph
      if (node.nodeType === 3) {
        return showdown.subParser('makeMarkdown.txt')(node, globals);
      }
    
      // HTML comment
      if (node.nodeType === 8) {
        return '<!--' + node.data + '-->\n\n';
      }
    
      // process only node elements
      if (node.nodeType !== 1) {
        return '';
      }
    
      var tagName = node.tagName.toLowerCase();
    
      switch (tagName) {
    
        //
        // BLOCKS
        //
        case 'h1':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; }
          break;
        case 'h2':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; }
          break;
        case 'h3':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; }
          break;
        case 'h4':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; }
          break;
        case 'h5':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; }
          break;
        case 'h6':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; }
          break;
    
        case 'p':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; }
          break;
    
        case 'blockquote':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; }
          break;
    
        case 'hr':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; }
          break;
    
        case 'ol':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; }
          break;
    
        case 'ul':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; }
          break;
    
        case 'precode':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; }
          break;
    
        case 'pre':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; }
          break;
    
        case 'table':
          if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; }
          break;
    
        //
        // SPANS
        //
        case 'code':
          txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals);
          break;
    
        case 'em':
        case 'i':
          txt = showdown.subParser('makeMarkdown.emphasis')(node, globals);
          break;
    
        case 'strong':
        case 'b':
          txt = showdown.subParser('makeMarkdown.strong')(node, globals);
          break;
    
        case 'del':
          txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals);
          break;
    
        case 'a':
          txt = showdown.subParser('makeMarkdown.links')(node, globals);
          break;
    
        case 'img':
          txt = showdown.subParser('makeMarkdown.image')(node, globals);
          break;
    
        default:
          txt = node.outerHTML + '\n\n';
      }
    
      // common normalization
      // TODO eventually
    
      return txt;
    });
    
    showdown.subParser('makeMarkdown.paragraph', function (node, globals) {
      'use strict';
    
      var txt = '';
      if (node.hasChildNodes()) {
        var children = node.childNodes,
            childrenLength = children.length;
        for (var i = 0; i < childrenLength; ++i) {
          txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
        }
      }
    
      // some text normalization
      txt = txt.trim();
    
      return txt;
    });
    
    showdown.subParser('makeMarkdown.pre', function (node, globals) {
      'use strict';
    
      var num  = node.getAttribute('prenum');
      return '<pre>' + globals.preList[num] + '</pre>';
    });
    
    showdown.subParser('makeMarkdown.strikethrough', function (node, globals) {
      'use strict';
    
      var txt = '';
      if (node.hasChildNodes()) {
        txt += '~~';
        var children = node.childNodes,
            childrenLength = children.length;
        for (var i = 0; i < childrenLength; ++i) {
          txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
        }
        txt += '~~';
      }
      return txt;
    });
    
    showdown.subParser('makeMarkdown.strong', function (node, globals) {
      'use strict';
    
      var txt = '';
      if (node.hasChildNodes()) {
        txt += '**';
        var children = node.childNodes,
            childrenLength = children.length;
        for (var i = 0; i < childrenLength; ++i) {
          txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
        }
        txt += '**';
      }
      return txt;
    });
    
    showdown.subParser('makeMarkdown.table', function (node, globals) {
      'use strict';
    
      var txt = '',
          tableArray = [[], []],
          headings   = node.querySelectorAll('thead>tr>th'),
          rows       = node.querySelectorAll('tbody>tr'),
          i, ii;
      for (i = 0; i < headings.length; ++i) {
        var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals),
            allign = '---';
    
        if (headings[i].hasAttribute('style')) {
          var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
          switch (style) {
            case 'text-align:left;':
              allign = ':---';
              break;
            case 'text-align:right;':
              allign = '---:';
              break;
            case 'text-align:center;':
              allign = ':---:';
              break;
          }
        }
        tableArray[0][i] = headContent.trim();
        tableArray[1][i] = allign;
      }
    
      for (i = 0; i < rows.length; ++i) {
        var r = tableArray.push([]) - 1,
            cols = rows[i].getElementsByTagName('td');
    
        for (ii = 0; ii < headings.length; ++ii) {
          var cellContent = ' ';
          if (typeof cols[ii] !== 'undefined') {
            cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals);
          }
          tableArray[r].push(cellContent);
        }
      }
    
      var cellSpacesCount = 3;
      for (i = 0; i < tableArray.length; ++i) {
        for (ii = 0; ii < tableArray[i].length; ++ii) {
          var strLen = tableArray[i][ii].length;
          if (strLen > cellSpacesCount) {
            cellSpacesCount = strLen;
          }
        }
      }
    
      for (i = 0; i < tableArray.length; ++i) {
        for (ii = 0; ii < tableArray[i].length; ++ii) {
          if (i === 1) {
            if (tableArray[i][ii].slice(-1) === ':') {
              tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
            } else {
              tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
            }
          } else {
            tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
          }
        }
        txt += '| ' + tableArray[i].join(' | ') + ' |\n';
      }
    
      return txt.trim();
    });
    
    showdown.subParser('makeMarkdown.tableCell', function (node, globals) {
      'use strict';
    
      var txt = '';
      if (!node.hasChildNodes()) {
        return '';
      }
      var children = node.childNodes,
          childrenLength = children.length;
    
      for (var i = 0; i < childrenLength; ++i) {
        txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true);
      }
      return txt.trim();
    });
    
    showdown.subParser('makeMarkdown.txt', function (node) {
      'use strict';
    
      var txt = node.nodeValue;
    
      // multiple spaces are collapsed
      txt = txt.replace(/ +/g, ' ');
    
      // replace the custom ¨NBSP; with a space
      txt = txt.replace(/¨NBSP;/g, ' ');
    
      // ", <, > and & should replace escaped html entities
      txt = showdown.helper.unescapeHTMLEntities(txt);
    
      // escape markdown magic characters
      // emphasis, strong and strikethrough - can appear everywhere
      // we also escape pipe (|) because of tables
      // and escape ` because of code blocks and spans
      txt = txt.replace(/([*_~|`])/g, '\\$1');
    
      // escape > because of blockquotes
      txt = txt.replace(/^(\s*)>/g, '\\$1>');
    
      // hash character, only troublesome at the beginning of a line because of headers
      txt = txt.replace(/^#/gm, '\\#');
    
      // horizontal rules
      txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
    
      // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
      txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
    
      // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
      txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
    
      // images and links, ] followed by ( is problematic, so we escape it
      txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
    
      // reference URIs must also be escaped
      txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
    
      return txt;
    });
    
    var root = this;
    
    // AMD Loader
    if (typeof define === 'function' && define.amd) {
      define(function () {
        'use strict';
        return showdown;
      });
    
    // CommonJS/nodeJS Loader
    } else if (typeof module !== 'undefined' && module.exports) {
      module.exports = showdown;
    
    // Regular Browser loader
    } else {
      root.showdown = showdown;
    }
    }).call(this);
    
    //# sourceMappingURL=showdown.js.map
    
    // Released under MIT license
    // Copyright (c) 2009-2010 Dominic Baggott
    // Copyright (c) 2009-2010 Ash Berlin
    // Copyright (c) 2011 Christoph Dorn <christoph@christophdorn.com> (http://www.christophdorn.com)
    
    /*jshint browser:true, devel:true */
    
    (function( expose ) {
    
    /**
     *  class Markdown
     *
     *  Markdown processing in Javascript done right. We have very particular views
     *  on what constitutes 'right' which include:
     *
     *  - produces well-formed HTML (this means that em and strong nesting is
     *    important)
     *
     *  - has an intermediate representation to allow processing of parsed data (We
     *    in fact have two, both as [JsonML]: a markdown tree and an HTML tree).
     *
     *  - is easily extensible to add new dialects without having to rewrite the
     *    entire parsing mechanics
     *
     *  - has a good test suite
     *
     *  This implementation fulfills all of these (except that the test suite could
     *  do with expanding to automatically run all the fixtures from other Markdown
     *  implementations.)
     *
     *  ##### Intermediate Representation
     *
     *  *TODO* Talk about this :) Its JsonML, but document the node names we use.
     *
     *  [JsonML]: http://jsonml.org/ "JSON Markup Language"
     **/
    var Markdown = expose.Markdown = function(dialect) {
      switch (typeof dialect) {
        case "undefined":
          this.dialect = Markdown.dialects.Gruber;
          break;
        case "object":
          this.dialect = dialect;
          break;
        default:
          if ( dialect in Markdown.dialects ) {
            this.dialect = Markdown.dialects[dialect];
          }
          else {
            throw new Error("Unknown Markdown dialect '" + String(dialect) + "'");
          }
          break;
      }
      this.em_state = [];
      this.strong_state = [];
      this.debug_indent = "";
    };
    
    /**
     *  parse( markdown, [dialect] ) -> JsonML
     *  - markdown (String): markdown string to parse
     *  - dialect (String | Dialect): the dialect to use, defaults to gruber
     *
     *  Parse `markdown` and return a markdown document as a Markdown.JsonML tree.
     **/
    expose.parse = function( source, dialect ) {
      // dialect will default if undefined
      var md = new Markdown( dialect );
      return md.toTree( source );
    };
    
    /**
     *  toHTML( markdown, [dialect]  ) -> String
     *  toHTML( md_tree ) -> String
     *  - markdown (String): markdown string to parse
     *  - md_tree (Markdown.JsonML): parsed markdown tree
     *
     *  Take markdown (either as a string or as a JsonML tree) and run it through
     *  [[toHTMLTree]] then turn it into a well-formated HTML fragment.
     **/
    expose.toHTML = function toHTML( source , dialect , options ) {
      var input = expose.toHTMLTree( source , dialect , options );
    
      return expose.renderJsonML( input );
    };
    
    /**
     *  toHTMLTree( markdown, [dialect] ) -> JsonML
     *  toHTMLTree( md_tree ) -> JsonML
     *  - markdown (String): markdown string to parse
     *  - dialect (String | Dialect): the dialect to use, defaults to gruber
     *  - md_tree (Markdown.JsonML): parsed markdown tree
     *
     *  Turn markdown into HTML, represented as a JsonML tree. If a string is given
     *  to this function, it is first parsed into a markdown tree by calling
     *  [[parse]].
     **/
    expose.toHTMLTree = function toHTMLTree( input, dialect , options ) {
      // convert string input to an MD tree
      if ( typeof input ==="string" ) input = this.parse( input, dialect );
    
      // Now convert the MD tree to an HTML tree
    
      // remove references from the tree
      var attrs = extract_attr( input ),
          refs = {};
    
      if ( attrs && attrs.references ) {
        refs = attrs.references;
      }
    
      var html = convert_tree_to_html( input, refs , options );
      merge_text_nodes( html );
      return html;
    };
    
    // For Spidermonkey based engines
    function mk_block_toSource() {
      return "Markdown.mk_block( " +
              uneval(this.toString()) +
              ", " +
              uneval(this.trailing) +
              ", " +
              uneval(this.lineNumber) +
              " )";
    }
    
    // node
    function mk_block_inspect() {
      var util = require("util");
      return "Markdown.mk_block( " +
              util.inspect(this.toString()) +
              ", " +
              util.inspect(this.trailing) +
              ", " +
              util.inspect(this.lineNumber) +
              " )";
    
    }
    
    var mk_block = Markdown.mk_block = function(block, trail, line) {
      // Be helpful for default case in tests.
      if ( arguments.length == 1 ) trail = "\n\n";
    
      var s = new String(block);
      s.trailing = trail;
      // To make it clear its not just a string
      s.inspect = mk_block_inspect;
      s.toSource = mk_block_toSource;
    
      if ( line != undefined )
        s.lineNumber = line;
    
      return s;
    };
    
    function count_lines( str ) {
      var n = 0, i = -1;
      while ( ( i = str.indexOf("\n", i + 1) ) !== -1 ) n++;
      return n;
    }
    
    // Internal - split source into rough blocks
    Markdown.prototype.split_blocks = function splitBlocks( input, startLine ) {
      input = input.replace(/(\r\n|\n|\r)/g, "\n");
      // [\s\S] matches _anything_ (newline or space)
      // [^] is equivalent but doesn't work in IEs.
      var re = /([\s\S]+?)($|\n#|\n(?:\s*\n|$)+)/g,
          blocks = [],
          m;
    
      var line_no = 1;
    
      if ( ( m = /^(\s*\n)/.exec(input) ) != null ) {
        // skip (but count) leading blank lines
        line_no += count_lines( m[0] );
        re.lastIndex = m[0].length;
      }
    
      while ( ( m = re.exec(input) ) !== null ) {
        if (m[2] == "\n#") {
          m[2] = "\n";
          re.lastIndex--;
        }
        blocks.push( mk_block( m[1], m[2], line_no ) );
        line_no += count_lines( m[0] );
      }
    
      return blocks;
    };
    
    /**
     *  Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ]
     *  - block (String): the block to process
     *  - next (Array): the following blocks
     *
     * Process `block` and return an array of JsonML nodes representing `block`.
     *
     * It does this by asking each block level function in the dialect to process
     * the block until one can. Succesful handling is indicated by returning an
     * array (with zero or more JsonML nodes), failure by a false value.
     *
     * Blocks handlers are responsible for calling [[Markdown#processInline]]
     * themselves as appropriate.
     *
     * If the blocks were split incorrectly or adjacent blocks need collapsing you
     * can adjust `next` in place using shift/splice etc.
     *
     * If any of this default behaviour is not right for the dialect, you can
     * define a `__call__` method on the dialect that will get invoked to handle
     * the block processing.
     */
    Markdown.prototype.processBlock = function processBlock( block, next ) {
      var cbs = this.dialect.block,
          ord = cbs.__order__;
    
      if ( "__call__" in cbs ) {
        return cbs.__call__.call(this, block, next);
      }
    
      for ( var i = 0; i < ord.length; i++ ) {
        //D:this.debug( "Testing", ord[i] );
        var res = cbs[ ord[i] ].call( this, block, next );
        if ( res ) {
          //D:this.debug("  matched");
          if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) ) )
            this.debug(ord[i], "didn't return a proper array");
          //D:this.debug( "" );
          return res;
        }
      }
    
      // Uhoh! no match! Should we throw an error?
      return [];
    };
    
    Markdown.prototype.processInline = function processInline( block ) {
      return this.dialect.inline.__call__.call( this, String( block ) );
    };
    
    /**
     *  Markdown#toTree( source ) -> JsonML
     *  - source (String): markdown source to parse
     *
     *  Parse `source` into a JsonML tree representing the markdown document.
     **/
    // custom_tree means set this.tree to `custom_tree` and restore old value on return
    Markdown.prototype.toTree = function toTree( source, custom_root ) {
      var blocks = source instanceof Array ? source : this.split_blocks( source );
    
      // Make tree a member variable so its easier to mess with in extensions
      var old_tree = this.tree;
      try {
        this.tree = custom_root || this.tree || [ "markdown" ];
    
        blocks:
        while ( blocks.length ) {
          var b = this.processBlock( blocks.shift(), blocks );
    
          // Reference blocks and the like won't return any content
          if ( !b.length ) continue blocks;
    
          this.tree.push.apply( this.tree, b );
        }
        return this.tree;
      }
      finally {
        if ( custom_root ) {
          this.tree = old_tree;
        }
      }
    };
    
    // Noop by default
    Markdown.prototype.debug = function () {
      var args = Array.prototype.slice.call( arguments);
      args.unshift(this.debug_indent);
      if ( typeof print !== "undefined" )
          print.apply( print, args );
      if ( typeof console !== "undefined" && typeof console.log !== "undefined" )
          console.log.apply( null, args );
    }
    
    Markdown.prototype.loop_re_over_block = function( re, block, cb ) {
      // Dont use /g regexps with this
      var m,
          b = block.valueOf();
    
      while ( b.length && (m = re.exec(b) ) != null ) {
        b = b.substr( m[0].length );
        cb.call(this, m);
      }
      return b;
    };
    
    /**
     * Markdown.dialects
     *
     * Namespace of built-in dialects.
     **/
    Markdown.dialects = {};
    
    /**
     * Markdown.dialects.Gruber
     *
     * The default dialect that follows the rules set out by John Gruber's
     * markdown.pl as closely as possible. Well actually we follow the behaviour of
     * that script which in some places is not exactly what the syntax web page
     * says.
     **/
    Markdown.dialects.Gruber = {
      block: {
        atxHeader: function atxHeader( block, next ) {
          var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ );
    
          if ( !m ) return undefined;
    
          var header = [ "header", { level: m[ 1 ].length } ];
          Array.prototype.push.apply(header, this.processInline(m[ 2 ]));
    
          if ( m[0].length < block.length )
            next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
    
          return [ header ];
        },
    
        setextHeader: function setextHeader( block, next ) {
          var m = block.match( /^(.*)\n([-=])\2\2+(?:\n|$)/ );
    
          if ( !m ) return undefined;
    
          var level = ( m[ 2 ] === "=" ) ? 1 : 2;
          var header = [ "header", { level : level }, m[ 1 ] ];
    
          if ( m[0].length < block.length )
            next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
    
          return [ header ];
        },
    
        code: function code( block, next ) {
          // |    Foo
          // |bar
          // should be a code block followed by a paragraph. Fun
          //
          // There might also be adjacent code block to merge.
    
          var ret = [],
              re = /^(?: {0,3}\t| {4})(.*)\n?/,
              lines;
    
          // 4 spaces + content
          if ( !block.match( re ) ) return undefined;
    
          block_search:
          do {
            // Now pull out the rest of the lines
            var b = this.loop_re_over_block(
                      re, block.valueOf(), function( m ) { ret.push( m[1] ); } );
    
            if ( b.length ) {
              // Case alluded to in first comment. push it back on as a new block
              next.unshift( mk_block(b, block.trailing) );
              break block_search;
            }
            else if ( next.length ) {
              // Check the next block - it might be code too
              if ( !next[0].match( re ) ) break block_search;
    
              // Pull how how many blanks lines follow - minus two to account for .join
              ret.push ( block.trailing.replace(/[^\n]/g, "").substring(2) );
    
              block = next.shift();
            }
            else {
              break block_search;
            }
          } while ( true );
    
          return [ [ "code_block", ret.join("\n") ] ];
        },
    
        horizRule: function horizRule( block, next ) {
          // this needs to find any hr in the block to handle abutting blocks
          var m = block.match( /^(?:([\s\S]*?)\n)?[ \t]*([-_*])(?:[ \t]*\2){2,}[ \t]*(?:\n([\s\S]*))?$/ );
    
          if ( !m ) {
            return undefined;
          }
    
          var jsonml = [ [ "hr" ] ];
    
          // if there's a leading abutting block, process it
          if ( m[ 1 ] ) {
            jsonml.unshift.apply( jsonml, this.processBlock( m[ 1 ], [] ) );
          }
    
          // if there's a trailing abutting block, stick it into next
          if ( m[ 3 ] ) {
            next.unshift( mk_block( m[ 3 ] ) );
          }
    
          return jsonml;
        },
    
        // There are two types of lists. Tight and loose. Tight lists have no whitespace
        // between the items (and result in text just in the <li>) and loose lists,
        // which have an empty line between list items, resulting in (one or more)
        // paragraphs inside the <li>.
        //
        // There are all sorts weird edge cases about the original markdown.pl's
        // handling of lists:
        //
        // * Nested lists are supposed to be indented by four chars per level. But
        //   if they aren't, you can get a nested list by indenting by less than
        //   four so long as the indent doesn't match an indent of an existing list
        //   item in the 'nest stack'.
        //
        // * The type of the list (bullet or number) is controlled just by the
        //    first item at the indent. Subsequent changes are ignored unless they
        //    are for nested lists
        //
        lists: (function( ) {
          // Use a closure to hide a few variables.
          var any_list = "[*+-]|\\d+\\.",
              bullet_list = /[*+-]/,
              number_list = /\d+\./,
              // Capture leading indent as it matters for determining nested lists.
              is_list_re = new RegExp( "^( {0,3})(" + any_list + ")[ \t]+" ),
              indent_re = "(?: {0,3}\\t| {4})";
    
          // TODO: Cache this regexp for certain depths.
          // Create a regexp suitable for matching an li for a given stack depth
          function regex_for_depth( depth ) {
    
            return new RegExp(
              // m[1] = indent, m[2] = list_type
              "(?:^(" + indent_re + "{0," + depth + "} {0,3})(" + any_list + ")\\s+)|" +
              // m[3] = cont
              "(^" + indent_re + "{0," + (depth-1) + "}[ ]{0,4})"
            );
          }
          function expand_tab( input ) {
            return input.replace( / {0,3}\t/g, "    " );
          }
    
          // Add inline content `inline` to `li`. inline comes from processInline
          // so is an array of content
          function add(li, loose, inline, nl) {
            if ( loose ) {
              li.push( [ "para" ].concat(inline) );
              return;
            }
            // Hmmm, should this be any block level element or just paras?
            var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] == "para"
                       ? li[li.length -1]
                       : li;
    
            // If there is already some content in this list, add the new line in
            if ( nl && li.length > 1 ) inline.unshift(nl);
    
            for ( var i = 0; i < inline.length; i++ ) {
              var what = inline[i],
                  is_str = typeof what == "string";
              if ( is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == "string" ) {
                add_to[ add_to.length-1 ] += what;
              }
              else {
                add_to.push( what );
              }
            }
          }
    
          // contained means have an indent greater than the current one. On
          // *every* line in the block
          function get_contained_blocks( depth, blocks ) {
    
            var re = new RegExp( "^(" + indent_re + "{" + depth + "}.*?\\n?)*$" ),
                replace = new RegExp("^" + indent_re + "{" + depth + "}", "gm"),
                ret = [];
    
            while ( blocks.length > 0 ) {
              if ( re.exec( blocks[0] ) ) {
                var b = blocks.shift(),
                    // Now remove that indent
                    x = b.replace( replace, "");
    
                ret.push( mk_block( x, b.trailing, b.lineNumber ) );
              }
              else {
                break;
              }
            }
            return ret;
          }
    
          // passed to stack.forEach to turn list items up the stack into paras
          function paragraphify(s, i, stack) {
            var list = s.list;
            var last_li = list[list.length-1];
    
            if ( last_li[1] instanceof Array && last_li[1][0] == "para" ) {
              return;
            }
            if ( i + 1 == stack.length ) {
              // Last stack frame
              // Keep the same array, but replace the contents
              last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ) );
            }
            else {
              var sublist = last_li.pop();
              last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ), sublist );
            }
          }
    
          // The matcher function
          return function( block, next ) {
            var m = block.match( is_list_re );
            if ( !m ) return undefined;
    
            function make_list( m ) {
              var list = bullet_list.exec( m[2] )
                       ? ["bulletlist"]
                       : ["numberlist"];
    
              stack.push( { list: list, indent: m[1] } );
              return list;
            }
    
    
            var stack = [], // Stack of lists for nesting.
                list = make_list( m ),
                last_li,
                loose = false,
                ret = [ stack[0].list ],
                i;
    
            // Loop to search over block looking for inner block elements and loose lists
            loose_search:
            while ( true ) {
              // Split into lines preserving new lines at end of line
              var lines = block.split( /(?=\n)/ );
    
              // We have to grab all lines for a li and call processInline on them
              // once as there are some inline things that can span lines.
              var li_accumulate = "";
    
              // Loop over the lines in this block looking for tight lists.
              tight_search:
              for ( var line_no = 0; line_no < lines.length; line_no++ ) {
                var nl = "",
                    l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; });
    
                // TODO: really should cache this
                var line_re = regex_for_depth( stack.length );
    
                m = l.match( line_re );
                //print( "line:", uneval(l), "\nline match:", uneval(m) );
    
                // We have a list item
                if ( m[1] !== undefined ) {
                  // Process the previous list item, if any
                  if ( li_accumulate.length ) {
                    add( last_li, loose, this.processInline( li_accumulate ), nl );
                    // Loose mode will have been dealt with. Reset it
                    loose = false;
                    li_accumulate = "";
                  }
    
                  m[1] = expand_tab( m[1] );
                  var wanted_depth = Math.floor(m[1].length/4)+1;
                  //print( "want:", wanted_depth, "stack:", stack.length);
                  if ( wanted_depth > stack.length ) {
                    // Deep enough for a nested list outright
                    //print ( "new nested list" );
                    list = make_list( m );
                    last_li.push( list );
                    last_li = list[1] = [ "listitem" ];
                  }
                  else {
                    // We aren't deep enough to be strictly a new level. This is
                    // where Md.pl goes nuts. If the indent matches a level in the
                    // stack, put it there, else put it one deeper then the
                    // wanted_depth deserves.
                    var found = false;
                    for ( i = 0; i < stack.length; i++ ) {
                      if ( stack[ i ].indent != m[1] ) continue;
                      list = stack[ i ].list;
                      stack.splice( i+1, stack.length - (i+1) );
                      found = true;
                      break;
                    }
    
                    if (!found) {
                      //print("not found. l:", uneval(l));
                      wanted_depth++;
                      if ( wanted_depth <= stack.length ) {
                        stack.splice(wanted_depth, stack.length - wanted_depth);
                        //print("Desired depth now", wanted_depth, "stack:", stack.length);
                        list = stack[wanted_depth-1].list;
                        //print("list:", uneval(list) );
                      }
                      else {
                        //print ("made new stack for messy indent");
                        list = make_list(m);
                        last_li.push(list);
                      }
                    }
    
                    //print( uneval(list), "last", list === stack[stack.length-1].list );
                    last_li = [ "listitem" ];
                    list.push(last_li);
                  } // end depth of shenegains
                  nl = "";
                }
    
                // Add content
                if ( l.length > m[0].length ) {
                  li_accumulate += nl + l.substr( m[0].length );
                }
              } // tight_search
    
              if ( li_accumulate.length ) {
                add( last_li, loose, this.processInline( li_accumulate ), nl );
                // Loose mode will have been dealt with. Reset it
                loose = false;
                li_accumulate = "";
              }
    
              // Look at the next block - we might have a loose list. Or an extra
              // paragraph for the current li
              var contained = get_contained_blocks( stack.length, next );
    
              // Deal with code blocks or properly nested lists
              if ( contained.length > 0 ) {
                // Make sure all listitems up the stack are paragraphs
                forEach( stack, paragraphify, this);
    
                last_li.push.apply( last_li, this.toTree( contained, [] ) );
              }
    
              var next_block = next[0] && next[0].valueOf() || "";
    
              if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) {
                block = next.shift();
    
                // Check for an HR following a list: features/lists/hr_abutting
                var hr = this.dialect.block.horizRule( block, next );
    
                if ( hr ) {
                  ret.push.apply(ret, hr);
                  break;
                }
    
                // Make sure all listitems up the stack are paragraphs
                forEach( stack, paragraphify, this);
    
                loose = true;
                continue loose_search;
              }
              break;
            } // loose_search
    
            return ret;
          };
        })(),
    
        blockquote: function blockquote( block, next ) {
          if ( !block.match( /^>/m ) )
            return undefined;
    
          var jsonml = [];
    
          // separate out the leading abutting block, if any. I.e. in this case:
          //
          //  a
          //  > b
          //
          if ( block[ 0 ] != ">" ) {
            var lines = block.split( /\n/ ),
                prev = [],
                line_no = block.lineNumber;
    
            // keep shifting lines until you find a crotchet
            while ( lines.length && lines[ 0 ][ 0 ] != ">" ) {
                prev.push( lines.shift() );
                line_no++;
            }
    
            var abutting = mk_block( prev.join( "\n" ), "\n", block.lineNumber );
            jsonml.push.apply( jsonml, this.processBlock( abutting, [] ) );
            // reassemble new block of just block quotes!
            block = mk_block( lines.join( "\n" ), block.trailing, line_no );
          }
    
    
          // if the next block is also a blockquote merge it in
          while ( next.length && next[ 0 ][ 0 ] == ">" ) {
            var b = next.shift();
            block = mk_block( block + block.trailing + b, b.trailing, block.lineNumber );
          }
    
          // Strip off the leading "> " and re-process as a block.
          var input = block.replace( /^> ?/gm, "" ),
              old_tree = this.tree,
              processedBlock = this.toTree( input, [ "blockquote" ] ),
              attr = extract_attr( processedBlock );
    
          // If any link references were found get rid of them
          if ( attr && attr.references ) {
            delete attr.references;
            // And then remove the attribute object if it's empty
            if ( isEmpty( attr ) ) {
              processedBlock.splice( 1, 1 );
            }
          }
    
          jsonml.push( processedBlock );
          return jsonml;
        },
    
        referenceDefn: function referenceDefn( block, next) {
          var re = /^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;
          // interesting matches are [ , ref_id, url, , title, title ]
    
          if ( !block.match(re) )
            return undefined;
    
          // make an attribute node if it doesn't exist
          if ( !extract_attr( this.tree ) ) {
            this.tree.splice( 1, 0, {} );
          }
    
          var attrs = extract_attr( this.tree );
    
          // make a references hash if it doesn't exist
          if ( attrs.references === undefined ) {
            attrs.references = {};
          }
    
          var b = this.loop_re_over_block(re, block, function( m ) {
    
            if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
              m[2] = m[2].substring( 1, m[2].length - 1 );
    
            var ref = attrs.references[ m[1].toLowerCase() ] = {
              href: m[2]
            };
    
            if ( m[4] !== undefined )
              ref.title = m[4];
            else if ( m[5] !== undefined )
              ref.title = m[5];
    
          } );
    
          if ( b.length )
            next.unshift( mk_block( b, block.trailing ) );
    
          return [];
        },
    
        para: function para( block, next ) {
          // everything's a para!
          return [ ["para"].concat( this.processInline( block ) ) ];
        }
      }
    };
    
    Markdown.dialects.Gruber.inline = {
    
        __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {
          var m,
              res,
              lastIndex = 0;
    
          patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__;
          var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" );
    
          m = re.exec( text );
          if (!m) {
            // Just boring text
            return [ text.length, text ];
          }
          else if ( m[1] ) {
            // Some un-interesting text matched. Return that first
            return [ m[1].length, m[1] ];
          }
    
          var res;
          if ( m[2] in this.dialect.inline ) {
            res = this.dialect.inline[ m[2] ].call(
                      this,
                      text.substr( m.index ), m, previous_nodes || [] );
          }
          // Default for now to make dev easier. just slurp special and output it.
          res = res || [ m[2].length, m[2] ];
          return res;
        },
    
        __call__: function inline( text, patterns ) {
    
          var out = [],
              res;
    
          function add(x) {
            //D:self.debug("  adding output", uneval(x));
            if ( typeof x == "string" && typeof out[out.length-1] == "string" )
              out[ out.length-1 ] += x;
            else
              out.push(x);
          }
    
          while ( text.length > 0 ) {
            res = this.dialect.inline.__oneElement__.call(this, text, patterns, out );
            text = text.substr( res.shift() );
            forEach(res, add )
          }
    
          return out;
        },
    
        // These characters are intersting elsewhere, so have rules for them so that
        // chunks of plain text blocks don't include them
        "]": function () {},
        "}": function () {},
    
        __escape__ : /^\\[\\`\*_{}\[\]()#\+.!\-]/,
    
        "\\": function escaped( text ) {
          // [ length of input processed, node/children to add... ]
          // Only esacape: \ ` * _ { } [ ] ( ) # * + - . !
          if ( this.dialect.inline.__escape__.exec( text ) )
            return [ 2, text.charAt( 1 ) ];
          else
            // Not an esacpe
            return [ 1, "\\" ];
        },
    
        "![": function image( text ) {
    
          // Unlike images, alt text is plain text only. no other elements are
          // allowed in there
    
          // ![Alt text](/path/to/img.jpg "Optional title")
          //      1          2            3       4         <--- captures
          var m = text.match( /^!\[(.*?)\][ \t]*\([ \t]*([^")]*?)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ );
    
          if ( m ) {
            if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
              m[2] = m[2].substring( 1, m[2].length - 1 );
    
            m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0];
    
            var attrs = { alt: m[1], href: m[2] || "" };
            if ( m[4] !== undefined)
              attrs.title = m[4];
    
            return [ m[0].length, [ "img", attrs ] ];
          }
    
          // ![Alt text][id]
          m = text.match( /^!\[(.*?)\][ \t]*\[(.*?)\]/ );
    
          if ( m ) {
            // We can't check if the reference is known here as it likely wont be
            // found till after. Check it in md tree->hmtl tree conversion
            return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ];
          }
    
          // Just consume the '!['
          return [ 2, "![" ];
        },
    
        "[": function link( text ) {
    
          var orig = String(text);
          // Inline content is possible inside `link text`
          var res = Markdown.DialectHelpers.inline_until_char.call( this, text.substr(1), "]" );
    
          // No closing ']' found. Just consume the [
          if ( !res ) return [ 1, "[" ];
    
          var consumed = 1 + res[ 0 ],
              children = res[ 1 ],
              link,
              attrs;
    
          // At this point the first [...] has been parsed. See what follows to find
          // out which kind of link we are (reference or direct url)
          text = text.substr( consumed );
    
          // [link text](/path/to/img.jpg "Optional title")
          //                 1            2       3         <--- captures
          // This will capture up to the last paren in the block. We then pull
          // back based on if there a matching ones in the url
          //    ([here](/url/(test))
          // The parens have to be balanced
          var m = text.match( /^\s*\([ \t]*([^"']*)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ );
          if ( m ) {
            var url = m[1];
            consumed += m[0].length;
    
            if ( url && url[0] == "<" && url[url.length-1] == ">" )
              url = url.substring( 1, url.length - 1 );
    
            // If there is a title we don't have to worry about parens in the url
            if ( !m[3] ) {
              var open_parens = 1; // One open that isn't in the capture
              for ( var len = 0; len < url.length; len++ ) {
                switch ( url[len] ) {
                case "(":
                  open_parens++;
                  break;
                case ")":
                  if ( --open_parens == 0) {
                    consumed -= url.length - len;
                    url = url.substring(0, len);
                  }
                  break;
                }
              }
            }
    
            // Process escapes only
            url = this.dialect.inline.__call__.call( this, url, /\\/ )[0];
    
            attrs = { href: url || "" };
            if ( m[3] !== undefined)
              attrs.title = m[3];
    
            link = [ "link", attrs ].concat( children );
            return [ consumed, link ];
          }
    
          // [Alt text][id]
          // [Alt text] [id]
          m = text.match( /^\s*\[(.*?)\]/ );
    
          if ( m ) {
    
            consumed += m[ 0 ].length;
    
            // [links][] uses links as its reference
            attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(),  original: orig.substr( 0, consumed ) };
    
            link = [ "link_ref", attrs ].concat( children );
    
            // We can't check if the reference is known here as it likely wont be
            // found till after. Check it in md tree->hmtl tree conversion.
            // Store the original so that conversion can revert if the ref isn't found.
            return [ consumed, link ];
          }
    
          // [id]
          // Only if id is plain (no formatting.)
          if ( children.length == 1 && typeof children[0] == "string" ) {
    
            attrs = { ref: children[0].toLowerCase(),  original: orig.substr( 0, consumed ) };
            link = [ "link_ref", attrs, children[0] ];
            return [ consumed, link ];
          }
    
          // Just consume the "["
          return [ 1, "[" ];
        },
    
    
        "<": function autoLink( text ) {
          var m;
    
          if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\.[a-zA-Z]+))>/ ) ) != null ) {
            if ( m[3] ) {
              return [ m[0].length, [ "link", { href: "mailto:" + m[3] }, m[3] ] ];
    
            }
            else if ( m[2] == "mailto" ) {
              return [ m[0].length, [ "link", { href: m[1] }, m[1].substr("mailto:".length ) ] ];
            }
            else
              return [ m[0].length, [ "link", { href: m[1] }, m[1] ] ];
          }
    
          return [ 1, "<" ];
        },
    
        "`": function inlineCode( text ) {
          // Inline code block. as many backticks as you like to start it
          // Always skip over the opening ticks.
          var m = text.match( /(`+)(([\s\S]*?)\1)/ );
    
          if ( m && m[2] )
            return [ m[1].length + m[2].length, [ "inlinecode", m[3] ] ];
          else {
            // TODO: No matching end code found - warn!
            return [ 1, "`" ];
          }
        },
    
        "  \n": function lineBreak( text ) {
          return [ 3, [ "linebreak" ] ];
        }
    
    };
    
    // Meta Helper/generator method for em and strong handling
    function strong_em( tag, md ) {
    
      var state_slot = tag + "_state",
          other_slot = tag == "strong" ? "em_state" : "strong_state";
    
      function CloseTag(len) {
        this.len_after = len;
        this.name = "close_" + md;
      }
    
      return function ( text, orig_match ) {
    
        if ( this[state_slot][0] == md ) {
          // Most recent em is of this type
          //D:this.debug("closing", md);
          this[state_slot].shift();
    
          // "Consume" everything to go back to the recrusion in the else-block below
          return[ text.length, new CloseTag(text.length-md.length) ];
        }
        else {
          // Store a clone of the em/strong states
          var other = this[other_slot].slice(),
              state = this[state_slot].slice();
    
          this[state_slot].unshift(md);
    
          //D:this.debug_indent += "  ";
    
          // Recurse
          var res = this.processInline( text.substr( md.length ) );
          //D:this.debug_indent = this.debug_indent.substr(2);
    
          var last = res[res.length - 1];
    
          //D:this.debug("processInline from", tag + ": ", uneval( res ) );
    
          var check = this[state_slot].shift();
          if ( last instanceof CloseTag ) {
            res.pop();
            // We matched! Huzzah.
            var consumed = text.length - last.len_after;
            return [ consumed, [ tag ].concat(res) ];
          }
          else {
            // Restore the state of the other kind. We might have mistakenly closed it.
            this[other_slot] = other;
            this[state_slot] = state;
    
            // We can't reuse the processed result as it could have wrong parsing contexts in it.
            return [ md.length, md ];
          }
        }
      }; // End returned function
    }
    
    Markdown.dialects.Gruber.inline["**"] = strong_em("strong", "**");
    Markdown.dialects.Gruber.inline["__"] = strong_em("strong", "__");
    Markdown.dialects.Gruber.inline["*"]  = strong_em("em", "*");
    Markdown.dialects.Gruber.inline["_"]  = strong_em("em", "_");
    
    
    // Build default order from insertion order.
    Markdown.buildBlockOrder = function(d) {
      var ord = [];
      for ( var i in d ) {
        if ( i == "__order__" || i == "__call__" ) continue;
        ord.push( i );
      }
      d.__order__ = ord;
    };
    
    // Build patterns for inline matcher
    Markdown.buildInlinePatterns = function(d) {
      var patterns = [];
    
      for ( var i in d ) {
        // __foo__ is reserved and not a pattern
        if ( i.match( /^__.*__$/) ) continue;
        var l = i.replace( /([\\.*+?|()\[\]{}])/g, "\\$1" )
                 .replace( /\n/, "\\n" );
        patterns.push( i.length == 1 ? l : "(?:" + l + ")" );
      }
    
      patterns = patterns.join("|");
      d.__patterns__ = patterns;
      //print("patterns:", uneval( patterns ) );
    
      var fn = d.__call__;
      d.__call__ = function(text, pattern) {
        if ( pattern != undefined ) {
          return fn.call(this, text, pattern);
        }
        else
        {
          return fn.call(this, text, patterns);
        }
      };
    };
    
    Markdown.DialectHelpers = {};
    Markdown.DialectHelpers.inline_until_char = function( text, want ) {
      var consumed = 0,
          nodes = [];
    
      while ( true ) {
        if ( text.charAt( consumed ) == want ) {
          // Found the character we were looking for
          consumed++;
          return [ consumed, nodes ];
        }
    
        if ( consumed >= text.length ) {
          // No closing char found. Abort.
          return null;
        }
    
        var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) );
        consumed += res[ 0 ];
        // Add any returned nodes.
        nodes.push.apply( nodes, res.slice( 1 ) );
      }
    }
    
    // Helper function to make sub-classing a dialect easier
    Markdown.subclassDialect = function( d ) {
      function Block() {}
      Block.prototype = d.block;
      function Inline() {}
      Inline.prototype = d.inline;
    
      return { block: new Block(), inline: new Inline() };
    };
    
    Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block );
    Markdown.buildInlinePatterns( Markdown.dialects.Gruber.inline );
    
    Markdown.dialects.Maruku = Markdown.subclassDialect( Markdown.dialects.Gruber );
    
    Markdown.dialects.Maruku.processMetaHash = function processMetaHash( meta_string ) {
      var meta = split_meta_hash( meta_string ),
          attr = {};
    
      for ( var i = 0; i < meta.length; ++i ) {
        // id: #foo
        if ( /^#/.test( meta[ i ] ) ) {
          attr.id = meta[ i ].substring( 1 );
        }
        // class: .foo
        else if ( /^\./.test( meta[ i ] ) ) {
          // if class already exists, append the new one
          if ( attr["class"] ) {
            attr["class"] = attr["class"] + meta[ i ].replace( /./, " " );
          }
          else {
            attr["class"] = meta[ i ].substring( 1 );
          }
        }
        // attribute: foo=bar
        else if ( /\=/.test( meta[ i ] ) ) {
          var s = meta[ i ].split( /\=/ );
          attr[ s[ 0 ] ] = s[ 1 ];
        }
      }
    
      return attr;
    }
    
    function split_meta_hash( meta_string ) {
      var meta = meta_string.split( "" ),
          parts = [ "" ],
          in_quotes = false;
    
      while ( meta.length ) {
        var letter = meta.shift();
        switch ( letter ) {
          case " " :
            // if we're in a quoted section, keep it
            if ( in_quotes ) {
              parts[ parts.length - 1 ] += letter;
            }
            // otherwise make a new part
            else {
              parts.push( "" );
            }
            break;
          case "'" :
          case '"' :
            // reverse the quotes and move straight on
            in_quotes = !in_quotes;
            break;
          case "\\" :
            // shift off the next letter to be used straight away.
            // it was escaped so we'll keep it whatever it is
            letter = meta.shift();
          default :
            parts[ parts.length - 1 ] += letter;
            break;
        }
      }
    
      return parts;
    }
    
    Markdown.dialects.Maruku.block.document_meta = function document_meta( block, next ) {
      // we're only interested in the first block
      if ( block.lineNumber > 1 ) return undefined;
    
      // document_meta blocks consist of one or more lines of `Key: Value\n`
      if ( ! block.match( /^(?:\w+:.*\n)*\w+:.*$/ ) ) return undefined;
    
      // make an attribute node if it doesn't exist
      if ( !extract_attr( this.tree ) ) {
        this.tree.splice( 1, 0, {} );
      }
    
      var pairs = block.split( /\n/ );
      for ( p in pairs ) {
        var m = pairs[ p ].match( /(\w+):\s*(.*)$/ ),
            key = m[ 1 ].toLowerCase(),
            value = m[ 2 ];
    
        this.tree[ 1 ][ key ] = value;
      }
    
      // document_meta produces no content!
      return [];
    };
    
    Markdown.dialects.Maruku.block.block_meta = function block_meta( block, next ) {
      // check if the last line of the block is an meta hash
      var m = block.match( /(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/ );
      if ( !m ) return undefined;
    
      // process the meta hash
      var attr = this.dialect.processMetaHash( m[ 2 ] );
    
      var hash;
    
      // if we matched ^ then we need to apply meta to the previous block
      if ( m[ 1 ] === "" ) {
        var node = this.tree[ this.tree.length - 1 ];
        hash = extract_attr( node );
    
        // if the node is a string (rather than JsonML), bail
        if ( typeof node === "string" ) return undefined;
    
        // create the attribute hash if it doesn't exist
        if ( !hash ) {
          hash = {};
          node.splice( 1, 0, hash );
        }
    
        // add the attributes in
        for ( a in attr ) {
          hash[ a ] = attr[ a ];
        }
    
        // return nothing so the meta hash is removed
        return [];
      }
    
      // pull the meta hash off the block and process what's left
      var b = block.replace( /\n.*$/, "" ),
          result = this.processBlock( b, [] );
    
      // get or make the attributes hash
      hash = extract_attr( result[ 0 ] );
      if ( !hash ) {
        hash = {};
        result[ 0 ].splice( 1, 0, hash );
      }
    
      // attach the attributes to the block
      for ( a in attr ) {
        hash[ a ] = attr[ a ];
      }
    
      return result;
    };
    
    Markdown.dialects.Maruku.block.definition_list = function definition_list( block, next ) {
      // one or more terms followed by one or more definitions, in a single block
      var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,
          list = [ "dl" ],
          i, m;
    
      // see if we're dealing with a tight or loose block
      if ( ( m = block.match( tight ) ) ) {
        // pull subsequent tight DL blocks out of `next`
        var blocks = [ block ];
        while ( next.length && tight.exec( next[ 0 ] ) ) {
          blocks.push( next.shift() );
        }
    
        for ( var b = 0; b < blocks.length; ++b ) {
          var m = blocks[ b ].match( tight ),
              terms = m[ 1 ].replace( /\n$/, "" ).split( /\n/ ),
              defns = m[ 2 ].split( /\n:\s+/ );
    
          // print( uneval( m ) );
    
          for ( i = 0; i < terms.length; ++i ) {
            list.push( [ "dt", terms[ i ] ] );
          }
    
          for ( i = 0; i < defns.length; ++i ) {
            // run inline processing over the definition
            list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) );
          }
        }
      }
      else {
        return undefined;
      }
    
      return [ list ];
    };
    
    // splits on unescaped instances of @ch. If @ch is not a character the result
    // can be unpredictable
    
    Markdown.dialects.Maruku.block.table = function table (block, next) {
    
        var _split_on_unescaped = function(s, ch) {
            ch = ch || '\\s';
            if (ch.match(/^[\\|\[\]{}?*.+^$]$/)) { ch = '\\' + ch; }
            var res = [ ],
                r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'),
                m;
            while(m = s.match(r)) {
                res.push(m[1]);
                s = m[2];
            }
            res.push(s);
            return res;
        }
    
        var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/,
            // find at least an unescaped pipe in each line
            no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/,
            i, m;
        if (m = block.match(leading_pipe)) {
            // remove leading pipes in contents
            // (header and horizontal rule already have the leading pipe left out)
            m[3] = m[3].replace(/^\s*\|/gm, '');
        } else if (! ( m = block.match(no_leading_pipe))) {
            return undefined;
        }
    
        var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ];
    
        // remove trailing pipes, then split on pipes
        // (no escaped pipes are allowed in horizontal rule)
        m[2] = m[2].replace(/\|\s*$/, '').split('|');
    
        // process alignment
        var html_attrs = [ ];
        forEach (m[2], function (s) {
            if (s.match(/^\s*-+:\s*$/))       html_attrs.push({align: "right"});
            else if (s.match(/^\s*:-+\s*$/))  html_attrs.push({align: "left"});
            else if (s.match(/^\s*:-+:\s*$/)) html_attrs.push({align: "center"});
            else                              html_attrs.push({});
        });
    
        // now for the header, avoid escaped pipes
        m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|');
        for (i = 0; i < m[1].length; i++) {
            table[1][1].push(['th', html_attrs[i] || {}].concat(
                this.processInline(m[1][i].trim())));
        }
    
        // now for body contents
        forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) {
            var html_row = ['tr'];
            row = _split_on_unescaped(row, '|');
            for (i = 0; i < row.length; i++) {
                html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim())));
            }
            table[2].push(html_row);
        }, this);
    
        return [table];
    }
    
    Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) {
      if ( !out.length ) {
        return [ 2, "{:" ];
      }
    
      // get the preceeding element
      var before = out[ out.length - 1 ];
    
      if ( typeof before === "string" ) {
        return [ 2, "{:" ];
      }
    
      // match a meta hash
      var m = text.match( /^\{:\s*((?:\\\}|[^\}])*)\s*\}/ );
    
      // no match, false alarm
      if ( !m ) {
        return [ 2, "{:" ];
      }
    
      // attach the attributes to the preceeding element
      var meta = this.dialect.processMetaHash( m[ 1 ] ),
          attr = extract_attr( before );
    
      if ( !attr ) {
        attr = {};
        before.splice( 1, 0, attr );
      }
    
      for ( var k in meta ) {
        attr[ k ] = meta[ k ];
      }
    
      // cut out the string and replace it with nothing
      return [ m[ 0 ].length, "" ];
    };
    
    Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/;
    
    Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block );
    Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline );
    
    var isArray = Array.isArray || function(obj) {
      return Object.prototype.toString.call(obj) == "[object Array]";
    };
    
    var forEach;
    // Don't mess with Array.prototype. Its not friendly
    if ( Array.prototype.forEach ) {
      forEach = function( arr, cb, thisp ) {
        return arr.forEach( cb, thisp );
      };
    }
    else {
      forEach = function(arr, cb, thisp) {
        for (var i = 0; i < arr.length; i++) {
          cb.call(thisp || arr, arr[i], i, arr);
        }
      }
    }
    
    var isEmpty = function( obj ) {
      for ( var key in obj ) {
        if ( hasOwnProperty.call( obj, key ) ) {
          return false;
        }
      }
    
      return true;
    }
    
    function extract_attr( jsonml ) {
      return isArray(jsonml)
          && jsonml.length > 1
          && typeof jsonml[ 1 ] === "object"
          && !( isArray(jsonml[ 1 ]) )
          ? jsonml[ 1 ]
          : undefined;
    }
    
    
    
    /**
     *  renderJsonML( jsonml[, options] ) -> String
     *  - jsonml (Array): JsonML array to render to XML
     *  - options (Object): options
     *
     *  Converts the given JsonML into well-formed XML.
     *
     *  The options currently understood are:
     *
     *  - root (Boolean): wether or not the root node should be included in the
     *    output, or just its children. The default `false` is to not include the
     *    root itself.
     */
    expose.renderJsonML = function( jsonml, options ) {
      options = options || {};
      // include the root element in the rendered output?
      options.root = options.root || false;
    
      var content = [];
    
      if ( options.root ) {
        content.push( render_tree( jsonml ) );
      }
      else {
        jsonml.shift(); // get rid of the tag
        if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
          jsonml.shift(); // get rid of the attributes
        }
    
        while ( jsonml.length ) {
          content.push( render_tree( jsonml.shift() ) );
        }
      }
    
      return content.join( "\n\n" );
    };
    
    function escapeHTML( text ) {
      return text.replace( /&/g, "&amp;" )
                 .replace( /</g, "&lt;" )
                 .replace( />/g, "&gt;" )
                 .replace( /"/g, "&quot;" )
                 .replace( /'/g, "&#39;" );
    }
    
    function render_tree( jsonml ) {
      // basic case
      if ( typeof jsonml === "string" ) {
        return escapeHTML( jsonml );
      }
    
      var tag = jsonml.shift(),
          attributes = {},
          content = [];
    
      if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
        attributes = jsonml.shift();
      }
    
      while ( jsonml.length ) {
        content.push( render_tree( jsonml.shift() ) );
      }
    
      var tag_attrs = "";
      for ( var a in attributes ) {
        tag_attrs += " " + a + '="' + escapeHTML( attributes[ a ] ) + '"';
      }
    
      // be careful about adding whitespace here for inline elements
      if ( tag == "img" || tag == "br" || tag == "hr" ) {
        return "<"+ tag + tag_attrs + "/>";
      }
      else {
        return "<"+ tag + tag_attrs + ">" + content.join( "" ) + "</" + tag + ">";
      }
    }
    
    function convert_tree_to_html( tree, references, options ) {
      var i;
      options = options || {};
    
      // shallow clone
      var jsonml = tree.slice( 0 );
    
      if ( typeof options.preprocessTreeNode === "function" ) {
          jsonml = options.preprocessTreeNode(jsonml, references);
      }
    
      // Clone attributes if they exist
      var attrs = extract_attr( jsonml );
      if ( attrs ) {
        jsonml[ 1 ] = {};
        for ( i in attrs ) {
          jsonml[ 1 ][ i ] = attrs[ i ];
        }
        attrs = jsonml[ 1 ];
      }
    
      // basic case
      if ( typeof jsonml === "string" ) {
        return jsonml;
      }
    
      // convert this node
      switch ( jsonml[ 0 ] ) {
        case "header":
          jsonml[ 0 ] = "h" + jsonml[ 1 ].level;
          delete jsonml[ 1 ].level;
          break;
        case "bulletlist":
          jsonml[ 0 ] = "ul";
          break;
        case "numberlist":
          jsonml[ 0 ] = "ol";
          break;
        case "listitem":
          jsonml[ 0 ] = "li";
          break;
        case "para":
          jsonml[ 0 ] = "p";
          break;
        case "markdown":
          jsonml[ 0 ] = "html";
          if ( attrs ) delete attrs.references;
          break;
        case "code_block":
          jsonml[ 0 ] = "pre";
          i = attrs ? 2 : 1;
          var code = [ "code" ];
          code.push.apply( code, jsonml.splice( i, jsonml.length - i ) );
          jsonml[ i ] = code;
          break;
        case "inlinecode":
          jsonml[ 0 ] = "code";
          break;
        case "img":
          jsonml[ 1 ].src = jsonml[ 1 ].href;
          delete jsonml[ 1 ].href;
          break;
        case "linebreak":
          jsonml[ 0 ] = "br";
        break;
        case "link":
          jsonml[ 0 ] = "a";
          break;
        case "link_ref":
          jsonml[ 0 ] = "a";
    
          // grab this ref and clean up the attribute node
          var ref = references[ attrs.ref ];
    
          // if the reference exists, make the link
          if ( ref ) {
            delete attrs.ref;
    
            // add in the href and title, if present
            attrs.href = ref.href;
            if ( ref.title ) {
              attrs.title = ref.title;
            }
    
            // get rid of the unneeded original text
            delete attrs.original;
          }
          // the reference doesn't exist, so revert to plain text
          else {
            return attrs.original;
          }
          break;
        case "img_ref":
          jsonml[ 0 ] = "img";
    
          // grab this ref and clean up the attribute node
          var ref = references[ attrs.ref ];
    
          // if the reference exists, make the link
          if ( ref ) {
            delete attrs.ref;
    
            // add in the href and title, if present
            attrs.src = ref.href;
            if ( ref.title ) {
              attrs.title = ref.title;
            }
    
            // get rid of the unneeded original text
            delete attrs.original;
          }
          // the reference doesn't exist, so revert to plain text
          else {
            return attrs.original;
          }
          break;
      }
    
      // convert all the children
      i = 1;
    
      // deal with the attribute node, if it exists
      if ( attrs ) {
        // if there are keys, skip over it
        for ( var key in jsonml[ 1 ] ) {
            i = 2;
            break;
        }
        // if there aren't, remove it
        if ( i === 1 ) {
          jsonml.splice( i, 1 );
        }
      }
    
      for ( ; i < jsonml.length; ++i ) {
        jsonml[ i ] = convert_tree_to_html( jsonml[ i ], references, options );
      }
    
      return jsonml;
    }
    
    
    // merges adjacent text nodes into a single node
    function merge_text_nodes( jsonml ) {
      // skip the tag name and attribute hash
      var i = extract_attr( jsonml ) ? 2 : 1;
    
      while ( i < jsonml.length ) {
        // if it's a string check the next item too
        if ( typeof jsonml[ i ] === "string" ) {
          if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === "string" ) {
            // merge the second string into the first and remove it
            jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ];
          }
          else {
            ++i;
          }
        }
        // if it's not a string recurse
        else {
          merge_text_nodes( jsonml[ i ] );
          ++i;
        }
      }
    }
    
    } )( (function() {
      if ( typeof exports === "undefined" ) {
        window.markdown = {};
        return window.markdown;
      }
      else {
        return exports;
      }
    } )() );
    
    (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.toMarkdown = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
    /*
     * to-markdown - an HTML to Markdown converter
     *
     * Copyright 2011+, Dom Christie
     * Licenced under the MIT licence
     *
     */
    
    'use strict'
    
    var toMarkdown
    var converters
    var mdConverters = require('./lib/md-converters')
    var gfmConverters = require('./lib/gfm-converters')
    var HtmlParser = require('./lib/html-parser')
    var collapse = require('collapse-whitespace')
    
    /*
     * Utilities
     */
    
    var blocks = ['address', 'article', 'aside', 'audio', 'blockquote', 'body',
      'canvas', 'center', 'dd', 'dir', 'div', 'dl', 'dt', 'fieldset', 'figcaption',
      'figure', 'footer', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
      'header', 'hgroup', 'hr', 'html', 'isindex', 'li', 'main', 'menu', 'nav',
      'noframes', 'noscript', 'ol', 'output', 'p', 'pre', 'section', 'table',
      'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul'
    ]
    
    function isBlock (node) {
      return blocks.indexOf(node.nodeName.toLowerCase()) !== -1
    }
    
    var voids = [
      'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input',
      'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'
    ]
    
    function isVoid (node) {
      return voids.indexOf(node.nodeName.toLowerCase()) !== -1
    }
    
    function htmlToDom (string) {
      var tree = new HtmlParser().parseFromString(string, 'text/html')
      collapse(tree.documentElement, isBlock)
      return tree
    }
    
    /*
     * Flattens DOM tree into single array
     */
    
    function bfsOrder (node) {
      var inqueue = [node]
      var outqueue = []
      var elem
      var children
      var i
    
      while (inqueue.length > 0) {
        elem = inqueue.shift()
        outqueue.push(elem)
        children = elem.childNodes
        for (i = 0; i < children.length; i++) {
          if (children[i].nodeType === 1) inqueue.push(children[i])
        }
      }
      outqueue.shift()
      return outqueue
    }
    
    /*
     * Contructs a Markdown string of replacement text for a given node
     */
    
    function getContent (node) {
      var text = ''
      for (var i = 0; i < node.childNodes.length; i++) {
        if (node.childNodes[i].nodeType === 1) {
          text += node.childNodes[i]._replacement
        } else if (node.childNodes[i].nodeType === 3) {
          text += node.childNodes[i].data
        } else continue
      }
      return text
    }
    
    /*
     * Returns the HTML string of an element with its contents converted
     */
    
    function outer (node, content) {
      return node.cloneNode(false).outerHTML.replace('><', '>' + content + '<')
    }
    
    function canConvert (node, filter) {
      if (typeof filter === 'string') {
        return filter === node.nodeName.toLowerCase()
      }
      if (Array.isArray(filter)) {
        return filter.indexOf(node.nodeName.toLowerCase()) !== -1
      } else if (typeof filter === 'function') {
        return filter.call(toMarkdown, node)
      } else {
        throw new TypeError('`filter` needs to be a string, array, or function')
      }
    }
    
    function isFlankedByWhitespace (side, node) {
      var sibling
      var regExp
      var isFlanked
    
      if (side === 'left') {
        sibling = node.previousSibling
        regExp = / $/
      } else {
        sibling = node.nextSibling
        regExp = /^ /
      }
    
      if (sibling) {
        if (sibling.nodeType === 3) {
          isFlanked = regExp.test(sibling.nodeValue)
        } else if (sibling.nodeType === 1 && !isBlock(sibling)) {
          isFlanked = regExp.test(sibling.textContent)
        }
      }
      return isFlanked
    }
    
    function flankingWhitespace (node, content) {
      var leading = ''
      var trailing = ''
    
      if (!isBlock(node)) {
        var hasLeading = /^[ \r\n\t]/.test(content)
        var hasTrailing = /[ \r\n\t]$/.test(content)
    
        if (hasLeading && !isFlankedByWhitespace('left', node)) {
          leading = ' '
        }
        if (hasTrailing && !isFlankedByWhitespace('right', node)) {
          trailing = ' '
        }
      }
    
      return { leading: leading, trailing: trailing }
    }
    
    /*
     * Finds a Markdown converter, gets the replacement, and sets it on
     * `_replacement`
     */
    
    function process (node) {
      var replacement
      var content = getContent(node)
    
      // Remove blank nodes
      if (!isVoid(node) && !/A|TH|TD/.test(node.nodeName) && /^\s*$/i.test(content)) {
        node._replacement = ''
        return
      }
    
      for (var i = 0; i < converters.length; i++) {
        var converter = converters[i]
    
        if (canConvert(node, converter.filter)) {
          if (typeof converter.replacement !== 'function') {
            throw new TypeError(
              '`replacement` needs to be a function that returns a string'
            )
          }
    
          var whitespace = flankingWhitespace(node, content)
    
          if (whitespace.leading || whitespace.trailing) {
            content = content.trim()
          }
          replacement = whitespace.leading +
            converter.replacement.call(toMarkdown, content, node) +
            whitespace.trailing
          break
        }
      }
    
      node._replacement = replacement
    }
    
    toMarkdown = function (input, options) {
      options = options || {}
    
      if (typeof input !== 'string') {
        throw new TypeError(input + ' is not a string')
      }
    
      if (input === '') {
        return ''
      }
    
      // Escape potential ol triggers
      input = input.replace(/(\d+)\. /g, '$1\\. ')
    
      var clone = htmlToDom(input).body
      var nodes = bfsOrder(clone)
      var output
    
      converters = mdConverters.slice(0)
      if (options.gfm) {
        converters = gfmConverters.concat(converters)
      }
    
      if (options.converters) {
        converters = options.converters.concat(converters)
      }
    
      // Process through nodes in reverse (so deepest child elements are first).
      for (var i = nodes.length - 1; i >= 0; i--) {
        process(nodes[i])
      }
      output = getContent(clone)
    
      return output.replace(/^[\t\r\n]+|[\t\r\n\s]+$/g, '')
        .replace(/\n\s+\n/g, '\n\n')
        .replace(/\n{3,}/g, '\n\n')
    }
    
    toMarkdown.isBlock = isBlock
    toMarkdown.isVoid = isVoid
    toMarkdown.outer = outer
    
    module.exports = toMarkdown
    
    },{"./lib/gfm-converters":2,"./lib/html-parser":3,"./lib/md-converters":4,"collapse-whitespace":7}],2:[function(require,module,exports){
    'use strict'
    
    function cell (content, node) {
      var index = Array.prototype.indexOf.call(node.parentNode.childNodes, node)
      var prefix = ' '
      if (index === 0) prefix = '| '
      return prefix + content + ' |'
    }
    
    var highlightRegEx = /highlight highlight-(\S+)/
    
    module.exports = [
      {
        filter: 'br',
        replacement: function () {
          return '\n'
        }
      },
      {
        filter: ['del', 's', 'strike'],
        replacement: function (content) {
          return '~~' + content + '~~'
        }
      },
    
      {
        filter: function (node) {
          return node.type === 'checkbox' && node.parentNode.nodeName === 'LI'
        },
        replacement: function (content, node) {
          return (node.checked ? '[x]' : '[ ]') + ' '
        }
      },
    
      {
        filter: ['th', 'td'],
        replacement: function (content, node) {
          return cell(content, node)
        }
      },
    
      {
        filter: 'tr',
        replacement: function (content, node) {
          var borderCells = ''
          var alignMap = { left: ':--', right: '--:', center: ':-:' }
    
          if (node.parentNode.nodeName === 'THEAD') {
            for (var i = 0; i < node.childNodes.length; i++) {
              var align = node.childNodes[i].attributes.align
              var border = '---'
    
              if (align) border = alignMap[align.value] || border
    
              borderCells += cell(border, node.childNodes[i])
            }
          }
          return '\n' + content + (borderCells ? '\n' + borderCells : '')
        }
      },
    
      {
        filter: 'table',
        replacement: function (content) {
          return '\n\n' + content + '\n\n'
        }
      },
    
      {
        filter: ['thead', 'tbody', 'tfoot'],
        replacement: function (content) {
          return content
        }
      },
    
      // Fenced code blocks
      {
        filter: function (node) {
          return node.nodeName === 'PRE' &&
          node.firstChild &&
          node.firstChild.nodeName === 'CODE'
        },
        replacement: function (content, node) {
          return '\n\n```\n' + node.firstChild.textContent + '\n```\n\n'
        }
      },
    
      // Syntax-highlighted code blocks
      {
        filter: function (node) {
          return node.nodeName === 'PRE' &&
          node.parentNode.nodeName === 'DIV' &&
          highlightRegEx.test(node.parentNode.className)
        },
        replacement: function (content, node) {
          var language = node.parentNode.className.match(highlightRegEx)[1]
          return '\n\n```' + language + '\n' + node.textContent + '\n```\n\n'
        }
      },
    
      {
        filter: function (node) {
          return node.nodeName === 'DIV' &&
          highlightRegEx.test(node.className)
        },
        replacement: function (content) {
          return '\n\n' + content + '\n\n'
        }
      }
    ]
    
    },{}],3:[function(require,module,exports){
    /*
     * Set up window for Node.js
     */
    
    var _window = (typeof window !== 'undefined' ? window : this)
    
    /*
     * Parsing HTML strings
     */
    
    function canParseHtmlNatively () {
      var Parser = _window.DOMParser
      var canParse = false
    
      // Adapted from https://gist.github.com/1129031
      // Firefox/Opera/IE throw errors on unsupported types
      try {
        // WebKit returns null on unsupported types
        if (new Parser().parseFromString('', 'text/html')) {
          canParse = true
        }
      } catch (e) {}
    
      return canParse
    }
    
    function createHtmlParser () {
      var Parser = function () {}
    
      // For Node.js environments
      if (typeof document === 'undefined') {
        var jsdom = require('jsdom')
        Parser.prototype.parseFromString = function (string) {
          return jsdom.jsdom(string, {
            features: {
              FetchExternalResources: [],
              ProcessExternalResources: false
            }
          })
        }
      } else {
        if (!shouldUseActiveX()) {
          Parser.prototype.parseFromString = function (string) {
            var doc = document.implementation.createHTMLDocument('')
            doc.open()
            doc.write(string)
            doc.close()
            return doc
          }
        } else {
          Parser.prototype.parseFromString = function (string) {
            var doc = new window.ActiveXObject('htmlfile')
            doc.designMode = 'on' // disable on-page scripts
            doc.open()
            doc.write(string)
            doc.close()
            return doc
          }
        }
      }
      return Parser
    }
    
    function shouldUseActiveX () {
      var useActiveX = false
    
      try {
        document.implementation.createHTMLDocument('').open()
      } catch (e) {
        if (window.ActiveXObject) useActiveX = true
      }
    
      return useActiveX
    }
    
    module.exports = canParseHtmlNatively() ? _window.DOMParser : createHtmlParser()
    
    },{"jsdom":6}],4:[function(require,module,exports){
    'use strict'
    
    module.exports = [
      {
        filter: 'p',
        replacement: function (content) {
          return '\n\n' + content + '\n\n'
        }
      },
    
      {
        filter: 'br',
        replacement: function () {
          return '  \n'
        }
      },
    
      {
        filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
        replacement: function (content, node) {
          var hLevel = node.nodeName.charAt(1)
          var hPrefix = ''
          for (var i = 0; i < hLevel; i++) {
            hPrefix += '#'
          }
          return '\n\n' + hPrefix + ' ' + content + '\n\n'
        }
      },
    
      {
        filter: 'hr',
        replacement: function () {
          return '\n\n* * *\n\n'
        }
      },
    
      {
        filter: ['em', 'i'],
        replacement: function (content) {
          return '_' + content + '_'
        }
      },
    
      {
        filter: ['strong', 'b'],
        replacement: function (content) {
          return '**' + content + '**'
        }
      },
    
      // Inline code
      {
        filter: function (node) {
          var hasSiblings = node.previousSibling || node.nextSibling
          var isCodeBlock = node.parentNode.nodeName === 'PRE' && !hasSiblings
    
          return node.nodeName === 'CODE' && !isCodeBlock
        },
        replacement: function (content) {
          return '`' + content + '`'
        }
      },
    
      {
        filter: function (node) {
          return node.nodeName === 'A' && node.getAttribute('href')
        },
        replacement: function (content, node) {
          var titlePart = node.title ? ' "' + node.title + '"' : ''
          return '[' + content + '](' + node.getAttribute('href') + titlePart + ')'
        }
      },
    
      {
        filter: 'img',
        replacement: function (content, node) {
          var alt = node.alt || ''
          var src = node.getAttribute('src') || ''
          var title = node.title || ''
          var titlePart = title ? ' "' + title + '"' : ''
          return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : ''
        }
      },
    
      // Code blocks
      {
        filter: function (node) {
          return node.nodeName === 'PRE' && node.firstChild.nodeName === 'CODE'
        },
        replacement: function (content, node) {
          return '\n\n    ' + node.firstChild.textContent.replace(/\n/g, '\n    ') + '\n\n'
        }
      },
    
      {
        filter: 'blockquote',
        replacement: function (content) {
          content = content.trim()
          content = content.replace(/\n{3,}/g, '\n\n')
          content = content.replace(/^/gm, '> ')
          return '\n\n' + content + '\n\n'
        }
      },
    
      {
        filter: 'li',
        replacement: function (content, node) {
          content = content.replace(/^\s+/, '').replace(/\n/gm, '\n    ')
          var prefix = '*   '
          var parent = node.parentNode
          var index = Array.prototype.indexOf.call(parent.children, node) + 1
    
          prefix = /ol/i.test(parent.nodeName) ? index + '.  ' : '*   '
          return prefix + content
        }
      },
    
      {
        filter: ['ul', 'ol'],
        replacement: function (content, node) {
          var strings = []
          for (var i = 0; i < node.childNodes.length; i++) {
            strings.push(node.childNodes[i]._replacement)
          }
    
          if (/li/i.test(node.parentNode.nodeName)) {
            return '\n' + strings.join('\n')
          }
          return '\n\n' + strings.join('\n') + '\n\n'
        }
      },
    
      {
        filter: function (node) {
          return this.isBlock(node)
        },
        replacement: function (content, node) {
          return '\n\n' + this.outer(node, content) + '\n\n'
        }
      },
    
      // Anything else!
      {
        filter: function () {
          return true
        },
        replacement: function (content, node) {
          return this.outer(node, content)
        }
      }
    ]
    
    },{}],5:[function(require,module,exports){
    /**
     * This file automatically generated from `build.js`.
     * Do not manually edit.
     */
    
    module.exports = [
      "address",
      "article",
      "aside",
      "audio",
      "blockquote",
      "canvas",
      "dd",
      "div",
      "dl",
      "fieldset",
      "figcaption",
      "figure",
      "footer",
      "form",
      "h1",
      "h2",
      "h3",
      "h4",
      "h5",
      "h6",
      "header",
      "hgroup",
      "hr",
      "main",
      "nav",
      "noscript",
      "ol",
      "output",
      "p",
      "pre",
      "section",
      "table",
      "tfoot",
      "ul",
      "video"
    ];
    
    },{}],6:[function(require,module,exports){
    
    },{}],7:[function(require,module,exports){
    'use strict';
    
    var voidElements = require('void-elements');
    Object.keys(voidElements).forEach(function (name) {
      voidElements[name.toUpperCase()] = 1;
    });
    
    var blockElements = {};
    require('block-elements').forEach(function (name) {
      blockElements[name.toUpperCase()] = 1;
    });
    
    /**
     * isBlockElem(node) determines if the given node is a block element.
     *
     * @param {Node} node
     * @return {Boolean}
     */
    function isBlockElem(node) {
      return !!(node && blockElements[node.nodeName]);
    }
    
    /**
     * isVoid(node) determines if the given node is a void element.
     *
     * @param {Node} node
     * @return {Boolean}
     */
    function isVoid(node) {
      return !!(node && voidElements[node.nodeName]);
    }
    
    /**
     * whitespace(elem [, isBlock]) removes extraneous whitespace from an
     * the given element. The function isBlock may optionally be passed in
     * to determine whether or not an element is a block element; if none
     * is provided, defaults to using the list of block elements provided
     * by the `block-elements` module.
     *
     * @param {Node} elem
     * @param {Function} blockTest
     */
    function collapseWhitespace(elem, isBlock) {
      if (!elem.firstChild || elem.nodeName === 'PRE') return;
    
      if (typeof isBlock !== 'function') {
        isBlock = isBlockElem;
      }
    
      var prevText = null;
      var prevVoid = false;
    
      var prev = null;
      var node = next(prev, elem);
    
      while (node !== elem) {
        if (node.nodeType === 3) {
          // Node.TEXT_NODE
          var text = node.data.replace(/[ \r\n\t]+/g, ' ');
    
          if ((!prevText || / $/.test(prevText.data)) && !prevVoid && text[0] === ' ') {
            text = text.substr(1);
          }
    
          // `text` might be empty at this point.
          if (!text) {
            node = remove(node);
            continue;
          }
    
          node.data = text;
          prevText = node;
        } else if (node.nodeType === 1) {
          // Node.ELEMENT_NODE
          if (isBlock(node) || node.nodeName === 'BR') {
            if (prevText) {
              prevText.data = prevText.data.replace(/ $/, '');
            }
    
            prevText = null;
            prevVoid = false;
          } else if (isVoid(node)) {
            // Avoid trimming space around non-block, non-BR void elements.
            prevText = null;
            prevVoid = true;
          }
        } else {
          node = remove(node);
          continue;
        }
    
        var nextNode = next(prev, node);
        prev = node;
        node = nextNode;
      }
    
      if (prevText) {
        prevText.data = prevText.data.replace(/ $/, '');
        if (!prevText.data) {
          remove(prevText);
        }
      }
    }
    
    /**
     * remove(node) removes the given node from the DOM and returns the
     * next node in the sequence.
     *
     * @param {Node} node
     * @return {Node} node
     */
    function remove(node) {
      var next = node.nextSibling || node.parentNode;
    
      node.parentNode.removeChild(node);
    
      return next;
    }
    
    /**
     * next(prev, current) returns the next node in the sequence, given the
     * current and previous nodes.
     *
     * @param {Node} prev
     * @param {Node} current
     * @return {Node}
     */
    function next(prev, current) {
      if (prev && prev.parentNode === current || current.nodeName === 'PRE') {
        return current.nextSibling || current.parentNode;
      }
    
      return current.firstChild || current.nextSibling || current.parentNode;
    }
    
    module.exports = collapseWhitespace;
    
    },{"block-elements":5,"void-elements":8}],8:[function(require,module,exports){
    /**
     * This file automatically generated from `pre-publish.js`.
     * Do not manually edit.
     */
    
    module.exports = {
      "area": true,
      "base": true,
      "br": true,
      "col": true,
      "embed": true,
      "hr": true,
      "img": true,
      "input": true,
      "keygen": true,
      "link": true,
      "menuitem": true,
      "meta": true,
      "param": true,
      "source": true,
      "track": true,
      "wbr": true
    };
    
    },{}]},{},[1])(1)
    });
    /* ===================================================
     * bootstrap-markdown.js v2.10.0
     * http://github.com/toopay/bootstrap-markdown
     * ===================================================
     * Copyright 2013-2016 Taufan Aditya
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     * ========================================================== */
    
    (function(factory){
        if (typeof define === "function" && define.amd) {
            //RequireJS
            define(["jquery"], factory);
        } else if (typeof exports === 'object') {
            //Backbone.js
            factory(require('jquery'));
        } else {
            //Jquery plugin
            factory(jQuery);
        }
    }(function($){
      "use strict"; // jshint ;_;
    
      /* MARKDOWN CLASS DEFINITION
       * ========================== */
    
      var Markdown = function (element, options) {
        // @TODO : remove this BC on next major release
        // @see : https://github.com/toopay/bootstrap-markdown/issues/109
        var opts = ['autofocus', 'savable', 'hideable', 'width', 
          'height', 'resize', 'iconlibrary', 'language', 
          'footer', 'fullscreen', 'hiddenButtons', 'disabledButtons'];
        $.each(opts,function(_, opt){
          if (typeof $(element).data(opt) !== 'undefined') {
            options = typeof options == 'object' ? options : {}
            options[opt] = $(element).data(opt)
          }
        });
        // End BC
    
        // Class Properties
        this.$ns           = 'bootstrap-markdown';
        this.$element      = $(element);
        this.$editable     = {el:null, type:null,attrKeys:[], attrValues:[], content:null};
        this.$options      = $.extend(true, {}, $.fn.markdown.defaults, options, this.$element.data('options'));
        this.$oldContent   = null;
        this.$isPreview    = false;
        this.$isFullscreen = false;
        this.$editor       = null;
        this.$textarea     = null;
        this.$handler      = [];
        this.$callback     = [];
        this.$nextTab      = [];
    
        this.showEditor();
      };
    
      Markdown.prototype = {
    
        constructor: Markdown
    
      , __alterButtons: function(name,alter) {
          var handler = this.$handler, isAll = (name == 'all'),that = this;
    
          $.each(handler,function(k,v) {
            var halt = true;
            if (isAll) {
              halt = false;
            } else {
              halt = v.indexOf(name) < 0;
            }
    
            if (halt === false) {
              alter(that.$editor.find('button[data-handler="'+v+'"]'));
            }
          });
        }
    
      , __buildButtons: function(buttonsArray, container) {
          var i,
              ns = this.$ns,
              handler = this.$handler,
              callback = this.$callback;
    
          for (i=0;i<buttonsArray.length;i++) {
            // Build each group container
            var y, btnGroups = buttonsArray[i];
            for (y=0;y<btnGroups.length;y++) {
              // Build each button group
              var z,
                  buttons = btnGroups[y].data,
                  btnGroupContainer = $('<div/>', {
                                        'class': 'btn-group'
                                      });
    
              for (z=0;z<buttons.length;z++) {
                var button = buttons[z],
                    buttonContainer, buttonIconContainer,
                    buttonHandler = ns+'-'+button.name,
                    buttonIcon = this.__getIcon(button.icon),
                    btnText = button.btnText ? button.btnText : '',
                    btnClass = button.btnClass ? button.btnClass : 'btn',
                    tabIndex = button.tabIndex ? button.tabIndex : '-1',
                    hotkey = typeof button.hotkey !== 'undefined' ? button.hotkey : '',
                    hotkeyCaption = typeof jQuery.hotkeys !== 'undefined' && hotkey !== '' ? ' ('+hotkey+')' : '';
    
                // Construct the button object
                buttonContainer = $('<button></button>');
                buttonContainer.text(' ' + this.__localize(btnText)).addClass('btn-default btn-sm').addClass(btnClass);
                if(btnClass.match(/btn\-(primary|success|info|warning|danger|link)/)){
                    buttonContainer.removeClass('btn-default');
                }
                buttonContainer.attr({
                    'type': 'button',
                    'title': this.__localize(button.title) + hotkeyCaption,
                    'tabindex': tabIndex,
                    'data-provider': ns,
                    'data-handler': buttonHandler,
                    'data-hotkey': hotkey
                });
                if (button.toggle === true){
                  buttonContainer.attr('data-toggle', 'button');
                }
                buttonIconContainer = $('<span/>');
                buttonIconContainer.addClass(buttonIcon);
                buttonIconContainer.prependTo(buttonContainer);
    
                // Attach the button object
                btnGroupContainer.append(buttonContainer);
    
                // Register handler and callback
                handler.push(buttonHandler);
                callback.push(button.callback);
              }
    
              // Attach the button group into container dom
              container.append(btnGroupContainer);
            }
          }
    
          return container;
        }
      , __setListener: function() {
          // Set size and resizable Properties
          var hasRows = typeof this.$textarea.attr('rows') !== 'undefined',
              maxRows = this.$textarea.val().split("\n").length > 5 ? this.$textarea.val().split("\n").length : '5',
              rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows;
    
          this.$textarea.attr('rows',rowsVal);
          if (this.$options.resize) {
            this.$textarea.css('resize',this.$options.resize);
          }
    
          this.$textarea.on({
              'focus' : $.proxy(this.focus, this),
              'keyup' : $.proxy(this.keyup, this),
              'change' : $.proxy(this.change, this),
              'select' : $.proxy(this.select, this)
          });
    
          if (this.eventSupported('keydown')) {
            this.$textarea.on('keydown', $.proxy(this.keydown, this));
          }
    
          if (this.eventSupported('keypress')) {
            this.$textarea.on('keypress', $.proxy(this.keypress, this))
          }
    
          // Re-attach markdown data
          this.$textarea.data('markdown',this);
        }
    
      , __handle: function(e) {
          var target = $(e.currentTarget),
              handler = this.$handler,
              callback = this.$callback,
              handlerName = target.attr('data-handler'),
              callbackIndex = handler.indexOf(handlerName),
              callbackHandler = callback[callbackIndex];
    
          // Trigger the focusin
          $(e.currentTarget).focus();
    
          callbackHandler(this);
    
          // Trigger onChange for each button handle
          this.change(this);
    
          // Unless it was the save handler,
          // focusin the textarea
          if (handlerName.indexOf('cmdSave') < 0) {
            this.$textarea.focus();
          }
    
          e.preventDefault();
        }
    
      , __localize: function(string) {
          var messages = $.fn.markdown.messages,
              language = this.$options.language;
          if (
            typeof messages !== 'undefined' &&
            typeof messages[language] !== 'undefined' &&
            typeof messages[language][string] !== 'undefined'
          ) {
            return messages[language][string];
          }
          return string;
        }
    
      , __getIcon: function(src) {
        return typeof src == 'object' ? src[this.$options.iconlibrary] : src;
      }
    
      , setFullscreen: function(mode) {
        var $editor = this.$editor,
            $textarea = this.$textarea;
    
        if (mode === true) {
          $editor.addClass('md-fullscreen-mode');
          $('body').addClass('md-nooverflow');
          this.$options.onFullscreen(this);
        } else {
          $editor.removeClass('md-fullscreen-mode');
          $('body').removeClass('md-nooverflow');
    
          if (this.$isPreview == true) this.hidePreview().showPreview()
        }
    
        this.$isFullscreen = mode;
        $textarea.focus();
      }
    
      , showEditor: function() {
          var instance = this,
              textarea,
              ns = this.$ns,
              container = this.$element,
              originalHeigth = container.css('height'),
              originalWidth = container.css('width'),
              editable = this.$editable,
              handler = this.$handler,
              callback = this.$callback,
              options = this.$options,
              editor = $( '<div/>', {
                          'class': 'md-editor',
                          click: function() {
                            instance.focus();
                          }
                        });
    
          // Prepare the editor
          if (this.$editor === null) {
            // Create the panel
            var editorHeader = $('<div/>', {
                                'class': 'md-header btn-toolbar'
                                });
    
            // Merge the main & additional button groups together
            var allBtnGroups = [];
            if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0]);
            if (options.additionalButtons.length > 0) {
              // iterate the additional button groups
              $.each(options.additionalButtons[0], function(idx, buttonGroup){
                
                // see if the group name of the addional group matches an existing group
                var matchingGroups = $.grep(allBtnGroups, function(allButtonGroup, allIdx){
                  return allButtonGroup.name === buttonGroup.name;
                });
    
                // if it matches add the addional buttons to that group, if not just add it to the all buttons group
                if(matchingGroups.length > 0) {
                  matchingGroups[0].data = matchingGroups[0].data.concat(buttonGroup.data);
                } else {              
                  allBtnGroups.push(options.additionalButtons[0][idx]);
                }
    
              });
            } 
    
            // Reduce and/or reorder the button groups
            if (options.reorderButtonGroups.length > 0) {
              allBtnGroups = allBtnGroups
                  .filter(function(btnGroup) {
                    return options.reorderButtonGroups.indexOf(btnGroup.name) > -1;
                  })
                  .sort(function(a, b) {
                    if (options.reorderButtonGroups.indexOf(a.name) < options.reorderButtonGroups.indexOf(b.name)) return -1;
                    if (options.reorderButtonGroups.indexOf(a.name) > options.reorderButtonGroups.indexOf(b.name)) return 1;
                    return 0;
                  });
            }
    
            // Build the buttons
            if (allBtnGroups.length > 0) {
              editorHeader = this.__buildButtons([allBtnGroups], editorHeader);
            }
    
            if (options.fullscreen.enable) {
              editorHeader.append('<div class="md-controls"><a class="md-control md-control-fullscreen" href="#"><span class="'+this.__getIcon(options.fullscreen.icons.fullscreenOn)+'"></span></a></div>').on('click', '.md-control-fullscreen', function(e) {
                  e.preventDefault();
                  instance.setFullscreen(true);
              });
            }
    
            editor.append(editorHeader);
    
            // Wrap the textarea
            if (container.is('textarea')) {
              container.before(editor);
              textarea = container;
              textarea.addClass('md-input');
              editor.append(textarea);
            } else {
              var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(),
                  currentContent = $.trim(rawContent);
    
              // This is some arbitrary content that could be edited
              textarea = $('<textarea/>', {
                           'class': 'md-input',
                           'val' : currentContent
                          });
    
              editor.append(textarea);
    
              // Save the editable
              editable.el = container;
              editable.type = container.prop('tagName').toLowerCase();
              editable.content = container.html();
    
              $(container[0].attributes).each(function(){
                editable.attrKeys.push(this.nodeName);
                editable.attrValues.push(this.nodeValue);
              });
    
              // Set editor to blocked the original container
              container.replaceWith(editor);
            }
    
            var editorFooter = $('<div/>', {
                               'class': 'md-footer'
                             }),
                createFooter = false,
                footer = '';
            // Create the footer if savable
            if (options.savable) {
              createFooter = true;
              var saveHandler = 'cmdSave';
    
              // Register handler and callback
              handler.push(saveHandler);
              callback.push(options.onSave);
    
              editorFooter.append('<button class="btn btn-success" data-provider="'
                                  + ns
                                  + '" data-handler="'
                                  + saveHandler
                                  + '"><i class="icon icon-white icon-ok"></i> '
                                  + this.__localize('Save')
                                  + '</button>');
    
    
            }
    
            footer = typeof options.footer === 'function' ? options.footer(this) : options.footer;
    
            if ($.trim(footer) !== '') {
              createFooter = true;
              editorFooter.append(footer);
            }
    
            if (createFooter) editor.append(editorFooter);
    
            // Set width
            if (options.width && options.width !== 'inherit') {
              if (jQuery.isNumeric(options.width)) {
                editor.css('display', 'table');
                textarea.css('width', options.width + 'px');
              } else {
                editor.addClass(options.width);
              }
            }
    
            // Set height
            if (options.height && options.height !== 'inherit') {
              if (jQuery.isNumeric(options.height)) {
                var height = options.height;
                if (editorHeader) height = Math.max(0, height - editorHeader.outerHeight());
                if (editorFooter) height = Math.max(0, height - editorFooter.outerHeight());
                textarea.css('height', height + 'px');
              } else {
                editor.addClass(options.height);
              }
            }
    
            // Reference
            this.$editor     = editor;
            this.$textarea   = textarea;
            this.$editable   = editable;
            this.$oldContent = this.getContent();
    
            this.__setListener();
    
            // Set editor attributes, data short-hand API and listener
            this.$editor.attr('id',(new Date()).getTime());
            this.$editor.on('click', '[data-provider="bootstrap-markdown"]', $.proxy(this.__handle, this));
    
            if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {
              this.$editor.addClass('md-editor-disabled');
              this.disableButtons('all');
            }
    
            if (this.eventSupported('keydown') && typeof jQuery.hotkeys === 'object') {
              editorHeader.find('[data-provider="bootstrap-markdown"]').each(function() {
                var $button = $(this),
                    hotkey = $button.attr('data-hotkey');
                if (hotkey.toLowerCase() !== '') {
                  textarea.bind('keydown', hotkey, function() {
                    $button.trigger('click');
                    return false;
                  });
                }
              });
            }
    
            if (options.initialstate === 'preview') {
              this.showPreview();
            } else if (options.initialstate === 'fullscreen' && options.fullscreen.enable) {
              this.setFullscreen(true);
            }
    
          } else {
            this.$editor.show();
          }
    
          if (options.autofocus) {
            this.$textarea.focus();
            this.$editor.addClass('active');
          }
    
          if (options.fullscreen.enable && options.fullscreen !== false) {
            this.$editor.append('<div class="md-fullscreen-controls">'
                            + '<a href="#" class="exit-fullscreen" title="Exit fullscreen"><span class="' + this.__getIcon(options.fullscreen.icons.fullscreenOff) + '">'
                            + '</span></a>'
                            + '</div>');
            this.$editor.on('click', '.exit-fullscreen', function(e) {
              e.preventDefault();
              instance.setFullscreen(false);
            });
          }
    
          // hide hidden buttons from options
          this.hideButtons(options.hiddenButtons);
    
          // disable disabled buttons from options
          this.disableButtons(options.disabledButtons);
    
          // Trigger the onShow hook
          options.onShow(this);
    
          return this;
        }
    
      , parseContent: function(val) {
          var content;
    
          // parse with supported markdown parser
          var val = val || this.$textarea.val();
    
          if (this.$options.parser) {
            content = this.$options.parser(val);
          } else if (typeof markdown == 'object') {
            content = markdown.toHTML(val);
          } else if (typeof marked == 'function') {
            content = marked(val);
          } else {
            content = val;
          }
    
          return content;
        }
    
      , showPreview: function() {
          var options = this.$options,
              container = this.$textarea,
              afterContainer = container.next(),
              replacementContainer = $('<div/>',{'class':'md-preview','data-provider':'markdown-preview'}),
              content,
              callbackContent;
    
          if (this.$isPreview == true) {
            // Avoid sequenced element creation on missused scenario
            // @see https://github.com/toopay/bootstrap-markdown/issues/170
            return this;
          }
          
          // Give flag that tell the editor enter preview mode
          this.$isPreview = true;
          // Disable all buttons
          this.disableButtons('all').enableButtons('cmdPreview');
    
          // Try to get the content from callback
          callbackContent = options.onPreview(this);
          // Set the content based from the callback content if string otherwise parse value from textarea
          content = typeof callbackContent == 'string' ? callbackContent : this.parseContent();
    
          // Build preview element
          replacementContainer.html(content);
    
          if (afterContainer && afterContainer.attr('class') == 'md-footer') {
            // If there is footer element, insert the preview container before it
            replacementContainer.insertBefore(afterContainer);
          } else {
            // Otherwise, just append it after textarea
            container.parent().append(replacementContainer);
          }
    
          // Set the preview element dimensions
          replacementContainer.css({
            width: container.outerWidth() + 'px',
            height: container.outerHeight() + 'px'
          });
    
          if (this.$options.resize) {
            replacementContainer.css('resize',this.$options.resize);
          }
    
          // Hide the last-active textarea
          container.hide();
    
          // Attach the editor instances
          replacementContainer.data('markdown',this);
    
          if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {
            this.$editor.addClass('md-editor-disabled');
            this.disableButtons('all');
          }
    
          return this;
        }
    
      , hidePreview: function() {
          // Give flag that tell the editor quit preview mode
          this.$isPreview = false;
    
          // Obtain the preview container
          var container = this.$editor.find('div[data-provider="markdown-preview"]');
    
          // Remove the preview container
          container.remove();
    
          // Enable all buttons
          this.enableButtons('all');
          // Disable configured disabled buttons
          this.disableButtons(this.$options.disabledButtons);
    
          // Back to the editor
          this.$textarea.show();
          this.__setListener();
    
          return this;
        }
    
      , isDirty: function() {
          return this.$oldContent != this.getContent();
        }
    
      , getContent: function() {
          return this.$textarea.val();
        }
    
      , setContent: function(content) {
          this.$textarea.val(content);
    
          return this;
        }
    
      , findSelection: function(chunk) {
        var content = this.getContent(), startChunkPosition;
    
        if (startChunkPosition = content.indexOf(chunk), startChunkPosition >= 0 && chunk.length > 0) {
          var oldSelection = this.getSelection(), selection;
    
          this.setSelection(startChunkPosition,startChunkPosition+chunk.length);
          selection = this.getSelection();
    
          this.setSelection(oldSelection.start,oldSelection.end);
    
          return selection;
        } else {
          return null;
        }
      }
    
      , getSelection: function() {
    
          var e = this.$textarea[0];
    
          return (
    
              ('selectionStart' in e && function() {
                  var l = e.selectionEnd - e.selectionStart;
                  return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) };
              }) ||
    
              /* browser not supported */
              function() {
                return null;
              }
    
          )();
    
        }
    
      , setSelection: function(start,end) {
    
          var e = this.$textarea[0];
    
          return (
    
              ('selectionStart' in e && function() {
                  e.selectionStart = start;
                  e.selectionEnd = end;
                  return;
              }) ||
    
              /* browser not supported */
              function() {
                return null;
              }
    
          )();
    
        }
    
      , replaceSelection: function(text) {
    
          var e = this.$textarea[0];
    
          return (
    
              ('selectionStart' in e && function() {
                  e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length);
                  // Set cursor to the last replacement end
                  e.selectionStart = e.value.length;
                  return this;
              }) ||
    
              /* browser not supported */
              function() {
                  e.value += text;
                  return jQuery(e);
              }
    
          )();
        }
    
      , getNextTab: function() {
          // Shift the nextTab
          if (this.$nextTab.length === 0) {
            return null;
          } else {
            var nextTab, tab = this.$nextTab.shift();
    
            if (typeof tab == 'function') {
              nextTab = tab();
            } else if (typeof tab == 'object' && tab.length > 0) {
              nextTab = tab;
            }
    
            return nextTab;
          }
        }
    
      , setNextTab: function(start,end) {
          // Push new selection into nextTab collections
          if (typeof start == 'string') {
            var that = this;
            this.$nextTab.push(function(){
              return that.findSelection(start);
            });
          } else if (typeof start == 'number' && typeof end == 'number') {
            var oldSelection = this.getSelection();
    
            this.setSelection(start,end);
            this.$nextTab.push(this.getSelection());
    
            this.setSelection(oldSelection.start,oldSelection.end);
          }
    
          return;
        }
    
      , __parseButtonNameParam: function (names) {
          return typeof names == 'string' ?
                          names.split(' ') :
                          names;
    
        }
    
      , enableButtons: function(name) {
          var buttons = this.__parseButtonNameParam(name),
            that = this;
    
          $.each(buttons, function(i, v) {
            that.__alterButtons(buttons[i], function (el) {
              el.removeAttr('disabled');
            });
          });
    
          return this;
        }
    
      , disableButtons: function(name) {
          var buttons = this.__parseButtonNameParam(name),
            that = this;
    
          $.each(buttons, function(i, v) {
            that.__alterButtons(buttons[i], function (el) {
              el.attr('disabled','disabled');
            });
          });
    
          return this;
        }
    
      , hideButtons: function(name) {
          var buttons = this.__parseButtonNameParam(name),
            that = this;
    
          $.each(buttons, function(i, v) {
            that.__alterButtons(buttons[i], function (el) {
              el.addClass('hidden');
            });
          });
    
          return this;
        }
    
      , showButtons: function(name) {
          var buttons = this.__parseButtonNameParam(name),
            that = this;
    
          $.each(buttons, function(i, v) {
            that.__alterButtons(buttons[i], function (el) {
              el.removeClass('hidden');
            });
          });
    
          return this;
        }
    
      , eventSupported: function(eventName) {
          var isSupported = eventName in this.$element;
          if (!isSupported) {
            this.$element.setAttribute(eventName, 'return;');
            isSupported = typeof this.$element[eventName] === 'function';
          }
          return isSupported;
        }
    
      , keyup: function (e) {
          var blocked = false;
          switch(e.keyCode) {
            case 40: // down arrow
            case 38: // up arrow
            case 16: // shift
            case 17: // ctrl
            case 18: // alt
              break;
    
            case 9: // tab
              var nextTab;
              if (nextTab = this.getNextTab(),nextTab !== null) {
                // Get the nextTab if exists
                var that = this;
                setTimeout(function(){
                  that.setSelection(nextTab.start,nextTab.end);
                },500);
    
                blocked = true;
              } else {
                // The next tab memory contains nothing...
                // check the cursor position to determine tab action
                var cursor = this.getSelection();
    
                if (cursor.start == cursor.end && cursor.end == this.getContent().length) {
                  // The cursor already reach the end of the content
                  blocked = false;
                } else {
                  // Put the cursor to the end
                  this.setSelection(this.getContent().length,this.getContent().length);
    
                  blocked = true;
                }
              }
    
              break;
    
            case 13: // enter
              blocked = false;
              break;
            case 27: // escape
              if (this.$isFullscreen) this.setFullscreen(false);
              blocked = false;
              break;
    
            default:
              blocked = false;
          }
    
          if (blocked) {
            e.stopPropagation();
            e.preventDefault();
          }
    
          this.$options.onChange(this);
        }
    
      , change: function(e) {
          this.$options.onChange(this);
          return this;
        }
      , select: function (e) {
          this.$options.onSelect(this);
          return this;
        }
      , focus: function (e) {
          var options = this.$options,
              isHideable = options.hideable,
              editor = this.$editor;
    
          editor.addClass('active');
    
          // Blur other markdown(s)
          $(document).find('.md-editor').each(function(){
            if ($(this).attr('id') !== editor.attr('id')) {
              var attachedMarkdown;
    
              if (attachedMarkdown = $(this).find('textarea').data('markdown'),
                  attachedMarkdown === null) {
                  attachedMarkdown = $(this).find('div[data-provider="markdown-preview"]').data('markdown');
              }
    
              if (attachedMarkdown) {
                attachedMarkdown.blur();
              }
            }
          });
    
          // Trigger the onFocus hook
          options.onFocus(this);
    
          return this;
        }
    
      , blur: function (e) {
          var options = this.$options,
              isHideable = options.hideable,
              editor = this.$editor,
              editable = this.$editable;
    
          if (editor.hasClass('active') || this.$element.parent().length === 0) {
            editor.removeClass('active');
    
            if (isHideable) {
              // Check for editable elements
              if (editable.el !== null) {
                // Build the original element
                var oldElement = $('<'+editable.type+'/>'),
                    content = this.getContent(),
                    currentContent = this.parseContent(content);
    
                $(editable.attrKeys).each(function(k,v) {
                  oldElement.attr(editable.attrKeys[k],editable.attrValues[k]);
                });
    
                // Get the editor content
                oldElement.html(currentContent);
    
                editor.replaceWith(oldElement);
              } else {
                editor.hide();
              }
            }
    
            // Trigger the onBlur hook
            options.onBlur(this);
          }
    
          return this;
        }
    
      };
    
     /* MARKDOWN PLUGIN DEFINITION
      * ========================== */
    
      var old = $.fn.markdown;
    
      $.fn.markdown = function (option) {
        return this.each(function () {
          var $this = $(this)
            , data = $this.data('markdown')
            , options = typeof option == 'object' && option;
          if (!data) $this.data('markdown', (data = new Markdown(this, options)))
        })
      };
    
      $.fn.markdown.messages = {};
    
      $.fn.markdown.defaults = {
        /* Editor Properties */
        autofocus: false,
        hideable: false,
        savable: false,
        width: 'inherit',
        height: 'inherit',
        resize: 'none',
        iconlibrary: 'glyph',
        language: 'en',
        initialstate: 'editor',
        parser: null,
    
        /* Buttons Properties */
        buttons: [
          [{
            name: 'groupFont',
            data: [{
              name: 'cmdBold',
              hotkey: 'Ctrl+B',
              title: 'Bold',
              icon: { glyph: 'glyphicon glyphicon-bold', fa: 'fa fa-bold', 'fa-3': 'icon-bold' },
              callback: function(e){
                // Give/remove ** surround the selection
                var chunk, cursor, selected = e.getSelection(), content = e.getContent();
    
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('strong text');
                } else {
                  chunk = selected.text;
                }
    
                // transform selection and set the cursor into chunked text
                if (content.substr(selected.start-2,2) === '**'
                    && content.substr(selected.end,2) === '**' ) {
                  e.setSelection(selected.start-2,selected.end+2);
                  e.replaceSelection(chunk);
                  cursor = selected.start-2;
                } else {
                  e.replaceSelection('**'+chunk+'**');
                  cursor = selected.start+2;
                }
    
                // Set the cursor
                e.setSelection(cursor,cursor+chunk.length);
              }
            },{
              name: 'cmdItalic',
              title: 'Italic',
              hotkey: 'Ctrl+I',
              icon: { glyph: 'glyphicon glyphicon-italic', fa: 'fa fa-italic', 'fa-3': 'icon-italic' },
              callback: function(e){
                // Give/remove * surround the selection
                var chunk, cursor, selected = e.getSelection(), content = e.getContent();
    
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('emphasized text');
                } else {
                  chunk = selected.text;
                }
    
                // transform selection and set the cursor into chunked text
                if (content.substr(selected.start-1,1) === '_'
                    && content.substr(selected.end,1) === '_' ) {
                  e.setSelection(selected.start-1,selected.end+1);
                  e.replaceSelection(chunk);
                  cursor = selected.start-1;
                } else {
                  e.replaceSelection('_'+chunk+'_');
                  cursor = selected.start+1;
                }
    
                // Set the cursor
                e.setSelection(cursor,cursor+chunk.length);
              }
            },{
              name: 'cmdHeading',
              title: 'Heading',
              hotkey: 'Ctrl+H',
              icon: { glyph: 'glyphicon glyphicon-header', fa: 'fa fa-header', 'fa-3': 'icon-font' },
              callback: function(e){
                // Append/remove ### surround the selection
                var chunk, cursor, selected = e.getSelection(), content = e.getContent(), pointer, prevChar;
    
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('heading text');
                } else {
                  chunk = selected.text + '\n';
                }
    
                // transform selection and set the cursor into chunked text
                if ((pointer = 4, content.substr(selected.start-pointer,pointer) === '### ')
                    || (pointer = 3, content.substr(selected.start-pointer,pointer) === '###')) {
                  e.setSelection(selected.start-pointer,selected.end);
                  e.replaceSelection(chunk);
                  cursor = selected.start-pointer;
                } else if (selected.start > 0 && (prevChar = content.substr(selected.start-1,1), !!prevChar && prevChar != '\n')) {
                  e.replaceSelection('\n\n### '+chunk);
                  cursor = selected.start+6;
                } else {
                  // Empty string before element
                  e.replaceSelection('### '+chunk);
                  cursor = selected.start+4;
                }
    
                // Set the cursor
                e.setSelection(cursor,cursor+chunk.length);
              }
            }]
          },{
            name: 'groupLink',
            data: [{
              name: 'cmdUrl',
              title: 'URL/Link',
              hotkey: 'Ctrl+L',
              icon: { glyph: 'glyphicon glyphicon-link', fa: 'fa fa-link', 'fa-3': 'icon-link' },
              callback: function(e){
                // Give [] surround the selection and prepend the link
                var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;
    
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('enter link description here');
                } else {
                  chunk = selected.text;
                }
    
                link = prompt(e.__localize('Insert Hyperlink'),'http://');
    
                var urlRegex = new RegExp('^((http|https)://|(mailto:)|(//))[a-z0-9]', 'i');
                if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
                  var sanitizedLink = $('<div>'+link+'</div>').text();
    
                  // transform selection and set the cursor into chunked text
                  e.replaceSelection('['+chunk+']('+sanitizedLink+')');
                  cursor = selected.start+1;
    
                  // Set the cursor
                  e.setSelection(cursor,cursor+chunk.length);
                }
              }
            },{
              name: 'cmdImage',
              title: 'Image',
              hotkey: 'Ctrl+G',
              icon: { glyph: 'glyphicon glyphicon-picture', fa: 'fa fa-picture-o', 'fa-3': 'icon-picture' },
              callback: function(e){
                // Give ![] surround the selection and prepend the image link
                var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;
    
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('enter image description here');
                } else {
                  chunk = selected.text;
                }
    
                link = prompt(e.__localize('Insert Image Hyperlink'),'http://');
    
                var urlRegex = new RegExp('^((http|https)://|(//))[a-z0-9]', 'i');
                if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
                  var sanitizedLink = $('<div>'+link+'</div>').text();
    
                  // transform selection and set the cursor into chunked text
                  e.replaceSelection('!['+chunk+']('+sanitizedLink+' "'+e.__localize('enter image title here')+'")');
                  cursor = selected.start+2;
    
                  // Set the next tab
                  e.setNextTab(e.__localize('enter image title here'));
    
                  // Set the cursor
                  e.setSelection(cursor,cursor+chunk.length);
                }
              }
            }]
          },{
            name: 'groupMisc',
            data: [{
              name: 'cmdList',
              hotkey: 'Ctrl+U',
              title: 'Unordered List',
              icon: { glyph: 'glyphicon glyphicon-list', fa: 'fa fa-list', 'fa-3': 'icon-list-ul' },
              callback: function(e){
                // Prepend/Give - surround the selection
                var chunk, cursor, selected = e.getSelection(), content = e.getContent();
    
                // transform selection and set the cursor into chunked text
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('list text here');
    
                  e.replaceSelection('- '+chunk);
                  // Set the cursor
                  cursor = selected.start+2;
                } else {
                  if (selected.text.indexOf('\n') < 0) {
                    chunk = selected.text;
    
                    e.replaceSelection('- '+chunk);
    
                    // Set the cursor
                    cursor = selected.start+2;
                  } else {
                    var list = [];
    
                    list = selected.text.split('\n');
                    chunk = list[0];
    
                    $.each(list,function(k,v) {
                      list[k] = '- '+v;
                    });
    
                    e.replaceSelection('\n\n'+list.join('\n'));
    
                    // Set the cursor
                    cursor = selected.start+4;
                  }
                }
    
                // Set the cursor
                e.setSelection(cursor,cursor+chunk.length);
              }
            },
            {
              name: 'cmdListO',
              hotkey: 'Ctrl+O',
              title: 'Ordered List',
              icon: { glyph: 'glyphicon glyphicon-th-list', fa: 'fa fa-list-ol', 'fa-3': 'icon-list-ol' },
              callback: function(e) {
    
                // Prepend/Give - surround the selection
                var chunk, cursor, selected = e.getSelection(), content = e.getContent();
    
                // transform selection and set the cursor into chunked text
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('list text here');
                  e.replaceSelection('1. '+chunk);
                  // Set the cursor
                  cursor = selected.start+3;
                } else {
                  if (selected.text.indexOf('\n') < 0) {
                    chunk = selected.text;
    
                    e.replaceSelection('1. '+chunk);
    
                    // Set the cursor
                    cursor = selected.start+3;
                  } else {
                    var list = [];
    
                    list = selected.text.split('\n');
                    chunk = list[0];
    
                    $.each(list,function(k,v) {
                      list[k] = '1. '+v;
                    });
    
                    e.replaceSelection('\n\n'+list.join('\n'));
    
                    // Set the cursor
                    cursor = selected.start+5;
                  }
                }
    
                // Set the cursor
                e.setSelection(cursor,cursor+chunk.length);
              }
            },
            {
              name: 'cmdCode',
              hotkey: 'Ctrl+K',
              title: 'Code',
              icon: { glyph: 'glyphicon glyphicon-asterisk', fa: 'fa fa-code', 'fa-3': 'icon-code' },
              callback: function(e) {
                // Give/remove ** surround the selection
                var chunk, cursor, selected = e.getSelection(), content = e.getContent();
    
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('code text here');
                } else {
                  chunk = selected.text;
                }
    
                // transform selection and set the cursor into chunked text
                if (content.substr(selected.start-4,4) === '```\n'
                    && content.substr(selected.end,4) === '\n```') {
                  e.setSelection(selected.start-4, selected.end+4);
                  e.replaceSelection(chunk);
                  cursor = selected.start-4;
                } else if (content.substr(selected.start-1,1) === '`'
                    && content.substr(selected.end,1) === '`') {
                  e.setSelection(selected.start-1,selected.end+1);
                  e.replaceSelection(chunk);
                  cursor = selected.start-1;
                } else if (content.indexOf('\n') > -1) {
                  e.replaceSelection('```\n'+chunk+'\n```');
                  cursor = selected.start+4;
                } else {
                  e.replaceSelection('`'+chunk+'`');
                  cursor = selected.start+1;
                }
    
                // Set the cursor
                e.setSelection(cursor,cursor+chunk.length);
              }
            },
            {
              name: 'cmdQuote',
              hotkey: 'Ctrl+Q',
              title: 'Quote',
              icon: { glyph: 'glyphicon glyphicon-comment', fa: 'fa fa-quote-left', 'fa-3': 'icon-quote-left' },
              callback: function(e) {
                // Prepend/Give - surround the selection
                var chunk, cursor, selected = e.getSelection(), content = e.getContent();
    
                // transform selection and set the cursor into chunked text
                if (selected.length === 0) {
                  // Give extra word
                  chunk = e.__localize('quote here');
    
                  e.replaceSelection('> '+chunk);
    
                  // Set the cursor
                  cursor = selected.start+2;
                } else {
                  if (selected.text.indexOf('\n') < 0) {
                    chunk = selected.text;
    
                    e.replaceSelection('> '+chunk);
    
                    // Set the cursor
                    cursor = selected.start+2;
                  } else {
                    var list = [];
    
                    list = selected.text.split('\n');
                    chunk = list[0];
    
                    $.each(list,function(k,v) {
                      list[k] = '> '+v;
                    });
    
                    e.replaceSelection('\n\n'+list.join('\n'));
    
                    // Set the cursor
                    cursor = selected.start+4;
                  }
                }
    
                // Set the cursor
                e.setSelection(cursor,cursor+chunk.length);
              }
            }]
          },{
            name: 'groupUtil',
            data: [{
              name: 'cmdPreview',
              toggle: true,
              hotkey: 'Ctrl+P',
              title: 'Preview',
              btnText: 'Preview',
              btnClass: 'btn btn-primary btn-sm',
              icon: { glyph: 'glyphicon glyphicon-search', fa: 'fa fa-search', 'fa-3': 'icon-search' },
              callback: function(e){
                // Check the preview mode and toggle based on this flag
                var isPreview = e.$isPreview,content;
    
                if (isPreview === false) {
                  // Give flag that tell the editor enter preview mode
                  e.showPreview();
                } else {
                  e.hidePreview();
                }
              }
            }]
          }]
        ],
        additionalButtons:[], // Place to hook more buttons by code
        reorderButtonGroups:[],
        hiddenButtons:[], // Default hidden buttons
        disabledButtons:[], // Default disabled buttons
        footer: '',
        fullscreen: {
          enable: true,
          icons: {
            fullscreenOn: {
              fa: 'fa fa-expand',
              glyph: 'glyphicon glyphicon-fullscreen',
              'fa-3': 'icon-resize-full'
            },
            fullscreenOff: {
              fa: 'fa fa-compress',
              glyph: 'glyphicon glyphicon-fullscreen',
              'fa-3': 'icon-resize-small'
            }
          }
        },
    
        /* Events hook */
        onShow: function (e) {},
        onPreview: function (e) {},
        onSave: function (e) {},
        onBlur: function (e) {},
        onFocus: function (e) {},
        onChange: function(e) {},
        onFullscreen: function(e) {},
        onSelect: function (e) {}
      };
    
      $.fn.markdown.Constructor = Markdown;
    
    
     /* MARKDOWN NO CONFLICT
      * ==================== */
    
      $.fn.markdown.noConflict = function () {
        $.fn.markdown = old;
        return this;
      };
    
      /* MARKDOWN GLOBAL FUNCTION & DATA-API
      * ==================================== */
      var initMarkdown = function(el) {
        var $this = el;
    
        if ($this.data('markdown')) {
          $this.data('markdown').showEditor();
          return;
        }
    
        $this.markdown()
      };
    
      var blurNonFocused = function(e) {
        var $activeElement = $(document.activeElement);
    
        // Blur event
        $(document).find('.md-editor').each(function(){
          var $this            = $(this),
              focused          = $activeElement.closest('.md-editor')[0] === this,
              attachedMarkdown = $this.find('textarea').data('markdown') ||
                                 $this.find('div[data-provider="markdown-preview"]').data('markdown');
    
          if (attachedMarkdown && !focused) {
            attachedMarkdown.blur();
          }
        })
      };
    
      $(document)
        .on('click.markdown.data-api', '[data-provide="markdown-editable"]', function (e) {
          initMarkdown($(this));
          e.preventDefault();
        })
        .on('click focusin', function (e) {
          blurNonFocused(e);
        })
        .ready(function(){
          $('textarea[data-provide="markdown"]').each(function(){
            initMarkdown($(this));
          })
        });
    
    }));
    
    /*
     * Arabic translation for bootstrap-markdown
     * George Ajam <george.ejaam@gmail.com>
     */
    (function ($) {
      $.fn.markdown.messages.nl = {
        'Bold': "غامق",
        'Italic': "مائل",
        'Heading': "عنوان",
        'URL/Link': "URL/رابط",
        'Image': "صورة",
        'List': "قائمة",
        'Preview': "استعراض",
        'strong text': "نص غامق",
        'emphasized text': "نص هام",
        'heading text': "العنوان",
        'enter link description here': "ادخل وصف الرابط هنا",
        'Insert Hyperlink': "ادخل الرابط هنا",
        'enter image description here': "ادخل وصف الصورة هنا",
        'Insert Image Hyperlink': "ادخل رابط الصورة هنا",
        'enter image title here': "ادخل عنوان الصورة هنا",
        'list text here': "اكتب النص هنا"
      };
    }(jQuery));
    
    /**
     * Czech translation for bootstrap-markdown
     * Vít Kabele <vit@kabele.me>
     */
    (function ($) {
      $.fn.markdown.messages.cs = {
        'Bold': "Tučně",
        'Italic': "Kurzíva",
        'Heading': "Nadpis",
        'URL/Link': "URL/Odkaz",
        'Image': "Obrázek",
        'Unordered List': "Seznam",
        'Ordered List': "Seřazený seznam",
        'Code': "Úsek kódu",
        'Quote': "Citace",
        'Preview': "Náhled",
        'strong text': "tučný text",
        'emphasized text': "zdůrazněný text",
        'heading text': "text nadpisu",
        'enter link description here': "sem vlož popis odkazu",
        'Insert Hyperlink': "Vložit Hyperlink",
        'enter image description here': "sem vlož popis obrázku",
        'Insert Image Hyperlink': "Vlož adresu obrázku",
        'enter image title here': "sem vlož popis obrázku",
        'list text here': "položka seznamu"
      };
    }(jQuery));
    
    /**
     * Danish translation for bootstrap-markdown
     * Dan Storm <storm@catalystcode.net>
     */
    (function ($) {
      $.fn.markdown.messages.nb = {
        'Bold': 'Fed',
        'Italic': 'Kursiv',
        'Heading': 'Overskrift',
        'URL/Link': 'URL/Link',
        'Image': 'Billede',
        'List': 'Liste',
        'Preview': 'Forhåndsvisning',
        'strong text': 'stærk tekst',
        'emphasized text': 'fremhævet tekst',
        'heading text': 'overskrift tekst',
        'enter link description here': 'Skriv link beskrivelse her',
        'Insert Hyperlink': 'Indsæt link',
        'enter image description here': 'Indsæt billede beskrivelse her',
        'Insert Image Hyperlink': 'Indsæt billede link',
        'enter image title here': 'Indsæt billede titel',
        'list text here': 'Indsæt liste tekst her',
        'quote here': 'Indsæt citat her',
        'code text here': 'Indsæt kode her'
      };
    }(jQuery));
    
    /**
     * German translation for bootstrap-markdown
     * Tobias Nitsche <tobias-nitsche@gmx.net>
     */
    (function ($) {
      $.fn.markdown.messages.de = {
        'Bold': "Fett",
        'Italic': "Kursiv",
        'Heading': "Überschrift",
        'URL/Link': "Link hinzufügen",
        'Image': "Bild hinzufügen",
        'Unordered List': "Unnummerierte Liste",
        'Ordered List': "Nummerierte Liste",
        'Code': "Quelltext",
        'Quote': "Zitat",
        'Preview': "Vorschau",
        'strong text': "Sehr betonter Text",
        'emphasized text': "Betonter Text",
        'heading text': "Überschrift Text",
        'enter link description here': "Linkbeschreibung",
        'Insert Hyperlink': "URL",
        'enter image description here': "Bildbeschreibung",
        'Insert Image Hyperlink': "Bild-URL",
        'enter image title here': "Titel des Bildes",
        'list text here': "Aufzählungs-Text"
      };
    }(jQuery));
    
    /**
     * Spanish translation for bootstrap-markdown
     * by Leandro Poblet <leandrodrhouse@gmail.com>
     */
    ;(function($){
      $.fn.markdown.messages['es'] = {
        'Bold': "Negrita",
        'Italic': "Itálica",
        'Heading': "Título",
        'URL/Link': "Inserte un link",
        'Image': "Inserte una imagen",
        'List': "Lista de items",
        'Preview': "Previsualizar",
        'strong text': "texto importante",
        'emphasized text': "texto con énfasis",
        'heading text': "texto titular",
        'enter link description here': "descripción del link",
        'Insert Hyperlink': "Inserte un hipervínculo",
        'enter image description here': "descripción de la imagen",
        'Insert Image Hyperlink': "Inserte una imagen con un hipervínculo",
        'enter image title here': "Inserte una imagen con título",
        'list text here': "lista con texto"
      };
    }(jQuery));
    
    /**
     * Persian(Farsi) translation for bootstrap-markdown
     * Sajad Dehshiri <Pelakweb.ir>
     */
    (function ($) {
      $.fn.markdown.messages.fa = {
        'Bold': "توپر",
        'Italic': "مورب",
        'Heading': "عنوان",
        'URL/Link': "پیوند",
        'Image': "تصویر",
        'List': "فهرست",
        'Preview': "پیش نمایش",
        'strong text': "متن ضخیم",
        'emphasized text': "نوشته تاکیدی",
        'heading text': "عنوان",
        'enter link description here': "توضیحات پیوند را بنویسید.",
        'Insert Hyperlink': "پیوند را درج نمایید:",
        'enter image description here': "توضیحی برای تصوی بنویسید.",
        'Insert Image Hyperlink': "آدرس تصویر را بنویسید.",
        'enter image title here': "عنوان تصویر را اینجا بنویسید",
        'list text here': "محل متن فهرست"
      };
    }(jQuery));
    
    /**
     * French translation for bootstrap-markdown
     * Benoît Bourgeois <bierdok@gmail.com>
     */
    (function ($) {
      $.fn.markdown.messages.fr = {
        'Bold': "Gras",
        'Italic': "Italique",
        'Heading': "Titre",
        'URL/Link': "Insérer un lien HTTP",
        'Image': "Insérer une image",
        'List': "Liste à puces",
        'Preview': "Prévisualiser",
        'strong text': "texte important",
        'emphasized text': "texte en italique",
        'heading text': "texte d'entête",
        'enter link description here': "entrez la description du lien ici",
        'Insert Hyperlink': "Insérez le lien hypertexte",
        'enter image description here': "entrez la description de l'image ici",
        'Insert Image Hyperlink': "Insérez le lien hypertexte de l'image",
        'enter image title here': "entrez le titre de l'image ici",
        'list text here': "texte à puce ici",
        'Save': "Sauvegarder",
        'Ordered List': "Liste ordonnée",
        'Unordered List': "Liste désordonnée",
        'Quote': "Citation",
        'quote here': "Votre citation",
        'Code': "Code",
        'code text here': "écrire du code ici"
      };
    }(jQuery));
    
    /**
     * Japanese translation for bootstrap-markdown
     * Kenta Murakami <kntmrkm@gmail.com>
     */
    (function ($) {
      $.fn.markdown.messages['ja'] = {
        'Bold': "太字",
        'Italic': "斜体",
        'Heading': "見出し",
        'URL/Link': "リンク",
        'Image': "画像",
        'Unordered List': "リスト",
        'Ordered List': "数字リスト",
        'Code': "コード",
        'Quote': "引用",
        'Preview': "プレビュー",
        'strong text': "太字",
        'emphasized text': "強調",
        'heading text': "見出し",
        'enter link description here': "リンク説明",
        'Insert Hyperlink': "リンク挿入",
        'enter image description here': "画像説明",
        'Insert Image Hyperlink': "画像挿入",
        'enter image title here': "画像タイトル",
        'list text here': "リスト挿入",
        'code text here': "コード",
        'quote here': "引用挿入"
      };
    }(jQuery));
    
    /**
     + * Korean translation for bootstrap-markdown
     + * WoongBi Kim <ssinss@gmail.com>
     + */
    ;(function($){
      $.fn.markdown.messages['kr'] = {
        'Bold': "진하게",
        'Italic': "이탤릭체",
        'Heading': "머리글",
        'URL/Link': "링크주소",
        'Image': "이미지",
        'List': "리스트",
        'Preview': "미리보기",
        'strong text': "강한 강조 텍스트",
        'emphasized text': "강조 텍스트",
        'heading text': "머리글 텍스트",
        'enter link description here': "여기에 링크의 설명을 적으세요",
        'Insert Hyperlink': "하이퍼링크 삽입",
        'enter image description here': "여기세 이미지 설명을 적으세요",
        'Insert Image Hyperlink': "이미지 링크 삽입",
        'enter image title here': "여기에 이미지 제목을 적으세요",
        'list text here': "리스트 텍스트"
      };
    }(jQuery));
    
    /**
     * Norwegian bokmål translation for bootstrap-markdown
     * Tobias Bohwalli <hi@futhr.io>
     */
    (function ($) {
      $.fn.markdown.messages.nb = {
        'Bold': 'Fet',
        'Italic': 'Kursiv',
        'Heading': 'Overskrift',
        'URL/Link': 'URL/Lenke',
        'Image': 'Bilde',
        'List': 'Liste',
        'Preview': 'Forhåndsvisning',
        'strong text': 'sterk tekst',
        'emphasized text': 'streket tekst',
        'heading text': 'overskriften tekst',
        'enter link description here': 'Skriv linken beskrivelse her',
        'Insert Hyperlink': 'Sett inn lenke',
        'enter image description here': 'Angi bildebeskrivelse her',
        'Insert Image Hyperlink': 'Sett inn lenke for bilde',
        'enter image title here': 'Angi bildetittel her',
        'list text here': 'liste tekst her'
      };
    }(jQuery));
    
    /**
     * Dutch translation for bootstrap-markdown
     * Jeroen Thora <jeroenthora@gmail.com>
     */
    (function ($) {
      $.fn.markdown.messages.nl = {
        'Bold': "Vet",
        'Italic': "Cursief",
        'Heading': "Titel",
        'URL/Link': "URL/Link",
        'Image': "Afbeelding",
        'List': "Lijst",
        'Preview': "Voorbeeld",
        'strong text': "vet gedrukte tekst",
        'emphasized text': "schuin gedrukte tekst",
        'heading text': "Titel",
        'enter link description here': "Voer een link beschrijving in",
        'Insert Hyperlink': "Voer een http link in",
        'enter image description here': "Voer een afbeelding beschrijving in",
        'Insert Image Hyperlink': "Voer een afbeelding link in",
        'enter image title here': "Voer de afbeelding titel in",
        'list text here': "lijst item"
      };
    }(jQuery));
    
    /**
     * Polish translation for bootstrap-markdown
     * Marek Kaput
     */
    (function ($) {
      $.fn.markdown.messages.pl = {
        'Bold': "Pogrubienie",
        'Italic': "Kursywa",
        'Heading': "Nagłówek",
        'URL/Link': "Wstaw link",
        'Image': "Wstaw obrazek",
        'Unordered List': "Lista punktowana",
        'Ordered List': "Lista numerowana",
        'Code': "Kod źródłowy",
        'Quote': "Cytat",
        'Preview': "Podgląd",
        'strong text': "pogrubiony tekst",
        'emphasized text': "pochylony tekst",
        'heading text': "nagłówek",
        'enter link description here': "opis linka",
        'Insert Hyperlink': "Wstaw link",
        'enter image description here': "opis obrazka",
        'Insert Image Hyperlink': "Wstaw obrazek",
        'enter image title here': "tytuł obrazka",
        'list text here': "lista"
      };
    }(jQuery));
    
    /**
     * Slovenian translation for bootstrap-markdown
     * Davor Padovan <davor.padovan@gmail.com>
     */
    (function ($) {
      $.fn.markdown.messages.sl = {
        'Bold': "Odebeljeno",
        'Italic': "Poševno",
        'Heading': "Naslov",
        'URL/Link': "Povezava",
        'Image': "Slika",
        'Unordered List': "Neurejen seznam",
        'Ordered List': "Urejen seznam",
        'Code': "Koda",
        'Quote': "Citat",
        'Preview': "Predogled",
        'strong text': "odebeljeno besedilo",
        'emphasized text': "poševno besedilo",
        'heading text': "naslov",
        'enter link description here': "opis povezave",
        'Insert Hyperlink': "Vstavi povezavo",
        'enter image description here': "opis slike",
        'Insert Image Hyperlink': "Vstavi povezavo do slike",
        'enter image title here': "naslov slike",
        'list text here': "seznam"
      };
    }(jQuery));
    
    /**
     * Swedish translation for bootstrap-markdown
     * Tobias Bohwalli <hi@futhr.io>
     */
    (function ($) {
      $.fn.markdown.messages.sv = {
        'Bold': 'Fet',
        'Italic': 'Kursiv',
        'Heading': 'Rubrik',
        'URL/Link': 'URL/Länk',
        'Image': 'Bild',
        'List': 'Lista',
        'Preview': 'Förhandsgranska',
        'strong text': 'fet text',
        'emphasized text': 'överstruken text',
        'heading text': 'Rubrik',
        'enter link description here': 'Ange länk beskrivning här',
        'Insert Hyperlink': 'Sätt in länk',
        'enter image description here': 'Ange bild beskrivning här',
        'Insert Image Hyperlink': 'Sätt in länk för bild',
        'enter image title here': 'Ange bild rubrik här',
        'list text here': 'list text'
      };
    }(jQuery));
    
    /**
     * Turkish translation for bootstrap-markdown
     * Serkan Algur <info@wpadami.com>
     */
    (function ($) {
      $.fn.markdown.messages.tr = {
        'Bold': "Kalın",
        'Italic': "İtalik",
        'Heading': "Başlık",
        'URL/Link': "Link ekle",
        'Image': "Resim ekle",
        'List': "Liste Oluşturun",
        'Preview': "Önizleme",
        'strong text': "kalın yazı",
        'emphasized text': "italik yazı",
        'heading text': "Başlık Yazısı",
        'enter link description here': "Link açıklamasını buraya girin",
        'Insert Hyperlink': "İnternet adresi girin",
        'enter image description here': "resim açıklamasını buraya ekleyin",
        'Insert Image Hyperlink': "Resim linkini ekleyin",
        'enter image title here': "resim başlığını buraya ekleyin",
        'list text here': "liste yazısı",
        'Save' : "Kaydet",
        'Ordered List' : "Numaralı Liste",
        'Unordered List' : "Madde imli liste",
        'Quote' : "Alıntı",
        'quote here' : "alıntıyı buraya ekleyin",
        'Code' : "Kod",
        'code text here' : "kodu buraya ekleyin"
      };
    }(jQuery));
    
    /**
     * Chinese translation for bootstrap-markdown
     * benhaile <denghaier@163.com>
     */
    (function ($) {
      $.fn.markdown.messages.zh = {
        'Bold': "粗体",
        'Italic': "斜体",
        'Heading': "标题",
        'URL/Link': "链接",
        'Image': "图片",
        'List': "列表",
        'Unordered List': "无序列表",
        'Ordered List': "有序列表",
        'Code': "代码",
        'Quote': "引用",
        'Preview': "预览",
        'strong text': "粗体",
        'emphasized text': "强调",
        'heading text': "标题",
        'enter link description here': "输入链接说明",
        'Insert Hyperlink': "URL地址",
        'enter image description here': "输入图片说明",
        'Insert Image Hyperlink': "图片URL地址",
        'enter image title here': "在这里输入图片标题",
        'list text here': "这里是列表文本",
        'code text here': "这里输入代码",
        'quote here': "这里输入引用文本"
    
    
      };
    }(jQuery));
    
    (function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):(global=global||self,global.Mustache=factory())})(this,function(){"use strict";var objectToString=Object.prototype.toString;var isArray=Array.isArray||function isArrayPolyfill(object){return objectToString.call(object)==="[object Array]"};function isFunction(object){return typeof object==="function"}function typeStr(obj){return isArray(obj)?"array":typeof obj}function escapeRegExp(string){return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function hasProperty(obj,propName){return obj!=null&&typeof obj==="object"&&propName in obj}function primitiveHasOwnProperty(primitive,propName){return primitive!=null&&typeof primitive!=="object"&&primitive.hasOwnProperty&&primitive.hasOwnProperty(propName)}var regExpTest=RegExp.prototype.test;function testRegExp(re,string){return regExpTest.call(re,string)}var nonSpaceRe=/\S/;function isWhitespace(string){return!testRegExp(nonSpaceRe,string)}var entityMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};function escapeHtml(string){return String(string).replace(/[&<>"'`=\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var lineHasNonSpace=false;var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;var indentation="";var tagIndex=0;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i<valueLength;++i){chr=value.charAt(i);if(isWhitespace(chr)){spaces.push(tokens.length);indentation+=chr}else{nonSpace=true;lineHasNonSpace=true;indentation+=" "}tokens.push(["text",chr,start,start+1]);start+=1;if(chr==="\n"){stripSpace();indentation="";tagIndex=0;lineHasNonSpace=false}}}if(!scanner.scan(openingTagRe))break;hasTag=true;type=scanner.scan(tagRe)||"name";scanner.scan(whiteRe);if(type==="="){value=scanner.scanUntil(equalsRe);scanner.scan(equalsRe);scanner.scanUntil(closingTagRe)}else if(type==="{"){value=scanner.scanUntil(closingCurlyRe);scanner.scan(curlyRe);scanner.scanUntil(closingTagRe);type="&"}else{value=scanner.scanUntil(closingTagRe)}if(!scanner.scan(closingTagRe))throw new Error("Unclosed tag at "+scanner.pos);if(type==">"){token=[type,value,start,scanner.pos,indentation,tagIndex,lineHasNonSpace]}else{token=[type,value,start,scanner.pos]}tagIndex++;tokens.push(token);if(type==="#"||type==="^"){sections.push(token)}else if(type==="/"){openSection=sections.pop();if(!openSection)throw new Error('Unopened section "'+value+'" at '+start);if(openSection[1]!==value)throw new Error('Unclosed section "'+openSection[1]+'" at '+start)}else if(type==="name"||type==="{"||type==="&"){nonSpace=true}else if(type==="="){compileTags(value)}}stripSpace();openSection=sections.pop();if(openSection)throw new Error('Unclosed section "'+openSection[1]+'" at '+scanner.pos);return nestTokens(squashTokens(tokens))}function squashTokens(tokens){var squashedTokens=[];var token,lastToken;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];if(token){if(token[0]==="text"&&lastToken&&lastToken[0]==="text"){lastToken[1]+=token[1];lastToken[3]=token[3]}else{squashedTokens.push(token);lastToken=token}}}return squashedTokens}function nestTokens(tokens){var nestedTokens=[];var collector=nestedTokens;var sections=[];var token,section;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];switch(token[0]){case"#":case"^":collector.push(token);sections.push(token);collector=token[4]=[];break;case"/":section=sections.pop();section[5]=token[2];collector=sections.length>0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,intermediateValue,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){intermediateValue=context.view;names=name.split(".");index=0;while(intermediateValue!=null&&index<names.length){if(index===names.length-1)lookupHit=hasProperty(intermediateValue,names[index])||primitiveHasOwnProperty(intermediateValue,names[index]);intermediateValue=intermediateValue[names[index++]]}}else{intermediateValue=context.view[name];lookupHit=hasProperty(context.view,name)}if(lookupHit){value=intermediateValue;break}context=context.parent}cache[name]=value}if(isFunction(value))value=value.call(this.view);return value};function Writer(){this.templateCache={_cache:{},set:function set(key,value){this._cache[key]=value},get:function get(key){return this._cache[key]},clear:function clear(){this._cache={}}}}Writer.prototype.clearCache=function clearCache(){if(typeof this.templateCache!=="undefined"){this.templateCache.clear()}};Writer.prototype.parse=function parse(template,tags){var cache=this.templateCache;var cacheKey=template+":"+(tags||mustache.tags).join(":");var isCacheEnabled=typeof cache!=="undefined";var tokens=isCacheEnabled?cache.get(cacheKey):undefined;if(tokens==undefined){tokens=parseTemplate(template,tags);isCacheEnabled&&cache.set(cacheKey,tokens)}return tokens};Writer.prototype.render=function render(template,view,partials,config){var tags=this.getConfigTags(config);var tokens=this.parse(template,tags);var context=view instanceof Context?view:new Context(view,undefined);return this.renderTokens(tokens,context,partials,template,config)};Writer.prototype.renderTokens=function renderTokens(tokens,context,partials,originalTemplate,config){var buffer="";var token,symbol,value;for(var i=0,numTokens=tokens.length;i<numTokens;++i){value=undefined;token=tokens[i];symbol=token[0];if(symbol==="#")value=this.renderSection(token,context,partials,originalTemplate,config);else if(symbol==="^")value=this.renderInverted(token,context,partials,originalTemplate,config);else if(symbol===">")value=this.renderPartial(token,context,partials,config);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context,config);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate,config){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials,config)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j<valueLength;++j){buffer+=this.renderTokens(token[4],context.push(value[j]),partials,originalTemplate,config)}}else if(typeof value==="object"||typeof value==="string"||typeof value==="number"){buffer+=this.renderTokens(token[4],context.push(value),partials,originalTemplate,config)}else if(isFunction(value)){if(typeof originalTemplate!=="string")throw new Error("Cannot use higher-order sections without the original template");value=value.call(context.view,originalTemplate.slice(token[3],token[5]),subRender);if(value!=null)buffer+=value}else{buffer+=this.renderTokens(token[4],context,partials,originalTemplate,config)}return buffer};Writer.prototype.renderInverted=function renderInverted(token,context,partials,originalTemplate,config){var value=context.lookup(token[1]);if(!value||isArray(value)&&value.length===0)return this.renderTokens(token[4],context,partials,originalTemplate,config)};Writer.prototype.indentPartial=function indentPartial(partial,indentation,lineHasNonSpace){var filteredIndentation=indentation.replace(/[^ \t]/g,"");var partialByNl=partial.split("\n");for(var i=0;i<partialByNl.length;i++){if(partialByNl[i].length&&(i>0||!lineHasNonSpace)){partialByNl[i]=filteredIndentation+partialByNl[i]}}return partialByNl.join("\n")};Writer.prototype.renderPartial=function renderPartial(token,context,partials,config){if(!partials)return;var tags=this.getConfigTags(config);var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null){var lineHasNonSpace=token[6];var tagIndex=token[5];var indentation=token[4];var indentedValue=value;if(tagIndex==0&&indentation){indentedValue=this.indentPartial(value,indentation,lineHasNonSpace)}var tokens=this.parse(indentedValue,tags);return this.renderTokens(tokens,context,partials,indentedValue,config)}};Writer.prototype.unescapedValue=function unescapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return value};Writer.prototype.escapedValue=function escapedValue(token,context,config){var escape=this.getConfigEscape(config)||mustache.escape;var value=context.lookup(token[1]);if(value!=null)return typeof value==="number"&&escape===mustache.escape?String(value):escape(value)};Writer.prototype.rawValue=function rawValue(token){return token[1]};Writer.prototype.getConfigTags=function getConfigTags(config){if(isArray(config)){return config}else if(config&&typeof config==="object"){return config.tags}else{return undefined}};Writer.prototype.getConfigEscape=function getConfigEscape(config){if(config&&typeof config==="object"&&!isArray(config)){return config.escape}else{return undefined}};var mustache={name:"mustache.js",version:"4.1.0",tags:["{{","}}"],clearCache:undefined,escape:undefined,parse:undefined,render:undefined,Scanner:undefined,Context:undefined,Writer:undefined,set templateCache(cache){defaultWriter.templateCache=cache},get templateCache(){return defaultWriter.templateCache}};var defaultWriter=new Writer;mustache.clearCache=function clearCache(){return defaultWriter.clearCache()};mustache.parse=function parse(template,tags){return defaultWriter.parse(template,tags)};mustache.render=function render(template,view,partials,config){if(typeof template!=="string"){throw new TypeError('Invalid template! Template should be a "string" '+'but "'+typeStr(template)+'" was given as the first '+"argument for mustache#render(template, view, partials)")}return defaultWriter.render(template,view,partials,config)};mustache.escape=escapeHtml;mustache.Scanner=Scanner;mustache.Context=Context;mustache.Writer=Writer;return mustache});
    
    /*!
    *
    *  Copyright 2016 Yann Massard (https://github.com/yamass) and other contributors
    *
    *  Licensed under the Apache License, Version 2.0 (the "License");
    *  you may not use this file except in compliance with the License.
    *  You may obtain a copy of the License at
    *
    *  http://www.apache.org/licenses/LICENSE-2.0
    *
    *  Unless required by applicable law or agreed to in writing, software
    *  distributed under the License is distributed on an "AS IS" BASIS,
    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    *  See the License for the specific language governing permissions and
    *  limitations under the License.
    *
    */
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "levenshtein"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var Levenshtein = require("levenshtein");
        exports.keyCodes = {
            backspace: 8,
            tab: 9,
            enter: 13,
            shift: 16,
            ctrl: 17,
            alt: 18,
            pause: 19,
            caps_lock: 20,
            escape: 27,
            space: 32,
            page_up: 33,
            page_down: 34,
            end: 35,
            home: 36,
            left_arrow: 37,
            up_arrow: 38,
            right_arrow: 39,
            down_arrow: 40,
            insert: 45,
            "delete": 46,
            left_window_key: 91,
            right_window_key: 92,
            select_key: 93,
            num_lock: 144,
            scroll_lock: 145,
            specialKeys: [8, 9, 13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 91, 92, 93, 144, 145],
            numberKeys: [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105],
            isSpecialKey: function (keyCode) {
                return this.specialKeys.indexOf(keyCode) != -1;
            },
            isDigitKey: function (keyCode) {
                return this.numberKeys.indexOf(keyCode) != -1;
            },
            isModifierKey: function (e) {
                return [exports.keyCodes.shift, exports.keyCodes.caps_lock, exports.keyCodes.alt, exports.keyCodes.ctrl, exports.keyCodes.left_window_key, exports.keyCodes.right_window_key]
                    .indexOf(e.which) != -1;
            }
        };
        exports.DEFAULT_TEMPLATES = {
            image2LinesTemplate: '<div class="tr-template-image-2-lines">' +
                '  <div class="img-wrapper" style="background-image: url({{imageUrl}})"></div>' +
                '  <div class="content-wrapper tr-editor-area"> ' +
                '    <div class="main-line">{{displayValue}}</div> ' +
                '    <div class="additional-info">{{additionalInfo}}</div>' +
                '  </div>' +
                '</div>',
            roundImage2LinesColorBubbleTemplate: '<div class="tr-template-round-image-2-lines-color-bubble">' +
                '  {{#imageUrl}}<div class="img-wrapper" style="background-image: url({{imageUrl}})"></div>{{/imageUrl}}' +
                '  <div class="content-wrapper tr-editor-area"> ' +
                '    <div class="main-line">{{displayValue}}</div> ' +
                '    <div class="additional-info">{{#statusColor}}<span class="status-bubble" style="background-color: {{statusColor}}"></span>{{/statusColor}}{{additionalInfo}}</div>' +
                '  </div>' +
                '</div>',
            icon2LinesTemplate: '<div class="tr-template-icon-2-lines">' +
                '  <div class="img-wrapper" style="background-image: url({{imageUrl}})"></div>' +
                '  <div class="content-wrapper tr-editor-area"> ' +
                '    <div class="main-line">{{displayValue}}</div> ' +
                '    <div class="additional-info">{{additionalInfo}}</div>' +
                '  </div>' +
                '</div>',
            iconSingleLineTemplate: '<div class="tr-template-icon-single-line">' +
                '  <div class="img-wrapper" style="background-image: url({{imageUrl}})"></div>' +
                '  <div class="content-wrapper tr-editor-area">{{displayValue}}</div>' +
                '</div>',
            singleLineTemplate: '<div class="tr-template-single-line">' +
                '  <div class="content-wrapper tr-editor-area"> ' +
                '    <div>{{displayValue}}</div> ' +
                '  </div>' +
                '</div>',
            currencySingleLineShortTemplate: '<div class="tr-template-currency-single-line-short">' +
                '  <div class="content-wrapper tr-editor-area"> ' +
                '    <div>{{#symbol}}<span class="currency-symbol">{{symbol}}</span>{{/symbol}} {{#code}}<span class="currency-code">{{code}}</span>{{/code}}</div> ' +
                '  </div>' +
                '</div>',
            currencySingleLineLongTemplate: '<div class="tr-template-currency-single-line-long">' +
                '  <div class="content-wrapper tr-editor-area"> ' +
                '    <div class="symbol-and-code">{{#code}}<span class="currency-code">{{code}}</span>{{/code}} {{#symbol}}<span class="currency-symbol">{{symbol}}</span>{{/symbol}}</div>' +
                '    <div class="currency-name">{{name}}</div>' +
                '  </div>' +
                '</div>',
            currency2LineTemplate: '<div class="tr-template-currency-2-lines">' +
                '  <div class="content-wrapper tr-editor-area"> ' +
                '    <div class="main-line">' +
                '      <span class="currency-code">{{code}}</span>' +
                '      <span class="currency-name">{{name}}</span>' +
                '    </div> ' +
                '    <div class="additional-info">' +
                '      <span class="currency-symbol">{{symbol}}</span>&nbsp;' +
                '      {{#exchangeRate}}' +
                '      <div class="exchange">' +
                '        = ' +
                '        <span class="exchange-rate">{{exchangeRate}}</span>' +
                '        <span class="exchange-rate-base">{{exchangeRateBase}}</span>' +
                '      </div>' +
                '      {{/exchangeRate}}' +
                '    </div>' +
                '  </div>' +
                '</div>',
            defaultSpinnerTemplate: '<div class="tr-default-spinner"><div class="spinner"></div><div>Fetching data...</div></div>',
            defaultNoEntriesTemplate: '<div class="tr-default-no-data-display"><div>No matching entries...</div></div>'
        };
        function wrapWithDefaultTagWrapper(entryHtml) {
            return ('<div class="tr-tagbox-default-wrapper-template">' +
                '<div class="tr-tagbox-tag-content">##entryHtml##</div>' +
                '<div class="tr-remove-button"></div>' +
                '</div>').replace("##entryHtml##", entryHtml);
        }
        exports.wrapWithDefaultTagWrapper = wrapWithDefaultTagWrapper;
        function defaultListQueryFunctionFactory(entries, matchingOptions) {
            function filterElements(queryString) {
                var visibleEntries = [];
                for (var i = 0; i < entries.length; i++) {
                    var entry = entries[i];
                    var $entryElement = entry._trEntryElement;
                    if (!queryString || trivialMatch($entryElement.text().trim().replace(/\s{2,}/g, ' '), queryString, matchingOptions).length > 0) {
                        visibleEntries.push(entry);
                    }
                }
                return visibleEntries;
            }
            return function (queryString, resultCallback) {
                resultCallback(filterElements(queryString));
            };
        }
        exports.defaultListQueryFunctionFactory = defaultListQueryFunctionFactory;
        function createProxy(delegate) {
            var proxyConstructor = function () {
            };
            proxyConstructor.prototype = delegate;
            var proxyConstructorTypescriptHack = proxyConstructor;
            return new proxyConstructorTypescriptHack();
        }
        exports.createProxy = createProxy;
        function defaultEntryMatchingFunctionFactory(searchedPropertyNames, matchingOptions) {
            return function (entry, queryString, depth) {
                return searchedPropertyNames
                    .some(function (propertyName) {
                    var value = entry[propertyName];
                    return value != null && trivialMatch(value.toString(), queryString, matchingOptions).length > 0;
                });
            };
        }
        exports.defaultEntryMatchingFunctionFactory = defaultEntryMatchingFunctionFactory;
        function defaultTreeQueryFunctionFactory(topLevelEntries, entryMatchingFunction, childrenPropertyName, expandedPropertyName) {
            function findMatchingEntriesAndTheirAncestors(entry, queryString, nodeDepth) {
                var entryProxy = createProxy(entry);
                entryProxy[childrenPropertyName] = [];
                entryProxy[expandedPropertyName] = false;
                if (entry[childrenPropertyName]) {
                    for (var i = 0; i < entry[childrenPropertyName].length; i++) {
                        var child = entry[childrenPropertyName][i];
                        var childProxy = findMatchingEntriesAndTheirAncestors(child, queryString, nodeDepth + 1);
                        if (childProxy) {
                            entryProxy[childrenPropertyName].push(childProxy);
                            entryProxy[expandedPropertyName] = true;
                        }
                    }
                }
                var hasMatchingChildren = entryProxy[childrenPropertyName].length > 0;
                var matchesItself = entryMatchingFunction(entry, queryString, nodeDepth);
                if (matchesItself && !hasMatchingChildren) {
                    entryProxy[childrenPropertyName] = entry[childrenPropertyName];
                }
                return matchesItself || hasMatchingChildren ? entryProxy : null;
            }
            return function (queryString, resultCallback) {
                if (!queryString) {
                    resultCallback(topLevelEntries);
                }
                else {
                    var matchingEntries = [];
                    for (var i = 0; i < topLevelEntries.length; i++) {
                        var topLevelEntry = topLevelEntries[i];
                        var entryProxy = findMatchingEntriesAndTheirAncestors(topLevelEntry, queryString, 0);
                        if (entryProxy) {
                            matchingEntries.push(entryProxy);
                        }
                    }
                    resultCallback(matchingEntries);
                }
            };
        }
        exports.defaultTreeQueryFunctionFactory = defaultTreeQueryFunctionFactory;
        function customTreeQueryFunctionFactory(topLevelEntries, childrenPropertyName, expandedPropertyName, customNodeMatchingFunction) {
            function findMatchingEntriesAndTheirAncestors(entry, queryString, nodeDepth) {
                var entryProxy = createProxy(entry);
                entryProxy[childrenPropertyName] = [];
                entryProxy[expandedPropertyName] = false;
                if (entry[childrenPropertyName]) {
                    for (var i = 0; i < entry[childrenPropertyName].length; i++) {
                        var child = entry[childrenPropertyName][i];
                        var childProxy = findMatchingEntriesAndTheirAncestors(child, queryString, nodeDepth + 1);
                        if (childProxy) {
                            entryProxy[childrenPropertyName].push(childProxy);
                            entryProxy[expandedPropertyName] = true;
                        }
                    }
                }
                var hasMatchingChildren = entryProxy[childrenPropertyName].length > 0;
                var matchesItself = customNodeMatchingFunction(entry, queryString, nodeDepth);
                if (matchesItself && !hasMatchingChildren) {
                    entryProxy[childrenPropertyName] = entry[childrenPropertyName];
                }
                return matchesItself || hasMatchingChildren ? entryProxy : null;
            }
            return function (queryString, resultCallback) {
                if (!queryString) {
                    resultCallback(topLevelEntries);
                }
                else {
                    var matchingEntries = [];
                    for (var i = 0; i < topLevelEntries.length; i++) {
                        var topLevelEntry = topLevelEntries[i];
                        var entryProxy = findMatchingEntriesAndTheirAncestors(topLevelEntry, queryString, 0);
                        if (entryProxy) {
                            matchingEntries.push(entryProxy);
                        }
                    }
                    resultCallback(matchingEntries);
                }
            };
        }
        exports.customTreeQueryFunctionFactory = customTreeQueryFunctionFactory;
        function selectElementContents(domElement, start, end) {
            domElement = domElement.firstChild || domElement;
            end = end || start;
            var range = document.createRange();
            range.setStart(domElement, start);
            range.setEnd(domElement, end);
            var sel = window.getSelection();
            try {
                sel.removeAllRanges();
            }
            catch (e) {
            }
            sel.addRange(range);
        }
        exports.selectElementContents = selectElementContents;
        exports.escapeSpecialRegexCharacter = function (s) {
            return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
        };
        function objectEquals(x, y) {
            'use strict';
            if (x === null || x === undefined || y === null || y === undefined) {
                return x === y;
            }
            if (x.constructor !== y.constructor) {
                return false;
            }
            if (x instanceof Function) {
                return x === y;
            }
            if (x instanceof RegExp) {
                return x === y;
            }
            if (x === y || x.valueOf() === y.valueOf()) {
                return true;
            }
            if (Array.isArray(x) && x.length !== y.length) {
                return false;
            }
            if (x instanceof Date) {
                return false;
            }
            if (!(x instanceof Object)) {
                return false;
            }
            if (!(y instanceof Object)) {
                return false;
            }
            var p = Object.keys(x);
            return Object.keys(y).every(function (i) {
                return p.indexOf(i) !== -1;
            }) &&
                p.every(function (i) {
                    return objectEquals(x[i], y[i]);
                });
        }
        exports.objectEquals = objectEquals;
        function trivialMatch(text, searchString, options) {
            if (!searchString) {
                return [{
                        start: 0,
                        length: text.length
                    }];
            }
            options = $.extend({
                matchingMode: 'contains',
                ignoreCase: true,
                maxLevenshteinDistance: 3
            }, options || null);
            if (options.ignoreCase) {
                text = text.toLowerCase();
                searchString = searchString.toLowerCase();
            }
            function findRegexMatches(regex) {
                var matches = [];
                var match;
                while (match = regex.exec(text)) {
                    matches.push({
                        start: match.index,
                        length: match[0].length
                    });
                }
                return matches;
            }
            function findLevenshteinMatches(text, searchString) {
                var levenshtein = new Levenshtein(text, searchString);
                if (levenshtein.distance <= options.maxLevenshteinDistance) {
                    return [{
                            start: 0,
                            length: searchString.length,
                            distance: levenshtein.distance
                        }];
                }
                else {
                    return [];
                }
            }
            if (options.matchingMode == 'contains') {
                searchString = searchString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
                return findRegexMatches(new RegExp(searchString, "g"));
            }
            else if (options.matchingMode == 'prefix') {
                searchString = searchString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
                return findRegexMatches(new RegExp('^' + searchString, "g"));
            }
            else if (options.matchingMode == 'prefix-word') {
                searchString = searchString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
                if (searchString.charAt(0).match(/^\w/)) {
                    return findRegexMatches(new RegExp('\\b' + searchString, "g"));
                }
                else {
                    return findRegexMatches(new RegExp(searchString, "g"));
                }
            }
            else if (options.matchingMode == 'prefix-levenshtein') {
                return findLevenshteinMatches(text.substr(0, Math.min(searchString.length, text.length)), searchString);
            }
            else if (options.matchingMode == 'levenshtein') {
                return findLevenshteinMatches(text, searchString);
            }
            else {
                throw "unknown matchingMode: " + options.matchingMode;
            }
        }
        exports.trivialMatch = trivialMatch;
        function minimallyScrollTo(element, target) {
            var $target = $(target);
            $(element).each(function () {
                var $this = $(this);
                var viewPortMinY = $this.scrollTop();
                var viewPortMaxY = viewPortMinY + $this.innerHeight();
                var targetMinY = $($target).offset().top - $(this).offset().top + $this.scrollTop();
                var targetMaxY = targetMinY + $target.height();
                if (targetMinY < viewPortMinY) {
                    $this.scrollTop(targetMinY);
                }
                else if (targetMaxY > viewPortMaxY) {
                    $this.scrollTop(Math.min(targetMinY, targetMaxY - $this.innerHeight()));
                }
                var viewPortMinX = $this.scrollLeft();
                var viewPortMaxX = viewPortMinX + $this.innerWidth();
                var targetMinX = $($target).offset().left - $(this).offset().left + $this.scrollLeft();
                var targetMaxX = targetMinX + $target.width();
                if (targetMinX < viewPortMinX) {
                    $this.scrollLeft(targetMinX);
                }
                else if (targetMaxX > viewPortMaxX) {
                    $this.scrollLeft(Math.min(targetMinX, targetMaxX - $this.innerWidth()));
                }
            });
        }
        exports.minimallyScrollTo = minimallyScrollTo;
        function setTimeoutOrDoImmediately(f, delay) {
            if (delay != null) {
                return window.setTimeout(f(), delay);
            }
            else {
                return void f();
            }
        }
        exports.setTimeoutOrDoImmediately = setTimeoutOrDoImmediately;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "moment", "./TrivialEvent"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var moment = require("moment");
        var TrivialEvent_1 = require("./TrivialEvent");
        var WeekDay;
        (function (WeekDay) {
            WeekDay[WeekDay["MONDAY"] = 1] = "MONDAY";
            WeekDay[WeekDay["TUESDAY"] = 2] = "TUESDAY";
            WeekDay[WeekDay["WEDNESDAY"] = 3] = "WEDNESDAY";
            WeekDay[WeekDay["THURSDAY"] = 4] = "THURSDAY";
            WeekDay[WeekDay["FRIDAY"] = 5] = "FRIDAY";
            WeekDay[WeekDay["SATURDAY"] = 6] = "SATURDAY";
            WeekDay[WeekDay["SUNDAY"] = 7] = "SUNDAY";
        })(WeekDay = exports.WeekDay || (exports.WeekDay = {}));
        var TrivialCalendarBox = (function () {
            function TrivialCalendarBox($container, options) {
                if (options === void 0) { options = {}; }
                this.$container = $container;
                this.onChange = new TrivialEvent_1.TrivialEvent(this);
                this.onOnEditingTimeUnitChange = new TrivialEvent_1.TrivialEvent(this);
                this.config = $.extend({
                    selectedDate: moment(),
                    firstDayOfWeek: WeekDay.MONDAY,
                    mode: 'datetime',
                    highlightKeyboardNavigationState: false
                }, options);
                this.keyboardNavigationState = this.config.mode == 'time' ? 'hour' : 'day';
                this.keyboardNavCssClass = this.config.highlightKeyboardNavigationState ? "keyboard-nav" : "";
                this.selectedDate = this.config.selectedDate;
                this.$calendarBox = $('<div class="tr-calendarbox"/>').appendTo(this.$container);
                this.$calendarDisplay = $('<div class="tr-calendar-display"/>');
                this.$yearDisplay = $('<div class="year"><span class="back-button"/><span class="name"/><span class="forward-button"/></div>').appendTo(this.$calendarDisplay);
                this.$monthDisplay = $('<div class="month"><span class="back-button"/><span class="name"/><span class="forward-button"/></div>').appendTo(this.$calendarDisplay);
                this.$monthTable = $('<div class="month-table">').appendTo(this.$calendarDisplay);
                this.$year = this.$yearDisplay.find(".name");
                this.$month = this.$monthDisplay.find(".name");
                this.$yearDisplay.click(this.setKeyboardNavigationState.bind(this, "year"));
                this.$yearDisplay.find('.back-button').click(this.navigateByUnit.bind(this, "year", "left", true));
                this.$yearDisplay.find('.forward-button').click(this.navigateByUnit.bind(this, "year", "right", true));
                this.$monthDisplay.click(this.setKeyboardNavigationState.bind(this, "month"));
                this.$monthDisplay.find('.back-button').click(this.navigateByUnit.bind(this, "month", "left", true));
                this.$monthDisplay.find('.forward-button').click(this.navigateByUnit.bind(this, "month", "right", true));
                this.$clockDisplay = $('<div class="tr-clock-display"/>')
                    .append('<svg class="clock" viewBox="0 0 100 100" width="100" height="100"> ' +
                    '<circle class="clockcircle" cx="50" cy="50" r="45"/> ' +
                    '<g class="ticks" > ' +
                    ' <line x1="50" y1="5.000" x2="50.00" y2="10.00"/> <line x1="72.50" y1="11.03" x2="70.00" y2="15.36"/> <line x1="88.97" y1="27.50" x2="84.64" y2="30.00"/> <line x1="95.00" y1="50.00" x2="90.00" y2="50.00"/> <line x1="88.97" y1="72.50" x2="84.64" y2="70.00"/> <line x1="72.50" y1="88.97" x2="70.00" y2="84.64"/> <line x1="50.00" y1="95.00" x2="50.00" y2="90.00"/> <line x1="27.50" y1="88.97" x2="30.00" y2="84.64"/> <line x1="11.03" y1="72.50" x2="15.36" y2="70.00"/> <line x1="5.000" y1="50.00" x2="10.00" y2="50.00"/> <line x1="11.03" y1="27.50" x2="15.36" y2="30.00"/> <line x1="27.50" y1="11.03" x2="30.00" y2="15.36"/> ' +
                    '</g> ' +
                    '<g class="numbers">' +
                    ' <text x="50" y="22">12</text> <text x="85" y="55">3</text> <text x="50" y="88">6</text> <text x="15" y="55">9</text> ' +
                    '</g> ' +
                    '<g class="hands">' +
                    ' <line class="minutehand" x1="50" y1="50" x2="50" y2="20"/>' +
                    ' <line class="hourhand" x1="50" y1="50" x2="50" y2="26"/> ' +
                    '</g> ' +
                    '<g class="am-pm-box">' +
                    ' <rect x="58" y="59" width="20" height="15"/>' +
                    ' <text class="am-pm-text" x="60" y="70" >??</text>' +
                    '</g>' +
                    '</svg>').append('<div class="digital-time-display"><div class="hour-wrapper">' +
                    '<div class="up-button"/><div class="hour">??</div><div class="down-button"/>' +
                    '</div>:<div class="minute-wrapper">' +
                    '<div class="up-button"/><div class="minute">??</div><div class="down-button"/>' +
                    '</div></div>');
                this.$hourHand = this.$clockDisplay.find('.hourhand');
                this.$minuteHand = this.$clockDisplay.find('.minutehand');
                this.$amPmText = this.$clockDisplay.find('.am-pm-text');
                this.$digitalTimeHourDisplayWrapper = this.$clockDisplay.find('.digital-time-display .hour-wrapper');
                this.$digitalTimeHourDisplay = this.$clockDisplay.find('.digital-time-display .hour');
                this.$digitalTimeHourDisplayWrapper.click(this.setKeyboardNavigationState.bind(this, "hour"));
                this.$digitalTimeHourDisplayWrapper.find(".up-button").click(this.navigateByUnit.bind(this, "hour", "up", true));
                this.$digitalTimeHourDisplayWrapper.find(".down-button").click(this.navigateByUnit.bind(this, "hour", "down", true));
                this.$digitalTimeMinuteDisplayWrapper = this.$clockDisplay.find('.digital-time-display .minute-wrapper');
                this.$digitalTimeMinuteDisplay = this.$clockDisplay.find('.digital-time-display .minute');
                this.$digitalTimeMinuteDisplayWrapper.click(this.setKeyboardNavigationState.bind(this, "minute"));
                this.$digitalTimeMinuteDisplayWrapper.find(".up-button").click(this.navigateByUnit.bind(this, "minute", "up", true));
                this.$digitalTimeMinuteDisplayWrapper.find(".down-button").click(this.navigateByUnit.bind(this, "minute", "down", true));
                if (this.config.mode == 'date' || this.config.mode == 'datetime') {
                    this.$calendarDisplay.appendTo(this.$calendarBox);
                }
                if (this.config.mode == 'time' || this.config.mode === 'datetime') {
                    this.$clockDisplay.appendTo(this.$calendarBox);
                }
                if (this.selectedDate) {
                    this.updateMonthDisplay(this.selectedDate);
                    this.updateClockDisplay(this.selectedDate);
                }
                else {
                    this.updateMonthDisplay(moment());
                    this.updateClockDisplay(moment());
                }
            }
            TrivialCalendarBox.getDaysForCalendarDisplay = function (dateInMonthDoBeDisplayed, firstDayOfWeek) {
                var firstDayOfMonth = dateInMonthDoBeDisplayed.clone().utc().startOf('month').hour(12);
                var firstDayToBeDisplayed = firstDayOfMonth.clone().isoWeekday(firstDayOfWeek <= firstDayOfMonth.isoWeekday() ? firstDayOfWeek : firstDayOfWeek - 7);
                var daysOfMonth = [];
                for (var day = firstDayToBeDisplayed.clone(); daysOfMonth.length < 42; day.add(1, 'day')) {
                    daysOfMonth.push(day.clone());
                }
                return daysOfMonth;
            };
            TrivialCalendarBox.prototype.updateMonthDisplay = function (dateInMonthToBeDisplayed) {
                var _this = this;
                this.$year.text(dateInMonthToBeDisplayed.year());
                this.$month.text(moment.months()[dateInMonthToBeDisplayed.month()]);
                this.$monthTable.remove();
                this.$monthTable = $('<div class="month-table">').appendTo(this.$calendarDisplay);
                var daysToBeDisplayed = TrivialCalendarBox.getDaysForCalendarDisplay(dateInMonthToBeDisplayed, 1);
                var $tr = $('<tr>').appendTo(this.$monthTable);
                for (var i = 0; i < 7; i++) {
                    $tr.append('<th>' + moment.weekdaysMin()[(this.config.firstDayOfWeek + i) % 7] + '</th>');
                }
                for (var w = 0; w < daysToBeDisplayed.length / 7; w++) {
                    $tr = $('<tr>').appendTo(this.$monthTable);
                    for (var d = 0; d < 7; d++) {
                        var day = daysToBeDisplayed[w * 7 + d];
                        var $td = $('<td>' + day.date() + '</td>');
                        if (day.month() == dateInMonthToBeDisplayed.month()) {
                            $td.addClass('current-month');
                        }
                        else {
                            $td.addClass('other-month');
                        }
                        if (day.year() == moment().year() && day.dayOfYear() == moment().dayOfYear()) {
                            $td.addClass('today');
                        }
                        if (day.year() == this.selectedDate.year() && day.dayOfYear() == this.selectedDate.dayOfYear()) {
                            $td.addClass('selected');
                            if (this.keyboardNavigationState === 'day') {
                                $td.addClass(this.keyboardNavCssClass);
                            }
                        }
                        $td.click((function (day) {
                            _this.setKeyboardNavigationState("day");
                            _this.setMonthAndDay(day.month() + 1, day.date(), true);
                        }).bind(this, day));
                        $tr.append($td);
                    }
                }
            };
            TrivialCalendarBox.prototype.updateClockDisplay = function (date) {
                this.$amPmText.text(date.hour() >= 12 ? 'pm' : 'am');
                var minutesAngle = date.minute() * 6;
                var hours = (date.hour() % 12) + date.minute() / 60;
                var hourAngle = hours * 30;
                this.$hourHand.attr("transform", "rotate(" + hourAngle + ",50,50)");
                this.$minuteHand.attr("transform", "rotate(" + minutesAngle + ",50,50)");
                this.$digitalTimeHourDisplay.text(date.format('HH'));
                this.$digitalTimeMinuteDisplay.text(date.format('mm'));
            };
            TrivialCalendarBox.prototype.updateDisplay = function () {
                this.updateMonthDisplay(this.selectedDate);
                this.updateClockDisplay(this.selectedDate);
            };
            ;
            TrivialCalendarBox.prototype.setSelectedDate = function (moment) {
                this.selectedDate = moment;
                this.updateDisplay();
            };
            TrivialCalendarBox.prototype.setYear = function (year, fireEvent) {
                this.selectedDate.year(year);
                this.updateDisplay();
                if (fireEvent) {
                    this.onOnEditingTimeUnitChange.fire('year');
                    this.fireChangeEvents('year');
                }
            };
            TrivialCalendarBox.prototype.setMonth = function (month, fireEvent) {
                this.selectedDate.month(month - 1);
                this.updateDisplay();
                if (fireEvent) {
                    this.onOnEditingTimeUnitChange.fire('month');
                    this.fireChangeEvents('month');
                }
            };
            TrivialCalendarBox.prototype.setDayOfMonth = function (dayOfMonth, fireEvent) {
                this.selectedDate.date(dayOfMonth);
                this.updateDisplay();
                if (fireEvent) {
                    this.onOnEditingTimeUnitChange.fire('day');
                    this.fireChangeEvents('day');
                }
            };
            TrivialCalendarBox.prototype.setMonthAndDay = function (month, day, fireEvent) {
                this.selectedDate.month(month - 1);
                this.selectedDate.date(day);
                this.updateDisplay();
                if (fireEvent) {
                    this.onOnEditingTimeUnitChange.fire('day');
                    this.fireChangeEvents('month');
                    this.fireChangeEvents('day');
                }
            };
            TrivialCalendarBox.prototype.setHour = function (hour, fireEvent) {
                this.selectedDate.hour(hour);
                this.updateDisplay();
                if (fireEvent) {
                    this.onOnEditingTimeUnitChange.fire('hour');
                    this.fireChangeEvents('hour');
                }
            };
            TrivialCalendarBox.prototype.setMinute = function (minute, fireEvent) {
                this.selectedDate.minute(minute);
                this.updateDisplay();
                if (fireEvent) {
                    this.onOnEditingTimeUnitChange.fire('minute');
                    this.fireChangeEvents('minute');
                }
            };
            TrivialCalendarBox.prototype.fireChangeEvents = function (timeUnit) {
                this.$calendarBox.trigger("change");
                this.onChange.fire({
                    value: this.getSelectedDate(),
                    timeUnitEdited: timeUnit
                });
            };
            TrivialCalendarBox.prototype.setKeyboardNavigationState = function (newKeyboardNavigationState) {
                this.keyboardNavigationState = newKeyboardNavigationState;
                if (this.config.highlightKeyboardNavigationState) {
                    var me_1 = this;
                    $(this.$yearDisplay).add(this.$monthDisplay).add(this.$monthTable.find('td.' + this.keyboardNavCssClass)).add(this.$hourHand).add(this.$digitalTimeHourDisplayWrapper).add(this.$minuteHand).add(this.$digitalTimeMinuteDisplayWrapper)
                        .each(function () {
                        $(this).attr("class", $(this).attr("class").replace(me_1.keyboardNavCssClass, ''));
                    });
                    if (this.keyboardNavigationState == 'year') {
                        this.$yearDisplay.addClass(this.keyboardNavCssClass);
                    }
                    else if (this.keyboardNavigationState == 'month') {
                        this.$monthDisplay.addClass(this.keyboardNavCssClass);
                    }
                    else if (this.keyboardNavigationState == 'day') {
                        this.$monthTable.find(".selected").addClass(this.keyboardNavCssClass);
                    }
                    else if (this.keyboardNavigationState == 'hour') {
                        this.$hourHand.attr("class", "hourhand " + this.keyboardNavCssClass);
                        this.$digitalTimeHourDisplayWrapper.addClass(this.keyboardNavCssClass);
                    }
                    else if (this.keyboardNavigationState == 'minute') {
                        this.$minuteHand.attr("class", "minutehand " + this.keyboardNavCssClass);
                        this.$digitalTimeMinuteDisplayWrapper.addClass(this.keyboardNavCssClass);
                    }
                }
            };
            TrivialCalendarBox.prototype.getSelectedDate = function () {
                return this.selectedDate;
            };
            ;
            TrivialCalendarBox.prototype.navigateByUnit = function (unit, direction, fireEvent) {
                if (fireEvent === void 0) { fireEvent = false; }
                if (unit == 'year') {
                    if (direction == 'down' || direction == 'left') {
                        this.setYear(this.selectedDate.year() - 1, fireEvent);
                    }
                    else if (direction == 'up' || direction == 'right') {
                        this.setYear(this.selectedDate.year() + 1, fireEvent);
                    }
                    fireEvent && this.fireChangeEvents('year');
                    return true;
                }
                else if (unit == 'month') {
                    if (direction == 'down' || direction == 'left') {
                        this.setMonth(this.selectedDate.month(), fireEvent);
                    }
                    else if (direction == 'up' || direction == 'right') {
                        this.setMonth(this.selectedDate.month() + 2, fireEvent);
                    }
                    fireEvent && this.fireChangeEvents('month');
                    return true;
                }
                else if (unit == 'day') {
                    if (direction == 'down') {
                        this.selectedDate.dayOfYear(this.selectedDate.dayOfYear() + 7);
                    }
                    else if (direction == 'left') {
                        this.selectedDate.dayOfYear(this.selectedDate.dayOfYear() - 1);
                    }
                    else if (direction == 'up') {
                        this.selectedDate.dayOfYear(this.selectedDate.dayOfYear() - 7);
                    }
                    else if (direction == 'right') {
                        this.selectedDate.dayOfYear(this.selectedDate.dayOfYear() + 1);
                    }
                    this.updateDisplay();
                    fireEvent && this.fireChangeEvents('day');
                    return true;
                }
                else if (unit == 'hour') {
                    if (direction == 'down' || direction == 'left') {
                        this.setHour(this.selectedDate.hour() - 1, fireEvent);
                    }
                    else if (direction == 'up' || direction == 'right') {
                        this.setHour(this.selectedDate.hour() + 1, fireEvent);
                    }
                    fireEvent && this.fireChangeEvents('hour');
                    return true;
                }
                else if (unit == 'minute') {
                    if (direction == 'down' || direction == 'left') {
                        this.setMinute(this.selectedDate.minute() - (this.selectedDate.minute() % 5) - 5, fireEvent);
                    }
                    else if (direction == 'up' || direction == 'right') {
                        this.setMinute(this.selectedDate.minute() - (this.selectedDate.minute() % 5) + 5, fireEvent);
                    }
                    fireEvent && this.fireChangeEvents('minute');
                    return true;
                }
            };
            TrivialCalendarBox.prototype.navigate = function (direction) {
                this.navigateByUnit(this.keyboardNavigationState, direction);
            };
            ;
            TrivialCalendarBox.prototype.getMainDomElement = function () {
                return this.$calendarBox[0];
            };
            TrivialCalendarBox.prototype.destroy = function () {
                this.$calendarBox.remove();
            };
            ;
            return TrivialCalendarBox;
        }());
        exports.TrivialCalendarBox = TrivialCalendarBox;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "mustache", "./TrivialCore", "./TrivialListBox", "./TrivialEvent"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var Mustache = require("mustache");
        var TrivialCore_1 = require("./TrivialCore");
        var TrivialListBox_1 = require("./TrivialListBox");
        var TrivialEvent_1 = require("./TrivialEvent");
        var TrivialComboBox = (function () {
            function TrivialComboBox(originalInput, options) {
                if (options === void 0) { options = {}; }
                var _this = this;
                this.$spinners = $();
                this.onSelectedEntryChanged = new TrivialEvent_1.TrivialEvent(this);
                this.onFocus = new TrivialEvent_1.TrivialEvent(this);
                this.onBlur = new TrivialEvent_1.TrivialEvent(this);
                this.isDropDownOpen = false;
                this.isEditorVisible = false;
                this.lastQueryString = null;
                this.lastCompleteInputQueryString = null;
                this.selectedEntry = null;
                this.lastCommittedValue = null;
                this.blurCausedByClickInsideComponent = false;
                this.autoCompleteTimeoutId = -1;
                this.doNoAutoCompleteBecauseBackspaceWasPressed = false;
                this.listBoxDirty = true;
                this.usingDefaultQueryFunction = false;
                this.config = $.extend({
                    valueFunction: function (entry) { return entry ? "" + entry.id : null; },
                    entryRenderingFunction: function (entry) {
                        return Mustache.render(TrivialCore_1.DEFAULT_TEMPLATES.image2LinesTemplate, entry);
                    },
                    selectedEntryRenderingFunction: function (entry) {
                        return _this.config.entryRenderingFunction(entry);
                    },
                    selectedEntry: undefined,
                    spinnerTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultSpinnerTemplate,
                    noEntriesTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultNoEntriesTemplate,
                    textHighlightingEntryLimit: 100,
                    entries: null,
                    queryFunction: null,
                    autoComplete: true,
                    autoCompleteDelay: 0,
                    entryToEditorTextFunction: function (entry) {
                        return entry["displayValue"];
                    },
                    autoCompleteFunction: function (editorText, entry) {
                        if (editorText) {
                            for (var propertyName in entry) {
                                if (entry.hasOwnProperty(propertyName)) {
                                    var propertyValue = entry[propertyName];
                                    if (propertyValue && propertyValue.toString().toLowerCase().indexOf(editorText.toLowerCase()) === 0) {
                                        return propertyValue.toString();
                                    }
                                }
                            }
                            return null;
                        }
                        else {
                            return entry ? _this.config.entryToEditorTextFunction(entry) : null;
                        }
                    },
                    allowFreeText: false,
                    freeTextEntryFactory: function (freeText) {
                        return {
                            displayValue: freeText,
                            _isFreeTextEntry: true
                        };
                    },
                    showClearButton: false,
                    showTrigger: true,
                    matchingOptions: {
                        matchingMode: 'contains',
                        ignoreCase: true,
                        maxLevenshteinDistance: 2
                    },
                    editingMode: 'editable',
                    showDropDownOnResultsOnly: false
                }, options);
                if (!this.config.queryFunction) {
                    this.config.queryFunction = TrivialCore_1.defaultListQueryFunctionFactory(this.config.entries || [], this.config.matchingOptions);
                    this.usingDefaultQueryFunction = true;
                }
                this.entries = this.config.entries;
                this.$originalInput = $(originalInput);
                this.$comboBox = $('<div class="tr-combobox tr-input-wrapper"/>')
                    .insertAfter(this.$originalInput);
                this.$selectedEntryWrapper = $('<div class="tr-combobox-selected-entry-wrapper"/>').appendTo(this.$comboBox);
                if (this.config.showClearButton) {
                    this.$clearButton = $('<div class="tr-remove-button">').appendTo(this.$comboBox);
                    this.$clearButton.mousedown(function (e) {
                        _this.$editor.val("");
                        _this.setSelectedEntry(null, true, true, e);
                    });
                }
                if (this.config.showTrigger) {
                    this.$trigger = $('<div class="tr-trigger"><span class="tr-trigger-icon"/></div>').appendTo(this.$comboBox);
                    this.$trigger.mousedown(function () {
                        if (_this.isDropDownOpen) {
                            _this.showEditor();
                            _this.closeDropDown();
                        }
                        else {
                            setTimeout(function () {
                                _this.showEditor();
                                _this.$editor.select();
                                _this.openDropDown();
                                _this.query();
                            });
                        }
                    });
                }
                this.$dropDown = $('<div class="tr-dropdown"></div>')
                    .scroll(function () {
                    return false;
                });
                this.$dropDownTargetElement = $("body");
                this.setEditingMode(this.config.editingMode);
                this.$originalInput.addClass("tr-original-input");
                this.$editor = $('<input type="text" autocomplete="off"/>');
                this.$editor.prependTo(this.$comboBox).addClass("tr-combobox-editor tr-editor")
                    .focus(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                    }
                    else {
                        _this.$originalInput.triggerHandler('focus');
                        _this.onFocus.fire();
                        _this.$comboBox.addClass('focus');
                        _this.showEditor();
                    }
                })
                    .blur(function (e) {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                    }
                    else {
                        _this.$originalInput.triggerHandler('blur');
                        _this.onBlur.fire();
                        _this.$comboBox.removeClass('focus');
                        if (_this.editorContainsFreeText()) {
                            if (!TrivialCore_1.objectEquals(_this.getSelectedEntry(), _this.lastCommittedValue)) {
                                _this.setSelectedEntry(_this.getSelectedEntry(), true, true, e);
                            }
                        }
                        else {
                            _this.$editor.val("");
                            _this.setSelectedEntry(_this.lastCommittedValue, false, true, e);
                        }
                        _this.hideEditor();
                        _this.closeDropDown();
                    }
                })
                    .keydown(function (e) {
                    if (TrivialCore_1.keyCodes.isModifierKey(e)) {
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.tab) {
                        var highlightedEntry = _this.listBox.getHighlightedEntry();
                        if (_this.isDropDownOpen && highlightedEntry) {
                            _this.setSelectedEntry(highlightedEntry, true, true, e);
                        }
                        else if (!_this.$editor.val()) {
                            _this.setSelectedEntry(null, true, true);
                        }
                        else if (_this.config.allowFreeText) {
                            _this.setSelectedEntry(_this.getSelectedEntry(), true, true, e);
                        }
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.left_arrow || e.which == TrivialCore_1.keyCodes.right_arrow) {
                        _this.showEditor();
                        return;
                    }
                    setTimeout(function () {
                        var isNonIgnoredKey = !TrivialCore_1.keyCodes.isModifierKey(e) && [TrivialCore_1.keyCodes.enter, TrivialCore_1.keyCodes.escape, TrivialCore_1.keyCodes.tab].indexOf(e.which) === -1;
                        var editorValueDoesNotCorrespondToSelectedValue = _this.isEntrySelected() && _this.$editor.val() !== _this.config.entryToEditorTextFunction(_this.selectedEntry);
                        if (isNonIgnoredKey && (editorValueDoesNotCorrespondToSelectedValue || _this.config.valueFunction(_this.listBox.getHighlightedEntry())) !== _this.config.valueFunction(_this.getSelectedEntry())) {
                            _this.setSelectedEntry(null, false, false, e);
                        }
                    });
                    if (e.which == TrivialCore_1.keyCodes.backspace || e.which == TrivialCore_1.keyCodes.delete) {
                        _this.doNoAutoCompleteBecauseBackspaceWasPressed = true;
                    }
                    if (e.which == TrivialCore_1.keyCodes.up_arrow || e.which == TrivialCore_1.keyCodes.down_arrow) {
                        if (!_this.isEditorVisible) {
                            _this.$editor.select();
                            _this.showEditor();
                        }
                        var direction = e.which == TrivialCore_1.keyCodes.up_arrow ? -1 : 1;
                        if (!_this.isDropDownOpen) {
                            _this.query(direction);
                            if (!_this.config.showDropDownOnResultsOnly) {
                                _this.openDropDown();
                            }
                        }
                        else {
                            _this.listBox.highlightNextEntry(direction);
                            _this.autoCompleteIfPossible();
                        }
                        return false;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.enter) {
                        if (_this.isEditorVisible || _this.editorContainsFreeText()) {
                            e.preventDefault();
                            var highlightedEntry = _this.listBox.getHighlightedEntry();
                            if (_this.isDropDownOpen && highlightedEntry) {
                                _this.setSelectedEntry(highlightedEntry, true, true, e);
                            }
                            else if (!_this.$editor.val()) {
                                _this.setSelectedEntry(null, true, true, e);
                            }
                            else if (_this.config.allowFreeText) {
                                _this.setSelectedEntry(_this.getSelectedEntry(), true, true, e);
                            }
                            _this.closeDropDown();
                            _this.hideEditor();
                        }
                    }
                    else if (e.which == TrivialCore_1.keyCodes.escape) {
                        e.preventDefault();
                        if (!(_this.editorContainsFreeText() && _this.isDropDownOpen)) {
                            _this.hideEditor();
                            _this.$editor.val("");
                            _this.entries = null;
                            _this.setSelectedEntry(_this.lastCommittedValue, false, true, e);
                        }
                        _this.closeDropDown();
                    }
                    else {
                        if (!_this.isEditorVisible) {
                            _this.showEditor();
                            _this.$editor.select();
                        }
                        if (!_this.config.showDropDownOnResultsOnly) {
                            _this.openDropDown();
                        }
                        setTimeout(function () {
                            if (_this.$editor.val()) {
                                _this.query(1);
                            }
                            else {
                                _this.query(0);
                                _this.listBox.setHighlightedEntry(null);
                            }
                        });
                    }
                })
                    .mousedown(function () {
                    if (!_this.config.showDropDownOnResultsOnly) {
                        _this.openDropDown();
                    }
                    _this.query();
                });
                if (this.$originalInput.attr("tabindex")) {
                    this.$editor.attr("tabindex", this.$originalInput.attr("tabindex"));
                }
                if (this.$originalInput.attr("autofocus")) {
                    this.$editor.focus();
                }
                this.$comboBox.add(this.$dropDown).mousedown(function () {
                    if (_this.$editor.is(":focus")) {
                        _this.blurCausedByClickInsideComponent = true;
                    }
                }).mouseup(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                        _this.blurCausedByClickInsideComponent = false;
                    }
                }).mouseout(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                        _this.blurCausedByClickInsideComponent = false;
                    }
                });
                var configWithoutEntries = $.extend({}, this.config);
                configWithoutEntries.entries = [];
                this.listBox = new TrivialListBox_1.TrivialListBox(this.$dropDown, configWithoutEntries);
                this.listBox.onSelectedEntryChanged.addListener(function (selectedEntry, eventSource, originalEvent) {
                    if (selectedEntry) {
                        _this.setSelectedEntry(selectedEntry, true, !TrivialCore_1.objectEquals(selectedEntry, _this.lastCommittedValue), originalEvent);
                        _this.listBox.setSelectedEntry(null);
                        _this.closeDropDown();
                    }
                    _this.hideEditor();
                });
                this.setSelectedEntry(this.config.selectedEntry, true, false);
                this.$selectedEntryWrapper.click(function () {
                    _this.showEditor();
                    _this.$editor.select();
                    if (!_this.config.showDropDownOnResultsOnly) {
                        _this.openDropDown();
                    }
                    _this.query();
                });
            }
            TrivialComboBox.prototype.query = function (highlightDirection) {
                var _this = this;
                var queryString = this.getNonSelectedEditorValue();
                var completeInputString = this.$editor.val();
                if (this.lastQueryString !== queryString || this.lastCompleteInputQueryString !== completeInputString) {
                    if (this.$spinners.length === 0) {
                        var $spinner = $(this.config.spinnerTemplate).appendTo(this.$dropDown);
                        this.$spinners = this.$spinners.add($spinner);
                    }
                    this.config.queryFunction(queryString, function (newEntries) {
                        _this.updateEntries(newEntries, highlightDirection);
                        if (_this.config.showDropDownOnResultsOnly && newEntries && newEntries.length > 0 && _this.$editor.is(":focus")) {
                            _this.openDropDown();
                        }
                    });
                    this.lastQueryString = queryString;
                    this.lastCompleteInputQueryString = completeInputString;
                }
                else {
                    this.openDropDown();
                }
            };
            TrivialComboBox.prototype.fireChangeEvents = function (entry, originalEvent) {
                this.$originalInput.trigger("change");
                this.onSelectedEntryChanged.fire(entry, originalEvent);
            };
            TrivialComboBox.prototype.setSelectedEntry = function (entry, commit, fireEvent, originalEvent) {
                if (commit === void 0) { commit = true; }
                if (fireEvent === void 0) { fireEvent = false; }
                this.$originalInput.val(this.config.valueFunction(entry));
                this.selectedEntry = entry;
                var $selectedEntry = $(this.config.selectedEntryRenderingFunction(entry))
                    .addClass("tr-combobox-entry");
                this.$selectedEntryWrapper.empty().append($selectedEntry);
                if (entry != null) {
                    this.$editor.val(this.config.entryToEditorTextFunction(entry));
                }
                if (commit) {
                    this.lastCommittedValue = entry;
                    if (fireEvent) {
                        this.fireChangeEvents(entry, originalEvent);
                    }
                }
                if (this.$clearButton) {
                    this.$clearButton.toggle(entry != null);
                }
                if (this.isEditorVisible) {
                    this.showEditor();
                }
                if (this.isDropDownOpen) {
                    this.repositionDropDown();
                }
            };
            TrivialComboBox.prototype.isEntrySelected = function () {
                return this.selectedEntry != null;
            };
            TrivialComboBox.prototype.showEditor = function () {
                var $editorArea = this.$selectedEntryWrapper.find(".tr-editor-area");
                if ($editorArea.length === 0) {
                    $editorArea = this.$selectedEntryWrapper;
                }
                this.$editor
                    .css({
                    "width": Math.min($editorArea[0].offsetWidth, this.$trigger ? this.$trigger[0].offsetLeft - $editorArea[0].offsetLeft : 99999999) + "px",
                    "height": ($editorArea[0].offsetHeight) + "px"
                })
                    .position({
                    my: "left top",
                    at: "left top",
                    of: $editorArea
                });
                this.isEditorVisible = true;
            };
            TrivialComboBox.prototype.editorContainsFreeText = function () {
                return this.config.allowFreeText && this.$editor.val().length > 0 && !this.isEntrySelected();
            };
            ;
            TrivialComboBox.prototype.hideEditor = function () {
                this.$editor.width(0).height(0);
                this.isEditorVisible = false;
            };
            TrivialComboBox.prototype.repositionDropDown = function () {
                var _this = this;
                this.$dropDown
                    .show()
                    .position({
                    my: "left top",
                    at: "left bottom",
                    of: this.$comboBox,
                    collision: "flip",
                    using: function (calculatedPosition, info) {
                        if (info.vertical === "top") {
                            _this.$comboBox.removeClass("dropdown-flipped");
                            _this.$dropDown.removeClass("flipped");
                        }
                        else {
                            _this.$comboBox.addClass("dropdown-flipped");
                            _this.$dropDown.addClass("flipped");
                        }
                        _this.$dropDown.css({
                            left: calculatedPosition.left + 'px',
                            top: calculatedPosition.top + 'px'
                        });
                    }
                })
                    .width(this.$comboBox.width());
            };
            ;
            TrivialComboBox.prototype.openDropDown = function () {
                void 0;
                if (this.isDropDownNeeded()) {
                    if (this.listBoxDirty) {
                        this.updateListBoxEntries();
                    }
                    this.$comboBox.addClass("open");
                    this.repositionDropDown();
                    this.isDropDownOpen = true;
                }
            };
            TrivialComboBox.prototype.closeDropDown = function () {
                this.$comboBox.removeClass("open");
                this.$dropDown.hide();
                this.isDropDownOpen = false;
            };
            TrivialComboBox.prototype.getNonSelectedEditorValue = function () {
                return this.$editor.val().substring(0, this.$editor[0].selectionStart);
            };
            TrivialComboBox.prototype.autoCompleteIfPossible = function (delay) {
                var _this = this;
                if (this.config.autoComplete) {
                    clearTimeout(this.autoCompleteTimeoutId);
                    var highlightedEntry_1 = this.listBox.getHighlightedEntry();
                    if (highlightedEntry_1 && !this.doNoAutoCompleteBecauseBackspaceWasPressed) {
                        this.autoCompleteTimeoutId = TrivialCore_1.setTimeoutOrDoImmediately(function () {
                            var currentEditorValue = _this.getNonSelectedEditorValue();
                            var autoCompleteString = _this.config.autoCompleteFunction(currentEditorValue, highlightedEntry_1) || currentEditorValue;
                            _this.$editor.val(currentEditorValue + autoCompleteString.substr(currentEditorValue.length));
                            if (_this.$editor.is(":focus")) {
                                _this.$editor[0].setSelectionRange(currentEditorValue.length, autoCompleteString.length);
                            }
                        }, delay);
                    }
                    this.doNoAutoCompleteBecauseBackspaceWasPressed = false;
                }
            };
            TrivialComboBox.prototype.updateListBoxEntries = function () {
                this.blurCausedByClickInsideComponent = false;
                this.listBox.updateEntries(this.entries);
                this.listBoxDirty = false;
            };
            TrivialComboBox.prototype.updateEntries = function (newEntries, highlightDirection) {
                this.entries = newEntries;
                this.$spinners.remove();
                this.$spinners = $();
                if (this.isDropDownOpen) {
                    this.updateListBoxEntries();
                }
                else {
                    this.listBoxDirty = true;
                }
                var nonSelectedEditorValue = this.getNonSelectedEditorValue();
                this.listBox.highlightTextMatches(newEntries.length <= this.config.textHighlightingEntryLimit ? nonSelectedEditorValue : null);
                if (highlightDirection == null) {
                    if (this.selectedEntry) {
                        this.listBox.setHighlightedEntry(null);
                    }
                    else {
                        this.listBox.highlightNextEntry(1);
                    }
                }
                else if (highlightDirection === 0) {
                    this.listBox.setHighlightedEntry(null);
                }
                else {
                    this.listBox.highlightNextEntry(highlightDirection);
                }
                this.autoCompleteIfPossible(this.config.autoCompleteDelay);
                if (this.isDropDownOpen) {
                    this.openDropDown();
                }
            };
            TrivialComboBox.prototype.isDropDownNeeded = function () {
                return this.editingMode == 'editable' && (this.config.entries && this.config.entries.length > 0 || !this.usingDefaultQueryFunction || this.config.showTrigger);
            };
            TrivialComboBox.prototype.setEditingMode = function (newEditingMode) {
                this.editingMode = newEditingMode;
                this.$comboBox.removeClass("editable readonly disabled").addClass(this.editingMode);
                if (this.isDropDownNeeded()) {
                    this.$dropDown.appendTo(this.$dropDownTargetElement);
                }
            };
            TrivialComboBox.prototype.getSelectedEntry = function () {
                if (this.selectedEntry == null && (!this.config.allowFreeText || !this.$editor.val())) {
                    return null;
                }
                else if (this.selectedEntry == null && this.config.allowFreeText) {
                    return this.config.freeTextEntryFactory(this.$editor.val());
                }
                else {
                    var selectedEntryToReturn = $.extend({}, this.selectedEntry);
                    selectedEntryToReturn._trEntryElement = undefined;
                    return selectedEntryToReturn;
                }
            };
            ;
            TrivialComboBox.prototype.focus = function () {
                this.showEditor();
                this.$editor.select();
            };
            ;
            TrivialComboBox.prototype.getEditor = function () {
                return this.$editor[0];
            };
            TrivialComboBox.prototype.getDropDown = function () {
                return this.$dropDown;
            };
            ;
            TrivialComboBox.prototype.destroy = function () {
                this.$originalInput.removeClass('tr-original-input').insertBefore(this.$comboBox);
                this.$comboBox.remove();
                this.$dropDown.remove();
            };
            ;
            TrivialComboBox.prototype.getMainDomElement = function () {
                return this.$comboBox[0];
            };
            return TrivialComboBox;
        }());
        exports.TrivialComboBox = TrivialComboBox;
    });
    
    
    var __assign = (this && this.__assign) || Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "moment"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var moment = require("moment");
        var TrivialDateSuggestionEngine = (function () {
            function TrivialDateSuggestionEngine(options) {
                this.options = __assign({ preferredDateFormat: "YYYY-MM-DD" }, options);
            }
            TrivialDateSuggestionEngine.prototype.generateSuggestions = function (searchString, now) {
                now = moment(now);
                var suggestions;
                if (searchString.match(/[^\d]/)) {
                    var fragments = searchString.split(/[^\d]/).filter(function (f) { return !!f; });
                    suggestions = this.createSuggestionsForFragments(fragments, now);
                }
                else {
                    suggestions = this.generateSuggestionsForDigitsOnlyInput(searchString, now);
                }
                var preferredYmdOrder = TrivialDateSuggestionEngine.dateFormatToYmdOrder(this.options.preferredDateFormat);
                suggestions.sort(function (a, b) {
                    if (preferredYmdOrder.indexOf(a.ymdOrder) === -1 && preferredYmdOrder.indexOf(b.ymdOrder) !== -1) {
                        return 1;
                    }
                    else if (preferredYmdOrder.indexOf(a.ymdOrder) !== -1 && preferredYmdOrder.indexOf(b.ymdOrder) === -1) {
                        return -1;
                    }
                    else if (a.ymdOrder.length != b.ymdOrder.length) {
                        return a.ymdOrder.length - b.ymdOrder.length;
                    }
                    else {
                        return a.moment.diff(now, 'days') - b.moment.diff(now, 'days');
                    }
                });
                suggestions = this.removeDuplicates(suggestions);
                return suggestions;
            };
            TrivialDateSuggestionEngine.prototype.removeDuplicates = function (suggestions) {
                var seenDates = [];
                return suggestions.filter(function (s) {
                    var dateAlreadyContained = seenDates.filter(function (seenDate) { return s.moment.isSame(seenDate, 'day'); }).length > 0;
                    if (dateAlreadyContained) {
                        return false;
                    }
                    else {
                        seenDates.push(s.moment);
                        return true;
                    }
                });
            };
            TrivialDateSuggestionEngine.dateFormatToYmdOrder = function (dateFormat) {
                var ymdIndexes = {
                    D: dateFormat.indexOf("D"),
                    M: dateFormat.indexOf("M"),
                    Y: dateFormat.indexOf("Y")
                };
                return (["D", "M", "Y"].sort(function (a, b) { return ymdIndexes[a] - ymdIndexes[b]; }).join(""));
            };
            TrivialDateSuggestionEngine.createSuggestion = function (moment, ymdOrder) {
                return { moment: moment, ymdOrder: ymdOrder };
            };
            TrivialDateSuggestionEngine.prototype.generateSuggestionsForDigitsOnlyInput = function (input, today) {
                input = input || "";
                if (input.length === 0) {
                    return this.createSuggestionsForFragments([], today);
                }
                else if (input.length > 8) {
                    return [];
                }
                var suggestions = [];
                for (var i = 1; i <= input.length; i++) {
                    for (var j = Math.min(input.length, i + 1); j <= input.length && j - i <= 4; j - i === 2 ? j += 2 : j++) {
                        suggestions = suggestions.concat(this.createSuggestionsForFragments([input.substring(0, i), input.substring(i, j), input.substring(j, input.length)], today));
                    }
                }
                return suggestions;
            };
            TrivialDateSuggestionEngine.prototype.todayOrFavoriteDirection = function (m, today) {
                return this.options.favorPastDates ? today.isSameOrAfter(m, 'day') : today.isSameOrBefore(m, 'day');
            };
            TrivialDateSuggestionEngine.prototype.createSuggestionsForFragments = function (fragments, today) {
                var _this = this;
                function mod(n, m) {
                    return ((n % m) + m) % m;
                }
                function numberToYear(n) {
                    var shortYear = today.year() % 100;
                    var yearSuggestionBoundary = (shortYear + 20) % 100;
                    var currentCentury = Math.floor(today.year() / 100) * 100;
                    if (n < yearSuggestionBoundary) {
                        return currentCentury + n;
                    }
                    else if (n < 100) {
                        return currentCentury - 100 + n;
                    }
                    else if (n > today.year() - 100 && n < today.year() + 100) {
                        return n;
                    }
                    else {
                        return null;
                    }
                }
                var s1 = fragments[0], s2 = fragments[1], s3 = fragments[2];
                var _a = [parseInt(s1), parseInt(s2), parseInt(s3)], n1 = _a[0], n2 = _a[1], n3 = _a[2];
                var suggestions = [];
                if (!s1 && !s2 && !s3) {
                    var result = [];
                    for (var i = 0; i < 7; i++) {
                        result.push(TrivialDateSuggestionEngine.createSuggestion(moment(today).add((this.options.favorPastDates ? -1 : 1) * i, "day"), ""));
                    }
                    return result;
                }
                else if (s1 && !s2 && !s3) {
                    if (n1 > 0 && n1 <= 31) {
                        var nextValidDate = this.findNextValidDate({ year: today.year(), month: today.month(), day: n1 }, function (currentDate) {
                            return {
                                year: currentDate.year + (_this.options.favorPastDates ? (currentDate.month == 0 ? -1 : 0) : (currentDate.month == 11 ? 1 : 0)),
                                month: mod(currentDate.month + (_this.options.favorPastDates ? -1 : 1), 12),
                                day: currentDate.day
                            };
                        }, today);
                        if (nextValidDate) {
                            suggestions.push(TrivialDateSuggestionEngine.createSuggestion(nextValidDate, "D"));
                        }
                    }
                }
                else if (s1 && s2 && !s3) {
                    if (n1 <= 12 && n2 > 0 && n2 <= 31) {
                        var nextValidDate = this.findNextValidDate({ year: today.year(), month: n1 - 1, day: n2 }, function (currentDate) {
                            return {
                                year: currentDate.year + (_this.options.favorPastDates ? -1 : 1),
                                month: currentDate.month,
                                day: currentDate.day
                            };
                        }, today);
                        if (nextValidDate) {
                            suggestions.push(TrivialDateSuggestionEngine.createSuggestion(nextValidDate, "MD"));
                        }
                    }
                    if (n2 <= 12 && n1 > 0 && n1 <= 31) {
                        var nextValidDate = this.findNextValidDate({ year: today.year(), month: n2 - 1, day: n1 }, function (currentDate) {
                            return {
                                year: currentDate.year + (_this.options.favorPastDates ? -1 : 1),
                                month: currentDate.month,
                                day: currentDate.day
                            };
                        }, today);
                        if (nextValidDate) {
                            suggestions.push(TrivialDateSuggestionEngine.createSuggestion(nextValidDate, "DM"));
                        }
                    }
                }
                else {
                    var mom = void 0;
                    mom = moment([numberToYear(n1), n2 - 1, s3]);
                    if (mom.isValid()) {
                        suggestions.push(TrivialDateSuggestionEngine.createSuggestion(mom, "YMD"));
                    }
                    mom = moment([numberToYear(n1), n3 - 1, s2]);
                    if (mom.isValid()) {
                        suggestions.push(TrivialDateSuggestionEngine.createSuggestion(mom, "YDM"));
                    }
                    mom = moment([numberToYear(n2), n1 - 1, s3]);
                    if (mom.isValid()) {
                        suggestions.push(TrivialDateSuggestionEngine.createSuggestion(mom, "MYD"));
                    }
                    mom = moment([numberToYear(n2), n3 - 1, s1]);
                    if (mom.isValid()) {
                        suggestions.push(TrivialDateSuggestionEngine.createSuggestion(mom, "DYM"));
                    }
                    mom = moment([numberToYear(n3), n1 - 1, s2]);
                    if (mom.isValid()) {
                        suggestions.push(TrivialDateSuggestionEngine.createSuggestion(mom, "MDY"));
                    }
                    mom = moment([numberToYear(n3), n2 - 1, s1]);
                    if (mom.isValid()) {
                        suggestions.push(TrivialDateSuggestionEngine.createSuggestion(mom, "DMY"));
                    }
                }
                return suggestions;
            };
            ;
            TrivialDateSuggestionEngine.prototype.findNextValidDate = function (startDate, incementor, today) {
                var currentDate = startDate;
                var momentInNextMonth = moment(startDate);
                var numberOfIterations = 0;
                while (!(momentInNextMonth.isValid() && this.todayOrFavoriteDirection(momentInNextMonth, today)) && numberOfIterations < 4) {
                    currentDate = incementor(currentDate);
                    momentInNextMonth = moment(currentDate);
                    numberOfIterations++;
                }
                return momentInNextMonth.isValid() ? momentInNextMonth : null;
            };
            return TrivialDateSuggestionEngine;
        }());
        exports.TrivialDateSuggestionEngine = TrivialDateSuggestionEngine;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "moment", "mustache", "./TrivialCore", "./TrivialEvent", "./TrivialListBox", "./TrivialCalendarBox", "./TrivialDateSuggestionEngine", "./TrivialTimeSuggestionEngine"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var moment = require("moment");
        var Mustache = require("mustache");
        var TrivialCore_1 = require("./TrivialCore");
        var TrivialEvent_1 = require("./TrivialEvent");
        var TrivialListBox_1 = require("./TrivialListBox");
        var TrivialCalendarBox_1 = require("./TrivialCalendarBox");
        var TrivialDateSuggestionEngine_1 = require("./TrivialDateSuggestionEngine");
        var TrivialTimeSuggestionEngine_1 = require("./TrivialTimeSuggestionEngine");
        var Mode;
        (function (Mode) {
            Mode[Mode["MODE_CALENDAR"] = 0] = "MODE_CALENDAR";
            Mode[Mode["MODE_DATE_LIST"] = 1] = "MODE_DATE_LIST";
            Mode[Mode["MODE_TIME_LIST"] = 2] = "MODE_TIME_LIST";
        })(Mode || (Mode = {}));
        var TrivialDateTimeField = (function () {
            function TrivialDateTimeField(originalInput, options) {
                if (options === void 0) { options = {}; }
                var _this = this;
                this.dateIconTemplate = "<svg viewBox=\"0 0 540 540\" width=\"22\" height=\"22\" class=\"calendar-icon\">\n    <defs>\n        <linearGradient id=\"Gradient1\" x1=\"0\" x2=\"0\" y1=\"0\" y2=\"1\">\n            <stop class=\"calendar-symbol-ring-gradient-stop1\" offset=\"0%\"/>\n            <stop class=\"calendar-symbol-ring-gradient-stop2\" offset=\"50%\"/>\n            <stop class=\"calendar-symbol-ring-gradient-stop3\" offset=\"100%\"/>\n        </linearGradient>\n    </defs>        \n    <g id=\"layer1\">\n        <rect class=\"calendar-symbol-page-background\" x=\"90\" y=\"90\" width=\"360\" height=\"400\" ry=\"3.8\"></rect>\n        <rect class=\"calendar-symbol-color\" x=\"90\" y=\"90\" width=\"360\" height=\"100\" ry=\"3.5\"></rect>\n        <rect class=\"calendar-symbol-page\" x=\"90\" y=\"90\" width=\"360\" height=\"395\" ry=\"3.8\"></rect>\n        <rect class=\"calendar-symbol-ring\" fill=\"url(#Gradient2)\" x=\"140\" y=\"30\" width=\"40\" height=\"120\" ry=\"30.8\"></rect>\n        <rect class=\"calendar-symbol-ring\" fill=\"url(#Gradient2)\" x=\"250\" y=\"30\" width=\"40\" height=\"120\" ry=\"30.8\"></rect>\n        <rect class=\"calendar-symbol-ring\" fill=\"url(#Gradient2)\" x=\"360\" y=\"30\" width=\"40\" height=\"120\" ry=\"30.8\"></rect>\n        <text class=\"calendar-symbol-date\" x=\"270\" y=\"415\" text-anchor=\"middle\">{{weekDay}}</text>\n    </g>\n</svg>";
                this.dateTemplate = '<div class="tr-template-icon-single-line">'
                    + this.dateIconTemplate
                    + '<div class="content-wrapper tr-editor-area">{{displayString}}</div>'
                    + '</div>';
                this.timeIconTemplate = '<svg class="clock-icon night-{{isNight}}" viewBox="0 0 110 110" width="22" height="22"> ' +
                    '<circle class="clockcircle" cx="55" cy="55" r="45"/>' +
                    '<g class="hands">' +
                    ' <line class="hourhand" x1="55" y1="55" x2="55" y2="35" {{#hourAngle}}transform="rotate({{hourAngle}},55,55)"{{/hourAngle}}/> ' +
                    ' <line class="minutehand" x1="55" y1="55" x2="55" y2="22" {{#minuteAngle}}transform="rotate({{minuteAngle}},55,55)"{{/minuteAngle}}/>' +
                    '</g> ' +
                    '</svg>';
                this.timeTemplate = '<div class="tr-template-icon-single-line">' +
                    this.timeIconTemplate +
                    '  <div class="content-wrapper tr-editor-area">{{displayString}}</div>' +
                    '</div>';
                this.onChange = new TrivialEvent_1.TrivialEvent(this);
                this.isDropDownOpen = false;
                this.dateValue = null;
                this.timeValue = null;
                this.blurCausedByClickInsideComponent = false;
                this.focusGoesToOtherEditor = false;
                this.autoCompleteTimeoutId = -1;
                this.doNoAutoCompleteBecauseBackspaceWasPressed = false;
                this.calendarBoxInitialized = false;
                this.dropDownMode = Mode.MODE_CALENDAR;
                options = options || {};
                this.config = $.extend({
                    dateFormat: "MM/DD/YYYY",
                    timeFormat: "HH:mm",
                    autoComplete: true,
                    autoCompleteDelay: 0,
                    showTrigger: true,
                    editingMode: "editable"
                }, options);
                this.$originalInput = $(originalInput).addClass("tr-original-input");
                this.$dateTimeField = $('<div class="tr-datetimefield tr-input-wrapper"/>')
                    .addClass(this.config.editingMode)
                    .insertAfter(this.$originalInput);
                var $editorWrapper = $('<div class="tr-editor-wrapper">').appendTo(this.$dateTimeField);
                this.$dateIconWrapper = $('<div class="tr-date-icon-wrapper"/>').appendTo($editorWrapper);
                this.$dateEditor = $('<div class="tr-date-editor" contenteditable="true"/>').appendTo($editorWrapper);
                this.$timeIconWrapper = $('<div class="tr-time-icon-wrapper"/>').appendTo($editorWrapper);
                this.$timeEditor = $('<div class="tr-time-editor" contenteditable="true"/>').appendTo($editorWrapper);
                this.$dateIconWrapper.click(function () {
                    _this.$activeEditor = _this.$dateEditor;
                    _this.setDropDownMode(Mode.MODE_CALENDAR);
                    _this.openDropDown();
                    TrivialCore_1.selectElementContents(_this.$dateEditor[0], 0, _this.$dateEditor.text().length);
                });
                this.$timeIconWrapper.click(function () {
                    _this.$activeEditor = _this.$timeEditor;
                    _this.setDropDownMode(Mode.MODE_CALENDAR);
                    TrivialCore_1.selectElementContents(_this.$timeEditor[0], 0, _this.$timeEditor.text().length);
                });
                this.$dateEditor.focus(function () {
                    _this.$activeEditor = _this.$dateEditor;
                    if (!_this.blurCausedByClickInsideComponent || _this.focusGoesToOtherEditor) {
                        TrivialCore_1.selectElementContents(_this.$dateEditor[0], 0, _this.$dateEditor.text().length);
                    }
                });
                this.$timeEditor.focus(function () {
                    _this.$activeEditor = _this.$timeEditor;
                    if (!_this.blurCausedByClickInsideComponent || _this.focusGoesToOtherEditor) {
                        TrivialCore_1.selectElementContents(_this.$timeEditor[0], 0, _this.$timeEditor.text().length);
                    }
                });
                if (this.config.showTrigger) {
                    var $trigger = $('<div class="tr-trigger"><span class="tr-trigger-icon"/></div>').appendTo(this.$dateTimeField);
                    $trigger.mousedown(function () {
                        if (_this.isDropDownOpen) {
                            _this.closeDropDown();
                        }
                        else {
                            setTimeout(function () {
                                _this.setDropDownMode(Mode.MODE_CALENDAR);
                                _this.calendarBox.setSelectedDate(_this.dateValue ? _this.dateValue.moment : moment());
                                _this.$activeEditor = _this.$dateEditor;
                                TrivialCore_1.selectElementContents(_this.$dateEditor[0], 0, _this.$dateEditor.text().length);
                                _this.openDropDown();
                            });
                        }
                    });
                }
                this.$dropDown = $('<div class="tr-dropdown"></div>')
                    .scroll(function () {
                    return false;
                });
                this.dropdownNeeded = this.config.editingMode == 'editable';
                if (this.dropdownNeeded) {
                    this.$dropDown.appendTo("body");
                }
                var $dateListBox = $('<div class="date-listbox">').appendTo(this.$dropDown);
                this.dateListBox = new TrivialListBox_1.TrivialListBox($dateListBox, {
                    entryRenderingFunction: function (entry) {
                        return Mustache.render(_this.dateTemplate, entry);
                    }
                });
                this.dateListBox.onSelectedEntryChanged.addListener(function (selectedEntry) {
                    if (selectedEntry) {
                        _this.setDate(selectedEntry, selectedEntry.displayString != (_this.dateValue && _this.dateValue.displayString));
                        _this.dateListBox.setSelectedEntry(null);
                        _this.closeDropDown();
                    }
                });
                var $timeListBox = $('<div class="time-listbox">').appendTo(this.$dropDown);
                this.timeListBox = new TrivialListBox_1.TrivialListBox($timeListBox, {
                    entryRenderingFunction: function (entry) {
                        return Mustache.render(_this.timeTemplate, entry);
                    }
                });
                this.timeListBox.onSelectedEntryChanged.addListener(function (selectedEntry) {
                    if (selectedEntry) {
                        _this.setTime(selectedEntry, selectedEntry.displayString != (_this.timeValue && _this.timeValue.displayString));
                        _this.dateListBox.setSelectedEntry(null);
                        _this.closeDropDown();
                    }
                });
                this.$calendarBox = $('<div class="calendarbox">').appendTo(this.$dropDown);
                this.$dateEditor
                    .add(this.$timeEditor)
                    .focus(function () {
                    _this.$dateTimeField.addClass('focus');
                })
                    .blur(function () {
                    if (!_this.blurCausedByClickInsideComponent) {
                        _this.$dateTimeField.removeClass('focus');
                        _this.updateDisplay();
                        _this.closeDropDown();
                    }
                })
                    .keydown(function (e) {
                    if (TrivialCore_1.keyCodes.isModifierKey(e)) {
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.tab) {
                        _this.selectHighlightedListBoxEntry();
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.left_arrow || e.which == TrivialCore_1.keyCodes.right_arrow) {
                        if (_this.getActiveEditor() === _this.$timeEditor && e.which == TrivialCore_1.keyCodes.left_arrow && window.getSelection().focusOffset === 0) {
                            e.preventDefault();
                            TrivialCore_1.selectElementContents(_this.$dateEditor[0], 0, _this.$dateEditor.text().length);
                        }
                        else if (_this.getActiveEditor() === _this.$dateEditor && e.which == TrivialCore_1.keyCodes.right_arrow && window.getSelection().focusOffset === _this.$dateEditor.text().length) {
                            e.preventDefault();
                            TrivialCore_1.selectElementContents(_this.$timeEditor[0], 0, _this.$timeEditor.text().length);
                        }
                        return;
                    }
                    if (e.which == TrivialCore_1.keyCodes.backspace || e.which == TrivialCore_1.keyCodes.delete) {
                        _this.doNoAutoCompleteBecauseBackspaceWasPressed = true;
                    }
                    if (e.which == TrivialCore_1.keyCodes.up_arrow || e.which == TrivialCore_1.keyCodes.down_arrow) {
                        _this.getActiveEditor().select();
                        var direction = e.which == TrivialCore_1.keyCodes.up_arrow ? -1 : 1;
                        if (_this.isDropDownOpen) {
                            _this.setDropDownMode(e.currentTarget === _this.$dateEditor[0] ? Mode.MODE_DATE_LIST : Mode.MODE_TIME_LIST);
                            _this.query(direction);
                            _this.openDropDown();
                        }
                        else {
                            if (_this.dropDownMode !== Mode.MODE_CALENDAR) {
                                _this.getActiveBox().navigate(direction === 1 ? 'down' : 'up');
                                _this.autoCompleteIfPossible(_this.config.autoCompleteDelay);
                            }
                        }
                        return false;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.enter) {
                        if (_this.isDropDownOpen) {
                            e.preventDefault();
                            _this.selectHighlightedListBoxEntry();
                            TrivialCore_1.selectElementContents(_this.getActiveEditor()[0], 0, _this.getActiveEditor().text().length);
                            _this.closeDropDown();
                        }
                    }
                    else if (e.which == TrivialCore_1.keyCodes.escape) {
                        e.preventDefault();
                        if (_this.isDropDownOpen) {
                            _this.updateDisplay();
                            TrivialCore_1.selectElementContents(_this.getActiveEditor()[0], 0, _this.getActiveEditor().text().length);
                        }
                        _this.closeDropDown();
                    }
                    else {
                        _this.setDropDownMode(e.currentTarget === _this.$dateEditor[0] ? Mode.MODE_DATE_LIST : Mode.MODE_TIME_LIST);
                        _this.query(1);
                        _this.openDropDown();
                    }
                });
                if (this.$originalInput.val()) {
                    this.setValue(moment(this.$originalInput.val()));
                }
                else {
                    this.setValue(null);
                }
                if (this.$originalInput.attr("tabindex")) {
                    this.$dateEditor.add(this.$timeEditor).attr("tabindex", this.$originalInput.attr("tabindex"));
                }
                if (this.$originalInput.attr("autofocus")) {
                    this.$dateEditor.focus();
                }
                this.$dateTimeField.add(this.$dropDown).mousedown(function (e) {
                    if (_this.$dateEditor.is(":focus") || _this.$timeEditor.is(":focus")) {
                        _this.blurCausedByClickInsideComponent = true;
                    }
                    if (e.target === _this.$dateEditor[0]
                        || e.target === _this.$timeEditor[0]
                        || e.target === _this.$dateIconWrapper[0]
                        || e.target === _this.$timeIconWrapper[0]) {
                        _this.focusGoesToOtherEditor = true;
                    }
                }).on('mouseup mouseout', function () {
                    if (_this.blurCausedByClickInsideComponent && !_this.focusGoesToOtherEditor) {
                        _this.getActiveEditor().focus();
                    }
                    _this.blurCausedByClickInsideComponent = false;
                    _this.focusGoesToOtherEditor = false;
                });
                this.$activeEditor = this.$dateEditor;
                this.dateSuggestionEngine = new TrivialDateSuggestionEngine_1.TrivialDateSuggestionEngine({
                    preferredDateFormat: this.config.dateFormat
                });
                this.timeSuggestionEngine = new TrivialTimeSuggestionEngine_1.TrivialTimeSuggestionEngine();
            }
            TrivialDateTimeField.prototype.setDropDownMode = function (mode) {
                var _this = this;
                this.dropDownMode = mode;
                if (!this.calendarBoxInitialized && mode === Mode.MODE_CALENDAR) {
                    this.calendarBox = new TrivialCalendarBox_1.TrivialCalendarBox(this.$calendarBox, {
                        firstDayOfWeek: 1,
                        mode: 'date'
                    });
                    this.calendarBox.setKeyboardNavigationState('month');
                    this.calendarBox.onChange.addListener(function (_a) {
                        var value = _a.value, timeUnitEdited = _a.timeUnitEdited;
                        _this.setDate(TrivialDateTimeField.createDateComboBoxEntry(value, _this.config.dateFormat));
                        if (timeUnitEdited === 'day') {
                            _this.closeDropDown();
                            _this.$activeEditor = _this.$timeEditor;
                            TrivialCore_1.selectElementContents(_this.$timeEditor[0], 0, _this.$timeEditor.text().length);
                            _this.fireChangeEvents();
                        }
                    });
                    this.calendarBoxInitialized = true;
                }
                this.calendarBoxInitialized && $(this.calendarBox.getMainDomElement()).toggle(mode === Mode.MODE_CALENDAR);
                $(this.dateListBox.getMainDomElement()).toggle(mode === Mode.MODE_DATE_LIST);
                $(this.timeListBox.getMainDomElement()).toggle(mode === Mode.MODE_TIME_LIST);
            };
            TrivialDateTimeField.prototype.getActiveBox = function () {
                if (this.dropDownMode === Mode.MODE_CALENDAR) {
                    return this.calendarBox;
                }
                else if (this.dropDownMode === Mode.MODE_DATE_LIST) {
                    return this.dateListBox;
                }
                else {
                    return this.timeListBox;
                }
            };
            TrivialDateTimeField.prototype.getActiveEditor = function () {
                return this.$activeEditor;
            };
            TrivialDateTimeField.prototype.selectHighlightedListBoxEntry = function () {
                if (this.dropDownMode === Mode.MODE_DATE_LIST || this.dropDownMode === Mode.MODE_TIME_LIST) {
                    var highlightedEntry = this.getActiveBox().getHighlightedEntry();
                    if (this.isDropDownOpen && highlightedEntry) {
                        if (this.getActiveEditor() === this.$dateEditor) {
                            this.setDate(highlightedEntry, true);
                        }
                        else {
                            this.setTime(highlightedEntry, true);
                        }
                    }
                }
            };
            TrivialDateTimeField.prototype.query = function (highlightDirection) {
                var _this = this;
                setTimeout(function () {
                    var queryString = _this.getNonSelectedEditorValue();
                    if (_this.getActiveEditor() === _this.$dateEditor) {
                        var entries = _this.dateSuggestionEngine.generateSuggestions(queryString, moment())
                            .map(function (s) { return TrivialDateTimeField.createDateComboBoxEntry(s.moment, _this.config.dateFormat); });
                        _this.updateEntries(entries, highlightDirection);
                    }
                    else {
                        var entries = _this.timeSuggestionEngine.generateSuggestions(queryString)
                            .map(function (s) { return TrivialDateTimeField.createTimeComboBoxEntry(s.hour, s.minute, _this.config.timeFormat); });
                        _this.updateEntries(entries, highlightDirection);
                    }
                }, 0);
            };
            TrivialDateTimeField.prototype.getValue = function () {
                if (this.dateValue == null && this.timeValue == null) {
                    return null;
                }
                else if (this.dateValue == null) {
                    return null;
                }
                else if (this.timeValue == null) {
                    return moment([
                        this.dateValue.year,
                        this.dateValue.month - 1,
                        this.dateValue.day
                    ]).startOf('day');
                }
                else {
                    return moment([
                        this.dateValue.year,
                        this.dateValue.month - 1,
                        this.dateValue.day,
                        this.timeValue.hour,
                        this.timeValue.minute
                    ]);
                }
            };
            ;
            TrivialDateTimeField.prototype.fireChangeEvents = function () {
                this.$originalInput.trigger("change");
                this.onChange.fire(this.getValue());
            };
            TrivialDateTimeField.prototype.setDate = function (newDateValue, fireEvent) {
                if (fireEvent === void 0) { fireEvent = false; }
                this.dateValue = newDateValue;
                this.updateDisplay();
                if (fireEvent) {
                    this.fireChangeEvents();
                }
            };
            TrivialDateTimeField.prototype.setTime = function (newTimeValue, fireEvent) {
                if (fireEvent === void 0) { fireEvent = false; }
                this.timeValue = newTimeValue;
                this.updateDisplay();
                if (fireEvent) {
                    this.fireChangeEvents();
                }
            };
            TrivialDateTimeField.prototype.updateDisplay = function () {
                if (this.dateValue) {
                    this.$dateEditor.text(moment([this.dateValue.year, this.dateValue.month - 1, this.dateValue.day]).format(this.config.dateFormat));
                    this.$dateIconWrapper.empty().append(Mustache.render(this.dateIconTemplate, this.dateValue));
                }
                else {
                    this.$dateEditor.text("");
                    this.$dateIconWrapper.empty().append(Mustache.render(this.dateIconTemplate, {}));
                }
                if (this.timeValue) {
                    this.$timeEditor.text(moment([1970, 0, 1, this.timeValue.hour, this.timeValue.minute]).format(this.config.timeFormat));
                    this.$timeIconWrapper.empty().append(Mustache.render(this.timeIconTemplate, this.timeValue));
                }
                else {
                    this.$timeEditor.text("");
                    this.$timeIconWrapper.empty().append(Mustache.render(this.timeIconTemplate, {}));
                }
            };
            TrivialDateTimeField.prototype.setValue = function (mom) {
                this.setDate(mom && TrivialDateTimeField.createDateComboBoxEntry(mom, this.config.dateFormat));
                this.setTime(mom && TrivialDateTimeField.createTimeComboBoxEntry(mom.hour(), mom.minute(), this.config.timeFormat));
            };
            TrivialDateTimeField.prototype.repositionDropDown = function () {
                var _this = this;
                this.$dropDown
                    .show()
                    .position({
                    my: "left top",
                    at: "left bottom",
                    of: this.$dateTimeField,
                    collision: "flip",
                    using: function (calculatedPosition, info) {
                        if (info.vertical === "top") {
                            _this.$dateTimeField.removeClass("dropdown-flipped");
                            _this.$dropDown.removeClass("flipped");
                        }
                        else {
                            _this.$dateTimeField.addClass("dropdown-flipped");
                            _this.$dropDown.addClass("flipped");
                        }
                        _this.$dropDown.css({
                            left: calculatedPosition.left + 'px',
                            top: calculatedPosition.top + 'px'
                        });
                    }
                })
                    .width(this.$dateTimeField.width());
            };
            TrivialDateTimeField.prototype.openDropDown = function () {
                if (this.dropdownNeeded) {
                    this.$dateTimeField.addClass("open");
                    this.repositionDropDown();
                    this.isDropDownOpen = true;
                }
            };
            TrivialDateTimeField.prototype.closeDropDown = function () {
                this.$dateTimeField.removeClass("open");
                this.$dropDown.hide();
                this.isDropDownOpen = false;
            };
            TrivialDateTimeField.prototype.getNonSelectedEditorValue = function () {
                var editorText = this.getActiveEditor().text().replace(String.fromCharCode(160), " ");
                var selection = window.getSelection();
                if (selection.anchorOffset != selection.focusOffset) {
                    return editorText.substring(0, Math.min(selection.anchorOffset, selection.focusOffset));
                }
                else {
                    return editorText;
                }
            };
            TrivialDateTimeField.prototype.autoCompleteIfPossible = function (delay) {
                var _this = this;
                if (this.config.autoComplete && (this.dropDownMode === Mode.MODE_DATE_LIST || this.dropDownMode === Mode.MODE_TIME_LIST)) {
                    clearTimeout(this.autoCompleteTimeoutId);
                    var listBox = this.getActiveBox();
                    var highlightedEntry = listBox.getHighlightedEntry();
                    if (highlightedEntry && this.doNoAutoCompleteBecauseBackspaceWasPressed) {
                        var autoCompletingEntryDisplayValue_1 = highlightedEntry.displayString;
                        if (autoCompletingEntryDisplayValue_1) {
                            this.autoCompleteTimeoutId = window.setTimeout(function () {
                                var oldEditorValue = _this.getNonSelectedEditorValue();
                                var newEditorValue;
                                if (autoCompletingEntryDisplayValue_1.toLowerCase().indexOf(oldEditorValue.toLowerCase()) === 0) {
                                    newEditorValue = oldEditorValue + autoCompletingEntryDisplayValue_1.substr(oldEditorValue.length);
                                }
                                else {
                                    newEditorValue = _this.getNonSelectedEditorValue();
                                }
                                _this.getActiveEditor().text(newEditorValue);
                                if (_this.getActiveEditor().is(":focus")) {
                                    TrivialCore_1.selectElementContents(_this.getActiveEditor()[0], oldEditorValue.length, newEditorValue.length);
                                }
                            }, delay || 0);
                        }
                    }
                    this.doNoAutoCompleteBecauseBackspaceWasPressed = false;
                }
            };
            TrivialDateTimeField.prototype.updateEntries = function (newEntries, highlightDirection) {
                var listBox = this.getActiveBox();
                highlightDirection = highlightDirection === undefined ? 1 : highlightDirection;
                listBox.updateEntries(newEntries);
                listBox.highlightTextMatches(this.getNonSelectedEditorValue());
                listBox.highlightNextEntry(highlightDirection);
                this.autoCompleteIfPossible(this.config.autoCompleteDelay);
                if (this.isDropDownOpen) {
                    this.openDropDown();
                }
            };
            TrivialDateTimeField.createTimeComboBoxEntry = function (hour, minute, timeFormat) {
                return {
                    hour: hour,
                    minute: minute,
                    hourString: TrivialDateTimeField.pad(hour, 2),
                    minuteString: TrivialDateTimeField.pad(minute, 2),
                    displayString: moment().hour(hour).minute(minute).format(timeFormat),
                    hourAngle: ((hour % 12) + minute / 60) * 30,
                    minuteAngle: minute * 6,
                    isNight: hour < 6 || hour >= 20
                };
            };
            TrivialDateTimeField.pad = function (num, size) {
                var s = num + "";
                while (s.length < size)
                    s = "0" + s;
                return s;
            };
            TrivialDateTimeField.createDateComboBoxEntry = function (m, dateFormat) {
                return {
                    moment: m,
                    day: m.date(),
                    weekDay: m.format('dd'),
                    month: m.month() + 1,
                    year: m.year(),
                    displayString: m.format(dateFormat)
                };
            };
            TrivialDateTimeField.prototype.focus = function () {
                TrivialCore_1.selectElementContents(this.getActiveEditor()[0], 0, this.getActiveEditor().text().length);
            };
            TrivialDateTimeField.prototype.destroy = function () {
                this.$originalInput.removeClass('tr-original-input').insertBefore(this.$dateTimeField);
                this.$dateTimeField.remove();
                this.$dropDown.remove();
            };
            TrivialDateTimeField.prototype.getMainDomElement = function () {
                return this.$dateTimeField[0];
            };
            return TrivialDateTimeField;
        }());
        exports.TrivialDateTimeField = TrivialDateTimeField;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var TrivialEvent = (function () {
            function TrivialEvent(eventSource) {
                this.eventSource = eventSource;
                this.listeners = [];
            }
            TrivialEvent.prototype.addListener = function (fn) {
                this.listeners.push(fn);
            };
            ;
            TrivialEvent.prototype.removeListener = function (fn) {
                var listenerIndex = this.listeners.indexOf(fn);
                if (listenerIndex != -1) {
                    this.listeners.splice(listenerIndex, 1);
                }
            };
            ;
            TrivialEvent.prototype.fire = function (eventObject, originalEvent) {
                for (var i = 0; i < this.listeners.length; i++) {
                    this.listeners[i].call(this.listeners[i], eventObject, this.eventSource, originalEvent);
                }
            };
            ;
            return TrivialEvent;
        }());
        exports.TrivialEvent = TrivialEvent;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "mustache", "./TrivialCore", "./TrivialEvent"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var Mustache = require("mustache");
        var TrivialCore_1 = require("./TrivialCore");
        var TrivialEvent_1 = require("./TrivialEvent");
        var TrivialListBox = (function () {
            function TrivialListBox($container, options) {
                if (options === void 0) { options = {}; }
                this.onSelectedEntryChanged = new TrivialEvent_1.TrivialEvent(this);
                this.config = $.extend({
                    entryRenderingFunction: function (entry) {
                        var template = entry.template || TrivialCore_1.DEFAULT_TEMPLATES.image2LinesTemplate;
                        return Mustache.render(template, entry);
                    },
                    selectedEntry: null,
                    spinnerTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultSpinnerTemplate,
                    entries: null,
                    matchingOptions: {
                        matchingMode: 'contains',
                        ignoreCase: true,
                        maxLevenshteinDistance: 2
                    },
                    noEntriesTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultNoEntriesTemplate
                }, options);
                this.$listBox = $('<div class="tr-listbox"/>').appendTo($container);
                var me = this;
                this.$listBox.on("mousedown", ".tr-listbox-entry", function (e) {
                    me.setSelectedEntry($(this).data("entry"), e, true);
                }).on("mouseup", ".tr-listbox-entry", function (e) {
                    me.$listBox.trigger("mouseup", e);
                }).on("mouseenter", ".tr-listbox-entry", function (e) {
                    me.setHighlightedEntry($(this).data("entry"));
                }).on("mouseleave", ".tr-listbox-entry", function (e) {
                    if (!$(e.toElement).is('.tr-listbox-entry')) {
                        me.setHighlightedEntry(null);
                    }
                });
                this.$entryList = $('<div class="tr-listbox-entry-list"></div>').appendTo(this.$listBox);
                if (this.config.entries) {
                    this.entries = this.config.entries;
                    this.updateEntryElements(this.entries);
                }
                this.$listBox.data("trivialListBox", this);
            }
            TrivialListBox.prototype.updateEntryElements = function (entries) {
                this.$entryList.detach();
                this.$entryList.empty();
                if (entries.length > 0) {
                    for (var i = 0; i < entries.length; i++) {
                        var entry = entries[i];
                        var $entry = void 0;
                        if (!entry._trEntryElement) {
                            var html = this.config.entryRenderingFunction(entry);
                            $entry = $(html).addClass("tr-listbox-entry filterable-item");
                        }
                        else {
                            $entry = entry._trEntryElement;
                        }
                        $entry.appendTo(this.$entryList)
                            .data("entry", entry);
                        entry._trEntryElement = $entry;
                    }
                }
                else {
                    this.$entryList.append(this.config.noEntriesTemplate);
                }
                this.$entryList.appendTo(this.$listBox);
            };
            TrivialListBox.prototype.updateEntries = function (newEntries) {
                if (newEntries == null) {
                    newEntries = [];
                }
                this.setHighlightedEntry(null);
                this.entries = newEntries;
                this.updateEntryElements(this.entries);
            };
            TrivialListBox.prototype.minimallyScrollTo = function ($entryWrapper) {
                TrivialCore_1.minimallyScrollTo(this.$listBox.parent(), $entryWrapper);
            };
            TrivialListBox.prototype.setHighlightedEntry = function (entry) {
                if (entry !== this.highlightedEntry) {
                    this.highlightedEntry = entry;
                    this.$entryList.find('.tr-listbox-entry').removeClass('tr-highlighted-entry');
                    if (entry != null) {
                        entry._trEntryElement.addClass('tr-highlighted-entry');
                        this.minimallyScrollTo(entry._trEntryElement);
                    }
                }
            };
            TrivialListBox.prototype.fireChangeEvents = function (selectedEntry, originalEvent) {
                this.$listBox.trigger("change");
                this.onSelectedEntryChanged.fire(selectedEntry, originalEvent);
            };
            TrivialListBox.prototype.setSelectedEntry = function (entry, originalEvent, fireEvent) {
                if (fireEvent === void 0) { fireEvent = false; }
                this.selectedEntry = entry;
                this.$entryList.find(".tr-selected-entry").removeClass("tr-selected-entry");
                if (entry != null) {
                    this.selectedEntry._trEntryElement.addClass("tr-selected-entry");
                }
                if (fireEvent) {
                    this.fireChangeEvents(this.selectedEntry, originalEvent);
                }
            };
            TrivialListBox.prototype.highlightNextEntry = function (direction) {
                var newHighlightedEntry = this.getNextHighlightableEntry(direction);
                if (newHighlightedEntry != null) {
                    this.setHighlightedEntry(newHighlightedEntry);
                }
            };
            TrivialListBox.prototype.getNextHighlightableEntry = function (direction) {
                var newHighlightedElementIndex;
                if (this.entries == null || this.entries.length == 0) {
                    return null;
                }
                else if (this.highlightedEntry == null && direction > 0) {
                    newHighlightedElementIndex = -1 + direction;
                }
                else if (this.highlightedEntry == null && direction < 0) {
                    newHighlightedElementIndex = this.entries.length + direction;
                }
                else {
                    var currentHighlightedElementIndex = this.entries.indexOf(this.highlightedEntry);
                    newHighlightedElementIndex = (currentHighlightedElementIndex + this.entries.length + direction) % this.entries.length;
                }
                return this.entries[newHighlightedElementIndex];
            };
            TrivialListBox.prototype.highlightTextMatches = function (searchString) {
                for (var i = 0; i < this.entries.length; i++) {
                    var $entryElement = this.entries[i]._trEntryElement;
                    $entryElement.trivialHighlight(searchString, this.config.matchingOptions);
                }
            };
            TrivialListBox.prototype.getSelectedEntry = function () {
                if (this.selectedEntry) {
                    var selectedEntryToReturn = $.extend({}, this.selectedEntry);
                    selectedEntryToReturn._trEntryElement = undefined;
                    return selectedEntryToReturn;
                }
                else {
                    return null;
                }
            };
            TrivialListBox.prototype.getHighlightedEntry = function () {
                return this.highlightedEntry;
            };
            ;
            TrivialListBox.prototype.navigate = function (direction) {
                if (direction === 'up') {
                    this.highlightNextEntry(-1);
                }
                else if (direction === 'down') {
                    this.highlightNextEntry(1);
                }
            };
            TrivialListBox.prototype.getMainDomElement = function () {
                return this.$listBox[0];
            };
            TrivialListBox.prototype.destroy = function () {
                this.$listBox.remove();
            };
            ;
            return TrivialListBox;
        }());
        exports.TrivialListBox = TrivialListBox;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "mustache", "./TrivialListBox", "./TrivialCore", "./TrivialEvent"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var Mustache = require("mustache");
        var TrivialListBox_1 = require("./TrivialListBox");
        var TrivialCore_1 = require("./TrivialCore");
        var TrivialEvent_1 = require("./TrivialEvent");
        var TrivialTagComboBox = (function () {
            function TrivialTagComboBox(originalInput, options) {
                var _this = this;
                this.$spinners = $();
                this.onSelectedEntryChanged = new TrivialEvent_1.TrivialEvent(this);
                this.onFocus = new TrivialEvent_1.TrivialEvent(this);
                this.onBlur = new TrivialEvent_1.TrivialEvent(this);
                this.isDropDownOpen = false;
                this.lastQueryString = null;
                this.lastCompleteInputQueryString = null;
                this.selectedEntries = [];
                this.blurCausedByClickInsideComponent = false;
                this.autoCompleteTimeoutId = -1;
                this.doNoAutoCompleteBecauseBackspaceWasPressed = false;
                this.listBoxDirty = true;
                this.repositionDropDownScheduler = null;
                options = options || {};
                this.config = $.extend({
                    valueFunction: function (entries) { return entries.map(function (e) { return e._isFreeTextEntry ? e.displayValue : e.id; }).join(','); },
                    entryRenderingFunction: function (entry) {
                        return Mustache.render(TrivialCore_1.DEFAULT_TEMPLATES.image2LinesTemplate, entry);
                    },
                    selectedEntryRenderingFunction: function (entry) {
                        return TrivialCore_1.wrapWithDefaultTagWrapper(_this.config.entryRenderingFunction(entry));
                    },
                    spinnerTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultSpinnerTemplate,
                    noEntriesTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultNoEntriesTemplate,
                    textHighlightingEntryLimit: 100,
                    entries: null,
                    selectedEntries: [],
                    maxSelectedEntries: null,
                    queryFunction: null,
                    autoComplete: true,
                    autoCompleteDelay: 0,
                    autoCompleteFunction: function (editorText, entry) {
                        if (editorText) {
                            for (var propertyName in entry) {
                                if (entry.hasOwnProperty(propertyName)) {
                                    var propertyValue = entry[propertyName];
                                    if (propertyValue && ("" + propertyValue).toLowerCase().indexOf(editorText.toLowerCase()) === 0) {
                                        return "" + propertyValue;
                                    }
                                }
                            }
                            return null;
                        }
                        else {
                            return null;
                        }
                    },
                    allowFreeText: false,
                    freeTextSeparators: [',', ';'],
                    freeTextEntryFactory: function (freeText) {
                        return {
                            displayValue: freeText,
                            _isFreeTextEntry: true
                        };
                    },
                    showTrigger: true,
                    distinct: true,
                    matchingOptions: {
                        matchingMode: 'contains',
                        ignoreCase: true,
                        maxLevenshteinDistance: 2
                    },
                    editingMode: "editable",
                    showDropDownOnResultsOnly: false
                }, options);
                if (!this.config.queryFunction) {
                    this.config.queryFunction = TrivialCore_1.defaultListQueryFunctionFactory(this.config.entries || [], this.config.matchingOptions);
                    this.usingDefaultQueryFunction = true;
                }
                this.entries = this.config.entries;
                this.$originalInput = $(originalInput).addClass("tr-original-input");
                this.$tagComboBox = $('<div class="tr-tagbox tr-input-wrapper"/>')
                    .insertAfter(this.$originalInput);
                this.$originalInput.appendTo(this.$tagComboBox);
                var $tagArea = $('<div class="tr-tagbox-tagarea"/>').appendTo(this.$tagComboBox);
                if (this.config.showTrigger) {
                    this.$trigger = $('<div class="tr-trigger"><span class="tr-trigger-icon"/></div>').appendTo(this.$tagComboBox);
                    this.$trigger.mousedown(function () {
                        _this.$editor.focus();
                        if (_this.isDropDownOpen) {
                            _this.closeDropDown();
                        }
                        else {
                            setTimeout(function () {
                                _this.$editor.select();
                                _this.openDropDown();
                                _this.query();
                            });
                        }
                    });
                }
                this.$dropDown = $('<div class="tr-dropdown"></div>')
                    .scroll(function () {
                    return false;
                });
                this.$dropDownTargetElement = $("body");
                this.setEditingMode(this.config.editingMode);
                this.$editor = $('<span contenteditable="true" class="tagbox-editor" autocomplete="off"></span>');
                this.$editor.appendTo($tagArea).addClass("tr-tagbox-editor tr-editor")
                    .focus(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                    }
                    else {
                        _this.$originalInput.triggerHandler('focus');
                        _this.onFocus.fire();
                        _this.$tagComboBox.addClass('focus');
                    }
                    setTimeout(function () {
                        TrivialCore_1.minimallyScrollTo($tagArea, _this.$editor);
                    });
                })
                    .blur(function (e) {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                    }
                    else {
                        _this.$originalInput.triggerHandler('blur');
                        _this.onBlur.fire();
                        _this.$tagComboBox.removeClass('focus');
                        _this.entries = null;
                        _this.closeDropDown();
                        if (_this.config.allowFreeText && _this.$editor.text().trim().length > 0) {
                            _this.setSelectedEntry(_this.config.freeTextEntryFactory(_this.$editor.text()), true, e);
                        }
                        _this.$editor.text("");
                    }
                })
                    .keydown(function (e) {
                    if (TrivialCore_1.keyCodes.isModifierKey(e)) {
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.tab) {
                        var highlightedEntry = _this.listBox.getHighlightedEntry();
                        if (_this.isDropDownOpen && highlightedEntry) {
                            _this.setSelectedEntry(highlightedEntry, true, e);
                        }
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.left_arrow || e.which == TrivialCore_1.keyCodes.right_arrow) {
                        if (e.which == TrivialCore_1.keyCodes.left_arrow && _this.$editor.text().length === 0 && window.getSelection().anchorOffset === 0) {
                            if (_this.$editor.prev()) {
                                _this.$editor.insertBefore(_this.$editor.prev());
                                _this.$editor.focus();
                            }
                        }
                        else if (e.which == TrivialCore_1.keyCodes.right_arrow && _this.$editor.text().length === 0 && window.getSelection().anchorOffset === 0) {
                            if (_this.$editor.next()) {
                                _this.$editor.insertAfter(_this.$editor.next());
                                _this.$editor.focus();
                            }
                        }
                        return;
                    }
                    if (e.which == TrivialCore_1.keyCodes.backspace || e.which == TrivialCore_1.keyCodes.delete) {
                        if (_this.$editor.text() == "") {
                            var tagToBeRemoved = _this.selectedEntries[_this.$editor.index() + (e.which == TrivialCore_1.keyCodes.backspace ? -1 : 0)];
                            if (tagToBeRemoved) {
                                _this.removeTag(tagToBeRemoved, e);
                                _this.closeDropDown();
                            }
                        }
                        else {
                            _this.doNoAutoCompleteBecauseBackspaceWasPressed = true;
                            _this.query(1);
                        }
                        return;
                    }
                    if (e.which == TrivialCore_1.keyCodes.up_arrow || e.which == TrivialCore_1.keyCodes.down_arrow) {
                        _this.openDropDown();
                        var direction = e.which == TrivialCore_1.keyCodes.up_arrow ? -1 : 1;
                        if (!_this.isDropDownOpen) {
                            _this.query(direction);
                            if (!_this.config.showDropDownOnResultsOnly) {
                                _this.openDropDown();
                            }
                        }
                        else {
                            _this.listBox.highlightNextEntry(direction);
                            _this.autoCompleteIfPossible(_this.config.autoCompleteDelay);
                        }
                        return false;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.enter) {
                        var highlightedEntry = _this.listBox.getHighlightedEntry();
                        if (_this.isDropDownOpen && highlightedEntry != null) {
                            _this.setSelectedEntry(highlightedEntry, true, e);
                            _this.entries = null;
                        }
                        else if (_this.config.allowFreeText && _this.$editor.text().trim().length > 0) {
                            _this.setSelectedEntry(_this.config.freeTextEntryFactory(_this.$editor.text()), false, e);
                        }
                        _this.closeDropDown();
                        e.preventDefault();
                    }
                    else if (e.which == TrivialCore_1.keyCodes.escape) {
                        _this.closeDropDown();
                        _this.$editor.text("");
                    }
                    else {
                        if (!_this.config.showDropDownOnResultsOnly) {
                            _this.openDropDown();
                        }
                        _this.query(1);
                    }
                })
                    .keyup(function (e) {
                    function splitStringBySeparatorChars(s, separatorChars) {
                        return s.split(new RegExp("[" + TrivialCore_1.escapeSpecialRegexCharacter(separatorChars.join()) + "]"));
                    }
                    if (_this.$editor.find('*').length > 0) {
                        _this.$editor.text(_this.$editor.text());
                    }
                    if (_this.config.allowFreeText) {
                        var editorValueBeforeCursor = _this.getNonSelectedEditorValue();
                        if (editorValueBeforeCursor.length > 0) {
                            var tagValuesEnteredByUser = splitStringBySeparatorChars(editorValueBeforeCursor, _this.config.freeTextSeparators);
                            for (var i = 0; i < tagValuesEnteredByUser.length - 1; i++) {
                                var value = tagValuesEnteredByUser[i].trim();
                                if (value.length > 0) {
                                    _this.setSelectedEntry(_this.config.freeTextEntryFactory(value), true, e);
                                }
                                _this.$editor.text(tagValuesEnteredByUser[tagValuesEnteredByUser.length - 1]);
                                TrivialCore_1.selectElementContents(_this.$editor[0], _this.$editor.text().length, _this.$editor.text().length);
                                _this.entries = null;
                                _this.closeDropDown();
                            }
                        }
                    }
                })
                    .mousedown(function () {
                    if (!_this.config.showDropDownOnResultsOnly) {
                        _this.openDropDown();
                    }
                    _this.query();
                });
                if (this.$originalInput.attr("placeholder")) {
                    this.$editor.attr("placeholder", this.$originalInput.attr("placeholder"));
                }
                if (this.$originalInput.attr("tabindex")) {
                    this.$editor.attr("tabindex", this.$originalInput.attr("tabindex"));
                }
                if (this.$originalInput.attr("autofocus")) {
                    this.$editor.focus();
                }
                this.$tagComboBox.add(this.$dropDown).mousedown(function () {
                    if (_this.$editor.is(":focus")) {
                        _this.blurCausedByClickInsideComponent = true;
                    }
                }).mouseup(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                        setTimeout(function () { return _this.blurCausedByClickInsideComponent = false; });
                    }
                }).mouseout(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                        setTimeout(function () { return _this.blurCausedByClickInsideComponent = false; });
                    }
                });
                var configWithoutEntries = $.extend({}, this.config);
                configWithoutEntries.entries = [];
                this.listBox = new TrivialListBox_1.TrivialListBox(this.$dropDown, configWithoutEntries);
                this.listBox.onSelectedEntryChanged.addListener(function (selectedEntry, eventSource, originalEvent) {
                    if (selectedEntry) {
                        _this.setSelectedEntry(selectedEntry, true, originalEvent);
                        _this.listBox.setSelectedEntry(null);
                        _this.closeDropDown();
                    }
                });
                $tagArea.click(function (e) {
                    if (!_this.config.showDropDownOnResultsOnly) {
                        _this.openDropDown();
                    }
                    _this.query();
                    var $tagWithSmallestDistance = null;
                    var smallestDistanceX = 1000000;
                    for (var i = 0; i < _this.selectedEntries.length; i++) {
                        var selectedEntry = _this.selectedEntries[i];
                        var $tag = selectedEntry._trEntryElement;
                        var tagBoundingRect = $tag[0].getBoundingClientRect();
                        var sameRow = e.clientY >= tagBoundingRect.top && e.clientY < tagBoundingRect.bottom;
                        var sameCol = e.clientX >= tagBoundingRect.left && e.clientX < tagBoundingRect.right;
                        var distanceX = sameCol ? 0 : Math.min(Math.abs(e.clientX - tagBoundingRect.left), Math.abs(e.clientX - tagBoundingRect.right));
                        if (sameRow && distanceX < smallestDistanceX) {
                            $tagWithSmallestDistance = $tag;
                            smallestDistanceX = distanceX;
                            if (distanceX === 0) {
                                break;
                            }
                        }
                    }
                    if ($tagWithSmallestDistance) {
                        var tagBoundingRect = $tagWithSmallestDistance[0].getBoundingClientRect();
                        var isRightSide = e.clientX > (tagBoundingRect.left + tagBoundingRect.right) / 2;
                        if (isRightSide) {
                            _this.$editor.insertAfter($tagWithSmallestDistance);
                        }
                        else {
                            _this.$editor.insertBefore($tagWithSmallestDistance);
                        }
                    }
                    _this.$editor.focus();
                });
                this.setSelectedEntries(this.config.selectedEntries);
                this.$tagComboBox.data("trivialTagComboBox", this);
            }
            TrivialTagComboBox.prototype.updateListBoxEntries = function () {
                this.blurCausedByClickInsideComponent = false;
                this.listBox.updateEntries(this.entries);
                this.listBoxDirty = false;
            };
            TrivialTagComboBox.prototype.updateEntries = function (newEntries, highlightDirection) {
                this.entries = newEntries;
                this.$spinners.remove();
                this.$spinners = $();
                if (this.isDropDownOpen) {
                    this.updateListBoxEntries();
                }
                else {
                    this.listBoxDirty = true;
                }
                var nonSelectedEditorValue = this.getNonSelectedEditorValue();
                this.listBox.highlightTextMatches(newEntries.length <= this.config.textHighlightingEntryLimit ? nonSelectedEditorValue : null);
                if (highlightDirection) {
                    this.listBox.highlightNextEntry(highlightDirection);
                }
                else {
                    this.listBox.setHighlightedEntry(null);
                }
                this.autoCompleteIfPossible(this.config.autoCompleteDelay);
                if (this.isDropDownOpen) {
                    this.openDropDown();
                }
            };
            TrivialTagComboBox.prototype.removeTag = function (tagToBeRemoved, originalEvent) {
                var index = this.selectedEntries.indexOf(tagToBeRemoved);
                if (index > -1) {
                    this.selectedEntries.splice(index, 1);
                }
                tagToBeRemoved._trEntryElement.remove();
                this.$originalInput.val(this.config.valueFunction(this.getSelectedEntries()));
                this.fireChangeEvents(this.getSelectedEntries(), originalEvent);
            };
            TrivialTagComboBox.prototype.query = function (highlightDirection) {
                var _this = this;
                setTimeout(function () {
                    var queryString = _this.getNonSelectedEditorValue();
                    var completeInputString = _this.$editor.text().replace(String.fromCharCode(160), " ");
                    if (_this.lastQueryString !== queryString || _this.lastCompleteInputQueryString !== completeInputString) {
                        if (_this.$spinners.length === 0) {
                            var $spinner = $(_this.config.spinnerTemplate).appendTo(_this.$dropDown);
                            _this.$spinners = _this.$spinners.add($spinner);
                        }
                        _this.config.queryFunction(queryString, function (newEntries) {
                            _this.updateEntries(newEntries, highlightDirection);
                            if (_this.config.showDropDownOnResultsOnly && newEntries && newEntries.length > 0 && _this.$editor.is(":focus")) {
                                _this.openDropDown();
                            }
                        });
                        _this.lastQueryString = queryString;
                        _this.lastCompleteInputQueryString = completeInputString;
                    }
                }, 0);
            };
            TrivialTagComboBox.prototype.fireChangeEvents = function (entries, originalEvent) {
                this.$originalInput.trigger("change");
                this.onSelectedEntryChanged.fire(entries, originalEvent);
            };
            TrivialTagComboBox.prototype.setSelectedEntry = function (entry, fireEvent, originalEvent) {
                var _this = this;
                if (fireEvent === void 0) { fireEvent = false; }
                if (entry == null) {
                    return;
                }
                if (this.config.maxSelectedEntries && this.selectedEntries.length >= this.config.maxSelectedEntries) {
                    return;
                }
                if (this.config.distinct && this.selectedEntries.map(function (entry) {
                    return _this.config.valueFunction([entry]);
                }).indexOf(this.config.valueFunction([entry])) != -1) {
                    return;
                }
                var tag = $.extend({}, entry);
                this.selectedEntries.splice(this.$editor.index(), 0, tag);
                this.$originalInput.val(this.config.valueFunction(this.getSelectedEntries()));
                var $entry = $(this.config.selectedEntryRenderingFunction(tag));
                var $tagWrapper = $('<div class="tr-tagbox-tag"></div>');
                $tagWrapper.append($entry).insertBefore(this.$editor);
                tag._trEntryElement = $tagWrapper;
                if (this.config.editingMode == "editable") {
                    $entry.find('.tr-remove-button').click(function (e) {
                        _this.removeTag(tag);
                        return false;
                    });
                }
                this.$editor.text("");
                if (fireEvent) {
                    this.fireChangeEvents(this.getSelectedEntries(), originalEvent);
                }
            };
            TrivialTagComboBox.prototype.repositionDropDown = function () {
                var _this = this;
                this.$dropDown.position({
                    my: "left top",
                    at: "left bottom",
                    of: this.$tagComboBox,
                    collision: "flip",
                    using: function (calculatedPosition, info) {
                        if (info.vertical === "top") {
                            _this.$tagComboBox.removeClass("dropdown-flipped");
                            _this.$dropDown.removeClass("flipped");
                        }
                        else {
                            _this.$tagComboBox.addClass("dropdown-flipped");
                            _this.$dropDown.addClass("flipped");
                        }
                        _this.$dropDown.css({
                            left: calculatedPosition.left + 'px',
                            top: calculatedPosition.top + 'px'
                        });
                    }
                }).width(this.$tagComboBox.width());
            };
            TrivialTagComboBox.prototype.openDropDown = function () {
                var _this = this;
                if (this.isDropDownNeeded()) {
                    if (this.listBoxDirty) {
                        this.updateListBoxEntries();
                    }
                    this.$tagComboBox.addClass("open");
                    this.$dropDown.show();
                    this.repositionDropDown();
                    this.isDropDownOpen = true;
                }
                if (this.repositionDropDownScheduler == null) {
                    this.repositionDropDownScheduler = window.setInterval(function () { return _this.repositionDropDown(); }, 1000);
                }
            };
            TrivialTagComboBox.prototype.closeDropDown = function () {
                this.$tagComboBox.removeClass("open");
                this.$dropDown.hide();
                this.isDropDownOpen = false;
                if (this.repositionDropDownScheduler != null) {
                    clearInterval(this.repositionDropDownScheduler);
                }
            };
            TrivialTagComboBox.prototype.getNonSelectedEditorValue = function () {
                var editorText = this.$editor.text().replace(String.fromCharCode(160), " ");
                var selection = window.getSelection();
                if (selection.anchorOffset != selection.focusOffset) {
                    return editorText.substring(0, Math.min(window.getSelection().baseOffset, window.getSelection().focusOffset));
                }
                else {
                    return editorText;
                }
            };
            TrivialTagComboBox.prototype.autoCompleteIfPossible = function (delay) {
                var _this = this;
                if (this.config.autoComplete) {
                    clearTimeout(this.autoCompleteTimeoutId);
                    var highlightedEntry_1 = this.listBox.getHighlightedEntry();
                    if (highlightedEntry_1 && !this.doNoAutoCompleteBecauseBackspaceWasPressed) {
                        this.autoCompleteTimeoutId = window.setTimeout(function () {
                            var currentEditorValue = _this.getNonSelectedEditorValue();
                            var autoCompleteString = _this.config.autoCompleteFunction(currentEditorValue, highlightedEntry_1) || currentEditorValue;
                            _this.$editor.text(currentEditorValue + autoCompleteString.replace(' ', String.fromCharCode(160)).substr(currentEditorValue.length));
                            _this.repositionDropDown();
                            if (_this.$editor.is(":focus")) {
                                TrivialCore_1.selectElementContents(_this.$editor[0], currentEditorValue.length, autoCompleteString.length);
                            }
                        }, delay || 0);
                    }
                    this.doNoAutoCompleteBecauseBackspaceWasPressed = false;
                }
            };
            TrivialTagComboBox.prototype.isDropDownNeeded = function () {
                return this.editingMode == 'editable' && (this.config.entries && this.config.entries.length > 0 || !this.usingDefaultQueryFunction || this.config.showTrigger);
            };
            TrivialTagComboBox.prototype.setEditingMode = function (newEditingMode) {
                this.editingMode = newEditingMode;
                this.$tagComboBox.removeClass("editable readonly disabled").addClass(this.editingMode);
                if (this.isDropDownNeeded()) {
                    this.$dropDown.appendTo(this.$dropDownTargetElement);
                }
            };
            TrivialTagComboBox.prototype.setSelectedEntries = function (entries) {
                var _this = this;
                this.selectedEntries
                    .slice()
                    .forEach(function (e) { return _this.removeTag(e); });
                if (entries) {
                    for (var i = 0; i < entries.length; i++) {
                        this.setSelectedEntry(entries[i]);
                    }
                }
            };
            TrivialTagComboBox.prototype.getSelectedEntries = function () {
                var selectedEntriesToReturn = [];
                for (var i = 0; i < this.selectedEntries.length; i++) {
                    var selectedEntryToReturn = $.extend({}, this.selectedEntries[i]);
                    selectedEntryToReturn._trEntryElement = undefined;
                    selectedEntriesToReturn.push(selectedEntryToReturn);
                }
                return selectedEntriesToReturn;
            };
            ;
            TrivialTagComboBox.prototype.focus = function () {
                this.$editor.focus();
                TrivialCore_1.selectElementContents(this.$editor[0], 0, this.$editor.text().length);
            };
            ;
            TrivialTagComboBox.prototype.getEditor = function () {
                return this.$editor[0];
            };
            TrivialTagComboBox.prototype.destroy = function () {
                this.$originalInput.removeClass('tr-original-input').insertBefore(this.$tagComboBox);
                this.$tagComboBox.remove();
                this.$dropDown.remove();
            };
            ;
            TrivialTagComboBox.prototype.getMainDomElement = function () {
                return this.$tagComboBox[0];
            };
            return TrivialTagComboBox;
        }());
        exports.TrivialTagComboBox = TrivialTagComboBox;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var TrivialTimeSuggestionEngine = (function () {
            function TrivialTimeSuggestionEngine() {
            }
            TrivialTimeSuggestionEngine.prototype.generateSuggestions = function (searchString) {
                var suggestions = [];
                var match = searchString.match(/[^\d]/);
                var colonIndex = match != null ? match.index : null;
                if (colonIndex !== null) {
                    var hourString = searchString.substring(0, colonIndex);
                    var minuteString = searchString.substring(colonIndex + 1);
                    suggestions = suggestions.concat(TrivialTimeSuggestionEngine.createTimeSuggestions(TrivialTimeSuggestionEngine.createHourSuggestions(hourString), TrivialTimeSuggestionEngine.createMinuteSuggestions(minuteString)));
                }
                else if (searchString.length > 0) {
                    if (searchString.length >= 2) {
                        var hourString_1 = searchString.substr(0, 2);
                        var minuteString_1 = searchString.substring(2, searchString.length);
                        suggestions = suggestions.concat(TrivialTimeSuggestionEngine.createTimeSuggestions(TrivialTimeSuggestionEngine.createHourSuggestions(hourString_1), TrivialTimeSuggestionEngine.createMinuteSuggestions(minuteString_1)));
                    }
                    var hourString = searchString.substr(0, 1);
                    var minuteString = searchString.substring(1, searchString.length);
                    if (minuteString.length <= 2) {
                        suggestions = suggestions.concat(TrivialTimeSuggestionEngine.createTimeSuggestions(TrivialTimeSuggestionEngine.createHourSuggestions(hourString), TrivialTimeSuggestionEngine.createMinuteSuggestions(minuteString)));
                    }
                }
                else {
                    suggestions = suggestions.concat(TrivialTimeSuggestionEngine.createTimeSuggestions(TrivialTimeSuggestionEngine.intRange(6, 24).concat(TrivialTimeSuggestionEngine.intRange(1, 5)), [0]));
                }
                return suggestions;
            };
            TrivialTimeSuggestionEngine.intRange = function (fromInclusive, toInclusive) {
                var ints = [];
                for (var i = fromInclusive; i <= toInclusive; i++) {
                    ints.push(i);
                }
                return ints;
            };
            TrivialTimeSuggestionEngine.createTimeSuggestions = function (hourValues, minuteValues) {
                var entries = [];
                for (var i = 0; i < hourValues.length; i++) {
                    var hour = hourValues[i];
                    for (var j = 0; j < minuteValues.length; j++) {
                        var minute = minuteValues[j];
                        entries.push({ hour: hour, minute: minute });
                    }
                }
                return entries;
            };
            TrivialTimeSuggestionEngine.createMinuteSuggestions = function (minuteString) {
                var m = parseInt(minuteString);
                if (isNaN(m)) {
                    return [0];
                }
                else if (minuteString.length > 1) {
                    return [m % 60];
                }
                else if (m < 6) {
                    return [m * 10];
                }
                else {
                    return [m % 60];
                }
            };
            TrivialTimeSuggestionEngine.createHourSuggestions = function (hourString) {
                var h = parseInt(hourString);
                if (isNaN(h)) {
                    return TrivialTimeSuggestionEngine.intRange(1, 24);
                }
                else if (h < 12) {
                    return [h, (h + 12) % 24];
                }
                else if (h <= 24) {
                    return [h % 24];
                }
                else {
                    return [];
                }
            };
            return TrivialTimeSuggestionEngine;
        }());
        exports.TrivialTimeSuggestionEngine = TrivialTimeSuggestionEngine;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "mustache", "./TrivialTreeBox", "./TrivialCore", "./TrivialEvent"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var Mustache = require("mustache");
        var TrivialTreeBox_1 = require("./TrivialTreeBox");
        var TrivialCore_1 = require("./TrivialCore");
        var TrivialEvent_1 = require("./TrivialEvent");
        var TrivialTree = (function () {
            function TrivialTree(originalInput, options) {
                if (options === void 0) { options = {}; }
                var _this = this;
                this.onSelectedEntryChanged = new TrivialEvent_1.TrivialEvent(this);
                this.onNodeExpansionStateChanged = new TrivialEvent_1.TrivialEvent(this);
                this.$spinners = $();
                this.config = $.extend({
                    valueFunction: function (entry) { return entry ? "" + entry.id : null; },
                    childrenProperty: "children",
                    lazyChildrenFlagProperty: "hasLazyChildren",
                    searchBarMode: 'show-if-filled',
                    lazyChildrenQueryFunction: function (node, resultCallback) {
                        resultCallback([]);
                    },
                    expandedProperty: 'expanded',
                    entryRenderingFunction: function (entry, depth) {
                        var defaultTemplates = [TrivialCore_1.DEFAULT_TEMPLATES.icon2LinesTemplate, TrivialCore_1.DEFAULT_TEMPLATES.iconSingleLineTemplate];
                        var template = entry.template || defaultTemplates[Math.min(depth, defaultTemplates.length - 1)];
                        return Mustache.render(template, entry);
                    },
                    spinnerTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultSpinnerTemplate,
                    noEntriesTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultNoEntriesTemplate,
                    entries: null,
                    queryFunction: null,
                    selectedEntryId: null,
                    matchingOptions: {
                        matchingMode: 'contains',
                        ignoreCase: true,
                        maxLevenshteinDistance: 2
                    },
                    directSelectionViaArrowKeys: false,
                    performanceOptimizationSettings: {
                        toManyVisibleItemsRenderDelay: 750,
                        toManyVisibleItemsThreshold: 75
                    }
                }, options);
                if (!this.config.queryFunction) {
                    this.config.queryFunction = TrivialCore_1.defaultTreeQueryFunctionFactory(this.config.entries || [], TrivialCore_1.defaultEntryMatchingFunctionFactory(["displayValue", "additionalInfo"], this.config.matchingOptions), this.config.childrenProperty, this.config.expandedProperty);
                }
                this.entries = this.config.entries;
                this.$originalInput = $(originalInput).addClass("tr-original-input");
                this.$componentWrapper = $('<div class="tr-tree" tabindex="0"/>').insertAfter(this.$originalInput);
                if (this.config.searchBarMode !== 'always-visible') {
                    this.$componentWrapper.addClass("hide-searchfield");
                }
                this.$componentWrapper.keydown(function (e) {
                    if (e.which == TrivialCore_1.keyCodes.tab || TrivialCore_1.keyCodes.isModifierKey(e)) {
                        return;
                    }
                    if (_this.$editor.is(':visible') && TrivialCore_1.keyCodes.specialKeys.indexOf(e.which) === -1) {
                        _this.$editor.focus();
                    }
                    if (e.which == TrivialCore_1.keyCodes.up_arrow || e.which == TrivialCore_1.keyCodes.down_arrow) {
                        var direction = e.which == TrivialCore_1.keyCodes.up_arrow ? -1 : 1;
                        if (_this.entries != null) {
                            if (_this.config.directSelectionViaArrowKeys) {
                                _this.treeBox.selectNextEntry(direction, e);
                            }
                            else {
                                _this.treeBox.highlightNextEntry(direction);
                            }
                            return false;
                        }
                    }
                    else if (e.which == TrivialCore_1.keyCodes.left_arrow || e.which == TrivialCore_1.keyCodes.right_arrow) {
                        _this.treeBox.setHighlightedNodeExpanded(e.which == TrivialCore_1.keyCodes.right_arrow);
                    }
                    else if (e.which == TrivialCore_1.keyCodes.enter) {
                        _this.treeBox.setSelectedEntry(_this.treeBox.getHighlightedEntry(), e);
                    }
                    else if (e.which == TrivialCore_1.keyCodes.escape) {
                        _this.$editor.val("");
                        _this.query();
                        _this.$componentWrapper.focus();
                    }
                    else {
                        _this.query(1);
                    }
                });
                this.$editor = $('<input type="text" class="tr-tree-editor tr-editor"/>')
                    .prependTo(this.$componentWrapper)
                    .attr("tabindex", this.$originalInput.attr("-1"))
                    .focus(function () {
                    _this.$componentWrapper.addClass('focus');
                })
                    .blur(function () {
                    _this.$componentWrapper.removeClass('focus');
                })
                    .keydown(function (e) {
                    if (e.which == TrivialCore_1.keyCodes.left_arrow || e.which == TrivialCore_1.keyCodes.right_arrow) {
                        var changedExpandedState = _this.treeBox.setHighlightedNodeExpanded(e.which == TrivialCore_1.keyCodes.right_arrow);
                        if (changedExpandedState) {
                            return false;
                        }
                        else {
                            return;
                        }
                    }
                })
                    .on('keyup change', function () {
                    if (_this.config.searchBarMode === 'show-if-filled') {
                        if (_this.$editor.val()) {
                            _this.$componentWrapper.removeClass('hide-searchfield');
                        }
                        else {
                            _this.$componentWrapper.addClass('hide-searchfield');
                        }
                    }
                });
                if (this.config.searchBarMode === 'none') {
                    this.$editor.css("display", "none");
                }
                if (this.$originalInput.attr("placeholder")) {
                    this.$editor.attr("placeholder", this.$originalInput.attr("placeholder"));
                }
                if (this.$originalInput.attr("tabindex")) {
                    this.$componentWrapper.attr("tabindex", this.$originalInput.attr("tabindex"));
                }
                if (this.$originalInput.attr("autofocus")) {
                    this.$componentWrapper.focus();
                }
                this.treeBox = new TrivialTreeBox_1.TrivialTreeBox(this.$componentWrapper, this.config);
                this.treeBox.onNodeExpansionStateChanged.addListener(function (node) {
                    _this.onNodeExpansionStateChanged.fire(node);
                });
                this.treeBox.onSelectedEntryChanged.addListener(function () {
                    var selectedTreeBoxEntry = _this.treeBox.getSelectedEntry();
                    if (selectedTreeBoxEntry) {
                        _this.setSelectedEntry(selectedTreeBoxEntry);
                    }
                });
                this.setSelectedEntry((this.config.selectedEntryId !== undefined && this.config.selectedEntryId !== null) ? this.findEntryById(this.config.selectedEntryId) : null);
            }
            TrivialTree.prototype.updateEntries = function (newEntries) {
                this.entries = newEntries;
                this.$spinners.remove();
                this.$spinners = $();
                this.treeBox.updateEntries(newEntries);
            };
            TrivialTree.prototype.query = function (highlightDirection) {
                var _this = this;
                if (this.config.searchBarMode === 'always-visible' || this.config.searchBarMode === 'show-if-filled') {
                    var $spinner = $(this.config.spinnerTemplate).appendTo(this.treeBox.getMainDomElement());
                    this.$spinners = this.$spinners.add($spinner);
                    setTimeout(function () {
                        _this.config.queryFunction(_this.$editor.val(), function (newEntries) {
                            var processUpdate = function () {
                                _this.updateEntries(newEntries);
                                if (_this.$editor.val().length > 0) {
                                    _this.treeBox.highlightTextMatches(_this.$editor.val());
                                    if (!_this.config.directSelectionViaArrowKeys) {
                                        _this.treeBox.highlightNextMatchingEntry(highlightDirection);
                                    }
                                }
                                _this.treeBox.revealSelectedEntry();
                            };
                            clearTimeout(_this.processUpdateTimer);
                            if (_this.countVisibleEntries(newEntries) < _this.config.performanceOptimizationSettings.toManyVisibleItemsThreshold) {
                                processUpdate();
                            }
                            else {
                                _this.processUpdateTimer = window.setTimeout(processUpdate, _this.config.performanceOptimizationSettings.toManyVisibleItemsRenderDelay);
                            }
                        });
                    }, 0);
                }
            };
            TrivialTree.prototype.countVisibleEntries = function (entries) {
                var _this = this;
                var countVisibleChildrenAndSelf = function (node) {
                    if (node[_this.config.expandedProperty] && node[_this.config.childrenProperty]) {
                        return node[_this.config.childrenProperty].map(function (entry) {
                            return countVisibleChildrenAndSelf(entry);
                        }).reduce(function (a, b) {
                            return a + b;
                        }, 0) + 1;
                    }
                    else {
                        return 1;
                    }
                };
                return entries.map(function (entry) {
                    return countVisibleChildrenAndSelf(entry);
                }).reduce(function (a, b) {
                    return a + b;
                }, 0);
            };
            TrivialTree.prototype.findEntries = function (filterFunction) {
                var _this = this;
                var findEntriesInSubTree = function (node, listOfFoundEntries) {
                    if (filterFunction.call(_this, node)) {
                        listOfFoundEntries.push(node);
                    }
                    if (node[_this.config.childrenProperty]) {
                        for (var i = 0; i < node[_this.config.childrenProperty].length; i++) {
                            var child = node[_this.config.childrenProperty][i];
                            findEntriesInSubTree(child, listOfFoundEntries);
                        }
                    }
                };
                var matchingEntries = [];
                for (var i = 0; i < this.entries.length; i++) {
                    var rootEntry = this.entries[i];
                    findEntriesInSubTree(rootEntry, matchingEntries);
                }
                return matchingEntries;
            };
            TrivialTree.prototype.findEntryById = function (id) {
                var _this = this;
                return this.findEntries(function (entry) {
                    return _this.config.valueFunction(entry) === id.toString();
                })[0];
            };
            TrivialTree.prototype.setSelectedEntry = function (entry) {
                this.selectedEntryId = entry ? this.config.valueFunction(entry) : null;
                this.$originalInput.val(entry ? this.config.valueFunction(entry) : null);
                this.fireChangeEvents(entry);
            };
            TrivialTree.prototype.fireChangeEvents = function (entry) {
                this.$originalInput.trigger("change");
                this.$componentWrapper.trigger("change");
                this.onSelectedEntryChanged.fire(entry);
            };
            TrivialTree.prototype.getSelectedEntry = function () {
                this.treeBox.getSelectedEntry();
            };
            ;
            TrivialTree.prototype.updateChildren = function (parentNodeId, children) {
                this.treeBox.updateChildren(parentNodeId, children);
            };
            ;
            TrivialTree.prototype.updateNode = function (node) {
                this.treeBox.updateNode(node);
            };
            ;
            TrivialTree.prototype.removeNode = function (nodeId) {
                this.treeBox.removeNode(nodeId);
            };
            ;
            TrivialTree.prototype.addNode = function (parentNodeId, node) {
                this.treeBox.addNode(parentNodeId, node);
            };
            ;
            TrivialTree.prototype.selectNodeById = function (nodeId) {
                this.treeBox.setSelectedEntryById(nodeId);
            };
            ;
            TrivialTree.prototype.getEditor = function () {
                return this.$editor[0];
            };
            TrivialTree.prototype.destroy = function () {
                this.$originalInput.removeClass('tr-original-input').insertBefore(this.$componentWrapper);
                this.$componentWrapper.remove();
            };
            ;
            TrivialTree.prototype.getMainDomElement = function () {
                return this.$componentWrapper[0];
            };
            return TrivialTree;
        }());
        exports.TrivialTree = TrivialTree;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "mustache", "./TrivialCore", "./TrivialEvent"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var Mustache = require("mustache");
        var TrivialCore_1 = require("./TrivialCore");
        var TrivialEvent_1 = require("./TrivialEvent");
        var TrivialTreeBox = (function () {
            function TrivialTreeBox($container, options) {
                if (options === void 0) { options = {}; }
                this.onSelectedEntryChanged = new TrivialEvent_1.TrivialEvent(this);
                this.onNodeExpansionStateChanged = new TrivialEvent_1.TrivialEvent(this);
                this.config = $.extend({
                    valueFunction: function (entry) { return entry ? "" + entry.id : null; },
                    childrenProperty: "children",
                    lazyChildrenFlagProperty: "hasLazyChildren",
                    lazyChildrenQueryFunction: function (node, resultCallback) {
                        resultCallback(node.children || []);
                    },
                    expandedProperty: 'expanded',
                    entryRenderingFunction: function (entry, depth) {
                        var defaultTemplates = [TrivialCore_1.DEFAULT_TEMPLATES.icon2LinesTemplate, TrivialCore_1.DEFAULT_TEMPLATES.iconSingleLineTemplate];
                        var template = entry.template || defaultTemplates[Math.min(depth, defaultTemplates.length - 1)];
                        return Mustache.render(template, entry);
                    },
                    spinnerTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultSpinnerTemplate,
                    noEntriesTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultNoEntriesTemplate,
                    entries: null,
                    selectedEntryId: null,
                    matchingOptions: {
                        matchingMode: 'contains',
                        ignoreCase: true,
                        maxLevenshteinDistance: 2
                    },
                    animationDuration: 70,
                    showExpanders: true,
                    openOnSelection: false,
                    enforceSingleExpandedPath: false
                }, options);
                this.entries = this.config.entries;
                this.$componentWrapper = $('<div class="tr-treebox"/>').appendTo($container);
                this.$componentWrapper.toggleClass("hide-expanders", !this.config.showExpanders);
                this.$tree = $('<div class="tr-tree-entryTree"></div>').appendTo(this.$componentWrapper);
                if (this.entries) {
                    this.updateEntries(this.entries);
                }
                this.setSelectedEntry((this.config.selectedEntryId !== undefined && this.config.selectedEntryId !== null) ? this.findEntryById(this.config.selectedEntryId) : null);
            }
            TrivialTreeBox.prototype.isLeaf = function (entry) {
                return (entry[this.config.childrenProperty] == null || entry[this.config.childrenProperty].length == 0) && !entry[this.config.lazyChildrenFlagProperty];
            };
            TrivialTreeBox.prototype.createEntryElement = function (entry, depth) {
                var _this = this;
                var leaf = this.isLeaf(entry);
                var $outerEntryWrapper = $('<div class="tr-tree-entry-outer-wrapper ' + (leaf ? '' : 'has-children') + '" data-depth="' + depth + '"></div>');
                entry._trEntryElement = $outerEntryWrapper;
                var $entryAndExpanderWrapper = $('<div class="tr-tree-entry-and-expander-wrapper"></div>')
                    .appendTo($outerEntryWrapper);
                for (var k = 0; k < depth; k++) {
                    $entryAndExpanderWrapper.append('<div class="tr-indent-spacer"/>');
                }
                var $expander = $('<div class="tr-tree-expander"></div>')
                    .appendTo($entryAndExpanderWrapper);
                var $entry = $(this.config.entryRenderingFunction(entry, depth));
                $entry.addClass("tr-tree-entry filterable-item").appendTo($entryAndExpanderWrapper);
                if (this.config.valueFunction(entry) === this.selectedEntryId) {
                    $entryAndExpanderWrapper.addClass("tr-selected-entry");
                }
                $entryAndExpanderWrapper
                    .mousedown(function (e) {
                    _this.$componentWrapper.trigger("mousedown", e);
                    _this.setSelectedEntry(entry);
                }).mouseup(function (e) {
                    _this.$componentWrapper.trigger("mouseup", e);
                }).mouseenter(function () {
                    _this.setHighlightedEntry(entry);
                }).mouseleave(function (e) {
                    if (!$(e.toElement).is('.tr-tree-entry-outer-wrapper')) {
                        _this.setHighlightedEntry(null);
                    }
                });
                if (!leaf) {
                    var $childrenWrapper = $('<div class="tr-tree-entry-children-wrapper"></div>')
                        .appendTo($outerEntryWrapper);
                    $expander.mousedown(function () {
                        return false;
                    }).click(function (e) {
                        _this.setNodeExpanded(entry, !entry[_this.config.expandedProperty], true);
                    });
                    if (entry[this.config.childrenProperty]) {
                        if (entry[this.config.expandedProperty]) {
                            for (var i = 0; i < entry[this.config.childrenProperty].length; i++) {
                                this.createEntryElement(entry[this.config.childrenProperty][i], depth + 1).appendTo($childrenWrapper);
                            }
                        }
                    }
                    else if (entry[this.config.lazyChildrenFlagProperty]) {
                        $childrenWrapper.hide().append(this.config.spinnerTemplate).fadeIn();
                    }
                    this.setNodeExpanded(entry, entry[this.config.expandedProperty], false);
                }
                return $outerEntryWrapper;
            };
            TrivialTreeBox.prototype.updateTreeEntryElements = function () {
                this.$tree.detach();
                this.$tree = $('<div class="tr-tree-entryTree"></div>');
                if (this.entries.length > 0) {
                    for (var i = 0; i < this.entries.length; i++) {
                        this.createEntryElement(this.entries[i], 0).appendTo(this.$tree);
                    }
                }
                else {
                    this.$tree.append(this.config.noEntriesTemplate);
                }
                this.$tree.appendTo(this.$componentWrapper);
            };
            TrivialTreeBox.prototype.setNodeExpanded = function (node, expanded, animate) {
                var _this = this;
                var wasExpanded = node[this.config.expandedProperty];
                if (expanded && this.config.enforceSingleExpandedPath) {
                    var currentlyExpandedNodes = this.findEntries(function (n) {
                        return !!(n[_this.config.expandedProperty]);
                    });
                    var newExpandedPath = this.findPathToFirstMatchingNode(function (n) {
                        return n === node;
                    });
                    for (var i = 0; i < currentlyExpandedNodes.length; i++) {
                        var currentlyExpandedNode = currentlyExpandedNodes[i];
                        if (newExpandedPath.indexOf(currentlyExpandedNode) === -1) {
                            this.setNodeExpanded(currentlyExpandedNode, false, true);
                        }
                    }
                }
                node[this.config.expandedProperty] = !!expanded;
                node._trEntryElement.toggleClass("expanded", !!expanded);
                var nodeHasUnrenderedChildren = function (node) {
                    return node[_this.config.childrenProperty] && node[_this.config.childrenProperty].some(function (child) {
                        return !child._trEntryElement || !$.contains(document.documentElement, child._trEntryElement[0]);
                    });
                };
                if (expanded && node[this.config.lazyChildrenFlagProperty] && !node[this.config.childrenProperty]) {
                    this.config.lazyChildrenQueryFunction(node, function (children) {
                        _this.setChildren(node, children);
                    });
                }
                else if (expanded && nodeHasUnrenderedChildren(node)) {
                    this.renderChildren(node);
                }
                if (expanded) {
                    this.minimallyScrollTo(node._trEntryElement);
                }
                var childrenWrapper = node._trEntryElement.find("> .tr-tree-entry-children-wrapper");
                if (expanded) {
                    if (animate) {
                        childrenWrapper.slideDown(this.config.animationDuration);
                    }
                    else {
                        childrenWrapper.css("display", "block");
                    }
                }
                else {
                    if (animate) {
                        childrenWrapper.slideUp(this.config.animationDuration);
                    }
                    else {
                        childrenWrapper.hide();
                    }
                }
                if (!!wasExpanded != !!expanded) {
                    this.onNodeExpansionStateChanged.fire(node);
                }
            };
            TrivialTreeBox.prototype.nodeDepth = function (node) {
                return node ? parseInt(node._trEntryElement.attr('data-depth')) : 0;
            };
            TrivialTreeBox.prototype.setChildren = function (node, children) {
                node[this.config.childrenProperty] = children;
                node[this.config.lazyChildrenFlagProperty] = false;
                this.renderChildren(node);
            };
            TrivialTreeBox.prototype.renderChildren = function (node) {
                var $childrenWrapper = node._trEntryElement.find('> .tr-tree-entry-children-wrapper');
                $childrenWrapper.empty();
                var children = node[this.config.childrenProperty];
                if (children && children.length > 0) {
                    var depth = this.nodeDepth(node);
                    for (var i = 0; i < children.length; i++) {
                        var child = children[i];
                        this.createEntryElement(child, depth + 1).appendTo($childrenWrapper);
                    }
                }
                else {
                    node._trEntryElement.removeClass('has-children expanded');
                }
            };
            TrivialTreeBox.prototype.updateEntries = function (newEntries) {
                this.highlightedEntry = null;
                this.entries = newEntries;
                this.updateTreeEntryElements();
                var selectedEntry = this.findEntryById(this.selectedEntryId);
                if (selectedEntry) {
                    this.markSelectedEntry(selectedEntry);
                }
            };
            TrivialTreeBox.prototype.findEntries = function (filterFunction) {
                var _this = this;
                var findEntriesInSubTree = function (node, listOfFoundEntries) {
                    if (filterFunction.call(_this, node)) {
                        listOfFoundEntries.push(node);
                    }
                    if (node[_this.config.childrenProperty]) {
                        for (var i = 0; i < node[_this.config.childrenProperty].length; i++) {
                            var child = node[_this.config.childrenProperty][i];
                            findEntriesInSubTree(child, listOfFoundEntries);
                        }
                    }
                };
                var matchingEntries = [];
                for (var i = 0; i < this.entries.length; i++) {
                    var rootEntry = this.entries[i];
                    findEntriesInSubTree(rootEntry, matchingEntries);
                }
                return matchingEntries;
            };
            TrivialTreeBox.prototype.findPathToFirstMatchingNode = function (predicateFunction) {
                var _this = this;
                var searchInSubTree = function (node, path) {
                    if (predicateFunction.call(_this, node, path)) {
                        path.push(node);
                        return path;
                    }
                    if (node[_this.config.childrenProperty]) {
                        var newPath = path.slice();
                        newPath.push(node);
                        for (var i = 0; i < node[_this.config.childrenProperty].length; i++) {
                            var child = node[_this.config.childrenProperty][i];
                            var result = searchInSubTree(child, newPath);
                            if (result) {
                                return result;
                            }
                        }
                    }
                };
                for (var i = 0; i < this.entries.length; i++) {
                    var rootEntry = this.entries[i];
                    var path = searchInSubTree(rootEntry, []);
                    if (path) {
                        return path;
                    }
                }
            };
            TrivialTreeBox.prototype.findEntryById = function (id) {
                var _this = this;
                return this.findEntries(function (entry) {
                    return _this.config.valueFunction(entry) === id;
                })[0];
            };
            TrivialTreeBox.prototype.findParentNode = function (childNode) {
                var _this = this;
                return this.findEntries(function (entry) {
                    return entry[_this.config.childrenProperty] && entry[_this.config.childrenProperty].indexOf(childNode) != -1;
                })[0];
            };
            TrivialTreeBox.prototype.setSelectedEntry = function (entry, originalEvent) {
                this.selectedEntryId = entry ? this.config.valueFunction(entry) : null;
                this.markSelectedEntry(entry);
                this.setHighlightedEntry(entry);
                this.fireChangeEvents(entry, originalEvent);
                if (entry && this.config.openOnSelection) {
                    this.setNodeExpanded(entry, true, true);
                }
            };
            TrivialTreeBox.prototype.setSelectedEntryById = function (nodeId) {
                this.setSelectedEntry(this.findEntryById(nodeId), null);
            };
            TrivialTreeBox.prototype.minimallyScrollTo = function ($entryWrapper) {
                TrivialCore_1.minimallyScrollTo(this.$componentWrapper.parent(), $entryWrapper);
            };
            TrivialTreeBox.prototype.markSelectedEntry = function (entry) {
                this.$tree.find(".tr-selected-entry").removeClass("tr-selected-entry");
                if (entry && entry._trEntryElement) {
                    var $entryWrapper = entry._trEntryElement.find('>.tr-tree-entry-and-expander-wrapper');
                    $entryWrapper.addClass("tr-selected-entry");
                }
            };
            TrivialTreeBox.prototype.fireChangeEvents = function (entry, originalEvent) {
                this.$componentWrapper.trigger("change");
                this.onSelectedEntryChanged.fire(entry);
            };
            TrivialTreeBox.prototype.selectNextEntry = function (direction, originalEvent) {
                var nextVisibleEntry = this.getNextVisibleEntry(this.getSelectedEntry(), direction);
                if (nextVisibleEntry != null) {
                    this.setSelectedEntry(nextVisibleEntry, originalEvent);
                }
            };
            TrivialTreeBox.prototype.setHighlightedEntry = function (entry) {
                if (entry !== this.highlightedEntry) {
                    this.highlightedEntry = entry;
                    this.$tree.find('.tr-highlighted-entry').removeClass('tr-highlighted-entry');
                    if (entry != null && entry._trEntryElement) {
                        var $entry = entry._trEntryElement.find('>.tr-tree-entry-and-expander-wrapper');
                        $entry.addClass('tr-highlighted-entry');
                        this.minimallyScrollTo($entry);
                    }
                    else {
                        var selectedEntry = this.getSelectedEntry();
                        if (selectedEntry) {
                            this.highlightedEntry = selectedEntry;
                        }
                    }
                }
            };
            TrivialTreeBox.prototype.getNextVisibleEntry = function (currentEntry, direction, onlyEntriesWithTextMatches) {
                if (onlyEntriesWithTextMatches === void 0) { onlyEntriesWithTextMatches = false; }
                var newSelectedElementIndex;
                var visibleEntriesAsList = this.findEntries(function (entry) {
                    if (!entry._trEntryElement) {
                        return false;
                    }
                    else {
                        if (onlyEntriesWithTextMatches) {
                            return entry._trEntryElement.is(':visible') && entry._trEntryElement.has('>.tr-tree-entry-and-expander-wrapper .tr-highlighted-text').length > 0;
                        }
                        else {
                            return entry._trEntryElement.is(':visible') || entry === currentEntry;
                        }
                    }
                });
                if (visibleEntriesAsList == null || visibleEntriesAsList.length == 0) {
                    return null;
                }
                else if (currentEntry == null && direction > 0) {
                    newSelectedElementIndex = -1 + direction;
                }
                else if (currentEntry == null && direction < 0) {
                    newSelectedElementIndex = visibleEntriesAsList.length + direction;
                }
                else {
                    var currentSelectedElementIndex = visibleEntriesAsList.indexOf(currentEntry);
                    newSelectedElementIndex = (currentSelectedElementIndex + visibleEntriesAsList.length + direction) % visibleEntriesAsList.length;
                }
                return visibleEntriesAsList[newSelectedElementIndex];
            };
            TrivialTreeBox.prototype.highlightTextMatches = function (searchString) {
                this.$tree.detach();
                for (var i = 0; i < this.entries.length; i++) {
                    var entry = this.entries[i];
                    var $entryElement = entry._trEntryElement.find('.tr-tree-entry');
                    $entryElement.trivialHighlight(searchString, this.config.matchingOptions);
                }
                this.$tree.appendTo(this.$componentWrapper);
            };
            TrivialTreeBox.prototype.getSelectedEntry = function () {
                return (this.selectedEntryId !== undefined && this.selectedEntryId !== null) ? this.findEntryById(this.selectedEntryId) : null;
            };
            TrivialTreeBox.prototype.revealSelectedEntry = function (animate) {
                if (animate === void 0) { animate = false; }
                var selectedEntry = this.getSelectedEntry();
                if (!selectedEntry) {
                    return;
                }
                var currentEntry = selectedEntry;
                while (currentEntry = this.findParentNode(currentEntry)) {
                    this.setNodeExpanded(currentEntry, true, animate);
                }
                this.minimallyScrollTo(selectedEntry._trEntryElement);
            };
            TrivialTreeBox.prototype.highlightNextEntry = function (direction) {
                var nextVisibleEntry = this.getNextVisibleEntry(this.highlightedEntry || this.getSelectedEntry(), direction);
                if (nextVisibleEntry != null) {
                    this.setHighlightedEntry(nextVisibleEntry);
                }
            };
            TrivialTreeBox.prototype.highlightNextMatchingEntry = function (direction) {
                var nextMatchingEntry = this.getNextVisibleEntry(this.highlightedEntry || this.getSelectedEntry(), direction, true);
                if (nextMatchingEntry != null) {
                    this.setHighlightedEntry(nextMatchingEntry);
                }
            };
            TrivialTreeBox.prototype.selectNextMatchingEntry = function (direction) {
                var nextMatchingEntry = this.getNextVisibleEntry(this.highlightedEntry, direction, true);
                if (nextMatchingEntry != null) {
                    this.setSelectedEntry(nextMatchingEntry);
                }
            };
            TrivialTreeBox.prototype.getHighlightedEntry = function () {
                return this.highlightedEntry;
            };
            TrivialTreeBox.prototype.setHighlightedNodeExpanded = function (expanded) {
                if (!this.highlightedEntry || this.isLeaf(this.highlightedEntry)) {
                    return false;
                }
                else {
                    var wasExpanded = this.highlightedEntry[this.config.expandedProperty];
                    this.setNodeExpanded(this.highlightedEntry, expanded, true);
                    return !wasExpanded != !expanded;
                }
            };
            TrivialTreeBox.prototype.updateChildren = function (parentNodeId, children) {
                var node = this.findEntryById(parentNodeId);
                if (node) {
                    this.setChildren(node, children);
                }
                else {
                    void 0;
                }
            };
            ;
            TrivialTreeBox.prototype.updateNode = function (node) {
                var oldNode = this.findEntryById(this.config.valueFunction(node));
                var parent = this.findParentNode(oldNode);
                if (parent) {
                    parent[this.config.childrenProperty][parent[this.config.childrenProperty].indexOf(oldNode)] = node;
                }
                else {
                    this.entries[this.entries.indexOf(oldNode)] = node;
                }
                this.createEntryElement(node, this.nodeDepth(oldNode)).insertAfter(oldNode._trEntryElement);
                oldNode._trEntryElement.remove();
            };
            ;
            TrivialTreeBox.prototype.removeNode = function (nodeId) {
                var childNode = this.findEntryById(nodeId);
                if (childNode) {
                    var parentNode = this.findParentNode(childNode);
                    if (parentNode) {
                        parentNode[this.config.childrenProperty].splice(parentNode[this.config.childrenProperty].indexOf(childNode), 1);
                    }
                    else {
                        this.entries.splice(this.entries.indexOf(childNode), 1);
                    }
                    childNode._trEntryElement.remove();
                }
            };
            ;
            TrivialTreeBox.prototype.addNode = function (parentNodeId, node) {
                var parentNode = this.findEntryById(parentNodeId);
                if (this.isLeaf(parentNode)) {
                    void 0;
                }
                if (!parentNode[this.config.childrenProperty]) {
                    parentNode[this.config.childrenProperty] = [];
                }
                parentNode[this.config.childrenProperty].push(node);
                var entryElement = this.createEntryElement(node, this.nodeDepth(parentNode) + 1);
                entryElement
                    .appendTo(parentNode._trEntryElement.find('>.tr-tree-entry-children-wrapper'));
                parentNode._trEntryElement.addClass('has-children');
            };
            ;
            TrivialTreeBox.prototype.destroy = function () {
                this.$componentWrapper.remove();
            };
            ;
            TrivialTreeBox.prototype.getMainDomElement = function () {
                return this.$componentWrapper[0];
            };
            return TrivialTreeBox;
        }());
        exports.TrivialTreeBox = TrivialTreeBox;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "mustache", "./TrivialCore", "./TrivialTreeBox", "./TrivialEvent"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var Mustache = require("mustache");
        var TrivialCore_1 = require("./TrivialCore");
        var TrivialTreeBox_1 = require("./TrivialTreeBox");
        var TrivialEvent_1 = require("./TrivialEvent");
        var TrivialTreeComboBox = (function () {
            function TrivialTreeComboBox(originalInput, options) {
                if (options === void 0) { options = {}; }
                var _this = this;
                this.isDropDownOpen = false;
                this.isEditorVisible = false;
                this.lastQueryString = null;
                this.lastCompleteInputQueryString = null;
                this.selectedEntry = null;
                this.lastCommittedValue = null;
                this.blurCausedByClickInsideComponent = false;
                this.autoCompleteTimeoutId = -1;
                this.doNoAutoCompleteBecauseBackspaceWasPressed = false;
                this.usingDefaultQueryFunction = false;
                this.$spinners = $();
                this.onSelectedEntryChanged = new TrivialEvent_1.TrivialEvent(this);
                this.onFocus = new TrivialEvent_1.TrivialEvent(this);
                this.onBlur = new TrivialEvent_1.TrivialEvent(this);
                this.config = $.extend({
                    valueFunction: function (entry) { return entry ? "" + entry.id : null; },
                    entryRenderingFunction: function (entry, depth) {
                        var defaultTemplates = [TrivialCore_1.DEFAULT_TEMPLATES.icon2LinesTemplate, TrivialCore_1.DEFAULT_TEMPLATES.iconSingleLineTemplate];
                        var template = defaultTemplates[Math.min(depth, defaultTemplates.length - 1)];
                        return Mustache.render(template, entry);
                    },
                    selectedEntryRenderingFunction: function (entry) {
                        return _this.config.entryRenderingFunction(entry, 0);
                    },
                    selectedEntry: null,
                    spinnerTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultSpinnerTemplate,
                    noEntriesTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultNoEntriesTemplate,
                    textHighlightingEntryLimit: 100,
                    entries: null,
                    queryFunction: null,
                    autoComplete: true,
                    autoCompleteDelay: 0,
                    entryToEditorTextFunction: function (entry) {
                        return entry["displayValue"];
                    },
                    autoCompleteFunction: function (editorText, entry) {
                        if (editorText) {
                            for (var propertyName in entry) {
                                var propertyValue = entry[propertyName];
                                if (propertyValue && propertyValue.toString().toLowerCase().indexOf(editorText.toLowerCase()) === 0) {
                                    return propertyValue.toString();
                                }
                            }
                            return null;
                        }
                        else {
                            return entry ? _this.config.entryToEditorTextFunction(entry) : null;
                        }
                    },
                    allowFreeText: false,
                    freeTextEntryFactory: function (freeText) {
                        return {
                            displayValue: freeText,
                            _isFreeTextEntry: true
                        };
                    },
                    showClearButton: false,
                    showTrigger: true,
                    matchingOptions: {
                        matchingMode: 'contains',
                        ignoreCase: true,
                        maxLevenshteinDistance: 2
                    },
                    childrenProperty: "children",
                    lazyChildrenFlagProperty: "hasLazyChildren",
                    expandedProperty: 'expanded',
                    editingMode: "editable",
                    showDropDownOnResultsOnly: false
                }, options);
                if (!this.config.queryFunction) {
                    this.config.queryFunction = TrivialCore_1.defaultTreeQueryFunctionFactory(this.config.entries || [], TrivialCore_1.defaultEntryMatchingFunctionFactory(["displayValue", "additionalInfo"], this.config.matchingOptions), this.config.childrenProperty, this.config.expandedProperty);
                    this.usingDefaultQueryFunction = true;
                }
                this.$originalInput = $(originalInput);
                this.$treeComboBox = $('<div class="tr-treecombobox tr-combobox tr-input-wrapper"/>')
                    .insertAfter(this.$originalInput);
                this.$selectedEntryWrapper = $('<div class="tr-combobox-selected-entry-wrapper"/>').appendTo(this.$treeComboBox);
                if (this.config.showClearButton) {
                    this.$clearButton = $('<div class="tr-remove-button">').appendTo(this.$treeComboBox);
                    this.$clearButton.mousedown(function (e) {
                        _this.$editor.val("");
                        _this.setSelectedEntry(null, true, true, e);
                    });
                }
                if (this.config.showTrigger) {
                    this.$trigger = $('<div class="tr-trigger"><span class="tr-trigger-icon"/></div>').appendTo(this.$treeComboBox);
                    this.$trigger.mousedown(function () {
                        if (_this.isDropDownOpen) {
                            _this.showEditor();
                            _this.closeDropDown();
                        }
                        else {
                            setTimeout(function () {
                                _this.showEditor();
                                _this.$editor.select();
                                _this.openDropDown();
                                _this.query();
                            });
                        }
                    });
                }
                this.$dropDown = $('<div class="tr-dropdown"></div>')
                    .scroll(function () {
                    return false;
                });
                this.$dropDownTargetElement = $("body");
                this.setEditingMode(this.config.editingMode);
                this.$originalInput.addClass("tr-original-input");
                this.$editor = $('<input type="text" autocomplete="off"/>');
                this.$editor.prependTo(this.$treeComboBox).addClass("tr-combobox-editor tr-editor")
                    .focus(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                    }
                    else {
                        _this.$originalInput.triggerHandler('focus');
                        _this.onFocus.fire();
                        _this.$treeComboBox.addClass('focus');
                        _this.showEditor();
                    }
                })
                    .blur(function (e) {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                    }
                    else {
                        _this.$originalInput.triggerHandler('blur');
                        _this.onBlur.fire();
                        _this.$treeComboBox.removeClass('focus');
                        if (_this.editorContainsFreeText()) {
                            if (!TrivialCore_1.objectEquals(_this.getSelectedEntry(), _this.lastCommittedValue)) {
                                _this.setSelectedEntry(_this.getSelectedEntry(), true, true, e);
                            }
                        }
                        else {
                            _this.$editor.val("");
                            _this.setSelectedEntry(_this.lastCommittedValue, false, false, e);
                        }
                        _this.hideEditor();
                        _this.closeDropDown();
                    }
                })
                    .keydown(function (e) {
                    if (TrivialCore_1.keyCodes.isModifierKey(e)) {
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.tab) {
                        var highlightedEntry = _this.treeBox.getHighlightedEntry();
                        if (_this.isDropDownOpen && highlightedEntry) {
                            _this.setSelectedEntry(highlightedEntry, true, true, e);
                        }
                        else if (!_this.$editor.val()) {
                            _this.setSelectedEntry(null, true, true, e);
                        }
                        else if (_this.config.allowFreeText) {
                            _this.setSelectedEntry(_this.getSelectedEntry(), true, true, e);
                        }
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.left_arrow || e.which == TrivialCore_1.keyCodes.right_arrow) {
                        if (_this.isDropDownOpen) {
                            var changedExpandedState = _this.treeBox.setHighlightedNodeExpanded(e.which == TrivialCore_1.keyCodes.right_arrow);
                            if (changedExpandedState) {
                                return false;
                            }
                        }
                        _this.showEditor();
                        return;
                    }
                    setTimeout(function () {
                        var isNonIgnoredKey = !TrivialCore_1.keyCodes.isModifierKey(e) && [TrivialCore_1.keyCodes.enter, TrivialCore_1.keyCodes.escape, TrivialCore_1.keyCodes.tab].indexOf(e.which) === -1;
                        var editorValueDoesNotCorrespondToSelectedValue = _this.isEntrySelected() && _this.$editor.val() !== _this.config.entryToEditorTextFunction(_this.selectedEntry);
                        if (isNonIgnoredKey && (editorValueDoesNotCorrespondToSelectedValue || _this.config.valueFunction(_this.treeBox.getHighlightedEntry())) !== _this.config.valueFunction(_this.getSelectedEntry())) {
                            _this.setSelectedEntry(null, false, false, e);
                        }
                    });
                    if (e.which == TrivialCore_1.keyCodes.backspace || e.which == TrivialCore_1.keyCodes.delete) {
                        _this.doNoAutoCompleteBecauseBackspaceWasPressed = true;
                    }
                    if (e.which == TrivialCore_1.keyCodes.up_arrow || e.which == TrivialCore_1.keyCodes.down_arrow) {
                        if (!_this.isEditorVisible) {
                            _this.$editor.select();
                            _this.showEditor();
                        }
                        var direction = e.which == TrivialCore_1.keyCodes.up_arrow ? -1 : 1;
                        if (!_this.isDropDownOpen) {
                            _this.query(direction);
                            if (!_this.config.showDropDownOnResultsOnly) {
                                _this.openDropDown();
                            }
                        }
                        else {
                            _this.treeBox.highlightNextEntry(direction);
                            _this.autoCompleteIfPossible();
                        }
                        return false;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.enter) {
                        if (_this.isEditorVisible || _this.editorContainsFreeText()) {
                            e.preventDefault();
                            var highlightedEntry = _this.treeBox.getHighlightedEntry();
                            if (_this.isDropDownOpen && highlightedEntry) {
                                _this.setSelectedEntry(highlightedEntry, true, true, e);
                            }
                            else if (!_this.$editor.val()) {
                                _this.setSelectedEntry(null, true, true, e);
                            }
                            else if (_this.config.allowFreeText) {
                                _this.setSelectedEntry(_this.getSelectedEntry(), true, true, e);
                            }
                            _this.closeDropDown();
                            _this.hideEditor();
                        }
                    }
                    else if (e.which == TrivialCore_1.keyCodes.escape) {
                        e.preventDefault();
                        if (!(_this.editorContainsFreeText() && _this.isDropDownOpen)) {
                            _this.hideEditor();
                            _this.$editor.val("");
                            _this.setSelectedEntry(_this.lastCommittedValue, false, false, e);
                        }
                        _this.closeDropDown();
                    }
                    else {
                        if (!_this.isEditorVisible) {
                            _this.showEditor();
                            _this.$editor.select();
                        }
                        if (!_this.config.showDropDownOnResultsOnly) {
                            _this.openDropDown();
                        }
                        setTimeout(function () {
                            if (_this.$editor.val()) {
                                _this.query(1);
                            }
                            else {
                                _this.query(0);
                                _this.treeBox.setHighlightedEntry(null);
                            }
                        });
                    }
                })
                    .mousedown(function () {
                    if (!_this.config.showDropDownOnResultsOnly) {
                        _this.openDropDown();
                    }
                    _this.query();
                });
                if (this.$originalInput.attr("tabindex")) {
                    this.$editor.attr("tabindex", this.$originalInput.attr("tabindex"));
                }
                if (this.$originalInput.attr("autofocus")) {
                    this.$editor.focus();
                }
                this.$treeComboBox.add(this.$dropDown)
                    .mousedown(function () {
                    if (_this.$editor.is(":focus")) {
                        _this.blurCausedByClickInsideComponent = true;
                    }
                })
                    .mouseup(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                        _this.blurCausedByClickInsideComponent = false;
                    }
                })
                    .mouseout(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                        _this.blurCausedByClickInsideComponent = false;
                    }
                });
                this.treeBox = new TrivialTreeBox_1.TrivialTreeBox(this.$dropDown, this.config);
                this.treeBox.onSelectedEntryChanged.addListener(function (selectedEntry, eventSource, originalEvent) {
                    if (selectedEntry) {
                        _this.setSelectedEntry(selectedEntry, true, !TrivialCore_1.objectEquals(selectedEntry, _this.lastCommittedValue), originalEvent);
                        _this.treeBox.setSelectedEntry(null);
                        _this.closeDropDown();
                    }
                    _this.hideEditor();
                });
                this.setSelectedEntry(this.config.selectedEntry, true, false, null);
                this.$selectedEntryWrapper.click(function () {
                    _this.showEditor();
                    _this.$editor.select();
                    if (!_this.config.showDropDownOnResultsOnly) {
                        _this.openDropDown();
                    }
                    _this.query();
                });
            }
            TrivialTreeComboBox.prototype.query = function (highlightDirection) {
                var _this = this;
                var queryString = this.getNonSelectedEditorValue();
                var completeInputString = this.$editor.val();
                if (this.lastQueryString !== queryString || this.lastCompleteInputQueryString !== completeInputString) {
                    if (this.$spinners.length === 0) {
                        var $spinner = $(this.config.spinnerTemplate).appendTo(this.$dropDown);
                        this.$spinners = this.$spinners.add($spinner);
                    }
                    this.config.queryFunction(queryString, function (newEntries) {
                        _this.updateEntries(newEntries, highlightDirection);
                        if (_this.config.showDropDownOnResultsOnly && newEntries && newEntries.length > 0 && _this.$editor.is(":focus")) {
                            _this.openDropDown();
                        }
                    });
                    this.lastQueryString = queryString;
                    this.lastCompleteInputQueryString = completeInputString;
                }
                else {
                    this.openDropDown();
                }
            };
            TrivialTreeComboBox.prototype.fireChangeEvents = function (entry, originalEvent) {
                this.$originalInput.trigger("change");
                this.onSelectedEntryChanged.fire(entry, originalEvent);
            };
            TrivialTreeComboBox.prototype.setSelectedEntry = function (entry, commit, fireEvent, originalEvent) {
                this.$originalInput.val(this.config.valueFunction(entry));
                this.selectedEntry = entry;
                var $selectedEntry = $(this.config.selectedEntryRenderingFunction(entry))
                    .addClass("tr-combobox-entry");
                this.$selectedEntryWrapper.empty().append($selectedEntry);
                if (entry != null) {
                    this.$editor.val(this.config.entryToEditorTextFunction(entry));
                }
                if (commit) {
                    this.lastCommittedValue = entry;
                    if (fireEvent) {
                        this.fireChangeEvents(entry, originalEvent);
                    }
                }
                if (this.$clearButton) {
                    this.$clearButton.toggle(entry != null);
                }
                if (this.isEditorVisible) {
                    this.showEditor();
                }
                if (this.isDropDownOpen) {
                    this.repositionDropDown();
                }
            };
            TrivialTreeComboBox.prototype.isEntrySelected = function () {
                return this.selectedEntry != null;
            };
            TrivialTreeComboBox.prototype.showEditor = function () {
                var $editorArea = this.$selectedEntryWrapper.find(".tr-editor-area");
                if ($editorArea.length === 0) {
                    $editorArea = this.$selectedEntryWrapper;
                }
                this.$editor
                    .css({
                    "width": Math.min($editorArea[0].offsetWidth, this.$trigger ? this.$trigger[0].offsetLeft - $editorArea[0].offsetLeft : 99999999) + "px",
                    "height": ($editorArea[0].offsetHeight) + "px"
                })
                    .position({
                    my: "left top",
                    at: "left top",
                    of: $editorArea
                });
                this.isEditorVisible = true;
            };
            TrivialTreeComboBox.prototype.editorContainsFreeText = function () {
                return this.config.allowFreeText && this.$editor.val().length > 0 && !this.isEntrySelected();
            };
            ;
            TrivialTreeComboBox.prototype.hideEditor = function () {
                this.$editor.width(0).height(0);
                this.isEditorVisible = false;
            };
            TrivialTreeComboBox.prototype.repositionDropDown = function () {
                var _this = this;
                this.$dropDown
                    .show()
                    .position({
                    my: "left top",
                    at: "left bottom",
                    of: this.$treeComboBox,
                    collision: "flip",
                    using: function (calculatedPosition, info) {
                        if (info.vertical === "top") {
                            _this.$treeComboBox.removeClass("dropdown-flipped");
                            _this.$dropDown.removeClass("flipped");
                        }
                        else {
                            _this.$treeComboBox.addClass("dropdown-flipped");
                            _this.$dropDown.addClass("flipped");
                        }
                        _this.$dropDown.css({
                            left: calculatedPosition.left + 'px',
                            top: calculatedPosition.top + 'px'
                        });
                    }
                })
                    .width(this.$treeComboBox.width());
            };
            ;
            TrivialTreeComboBox.prototype.openDropDown = function () {
                if (this.isDropDownNeeded()) {
                    this.$treeComboBox.addClass("open");
                    this.repositionDropDown();
                    this.isDropDownOpen = true;
                }
            };
            TrivialTreeComboBox.prototype.closeDropDown = function () {
                this.$treeComboBox.removeClass("open");
                this.$dropDown.hide();
                this.isDropDownOpen = false;
            };
            TrivialTreeComboBox.prototype.getNonSelectedEditorValue = function () {
                return this.$editor.val().substring(0, this.$editor[0].selectionStart);
            };
            TrivialTreeComboBox.prototype.autoCompleteIfPossible = function (delay) {
                var _this = this;
                if (this.config.autoComplete) {
                    clearTimeout(this.autoCompleteTimeoutId);
                    var highlightedEntry_1 = this.treeBox.getHighlightedEntry();
                    if (highlightedEntry_1 && !this.doNoAutoCompleteBecauseBackspaceWasPressed) {
                        this.autoCompleteTimeoutId = TrivialCore_1.setTimeoutOrDoImmediately(function () {
                            var currentEditorValue = _this.getNonSelectedEditorValue();
                            var autoCompleteString = _this.config.autoCompleteFunction(currentEditorValue, highlightedEntry_1) || currentEditorValue;
                            _this.$editor.val(currentEditorValue + autoCompleteString.substr(currentEditorValue.length));
                            if (_this.$editor.is(":focus")) {
                                _this.$editor[0].setSelectionRange(currentEditorValue.length, autoCompleteString.length);
                            }
                        }, delay);
                    }
                    this.doNoAutoCompleteBecauseBackspaceWasPressed = false;
                }
            };
            TrivialTreeComboBox.prototype.updateEntries = function (newEntries, highlightDirection) {
                this.blurCausedByClickInsideComponent = false;
                this.$spinners.remove();
                this.$spinners = $();
                this.treeBox.updateEntries(newEntries);
                var nonSelectedEditorValue = this.getNonSelectedEditorValue();
                this.treeBox.highlightTextMatches(newEntries.length <= this.config.textHighlightingEntryLimit ? nonSelectedEditorValue : null);
                if (highlightDirection == null) {
                    if (this.selectedEntry) {
                        this.treeBox.setHighlightedEntry(null);
                    }
                    else {
                        if (nonSelectedEditorValue.length > 0) {
                            this.treeBox.highlightNextMatchingEntry(1);
                        }
                        else {
                            this.treeBox.highlightNextEntry(1);
                        }
                    }
                }
                else if (highlightDirection === 0) {
                    this.treeBox.setHighlightedEntry(null);
                }
                else {
                    if (nonSelectedEditorValue.length > 0) {
                        this.treeBox.highlightNextMatchingEntry(1);
                    }
                    else {
                        this.treeBox.highlightNextEntry(1);
                    }
                }
                this.autoCompleteIfPossible(this.config.autoCompleteDelay);
                if (this.isDropDownOpen) {
                    this.openDropDown();
                }
            };
            TrivialTreeComboBox.prototype.isDropDownNeeded = function () {
                return this.editingMode == 'editable' && (this.config.entries && this.config.entries.length > 0 || !this.usingDefaultQueryFunction || this.config.showTrigger);
            };
            TrivialTreeComboBox.prototype.setEditingMode = function (newEditingMode) {
                this.editingMode = newEditingMode;
                this.$treeComboBox.removeClass("editable readonly disabled").addClass(this.editingMode);
                if (this.isDropDownNeeded()) {
                    this.$dropDown.appendTo(this.$dropDownTargetElement);
                }
            };
            TrivialTreeComboBox.prototype.getSelectedEntry = function () {
                if (this.selectedEntry == null && (!this.config.allowFreeText || !this.$editor.val())) {
                    return null;
                }
                else if (this.selectedEntry == null && this.config.allowFreeText) {
                    return this.config.freeTextEntryFactory(this.$editor.val());
                }
                else {
                    var selectedEntryToReturn = $.extend({}, this.selectedEntry);
                    selectedEntryToReturn._trEntryElement = undefined;
                    return selectedEntryToReturn;
                }
            };
            TrivialTreeComboBox.prototype.updateChildren = function (parentNodeId, children) {
                this.treeBox.updateChildren(parentNodeId, children);
            };
            TrivialTreeComboBox.prototype.updateNode = function (node) {
                this.treeBox.updateNode(node);
            };
            TrivialTreeComboBox.prototype.removeNode = function (nodeId) {
                this.treeBox.removeNode(nodeId);
            };
            TrivialTreeComboBox.prototype.focus = function () {
                this.showEditor();
                this.$editor.select();
            };
            ;
            TrivialTreeComboBox.prototype.getEditor = function () {
                return this.$editor[0];
            };
            TrivialTreeComboBox.prototype.getDropDown = function () {
                return this.$dropDown;
            };
            ;
            TrivialTreeComboBox.prototype.destroy = function () {
                this.$originalInput.removeClass('tr-original-input').insertBefore(this.$treeComboBox);
                this.$treeComboBox.remove();
                this.$dropDown.remove();
            };
            ;
            TrivialTreeComboBox.prototype.getMainDomElement = function () {
                return this.$treeComboBox[0];
            };
            return TrivialTreeComboBox;
        }());
        exports.TrivialTreeComboBox = TrivialTreeComboBox;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "mustache", "./TrivialListBox", "./TrivialCore", "./TrivialEvent"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var $ = require("jquery");
        var Mustache = require("mustache");
        var TrivialListBox_1 = require("./TrivialListBox");
        var TrivialCore_1 = require("./TrivialCore");
        var TrivialEvent_1 = require("./TrivialEvent");
        var TrivialUnitBox = (function () {
            function TrivialUnitBox(originalInput, options) {
                if (options === void 0) { options = {}; }
                var _this = this;
                this.onChange = new TrivialEvent_1.TrivialEvent(this);
                this.onSelectedEntryChanged = new TrivialEvent_1.TrivialEvent(this);
                this.onFocus = new TrivialEvent_1.TrivialEvent(this);
                this.onBlur = new TrivialEvent_1.TrivialEvent(this);
                this.isDropDownOpen = false;
                this.blurCausedByClickInsideComponent = false;
                this.$spinners = $();
                this.config = $.extend({
                    unitValueProperty: 'code',
                    unitIdProperty: 'code',
                    decimalPrecision: 2,
                    decimalSeparator: '.',
                    thousandsSeparator: ',',
                    unitDisplayPosition: 'right',
                    allowNullAmount: true,
                    entryRenderingFunction: function (entry) {
                        return Mustache.render(TrivialCore_1.DEFAULT_TEMPLATES.currency2LineTemplate, entry);
                    },
                    selectedEntryRenderingFunction: function (entry) {
                        return Mustache.render(TrivialCore_1.DEFAULT_TEMPLATES.currencySingleLineShortTemplate, entry);
                    },
                    amount: null,
                    selectedEntry: undefined,
                    spinnerTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultSpinnerTemplate,
                    noEntriesTemplate: TrivialCore_1.DEFAULT_TEMPLATES.defaultNoEntriesTemplate,
                    entries: null,
                    queryFunction: null,
                    queryOnNonNumberCharacters: true,
                    openDropdownOnEditorClick: false,
                    showTrigger: true,
                    matchingOptions: {
                        matchingMode: 'prefix-word',
                        ignoreCase: true,
                        maxLevenshteinDistance: 2
                    },
                    editingMode: 'editable',
                }, options);
                if (!this.config.queryFunction) {
                    this.config.queryFunction = TrivialCore_1.defaultListQueryFunctionFactory(this.config.entries || [], this.config.matchingOptions);
                    this.usingDefaultQueryFunction = true;
                }
                this.entries = this.config.entries;
                this.numberRegex = new RegExp('\\d*\\' + this.config.decimalSeparator + '?\\d*', 'g');
                this.$originalInput = $(originalInput).addClass("tr-original-input");
                this.$editor = $('<input type="text"/>');
                this.$unitBox = $('<div class="tr-unitbox tr-input-wrapper"/>').insertAfter(this.$originalInput)
                    .addClass(this.config.unitDisplayPosition === 'left' ? 'unit-display-left' : 'unit-display-right');
                this.$originalInput.appendTo(this.$unitBox);
                this.$selectedEntryAndTriggerWrapper = $('<div class="tr-unitbox-selected-entry-and-trigger-wrapper"/>').appendTo(this.$unitBox);
                this.$selectedEntryWrapper = $('<div class="tr-unitbox-selected-entry-wrapper"/>').appendTo(this.$selectedEntryAndTriggerWrapper);
                if (this.config.showTrigger) {
                    $('<div class="tr-trigger"><span class="tr-trigger-icon"/></div>').appendTo(this.$selectedEntryAndTriggerWrapper);
                }
                this.$selectedEntryAndTriggerWrapper.mousedown(function () {
                    if (_this.isDropDownOpen) {
                        _this.closeDropDown();
                    }
                    else if (_this.editingMode === "editable") {
                        setTimeout(function () {
                            _this.openDropDown();
                            _this.query();
                        });
                    }
                });
                this.$dropDown = $('<div class="tr-dropdown"></div>')
                    .scroll(function () {
                    return false;
                });
                this.$dropDownTargetElement = $("body");
                this.setEditingMode(this.config.editingMode);
                this.$editor.prependTo(this.$unitBox).addClass("tr-unitbox-editor tr-editor")
                    .focus(function () {
                    if (_this.editingMode !== "editable") {
                        _this.$editor.blur();
                        return false;
                    }
                    if (_this.blurCausedByClickInsideComponent) {
                    }
                    else {
                        _this.onFocus.fire();
                        _this.$unitBox.addClass('focus');
                        _this.cleanupEditorValue();
                        _this.$editor.select();
                    }
                })
                    .blur(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                    }
                    else {
                        _this.onBlur.fire();
                        _this.$unitBox.removeClass('focus');
                        _this.formatEditorValue();
                        _this.closeDropDown();
                    }
                })
                    .keydown(function (e) {
                    if (TrivialCore_1.keyCodes.isModifierKey(e)) {
                        return;
                    }
                    else if (e.which == TrivialCore_1.keyCodes.tab) {
                        var highlightedEntry = _this.listBox.getHighlightedEntry();
                        if (_this.isDropDownOpen && highlightedEntry) {
                            _this.setSelectedEntry(highlightedEntry, true, e);
                        }
                    }
                    else if (e.which == TrivialCore_1.keyCodes.left_arrow || e.which == TrivialCore_1.keyCodes.right_arrow) {
                        return;
                    }
                    if (e.which == TrivialCore_1.keyCodes.up_arrow || e.which == TrivialCore_1.keyCodes.down_arrow) {
                        var direction = e.which == TrivialCore_1.keyCodes.up_arrow ? -1 : 1;
                        if (_this.isDropDownOpen) {
                            _this.listBox.highlightNextEntry(direction);
                        }
                        else {
                            _this.openDropDown();
                            _this.query(direction);
                        }
                        return false;
                    }
                    else if (_this.isDropDownOpen && e.which == TrivialCore_1.keyCodes.enter) {
                        e.preventDefault();
                        _this.setSelectedEntry(_this.listBox.getHighlightedEntry(), true, e);
                        _this.closeDropDown();
                    }
                    else if (e.which == TrivialCore_1.keyCodes.escape) {
                        _this.closeDropDown();
                        _this.cleanupEditorValue();
                    }
                    else if (!e.shiftKey && TrivialCore_1.keyCodes.numberKeys.indexOf(e.which) != -1) {
                        var numberPart = _this.getEditorValueNumberPart();
                        var numberPartDecimalSeparatorIndex = numberPart.indexOf(_this.config.decimalSeparator);
                        var maxDecimalDigitsReached = numberPartDecimalSeparatorIndex != -1 && numberPart.length - (numberPartDecimalSeparatorIndex + 1) >= _this.config.decimalPrecision;
                        var editorValue = _this.$editor.val();
                        var decimalSeparatorIndex = editorValue.indexOf(_this.config.decimalSeparator);
                        var selectionStart = _this.$editor[0].selectionStart;
                        var selectionEnd = _this.$editor[0].selectionEnd;
                        var wouldAddAnotherDigit = decimalSeparatorIndex !== -1 && selectionEnd > decimalSeparatorIndex && selectionStart === selectionEnd;
                        if (maxDecimalDigitsReached && wouldAddAnotherDigit) {
                            if (/^\d$/.test(editorValue[selectionEnd])) {
                                _this.$editor.val(editorValue.substring(0, selectionEnd) + editorValue.substring(selectionEnd + 1));
                                _this.$editor[0].setSelectionRange(selectionEnd, selectionEnd);
                            }
                            else {
                                return false;
                            }
                        }
                    }
                })
                    .keyup(function (e) {
                    if (TrivialCore_1.keyCodes.specialKeys.indexOf(e.which) != -1
                        && e.which != TrivialCore_1.keyCodes.backspace
                        && e.which != TrivialCore_1.keyCodes.delete) {
                        return;
                    }
                    var hasDoubleDecimalSeparator = new RegExp("(?:\\" + _this.config.decimalSeparator + ".*)" + "\\" + _this.config.decimalSeparator, "g").test(_this.$editor.val());
                    if (hasDoubleDecimalSeparator) {
                        _this.cleanupEditorValue();
                        _this.$editor[0].setSelectionRange(_this.$editor.val().length - _this.config.decimalPrecision, _this.$editor.val().length - _this.config.decimalPrecision);
                    }
                    if (_this.config.queryOnNonNumberCharacters) {
                        if (_this.getQueryString().length > 0) {
                            _this.openDropDown();
                            _this.query(1);
                        }
                        else {
                            _this.closeDropDown();
                        }
                    }
                    else {
                        _this.ensureDecimalInput();
                    }
                })
                    .mousedown(function () {
                    if (_this.config.openDropdownOnEditorClick) {
                        _this.openDropDown();
                        if (_this.entries == null) {
                            _this.query();
                        }
                    }
                }).change(function (e) {
                    _this.updateOriginalInputValue();
                    _this.fireChangeEvents(e);
                });
                this.$unitBox.add(this.$dropDown).mousedown(function () {
                    if (_this.$editor.is(":focus")) {
                        _this.blurCausedByClickInsideComponent = true;
                    }
                }).mouseup(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                        _this.blurCausedByClickInsideComponent = false;
                    }
                }).mouseout(function () {
                    if (_this.blurCausedByClickInsideComponent) {
                        _this.$editor.focus();
                        _this.blurCausedByClickInsideComponent = false;
                    }
                });
                this.listBox = new TrivialListBox_1.TrivialListBox(this.$dropDown, this.config);
                this.listBox.onSelectedEntryChanged.addListener(function (selectedEntry, eventSource, originalEvent) {
                    if (selectedEntry) {
                        _this.setSelectedEntry(selectedEntry, true, originalEvent);
                        _this.listBox.setSelectedEntry(null);
                        _this.closeDropDown();
                    }
                });
                this.$editor.val(this.config.amount || this.$originalInput.val());
                this.formatEditorValue();
                this.setSelectedEntry(this.config.selectedEntry || null, false, null);
            }
            TrivialUnitBox.prototype.ensureDecimalInput = function () {
                var cursorPosition = this.$editor[0].selectionEnd;
                var oldValue = this.$editor.val();
                var newValue = oldValue.replace(new RegExp('[^\-0-9' + this.config.decimalSeparator + this.config.thousandsSeparator + ']', 'g'), '');
                newValue = newValue.replace(/(\d*\.\d*)\./g, '$1');
                newValue = newValue.replace(/(.)-*/g, '$1');
                var decimalSeparatorIndex = newValue.indexOf(this.config.decimalSeparator);
                if (decimalSeparatorIndex != -1 && newValue.length - decimalSeparatorIndex - 1 > this.config.decimalPrecision) {
                    newValue = newValue.substring(0, decimalSeparatorIndex + 1 + this.config.decimalPrecision);
                }
                if (oldValue !== newValue) {
                    this.$editor.val(newValue);
                    var newCursorPosition = Math.min(this.$editor.val().length, cursorPosition);
                    try {
                        this.$editor[0].setSelectionRange(newCursorPosition, newCursorPosition);
                    }
                    catch (e) {
                    }
                }
            };
            TrivialUnitBox.prototype.getQueryString = function () {
                return this.$editor.val().replace(this.numberRegex, '');
            };
            TrivialUnitBox.prototype.getEditorValueNumberPart = function (fillupDecimals) {
                var rawNumber = this.$editor.val().match(this.numberRegex).join('');
                var decimalDeparatorIndex = rawNumber.indexOf(this.config.decimalSeparator);
                var integerPart;
                var fractionalPart;
                if (decimalDeparatorIndex !== -1) {
                    integerPart = rawNumber.substring(0, decimalDeparatorIndex);
                    fractionalPart = rawNumber.substring(decimalDeparatorIndex + 1, rawNumber.length).replace(/\D/g, '');
                }
                else {
                    integerPart = rawNumber;
                    fractionalPart = "";
                }
                if (integerPart.length == 0 && fractionalPart.length == 0) {
                    return "";
                }
                else {
                    if (fillupDecimals) {
                        fractionalPart = (fractionalPart + new Array(this.config.decimalPrecision + 1).join("0")).substr(0, this.config.decimalPrecision);
                    }
                    return integerPart + this.config.decimalSeparator + fractionalPart;
                }
            };
            TrivialUnitBox.prototype.query = function (highlightDirection) {
                var _this = this;
                var $spinner = $(this.config.spinnerTemplate).appendTo(this.$dropDown);
                this.$spinners = this.$spinners.add($spinner);
                setTimeout(function () {
                    _this.config.queryFunction(_this.getQueryString(), function (newEntries) {
                        _this.updateEntries(newEntries);
                        var queryString = _this.getQueryString();
                        if (queryString.length > 0) {
                            _this.listBox.highlightTextMatches(queryString);
                        }
                        _this.listBox.highlightNextEntry(highlightDirection);
                        if (_this.isDropDownOpen) {
                            _this.openDropDown();
                        }
                    });
                });
            };
            TrivialUnitBox.prototype.fireSelectedEntryChangedEvent = function () {
                this.onSelectedEntryChanged.fire(this.selectedEntry);
            };
            TrivialUnitBox.prototype.fireChangeEvents = function (originalEvent) {
                this.$originalInput.trigger("change");
                this.onChange.fire({
                    unit: this.selectedEntry != null ? this.selectedEntry[this.config.unitValueProperty] : null,
                    unitEntry: this.selectedEntry,
                    amount: this.getAmount(),
                    amountAsFloatingPointNumber: parseFloat(this.formatAmount(this.getAmount(), this.config.decimalPrecision, this.config.decimalSeparator, this.config.thousandsSeparator))
                }, originalEvent);
            };
            TrivialUnitBox.prototype.setSelectedEntry = function (entry, fireEvent, originalEvent) {
                this.selectedEntry = entry;
                var $selectedEntry = $(this.config.selectedEntryRenderingFunction(entry))
                    .addClass("tr-combobox-entry");
                this.$selectedEntryWrapper.empty().append($selectedEntry);
                this.cleanupEditorValue();
                this.updateOriginalInputValue();
                if (!this.$editor.is(":focus")) {
                    this.formatEditorValue();
                }
                if (fireEvent) {
                    this.fireSelectedEntryChangedEvent();
                    this.fireChangeEvents(originalEvent);
                }
            };
            TrivialUnitBox.prototype.formatEditorValue = function () {
                this.$editor.val(this.formatAmount(this.getAmount(), this.config.decimalPrecision, this.config.decimalSeparator, this.config.thousandsSeparator));
            };
            TrivialUnitBox.prototype.cleanupEditorValue = function () {
                if (this.$editor.val()) {
                    this.$editor.val(this.getEditorValueNumberPart(true));
                }
            };
            TrivialUnitBox.prototype.formatAmount = function (integerNumber, precision, decimalSeparator, thousandsSeparator) {
                if (integerNumber == null || isNaN(integerNumber)) {
                    return "";
                }
                var amountAsString = "" + integerNumber;
                if (amountAsString.length <= precision) {
                    return 0 + decimalSeparator + new Array(precision - amountAsString.length + 1).join("0") + amountAsString;
                }
                else {
                    var integerPart = amountAsString.substring(0, amountAsString.length - precision);
                    var formattedIntegerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);
                    var fractionalPart = amountAsString.substr(amountAsString.length - precision, precision);
                    return formattedIntegerPart + decimalSeparator + fractionalPart;
                }
            };
            TrivialUnitBox.prototype.repositionDropDown = function () {
                var _this = this;
                this.$dropDown
                    .show()
                    .position({
                    my: "left top",
                    at: "left bottom",
                    of: this.$unitBox,
                    collision: "flip",
                    using: function (calculatedPosition, info) {
                        if (info.vertical === "top") {
                            _this.$unitBox.removeClass("dropdown-flipped");
                            _this.$dropDown.removeClass("flipped");
                        }
                        else {
                            _this.$unitBox.addClass("dropdown-flipped");
                            _this.$dropDown.addClass("flipped");
                        }
                        _this.$dropDown.css({
                            left: calculatedPosition.left + 'px',
                            top: calculatedPosition.top + 'px'
                        });
                    }
                })
                    .width(this.$unitBox.width());
            };
            ;
            TrivialUnitBox.prototype.openDropDown = function () {
                this.$unitBox.addClass("open");
                this.repositionDropDown();
                this.isDropDownOpen = true;
            };
            TrivialUnitBox.prototype.closeDropDown = function () {
                this.$unitBox.removeClass("open");
                this.$dropDown.hide();
                this.isDropDownOpen = false;
            };
            TrivialUnitBox.prototype.updateOriginalInputValue = function () {
                if (this.config.unitDisplayPosition === 'left') {
                    this.$originalInput.val((this.selectedEntry ? this.selectedEntry[this.config.unitValueProperty] : '') + this.formatAmount(this.getAmount(), this.config.decimalPrecision, this.config.decimalSeparator, ''));
                }
                else {
                    this.$originalInput.val(this.formatAmount(this.getAmount(), this.config.decimalPrecision, this.config.decimalSeparator, '') + (this.selectedEntry ? this.selectedEntry[this.config.unitValueProperty] : ''));
                }
            };
            TrivialUnitBox.prototype.getAmount = function () {
                var editorValueNumberPart = this.getEditorValueNumberPart(false);
                if (editorValueNumberPart.length === 0 && this.config.allowNullAmount) {
                    return null;
                }
                else if (editorValueNumberPart.length === 0) {
                    return 0;
                }
                else {
                    return parseInt(this.getEditorValueNumberPart(true).replace(/\D/g, ""));
                }
            };
            TrivialUnitBox.prototype.isDropDownNeeded = function () {
                return this.editingMode == 'editable' && (this.config.entries && this.config.entries.length > 0 || !this.usingDefaultQueryFunction || this.config.showTrigger);
            };
            TrivialUnitBox.prototype.setEditingMode = function (newEditingMode) {
                this.editingMode = newEditingMode;
                this.$unitBox.removeClass("editable readonly disabled").addClass(this.editingMode);
                this.$editor.prop("readonly", newEditingMode !== "editable");
                this.$editor.attr("tabindex", newEditingMode === "editable" ? this.$originalInput.attr("tabindex") : "-1");
                if (this.isDropDownNeeded()) {
                    this.$dropDown.appendTo(this.$dropDownTargetElement);
                }
            };
            TrivialUnitBox.prototype.selectUnit = function (unitIdentifier) {
                var _this = this;
                this.setSelectedEntry(this.entries.filter(function (entry) {
                    return entry[_this.config.unitIdProperty] === unitIdentifier;
                })[0], false, null);
            };
            TrivialUnitBox.prototype.updateEntries = function (newEntries) {
                this.entries = newEntries;
                this.$spinners.remove();
                this.$spinners = $();
                this.listBox.updateEntries(newEntries);
            };
            TrivialUnitBox.prototype.getSelectedEntry = function () {
                if (this.selectedEntry == null) {
                    return null;
                }
                else {
                    var selectedEntryToReturn = $.extend({}, this.selectedEntry);
                    selectedEntryToReturn._trEntryElement = undefined;
                    return selectedEntryToReturn;
                }
            };
            TrivialUnitBox.prototype.setAmount = function (amount) {
                if (amount != null && amount !== Math.floor(amount)) {
                    throw "TrivialUnitBox: You must specify an integer amount!";
                }
                if (amount == null) {
                    if (this.config.allowNullAmount) {
                        this.$editor.val("");
                    }
                    else {
                        this.$editor.val(this.formatAmount(0, this.config.decimalPrecision, this.config.decimalSeparator, ''));
                    }
                }
                else if (this.$editor.is(":focus")) {
                    this.$editor.val(this.formatAmount(amount, this.config.decimalPrecision, this.config.decimalSeparator, ''));
                }
                else {
                    this.$editor.val(this.formatAmount(amount, this.config.decimalPrecision, this.config.decimalSeparator, this.config.thousandsSeparator));
                }
            };
            ;
            TrivialUnitBox.prototype.focus = function () {
                this.$editor.select();
            };
            TrivialUnitBox.prototype.getEditor = function () {
                return this.$editor[0];
            };
            TrivialUnitBox.prototype.destroy = function () {
                this.$originalInput.removeClass('tr-original-input').insertBefore(this.$unitBox);
                this.$unitBox.remove();
                this.$dropDown.remove();
            };
            TrivialUnitBox.prototype.getMainDomElement = function () {
                return this.$unitBox[0];
            };
            return TrivialUnitBox;
        }());
        exports.TrivialUnitBox = TrivialUnitBox;
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "./TrivialCalendarBox", "./TrivialComboBox", "./TrivialCore", "./TrivialDateSuggestionEngine", "./TrivialDateTimeField", "./TrivialEvent", "./TrivialListBox", "./TrivialTagComboBox", "./TrivialTimeSuggestionEngine", "./TrivialTree", "./TrivialTreeBox", "./TrivialTreeComboBox", "./TrivialUnitBox"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        function __export(m) {
            for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
        }
        Object.defineProperty(exports, "__esModule", { value: true });
        __export(require("./TrivialCalendarBox"));
        __export(require("./TrivialComboBox"));
        __export(require("./TrivialCore"));
        __export(require("./TrivialDateSuggestionEngine"));
        __export(require("./TrivialDateTimeField"));
        __export(require("./TrivialEvent"));
        __export(require("./TrivialListBox"));
        __export(require("./TrivialTagComboBox"));
        __export(require("./TrivialTimeSuggestionEngine"));
        __export(require("./TrivialTree"));
        __export(require("./TrivialTreeBox"));
        __export(require("./TrivialTreeComboBox"));
        __export(require("./TrivialUnitBox"));
    });
    
    
    (function (factory) {
        if (typeof module === "object" && typeof module.exports === "object") {
            var v = factory(require, exports);
            if (v !== undefined) module.exports = v;
        }
        else if (typeof define === "function" && define.amd) {
            define(["require", "exports", "jquery", "./TrivialCore"], factory);
        } else {   window.TrivialComponents = window.TrivialComponents || {};  factory(function(name) {    if (name === "jquery") {      return window.jQuery;    } else if (name === "levenshtein") {      return window.Levenshtein;    } else if (name === "moment") {      return window.moment;    } else if (name === "mustache") {      return window.Mustache;    } else {      return window.TrivialComponents;    }  }, window.TrivialComponents);}
    })(function (require, exports) {
        "use strict";
        Object.defineProperty(exports, "__esModule", { value: true });
        var jQuery = require("jquery");
        var TrivialCore_1 = require("./TrivialCore");
        (function ($) {
            $.expr[":"].containsIgnoreCase = $.expr.createPseudo(function (arg) {
                return function (elem) {
                    return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
                };
            });
        })(jQuery);
        (function ($) {
            var isIE11 = !(window.ActiveXObject) && "ActiveXObject" in window;
            function normalizeForIE11(node) {
                if (!node) {
                    return;
                }
                if (node.nodeType == 3) {
                    while (node.nextSibling && node.nextSibling.nodeType == 3) {
                        node.nodeValue += node.nextSibling.nodeValue;
                        node.parentNode.removeChild(node.nextSibling);
                    }
                }
                else {
                    normalizeForIE11(node.firstChild);
                }
                normalizeForIE11(node.nextSibling);
            }
            $.fn.trivialHighlight = function (searchString, options) {
                options = $.extend({
                    highlightClassName: 'tr-highlighted-text',
                    matchingMode: 'contains',
                    ignoreCase: true,
                    maxLevenshteinDistance: 3
                }, options);
                return this.find('*').each(function () {
                    var $this = $(this);
                    $this.find('.' + options.highlightClassName).contents().unwrap();
                    if (isIE11) {
                        normalizeForIE11(this);
                    }
                    else {
                        this.normalize();
                    }
                    if (searchString && searchString !== '') {
                        $this.contents().filter(function () {
                            return this.nodeType == 3 && TrivialCore_1.trivialMatch(this.nodeValue, searchString, options).length > 0;
                        }).replaceWith(function () {
                            var oldNodeValue = (this.nodeValue || "");
                            var newNodeValue = "";
                            var matches = TrivialCore_1.trivialMatch(this.nodeValue, searchString, options);
                            var oldMatchEnd = 0;
                            for (var i = 0; i < matches.length; i++) {
                                var match = matches[i];
                                newNodeValue += this.nodeValue.substring(oldMatchEnd, match.start);
                                newNodeValue += "<span class=\"" + options.highlightClassName + "\">" + oldNodeValue.substr(match.start, match.length) + "</span>";
                                oldMatchEnd = match.start + match.length;
                            }
                            newNodeValue += oldNodeValue.substring(oldMatchEnd, oldNodeValue.length);
                            return newNodeValue;
                        });
                    }
                });
            };
        }(jQuery));
    });
    
    
    //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInByZXR0aWZ5LmpzIiwibW9tZW50LXdpdGgtbG9jYWxlcy5qcyIsIm1vbWVudC10aW1lem9uZS5taW4uanMiLCJ0ZW1wdXNkb21pbnVzLWNvcmUuanMiLCJ0ZW1wdXNkb21pbnVzLWJvb3RzdHJhcC00LmpzIiwianF1ZXJ5LmlucHV0bWFzay5qcyIsInZlcnNpb24uanMiLCJwb3NpdGlvbi5qcyIsInNob3dkb3duLmpzIiwibWFya2Rvd24uanMiLCJ0by1tYXJrZG93bi5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5hci5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5jcy5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5kYS5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5kZS5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5lcy5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5mYS5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5mci5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5qYS5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5rci5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5uYi5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5ubC5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5wbC5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5zbC5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi5zdi5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi50ci5qcyIsImJvb3RzdHJhcC1tYXJrZG93bi56aC5qcyIsIm11c3RhY2hlLm1pbi5qcyIsInRyaXZpYWwtY29tcG9uZW50cy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN2bkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ25xakJBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzd2REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2o3R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDdjRGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNsZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3ZoS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM3ckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3B4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzkyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDaENBO0FBQ0E7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiYnV0dGVyZmFjZXMtdGhpcmQtcGFydHkuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKEMpIDIwMDYgR29vZ2xlIEluYy5cbi8vXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuLy8geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuLy8gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4vL1xuLy8gICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbi8vXG4vLyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4vLyBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4vLyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbi8vIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbi8vIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG5cbi8qKlxuICogQGZpbGVvdmVydmlld1xuICogc29tZSBmdW5jdGlvbnMgZm9yIGJyb3dzZXItc2lkZSBwcmV0dHkgcHJpbnRpbmcgb2YgY29kZSBjb250YWluZWQgaW4gaHRtbC5cbiAqXG4gKiA8cD5cbiAqIEZvciBhIGZhaXJseSBjb21wcmVoZW5zaXZlIHNldCBvZiBsYW5ndWFnZXMgc2VlIHRoZVxuICogPGEgaHJlZj1cImh0dHA6Ly9nb29nbGUtY29kZS1wcmV0dGlmeS5nb29nbGVjb2RlLmNvbS9zdm4vdHJ1bmsvUkVBRE1FLmh0bWwjbGFuZ3NcIj5SRUFETUU8L2E+XG4gKiBmaWxlIHRoYXQgY2FtZSB3aXRoIHRoaXMgc291cmNlLiAgQXQgYSBtaW5pbXVtLCB0aGUgbGV4ZXIgc2hvdWxkIHdvcmsgb24gYVxuICogbnVtYmVyIG9mIGxhbmd1YWdlcyBpbmNsdWRpbmcgQyBhbmQgZnJpZW5kcywgSmF2YSwgUHl0aG9uLCBCYXNoLCBTUUwsIEhUTUwsXG4gKiBYTUwsIENTUywgSmF2YXNjcmlwdCwgYW5kIE1ha2VmaWxlcy4gIEl0IHdvcmtzIHBhc3NhYmx5IG9uIFJ1YnksIFBIUCBhbmQgQXdrXG4gKiBhbmQgYSBzdWJzZXQgb2YgUGVybCwgYnV0LCBiZWNhdXNlIG9mIGNvbW1lbnRpbmcgY29udmVudGlvbnMsIGRvZXNuJ3Qgd29yayBvblxuICogU21hbGx0YWxrLCBMaXNwLWxpa2UsIG9yIENBTUwtbGlrZSBsYW5ndWFnZXMgd2l0aG91dCBhbiBleHBsaWNpdCBsYW5nIGNsYXNzLlxuICogPHA+XG4gKiBVc2FnZTogPG9sPlxuICogPGxpPiBpbmNsdWRlIHRoaXMgc291cmNlIGZpbGUgaW4gYW4gaHRtbCBwYWdlIHZpYVxuICogICB7QGNvZGUgPHNjcmlwdCB0eXBlPVwidGV4dC9qYXZhc2NyaXB0XCIgc3JjPVwiL3BhdGgvdG8vcHJldHRpZnkuanNcIj48L3NjcmlwdD59XG4gKiA8bGk+IGRlZmluZSBzdHlsZSBydWxlcy4gIFNlZSB0aGUgZXhhbXBsZSBwYWdlIGZvciBleGFtcGxlcy5cbiAqIDxsaT4gbWFyayB0aGUge0Bjb2RlIDxwcmU+fSBhbmQge0Bjb2RlIDxjb2RlPn0gdGFncyBpbiB5b3VyIHNvdXJjZSB3aXRoXG4gKiAgICB7QGNvZGUgY2xhc3M9cHJldHR5cHJpbnQufVxuICogICAgWW91IGNhbiBhbHNvIHVzZSB0aGUgKGh0bWwgZGVwcmVjYXRlZCkge0Bjb2RlIDx4bXA+fSB0YWcsIGJ1dCB0aGUgcHJldHR5XG4gKiAgICBwcmludGVyIG5lZWRzIHRvIGRvIG1vcmUgc3Vic3RhbnRpYWwgRE9NIG1hbmlwdWxhdGlvbnMgdG8gc3VwcG9ydCB0aGF0LCBzb1xuICogICAgc29tZSBjc3Mgc3R5bGVzIG1heSBub3QgYmUgcHJlc2VydmVkLlxuICogPC9vbD5cbiAqIFRoYXQncyBpdC4gIEkgd2FudGVkIHRvIGtlZXAgdGhlIEFQSSBhcyBzaW1wbGUgYXMgcG9zc2libGUsIHNvIHRoZXJlJ3Mgbm9cbiAqIG5lZWQgdG8gc3BlY2lmeSB3aGljaCBsYW5ndWFnZSB0aGUgY29kZSBpcyBpbiwgYnV0IGlmIHlvdSB3aXNoLCB5b3UgY2FuIGFkZFxuICogYW5vdGhlciBjbGFzcyB0byB0aGUge0Bjb2RlIDxwcmU+fSBvciB7QGNvZGUgPGNvZGU+fSBlbGVtZW50IHRvIHNwZWNpZnkgdGhlXG4gKiBsYW5ndWFnZSwgYXMgaW4ge0Bjb2RlIDxwcmUgY2xhc3M9XCJwcmV0dHlwcmludCBsYW5nLWphdmFcIj59LiAgQW55IGNsYXNzIHRoYXRcbiAqIHN0YXJ0cyB3aXRoIFwibGFuZy1cIiBmb2xsb3dlZCBieSBhIGZpbGUgZXh0ZW5zaW9uLCBzcGVjaWZpZXMgdGhlIGZpbGUgdHlwZS5cbiAqIFNlZSB0aGUgXCJsYW5nLSouanNcIiBmaWxlcyBpbiB0aGlzIGRpcmVjdG9yeSBmb3IgY29kZSB0aGF0IGltcGxlbWVudHNcbiAqIHBlci1sYW5ndWFnZSBmaWxlIGhhbmRsZXJzLlxuICogPHA+XG4gKiBDaGFuZ2UgbG9nOjxicj5cbiAqIGNiZXVzdCwgMjAwNi8wOC8yMlxuICogPGJsb2NrcXVvdGU+XG4gKiAgIEphdmEgYW5ub3RhdGlvbnMgKHN0YXJ0IHdpdGggXCJAXCIpIGFyZSBub3cgY2FwdHVyZWQgYXMgbGl0ZXJhbHMgKFwibGl0XCIpXG4gKiA8L2Jsb2NrcXVvdGU+XG4gKiBAcmVxdWlyZXMgY29uc29sZVxuICovXG5cbi8vIEpTTGludCBkZWNsYXJhdGlvbnNcbi8qZ2xvYmFsIGNvbnNvbGUsIGRvY3VtZW50LCBuYXZpZ2F0b3IsIHNldFRpbWVvdXQsIHdpbmRvdywgZGVmaW5lICovXG5cbi8qKiBAZGVmaW5lIHtib29sZWFufSAqL1xudmFyIElOX0dMT0JBTF9TQ09QRSA9IHRydWU7XG5cbi8qKlxuICogU3BsaXQge0Bjb2RlIHByZXR0eVByaW50fSBpbnRvIG11bHRpcGxlIHRpbWVvdXRzIHNvIGFzIG5vdCB0byBpbnRlcmZlcmUgd2l0aFxuICogVUkgZXZlbnRzLlxuICogSWYgc2V0IHRvIHtAY29kZSBmYWxzZX0sIHtAY29kZSBwcmV0dHlQcmludCgpfSBpcyBzeW5jaHJvbm91cy5cbiAqL1xud2luZG93WydQUl9TSE9VTERfVVNFX0NPTlRJTlVBVElPTiddID0gdHJ1ZTtcblxuLyoqXG4gKiBQcmV0dHkgcHJpbnQgYSBjaHVuayBvZiBjb2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZUNvZGVIdG1sIFRoZSBIVE1MIHRvIHByZXR0eSBwcmludC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRfbGFuZ0V4dGVuc2lvbiBUaGUgbGFuZ3VhZ2UgbmFtZSB0byB1c2UuXG4gKiAgICAgVHlwaWNhbGx5LCBhIGZpbGVuYW1lIGV4dGVuc2lvbiBsaWtlICdjcHAnIG9yICdqYXZhJy5cbiAqIEBwYXJhbSB7bnVtYmVyfGJvb2xlYW59IG9wdF9udW1iZXJMaW5lcyBUcnVlIHRvIG51bWJlciBsaW5lcyxcbiAqICAgICBvciB0aGUgMS1pbmRleGVkIG51bWJlciBvZiB0aGUgZmlyc3QgbGluZSBpbiBzb3VyY2VDb2RlSHRtbC5cbiAqIEByZXR1cm4ge3N0cmluZ30gY29kZSBhcyBodG1sLCBidXQgcHJldHRpZXJcbiAqL1xudmFyIHByZXR0eVByaW50T25lO1xuLyoqXG4gKiBGaW5kIGFsbCB0aGUge0Bjb2RlIDxwcmU+fSBhbmQge0Bjb2RlIDxjb2RlPn0gdGFncyBpbiB0aGUgRE9NIHdpdGhcbiAqIHtAY29kZSBjbGFzcz1wcmV0dHlwcmludH0gYW5kIHByZXR0aWZ5IHRoZW0uXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gb3B0X3doZW5Eb25lIGNhbGxlZCB3aGVuIHByZXR0aWZ5aW5nIGlzIGRvbmUuXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxEb2N1bWVudH0gb3B0X3Jvb3QgYW4gZWxlbWVudCBvciBkb2N1bWVudFxuICogICBjb250YWluaW5nIGFsbCB0aGUgZWxlbWVudHMgdG8gcHJldHR5IHByaW50LlxuICogICBEZWZhdWx0cyB0byB7QGNvZGUgZG9jdW1lbnQuYm9keX0uXG4gKi9cbnZhciBwcmV0dHlQcmludDtcblxuXG4oZnVuY3Rpb24gKCkge1xuICB2YXIgd2luID0gd2luZG93O1xuICAvLyBLZXl3b3JkIGxpc3RzIGZvciB2YXJpb3VzIGxhbmd1YWdlcy5cbiAgLy8gV2UgdXNlIHRoaW5ncyB0aGF0IGNvZXJjZSB0byBzdHJpbmdzIHRvIG1ha2UgdGhlbSBjb21wYWN0IHdoZW4gbWluaWZpZWRcbiAgLy8gYW5kIHRvIGRlZmVhdCBhZ2dyZXNzaXZlIG9wdGltaXplcnMgdGhhdCBmb2xkIGxhcmdlIHN0cmluZyBjb25zdGFudHMuXG4gIHZhciBGTE9XX0NPTlRST0xfS0VZV09SRFMgPSBbXCJicmVhayxjb250aW51ZSxkbyxlbHNlLGZvcixpZixyZXR1cm4sd2hpbGVcIl07XG4gIHZhciBDX0tFWVdPUkRTID0gW0ZMT1dfQ09OVFJPTF9LRVlXT1JEUyxcImF1dG8sY2FzZSxjaGFyLGNvbnN0LGRlZmF1bHQsXCIgKyBcbiAgICAgIFwiZG91YmxlLGVudW0sZXh0ZXJuLGZsb2F0LGdvdG8saW5saW5lLGludCxsb25nLHJlZ2lzdGVyLHNob3J0LHNpZ25lZCxcIiArXG4gICAgICBcInNpemVvZixzdGF0aWMsc3RydWN0LHN3aXRjaCx0eXBlZGVmLHVuaW9uLHVuc2lnbmVkLHZvaWQsdm9sYXRpbGVcIl07XG4gIHZhciBDT01NT05fS0VZV09SRFMgPSBbQ19LRVlXT1JEUyxcImNhdGNoLGNsYXNzLGRlbGV0ZSxmYWxzZSxpbXBvcnQsXCIgK1xuICAgICAgXCJuZXcsb3BlcmF0b3IscHJpdmF0ZSxwcm90ZWN0ZWQscHVibGljLHRoaXMsdGhyb3csdHJ1ZSx0cnksdHlwZW9mXCJdO1xuICB2YXIgQ1BQX0tFWVdPUkRTID0gW0NPTU1PTl9LRVlXT1JEUyxcImFsaWdub2YsYWxpZ25fdW5pb24sYXNtLGF4aW9tLGJvb2wsXCIgK1xuICAgICAgXCJjb25jZXB0LGNvbmNlcHRfbWFwLGNvbnN0X2Nhc3QsY29uc3RleHByLGRlY2x0eXBlLGRlbGVnYXRlLFwiICtcbiAgICAgIFwiZHluYW1pY19jYXN0LGV4cGxpY2l0LGV4cG9ydCxmcmllbmQsZ2VuZXJpYyxsYXRlX2NoZWNrLFwiICtcbiAgICAgIFwibXV0YWJsZSxuYW1lc3BhY2UsbnVsbHB0cixwcm9wZXJ0eSxyZWludGVycHJldF9jYXN0LHN0YXRpY19hc3NlcnQsXCIgK1xuICAgICAgXCJzdGF0aWNfY2FzdCx0ZW1wbGF0ZSx0eXBlaWQsdHlwZW5hbWUsdXNpbmcsdmlydHVhbCx3aGVyZVwiXTtcbiAgdmFyIEpBVkFfS0VZV09SRFMgPSBbQ09NTU9OX0tFWVdPUkRTLFxuICAgICAgXCJhYnN0cmFjdCxhc3NlcnQsYm9vbGVhbixieXRlLGV4dGVuZHMsZmluYWwsZmluYWxseSxpbXBsZW1lbnRzLGltcG9ydCxcIiArXG4gICAgICBcImluc3RhbmNlb2YsaW50ZXJmYWNlLG51bGwsbmF0aXZlLHBhY2thZ2Usc3RyaWN0ZnAsc3VwZXIsc3luY2hyb25pemVkLFwiICtcbiAgICAgIFwidGhyb3dzLHRyYW5zaWVudFwiXTtcbiAgdmFyIENTSEFSUF9LRVlXT1JEUyA9IFtKQVZBX0tFWVdPUkRTLFxuICAgICAgXCJhcyxiYXNlLGJ5LGNoZWNrZWQsZGVjaW1hbCxkZWxlZ2F0ZSxkZXNjZW5kaW5nLGR5bmFtaWMsZXZlbnQsXCIgK1xuICAgICAgXCJmaXhlZCxmb3JlYWNoLGZyb20sZ3JvdXAsaW1wbGljaXQsaW4saW50ZXJuYWwsaW50byxpcyxsZXQsXCIgK1xuICAgICAgXCJsb2NrLG9iamVjdCxvdXQsb3ZlcnJpZGUsb3JkZXJieSxwYXJhbXMscGFydGlhbCxyZWFkb25seSxyZWYsc2J5dGUsXCIgK1xuICAgICAgXCJzZWFsZWQsc3RhY2thbGxvYyxzdHJpbmcsc2VsZWN0LHVpbnQsdWxvbmcsdW5jaGVja2VkLHVuc2FmZSx1c2hvcnQsXCIgK1xuICAgICAgXCJ2YXIsdmlydHVhbCx3aGVyZVwiXTtcbiAgdmFyIENPRkZFRV9LRVlXT1JEUyA9IFwiYWxsLGFuZCxieSxjYXRjaCxjbGFzcyxlbHNlLGV4dGVuZHMsZmFsc2UsZmluYWxseSxcIiArXG4gICAgICBcImZvcixpZixpbixpcyxpc250LGxvb3AsbmV3LG5vLG5vdCxudWxsLG9mLG9mZixvbixvcixyZXR1cm4sc3VwZXIsdGhlbixcIiArXG4gICAgICBcInRocm93LHRydWUsdHJ5LHVubGVzcyx1bnRpbCx3aGVuLHdoaWxlLHllc1wiO1xuICB2YXIgSlNDUklQVF9LRVlXT1JEUyA9IFtDT01NT05fS0VZV09SRFMsXG4gICAgICBcImRlYnVnZ2VyLGV2YWwsZXhwb3J0LGZ1bmN0aW9uLGdldCxudWxsLHNldCx1bmRlZmluZWQsdmFyLHdpdGgsXCIgK1xuICAgICAgXCJJbmZpbml0eSxOYU5cIl07XG4gIHZhciBQRVJMX0tFWVdPUkRTID0gXCJjYWxsZXIsZGVsZXRlLGRpZSxkbyxkdW1wLGVsc2lmLGV2YWwsZXhpdCxmb3JlYWNoLGZvcixcIiArXG4gICAgICBcImdvdG8saWYsaW1wb3J0LGxhc3QsbG9jYWwsbXksbmV4dCxubyxvdXIscHJpbnQscGFja2FnZSxyZWRvLHJlcXVpcmUsXCIgK1xuICAgICAgXCJzdWIsdW5kZWYsdW5sZXNzLHVudGlsLHVzZSx3YW50YXJyYXksd2hpbGUsQkVHSU4sRU5EXCI7XG4gIHZhciBQWVRIT05fS0VZV09SRFMgPSBbRkxPV19DT05UUk9MX0tFWVdPUkRTLCBcImFuZCxhcyxhc3NlcnQsY2xhc3MsZGVmLGRlbCxcIiArXG4gICAgICBcImVsaWYsZXhjZXB0LGV4ZWMsZmluYWxseSxmcm9tLGdsb2JhbCxpbXBvcnQsaW4saXMsbGFtYmRhLFwiICtcbiAgICAgIFwibm9ubG9jYWwsbm90LG9yLHBhc3MscHJpbnQscmFpc2UsdHJ5LHdpdGgseWllbGQsXCIgK1xuICAgICAgXCJGYWxzZSxUcnVlLE5vbmVcIl07XG4gIHZhciBSVUJZX0tFWVdPUkRTID0gW0ZMT1dfQ09OVFJPTF9LRVlXT1JEUywgXCJhbGlhcyxhbmQsYmVnaW4sY2FzZSxjbGFzcyxcIiArXG4gICAgICBcImRlZixkZWZpbmVkLGVsc2lmLGVuZCxlbnN1cmUsZmFsc2UsaW4sbW9kdWxlLG5leHQsbmlsLG5vdCxvcixyZWRvLFwiICtcbiAgICAgIFwicmVzY3VlLHJldHJ5LHNlbGYsc3VwZXIsdGhlbix0cnVlLHVuZGVmLHVubGVzcyx1bnRpbCx3aGVuLHlpZWxkLFwiICtcbiAgICAgIFwiQkVHSU4sRU5EXCJdO1xuICAgdmFyIFJVU1RfS0VZV09SRFMgPSBbRkxPV19DT05UUk9MX0tFWVdPUkRTLCBcImFzLGFzc2VydCxjb25zdCxjb3B5LGRyb3AsXCIgK1xuICAgICAgXCJlbnVtLGV4dGVybixmYWlsLGZhbHNlLGZuLGltcGwsbGV0LGxvZyxsb29wLG1hdGNoLG1vZCxtb3ZlLG11dCxwcml2LFwiICtcbiAgICAgIFwicHViLHB1cmUscmVmLHNlbGYsc3RhdGljLHN0cnVjdCx0cnVlLHRyYWl0LHR5cGUsdW5zYWZlLHVzZVwiXTtcbiAgdmFyIFNIX0tFWVdPUkRTID0gW0ZMT1dfQ09OVFJPTF9LRVlXT1JEUywgXCJjYXNlLGRvbmUsZWxpZixlc2FjLGV2YWwsZmksXCIgK1xuICAgICAgXCJmdW5jdGlvbixpbixsb2NhbCxzZXQsdGhlbix1bnRpbFwiXTtcbiAgdmFyIEFMTF9LRVlXT1JEUyA9IFtcbiAgICAgIENQUF9LRVlXT1JEUywgQ1NIQVJQX0tFWVdPUkRTLCBKU0NSSVBUX0tFWVdPUkRTLCBQRVJMX0tFWVdPUkRTLFxuICAgICAgUFlUSE9OX0tFWVdPUkRTLCBSVUJZX0tFWVdPUkRTLCBTSF9LRVlXT1JEU107XG4gIHZhciBDX1RZUEVTID0gL14oRElSfEZJTEV8dmVjdG9yfChkZXxwcmlvcml0eV8pP3F1ZXVlfGxpc3R8c3RhY2t8KGNvbnN0Xyk/aXRlcmF0b3J8KG11bHRpKT8oc2V0fG1hcCl8Yml0c2V0fHU/KGludHxmbG9hdClcXGQqKVxcYi87XG5cbiAgLy8gdG9rZW4gc3R5bGUgbmFtZXMuICBjb3JyZXNwb25kIHRvIGNzcyBjbGFzc2VzXG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYSBzdHJpbmcgbGl0ZXJhbFxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9TVFJJTkcgPSAnc3RyJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhIGtleXdvcmRcbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfS0VZV09SRCA9ICdrd2QnO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGEgY29tbWVudFxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9DT01NRU5UID0gJ2NvbSc7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYSB0eXBlXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX1RZUEUgPSAndHlwJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhIGxpdGVyYWwgdmFsdWUuICBlLmcuIDEsIG51bGwsIHRydWUuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX0xJVEVSQUwgPSAnbGl0JztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhIHB1bmN0dWF0aW9uIHN0cmluZy5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfUFVOQ1RVQVRJT04gPSAncHVuJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBwbGFpbiB0ZXh0LlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9QTEFJTiA9ICdwbG4nO1xuXG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYW4gc2dtbCB0YWcuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX1RBRyA9ICd0YWcnO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGEgbWFya3VwIGRlY2xhcmF0aW9uIHN1Y2ggYXMgYSBET0NUWVBFLlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9ERUNMQVJBVElPTiA9ICdkZWMnO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGVtYmVkZGVkIHNvdXJjZS5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfU09VUkNFID0gJ3NyYyc7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYW4gc2dtbCBhdHRyaWJ1dGUgbmFtZS5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfQVRUUklCX05BTUUgPSAnYXRuJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhbiBzZ21sIGF0dHJpYnV0ZSB2YWx1ZS5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfQVRUUklCX1ZBTFVFID0gJ2F0dic7XG5cbiAgLyoqXG4gICAqIEEgY2xhc3MgdGhhdCBpbmRpY2F0ZXMgYSBzZWN0aW9uIG9mIG1hcmt1cCB0aGF0IGlzIG5vdCBjb2RlLCBlLmcuIHRvIGFsbG93XG4gICAqIGVtYmVkZGluZyBvZiBsaW5lIG51bWJlcnMgd2l0aGluIGNvZGUgbGlzdGluZ3MuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX05PQ09ERSA9ICdub2NvZGUnO1xuXG4gIFxuICBcbiAgLyoqXG4gICAqIEEgc2V0IG9mIHRva2VucyB0aGF0IGNhbiBwcmVjZWRlIGEgcmVndWxhciBleHByZXNzaW9uIGxpdGVyYWwgaW5cbiAgICogamF2YXNjcmlwdFxuICAgKiBodHRwOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDA3MDcxNzE0MjUxNS9odHRwOi8vd3d3Lm1vemlsbGEub3JnL2pzL2xhbmd1YWdlL2pzMjAvcmF0aW9uYWxlL3N5bnRheC5odG1sXG4gICAqIGhhcyB0aGUgZnVsbCBsaXN0LCBidXQgSSd2ZSByZW1vdmVkIG9uZXMgdGhhdCBtaWdodCBiZSBwcm9ibGVtYXRpYyB3aGVuXG4gICAqIHNlZW4gaW4gbGFuZ3VhZ2VzIHRoYXQgZG9uJ3Qgc3VwcG9ydCByZWd1bGFyIGV4cHJlc3Npb24gbGl0ZXJhbHMuXG4gICAqXG4gICAqIDxwPlNwZWNpZmljYWxseSwgSSd2ZSByZW1vdmVkIGFueSBrZXl3b3JkcyB0aGF0IGNhbid0IHByZWNlZGUgYSByZWdleHBcbiAgICogbGl0ZXJhbCBpbiBhIHN5bnRhY3RpY2FsbHkgbGVnYWwgamF2YXNjcmlwdCBwcm9ncmFtLCBhbmQgSSd2ZSByZW1vdmVkIHRoZVxuICAgKiBcImluXCIga2V5d29yZCBzaW5jZSBpdCdzIG5vdCBhIGtleXdvcmQgaW4gbWFueSBsYW5ndWFnZXMsIGFuZCBtaWdodCBiZSB1c2VkXG4gICAqIGFzIGEgY291bnQgb2YgaW5jaGVzLlxuICAgKlxuICAgKiA8cD5UaGUgbGluayBhYm92ZSBkb2VzIG5vdCBhY2N1cmF0ZWx5IGRlc2NyaWJlIEVjbWFTY3JpcHQgcnVsZXMgc2luY2VcbiAgICogaXQgZmFpbHMgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiAoYT0rKy9iL2kpIGFuZCAoYSsrL2IvaSkgYnV0IGl0IHdvcmtzXG4gICAqIHZlcnkgd2VsbCBpbiBwcmFjdGljZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUkVHRVhQX1BSRUNFREVSX1BBVFRFUk4gPSAnKD86Xl5cXFxcLj98WystXXxbIT1dPT89P3xcXFxcI3wlPT98JiY/PT98XFxcXCh8XFxcXCo9P3xbK1xcXFwtXT18LT58XFxcXC89P3w6Oj98PDw/PT98Pj4/Pj89P3wsfDt8XFxcXD98QHxcXFxcW3x+fHt8XFxcXF5cXFxcXj89P3xcXFxcfFxcXFx8Pz0/fGJyZWFrfGNhc2V8Y29udGludWV8ZGVsZXRlfGRvfGVsc2V8ZmluYWxseXxpbnN0YW5jZW9mfHJldHVybnx0aHJvd3x0cnl8dHlwZW9mKVxcXFxzKic7XG4gIFxuICAvLyBDQVZFQVQ6IHRoaXMgZG9lcyBub3QgcHJvcGVybHkgaGFuZGxlIHRoZSBjYXNlIHdoZXJlIGEgcmVndWxhclxuICAvLyBleHByZXNzaW9uIGltbWVkaWF0ZWx5IGZvbGxvd3MgYW5vdGhlciBzaW5jZSBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBtYXlcbiAgLy8gaGF2ZSBmbGFncyBmb3IgY2FzZS1zZW5zaXRpdml0eSBhbmQgdGhlIGxpa2UuICBIYXZpbmcgcmVnZXhwIHRva2Vuc1xuICAvLyBhZGphY2VudCBpcyBub3QgdmFsaWQgaW4gYW55IGxhbmd1YWdlIEknbSBhd2FyZSBvZiwgc28gSSdtIHB1bnRpbmcuXG4gIC8vIFRPRE86IG1heWJlIHN0eWxlIHNwZWNpYWwgY2hhcmFjdGVycyBpbnNpZGUgYSByZWdleHAgYXMgcHVuY3R1YXRpb24uXG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgZ3JvdXAgb2Yge0BsaW5rIFJlZ0V4cH1zLCByZXR1cm5zIGEge0Bjb2RlIFJlZ0V4cH0gdGhhdCBnbG9iYWxseVxuICAgKiBtYXRjaGVzIHRoZSB1bmlvbiBvZiB0aGUgc2V0cyBvZiBzdHJpbmdzIG1hdGNoZWQgYnkgdGhlIGlucHV0IFJlZ0V4cC5cbiAgICogU2luY2UgaXQgbWF0Y2hlcyBnbG9iYWxseSwgaWYgdGhlIGlucHV0IHN0cmluZ3MgaGF2ZSBhIHN0YXJ0LW9mLWlucHV0XG4gICAqIGFuY2hvciAoL14uLi4vKSwgaXQgaXMgaWdub3JlZCBmb3IgdGhlIHB1cnBvc2VzIG9mIHVuaW9uaW5nLlxuICAgKiBAcGFyYW0ge0FycmF5LjxSZWdFeHA+fSByZWdleHMgbm9uIG11bHRpbGluZSwgbm9uLWdsb2JhbCByZWdleHMuXG4gICAqIEByZXR1cm4ge1JlZ0V4cH0gYSBnbG9iYWwgcmVnZXguXG4gICAqL1xuICBmdW5jdGlvbiBjb21iaW5lUHJlZml4UGF0dGVybnMocmVnZXhzKSB7XG4gICAgdmFyIGNhcHR1cmVkR3JvdXBJbmRleCA9IDA7XG4gIFxuICAgIHZhciBuZWVkVG9Gb2xkQ2FzZSA9IGZhbHNlO1xuICAgIHZhciBpZ25vcmVDYXNlID0gZmFsc2U7XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSByZWdleHMubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICB2YXIgcmVnZXggPSByZWdleHNbaV07XG4gICAgICBpZiAocmVnZXguaWdub3JlQ2FzZSkge1xuICAgICAgICBpZ25vcmVDYXNlID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoL1thLXpdL2kudGVzdChyZWdleC5zb3VyY2UucmVwbGFjZShcbiAgICAgICAgICAgICAgICAgICAgIC9cXFxcdVswLTlhLWZdezR9fFxcXFx4WzAtOWEtZl17Mn18XFxcXFtedXhdL2dpLCAnJykpKSB7XG4gICAgICAgIG5lZWRUb0ZvbGRDYXNlID0gdHJ1ZTtcbiAgICAgICAgaWdub3JlQ2FzZSA9IGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIFxuICAgIHZhciBlc2NhcGVDaGFyVG9Db2RlVW5pdCA9IHtcbiAgICAgICdiJzogOCxcbiAgICAgICd0JzogOSxcbiAgICAgICduJzogMHhhLFxuICAgICAgJ3YnOiAweGIsXG4gICAgICAnZic6IDB4YyxcbiAgICAgICdyJzogMHhkXG4gICAgfTtcbiAgXG4gICAgZnVuY3Rpb24gZGVjb2RlRXNjYXBlKGNoYXJzZXRQYXJ0KSB7XG4gICAgICB2YXIgY2MwID0gY2hhcnNldFBhcnQuY2hhckNvZGVBdCgwKTtcbiAgICAgIGlmIChjYzAgIT09IDkyIC8qIFxcXFwgKi8pIHtcbiAgICAgICAgcmV0dXJuIGNjMDtcbiAgICAgIH1cbiAgICAgIHZhciBjMSA9IGNoYXJzZXRQYXJ0LmNoYXJBdCgxKTtcbiAgICAgIGNjMCA9IGVzY2FwZUNoYXJUb0NvZGVVbml0W2MxXTtcbiAgICAgIGlmIChjYzApIHtcbiAgICAgICAgcmV0dXJuIGNjMDtcbiAgICAgIH0gZWxzZSBpZiAoJzAnIDw9IGMxICYmIGMxIDw9ICc3Jykge1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQoY2hhcnNldFBhcnQuc3Vic3RyaW5nKDEpLCA4KTtcbiAgICAgIH0gZWxzZSBpZiAoYzEgPT09ICd1JyB8fCBjMSA9PT0gJ3gnKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUludChjaGFyc2V0UGFydC5zdWJzdHJpbmcoMiksIDE2KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBjaGFyc2V0UGFydC5jaGFyQ29kZUF0KDEpO1xuICAgICAgfVxuICAgIH1cbiAgXG4gICAgZnVuY3Rpb24gZW5jb2RlRXNjYXBlKGNoYXJDb2RlKSB7XG4gICAgICBpZiAoY2hhckNvZGUgPCAweDIwKSB7XG4gICAgICAgIHJldHVybiAoY2hhckNvZGUgPCAweDEwID8gJ1xcXFx4MCcgOiAnXFxcXHgnKSArIGNoYXJDb2RlLnRvU3RyaW5nKDE2KTtcbiAgICAgIH1cbiAgICAgIHZhciBjaCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGUpO1xuICAgICAgcmV0dXJuIChjaCA9PT0gJ1xcXFwnIHx8IGNoID09PSAnLScgfHwgY2ggPT09ICddJyB8fCBjaCA9PT0gJ14nKVxuICAgICAgICAgID8gXCJcXFxcXCIgKyBjaCA6IGNoO1xuICAgIH1cbiAgXG4gICAgZnVuY3Rpb24gY2FzZUZvbGRDaGFyc2V0KGNoYXJTZXQpIHtcbiAgICAgIHZhciBjaGFyc2V0UGFydHMgPSBjaGFyU2V0LnN1YnN0cmluZygxLCBjaGFyU2V0Lmxlbmd0aCAtIDEpLm1hdGNoKFxuICAgICAgICAgIG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgICdcXFxcXFxcXHVbMC05QS1GYS1mXXs0fSdcbiAgICAgICAgICAgICAgKyAnfFxcXFxcXFxceFswLTlBLUZhLWZdezJ9J1xuICAgICAgICAgICAgICArICd8XFxcXFxcXFxbMC0zXVswLTddezAsMn0nXG4gICAgICAgICAgICAgICsgJ3xcXFxcXFxcXFswLTddezEsMn0nXG4gICAgICAgICAgICAgICsgJ3xcXFxcXFxcXFtcXFxcc1xcXFxTXSdcbiAgICAgICAgICAgICAgKyAnfC0nXG4gICAgICAgICAgICAgICsgJ3xbXi1cXFxcXFxcXF0nLFxuICAgICAgICAgICAgICAnZycpKTtcbiAgICAgIHZhciByYW5nZXMgPSBbXTtcbiAgICAgIHZhciBpbnZlcnNlID0gY2hhcnNldFBhcnRzWzBdID09PSAnXic7XG4gIFxuICAgICAgdmFyIG91dCA9IFsnWyddO1xuICAgICAgaWYgKGludmVyc2UpIHsgb3V0LnB1c2goJ14nKTsgfVxuICBcbiAgICAgIGZvciAodmFyIGkgPSBpbnZlcnNlID8gMSA6IDAsIG4gPSBjaGFyc2V0UGFydHMubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIHZhciBwID0gY2hhcnNldFBhcnRzW2ldO1xuICAgICAgICBpZiAoL1xcXFxbYmRzd10vaS50ZXN0KHApKSB7ICAvLyBEb24ndCBtdWNrIHdpdGggbmFtZWQgZ3JvdXBzLlxuICAgICAgICAgIG91dC5wdXNoKHApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBzdGFydCA9IGRlY29kZUVzY2FwZShwKTtcbiAgICAgICAgICB2YXIgZW5kO1xuICAgICAgICAgIGlmIChpICsgMiA8IG4gJiYgJy0nID09PSBjaGFyc2V0UGFydHNbaSArIDFdKSB7XG4gICAgICAgICAgICBlbmQgPSBkZWNvZGVFc2NhcGUoY2hhcnNldFBhcnRzW2kgKyAyXSk7XG4gICAgICAgICAgICBpICs9IDI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVuZCA9IHN0YXJ0O1xuICAgICAgICAgIH1cbiAgICAgICAgICByYW5nZXMucHVzaChbc3RhcnQsIGVuZF0pO1xuICAgICAgICAgIC8vIElmIHRoZSByYW5nZSBtaWdodCBpbnRlcnNlY3QgbGV0dGVycywgdGhlbiBleHBhbmQgaXQuXG4gICAgICAgICAgLy8gVGhpcyBjYXNlIGhhbmRsaW5nIGlzIHRvbyBzaW1wbGlzdGljLlxuICAgICAgICAgIC8vIEl0IGRvZXMgbm90IGRlYWwgd2l0aCBub24tbGF0aW4gY2FzZSBmb2xkaW5nLlxuICAgICAgICAgIC8vIEl0IHdvcmtzIGZvciBsYXRpbiBzb3VyY2UgY29kZSBpZGVudGlmaWVycyB0aG91Z2guXG4gICAgICAgICAgaWYgKCEoZW5kIDwgNjUgfHwgc3RhcnQgPiAxMjIpKSB7XG4gICAgICAgICAgICBpZiAoIShlbmQgPCA2NSB8fCBzdGFydCA+IDkwKSkge1xuICAgICAgICAgICAgICByYW5nZXMucHVzaChbTWF0aC5tYXgoNjUsIHN0YXJ0KSB8IDMyLCBNYXRoLm1pbihlbmQsIDkwKSB8IDMyXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShlbmQgPCA5NyB8fCBzdGFydCA+IDEyMikpIHtcbiAgICAgICAgICAgICAgcmFuZ2VzLnB1c2goW01hdGgubWF4KDk3LCBzdGFydCkgJiB+MzIsIE1hdGgubWluKGVuZCwgMTIyKSAmIH4zMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICBcbiAgICAgIC8vIFtbMSwgMTBdLCBbMywgNF0sIFs4LCAxMl0sIFsxNCwgMTRdLCBbMTYsIDE2XSwgWzE3LCAxN11dXG4gICAgICAvLyAtPiBbWzEsIDEyXSwgWzE0LCAxNF0sIFsxNiwgMTddXVxuICAgICAgcmFuZ2VzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIChhWzBdIC0gYlswXSkgfHwgKGJbMV0gIC0gYVsxXSk7IH0pO1xuICAgICAgdmFyIGNvbnNvbGlkYXRlZFJhbmdlcyA9IFtdO1xuICAgICAgdmFyIGxhc3RSYW5nZSA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIHJhbmdlID0gcmFuZ2VzW2ldO1xuICAgICAgICBpZiAocmFuZ2VbMF0gPD0gbGFzdFJhbmdlWzFdICsgMSkge1xuICAgICAgICAgIGxhc3RSYW5nZVsxXSA9IE1hdGgubWF4KGxhc3RSYW5nZVsxXSwgcmFuZ2VbMV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGlkYXRlZFJhbmdlcy5wdXNoKGxhc3RSYW5nZSA9IHJhbmdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICBcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29uc29saWRhdGVkUmFuZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciByYW5nZSA9IGNvbnNvbGlkYXRlZFJhbmdlc1tpXTtcbiAgICAgICAgb3V0LnB1c2goZW5jb2RlRXNjYXBlKHJhbmdlWzBdKSk7XG4gICAgICAgIGlmIChyYW5nZVsxXSA+IHJhbmdlWzBdKSB7XG4gICAgICAgICAgaWYgKHJhbmdlWzFdICsgMSA+IHJhbmdlWzBdKSB7IG91dC5wdXNoKCctJyk7IH1cbiAgICAgICAgICBvdXQucHVzaChlbmNvZGVFc2NhcGUocmFuZ2VbMV0pKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgb3V0LnB1c2goJ10nKTtcbiAgICAgIHJldHVybiBvdXQuam9pbignJyk7XG4gICAgfVxuICBcbiAgICBmdW5jdGlvbiBhbGxvd0FueXdoZXJlRm9sZENhc2VBbmRSZW51bWJlckdyb3VwcyhyZWdleCkge1xuICAgICAgLy8gU3BsaXQgaW50byBjaGFyYWN0ZXIgc2V0cywgZXNjYXBlIHNlcXVlbmNlcywgcHVuY3R1YXRpb24gc3RyaW5nc1xuICAgICAgLy8gbGlrZSAoJygnLCAnKD86JywgJyknLCAnXicpLCBhbmQgcnVucyBvZiBjaGFyYWN0ZXJzIHRoYXQgZG8gbm90XG4gICAgICAvLyBpbmNsdWRlIGFueSBvZiB0aGUgYWJvdmUuXG4gICAgICB2YXIgcGFydHMgPSByZWdleC5zb3VyY2UubWF0Y2goXG4gICAgICAgICAgbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgJyg/OidcbiAgICAgICAgICAgICAgKyAnXFxcXFsoPzpbXlxcXFx4NUNcXFxceDVEXXxcXFxcXFxcXFtcXFxcc1xcXFxTXSkqXFxcXF0nICAvLyBhIGNoYXJhY3RlciBzZXRcbiAgICAgICAgICAgICAgKyAnfFxcXFxcXFxcdVtBLUZhLWYwLTldezR9JyAgLy8gYSB1bmljb2RlIGVzY2FwZVxuICAgICAgICAgICAgICArICd8XFxcXFxcXFx4W0EtRmEtZjAtOV17Mn0nICAvLyBhIGhleCBlc2NhcGVcbiAgICAgICAgICAgICAgKyAnfFxcXFxcXFxcWzAtOV0rJyAgLy8gYSBiYWNrLXJlZmVyZW5jZSBvciBvY3RhbCBlc2NhcGVcbiAgICAgICAgICAgICAgKyAnfFxcXFxcXFxcW151eDAtOV0nICAvLyBvdGhlciBlc2NhcGUgc2VxdWVuY2VcbiAgICAgICAgICAgICAgKyAnfFxcXFwoXFxcXD9bOiE9XScgIC8vIHN0YXJ0IG9mIGEgbm9uLWNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICArICd8W1xcXFwoXFxcXClcXFxcXl0nICAvLyBzdGFydC9lbmQgb2YgYSBncm91cCwgb3IgbGluZSBzdGFydFxuICAgICAgICAgICAgICArICd8W15cXFxceDVCXFxcXHg1Q1xcXFwoXFxcXClcXFxcXl0rJyAgLy8gcnVuIG9mIG90aGVyIGNoYXJhY3RlcnNcbiAgICAgICAgICAgICAgKyAnKScsXG4gICAgICAgICAgICAgICdnJykpO1xuICAgICAgdmFyIG4gPSBwYXJ0cy5sZW5ndGg7XG4gIFxuICAgICAgLy8gTWFwcyBjYXB0dXJlZCBncm91cCBudW1iZXJzIHRvIHRoZSBudW1iZXIgdGhleSB3aWxsIG9jY3VweSBpblxuICAgICAgLy8gdGhlIG91dHB1dCBvciB0byAtMSBpZiB0aGF0IGhhcyBub3QgYmVlbiBkZXRlcm1pbmVkLCBvciB0b1xuICAgICAgLy8gdW5kZWZpbmVkIGlmIHRoZXkgbmVlZCBub3QgYmUgY2FwdHVyaW5nIGluIHRoZSBvdXRwdXQuXG4gICAgICB2YXIgY2FwdHVyZWRHcm91cHMgPSBbXTtcbiAgXG4gICAgICAvLyBXYWxrIG92ZXIgYW5kIGlkZW50aWZ5IGJhY2sgcmVmZXJlbmNlcyB0byBidWlsZCB0aGUgY2FwdHVyZWRHcm91cHNcbiAgICAgIC8vIG1hcHBpbmcuXG4gICAgICBmb3IgKHZhciBpID0gMCwgZ3JvdXBJbmRleCA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgdmFyIHAgPSBwYXJ0c1tpXTtcbiAgICAgICAgaWYgKHAgPT09ICcoJykge1xuICAgICAgICAgIC8vIGdyb3VwcyBhcmUgMS1pbmRleGVkLCBzbyBtYXggZ3JvdXAgaW5kZXggaXMgY291bnQgb2YgJygnXG4gICAgICAgICAgKytncm91cEluZGV4O1xuICAgICAgICB9IGVsc2UgaWYgKCdcXFxcJyA9PT0gcC5jaGFyQXQoMCkpIHtcbiAgICAgICAgICB2YXIgZGVjaW1hbFZhbHVlID0gK3Auc3Vic3RyaW5nKDEpO1xuICAgICAgICAgIGlmIChkZWNpbWFsVmFsdWUpIHtcbiAgICAgICAgICAgIGlmIChkZWNpbWFsVmFsdWUgPD0gZ3JvdXBJbmRleCkge1xuICAgICAgICAgICAgICBjYXB0dXJlZEdyb3Vwc1tkZWNpbWFsVmFsdWVdID0gLTE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBSZXBsYWNlIHdpdGggYW4gdW5hbWJpZ3VvdXMgZXNjYXBlIHNlcXVlbmNlIHNvIHRoYXRcbiAgICAgICAgICAgICAgLy8gYW4gb2N0YWwgZXNjYXBlIHNlcXVlbmNlIGRvZXMgbm90IHR1cm4gaW50byBhIGJhY2tyZWZlcmVuY2VcbiAgICAgICAgICAgICAgLy8gdG8gYSBjYXB0dXJpbmcgZ3JvdXAgZnJvbSBhbiBlYXJsaWVyIHJlZ2V4LlxuICAgICAgICAgICAgICBwYXJ0c1tpXSA9IGVuY29kZUVzY2FwZShkZWNpbWFsVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICBcbiAgICAgIC8vIFJlbnVtYmVyIGdyb3VwcyBhbmQgcmVkdWNlIGNhcHR1cmluZyBncm91cHMgdG8gbm9uLWNhcHR1cmluZyBncm91cHNcbiAgICAgIC8vIHdoZXJlIHBvc3NpYmxlLlxuICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBjYXB0dXJlZEdyb3Vwcy5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZiAoLTEgPT09IGNhcHR1cmVkR3JvdXBzW2ldKSB7XG4gICAgICAgICAgY2FwdHVyZWRHcm91cHNbaV0gPSArK2NhcHR1cmVkR3JvdXBJbmRleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZm9yICh2YXIgaSA9IDAsIGdyb3VwSW5kZXggPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIHZhciBwID0gcGFydHNbaV07XG4gICAgICAgIGlmIChwID09PSAnKCcpIHtcbiAgICAgICAgICArK2dyb3VwSW5kZXg7XG4gICAgICAgICAgaWYgKCFjYXB0dXJlZEdyb3Vwc1tncm91cEluZGV4XSkge1xuICAgICAgICAgICAgcGFydHNbaV0gPSAnKD86JztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoJ1xcXFwnID09PSBwLmNoYXJBdCgwKSkge1xuICAgICAgICAgIHZhciBkZWNpbWFsVmFsdWUgPSArcC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgaWYgKGRlY2ltYWxWYWx1ZSAmJiBkZWNpbWFsVmFsdWUgPD0gZ3JvdXBJbmRleCkge1xuICAgICAgICAgICAgcGFydHNbaV0gPSAnXFxcXCcgKyBjYXB0dXJlZEdyb3Vwc1tkZWNpbWFsVmFsdWVdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICBcbiAgICAgIC8vIFJlbW92ZSBhbnkgcHJlZml4IGFuY2hvcnMgc28gdGhhdCB0aGUgb3V0cHV0IHdpbGwgbWF0Y2ggYW55d2hlcmUuXG4gICAgICAvLyBeXiByZWFsbHkgZG9lcyBtZWFuIGFuIGFuY2hvcmVkIG1hdGNoIHRob3VnaC5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIGlmICgnXicgPT09IHBhcnRzW2ldICYmICdeJyAhPT0gcGFydHNbaSArIDFdKSB7IHBhcnRzW2ldID0gJyc7IH1cbiAgICAgIH1cbiAgXG4gICAgICAvLyBFeHBhbmQgbGV0dGVycyB0byBncm91cHMgdG8gaGFuZGxlIG1peGluZyBvZiBjYXNlLXNlbnNpdGl2ZSBhbmRcbiAgICAgIC8vIGNhc2UtaW5zZW5zaXRpdmUgcGF0dGVybnMgaWYgbmVjZXNzYXJ5LlxuICAgICAgaWYgKHJlZ2V4Lmlnbm9yZUNhc2UgJiYgbmVlZFRvRm9sZENhc2UpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICB2YXIgcCA9IHBhcnRzW2ldO1xuICAgICAgICAgIHZhciBjaDAgPSBwLmNoYXJBdCgwKTtcbiAgICAgICAgICBpZiAocC5sZW5ndGggPj0gMiAmJiBjaDAgPT09ICdbJykge1xuICAgICAgICAgICAgcGFydHNbaV0gPSBjYXNlRm9sZENoYXJzZXQocCk7XG4gICAgICAgICAgfSBlbHNlIGlmIChjaDAgIT09ICdcXFxcJykge1xuICAgICAgICAgICAgLy8gVE9ETzogaGFuZGxlIGxldHRlcnMgaW4gbnVtZXJpYyBlc2NhcGVzLlxuICAgICAgICAgICAgcGFydHNbaV0gPSBwLnJlcGxhY2UoXG4gICAgICAgICAgICAgICAgL1thLXpBLVpdL2csXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKGNoKSB7XG4gICAgICAgICAgICAgICAgICB2YXIgY2MgPSBjaC5jaGFyQ29kZUF0KDApO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuICdbJyArIFN0cmluZy5mcm9tQ2hhckNvZGUoY2MgJiB+MzIsIGNjIHwgMzIpICsgJ10nO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICBcbiAgICAgIHJldHVybiBwYXJ0cy5qb2luKCcnKTtcbiAgICB9XG4gIFxuICAgIHZhciByZXdyaXR0ZW4gPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IHJlZ2V4cy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIHZhciByZWdleCA9IHJlZ2V4c1tpXTtcbiAgICAgIGlmIChyZWdleC5nbG9iYWwgfHwgcmVnZXgubXVsdGlsaW5lKSB7IHRocm93IG5ldyBFcnJvcignJyArIHJlZ2V4KTsgfVxuICAgICAgcmV3cml0dGVuLnB1c2goXG4gICAgICAgICAgJyg/OicgKyBhbGxvd0FueXdoZXJlRm9sZENhc2VBbmRSZW51bWJlckdyb3VwcyhyZWdleCkgKyAnKScpO1xuICAgIH1cbiAgXG4gICAgcmV0dXJuIG5ldyBSZWdFeHAocmV3cml0dGVuLmpvaW4oJ3wnKSwgaWdub3JlQ2FzZSA/ICdnaScgOiAnZycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwbGl0IG1hcmt1cCBpbnRvIGEgc3RyaW5nIG9mIHNvdXJjZSBjb2RlIGFuZCBhbiBhcnJheSBtYXBwaW5nIHJhbmdlcyBpblxuICAgKiB0aGF0IHN0cmluZyB0byB0aGUgdGV4dCBub2RlcyBpbiB3aGljaCB0aGV5IGFwcGVhci5cbiAgICpcbiAgICogPHA+XG4gICAqIFRoZSBIVE1MIERPTSBzdHJ1Y3R1cmU6PC9wPlxuICAgKiA8cHJlPlxuICAgKiAoRWxlbWVudCAgIFwicFwiXG4gICAqICAgKEVsZW1lbnQgXCJiXCJcbiAgICogICAgIChUZXh0ICBcInByaW50IFwiKSkgICAgICAgOyAjMVxuICAgKiAgIChUZXh0ICAgIFwiJ0hlbGxvICdcIikgICAgICA7ICMyXG4gICAqICAgKEVsZW1lbnQgXCJiclwiKSAgICAgICAgICAgIDsgIzNcbiAgICogICAoVGV4dCAgICBcIiAgKyAnV29ybGQnO1wiKSkgOyAjNFxuICAgKiA8L3ByZT5cbiAgICogPHA+XG4gICAqIGNvcnJlc3BvbmRzIHRvIHRoZSBIVE1MXG4gICAqIHtAY29kZSA8cD48Yj5wcmludCA8L2I+J0hlbGxvICc8YnI+ICArICdXb3JsZCc7PC9wPn0uPC9wPlxuICAgKlxuICAgKiA8cD5cbiAgICogSXQgd2lsbCBwcm9kdWNlIHRoZSBvdXRwdXQ6PC9wPlxuICAgKiA8cHJlPlxuICAgKiB7XG4gICAqICAgc291cmNlQ29kZTogXCJwcmludCAnSGVsbG8gJ1xcbiAgKyAnV29ybGQnO1wiLFxuICAgKiAgIC8vICAgICAgICAgICAgICAgICAgICAgMSAgICAgICAgICAyXG4gICAqICAgLy8gICAgICAgICAgIDAxMjM0NTY3ODkwMTIzNCA1Njc4OTAxMjM0NTY3XG4gICAqICAgc3BhbnM6IFswLCAjMSwgNiwgIzIsIDE0LCAjMywgMTUsICM0XVxuICAgKiB9XG4gICAqIDwvcHJlPlxuICAgKiA8cD5cbiAgICogd2hlcmUgIzEgaXMgYSByZWZlcmVuY2UgdG8gdGhlIHtAY29kZSBcInByaW50IFwifSB0ZXh0IG5vZGUgYWJvdmUsIGFuZCBzb1xuICAgKiBvbiBmb3IgdGhlIG90aGVyIHRleHQgbm9kZXMuXG4gICAqIDwvcD5cbiAgICpcbiAgICogPHA+XG4gICAqIFRoZSB7QGNvZGV9IHNwYW5zIGFycmF5IGlzIGFuIGFycmF5IG9mIHBhaXJzLiAgRXZlbiBlbGVtZW50cyBhcmUgdGhlIHN0YXJ0XG4gICAqIGluZGljZXMgb2Ygc3Vic3RyaW5ncywgYW5kIG9kZCBlbGVtZW50cyBhcmUgdGhlIHRleHQgbm9kZXMgKG9yIEJSIGVsZW1lbnRzKVxuICAgKiB0aGF0IGNvbnRhaW4gdGhlIHRleHQgZm9yIHRob3NlIHN1YnN0cmluZ3MuXG4gICAqIFN1YnN0cmluZ3MgY29udGludWUgdW50aWwgdGhlIG5leHQgaW5kZXggb3IgdGhlIGVuZCBvZiB0aGUgc291cmNlLlxuICAgKiA8L3A+XG4gICAqXG4gICAqIEBwYXJhbSB7Tm9kZX0gbm9kZSBhbiBIVE1MIERPTSBzdWJ0cmVlIGNvbnRhaW5pbmcgc291cmNlLWNvZGUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNQcmVmb3JtYXR0ZWQgdHJ1ZSBpZiB3aGl0ZS1zcGFjZSBpbiB0ZXh0IG5vZGVzIHNob3VsZFxuICAgKiAgICBiZSBjb25zaWRlcmVkIHNpZ25pZmljYW50LlxuICAgKiBAcmV0dXJuIHtPYmplY3R9IHNvdXJjZSBjb2RlIGFuZCB0aGUgdGV4dCBub2RlcyBpbiB3aGljaCB0aGV5IG9jY3VyLlxuICAgKi9cbiAgZnVuY3Rpb24gZXh0cmFjdFNvdXJjZVNwYW5zKG5vZGUsIGlzUHJlZm9ybWF0dGVkKSB7XG4gICAgdmFyIG5vY29kZSA9IC8oPzpefFxccylub2NvZGUoPzpcXHN8JCkvO1xuICBcbiAgICB2YXIgY2h1bmtzID0gW107XG4gICAgdmFyIGxlbmd0aCA9IDA7XG4gICAgdmFyIHNwYW5zID0gW107XG4gICAgdmFyIGsgPSAwO1xuICBcbiAgICBmdW5jdGlvbiB3YWxrKG5vZGUpIHtcbiAgICAgIHZhciB0eXBlID0gbm9kZS5ub2RlVHlwZTtcbiAgICAgIGlmICh0eXBlID09IDEpIHsgIC8vIEVsZW1lbnRcbiAgICAgICAgaWYgKG5vY29kZS50ZXN0KG5vZGUuY2xhc3NOYW1lKSkgeyByZXR1cm47IH1cbiAgICAgICAgZm9yICh2YXIgY2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7IGNoaWxkOyBjaGlsZCA9IGNoaWxkLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgd2FsayhjaGlsZCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5vZGVOYW1lID0gbm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAoJ2JyJyA9PT0gbm9kZU5hbWUgfHwgJ2xpJyA9PT0gbm9kZU5hbWUpIHtcbiAgICAgICAgICBjaHVua3Nba10gPSAnXFxuJztcbiAgICAgICAgICBzcGFuc1trIDw8IDFdID0gbGVuZ3RoKys7XG4gICAgICAgICAgc3BhbnNbKGsrKyA8PCAxKSB8IDFdID0gbm9kZTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlID09IDMgfHwgdHlwZSA9PSA0KSB7ICAvLyBUZXh0XG4gICAgICAgIHZhciB0ZXh0ID0gbm9kZS5ub2RlVmFsdWU7XG4gICAgICAgIGlmICh0ZXh0Lmxlbmd0aCkge1xuICAgICAgICAgIGlmICghaXNQcmVmb3JtYXR0ZWQpIHtcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1sgXFx0XFxyXFxuXSsvZywgJyAnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxyXFxuPy9nLCAnXFxuJyk7ICAvLyBOb3JtYWxpemUgbmV3bGluZXMuXG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIFRPRE86IGhhbmRsZSB0YWJzIGhlcmU/XG4gICAgICAgICAgY2h1bmtzW2tdID0gdGV4dDtcbiAgICAgICAgICBzcGFuc1trIDw8IDFdID0gbGVuZ3RoO1xuICAgICAgICAgIGxlbmd0aCArPSB0ZXh0Lmxlbmd0aDtcbiAgICAgICAgICBzcGFuc1soaysrIDw8IDEpIHwgMV0gPSBub2RlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICBcbiAgICB3YWxrKG5vZGUpO1xuICBcbiAgICByZXR1cm4ge1xuICAgICAgc291cmNlQ29kZTogY2h1bmtzLmpvaW4oJycpLnJlcGxhY2UoL1xcbiQvLCAnJyksXG4gICAgICBzcGFuczogc3BhbnNcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGx5IHRoZSBnaXZlbiBsYW5ndWFnZSBoYW5kbGVyIHRvIHNvdXJjZUNvZGUgYW5kIGFkZCB0aGUgcmVzdWx0aW5nXG4gICAqIGRlY29yYXRpb25zIHRvIG91dC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGJhc2VQb3MgdGhlIGluZGV4IG9mIHNvdXJjZUNvZGUgd2l0aGluIHRoZSBjaHVuayBvZiBzb3VyY2VcbiAgICogICAgd2hvc2UgZGVjb3JhdGlvbnMgYXJlIGFscmVhZHkgcHJlc2VudCBvbiBvdXQuXG4gICAqL1xuICBmdW5jdGlvbiBhcHBlbmREZWNvcmF0aW9ucyhiYXNlUG9zLCBzb3VyY2VDb2RlLCBsYW5nSGFuZGxlciwgb3V0KSB7XG4gICAgaWYgKCFzb3VyY2VDb2RlKSB7IHJldHVybjsgfVxuICAgIHZhciBqb2IgPSB7XG4gICAgICBzb3VyY2VDb2RlOiBzb3VyY2VDb2RlLFxuICAgICAgYmFzZVBvczogYmFzZVBvc1xuICAgIH07XG4gICAgbGFuZ0hhbmRsZXIoam9iKTtcbiAgICBvdXQucHVzaC5hcHBseShvdXQsIGpvYi5kZWNvcmF0aW9ucyk7XG4gIH1cblxuICB2YXIgbm90V3MgPSAvXFxTLztcblxuICAvKipcbiAgICogR2l2ZW4gYW4gZWxlbWVudCwgaWYgaXQgY29udGFpbnMgb25seSBvbmUgY2hpbGQgZWxlbWVudCBhbmQgYW55IHRleHQgbm9kZXNcbiAgICogaXQgY29udGFpbnMgY29udGFpbiBvbmx5IHNwYWNlIGNoYXJhY3RlcnMsIHJldHVybiB0aGUgc29sZSBjaGlsZCBlbGVtZW50LlxuICAgKiBPdGhlcndpc2UgcmV0dXJucyB1bmRlZmluZWQuXG4gICAqIDxwPlxuICAgKiBUaGlzIGlzIG1lYW50IHRvIHJldHVybiB0aGUgQ09ERSBlbGVtZW50IGluIHtAY29kZSA8cHJlPjxjb2RlIC4uLj59IHdoZW5cbiAgICogdGhlcmUgaXMgYSBzaW5nbGUgY2hpbGQgZWxlbWVudCB0aGF0IGNvbnRhaW5zIGFsbCB0aGUgbm9uLXNwYWNlIHRleHR1YWxcbiAgICogY29udGVudCwgYnV0IG5vdCB0byByZXR1cm4gYW55dGhpbmcgd2hlcmUgdGhlcmUgYXJlIG11bHRpcGxlIGNoaWxkIGVsZW1lbnRzXG4gICAqIGFzIGluIHtAY29kZSA8cHJlPjxjb2RlPi4uLjwvY29kZT48Y29kZT4uLi48L2NvZGU+PC9wcmU+fSBvciB3aGVuIHRoZXJlXG4gICAqIGlzIHRleHR1YWwgY29udGVudC5cbiAgICovXG4gIGZ1bmN0aW9uIGNoaWxkQ29udGVudFdyYXBwZXIoZWxlbWVudCkge1xuICAgIHZhciB3cmFwcGVyID0gdW5kZWZpbmVkO1xuICAgIGZvciAodmFyIGMgPSBlbGVtZW50LmZpcnN0Q2hpbGQ7IGM7IGMgPSBjLm5leHRTaWJsaW5nKSB7XG4gICAgICB2YXIgdHlwZSA9IGMubm9kZVR5cGU7XG4gICAgICB3cmFwcGVyID0gKHR5cGUgPT09IDEpICAvLyBFbGVtZW50IE5vZGVcbiAgICAgICAgICA/ICh3cmFwcGVyID8gZWxlbWVudCA6IGMpXG4gICAgICAgICAgOiAodHlwZSA9PT0gMykgIC8vIFRleHQgTm9kZVxuICAgICAgICAgID8gKG5vdFdzLnRlc3QoYy5ub2RlVmFsdWUpID8gZWxlbWVudCA6IHdyYXBwZXIpXG4gICAgICAgICAgOiB3cmFwcGVyO1xuICAgIH1cbiAgICByZXR1cm4gd3JhcHBlciA9PT0gZWxlbWVudCA/IHVuZGVmaW5lZCA6IHdyYXBwZXI7XG4gIH1cblxuICAvKiogR2l2ZW4gdHJpcGxlcyBvZiBbc3R5bGUsIHBhdHRlcm4sIGNvbnRleHRdIHJldHVybnMgYSBsZXhpbmcgZnVuY3Rpb24sXG4gICAgKiBUaGUgbGV4aW5nIGZ1bmN0aW9uIGludGVycHJldHMgdGhlIHBhdHRlcm5zIHRvIGZpbmQgdG9rZW4gYm91bmRhcmllcyBhbmRcbiAgICAqIHJldHVybnMgYSBkZWNvcmF0aW9uIGxpc3Qgb2YgdGhlIGZvcm1cbiAgICAqIFtpbmRleF8wLCBzdHlsZV8wLCBpbmRleF8xLCBzdHlsZV8xLCAuLi4sIGluZGV4X24sIHN0eWxlX25dXG4gICAgKiB3aGVyZSBpbmRleF9uIGlzIGFuIGluZGV4IGludG8gdGhlIHNvdXJjZUNvZGUsIGFuZCBzdHlsZV9uIGlzIGEgc3R5bGVcbiAgICAqIGNvbnN0YW50IGxpa2UgUFJfUExBSU4uICBpbmRleF9uLTEgPD0gaW5kZXhfbiwgYW5kIHN0eWxlX24tMSBhcHBsaWVzIHRvXG4gICAgKiBhbGwgY2hhcmFjdGVycyBpbiBzb3VyY2VDb2RlW2luZGV4X24tMTppbmRleF9uXS5cbiAgICAqXG4gICAgKiBUaGUgc3R5bGVQYXR0ZXJucyBpcyBhIGxpc3Qgd2hvc2UgZWxlbWVudHMgaGF2ZSB0aGUgZm9ybVxuICAgICogW3N0eWxlIDogc3RyaW5nLCBwYXR0ZXJuIDogUmVnRXhwLCBERVBSRUNBVEVELCBzaG9ydGN1dCA6IHN0cmluZ10uXG4gICAgKlxuICAgICogU3R5bGUgaXMgYSBzdHlsZSBjb25zdGFudCBsaWtlIFBSX1BMQUlOLCBvciBjYW4gYmUgYSBzdHJpbmcgb2YgdGhlXG4gICAgKiBmb3JtICdsYW5nLUZPTycsIHdoZXJlIEZPTyBpcyBhIGxhbmd1YWdlIGV4dGVuc2lvbiBkZXNjcmliaW5nIHRoZVxuICAgICogbGFuZ3VhZ2Ugb2YgdGhlIHBvcnRpb24gb2YgdGhlIHRva2VuIGluICQxIGFmdGVyIHBhdHRlcm4gZXhlY3V0ZXMuXG4gICAgKiBFLmcuLCBpZiBzdHlsZSBpcyAnbGFuZy1saXNwJywgYW5kIGdyb3VwIDEgY29udGFpbnMgdGhlIHRleHRcbiAgICAqICcoaGVsbG8gKHdvcmxkKSknLCB0aGVuIHRoYXQgcG9ydGlvbiBvZiB0aGUgdG9rZW4gd2lsbCBiZSBwYXNzZWQgdG8gdGhlXG4gICAgKiByZWdpc3RlcmVkIGxpc3AgaGFuZGxlciBmb3IgZm9ybWF0dGluZy5cbiAgICAqIFRoZSB0ZXh0IGJlZm9yZSBhbmQgYWZ0ZXIgZ3JvdXAgMSB3aWxsIGJlIHJlc3R5bGVkIHVzaW5nIHRoaXMgZGVjb3JhdG9yXG4gICAgKiBzbyBkZWNvcmF0b3JzIHNob3VsZCB0YWtlIGNhcmUgdGhhdCB0aGlzIGRvZXNuJ3QgcmVzdWx0IGluIGluZmluaXRlXG4gICAgKiByZWN1cnNpb24uICBGb3IgZXhhbXBsZSwgdGhlIEhUTUwgbGV4ZXIgcnVsZSBmb3IgU0NSSVBUIGVsZW1lbnRzIGxvb2tzXG4gICAgKiBzb21ldGhpbmcgbGlrZSBbJ2xhbmctanMnLCAvPFtzXWNyaXB0PiguKz8pPFxcL3NjcmlwdD4vXS4gIFRoaXMgbWF5IG1hdGNoXG4gICAgKiAnPHNjcmlwdD5mb28oKTxcXC9zY3JpcHQ+Jywgd2hpY2ggd291bGQgY2F1c2UgdGhlIGN1cnJlbnQgZGVjb3JhdG9yIHRvXG4gICAgKiBiZSBjYWxsZWQgd2l0aCAnPHNjcmlwdD4nIHdoaWNoIHdvdWxkIG5vdCBtYXRjaCB0aGUgc2FtZSBydWxlIHNpbmNlXG4gICAgKiBncm91cCAxIG11c3Qgbm90IGJlIGVtcHR5LCBzbyBpdCB3b3VsZCBiZSBpbnN0ZWFkIHN0eWxlZCBhcyBQUl9UQUcgYnlcbiAgICAqIHRoZSBnZW5lcmljIHRhZyBydWxlLiAgVGhlIGhhbmRsZXIgcmVnaXN0ZXJlZCBmb3IgdGhlICdqcycgZXh0ZW5zaW9uIHdvdWxkXG4gICAgKiB0aGVuIGJlIGNhbGxlZCB3aXRoICdmb28oKScsIGFuZCBmaW5hbGx5LCB0aGUgY3VycmVudCBkZWNvcmF0b3Igd291bGRcbiAgICAqIGJlIGNhbGxlZCB3aXRoICc8XFwvc2NyaXB0Picgd2hpY2ggd291bGQgbm90IG1hdGNoIHRoZSBvcmlnaW5hbCBydWxlIGFuZFxuICAgICogc28gdGhlIGdlbmVyaWMgdGFnIHJ1bGUgd291bGQgaWRlbnRpZnkgaXQgYXMgYSB0YWcuXG4gICAgKlxuICAgICogUGF0dGVybiBtdXN0IG9ubHkgbWF0Y2ggcHJlZml4ZXMsIGFuZCBpZiBpdCBtYXRjaGVzIGEgcHJlZml4LCB0aGVuIHRoYXRcbiAgICAqIG1hdGNoIGlzIGNvbnNpZGVyZWQgYSB0b2tlbiB3aXRoIHRoZSBzYW1lIHN0eWxlLlxuICAgICpcbiAgICAqIENvbnRleHQgaXMgYXBwbGllZCB0byB0aGUgbGFzdCBub24td2hpdGVzcGFjZSwgbm9uLWNvbW1lbnQgdG9rZW5cbiAgICAqIHJlY29nbml6ZWQuXG4gICAgKlxuICAgICogU2hvcnRjdXQgaXMgYW4gb3B0aW9uYWwgc3RyaW5nIG9mIGNoYXJhY3RlcnMsIGFueSBvZiB3aGljaCwgaWYgdGhlIGZpcnN0XG4gICAgKiBjaGFyYWN0ZXIsIGd1cmFudGVlIHRoYXQgdGhpcyBwYXR0ZXJuIGFuZCBvbmx5IHRoaXMgcGF0dGVybiBtYXRjaGVzLlxuICAgICpcbiAgICAqIEBwYXJhbSB7QXJyYXl9IHNob3J0Y3V0U3R5bGVQYXR0ZXJucyBwYXR0ZXJucyB0aGF0IGFsd2F5cyBzdGFydCB3aXRoXG4gICAgKiAgIGEga25vd24gY2hhcmFjdGVyLiAgTXVzdCBoYXZlIGEgc2hvcnRjdXQgc3RyaW5nLlxuICAgICogQHBhcmFtIHtBcnJheX0gZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zIHBhdHRlcm5zIHRoYXQgd2lsbCBiZSB0cmllZCBpblxuICAgICogICBvcmRlciBpZiB0aGUgc2hvcnRjdXQgb25lcyBmYWlsLiAgTWF5IGhhdmUgc2hvcnRjdXRzLlxuICAgICpcbiAgICAqIEByZXR1cm4ge2Z1bmN0aW9uIChPYmplY3QpfSBhXG4gICAgKiAgIGZ1bmN0aW9uIHRoYXQgdGFrZXMgc291cmNlIGNvZGUgYW5kIHJldHVybnMgYSBsaXN0IG9mIGRlY29yYXRpb25zLlxuICAgICovXG4gIGZ1bmN0aW9uIGNyZWF0ZVNpbXBsZUxleGVyKHNob3J0Y3V0U3R5bGVQYXR0ZXJucywgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zKSB7XG4gICAgdmFyIHNob3J0Y3V0cyA9IHt9O1xuICAgIHZhciB0b2tlbml6ZXI7XG4gICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBhbGxQYXR0ZXJucyA9IHNob3J0Y3V0U3R5bGVQYXR0ZXJucy5jb25jYXQoZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zKTtcbiAgICAgIHZhciBhbGxSZWdleHMgPSBbXTtcbiAgICAgIHZhciByZWdleEtleXMgPSB7fTtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gYWxsUGF0dGVybnMubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuUGFydHMgPSBhbGxQYXR0ZXJuc1tpXTtcbiAgICAgICAgdmFyIHNob3J0Y3V0Q2hhcnMgPSBwYXR0ZXJuUGFydHNbM107XG4gICAgICAgIGlmIChzaG9ydGN1dENoYXJzKSB7XG4gICAgICAgICAgZm9yICh2YXIgYyA9IHNob3J0Y3V0Q2hhcnMubGVuZ3RoOyAtLWMgPj0gMDspIHtcbiAgICAgICAgICAgIHNob3J0Y3V0c1tzaG9ydGN1dENoYXJzLmNoYXJBdChjKV0gPSBwYXR0ZXJuUGFydHM7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciByZWdleCA9IHBhdHRlcm5QYXJ0c1sxXTtcbiAgICAgICAgdmFyIGsgPSAnJyArIHJlZ2V4O1xuICAgICAgICBpZiAoIXJlZ2V4S2V5cy5oYXNPd25Qcm9wZXJ0eShrKSkge1xuICAgICAgICAgIGFsbFJlZ2V4cy5wdXNoKHJlZ2V4KTtcbiAgICAgICAgICByZWdleEtleXNba10gPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBhbGxSZWdleHMucHVzaCgvW1xcMC1cXHVmZmZmXS8pO1xuICAgICAgdG9rZW5pemVyID0gY29tYmluZVByZWZpeFBhdHRlcm5zKGFsbFJlZ2V4cyk7XG4gICAgfSkoKTtcblxuICAgIHZhciBuUGF0dGVybnMgPSBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMubGVuZ3RoO1xuXG4gICAgLyoqXG4gICAgICogTGV4ZXMgam9iLnNvdXJjZUNvZGUgYW5kIHByb2R1Y2VzIGFuIG91dHB1dCBhcnJheSBqb2IuZGVjb3JhdGlvbnMgb2ZcbiAgICAgKiBzdHlsZSBjbGFzc2VzIHByZWNlZGVkIGJ5IHRoZSBwb3NpdGlvbiBhdCB3aGljaCB0aGV5IHN0YXJ0IGluXG4gICAgICogam9iLnNvdXJjZUNvZGUgaW4gb3JkZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gam9iIGFuIG9iamVjdCBsaWtlIDxwcmU+e1xuICAgICAqICAgIHNvdXJjZUNvZGU6IHtzdHJpbmd9IHNvdXJjZVRleHQgcGxhaW4gdGV4dCxcbiAgICAgKiAgICBiYXNlUG9zOiB7aW50fSBwb3NpdGlvbiBvZiBqb2Iuc291cmNlQ29kZSBpbiB0aGUgbGFyZ2VyIGNodW5rIG9mXG4gICAgICogICAgICAgIHNvdXJjZUNvZGUuXG4gICAgICogfTwvcHJlPlxuICAgICAqL1xuICAgIHZhciBkZWNvcmF0ZSA9IGZ1bmN0aW9uIChqb2IpIHtcbiAgICAgIHZhciBzb3VyY2VDb2RlID0gam9iLnNvdXJjZUNvZGUsIGJhc2VQb3MgPSBqb2IuYmFzZVBvcztcbiAgICAgIC8qKiBFdmVuIGVudHJpZXMgYXJlIHBvc2l0aW9ucyBpbiBzb3VyY2UgaW4gYXNjZW5kaW5nIG9yZGVyLiAgT2RkIGVudGllc1xuICAgICAgICAqIGFyZSBzdHlsZSBtYXJrZXJzIChlLmcuLCBQUl9DT01NRU5UKSB0aGF0IHJ1biBmcm9tIHRoYXQgcG9zaXRpb24gdW50aWxcbiAgICAgICAgKiB0aGUgZW5kLlxuICAgICAgICAqIEB0eXBlIHtBcnJheS48bnVtYmVyfHN0cmluZz59XG4gICAgICAgICovXG4gICAgICB2YXIgZGVjb3JhdGlvbnMgPSBbYmFzZVBvcywgUFJfUExBSU5dO1xuICAgICAgdmFyIHBvcyA9IDA7ICAvLyBpbmRleCBpbnRvIHNvdXJjZUNvZGVcbiAgICAgIHZhciB0b2tlbnMgPSBzb3VyY2VDb2RlLm1hdGNoKHRva2VuaXplcikgfHwgW107XG4gICAgICB2YXIgc3R5bGVDYWNoZSA9IHt9O1xuXG4gICAgICBmb3IgKHZhciB0aSA9IDAsIG5Ub2tlbnMgPSB0b2tlbnMubGVuZ3RoOyB0aSA8IG5Ub2tlbnM7ICsrdGkpIHtcbiAgICAgICAgdmFyIHRva2VuID0gdG9rZW5zW3RpXTtcbiAgICAgICAgdmFyIHN0eWxlID0gc3R5bGVDYWNoZVt0b2tlbl07XG4gICAgICAgIHZhciBtYXRjaCA9IHZvaWQgMDtcblxuICAgICAgICB2YXIgaXNFbWJlZGRlZDtcbiAgICAgICAgaWYgKHR5cGVvZiBzdHlsZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpc0VtYmVkZGVkID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHBhdHRlcm5QYXJ0cyA9IHNob3J0Y3V0c1t0b2tlbi5jaGFyQXQoMCldO1xuICAgICAgICAgIGlmIChwYXR0ZXJuUGFydHMpIHtcbiAgICAgICAgICAgIG1hdGNoID0gdG9rZW4ubWF0Y2gocGF0dGVyblBhcnRzWzFdKTtcbiAgICAgICAgICAgIHN0eWxlID0gcGF0dGVyblBhcnRzWzBdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5QYXR0ZXJuczsgKytpKSB7XG4gICAgICAgICAgICAgIHBhdHRlcm5QYXJ0cyA9IGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJuc1tpXTtcbiAgICAgICAgICAgICAgbWF0Y2ggPSB0b2tlbi5tYXRjaChwYXR0ZXJuUGFydHNbMV0pO1xuICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICBzdHlsZSA9IHBhdHRlcm5QYXJ0c1swXTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIW1hdGNoKSB7ICAvLyBtYWtlIHN1cmUgdGhhdCB3ZSBtYWtlIHByb2dyZXNzXG4gICAgICAgICAgICAgIHN0eWxlID0gUFJfUExBSU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaXNFbWJlZGRlZCA9IHN0eWxlLmxlbmd0aCA+PSA1ICYmICdsYW5nLScgPT09IHN0eWxlLnN1YnN0cmluZygwLCA1KTtcbiAgICAgICAgICBpZiAoaXNFbWJlZGRlZCAmJiAhKG1hdGNoICYmIHR5cGVvZiBtYXRjaFsxXSA9PT0gJ3N0cmluZycpKSB7XG4gICAgICAgICAgICBpc0VtYmVkZGVkID0gZmFsc2U7XG4gICAgICAgICAgICBzdHlsZSA9IFBSX1NPVVJDRTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWlzRW1iZWRkZWQpIHsgc3R5bGVDYWNoZVt0b2tlbl0gPSBzdHlsZTsgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRva2VuU3RhcnQgPSBwb3M7XG4gICAgICAgIHBvcyArPSB0b2tlbi5sZW5ndGg7XG5cbiAgICAgICAgaWYgKCFpc0VtYmVkZGVkKSB7XG4gICAgICAgICAgZGVjb3JhdGlvbnMucHVzaChiYXNlUG9zICsgdG9rZW5TdGFydCwgc3R5bGUpO1xuICAgICAgICB9IGVsc2UgeyAgLy8gVHJlYXQgZ3JvdXAgMSBhcyBhbiBlbWJlZGRlZCBibG9jayBvZiBzb3VyY2UgY29kZS5cbiAgICAgICAgICB2YXIgZW1iZWRkZWRTb3VyY2UgPSBtYXRjaFsxXTtcbiAgICAgICAgICB2YXIgZW1iZWRkZWRTb3VyY2VTdGFydCA9IHRva2VuLmluZGV4T2YoZW1iZWRkZWRTb3VyY2UpO1xuICAgICAgICAgIHZhciBlbWJlZGRlZFNvdXJjZUVuZCA9IGVtYmVkZGVkU291cmNlU3RhcnQgKyBlbWJlZGRlZFNvdXJjZS5sZW5ndGg7XG4gICAgICAgICAgaWYgKG1hdGNoWzJdKSB7XG4gICAgICAgICAgICAvLyBJZiBlbWJlZGRlZFNvdXJjZSBjYW4gYmUgYmxhbmssIHRoZW4gaXQgd291bGQgbWF0Y2ggYXQgdGhlXG4gICAgICAgICAgICAvLyBiZWdpbm5pbmcgd2hpY2ggd291bGQgY2F1c2UgdXMgdG8gaW5maW5pdGVseSByZWN1cnNlIG9uIHRoZVxuICAgICAgICAgICAgLy8gZW50aXJlIHRva2VuLCBzbyB3ZSBjYXRjaCB0aGUgcmlnaHQgY29udGV4dCBpbiBtYXRjaFsyXS5cbiAgICAgICAgICAgIGVtYmVkZGVkU291cmNlRW5kID0gdG9rZW4ubGVuZ3RoIC0gbWF0Y2hbMl0ubGVuZ3RoO1xuICAgICAgICAgICAgZW1iZWRkZWRTb3VyY2VTdGFydCA9IGVtYmVkZGVkU291cmNlRW5kIC0gZW1iZWRkZWRTb3VyY2UubGVuZ3RoO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgbGFuZyA9IHN0eWxlLnN1YnN0cmluZyg1KTtcbiAgICAgICAgICAvLyBEZWNvcmF0ZSB0aGUgbGVmdCBvZiB0aGUgZW1iZWRkZWQgc291cmNlXG4gICAgICAgICAgYXBwZW5kRGVjb3JhdGlvbnMoXG4gICAgICAgICAgICAgIGJhc2VQb3MgKyB0b2tlblN0YXJ0LFxuICAgICAgICAgICAgICB0b2tlbi5zdWJzdHJpbmcoMCwgZW1iZWRkZWRTb3VyY2VTdGFydCksXG4gICAgICAgICAgICAgIGRlY29yYXRlLCBkZWNvcmF0aW9ucyk7XG4gICAgICAgICAgLy8gRGVjb3JhdGUgdGhlIGVtYmVkZGVkIHNvdXJjZVxuICAgICAgICAgIGFwcGVuZERlY29yYXRpb25zKFxuICAgICAgICAgICAgICBiYXNlUG9zICsgdG9rZW5TdGFydCArIGVtYmVkZGVkU291cmNlU3RhcnQsXG4gICAgICAgICAgICAgIGVtYmVkZGVkU291cmNlLFxuICAgICAgICAgICAgICBsYW5nSGFuZGxlckZvckV4dGVuc2lvbihsYW5nLCBlbWJlZGRlZFNvdXJjZSksXG4gICAgICAgICAgICAgIGRlY29yYXRpb25zKTtcbiAgICAgICAgICAvLyBEZWNvcmF0ZSB0aGUgcmlnaHQgb2YgdGhlIGVtYmVkZGVkIHNlY3Rpb25cbiAgICAgICAgICBhcHBlbmREZWNvcmF0aW9ucyhcbiAgICAgICAgICAgICAgYmFzZVBvcyArIHRva2VuU3RhcnQgKyBlbWJlZGRlZFNvdXJjZUVuZCxcbiAgICAgICAgICAgICAgdG9rZW4uc3Vic3RyaW5nKGVtYmVkZGVkU291cmNlRW5kKSxcbiAgICAgICAgICAgICAgZGVjb3JhdGUsIGRlY29yYXRpb25zKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgam9iLmRlY29yYXRpb25zID0gZGVjb3JhdGlvbnM7XG4gICAgfTtcbiAgICByZXR1cm4gZGVjb3JhdGU7XG4gIH1cblxuICAvKiogcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYSBsaXN0IG9mIGRlY29yYXRpb25zIGZyb20gc291cmNlIHRleHQuXG4gICAgKlxuICAgICogVGhpcyBjb2RlIHRyZWF0cyBcIiwgJywgYW5kIGAgYXMgc3RyaW5nIGRlbGltaXRlcnMsIGFuZCBcXCBhcyBhIHN0cmluZ1xuICAgICogZXNjYXBlLiAgSXQgZG9lcyBub3QgcmVjb2duaXplIHBlcmwncyBxcSgpIHN0eWxlIHN0cmluZ3MuXG4gICAgKiBJdCBoYXMgbm8gc3BlY2lhbCBoYW5kbGluZyBmb3IgZG91YmxlIGRlbGltaXRlciBlc2NhcGVzIGFzIGluIGJhc2ljLCBvclxuICAgICogdGhlIHRyaXBsZWQgZGVsaW1pdGVycyB1c2VkIGluIHB5dGhvbiwgYnV0IHNob3VsZCB3b3JrIG9uIHRob3NlIHJlZ2FyZGxlc3NcbiAgICAqIGFsdGhvdWdoIGluIHRob3NlIGNhc2VzIGEgc2luZ2xlIHN0cmluZyBsaXRlcmFsIG1heSBiZSBicm9rZW4gdXAgaW50b1xuICAgICogbXVsdGlwbGUgYWRqYWNlbnQgc3RyaW5nIGxpdGVyYWxzLlxuICAgICpcbiAgICAqIEl0IHJlY29nbml6ZXMgQywgQysrLCBhbmQgc2hlbGwgc3R5bGUgY29tbWVudHMuXG4gICAgKlxuICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgYSBzZXQgb2Ygb3B0aW9uYWwgcGFyYW1ldGVycy5cbiAgICAqIEByZXR1cm4ge2Z1bmN0aW9uIChPYmplY3QpfSBhIGZ1bmN0aW9uIHRoYXQgZXhhbWluZXMgdGhlIHNvdXJjZSBjb2RlXG4gICAgKiAgICAgaW4gdGhlIGlucHV0IGpvYiBhbmQgYnVpbGRzIHRoZSBkZWNvcmF0aW9uIGxpc3QuXG4gICAgKi9cbiAgZnVuY3Rpb24gc291cmNlRGVjb3JhdG9yKG9wdGlvbnMpIHtcbiAgICB2YXIgc2hvcnRjdXRTdHlsZVBhdHRlcm5zID0gW10sIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucyA9IFtdO1xuICAgIGlmIChvcHRpb25zWyd0cmlwbGVRdW90ZWRTdHJpbmdzJ10pIHtcbiAgICAgIC8vICcnJ211bHRpLWxpbmUtc3RyaW5nJycnLCAnc2luZ2xlLWxpbmUtc3RyaW5nJywgYW5kIGRvdWJsZS1xdW90ZWRcbiAgICAgIHNob3J0Y3V0U3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIFtQUl9TVFJJTkcsICAvXig/OlxcJ1xcJ1xcJyg/OlteXFwnXFxcXF18XFxcXFtcXHNcXFNdfFxcJ3sxLDJ9KD89W15cXCddKSkqKD86XFwnXFwnXFwnfCQpfFxcXCJcXFwiXFxcIig/OlteXFxcIlxcXFxdfFxcXFxbXFxzXFxTXXxcXFwiezEsMn0oPz1bXlxcXCJdKSkqKD86XFxcIlxcXCJcXFwifCQpfFxcJyg/OlteXFxcXFxcJ118XFxcXFtcXHNcXFNdKSooPzpcXCd8JCl8XFxcIig/OlteXFxcXFxcXCJdfFxcXFxbXFxzXFxTXSkqKD86XFxcInwkKSkvLFxuICAgICAgICAgICBudWxsLCAnXFwnXCInXSk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zWydtdWx0aUxpbmVTdHJpbmdzJ10pIHtcbiAgICAgIC8vICdtdWx0aS1saW5lLXN0cmluZycsIFwibXVsdGktbGluZS1zdHJpbmdcIlxuICAgICAgc2hvcnRjdXRTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgW1BSX1NUUklORywgIC9eKD86XFwnKD86W15cXFxcXFwnXXxcXFxcW1xcc1xcU10pKig/OlxcJ3wkKXxcXFwiKD86W15cXFxcXFxcIl18XFxcXFtcXHNcXFNdKSooPzpcXFwifCQpfFxcYCg/OlteXFxcXFxcYF18XFxcXFtcXHNcXFNdKSooPzpcXGB8JCkpLyxcbiAgICAgICAgICAgbnVsbCwgJ1xcJ1wiYCddKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gJ3NpbmdsZS1saW5lLXN0cmluZycsIFwic2luZ2xlLWxpbmUtc3RyaW5nXCJcbiAgICAgIHNob3J0Y3V0U3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIFtQUl9TVFJJTkcsXG4gICAgICAgICAgIC9eKD86XFwnKD86W15cXFxcXFwnXFxyXFxuXXxcXFxcLikqKD86XFwnfCQpfFxcXCIoPzpbXlxcXFxcXFwiXFxyXFxuXXxcXFxcLikqKD86XFxcInwkKSkvLFxuICAgICAgICAgICBudWxsLCAnXCJcXCcnXSk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zWyd2ZXJiYXRpbVN0cmluZ3MnXSkge1xuICAgICAgLy8gdmVyYmF0aW0tc3RyaW5nLWxpdGVyYWwgcHJvZHVjdGlvbiBmcm9tIHRoZSBDIyBncmFtbWFyLiAgU2VlIGlzc3VlIDkzLlxuICAgICAgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgW1BSX1NUUklORywgL15AXFxcIig/OlteXFxcIl18XFxcIlxcXCIpKig/OlxcXCJ8JCkvLCBudWxsXSk7XG4gICAgfVxuICAgIHZhciBoYyA9IG9wdGlvbnNbJ2hhc2hDb21tZW50cyddO1xuICAgIGlmIChoYykge1xuICAgICAgaWYgKG9wdGlvbnNbJ2NTdHlsZUNvbW1lbnRzJ10pIHtcbiAgICAgICAgaWYgKGhjID4gMSkgeyAgLy8gbXVsdGlsaW5lIGhhc2ggY29tbWVudHNcbiAgICAgICAgICBzaG9ydGN1dFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICAgICAgW1BSX0NPTU1FTlQsIC9eIyg/OiMjKD86W14jXXwjKD8hIyMpKSooPzojIyN8JCl8LiopLywgbnVsbCwgJyMnXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU3RvcCBDIHByZXByb2Nlc3NvciBkZWNsYXJhdGlvbnMgYXQgYW4gdW5jbG9zZWQgb3BlbiBjb21tZW50XG4gICAgICAgICAgc2hvcnRjdXRTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgICAgIFtQUl9DT01NRU5ULCAvXiMoPzooPzpkZWZpbmV8ZSg/Omx8bmQpaWZ8ZWxzZXxlcnJvcnxpZm4/ZGVmfGluY2x1ZGV8bGluZXxwcmFnbWF8dW5kZWZ8d2FybmluZylcXGJ8W15cXHJcXG5dKikvLFxuICAgICAgICAgICAgICAgbnVsbCwgJyMnXSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gI2luY2x1ZGUgPHN0ZGlvLmg+XG4gICAgICAgIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgICAgW1BSX1NUUklORyxcbiAgICAgICAgICAgICAvXjwoPzooPzooPzpcXC5cXC5cXC8pKnxcXC8/KSg/OltcXHctXSsoPzpcXC9bXFx3LV0rKSspP1tcXHctXStcXC5oKD86aHxwcHxcXCtcXCspP3xbYS16XVxcdyopPi8sXG4gICAgICAgICAgICAgbnVsbF0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2hvcnRjdXRTdHlsZVBhdHRlcm5zLnB1c2goW1BSX0NPTU1FTlQsIC9eI1teXFxyXFxuXSovLCBudWxsLCAnIyddKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG9wdGlvbnNbJ2NTdHlsZUNvbW1lbnRzJ10pIHtcbiAgICAgIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5wdXNoKFtQUl9DT01NRU5ULCAvXlxcL1xcL1teXFxyXFxuXSovLCBudWxsXSk7XG4gICAgICBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBbUFJfQ09NTUVOVCwgL15cXC9cXCpbXFxzXFxTXSo/KD86XFwqXFwvfCQpLywgbnVsbF0pO1xuICAgIH1cbiAgICB2YXIgcmVnZXhMaXRlcmFscyA9IG9wdGlvbnNbJ3JlZ2V4TGl0ZXJhbHMnXTtcbiAgICBpZiAocmVnZXhMaXRlcmFscykge1xuICAgICAgLyoqXG4gICAgICAgKiBAY29uc3RcbiAgICAgICAqL1xuICAgICAgdmFyIHJlZ2V4RXhjbHMgPSByZWdleExpdGVyYWxzID4gMVxuICAgICAgICA/ICcnICAvLyBNdWx0aWxpbmUgcmVnZXggbGl0ZXJhbHNcbiAgICAgICAgOiAnXFxuXFxyJztcbiAgICAgIC8qKlxuICAgICAgICogQGNvbnN0XG4gICAgICAgKi9cbiAgICAgIHZhciByZWdleEFueSA9IHJlZ2V4RXhjbHMgPyAnLicgOiAnW1xcXFxTXFxcXHNdJztcbiAgICAgIC8qKlxuICAgICAgICogQGNvbnN0XG4gICAgICAgKi9cbiAgICAgIHZhciBSRUdFWF9MSVRFUkFMID0gKFxuICAgICAgICAgIC8vIEEgcmVndWxhciBleHByZXNzaW9uIGxpdGVyYWwgc3RhcnRzIHdpdGggYSBzbGFzaCB0aGF0IGlzXG4gICAgICAgICAgLy8gbm90IGZvbGxvd2VkIGJ5ICogb3IgLyBzbyB0aGF0IGl0IGlzIG5vdCBjb25mdXNlZCB3aXRoXG4gICAgICAgICAgLy8gY29tbWVudHMuXG4gICAgICAgICAgJy8oPz1bXi8qJyArIHJlZ2V4RXhjbHMgKyAnXSknXG4gICAgICAgICAgLy8gYW5kIHRoZW4gY29udGFpbnMgYW55IG51bWJlciBvZiByYXcgY2hhcmFjdGVycyxcbiAgICAgICAgICArICcoPzpbXi9cXFxceDVCXFxcXHg1QycgKyByZWdleEV4Y2xzICsgJ10nXG4gICAgICAgICAgLy8gZXNjYXBlIHNlcXVlbmNlcyAoXFx4NUMpLFxuICAgICAgICAgICsgICAgJ3xcXFxceDVDJyArIHJlZ2V4QW55XG4gICAgICAgICAgLy8gb3Igbm9uLW5lc3RpbmcgY2hhcmFjdGVyIHNldHMgKFxceDVCXFx4NUQpO1xuICAgICAgICAgICsgICAgJ3xcXFxceDVCKD86W15cXFxceDVDXFxcXHg1RCcgKyByZWdleEV4Y2xzICsgJ10nXG4gICAgICAgICAgKyAgICAgICAgICAgICAnfFxcXFx4NUMnICsgcmVnZXhBbnkgKyAnKSooPzpcXFxceDVEfCQpKSsnXG4gICAgICAgICAgLy8gZmluYWxseSBjbG9zZWQgYnkgYSAvLlxuICAgICAgICAgICsgJy8nKTtcbiAgICAgIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIFsnbGFuZy1yZWdleCcsXG4gICAgICAgICAgIFJlZ0V4cCgnXicgKyBSRUdFWFBfUFJFQ0VERVJfUEFUVEVSTiArICcoJyArIFJFR0VYX0xJVEVSQUwgKyAnKScpXG4gICAgICAgICAgIF0pO1xuICAgIH1cblxuICAgIHZhciB0eXBlcyA9IG9wdGlvbnNbJ3R5cGVzJ107XG4gICAgaWYgKHR5cGVzKSB7XG4gICAgICBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMucHVzaChbUFJfVFlQRSwgdHlwZXNdKTtcbiAgICB9XG5cbiAgICB2YXIga2V5d29yZHMgPSAoXCJcIiArIG9wdGlvbnNbJ2tleXdvcmRzJ10pLnJlcGxhY2UoL14gfCAkL2csICcnKTtcbiAgICBpZiAoa2V5d29yZHMubGVuZ3RoKSB7XG4gICAgICBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBbUFJfS0VZV09SRCxcbiAgICAgICAgICAgbmV3IFJlZ0V4cCgnXig/OicgKyBrZXl3b3Jkcy5yZXBsYWNlKC9bXFxzLF0rL2csICd8JykgKyAnKVxcXFxiJyksXG4gICAgICAgICAgIG51bGxdKTtcbiAgICB9XG5cbiAgICBzaG9ydGN1dFN0eWxlUGF0dGVybnMucHVzaChbUFJfUExBSU4sICAgICAgIC9eXFxzKy8sIG51bGwsICcgXFxyXFxuXFx0XFx4QTAnXSk7XG5cbiAgICB2YXIgcHVuY3R1YXRpb24gPVxuICAgICAgLy8gVGhlIEJhc2ggbWFuIHBhZ2Ugc2F5c1xuXG4gICAgICAvLyBBIHdvcmQgaXMgYSBzZXF1ZW5jZSBvZiBjaGFyYWN0ZXJzIGNvbnNpZGVyZWQgYXMgYSBzaW5nbGVcbiAgICAgIC8vIHVuaXQgYnkgR1JVQi4gV29yZHMgYXJlIHNlcGFyYXRlZCBieSBtZXRhY2hhcmFjdGVycyxcbiAgICAgIC8vIHdoaWNoIGFyZSB0aGUgZm9sbG93aW5nIHBsdXMgc3BhY2UsIHRhYiwgYW5kIG5ld2xpbmU6IHsgfVxuICAgICAgLy8gfCAmICQgOyA8ID5cbiAgICAgIC8vIC4uLlxuICAgICAgXG4gICAgICAvLyBBIHdvcmQgYmVnaW5uaW5nIHdpdGggIyBjYXVzZXMgdGhhdCB3b3JkIGFuZCBhbGwgcmVtYWluaW5nXG4gICAgICAvLyBjaGFyYWN0ZXJzIG9uIHRoYXQgbGluZSB0byBiZSBpZ25vcmVkLlxuXG4gICAgICAvLyB3aGljaCBtZWFucyB0aGF0IG9ubHkgYSAnIycgYWZ0ZXIgLyg/Ol58W3t9fCYkOzw+XFxzXSkvIHN0YXJ0cyBhXG4gICAgICAvLyBjb21tZW50IGJ1dCBlbXBpcmljYWxseVxuICAgICAgLy8gJCBlY2hvIHsjfVxuICAgICAgLy8geyN9XG4gICAgICAvLyAkIGVjaG8gXFwkI1xuICAgICAgLy8gJCNcbiAgICAgIC8vICQgZWNobyB9I1xuICAgICAgLy8gfSNcblxuICAgICAgLy8gc28gLyg/Ol58W3wmOzw+XFxzXSkvIGlzIG1vcmUgYXBwcm9wcmlhdGUuXG5cbiAgICAgIC8vIGh0dHA6Ly9nY2MuZ251Lm9yZy9vbmxpbmVkb2NzL2djYy0yLjk1LjMvY3BwXzEuaHRtbCNTRUMzXG4gICAgICAvLyBzdWdnZXN0cyB0aGF0IHRoaXMgZGVmaW5pdGlvbiBpcyBjb21wYXRpYmxlIHdpdGggYVxuICAgICAgLy8gZGVmYXVsdCBtb2RlIHRoYXQgdHJpZXMgdG8gdXNlIGEgc2luZ2xlIHRva2VuIGRlZmluaXRpb25cbiAgICAgIC8vIHRvIHJlY29nbml6ZSBib3RoIGJhc2gvcHl0aG9uIHN0eWxlIGNvbW1lbnRzIGFuZCBDXG4gICAgICAvLyBwcmVwcm9jZXNzb3IgZGlyZWN0aXZlcy5cblxuICAgICAgLy8gVGhpcyBkZWZpbml0aW9uIG9mIHB1bmN0dWF0aW9uIGRvZXMgbm90IGluY2x1ZGUgIyBpbiB0aGUgbGlzdCBvZlxuICAgICAgLy8gZm9sbG93LW9uIGV4Y2x1c2lvbnMsIHNvICMgd2lsbCBub3QgYmUgYnJva2VuIGJlZm9yZSBpZiBwcmVjZWVkZWRcbiAgICAgIC8vIGJ5IGEgcHVuY3R1YXRpb24gY2hhcmFjdGVyLiAgV2UgY291bGQgdHJ5IHRvIGV4Y2x1ZGUgIyBhZnRlclxuICAgICAgLy8gW3wmOzw+XSBidXQgdGhhdCBkb2Vzbid0IHNlZW0gdG8gY2F1c2UgbWFueSBtYWpvciBwcm9ibGVtcy5cbiAgICAgIC8vIElmIHRoYXQgZG9lcyB0dXJuIG91dCB0byBiZSBhIHByb2JsZW0sIHdlIHNob3VsZCBjaGFuZ2UgdGhlIGJlbG93XG4gICAgICAvLyB3aGVuIGhjIGlzIHRydXRoeSB0byBpbmNsdWRlICMgaW4gdGhlIHJ1biBvZiBwdW5jdHVhdGlvbiBjaGFyYWN0ZXJzXG4gICAgICAvLyBvbmx5IHdoZW4gbm90IGZvbGxvd2ludCBbfCY7PD5dLlxuICAgICAgJ14uW15cXFxcc1xcXFx3LiRAXFwnXCJgL1xcXFxcXFxcXSonO1xuICAgIGlmIChvcHRpb25zWydyZWdleExpdGVyYWxzJ10pIHtcbiAgICAgIHB1bmN0dWF0aW9uICs9ICcoPyFcXHMqXFwvKSc7XG4gICAgfVxuXG4gICAgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgIC8vIFRPRE8obWlrZXNhbXVlbCk6IHJlY29nbml6ZSBub24tbGF0aW4gbGV0dGVycyBhbmQgbnVtZXJhbHMgaW4gaWRlbnRzXG4gICAgICAgIFtQUl9MSVRFUkFMLCAgICAgL15AW2Etel8kXVthLXpfJEAwLTldKi9pLCBudWxsXSxcbiAgICAgICAgW1BSX1RZUEUsICAgICAgICAvXig/OltAX10/W0EtWl0rW2Etel1bQS1aYS16XyRAMC05XSp8XFx3K190XFxiKS8sIG51bGxdLFxuICAgICAgICBbUFJfUExBSU4sICAgICAgIC9eW2Etel8kXVthLXpfJEAwLTldKi9pLCBudWxsXSxcbiAgICAgICAgW1BSX0xJVEVSQUwsXG4gICAgICAgICBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgICdeKD86J1xuICAgICAgICAgICAgIC8vIEEgaGV4IG51bWJlclxuICAgICAgICAgICAgICsgJzB4W2EtZjAtOV0rJ1xuICAgICAgICAgICAgIC8vIG9yIGFuIG9jdGFsIG9yIGRlY2ltYWwgbnVtYmVyLFxuICAgICAgICAgICAgICsgJ3woPzpcXFxcZCg/Ol9cXFxcZCspKlxcXFxkKig/OlxcXFwuXFxcXGQqKT98XFxcXC5cXFxcZFxcXFwrKSdcbiAgICAgICAgICAgICAvLyBwb3NzaWJseSBpbiBzY2llbnRpZmljIG5vdGF0aW9uXG4gICAgICAgICAgICAgKyAnKD86ZVsrXFxcXC1dP1xcXFxkKyk/J1xuICAgICAgICAgICAgICsgJyknXG4gICAgICAgICAgICAgLy8gd2l0aCBhbiBvcHRpb25hbCBtb2RpZmllciBsaWtlIFVMIGZvciB1bnNpZ25lZCBsb25nXG4gICAgICAgICAgICAgKyAnW2Etel0qJywgJ2knKSxcbiAgICAgICAgIG51bGwsICcwMTIzNDU2Nzg5J10sXG4gICAgICAgIC8vIERvbid0IHRyZWF0IGVzY2FwZWQgcXVvdGVzIGluIGJhc2ggYXMgc3RhcnRpbmcgc3RyaW5ncy5cbiAgICAgICAgLy8gU2VlIGlzc3VlIDE0NC5cbiAgICAgICAgW1BSX1BMQUlOLCAgICAgICAvXlxcXFxbXFxzXFxTXT8vLCBudWxsXSxcbiAgICAgICAgW1BSX1BVTkNUVUFUSU9OLCBuZXcgUmVnRXhwKHB1bmN0dWF0aW9uKSwgbnVsbF0pO1xuXG4gICAgcmV0dXJuIGNyZWF0ZVNpbXBsZUxleGVyKHNob3J0Y3V0U3R5bGVQYXR0ZXJucywgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zKTtcbiAgfVxuXG4gIHZhciBkZWNvcmF0ZVNvdXJjZSA9IHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICdrZXl3b3Jkcyc6IEFMTF9LRVlXT1JEUyxcbiAgICAgICAgJ2hhc2hDb21tZW50cyc6IHRydWUsXG4gICAgICAgICdjU3R5bGVDb21tZW50cyc6IHRydWUsXG4gICAgICAgICdtdWx0aUxpbmVTdHJpbmdzJzogdHJ1ZSxcbiAgICAgICAgJ3JlZ2V4TGl0ZXJhbHMnOiB0cnVlXG4gICAgICB9KTtcblxuICAvKipcbiAgICogR2l2ZW4gYSBET00gc3VidHJlZSwgd3JhcHMgaXQgaW4gYSBsaXN0LCBhbmQgcHV0cyBlYWNoIGxpbmUgaW50byBpdHMgb3duXG4gICAqIGxpc3QgaXRlbS5cbiAgICpcbiAgICogQHBhcmFtIHtOb2RlfSBub2RlIG1vZGlmaWVkIGluIHBsYWNlLiAgSXRzIGNvbnRlbnQgaXMgcHVsbGVkIGludG8gYW5cbiAgICogICAgIEhUTUxPTGlzdEVsZW1lbnQsIGFuZCBlYWNoIGxpbmUgaXMgbW92ZWQgaW50byBhIHNlcGFyYXRlIGxpc3QgaXRlbS5cbiAgICogICAgIFRoaXMgcmVxdWlyZXMgY2xvbmluZyBlbGVtZW50cywgc28gdGhlIGlucHV0IG1pZ2h0IG5vdCBoYXZlIHVuaXF1ZVxuICAgKiAgICAgSURzIGFmdGVyIG51bWJlcmluZy5cbiAgICogQHBhcmFtIHtib29sZWFufSBpc1ByZWZvcm1hdHRlZCB0cnVlIGlmZiB3aGl0ZS1zcGFjZSBpbiB0ZXh0IG5vZGVzIHNob3VsZFxuICAgKiAgICAgYmUgdHJlYXRlZCBhcyBzaWduaWZpY2FudC5cbiAgICovXG4gIGZ1bmN0aW9uIG51bWJlckxpbmVzKG5vZGUsIG9wdF9zdGFydExpbmVOdW0sIGlzUHJlZm9ybWF0dGVkKSB7XG4gICAgdmFyIG5vY29kZSA9IC8oPzpefFxccylub2NvZGUoPzpcXHN8JCkvO1xuICAgIHZhciBsaW5lQnJlYWsgPSAvXFxyXFxuP3xcXG4vO1xuICBcbiAgICB2YXIgZG9jdW1lbnQgPSBub2RlLm93bmVyRG9jdW1lbnQ7XG4gIFxuICAgIHZhciBsaSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpJyk7XG4gICAgd2hpbGUgKG5vZGUuZmlyc3RDaGlsZCkge1xuICAgICAgbGkuYXBwZW5kQ2hpbGQobm9kZS5maXJzdENoaWxkKTtcbiAgICB9XG4gICAgLy8gQW4gYXJyYXkgb2YgbGluZXMuICBXZSBzcGxpdCBiZWxvdywgc28gdGhpcyBpcyBpbml0aWFsaXplZCB0byBvbmVcbiAgICAvLyB1bi1zcGxpdCBsaW5lLlxuICAgIHZhciBsaXN0SXRlbXMgPSBbbGldO1xuICBcbiAgICBmdW5jdGlvbiB3YWxrKG5vZGUpIHtcbiAgICAgIHZhciB0eXBlID0gbm9kZS5ub2RlVHlwZTtcbiAgICAgIGlmICh0eXBlID09IDEgJiYgIW5vY29kZS50ZXN0KG5vZGUuY2xhc3NOYW1lKSkgeyAgLy8gRWxlbWVudFxuICAgICAgICBpZiAoJ2JyJyA9PT0gbm9kZS5ub2RlTmFtZSkge1xuICAgICAgICAgIGJyZWFrQWZ0ZXIobm9kZSk7XG4gICAgICAgICAgLy8gRGlzY2FyZCB0aGUgPEJSPiBzaW5jZSBpdCBpcyBub3cgZmx1c2ggYWdhaW5zdCBhIDwvTEk+LlxuICAgICAgICAgIGlmIChub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yICh2YXIgY2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7IGNoaWxkOyBjaGlsZCA9IGNoaWxkLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgICB3YWxrKGNoaWxkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoKHR5cGUgPT0gMyB8fCB0eXBlID09IDQpICYmIGlzUHJlZm9ybWF0dGVkKSB7ICAvLyBUZXh0XG4gICAgICAgIHZhciB0ZXh0ID0gbm9kZS5ub2RlVmFsdWU7XG4gICAgICAgIHZhciBtYXRjaCA9IHRleHQubWF0Y2gobGluZUJyZWFrKTtcbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgdmFyIGZpcnN0TGluZSA9IHRleHQuc3Vic3RyaW5nKDAsIG1hdGNoLmluZGV4KTtcbiAgICAgICAgICBub2RlLm5vZGVWYWx1ZSA9IGZpcnN0TGluZTtcbiAgICAgICAgICB2YXIgdGFpbCA9IHRleHQuc3Vic3RyaW5nKG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgICBpZiAodGFpbCkge1xuICAgICAgICAgICAgdmFyIHBhcmVudCA9IG5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgIHBhcmVudC5pbnNlcnRCZWZvcmUoXG4gICAgICAgICAgICAgIGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRhaWwpLCBub2RlLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtBZnRlcihub2RlKTtcbiAgICAgICAgICBpZiAoIWZpcnN0TGluZSkge1xuICAgICAgICAgICAgLy8gRG9uJ3QgbGVhdmUgYmxhbmsgdGV4dCBub2RlcyBpbiB0aGUgRE9NLlxuICAgICAgICAgICAgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgXG4gICAgLy8gU3BsaXQgYSBsaW5lIGFmdGVyIHRoZSBnaXZlbiBub2RlLlxuICAgIGZ1bmN0aW9uIGJyZWFrQWZ0ZXIobGluZUVuZE5vZGUpIHtcbiAgICAgIC8vIElmIHRoZXJlJ3Mgbm90aGluZyB0byB0aGUgcmlnaHQsIHRoZW4gd2UgY2FuIHNraXAgZW5kaW5nIHRoZSBsaW5lXG4gICAgICAvLyBoZXJlLCBhbmQgbW92ZSByb290LXdhcmRzIHNpbmNlIHNwbGl0dGluZyBqdXN0IGJlZm9yZSBhbiBlbmQtdGFnXG4gICAgICAvLyB3b3VsZCByZXF1aXJlIHVzIHRvIGNyZWF0ZSBhIGJ1bmNoIG9mIGVtcHR5IGNvcGllcy5cbiAgICAgIHdoaWxlICghbGluZUVuZE5vZGUubmV4dFNpYmxpbmcpIHtcbiAgICAgICAgbGluZUVuZE5vZGUgPSBsaW5lRW5kTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICBpZiAoIWxpbmVFbmROb2RlKSB7IHJldHVybjsgfVxuICAgICAgfVxuICBcbiAgICAgIGZ1bmN0aW9uIGJyZWFrTGVmdE9mKGxpbWl0LCBjb3B5KSB7XG4gICAgICAgIC8vIENsb25lIHNoYWxsb3dseSBpZiB0aGlzIG5vZGUgbmVlZHMgdG8gYmUgb24gYm90aCBzaWRlcyBvZiB0aGUgYnJlYWsuXG4gICAgICAgIHZhciByaWdodFNpZGUgPSBjb3B5ID8gbGltaXQuY2xvbmVOb2RlKGZhbHNlKSA6IGxpbWl0O1xuICAgICAgICB2YXIgcGFyZW50ID0gbGltaXQucGFyZW50Tm9kZTtcbiAgICAgICAgaWYgKHBhcmVudCkge1xuICAgICAgICAgIC8vIFdlIGNsb25lIHRoZSBwYXJlbnQgY2hhaW4uXG4gICAgICAgICAgLy8gVGhpcyBoZWxwcyB1cyByZXN1cnJlY3QgaW1wb3J0YW50IHN0eWxpbmcgZWxlbWVudHMgdGhhdCBjcm9zcyBsaW5lcy5cbiAgICAgICAgICAvLyBFLmcuIGluIDxpPkZvbzxicj5CYXI8L2k+XG4gICAgICAgICAgLy8gc2hvdWxkIGJlIHJld3JpdHRlbiB0byA8bGk+PGk+Rm9vPC9pPjwvbGk+PGxpPjxpPkJhcjwvaT48L2xpPi5cbiAgICAgICAgICB2YXIgcGFyZW50Q2xvbmUgPSBicmVha0xlZnRPZihwYXJlbnQsIDEpO1xuICAgICAgICAgIC8vIE1vdmUgdGhlIGNsb25lIGFuZCBldmVyeXRoaW5nIHRvIHRoZSByaWdodCBvZiB0aGUgb3JpZ2luYWxcbiAgICAgICAgICAvLyBvbnRvIHRoZSBjbG9uZWQgcGFyZW50LlxuICAgICAgICAgIHZhciBuZXh0ID0gbGltaXQubmV4dFNpYmxpbmc7XG4gICAgICAgICAgcGFyZW50Q2xvbmUuYXBwZW5kQ2hpbGQocmlnaHRTaWRlKTtcbiAgICAgICAgICBmb3IgKHZhciBzaWJsaW5nID0gbmV4dDsgc2libGluZzsgc2libGluZyA9IG5leHQpIHtcbiAgICAgICAgICAgIG5leHQgPSBzaWJsaW5nLm5leHRTaWJsaW5nO1xuICAgICAgICAgICAgcGFyZW50Q2xvbmUuYXBwZW5kQ2hpbGQoc2libGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByaWdodFNpZGU7XG4gICAgICB9XG4gIFxuICAgICAgdmFyIGNvcGllZExpc3RJdGVtID0gYnJlYWtMZWZ0T2YobGluZUVuZE5vZGUubmV4dFNpYmxpbmcsIDApO1xuICBcbiAgICAgIC8vIFdhbGsgdGhlIHBhcmVudCBjaGFpbiB1bnRpbCB3ZSByZWFjaCBhbiB1bmF0dGFjaGVkIExJLlxuICAgICAgZm9yICh2YXIgcGFyZW50O1xuICAgICAgICAgICAvLyBDaGVjayBub2RlVHlwZSBzaW5jZSBJRSBpbnZlbnRzIGRvY3VtZW50IGZyYWdtZW50cy5cbiAgICAgICAgICAgKHBhcmVudCA9IGNvcGllZExpc3RJdGVtLnBhcmVudE5vZGUpICYmIHBhcmVudC5ub2RlVHlwZSA9PT0gMTspIHtcbiAgICAgICAgY29waWVkTGlzdEl0ZW0gPSBwYXJlbnQ7XG4gICAgICB9XG4gICAgICAvLyBQdXQgaXQgb24gdGhlIGxpc3Qgb2YgbGluZXMgZm9yIGxhdGVyIHByb2Nlc3NpbmcuXG4gICAgICBsaXN0SXRlbXMucHVzaChjb3BpZWRMaXN0SXRlbSk7XG4gICAgfVxuICBcbiAgICAvLyBTcGxpdCBsaW5lcyB3aGlsZSB0aGVyZSBhcmUgbGluZXMgbGVmdCB0byBzcGxpdC5cbiAgICBmb3IgKHZhciBpID0gMDsgIC8vIE51bWJlciBvZiBsaW5lcyB0aGF0IGhhdmUgYmVlbiBzcGxpdCBzbyBmYXIuXG4gICAgICAgICBpIDwgbGlzdEl0ZW1zLmxlbmd0aDsgIC8vIGxlbmd0aCB1cGRhdGVkIGJ5IGJyZWFrQWZ0ZXIgY2FsbHMuXG4gICAgICAgICArK2kpIHtcbiAgICAgIHdhbGsobGlzdEl0ZW1zW2ldKTtcbiAgICB9XG4gIFxuICAgIC8vIE1ha2Ugc3VyZSBudW1lcmljIGluZGljZXMgc2hvdyBjb3JyZWN0bHkuXG4gICAgaWYgKG9wdF9zdGFydExpbmVOdW0gPT09IChvcHRfc3RhcnRMaW5lTnVtfDApKSB7XG4gICAgICBsaXN0SXRlbXNbMF0uc2V0QXR0cmlidXRlKCd2YWx1ZScsIG9wdF9zdGFydExpbmVOdW0pO1xuICAgIH1cbiAgXG4gICAgdmFyIG9sID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb2wnKTtcbiAgICBvbC5jbGFzc05hbWUgPSAnbGluZW51bXMnO1xuICAgIHZhciBvZmZzZXQgPSBNYXRoLm1heCgwLCAoKG9wdF9zdGFydExpbmVOdW0gLSAxIC8qIHplcm8gaW5kZXggKi8pKSB8IDApIHx8IDA7XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBsaXN0SXRlbXMubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICBsaSA9IGxpc3RJdGVtc1tpXTtcbiAgICAgIC8vIFN0aWNrIGEgY2xhc3Mgb24gdGhlIExJcyBzbyB0aGF0IHN0eWxlc2hlZXRzIGNhblxuICAgICAgLy8gY29sb3Igb2RkL2V2ZW4gcm93cywgb3IgYW55IG90aGVyIHJvdyBwYXR0ZXJuIHRoYXRcbiAgICAgIC8vIGlzIGNvLXByaW1lIHdpdGggMTAuXG4gICAgICBsaS5jbGFzc05hbWUgPSAnTCcgKyAoKGkgKyBvZmZzZXQpICUgMTApO1xuICAgICAgaWYgKCFsaS5maXJzdENoaWxkKSB7XG4gICAgICAgIGxpLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCdcXHhBMCcpKTtcbiAgICAgIH1cbiAgICAgIG9sLmFwcGVuZENoaWxkKGxpKTtcbiAgICB9XG4gIFxuICAgIG5vZGUuYXBwZW5kQ2hpbGQob2wpO1xuICB9XG4gIC8qKlxuICAgKiBCcmVha3Mge0Bjb2RlIGpvYi5zb3VyY2VDb2RlfSBhcm91bmQgc3R5bGUgYm91bmRhcmllcyBpblxuICAgKiB7QGNvZGUgam9iLmRlY29yYXRpb25zfSBhbmQgbW9kaWZpZXMge0Bjb2RlIGpvYi5zb3VyY2VOb2RlfSBpbiBwbGFjZS5cbiAgICogQHBhcmFtIHtPYmplY3R9IGpvYiBsaWtlIDxwcmU+e1xuICAgKiAgICBzb3VyY2VDb2RlOiB7c3RyaW5nfSBzb3VyY2UgYXMgcGxhaW4gdGV4dCxcbiAgICogICAgc291cmNlTm9kZToge0hUTUxFbGVtZW50fSB0aGUgZWxlbWVudCBjb250YWluaW5nIHRoZSBzb3VyY2UsXG4gICAqICAgIHNwYW5zOiB7QXJyYXkuPG51bWJlcnxOb2RlPn0gYWx0ZXJuYXRpbmcgc3BhbiBzdGFydCBpbmRpY2VzIGludG8gc291cmNlXG4gICAqICAgICAgIGFuZCB0aGUgdGV4dCBub2RlIG9yIGVsZW1lbnQgKGUuZy4ge0Bjb2RlIDxCUj59KSBjb3JyZXNwb25kaW5nIHRvIHRoYXRcbiAgICogICAgICAgc3Bhbi5cbiAgICogICAgZGVjb3JhdGlvbnM6IHtBcnJheS48bnVtYmVyfHN0cmluZ30gYW4gYXJyYXkgb2Ygc3R5bGUgY2xhc3NlcyBwcmVjZWRlZFxuICAgKiAgICAgICBieSB0aGUgcG9zaXRpb24gYXQgd2hpY2ggdGhleSBzdGFydCBpbiBqb2Iuc291cmNlQ29kZSBpbiBvcmRlclxuICAgKiB9PC9wcmU+XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBmdW5jdGlvbiByZWNvbWJpbmVUYWdzQW5kRGVjb3JhdGlvbnMoam9iKSB7XG4gICAgdmFyIGlzSUU4T3JFYXJsaWVyID0gL1xcYk1TSUVcXHMoXFxkKykvLmV4ZWMobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgaXNJRThPckVhcmxpZXIgPSBpc0lFOE9yRWFybGllciAmJiAraXNJRThPckVhcmxpZXJbMV0gPD0gODtcbiAgICB2YXIgbmV3bGluZVJlID0gL1xcbi9nO1xuICBcbiAgICB2YXIgc291cmNlID0gam9iLnNvdXJjZUNvZGU7XG4gICAgdmFyIHNvdXJjZUxlbmd0aCA9IHNvdXJjZS5sZW5ndGg7XG4gICAgLy8gSW5kZXggaW50byBzb3VyY2UgYWZ0ZXIgdGhlIGxhc3QgY29kZS11bml0IHJlY29tYmluZWQuXG4gICAgdmFyIHNvdXJjZUluZGV4ID0gMDtcbiAgXG4gICAgdmFyIHNwYW5zID0gam9iLnNwYW5zO1xuICAgIHZhciBuU3BhbnMgPSBzcGFucy5sZW5ndGg7XG4gICAgLy8gSW5kZXggaW50byBzcGFucyBhZnRlciB0aGUgbGFzdCBzcGFuIHdoaWNoIGVuZHMgYXQgb3IgYmVmb3JlIHNvdXJjZUluZGV4LlxuICAgIHZhciBzcGFuSW5kZXggPSAwO1xuICBcbiAgICB2YXIgZGVjb3JhdGlvbnMgPSBqb2IuZGVjb3JhdGlvbnM7XG4gICAgdmFyIG5EZWNvcmF0aW9ucyA9IGRlY29yYXRpb25zLmxlbmd0aDtcbiAgICAvLyBJbmRleCBpbnRvIGRlY29yYXRpb25zIGFmdGVyIHRoZSBsYXN0IGRlY29yYXRpb24gd2hpY2ggZW5kcyBhdCBvciBiZWZvcmVcbiAgICAvLyBzb3VyY2VJbmRleC5cbiAgICB2YXIgZGVjb3JhdGlvbkluZGV4ID0gMDtcbiAgXG4gICAgLy8gUmVtb3ZlIGFsbCB6ZXJvLWxlbmd0aCBkZWNvcmF0aW9ucy5cbiAgICBkZWNvcmF0aW9uc1tuRGVjb3JhdGlvbnNdID0gc291cmNlTGVuZ3RoO1xuICAgIHZhciBkZWNQb3MsIGk7XG4gICAgZm9yIChpID0gZGVjUG9zID0gMDsgaSA8IG5EZWNvcmF0aW9uczspIHtcbiAgICAgIGlmIChkZWNvcmF0aW9uc1tpXSAhPT0gZGVjb3JhdGlvbnNbaSArIDJdKSB7XG4gICAgICAgIGRlY29yYXRpb25zW2RlY1BvcysrXSA9IGRlY29yYXRpb25zW2krK107XG4gICAgICAgIGRlY29yYXRpb25zW2RlY1BvcysrXSA9IGRlY29yYXRpb25zW2krK107XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpICs9IDI7XG4gICAgICB9XG4gICAgfVxuICAgIG5EZWNvcmF0aW9ucyA9IGRlY1BvcztcbiAgXG4gICAgLy8gU2ltcGxpZnkgZGVjb3JhdGlvbnMuXG4gICAgZm9yIChpID0gZGVjUG9zID0gMDsgaSA8IG5EZWNvcmF0aW9uczspIHtcbiAgICAgIHZhciBzdGFydFBvcyA9IGRlY29yYXRpb25zW2ldO1xuICAgICAgLy8gQ29uZmxhdGUgYWxsIGFkamFjZW50IGRlY29yYXRpb25zIHRoYXQgdXNlIHRoZSBzYW1lIHN0eWxlLlxuICAgICAgdmFyIHN0YXJ0RGVjID0gZGVjb3JhdGlvbnNbaSArIDFdO1xuICAgICAgdmFyIGVuZCA9IGkgKyAyO1xuICAgICAgd2hpbGUgKGVuZCArIDIgPD0gbkRlY29yYXRpb25zICYmIGRlY29yYXRpb25zW2VuZCArIDFdID09PSBzdGFydERlYykge1xuICAgICAgICBlbmQgKz0gMjtcbiAgICAgIH1cbiAgICAgIGRlY29yYXRpb25zW2RlY1BvcysrXSA9IHN0YXJ0UG9zO1xuICAgICAgZGVjb3JhdGlvbnNbZGVjUG9zKytdID0gc3RhcnREZWM7XG4gICAgICBpID0gZW5kO1xuICAgIH1cbiAgXG4gICAgbkRlY29yYXRpb25zID0gZGVjb3JhdGlvbnMubGVuZ3RoID0gZGVjUG9zO1xuICBcbiAgICB2YXIgc291cmNlTm9kZSA9IGpvYi5zb3VyY2VOb2RlO1xuICAgIHZhciBvbGREaXNwbGF5O1xuICAgIGlmIChzb3VyY2VOb2RlKSB7XG4gICAgICBvbGREaXNwbGF5ID0gc291cmNlTm9kZS5zdHlsZS5kaXNwbGF5O1xuICAgICAgc291cmNlTm9kZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgdmFyIGRlY29yYXRpb24gPSBudWxsO1xuICAgICAgd2hpbGUgKHNwYW5JbmRleCA8IG5TcGFucykge1xuICAgICAgICB2YXIgc3BhblN0YXJ0ID0gc3BhbnNbc3BhbkluZGV4XTtcbiAgICAgICAgdmFyIHNwYW5FbmQgPSBzcGFuc1tzcGFuSW5kZXggKyAyXSB8fCBzb3VyY2VMZW5ndGg7XG4gIFxuICAgICAgICB2YXIgZGVjRW5kID0gZGVjb3JhdGlvbnNbZGVjb3JhdGlvbkluZGV4ICsgMl0gfHwgc291cmNlTGVuZ3RoO1xuICBcbiAgICAgICAgdmFyIGVuZCA9IE1hdGgubWluKHNwYW5FbmQsIGRlY0VuZCk7XG4gIFxuICAgICAgICB2YXIgdGV4dE5vZGUgPSBzcGFuc1tzcGFuSW5kZXggKyAxXTtcbiAgICAgICAgdmFyIHN0eWxlZFRleHQ7XG4gICAgICAgIGlmICh0ZXh0Tm9kZS5ub2RlVHlwZSAhPT0gMSAgLy8gRG9uJ3QgbXVjayB3aXRoIDxCUj5zIG9yIDxMST5zXG4gICAgICAgICAgICAvLyBEb24ndCBpbnRyb2R1Y2Ugc3BhbnMgYXJvdW5kIGVtcHR5IHRleHQgbm9kZXMuXG4gICAgICAgICAgICAmJiAoc3R5bGVkVGV4dCA9IHNvdXJjZS5zdWJzdHJpbmcoc291cmNlSW5kZXgsIGVuZCkpKSB7XG4gICAgICAgICAgLy8gVGhpcyBtYXkgc2VlbSBiaXphcnJlLCBhbmQgaXQgaXMuICBFbWl0dGluZyBMRiBvbiBJRSBjYXVzZXMgdGhlXG4gICAgICAgICAgLy8gY29kZSB0byBkaXNwbGF5IHdpdGggc3BhY2VzIGluc3RlYWQgb2YgbGluZSBicmVha3MuXG4gICAgICAgICAgLy8gRW1pdHRpbmcgV2luZG93cyBzdGFuZGFyZCBpc3N1ZSBsaW5lYnJlYWtzIChDUkxGKSBjYXVzZXMgYSBibGFua1xuICAgICAgICAgIC8vIHNwYWNlIHRvIGFwcGVhciBhdCB0aGUgYmVnaW5uaW5nIG9mIGV2ZXJ5IGxpbmUgYnV0IHRoZSBmaXJzdC5cbiAgICAgICAgICAvLyBFbWl0dGluZyBhbiBvbGQgTWFjIE9TIDkgbGluZSBzZXBhcmF0b3IgbWFrZXMgZXZlcnl0aGluZyBzcGlmZnkuXG4gICAgICAgICAgaWYgKGlzSUU4T3JFYXJsaWVyKSB7XG4gICAgICAgICAgICBzdHlsZWRUZXh0ID0gc3R5bGVkVGV4dC5yZXBsYWNlKG5ld2xpbmVSZSwgJ1xccicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0ZXh0Tm9kZS5ub2RlVmFsdWUgPSBzdHlsZWRUZXh0O1xuICAgICAgICAgIHZhciBkb2N1bWVudCA9IHRleHROb2RlLm93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgdmFyIHNwYW4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgICAgICAgc3Bhbi5jbGFzc05hbWUgPSBkZWNvcmF0aW9uc1tkZWNvcmF0aW9uSW5kZXggKyAxXTtcbiAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IHRleHROb2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQoc3BhbiwgdGV4dE5vZGUpO1xuICAgICAgICAgIHNwYW4uYXBwZW5kQ2hpbGQodGV4dE5vZGUpO1xuICAgICAgICAgIGlmIChzb3VyY2VJbmRleCA8IHNwYW5FbmQpIHsgIC8vIFNwbGl0IG9mZiBhIHRleHQgbm9kZS5cbiAgICAgICAgICAgIHNwYW5zW3NwYW5JbmRleCArIDFdID0gdGV4dE5vZGVcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBQb3NzaWJseSBvcHRpbWl6ZSBieSB1c2luZyAnJyBpZiB0aGVyZSdzIG5vIGZsaWNrZXIuXG4gICAgICAgICAgICAgICAgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShzb3VyY2Uuc3Vic3RyaW5nKGVuZCwgc3BhbkVuZCkpO1xuICAgICAgICAgICAgcGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGV4dE5vZGUsIHNwYW4ubmV4dFNpYmxpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICBcbiAgICAgICAgc291cmNlSW5kZXggPSBlbmQ7XG4gIFxuICAgICAgICBpZiAoc291cmNlSW5kZXggPj0gc3BhbkVuZCkge1xuICAgICAgICAgIHNwYW5JbmRleCArPSAyO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzb3VyY2VJbmRleCA+PSBkZWNFbmQpIHtcbiAgICAgICAgICBkZWNvcmF0aW9uSW5kZXggKz0gMjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoc291cmNlTm9kZSkge1xuICAgICAgICBzb3VyY2VOb2RlLnN0eWxlLmRpc3BsYXkgPSBvbGREaXNwbGF5O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKiBNYXBzIGxhbmd1YWdlLXNwZWNpZmljIGZpbGUgZXh0ZW5zaW9ucyB0byBoYW5kbGVycy4gKi9cbiAgdmFyIGxhbmdIYW5kbGVyUmVnaXN0cnkgPSB7fTtcbiAgLyoqIFJlZ2lzdGVyIGEgbGFuZ3VhZ2UgaGFuZGxlciBmb3IgdGhlIGdpdmVuIGZpbGUgZXh0ZW5zaW9ucy5cbiAgICAqIEBwYXJhbSB7ZnVuY3Rpb24gKE9iamVjdCl9IGhhbmRsZXIgYSBmdW5jdGlvbiBmcm9tIHNvdXJjZSBjb2RlIHRvIGEgbGlzdFxuICAgICogICAgICBvZiBkZWNvcmF0aW9ucy4gIFRha2VzIGEgc2luZ2xlIGFyZ3VtZW50IGpvYiB3aGljaCBkZXNjcmliZXMgdGhlXG4gICAgKiAgICAgIHN0YXRlIG9mIHRoZSBjb21wdXRhdGlvbi4gICBUaGUgc2luZ2xlIHBhcmFtZXRlciBoYXMgdGhlIGZvcm1cbiAgICAqICAgICAge0Bjb2RlIHtcbiAgICAqICAgICAgICBzb3VyY2VDb2RlOiB7c3RyaW5nfSBhcyBwbGFpbiB0ZXh0LlxuICAgICogICAgICAgIGRlY29yYXRpb25zOiB7QXJyYXkuPG51bWJlcnxzdHJpbmc+fSBhbiBhcnJheSBvZiBzdHlsZSBjbGFzc2VzXG4gICAgKiAgICAgICAgICAgICAgICAgICAgIHByZWNlZGVkIGJ5IHRoZSBwb3NpdGlvbiBhdCB3aGljaCB0aGV5IHN0YXJ0IGluXG4gICAgKiAgICAgICAgICAgICAgICAgICAgIGpvYi5zb3VyY2VDb2RlIGluIG9yZGVyLlxuICAgICogICAgICAgICAgICAgICAgICAgICBUaGUgbGFuZ3VhZ2UgaGFuZGxlciBzaG91bGQgYXNzaWduZWQgdGhpcyBmaWVsZC5cbiAgICAqICAgICAgICBiYXNlUG9zOiB7aW50fSB0aGUgcG9zaXRpb24gb2Ygc291cmNlIGluIHRoZSBsYXJnZXIgc291cmNlIGNodW5rLlxuICAgICogICAgICAgICAgICAgICAgIEFsbCBwb3NpdGlvbnMgaW4gdGhlIG91dHB1dCBkZWNvcmF0aW9ucyBhcnJheSBhcmUgcmVsYXRpdmVcbiAgICAqICAgICAgICAgICAgICAgICB0byB0aGUgbGFyZ2VyIHNvdXJjZSBjaHVuay5cbiAgICAqICAgICAgfSB9XG4gICAgKiBAcGFyYW0ge0FycmF5LjxzdHJpbmc+fSBmaWxlRXh0ZW5zaW9uc1xuICAgICovXG4gIGZ1bmN0aW9uIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoaGFuZGxlciwgZmlsZUV4dGVuc2lvbnMpIHtcbiAgICBmb3IgKHZhciBpID0gZmlsZUV4dGVuc2lvbnMubGVuZ3RoOyAtLWkgPj0gMDspIHtcbiAgICAgIHZhciBleHQgPSBmaWxlRXh0ZW5zaW9uc1tpXTtcbiAgICAgIGlmICghbGFuZ0hhbmRsZXJSZWdpc3RyeS5oYXNPd25Qcm9wZXJ0eShleHQpKSB7XG4gICAgICAgIGxhbmdIYW5kbGVyUmVnaXN0cnlbZXh0XSA9IGhhbmRsZXI7XG4gICAgICB9IGVsc2UgaWYgKHdpblsnY29uc29sZSddKSB7XG4gICAgICAgIGNvbnNvbGVbJ3dhcm4nXSgnY2Fubm90IG92ZXJyaWRlIGxhbmd1YWdlIGhhbmRsZXIgJXMnLCBleHQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBsYW5nSGFuZGxlckZvckV4dGVuc2lvbihleHRlbnNpb24sIHNvdXJjZSkge1xuICAgIGlmICghKGV4dGVuc2lvbiAmJiBsYW5nSGFuZGxlclJlZ2lzdHJ5Lmhhc093blByb3BlcnR5KGV4dGVuc2lvbikpKSB7XG4gICAgICAvLyBUcmVhdCBpdCBhcyBtYXJrdXAgaWYgdGhlIGZpcnN0IG5vbiB3aGl0ZXNwYWNlIGNoYXJhY3RlciBpcyBhIDwgYW5kXG4gICAgICAvLyB0aGUgbGFzdCBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXIgaXMgYSA+LlxuICAgICAgZXh0ZW5zaW9uID0gL15cXHMqPC8udGVzdChzb3VyY2UpXG4gICAgICAgICAgPyAnZGVmYXVsdC1tYXJrdXAnXG4gICAgICAgICAgOiAnZGVmYXVsdC1jb2RlJztcbiAgICB9XG4gICAgcmV0dXJuIGxhbmdIYW5kbGVyUmVnaXN0cnlbZXh0ZW5zaW9uXTtcbiAgfVxuICByZWdpc3RlckxhbmdIYW5kbGVyKGRlY29yYXRlU291cmNlLCBbJ2RlZmF1bHQtY29kZSddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihcbiAgICAgIGNyZWF0ZVNpbXBsZUxleGVyKFxuICAgICAgICAgIFtdLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgW1BSX1BMQUlOLCAgICAgICAvXltePD9dKy9dLFxuICAgICAgICAgICBbUFJfREVDTEFSQVRJT04sIC9ePCFcXHdbXj5dKig/Oj58JCkvXSxcbiAgICAgICAgICAgW1BSX0NPTU1FTlQsICAgICAvXjxcXCEtLVtcXHNcXFNdKj8oPzotXFwtPnwkKS9dLFxuICAgICAgICAgICAvLyBVbmVzY2FwZWQgY29udGVudCBpbiBhbiB1bmtub3duIGxhbmd1YWdlXG4gICAgICAgICAgIFsnbGFuZy0nLCAgICAgICAgL148XFw/KFtcXHNcXFNdKz8pKD86XFw/PnwkKS9dLFxuICAgICAgICAgICBbJ2xhbmctJywgICAgICAgIC9ePCUoW1xcc1xcU10rPykoPzolPnwkKS9dLFxuICAgICAgICAgICBbUFJfUFVOQ1RVQVRJT04sIC9eKD86PFslP118WyU/XT4pL10sXG4gICAgICAgICAgIFsnbGFuZy0nLCAgICAgICAgL148eG1wXFxiW14+XSo+KFtcXHNcXFNdKz8pPFxcL3htcFxcYltePl0qPi9pXSxcbiAgICAgICAgICAgLy8gVW5lc2NhcGVkIGNvbnRlbnQgaW4gamF2YXNjcmlwdC4gIChPciBwb3NzaWJseSB2YnNjcmlwdCkuXG4gICAgICAgICAgIFsnbGFuZy1qcycsICAgICAgL148c2NyaXB0XFxiW14+XSo+KFtcXHNcXFNdKj8pKDxcXC9zY3JpcHRcXGJbXj5dKj4pL2ldLFxuICAgICAgICAgICAvLyBDb250YWlucyB1bmVzY2FwZWQgc3R5bGVzaGVldCBjb250ZW50XG4gICAgICAgICAgIFsnbGFuZy1jc3MnLCAgICAgL148c3R5bGVcXGJbXj5dKj4oW1xcc1xcU10qPykoPFxcL3N0eWxlXFxiW14+XSo+KS9pXSxcbiAgICAgICAgICAgWydsYW5nLWluLnRhZycsICAvXig8XFwvP1thLXpdW148Pl0qPikvaV1cbiAgICAgICAgICBdKSxcbiAgICAgIFsnZGVmYXVsdC1tYXJrdXAnLCAnaHRtJywgJ2h0bWwnLCAnbXhtbCcsICd4aHRtbCcsICd4bWwnLCAneHNsJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKFxuICAgICAgY3JlYXRlU2ltcGxlTGV4ZXIoXG4gICAgICAgICAgW1xuICAgICAgICAgICBbUFJfUExBSU4sICAgICAgICAvXltcXHNdKy8sIG51bGwsICcgXFx0XFxyXFxuJ10sXG4gICAgICAgICAgIFtQUl9BVFRSSUJfVkFMVUUsIC9eKD86XFxcIlteXFxcIl0qXFxcIj98XFwnW15cXCddKlxcJz8pLywgbnVsbCwgJ1xcXCJcXCcnXVxuICAgICAgICAgICBdLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgW1BSX1RBRywgICAgICAgICAgL15ePFxcLz9bYS16XSg/OltcXHcuOi1dKlxcdyk/fFxcLz8+JC9pXSxcbiAgICAgICAgICAgW1BSX0FUVFJJQl9OQU1FLCAgL14oPyFzdHlsZVtcXHM9XXxvbilbYS16XSg/OltcXHc6LV0qXFx3KT8vaV0sXG4gICAgICAgICAgIFsnbGFuZy11cS52YWwnLCAgIC9ePVxccyooW14+XFwnXFxcIlxcc10qKD86W14+XFwnXFxcIlxcc1xcL118XFwvKD89XFxzKSkpL10sXG4gICAgICAgICAgIFtQUl9QVU5DVFVBVElPTiwgIC9eWz08PlxcL10rL10sXG4gICAgICAgICAgIFsnbGFuZy1qcycsICAgICAgIC9eb25cXHcrXFxzKj1cXHMqXFxcIihbXlxcXCJdKylcXFwiL2ldLFxuICAgICAgICAgICBbJ2xhbmctanMnLCAgICAgICAvXm9uXFx3K1xccyo9XFxzKlxcJyhbXlxcJ10rKVxcJy9pXSxcbiAgICAgICAgICAgWydsYW5nLWpzJywgICAgICAgL15vblxcdytcXHMqPVxccyooW15cXFwiXFwnPlxcc10rKS9pXSxcbiAgICAgICAgICAgWydsYW5nLWNzcycsICAgICAgL15zdHlsZVxccyo9XFxzKlxcXCIoW15cXFwiXSspXFxcIi9pXSxcbiAgICAgICAgICAgWydsYW5nLWNzcycsICAgICAgL15zdHlsZVxccyo9XFxzKlxcJyhbXlxcJ10rKVxcJy9pXSxcbiAgICAgICAgICAgWydsYW5nLWNzcycsICAgICAgL15zdHlsZVxccyo9XFxzKihbXlxcXCJcXCc+XFxzXSspL2ldXG4gICAgICAgICAgIF0pLFxuICAgICAgWydpbi50YWcnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoXG4gICAgICBjcmVhdGVTaW1wbGVMZXhlcihbXSwgW1tQUl9BVFRSSUJfVkFMVUUsIC9eW1xcc1xcU10rL11dKSwgWyd1cS52YWwnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBDUFBfS0VZV09SRFMsXG4gICAgICAgICAgJ2hhc2hDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ2NTdHlsZUNvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAndHlwZXMnOiBDX1RZUEVTXG4gICAgICAgIH0pLCBbJ2MnLCAnY2MnLCAnY3BwJywgJ2N4eCcsICdjeWMnLCAnbSddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6ICdudWxsLHRydWUsZmFsc2UnXG4gICAgICAgIH0pLCBbJ2pzb24nXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBDU0hBUlBfS0VZV09SRFMsXG4gICAgICAgICAgJ2hhc2hDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ2NTdHlsZUNvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAndmVyYmF0aW1TdHJpbmdzJzogdHJ1ZSxcbiAgICAgICAgICAndHlwZXMnOiBDX1RZUEVTXG4gICAgICAgIH0pLCBbJ2NzJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogSkFWQV9LRVlXT1JEUyxcbiAgICAgICAgICAnY1N0eWxlQ29tbWVudHMnOiB0cnVlXG4gICAgICAgIH0pLCBbJ2phdmEnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBTSF9LRVlXT1JEUyxcbiAgICAgICAgICAnaGFzaENvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAnbXVsdGlMaW5lU3RyaW5ncyc6IHRydWVcbiAgICAgICAgfSksIFsnYmFzaCcsICdic2gnLCAnY3NoJywgJ3NoJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogUFlUSE9OX0tFWVdPUkRTLFxuICAgICAgICAgICdoYXNoQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdtdWx0aUxpbmVTdHJpbmdzJzogdHJ1ZSxcbiAgICAgICAgICAndHJpcGxlUXVvdGVkU3RyaW5ncyc6IHRydWVcbiAgICAgICAgfSksIFsnY3YnLCAncHknLCAncHl0aG9uJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogUEVSTF9LRVlXT1JEUyxcbiAgICAgICAgICAnaGFzaENvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAnbXVsdGlMaW5lU3RyaW5ncyc6IHRydWUsXG4gICAgICAgICAgJ3JlZ2V4TGl0ZXJhbHMnOiAyICAvLyBtdWx0aWxpbmUgcmVnZXggbGl0ZXJhbHNcbiAgICAgICAgfSksIFsncGVybCcsICdwbCcsICdwbSddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IFJVQllfS0VZV09SRFMsXG4gICAgICAgICAgJ2hhc2hDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ211bHRpTGluZVN0cmluZ3MnOiB0cnVlLFxuICAgICAgICAgICdyZWdleExpdGVyYWxzJzogdHJ1ZVxuICAgICAgICB9KSwgWydyYicsICdydWJ5J10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogSlNDUklQVF9LRVlXT1JEUyxcbiAgICAgICAgICAnY1N0eWxlQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdyZWdleExpdGVyYWxzJzogdHJ1ZVxuICAgICAgICB9KSwgWydqYXZhc2NyaXB0JywgJ2pzJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogQ09GRkVFX0tFWVdPUkRTLFxuICAgICAgICAgICdoYXNoQ29tbWVudHMnOiAzLCAgLy8gIyMjIHN0eWxlIGJsb2NrIGNvbW1lbnRzXG4gICAgICAgICAgJ2NTdHlsZUNvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAnbXVsdGlsaW5lU3RyaW5ncyc6IHRydWUsXG4gICAgICAgICAgJ3RyaXBsZVF1b3RlZFN0cmluZ3MnOiB0cnVlLFxuICAgICAgICAgICdyZWdleExpdGVyYWxzJzogdHJ1ZVxuICAgICAgICB9KSwgWydjb2ZmZWUnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBSVVNUX0tFWVdPUkRTLFxuICAgICAgICAgICdjU3R5bGVDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ211bHRpbGluZVN0cmluZ3MnOiB0cnVlXG4gICAgICAgIH0pLCBbJ3JjJywgJ3JzJywgJ3J1c3QnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoXG4gICAgICBjcmVhdGVTaW1wbGVMZXhlcihbXSwgW1tQUl9TVFJJTkcsIC9eW1xcc1xcU10rL11dKSwgWydyZWdleCddKTtcblxuICBmdW5jdGlvbiBhcHBseURlY29yYXRvcihqb2IpIHtcbiAgICB2YXIgb3B0X2xhbmdFeHRlbnNpb24gPSBqb2IubGFuZ0V4dGVuc2lvbjtcblxuICAgIHRyeSB7XG4gICAgICAvLyBFeHRyYWN0IHRhZ3MsIGFuZCBjb252ZXJ0IHRoZSBzb3VyY2UgY29kZSB0byBwbGFpbiB0ZXh0LlxuICAgICAgdmFyIHNvdXJjZUFuZFNwYW5zID0gZXh0cmFjdFNvdXJjZVNwYW5zKGpvYi5zb3VyY2VOb2RlLCBqb2IucHJlKTtcbiAgICAgIC8qKiBQbGFpbiB0ZXh0LiBAdHlwZSB7c3RyaW5nfSAqL1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZUFuZFNwYW5zLnNvdXJjZUNvZGU7XG4gICAgICBqb2Iuc291cmNlQ29kZSA9IHNvdXJjZTtcbiAgICAgIGpvYi5zcGFucyA9IHNvdXJjZUFuZFNwYW5zLnNwYW5zO1xuICAgICAgam9iLmJhc2VQb3MgPSAwO1xuXG4gICAgICAvLyBBcHBseSB0aGUgYXBwcm9wcmlhdGUgbGFuZ3VhZ2UgaGFuZGxlclxuICAgICAgbGFuZ0hhbmRsZXJGb3JFeHRlbnNpb24ob3B0X2xhbmdFeHRlbnNpb24sIHNvdXJjZSkoam9iKTtcblxuICAgICAgLy8gSW50ZWdyYXRlIHRoZSBkZWNvcmF0aW9ucyBhbmQgdGFncyBiYWNrIGludG8gdGhlIHNvdXJjZSBjb2RlLFxuICAgICAgLy8gbW9kaWZ5aW5nIHRoZSBzb3VyY2VOb2RlIGluIHBsYWNlLlxuICAgICAgcmVjb21iaW5lVGFnc0FuZERlY29yYXRpb25zKGpvYik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKHdpblsnY29uc29sZSddKSB7XG4gICAgICAgIGNvbnNvbGVbJ2xvZyddKGUgJiYgZVsnc3RhY2snXSB8fCBlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJldHR5IHByaW50IGEgY2h1bmsgb2YgY29kZS5cbiAgICogQHBhcmFtIHNvdXJjZUNvZGVIdG1sIHtzdHJpbmd9IFRoZSBIVE1MIHRvIHByZXR0eSBwcmludC5cbiAgICogQHBhcmFtIG9wdF9sYW5nRXh0ZW5zaW9uIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBuYW1lIHRvIHVzZS5cbiAgICogICAgIFR5cGljYWxseSwgYSBmaWxlbmFtZSBleHRlbnNpb24gbGlrZSAnY3BwJyBvciAnamF2YScuXG4gICAqIEBwYXJhbSBvcHRfbnVtYmVyTGluZXMge251bWJlcnxib29sZWFufSBUcnVlIHRvIG51bWJlciBsaW5lcyxcbiAgICogICAgIG9yIHRoZSAxLWluZGV4ZWQgbnVtYmVyIG9mIHRoZSBmaXJzdCBsaW5lIGluIHNvdXJjZUNvZGVIdG1sLlxuICAgKi9cbiAgZnVuY3Rpb24gJHByZXR0eVByaW50T25lKHNvdXJjZUNvZGVIdG1sLCBvcHRfbGFuZ0V4dGVuc2lvbiwgb3B0X251bWJlckxpbmVzKSB7XG4gICAgdmFyIGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIC8vIFRoaXMgY291bGQgY2F1c2UgaW1hZ2VzIHRvIGxvYWQgYW5kIG9ubG9hZCBsaXN0ZW5lcnMgdG8gZmlyZS5cbiAgICAvLyBFLmcuIDxpbWcgb25lcnJvcj1cImFsZXJ0KDEzMzcpXCIgc3JjPVwibm9zdWNoaW1hZ2UucG5nXCI+LlxuICAgIC8vIFdlIGFzc3VtZSB0aGF0IHRoZSBpbm5lciBIVE1MIGlzIGZyb20gYSB0cnVzdGVkIHNvdXJjZS5cbiAgICAvLyBUaGUgcHJlLXRhZyBpcyByZXF1aXJlZCBmb3IgSUU4IHdoaWNoIHN0cmlwcyBuZXdsaW5lcyBmcm9tIGlubmVySFRNTFxuICAgIC8vIHdoZW4gaXQgaXMgaW5qZWN0ZWQgaW50byBhIDxwcmU+IHRhZy5cbiAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzQ1MTQ4Ni9wcmUtdGFnLWxvc2VzLWxpbmUtYnJlYWtzLXdoZW4tc2V0dGluZy1pbm5lcmh0bWwtaW4taWVcbiAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzE5NTM2My9pbnNlcnRpbmctYS1uZXdsaW5lLWludG8tYS1wcmUtdGFnLWllLWphdmFzY3JpcHRcbiAgICBjb250YWluZXIuaW5uZXJIVE1MID0gJzxwcmU+JyArIHNvdXJjZUNvZGVIdG1sICsgJzwvcHJlPic7XG4gICAgY29udGFpbmVyID0gY29udGFpbmVyLmZpcnN0Q2hpbGQ7XG4gICAgaWYgKG9wdF9udW1iZXJMaW5lcykge1xuICAgICAgbnVtYmVyTGluZXMoY29udGFpbmVyLCBvcHRfbnVtYmVyTGluZXMsIHRydWUpO1xuICAgIH1cblxuICAgIHZhciBqb2IgPSB7XG4gICAgICBsYW5nRXh0ZW5zaW9uOiBvcHRfbGFuZ0V4dGVuc2lvbixcbiAgICAgIG51bWJlckxpbmVzOiBvcHRfbnVtYmVyTGluZXMsXG4gICAgICBzb3VyY2VOb2RlOiBjb250YWluZXIsXG4gICAgICBwcmU6IDFcbiAgICB9O1xuICAgIGFwcGx5RGVjb3JhdG9yKGpvYik7XG4gICAgcmV0dXJuIGNvbnRhaW5lci5pbm5lckhUTUw7XG4gIH1cblxuICAgLyoqXG4gICAgKiBGaW5kIGFsbCB0aGUge0Bjb2RlIDxwcmU+fSBhbmQge0Bjb2RlIDxjb2RlPn0gdGFncyBpbiB0aGUgRE9NIHdpdGhcbiAgICAqIHtAY29kZSBjbGFzcz1wcmV0dHlwcmludH0gYW5kIHByZXR0aWZ5IHRoZW0uXG4gICAgKlxuICAgICogQHBhcmFtIHtGdW5jdGlvbn0gb3B0X3doZW5Eb25lIGNhbGxlZCB3aGVuIHByZXR0aWZ5aW5nIGlzIGRvbmUuXG4gICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxEb2N1bWVudH0gb3B0X3Jvb3QgYW4gZWxlbWVudCBvciBkb2N1bWVudFxuICAgICogICBjb250YWluaW5nIGFsbCB0aGUgZWxlbWVudHMgdG8gcHJldHR5IHByaW50LlxuICAgICogICBEZWZhdWx0cyB0byB7QGNvZGUgZG9jdW1lbnQuYm9keX0uXG4gICAgKi9cbiAgZnVuY3Rpb24gJHByZXR0eVByaW50KG9wdF93aGVuRG9uZSwgb3B0X3Jvb3QpIHtcbiAgICB2YXIgcm9vdCA9IG9wdF9yb290IHx8IGRvY3VtZW50LmJvZHk7XG4gICAgdmFyIGRvYyA9IHJvb3Qub3duZXJEb2N1bWVudCB8fCBkb2N1bWVudDtcbiAgICBmdW5jdGlvbiBieVRhZ05hbWUodG4pIHsgcmV0dXJuIHJvb3QuZ2V0RWxlbWVudHNCeVRhZ05hbWUodG4pOyB9XG4gICAgLy8gZmV0Y2ggYSBsaXN0IG9mIG5vZGVzIHRvIHJld3JpdGVcbiAgICB2YXIgY29kZVNlZ21lbnRzID0gW2J5VGFnTmFtZSgncHJlJyksIGJ5VGFnTmFtZSgnY29kZScpLCBieVRhZ05hbWUoJ3htcCcpXTtcbiAgICB2YXIgZWxlbWVudHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvZGVTZWdtZW50cy5sZW5ndGg7ICsraSkge1xuICAgICAgZm9yICh2YXIgaiA9IDAsIG4gPSBjb2RlU2VnbWVudHNbaV0ubGVuZ3RoOyBqIDwgbjsgKytqKSB7XG4gICAgICAgIGVsZW1lbnRzLnB1c2goY29kZVNlZ21lbnRzW2ldW2pdKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29kZVNlZ21lbnRzID0gbnVsbDtcblxuICAgIHZhciBjbG9jayA9IERhdGU7XG4gICAgaWYgKCFjbG9ja1snbm93J10pIHtcbiAgICAgIGNsb2NrID0geyAnbm93JzogZnVuY3Rpb24gKCkgeyByZXR1cm4gKyhuZXcgRGF0ZSk7IH0gfTtcbiAgICB9XG5cbiAgICAvLyBUaGUgbG9vcCBpcyBicm9rZW4gaW50byBhIHNlcmllcyBvZiBjb250aW51YXRpb25zIHRvIG1ha2Ugc3VyZSB0aGF0IHdlXG4gICAgLy8gZG9uJ3QgbWFrZSB0aGUgYnJvd3NlciB1bnJlc3BvbnNpdmUgd2hlbiByZXdyaXRpbmcgYSBsYXJnZSBwYWdlLlxuICAgIHZhciBrID0gMDtcbiAgICB2YXIgcHJldHR5UHJpbnRpbmdKb2I7XG5cbiAgICB2YXIgbGFuZ0V4dGVuc2lvblJlID0gL1xcYmxhbmcoPzp1YWdlKT8tKFtcXHcuXSspKD8hXFxTKS87XG4gICAgdmFyIHByZXR0eVByaW50UmUgPSAvXFxicHJldHR5cHJpbnRcXGIvO1xuICAgIHZhciBwcmV0dHlQcmludGVkUmUgPSAvXFxicHJldHR5cHJpbnRlZFxcYi87XG4gICAgdmFyIHByZWZvcm1hdHRlZFRhZ05hbWVSZSA9IC9wcmV8eG1wL2k7XG4gICAgdmFyIGNvZGVSZSA9IC9eY29kZSQvaTtcbiAgICB2YXIgcHJlQ29kZVhtcFJlID0gL14oPzpwcmV8Y29kZXx4bXApJC9pO1xuICAgIHZhciBFTVBUWSA9IHt9O1xuXG4gICAgZnVuY3Rpb24gZG9Xb3JrKCkge1xuICAgICAgdmFyIGVuZFRpbWUgPSAod2luWydQUl9TSE9VTERfVVNFX0NPTlRJTlVBVElPTiddID9cbiAgICAgICAgICAgICAgICAgICAgIGNsb2NrWydub3cnXSgpICsgMjUwIC8qIG1zICovIDpcbiAgICAgICAgICAgICAgICAgICAgIEluZmluaXR5KTtcbiAgICAgIGZvciAoOyBrIDwgZWxlbWVudHMubGVuZ3RoICYmIGNsb2NrWydub3cnXSgpIDwgZW5kVGltZTsgaysrKSB7XG4gICAgICAgIHZhciBjcyA9IGVsZW1lbnRzW2tdO1xuXG4gICAgICAgIC8vIExvb2sgZm9yIGEgcHJlY2VkaW5nIGNvbW1lbnQgbGlrZVxuICAgICAgICAvLyA8P3ByZXR0aWZ5IGxhbmc9XCIuLi5cIiBsaW5lbnVtcz1cIi4uLlwiPz5cbiAgICAgICAgdmFyIGF0dHJzID0gRU1QVFk7XG4gICAgICAgIHtcbiAgICAgICAgICBmb3IgKHZhciBwcmVjZWRlciA9IGNzOyAocHJlY2VkZXIgPSBwcmVjZWRlci5wcmV2aW91c1NpYmxpbmcpOykge1xuICAgICAgICAgICAgdmFyIG50ID0gcHJlY2VkZXIubm9kZVR5cGU7XG4gICAgICAgICAgICAvLyA8P2Zvbz8+IGlzIHBhcnNlZCBieSBIVE1MIDUgdG8gYSBjb21tZW50IG5vZGUgKDgpXG4gICAgICAgICAgICAvLyBsaWtlIDwhLS0/Zm9vPy0tPiwgYnV0IGluIFhNTCBpcyBhIHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb25cbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IChudCA9PT0gNyB8fCBudCA9PT0gOCkgJiYgcHJlY2VkZXIubm9kZVZhbHVlO1xuICAgICAgICAgICAgaWYgKHZhbHVlXG4gICAgICAgICAgICAgICAgPyAhL15cXD8/cHJldHRpZnlcXGIvLnRlc3QodmFsdWUpXG4gICAgICAgICAgICAgICAgOiAobnQgIT09IDMgfHwgL1xcUy8udGVzdChwcmVjZWRlci5ub2RlVmFsdWUpKSkge1xuICAgICAgICAgICAgICAvLyBTa2lwIG92ZXIgd2hpdGUtc3BhY2UgdGV4dCBub2RlcyBidXQgbm90IG90aGVycy5cbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgYXR0cnMgPSB7fTtcbiAgICAgICAgICAgICAgdmFsdWUucmVwbGFjZShcbiAgICAgICAgICAgICAgICAgIC9cXGIoXFx3Kyk9KFtcXHc6LiUrLV0rKS9nLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChfLCBuYW1lLCB2YWx1ZSkgeyBhdHRyc1tuYW1lXSA9IHZhbHVlOyB9KTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9IGNzLmNsYXNzTmFtZTtcbiAgICAgICAgaWYgKChhdHRycyAhPT0gRU1QVFkgfHwgcHJldHR5UHJpbnRSZS50ZXN0KGNsYXNzTmFtZSkpXG4gICAgICAgICAgICAvLyBEb24ndCByZWRvIHRoaXMgaWYgd2UndmUgYWxyZWFkeSBkb25lIGl0LlxuICAgICAgICAgICAgLy8gVGhpcyBhbGxvd3MgcmVjYWxsaW5nIHByZXR0eSBwcmludCB0byBqdXN0IHByZXR0eXByaW50IGVsZW1lbnRzXG4gICAgICAgICAgICAvLyB0aGF0IGhhdmUgYmVlbiBhZGRlZCB0byB0aGUgcGFnZSBzaW5jZSBsYXN0IGNhbGwuXG4gICAgICAgICAgICAmJiAhcHJldHR5UHJpbnRlZFJlLnRlc3QoY2xhc3NOYW1lKSkge1xuXG4gICAgICAgICAgLy8gbWFrZSBzdXJlIHRoaXMgaXMgbm90IG5lc3RlZCBpbiBhbiBhbHJlYWR5IHByZXR0aWZpZWQgZWxlbWVudFxuICAgICAgICAgIHZhciBuZXN0ZWQgPSBmYWxzZTtcbiAgICAgICAgICBmb3IgKHZhciBwID0gY3MucGFyZW50Tm9kZTsgcDsgcCA9IHAucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgdmFyIHRuID0gcC50YWdOYW1lO1xuICAgICAgICAgICAgaWYgKHByZUNvZGVYbXBSZS50ZXN0KHRuKVxuICAgICAgICAgICAgICAgICYmIHAuY2xhc3NOYW1lICYmIHByZXR0eVByaW50UmUudGVzdChwLmNsYXNzTmFtZSkpIHtcbiAgICAgICAgICAgICAgbmVzdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmVzdGVkKSB7XG4gICAgICAgICAgICAvLyBNYXJrIGRvbmUuICBJZiB3ZSBmYWlsIHRvIHByZXR0eXByaW50IGZvciB3aGF0ZXZlciByZWFzb24sXG4gICAgICAgICAgICAvLyB3ZSBzaG91bGRuJ3QgdHJ5IGFnYWluLlxuICAgICAgICAgICAgY3MuY2xhc3NOYW1lICs9ICcgcHJldHR5cHJpbnRlZCc7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZSBjbGFzc2VzIGluY2x1ZGVzIGEgbGFuZ3VhZ2UgZXh0ZW5zaW9ucywgdXNlIGl0LlxuICAgICAgICAgICAgLy8gTGFuZ3VhZ2UgZXh0ZW5zaW9ucyBjYW4gYmUgc3BlY2lmaWVkIGxpa2VcbiAgICAgICAgICAgIC8vICAgICA8cHJlIGNsYXNzPVwicHJldHR5cHJpbnQgbGFuZy1jcHBcIj5cbiAgICAgICAgICAgIC8vIHRoZSBsYW5ndWFnZSBleHRlbnNpb24gXCJjcHBcIiBpcyB1c2VkIHRvIGZpbmQgYSBsYW5ndWFnZSBoYW5kbGVyXG4gICAgICAgICAgICAvLyBhcyBwYXNzZWQgdG8gUFIucmVnaXN0ZXJMYW5nSGFuZGxlci5cbiAgICAgICAgICAgIC8vIEhUTUw1IHJlY29tbWVuZHMgdGhhdCBhIGxhbmd1YWdlIGJlIHNwZWNpZmllZCB1c2luZyBcImxhbmd1YWdlLVwiXG4gICAgICAgICAgICAvLyBhcyB0aGUgcHJlZml4IGluc3RlYWQuICBHb29nbGUgQ29kZSBQcmV0dGlmeSBzdXBwb3J0cyBib3RoLlxuICAgICAgICAgICAgLy8gaHR0cDovL2Rldi53My5vcmcvaHRtbDUvc3BlYy1hdXRob3Itdmlldy90aGUtY29kZS1lbGVtZW50Lmh0bWxcbiAgICAgICAgICAgIHZhciBsYW5nRXh0ZW5zaW9uID0gYXR0cnNbJ2xhbmcnXTtcbiAgICAgICAgICAgIGlmICghbGFuZ0V4dGVuc2lvbikge1xuICAgICAgICAgICAgICBsYW5nRXh0ZW5zaW9uID0gY2xhc3NOYW1lLm1hdGNoKGxhbmdFeHRlbnNpb25SZSk7XG4gICAgICAgICAgICAgIC8vIFN1cHBvcnQgPHByZSBjbGFzcz1cInByZXR0eXByaW50XCI+PGNvZGUgY2xhc3M9XCJsYW5ndWFnZS1jXCI+XG4gICAgICAgICAgICAgIHZhciB3cmFwcGVyO1xuICAgICAgICAgICAgICBpZiAoIWxhbmdFeHRlbnNpb24gJiYgKHdyYXBwZXIgPSBjaGlsZENvbnRlbnRXcmFwcGVyKGNzKSlcbiAgICAgICAgICAgICAgICAgICYmIGNvZGVSZS50ZXN0KHdyYXBwZXIudGFnTmFtZSkpIHtcbiAgICAgICAgICAgICAgICBsYW5nRXh0ZW5zaW9uID0gd3JhcHBlci5jbGFzc05hbWUubWF0Y2gobGFuZ0V4dGVuc2lvblJlKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmIChsYW5nRXh0ZW5zaW9uKSB7IGxhbmdFeHRlbnNpb24gPSBsYW5nRXh0ZW5zaW9uWzFdOyB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwcmVmb3JtYXR0ZWQ7XG4gICAgICAgICAgICBpZiAocHJlZm9ybWF0dGVkVGFnTmFtZVJlLnRlc3QoY3MudGFnTmFtZSkpIHtcbiAgICAgICAgICAgICAgcHJlZm9ybWF0dGVkID0gMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHZhciBjdXJyZW50U3R5bGUgPSBjc1snY3VycmVudFN0eWxlJ107XG4gICAgICAgICAgICAgIHZhciBkZWZhdWx0VmlldyA9IGRvYy5kZWZhdWx0VmlldztcbiAgICAgICAgICAgICAgdmFyIHdoaXRlc3BhY2UgPSAoXG4gICAgICAgICAgICAgICAgICBjdXJyZW50U3R5bGVcbiAgICAgICAgICAgICAgICAgID8gY3VycmVudFN0eWxlWyd3aGl0ZVNwYWNlJ11cbiAgICAgICAgICAgICAgICAgIDogKGRlZmF1bHRWaWV3XG4gICAgICAgICAgICAgICAgICAgICAmJiBkZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKVxuICAgICAgICAgICAgICAgICAgPyBkZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKGNzLCBudWxsKVxuICAgICAgICAgICAgICAgICAgLmdldFByb3BlcnR5VmFsdWUoJ3doaXRlLXNwYWNlJylcbiAgICAgICAgICAgICAgICAgIDogMCk7XG4gICAgICAgICAgICAgIHByZWZvcm1hdHRlZCA9IHdoaXRlc3BhY2VcbiAgICAgICAgICAgICAgICAgICYmICdwcmUnID09PSB3aGl0ZXNwYWNlLnN1YnN0cmluZygwLCAzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTG9vayBmb3IgYSBjbGFzcyBsaWtlIGxpbmVudW1zIG9yIGxpbmVudW1zOjxuPiB3aGVyZSA8bj4gaXMgdGhlXG4gICAgICAgICAgICAvLyAxLWluZGV4ZWQgbnVtYmVyIG9mIHRoZSBmaXJzdCBsaW5lLlxuICAgICAgICAgICAgdmFyIGxpbmVOdW1zID0gYXR0cnNbJ2xpbmVudW1zJ107XG4gICAgICAgICAgICBpZiAoIShsaW5lTnVtcyA9IGxpbmVOdW1zID09PSAndHJ1ZScgfHwgK2xpbmVOdW1zKSkge1xuICAgICAgICAgICAgICBsaW5lTnVtcyA9IGNsYXNzTmFtZS5tYXRjaCgvXFxibGluZW51bXNcXGIoPzo6KFxcZCspKT8vKTtcbiAgICAgICAgICAgICAgbGluZU51bXMgPVxuICAgICAgICAgICAgICAgIGxpbmVOdW1zXG4gICAgICAgICAgICAgICAgPyBsaW5lTnVtc1sxXSAmJiBsaW5lTnVtc1sxXS5sZW5ndGhcbiAgICAgICAgICAgICAgICAgID8gK2xpbmVOdW1zWzFdIDogdHJ1ZVxuICAgICAgICAgICAgICAgIDogZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGluZU51bXMpIHsgbnVtYmVyTGluZXMoY3MsIGxpbmVOdW1zLCBwcmVmb3JtYXR0ZWQpOyB9XG5cbiAgICAgICAgICAgIC8vIGRvIHRoZSBwcmV0dHkgcHJpbnRpbmdcbiAgICAgICAgICAgIHByZXR0eVByaW50aW5nSm9iID0ge1xuICAgICAgICAgICAgICBsYW5nRXh0ZW5zaW9uOiBsYW5nRXh0ZW5zaW9uLFxuICAgICAgICAgICAgICBzb3VyY2VOb2RlOiBjcyxcbiAgICAgICAgICAgICAgbnVtYmVyTGluZXM6IGxpbmVOdW1zLFxuICAgICAgICAgICAgICBwcmU6IHByZWZvcm1hdHRlZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGFwcGx5RGVjb3JhdG9yKHByZXR0eVByaW50aW5nSm9iKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChrIDwgZWxlbWVudHMubGVuZ3RoKSB7XG4gICAgICAgIC8vIGZpbmlzaCB1cCBpbiBhIGNvbnRpbnVhdGlvblxuICAgICAgICBzZXRUaW1lb3V0KGRvV29yaywgMjUwKTtcbiAgICAgIH0gZWxzZSBpZiAoJ2Z1bmN0aW9uJyA9PT0gdHlwZW9mIG9wdF93aGVuRG9uZSkge1xuICAgICAgICBvcHRfd2hlbkRvbmUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBkb1dvcmsoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb250YWlucyBmdW5jdGlvbnMgZm9yIGNyZWF0aW5nIGFuZCByZWdpc3RlcmluZyBuZXcgbGFuZ3VhZ2UgaGFuZGxlcnMuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICB2YXIgUFIgPSB3aW5bJ1BSJ10gPSB7XG4gICAgICAgICdjcmVhdGVTaW1wbGVMZXhlcic6IGNyZWF0ZVNpbXBsZUxleGVyLFxuICAgICAgICAncmVnaXN0ZXJMYW5nSGFuZGxlcic6IHJlZ2lzdGVyTGFuZ0hhbmRsZXIsXG4gICAgICAgICdzb3VyY2VEZWNvcmF0b3InOiBzb3VyY2VEZWNvcmF0b3IsXG4gICAgICAgICdQUl9BVFRSSUJfTkFNRSc6IFBSX0FUVFJJQl9OQU1FLFxuICAgICAgICAnUFJfQVRUUklCX1ZBTFVFJzogUFJfQVRUUklCX1ZBTFVFLFxuICAgICAgICAnUFJfQ09NTUVOVCc6IFBSX0NPTU1FTlQsXG4gICAgICAgICdQUl9ERUNMQVJBVElPTic6IFBSX0RFQ0xBUkFUSU9OLFxuICAgICAgICAnUFJfS0VZV09SRCc6IFBSX0tFWVdPUkQsXG4gICAgICAgICdQUl9MSVRFUkFMJzogUFJfTElURVJBTCxcbiAgICAgICAgJ1BSX05PQ09ERSc6IFBSX05PQ09ERSxcbiAgICAgICAgJ1BSX1BMQUlOJzogUFJfUExBSU4sXG4gICAgICAgICdQUl9QVU5DVFVBVElPTic6IFBSX1BVTkNUVUFUSU9OLFxuICAgICAgICAnUFJfU09VUkNFJzogUFJfU09VUkNFLFxuICAgICAgICAnUFJfU1RSSU5HJzogUFJfU1RSSU5HLFxuICAgICAgICAnUFJfVEFHJzogUFJfVEFHLFxuICAgICAgICAnUFJfVFlQRSc6IFBSX1RZUEUsXG4gICAgICAgICdwcmV0dHlQcmludE9uZSc6XG4gICAgICAgICAgIElOX0dMT0JBTF9TQ09QRVxuICAgICAgICAgICAgID8gKHdpblsncHJldHR5UHJpbnRPbmUnXSA9ICRwcmV0dHlQcmludE9uZSlcbiAgICAgICAgICAgICA6IChwcmV0dHlQcmludE9uZSA9ICRwcmV0dHlQcmludE9uZSksXG4gICAgICAgICdwcmV0dHlQcmludCc6IHByZXR0eVByaW50ID1cbiAgICAgICAgICAgSU5fR0xPQkFMX1NDT1BFXG4gICAgICAgICAgICAgPyAod2luWydwcmV0dHlQcmludCddID0gJHByZXR0eVByaW50KVxuICAgICAgICAgICAgIDogKHByZXR0eVByaW50ID0gJHByZXR0eVByaW50KVxuICAgICAgfTtcblxuICAvLyBNYWtlIFBSIGF2YWlsYWJsZSB2aWEgdGhlIEFzeW5jaHJvbm91cyBNb2R1bGUgRGVmaW5pdGlvbiAoQU1EKSBBUEkuXG4gIC8vIFBlciBodHRwczovL2dpdGh1Yi5jb20vYW1kanMvYW1kanMtYXBpL3dpa2kvQU1EOlxuICAvLyBUaGUgQXN5bmNocm9ub3VzIE1vZHVsZSBEZWZpbml0aW9uIChBTUQpIEFQSSBzcGVjaWZpZXMgYVxuICAvLyBtZWNoYW5pc20gZm9yIGRlZmluaW5nIG1vZHVsZXMgc3VjaCB0aGF0IHRoZSBtb2R1bGUgYW5kIGl0c1xuICAvLyBkZXBlbmRlbmNpZXMgY2FuIGJlIGFzeW5jaHJvbm91c2x5IGxvYWRlZC5cbiAgLy8gLi4uXG4gIC8vIFRvIGFsbG93IGEgY2xlYXIgaW5kaWNhdG9yIHRoYXQgYSBnbG9iYWwgZGVmaW5lIGZ1bmN0aW9uIChhc1xuICAvLyBuZWVkZWQgZm9yIHNjcmlwdCBzcmMgYnJvd3NlciBsb2FkaW5nKSBjb25mb3JtcyB0byB0aGUgQU1EIEFQSSxcbiAgLy8gYW55IGdsb2JhbCBkZWZpbmUgZnVuY3Rpb24gU0hPVUxEIGhhdmUgYSBwcm9wZXJ0eSBjYWxsZWQgXCJhbWRcIlxuICAvLyB3aG9zZSB2YWx1ZSBpcyBhbiBvYmplY3QuIFRoaXMgaGVscHMgYXZvaWQgY29uZmxpY3Qgd2l0aCBhbnlcbiAgLy8gb3RoZXIgZXhpc3RpbmcgSmF2YVNjcmlwdCBjb2RlIHRoYXQgY291bGQgaGF2ZSBkZWZpbmVkIGEgZGVmaW5lKClcbiAgLy8gZnVuY3Rpb24gdGhhdCBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBBTUQgQVBJLlxuICBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZVsnYW1kJ10pIHtcbiAgICBkZWZpbmUoXCJnb29nbGUtY29kZS1wcmV0dGlmeVwiLCBbXSwgZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIFBSOyBcbiAgICB9KTtcbiAgfVxufSkoKTtcbiIsIjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpIDpcbiAgICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoZmFjdG9yeSkgOlxuICAgIGdsb2JhbC5tb21lbnQgPSBmYWN0b3J5KClcbn0odGhpcywgKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG4gICAgdmFyIGhvb2tDYWxsYmFjaztcblxuICAgIGZ1bmN0aW9uIGhvb2tzKCkge1xuICAgICAgICByZXR1cm4gaG9va0NhbGxiYWNrLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgfVxuXG4gICAgLy8gVGhpcyBpcyBkb25lIHRvIHJlZ2lzdGVyIHRoZSBtZXRob2QgY2FsbGVkIHdpdGggbW9tZW50KClcbiAgICAvLyB3aXRob3V0IGNyZWF0aW5nIGNpcmN1bGFyIGRlcGVuZGVuY2llcy5cbiAgICBmdW5jdGlvbiBzZXRIb29rQ2FsbGJhY2soY2FsbGJhY2spIHtcbiAgICAgICAgaG9va0NhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNBcnJheShpbnB1dCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgaW5wdXQgaW5zdGFuY2VvZiBBcnJheSB8fFxuICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgQXJyYXldJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzT2JqZWN0KGlucHV0KSB7XG4gICAgICAgIC8vIElFOCB3aWxsIHRyZWF0IHVuZGVmaW5lZCBhbmQgbnVsbCBhcyBvYmplY3QgaWYgaXQgd2Fzbid0IGZvclxuICAgICAgICAvLyBpbnB1dCAhPSBudWxsXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBpbnB1dCAhPSBudWxsICYmXG4gICAgICAgICAgICBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaW5wdXQpID09PSAnW29iamVjdCBPYmplY3RdJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhc093blByb3AoYSwgYikge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGEsIGIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzT2JqZWN0RW1wdHkob2JqKSB7XG4gICAgICAgIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcykge1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKG9iaikubGVuZ3RoID09PSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGs7XG4gICAgICAgICAgICBmb3IgKGsgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc093blByb3Aob2JqLCBrKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1VuZGVmaW5lZChpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQgPT09IHZvaWQgMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc051bWJlcihpbnB1dCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgTnVtYmVyXSdcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0RhdGUoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGlucHV0IGluc3RhbmNlb2YgRGF0ZSB8fFxuICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgRGF0ZV0nXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFwKGFyciwgZm4pIHtcbiAgICAgICAgdmFyIHJlcyA9IFtdLFxuICAgICAgICAgICAgaTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGFyci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgcmVzLnB1c2goZm4oYXJyW2ldLCBpKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgICAgICBmb3IgKHZhciBpIGluIGIpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wKGIsIGkpKSB7XG4gICAgICAgICAgICAgICAgYVtpXSA9IGJbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFzT3duUHJvcChiLCAndG9TdHJpbmcnKSkge1xuICAgICAgICAgICAgYS50b1N0cmluZyA9IGIudG9TdHJpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFzT3duUHJvcChiLCAndmFsdWVPZicpKSB7XG4gICAgICAgICAgICBhLnZhbHVlT2YgPSBiLnZhbHVlT2Y7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVVVEMoaW5wdXQsIGZvcm1hdCwgbG9jYWxlLCBzdHJpY3QpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsT3JVVEMoaW5wdXQsIGZvcm1hdCwgbG9jYWxlLCBzdHJpY3QsIHRydWUpLnV0YygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlZmF1bHRQYXJzaW5nRmxhZ3MoKSB7XG4gICAgICAgIC8vIFdlIG5lZWQgdG8gZGVlcCBjbG9uZSB0aGlzIG9iamVjdC5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGVtcHR5OiBmYWxzZSxcbiAgICAgICAgICAgIHVudXNlZFRva2VuczogW10sXG4gICAgICAgICAgICB1bnVzZWRJbnB1dDogW10sXG4gICAgICAgICAgICBvdmVyZmxvdzogLTIsXG4gICAgICAgICAgICBjaGFyc0xlZnRPdmVyOiAwLFxuICAgICAgICAgICAgbnVsbElucHV0OiBmYWxzZSxcbiAgICAgICAgICAgIGludmFsaWRFcmE6IG51bGwsXG4gICAgICAgICAgICBpbnZhbGlkTW9udGg6IG51bGwsXG4gICAgICAgICAgICBpbnZhbGlkRm9ybWF0OiBmYWxzZSxcbiAgICAgICAgICAgIHVzZXJJbnZhbGlkYXRlZDogZmFsc2UsXG4gICAgICAgICAgICBpc286IGZhbHNlLFxuICAgICAgICAgICAgcGFyc2VkRGF0ZVBhcnRzOiBbXSxcbiAgICAgICAgICAgIGVyYTogbnVsbCxcbiAgICAgICAgICAgIG1lcmlkaWVtOiBudWxsLFxuICAgICAgICAgICAgcmZjMjgyMjogZmFsc2UsXG4gICAgICAgICAgICB3ZWVrZGF5TWlzbWF0Y2g6IGZhbHNlLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFBhcnNpbmdGbGFncyhtKSB7XG4gICAgICAgIGlmIChtLl9wZiA9PSBudWxsKSB7XG4gICAgICAgICAgICBtLl9wZiA9IGRlZmF1bHRQYXJzaW5nRmxhZ3MoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbS5fcGY7XG4gICAgfVxuXG4gICAgdmFyIHNvbWU7XG4gICAgaWYgKEFycmF5LnByb3RvdHlwZS5zb21lKSB7XG4gICAgICAgIHNvbWUgPSBBcnJheS5wcm90b3R5cGUuc29tZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzb21lID0gZnVuY3Rpb24gKGZ1bikge1xuICAgICAgICAgICAgdmFyIHQgPSBPYmplY3QodGhpcyksXG4gICAgICAgICAgICAgICAgbGVuID0gdC5sZW5ndGggPj4+IDAsXG4gICAgICAgICAgICAgICAgaTtcblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgaW4gdCAmJiBmdW4uY2FsbCh0aGlzLCB0W2ldLCBpLCB0KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkKG0pIHtcbiAgICAgICAgaWYgKG0uX2lzVmFsaWQgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGZsYWdzID0gZ2V0UGFyc2luZ0ZsYWdzKG0pLFxuICAgICAgICAgICAgICAgIHBhcnNlZFBhcnRzID0gc29tZS5jYWxsKGZsYWdzLnBhcnNlZERhdGVQYXJ0cywgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGkgIT0gbnVsbDtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBpc05vd1ZhbGlkID1cbiAgICAgICAgICAgICAgICAgICAgIWlzTmFOKG0uX2QuZ2V0VGltZSgpKSAmJlxuICAgICAgICAgICAgICAgICAgICBmbGFncy5vdmVyZmxvdyA8IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgIWZsYWdzLmVtcHR5ICYmXG4gICAgICAgICAgICAgICAgICAgICFmbGFncy5pbnZhbGlkRXJhICYmXG4gICAgICAgICAgICAgICAgICAgICFmbGFncy5pbnZhbGlkTW9udGggJiZcbiAgICAgICAgICAgICAgICAgICAgIWZsYWdzLmludmFsaWRXZWVrZGF5ICYmXG4gICAgICAgICAgICAgICAgICAgICFmbGFncy53ZWVrZGF5TWlzbWF0Y2ggJiZcbiAgICAgICAgICAgICAgICAgICAgIWZsYWdzLm51bGxJbnB1dCAmJlxuICAgICAgICAgICAgICAgICAgICAhZmxhZ3MuaW52YWxpZEZvcm1hdCAmJlxuICAgICAgICAgICAgICAgICAgICAhZmxhZ3MudXNlckludmFsaWRhdGVkICYmXG4gICAgICAgICAgICAgICAgICAgICghZmxhZ3MubWVyaWRpZW0gfHwgKGZsYWdzLm1lcmlkaWVtICYmIHBhcnNlZFBhcnRzKSk7XG5cbiAgICAgICAgICAgIGlmIChtLl9zdHJpY3QpIHtcbiAgICAgICAgICAgICAgICBpc05vd1ZhbGlkID1cbiAgICAgICAgICAgICAgICAgICAgaXNOb3dWYWxpZCAmJlxuICAgICAgICAgICAgICAgICAgICBmbGFncy5jaGFyc0xlZnRPdmVyID09PSAwICYmXG4gICAgICAgICAgICAgICAgICAgIGZsYWdzLnVudXNlZFRva2Vucy5sZW5ndGggPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgZmxhZ3MuYmlnSG91ciA9PT0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoT2JqZWN0LmlzRnJvemVuID09IG51bGwgfHwgIU9iamVjdC5pc0Zyb3plbihtKSkge1xuICAgICAgICAgICAgICAgIG0uX2lzVmFsaWQgPSBpc05vd1ZhbGlkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNOb3dWYWxpZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbS5faXNWYWxpZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVJbnZhbGlkKGZsYWdzKSB7XG4gICAgICAgIHZhciBtID0gY3JlYXRlVVRDKE5hTik7XG4gICAgICAgIGlmIChmbGFncyAhPSBudWxsKSB7XG4gICAgICAgICAgICBleHRlbmQoZ2V0UGFyc2luZ0ZsYWdzKG0pLCBmbGFncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MobSkudXNlckludmFsaWRhdGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtO1xuICAgIH1cblxuICAgIC8vIFBsdWdpbnMgdGhhdCBhZGQgcHJvcGVydGllcyBzaG91bGQgYWxzbyBhZGQgdGhlIGtleSBoZXJlIChudWxsIHZhbHVlKSxcbiAgICAvLyBzbyB3ZSBjYW4gcHJvcGVybHkgY2xvbmUgb3Vyc2VsdmVzLlxuICAgIHZhciBtb21lbnRQcm9wZXJ0aWVzID0gKGhvb2tzLm1vbWVudFByb3BlcnRpZXMgPSBbXSksXG4gICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIGNvcHlDb25maWcodG8sIGZyb20pIHtcbiAgICAgICAgdmFyIGksIHByb3AsIHZhbDtcblxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2lzQU1vbWVudE9iamVjdCkpIHtcbiAgICAgICAgICAgIHRvLl9pc0FNb21lbnRPYmplY3QgPSBmcm9tLl9pc0FNb21lbnRPYmplY3Q7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9pKSkge1xuICAgICAgICAgICAgdG8uX2kgPSBmcm9tLl9pO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fZikpIHtcbiAgICAgICAgICAgIHRvLl9mID0gZnJvbS5fZjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2wpKSB7XG4gICAgICAgICAgICB0by5fbCA9IGZyb20uX2w7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9zdHJpY3QpKSB7XG4gICAgICAgICAgICB0by5fc3RyaWN0ID0gZnJvbS5fc3RyaWN0O1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fdHptKSkge1xuICAgICAgICAgICAgdG8uX3R6bSA9IGZyb20uX3R6bTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2lzVVRDKSkge1xuICAgICAgICAgICAgdG8uX2lzVVRDID0gZnJvbS5faXNVVEM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9vZmZzZXQpKSB7XG4gICAgICAgICAgICB0by5fb2Zmc2V0ID0gZnJvbS5fb2Zmc2V0O1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fcGYpKSB7XG4gICAgICAgICAgICB0by5fcGYgPSBnZXRQYXJzaW5nRmxhZ3MoZnJvbSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9sb2NhbGUpKSB7XG4gICAgICAgICAgICB0by5fbG9jYWxlID0gZnJvbS5fbG9jYWxlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1vbWVudFByb3BlcnRpZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IG1vbWVudFByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwcm9wID0gbW9tZW50UHJvcGVydGllc1tpXTtcbiAgICAgICAgICAgICAgICB2YWwgPSBmcm9tW3Byb3BdO1xuICAgICAgICAgICAgICAgIGlmICghaXNVbmRlZmluZWQodmFsKSkge1xuICAgICAgICAgICAgICAgICAgICB0b1twcm9wXSA9IHZhbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdG87XG4gICAgfVxuXG4gICAgLy8gTW9tZW50IHByb3RvdHlwZSBvYmplY3RcbiAgICBmdW5jdGlvbiBNb21lbnQoY29uZmlnKSB7XG4gICAgICAgIGNvcHlDb25maWcodGhpcywgY29uZmlnKTtcbiAgICAgICAgdGhpcy5fZCA9IG5ldyBEYXRlKGNvbmZpZy5fZCAhPSBudWxsID8gY29uZmlnLl9kLmdldFRpbWUoKSA6IE5hTik7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuX2QgPSBuZXcgRGF0ZShOYU4pO1xuICAgICAgICB9XG4gICAgICAgIC8vIFByZXZlbnQgaW5maW5pdGUgbG9vcCBpbiBjYXNlIHVwZGF0ZU9mZnNldCBjcmVhdGVzIG5ldyBtb21lbnRcbiAgICAgICAgLy8gb2JqZWN0cy5cbiAgICAgICAgaWYgKHVwZGF0ZUluUHJvZ3Jlc3MgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICB1cGRhdGVJblByb2dyZXNzID0gdHJ1ZTtcbiAgICAgICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzKTtcbiAgICAgICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzTW9tZW50KG9iaikge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgb2JqIGluc3RhbmNlb2YgTW9tZW50IHx8IChvYmogIT0gbnVsbCAmJiBvYmouX2lzQU1vbWVudE9iamVjdCAhPSBudWxsKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHdhcm4obXNnKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGhvb2tzLnN1cHByZXNzRGVwcmVjYXRpb25XYXJuaW5ncyA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgIHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgY29uc29sZS53YXJuXG4gICAgICAgICkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdEZXByZWNhdGlvbiB3YXJuaW5nOiAnICsgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlcHJlY2F0ZShtc2csIGZuKSB7XG4gICAgICAgIHZhciBmaXJzdFRpbWUgPSB0cnVlO1xuXG4gICAgICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaG9va3MuZGVwcmVjYXRpb25IYW5kbGVyKG51bGwsIG1zZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlyc3RUaW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgYXJnLFxuICAgICAgICAgICAgICAgICAgICBpLFxuICAgICAgICAgICAgICAgICAgICBrZXk7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBhcmcgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhcmd1bWVudHNbaV0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgKz0gJ1xcblsnICsgaSArICddICc7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGtleSBpbiBhcmd1bWVudHNbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaGFzT3duUHJvcChhcmd1bWVudHNbMF0sIGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJnICs9IGtleSArICc6ICcgKyBhcmd1bWVudHNbMF1ba2V5XSArICcsICc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJnLnNsaWNlKDAsIC0yKTsgLy8gUmVtb3ZlIHRyYWlsaW5nIGNvbW1hIGFuZCBzcGFjZVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGFyZ3MucHVzaChhcmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3YXJuKFxuICAgICAgICAgICAgICAgICAgICBtc2cgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ1xcbkFyZ3VtZW50czogJyArXG4gICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmdzKS5qb2luKCcnKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAnXFxuJyArXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgRXJyb3IoKS5zdGFja1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgZmlyc3RUaW1lID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSwgZm4pO1xuICAgIH1cblxuICAgIHZhciBkZXByZWNhdGlvbnMgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGRlcHJlY2F0ZVNpbXBsZShuYW1lLCBtc2cpIHtcbiAgICAgICAgaWYgKGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciAhPSBudWxsKSB7XG4gICAgICAgICAgICBob29rcy5kZXByZWNhdGlvbkhhbmRsZXIobmFtZSwgbXNnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWRlcHJlY2F0aW9uc1tuYW1lXSkge1xuICAgICAgICAgICAgd2Fybihtc2cpO1xuICAgICAgICAgICAgZGVwcmVjYXRpb25zW25hbWVdID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLnN1cHByZXNzRGVwcmVjYXRpb25XYXJuaW5ncyA9IGZhbHNlO1xuICAgIGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciA9IG51bGw7XG5cbiAgICBmdW5jdGlvbiBpc0Z1bmN0aW9uKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAodHlwZW9mIEZ1bmN0aW9uICE9PSAndW5kZWZpbmVkJyAmJiBpbnB1dCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB8fFxuICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgRnVuY3Rpb25dJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldChjb25maWcpIHtcbiAgICAgICAgdmFyIHByb3AsIGk7XG4gICAgICAgIGZvciAoaSBpbiBjb25maWcpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wKGNvbmZpZywgaSkpIHtcbiAgICAgICAgICAgICAgICBwcm9wID0gY29uZmlnW2ldO1xuICAgICAgICAgICAgICAgIGlmIChpc0Z1bmN0aW9uKHByb3ApKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXNbaV0gPSBwcm9wO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXNbJ18nICsgaV0gPSBwcm9wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gICAgICAgIC8vIExlbmllbnQgb3JkaW5hbCBwYXJzaW5nIGFjY2VwdHMganVzdCBhIG51bWJlciBpbiBhZGRpdGlvbiB0b1xuICAgICAgICAvLyBudW1iZXIgKyAocG9zc2libHkpIHN0dWZmIGNvbWluZyBmcm9tIF9kYXlPZk1vbnRoT3JkaW5hbFBhcnNlLlxuICAgICAgICAvLyBUT0RPOiBSZW1vdmUgXCJvcmRpbmFsUGFyc2VcIiBmYWxsYmFjayBpbiBuZXh0IG1ham9yIHJlbGVhc2UuXG4gICAgICAgIHRoaXMuX2RheU9mTW9udGhPcmRpbmFsUGFyc2VMZW5pZW50ID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICh0aGlzLl9kYXlPZk1vbnRoT3JkaW5hbFBhcnNlLnNvdXJjZSB8fCB0aGlzLl9vcmRpbmFsUGFyc2Uuc291cmNlKSArXG4gICAgICAgICAgICAgICAgJ3wnICtcbiAgICAgICAgICAgICAgICAvXFxkezEsMn0vLnNvdXJjZVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlQ29uZmlncyhwYXJlbnRDb25maWcsIGNoaWxkQ29uZmlnKSB7XG4gICAgICAgIHZhciByZXMgPSBleHRlbmQoe30sIHBhcmVudENvbmZpZyksXG4gICAgICAgICAgICBwcm9wO1xuICAgICAgICBmb3IgKHByb3AgaW4gY2hpbGRDb25maWcpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wKGNoaWxkQ29uZmlnLCBwcm9wKSkge1xuICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwYXJlbnRDb25maWdbcHJvcF0pICYmIGlzT2JqZWN0KGNoaWxkQ29uZmlnW3Byb3BdKSkge1xuICAgICAgICAgICAgICAgICAgICByZXNbcHJvcF0gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgZXh0ZW5kKHJlc1twcm9wXSwgcGFyZW50Q29uZmlnW3Byb3BdKTtcbiAgICAgICAgICAgICAgICAgICAgZXh0ZW5kKHJlc1twcm9wXSwgY2hpbGRDb25maWdbcHJvcF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGRDb25maWdbcHJvcF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXNbcHJvcF0gPSBjaGlsZENvbmZpZ1twcm9wXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgcmVzW3Byb3BdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHByb3AgaW4gcGFyZW50Q29uZmlnKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgaGFzT3duUHJvcChwYXJlbnRDb25maWcsIHByb3ApICYmXG4gICAgICAgICAgICAgICAgIWhhc093blByb3AoY2hpbGRDb25maWcsIHByb3ApICYmXG4gICAgICAgICAgICAgICAgaXNPYmplY3QocGFyZW50Q29uZmlnW3Byb3BdKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgLy8gbWFrZSBzdXJlIGNoYW5nZXMgdG8gcHJvcGVydGllcyBkb24ndCBtb2RpZnkgcGFyZW50IGNvbmZpZ1xuICAgICAgICAgICAgICAgIHJlc1twcm9wXSA9IGV4dGVuZCh7fSwgcmVzW3Byb3BdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIExvY2FsZShjb25maWcpIHtcbiAgICAgICAgaWYgKGNvbmZpZyAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnNldChjb25maWcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGtleXM7XG5cbiAgICBpZiAoT2JqZWN0LmtleXMpIHtcbiAgICAgICAga2V5cyA9IE9iamVjdC5rZXlzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGtleXMgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgICAgICByZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoaSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzT3duUHJvcChvYmosIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRDYWxlbmRhciA9IHtcbiAgICAgICAgc2FtZURheTogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW1RvbW9ycm93IGF0XSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbTGFzdF0gZGRkZCBbYXRdIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gY2FsZW5kYXIoa2V5LCBtb20sIG5vdykge1xuICAgICAgICB2YXIgb3V0cHV0ID0gdGhpcy5fY2FsZW5kYXJba2V5XSB8fCB0aGlzLl9jYWxlbmRhclsnc2FtZUVsc2UnXTtcbiAgICAgICAgcmV0dXJuIGlzRnVuY3Rpb24ob3V0cHV0KSA/IG91dHB1dC5jYWxsKG1vbSwgbm93KSA6IG91dHB1dDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6ZXJvRmlsbChudW1iZXIsIHRhcmdldExlbmd0aCwgZm9yY2VTaWduKSB7XG4gICAgICAgIHZhciBhYnNOdW1iZXIgPSAnJyArIE1hdGguYWJzKG51bWJlciksXG4gICAgICAgICAgICB6ZXJvc1RvRmlsbCA9IHRhcmdldExlbmd0aCAtIGFic051bWJlci5sZW5ndGgsXG4gICAgICAgICAgICBzaWduID0gbnVtYmVyID49IDA7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAoc2lnbiA/IChmb3JjZVNpZ24gPyAnKycgOiAnJykgOiAnLScpICtcbiAgICAgICAgICAgIE1hdGgucG93KDEwLCBNYXRoLm1heCgwLCB6ZXJvc1RvRmlsbCkpLnRvU3RyaW5nKCkuc3Vic3RyKDEpICtcbiAgICAgICAgICAgIGFic051bWJlclxuICAgICAgICApO1xuICAgIH1cblxuICAgIHZhciBmb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KFtIaF1tbShzcyk/fE1vfE1NP00/TT98RG98REREb3xERD9EP0Q/fGRkZD9kP3xkbz98d1tvfHddP3xXW298V10/fFFvP3xOezEsNX18WVlZWVlZfFlZWVlZfFlZWVl8WVl8eXsyLDR9fHlvP3xnZyhnZ2c/KT98R0coR0dHPyk/fGV8RXxhfEF8aGg/fEhIP3xraz98bW0/fHNzP3xTezEsOX18eHxYfHp6P3xaWj98LikvZyxcbiAgICAgICAgbG9jYWxGb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KExUU3xMVHxMTD9MP0w/fGx7MSw0fSkvZyxcbiAgICAgICAgZm9ybWF0RnVuY3Rpb25zID0ge30sXG4gICAgICAgIGZvcm1hdFRva2VuRnVuY3Rpb25zID0ge307XG5cbiAgICAvLyB0b2tlbjogICAgJ00nXG4gICAgLy8gcGFkZGVkOiAgIFsnTU0nLCAyXVxuICAgIC8vIG9yZGluYWw6ICAnTW8nXG4gICAgLy8gY2FsbGJhY2s6IGZ1bmN0aW9uICgpIHsgdGhpcy5tb250aCgpICsgMSB9XG4gICAgZnVuY3Rpb24gYWRkRm9ybWF0VG9rZW4odG9rZW4sIHBhZGRlZCwgb3JkaW5hbCwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGZ1bmMgPSBjYWxsYmFjaztcbiAgICAgICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGJhY2tdKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0b2tlbikge1xuICAgICAgICAgICAgZm9ybWF0VG9rZW5GdW5jdGlvbnNbdG9rZW5dID0gZnVuYztcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFkZGVkKSB7XG4gICAgICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1twYWRkZWRbMF1dID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB6ZXJvRmlsbChmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksIHBhZGRlZFsxXSwgcGFkZGVkWzJdKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9yZGluYWwpIHtcbiAgICAgICAgICAgIGZvcm1hdFRva2VuRnVuY3Rpb25zW29yZGluYWxdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5vcmRpbmFsKFxuICAgICAgICAgICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgICAgICAgICAgICAgIHRva2VuXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVGb3JtYXR0aW5nVG9rZW5zKGlucHV0KSB7XG4gICAgICAgIGlmIChpbnB1dC5tYXRjaCgvXFxbW1xcc1xcU10vKSkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL15cXFt8XFxdJC9nLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL1xcXFwvZywgJycpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VGb3JtYXRGdW5jdGlvbihmb3JtYXQpIHtcbiAgICAgICAgdmFyIGFycmF5ID0gZm9ybWF0Lm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIGxlbmd0aDtcblxuICAgICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBhcnJheS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGZvcm1hdFRva2VuRnVuY3Rpb25zW2FycmF5W2ldXSkge1xuICAgICAgICAgICAgICAgIGFycmF5W2ldID0gZm9ybWF0VG9rZW5GdW5jdGlvbnNbYXJyYXlbaV1dO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhcnJheVtpXSA9IHJlbW92ZUZvcm1hdHRpbmdUb2tlbnMoYXJyYXlbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtb20pIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSAnJyxcbiAgICAgICAgICAgICAgICBpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0ICs9IGlzRnVuY3Rpb24oYXJyYXlbaV0pXG4gICAgICAgICAgICAgICAgICAgID8gYXJyYXlbaV0uY2FsbChtb20sIGZvcm1hdClcbiAgICAgICAgICAgICAgICAgICAgOiBhcnJheVtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gZm9ybWF0IGRhdGUgdXNpbmcgbmF0aXZlIGRhdGUgb2JqZWN0XG4gICAgZnVuY3Rpb24gZm9ybWF0TW9tZW50KG0sIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW0uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gbS5sb2NhbGVEYXRhKCkuaW52YWxpZERhdGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcm1hdCA9IGV4cGFuZEZvcm1hdChmb3JtYXQsIG0ubG9jYWxlRGF0YSgpKTtcbiAgICAgICAgZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0gPVxuICAgICAgICAgICAgZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0gfHwgbWFrZUZvcm1hdEZ1bmN0aW9uKGZvcm1hdCk7XG5cbiAgICAgICAgcmV0dXJuIGZvcm1hdEZ1bmN0aW9uc1tmb3JtYXRdKG0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4cGFuZEZvcm1hdChmb3JtYXQsIGxvY2FsZSkge1xuICAgICAgICB2YXIgaSA9IDU7XG5cbiAgICAgICAgZnVuY3Rpb24gcmVwbGFjZUxvbmdEYXRlRm9ybWF0VG9rZW5zKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxlLmxvbmdEYXRlRm9ybWF0KGlucHV0KSB8fCBpbnB1dDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy5sYXN0SW5kZXggPSAwO1xuICAgICAgICB3aGlsZSAoaSA+PSAwICYmIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFxuICAgICAgICAgICAgICAgIGxvY2FsRm9ybWF0dGluZ1Rva2VucyxcbiAgICAgICAgICAgICAgICByZXBsYWNlTG9uZ0RhdGVGb3JtYXRUb2tlbnNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcbiAgICAgICAgICAgIGkgLT0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb25nRGF0ZUZvcm1hdCA9IHtcbiAgICAgICAgTFRTOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTFQ6ICdoOm1tIEEnLFxuICAgICAgICBMOiAnTU0vREQvWVlZWScsXG4gICAgICAgIExMOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgTExMOiAnTU1NTSBELCBZWVlZIGg6bW0gQScsXG4gICAgICAgIExMTEw6ICdkZGRkLCBNTU1NIEQsIFlZWVkgaDptbSBBJyxcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9uZ0RhdGVGb3JtYXQoa2V5KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldLFxuICAgICAgICAgICAgZm9ybWF0VXBwZXIgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXkudG9VcHBlckNhc2UoKV07XG5cbiAgICAgICAgaWYgKGZvcm1hdCB8fCAhZm9ybWF0VXBwZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldID0gZm9ybWF0VXBwZXJcbiAgICAgICAgICAgIC5tYXRjaChmb3JtYXR0aW5nVG9rZW5zKVxuICAgICAgICAgICAgLm1hcChmdW5jdGlvbiAodG9rKSB7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICB0b2sgPT09ICdNTU1NJyB8fFxuICAgICAgICAgICAgICAgICAgICB0b2sgPT09ICdNTScgfHxcbiAgICAgICAgICAgICAgICAgICAgdG9rID09PSAnREQnIHx8XG4gICAgICAgICAgICAgICAgICAgIHRvayA9PT0gJ2RkZGQnXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0b2suc2xpY2UoMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0b2s7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oJycpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0SW52YWxpZERhdGUgPSAnSW52YWxpZCBkYXRlJztcblxuICAgIGZ1bmN0aW9uIGludmFsaWREYXRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faW52YWxpZERhdGU7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRPcmRpbmFsID0gJyVkJyxcbiAgICAgICAgZGVmYXVsdERheU9mTW9udGhPcmRpbmFsUGFyc2UgPSAvXFxkezEsMn0vO1xuXG4gICAgZnVuY3Rpb24gb3JkaW5hbChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29yZGluYWwucmVwbGFjZSgnJWQnLCBudW1iZXIpO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0UmVsYXRpdmVUaW1lID0ge1xuICAgICAgICBmdXR1cmU6ICdpbiAlcycsXG4gICAgICAgIHBhc3Q6ICclcyBhZ28nLFxuICAgICAgICBzOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzOiAnJWQgc2Vjb25kcycsXG4gICAgICAgIG06ICdhIG1pbnV0ZScsXG4gICAgICAgIG1tOiAnJWQgbWludXRlcycsXG4gICAgICAgIGg6ICdhbiBob3VyJyxcbiAgICAgICAgaGg6ICclZCBob3VycycsXG4gICAgICAgIGQ6ICdhIGRheScsXG4gICAgICAgIGRkOiAnJWQgZGF5cycsXG4gICAgICAgIHc6ICdhIHdlZWsnLFxuICAgICAgICB3dzogJyVkIHdlZWtzJyxcbiAgICAgICAgTTogJ2EgbW9udGgnLFxuICAgICAgICBNTTogJyVkIG1vbnRocycsXG4gICAgICAgIHk6ICdhIHllYXInLFxuICAgICAgICB5eTogJyVkIHllYXJzJyxcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgb3V0cHV0ID0gdGhpcy5fcmVsYXRpdmVUaW1lW3N0cmluZ107XG4gICAgICAgIHJldHVybiBpc0Z1bmN0aW9uKG91dHB1dClcbiAgICAgICAgICAgID8gb3V0cHV0KG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSlcbiAgICAgICAgICAgIDogb3V0cHV0LnJlcGxhY2UoLyVkL2ksIG51bWJlcik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFzdEZ1dHVyZShkaWZmLCBvdXRwdXQpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHRoaXMuX3JlbGF0aXZlVGltZVtkaWZmID4gMCA/ICdmdXR1cmUnIDogJ3Bhc3QnXTtcbiAgICAgICAgcmV0dXJuIGlzRnVuY3Rpb24oZm9ybWF0KSA/IGZvcm1hdChvdXRwdXQpIDogZm9ybWF0LnJlcGxhY2UoLyVzL2ksIG91dHB1dCk7XG4gICAgfVxuXG4gICAgdmFyIGFsaWFzZXMgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGFkZFVuaXRBbGlhcyh1bml0LCBzaG9ydGhhbmQpIHtcbiAgICAgICAgdmFyIGxvd2VyQ2FzZSA9IHVuaXQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgYWxpYXNlc1tsb3dlckNhc2VdID0gYWxpYXNlc1tsb3dlckNhc2UgKyAncyddID0gYWxpYXNlc1tzaG9ydGhhbmRdID0gdW5pdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub3JtYWxpemVVbml0cyh1bml0cykge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHVuaXRzID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgPyBhbGlhc2VzW3VuaXRzXSB8fCBhbGlhc2VzW3VuaXRzLnRvTG93ZXJDYXNlKCldXG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub3JtYWxpemVPYmplY3RVbml0cyhpbnB1dE9iamVjdCkge1xuICAgICAgICB2YXIgbm9ybWFsaXplZElucHV0ID0ge30sXG4gICAgICAgICAgICBub3JtYWxpemVkUHJvcCxcbiAgICAgICAgICAgIHByb3A7XG5cbiAgICAgICAgZm9yIChwcm9wIGluIGlucHV0T2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcChpbnB1dE9iamVjdCwgcHJvcCkpIHtcbiAgICAgICAgICAgICAgICBub3JtYWxpemVkUHJvcCA9IG5vcm1hbGl6ZVVuaXRzKHByb3ApO1xuICAgICAgICAgICAgICAgIGlmIChub3JtYWxpemVkUHJvcCkge1xuICAgICAgICAgICAgICAgICAgICBub3JtYWxpemVkSW5wdXRbbm9ybWFsaXplZFByb3BdID0gaW5wdXRPYmplY3RbcHJvcF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRJbnB1dDtcbiAgICB9XG5cbiAgICB2YXIgcHJpb3JpdGllcyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gYWRkVW5pdFByaW9yaXR5KHVuaXQsIHByaW9yaXR5KSB7XG4gICAgICAgIHByaW9yaXRpZXNbdW5pdF0gPSBwcmlvcml0eTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRQcmlvcml0aXplZFVuaXRzKHVuaXRzT2JqKSB7XG4gICAgICAgIHZhciB1bml0cyA9IFtdLFxuICAgICAgICAgICAgdTtcbiAgICAgICAgZm9yICh1IGluIHVuaXRzT2JqKSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcCh1bml0c09iaiwgdSkpIHtcbiAgICAgICAgICAgICAgICB1bml0cy5wdXNoKHsgdW5pdDogdSwgcHJpb3JpdHk6IHByaW9yaXRpZXNbdV0gfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdW5pdHMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGEucHJpb3JpdHkgLSBiLnByaW9yaXR5O1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHVuaXRzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzTGVhcFllYXIoeWVhcikge1xuICAgICAgICByZXR1cm4gKHllYXIgJSA0ID09PSAwICYmIHllYXIgJSAxMDAgIT09IDApIHx8IHllYXIgJSA0MDAgPT09IDA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWJzRmxvb3IobnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICAgICAgICAvLyAtMCAtPiAwXG4gICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKG51bWJlcikgfHwgMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKG51bWJlcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b0ludChhcmd1bWVudEZvckNvZXJjaW9uKSB7XG4gICAgICAgIHZhciBjb2VyY2VkTnVtYmVyID0gK2FyZ3VtZW50Rm9yQ29lcmNpb24sXG4gICAgICAgICAgICB2YWx1ZSA9IDA7XG5cbiAgICAgICAgaWYgKGNvZXJjZWROdW1iZXIgIT09IDAgJiYgaXNGaW5pdGUoY29lcmNlZE51bWJlcikpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYWJzRmxvb3IoY29lcmNlZE51bWJlcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZUdldFNldCh1bml0LCBrZWVwVGltZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHNldCQxKHRoaXMsIHVuaXQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywga2VlcFRpbWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0KHRoaXMsIHVuaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldChtb20sIHVuaXQpIHtcbiAgICAgICAgcmV0dXJuIG1vbS5pc1ZhbGlkKClcbiAgICAgICAgICAgID8gbW9tLl9kWydnZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArIHVuaXRdKClcbiAgICAgICAgICAgIDogTmFOO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldCQxKG1vbSwgdW5pdCwgdmFsdWUpIHtcbiAgICAgICAgaWYgKG1vbS5pc1ZhbGlkKCkgJiYgIWlzTmFOKHZhbHVlKSkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHVuaXQgPT09ICdGdWxsWWVhcicgJiZcbiAgICAgICAgICAgICAgICBpc0xlYXBZZWFyKG1vbS55ZWFyKCkpICYmXG4gICAgICAgICAgICAgICAgbW9tLm1vbnRoKCkgPT09IDEgJiZcbiAgICAgICAgICAgICAgICBtb20uZGF0ZSgpID09PSAyOVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0b0ludCh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgbW9tLl9kWydzZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArIHVuaXRdKFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgbW9tLm1vbnRoKCksXG4gICAgICAgICAgICAgICAgICAgIGRheXNJbk1vbnRoKHZhbHVlLCBtb20ubW9udGgoKSlcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb20uX2RbJ3NldCcgKyAobW9tLl9pc1VUQyA/ICdVVEMnIDogJycpICsgdW5pdF0odmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gc3RyaW5nR2V0KHVuaXRzKSB7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW3VuaXRzXSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0cmluZ1NldCh1bml0cywgdmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB1bml0cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplT2JqZWN0VW5pdHModW5pdHMpO1xuICAgICAgICAgICAgdmFyIHByaW9yaXRpemVkID0gZ2V0UHJpb3JpdGl6ZWRVbml0cyh1bml0cyksXG4gICAgICAgICAgICAgICAgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBwcmlvcml0aXplZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXNbcHJpb3JpdGl6ZWRbaV0udW5pdF0odW5pdHNbcHJpb3JpdGl6ZWRbaV0udW5pdF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG4gICAgICAgICAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpc1t1bml0c10odmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHZhciBtYXRjaDEgPSAvXFxkLywgLy8gICAgICAgMCAtIDlcbiAgICAgICAgbWF0Y2gyID0gL1xcZFxcZC8sIC8vICAgICAgMDAgLSA5OVxuICAgICAgICBtYXRjaDMgPSAvXFxkezN9LywgLy8gICAgIDAwMCAtIDk5OVxuICAgICAgICBtYXRjaDQgPSAvXFxkezR9LywgLy8gICAgMDAwMCAtIDk5OTlcbiAgICAgICAgbWF0Y2g2ID0gL1srLV0/XFxkezZ9LywgLy8gLTk5OTk5OSAtIDk5OTk5OVxuICAgICAgICBtYXRjaDF0bzIgPSAvXFxkXFxkPy8sIC8vICAgICAgIDAgLSA5OVxuICAgICAgICBtYXRjaDN0bzQgPSAvXFxkXFxkXFxkXFxkPy8sIC8vICAgICA5OTkgLSA5OTk5XG4gICAgICAgIG1hdGNoNXRvNiA9IC9cXGRcXGRcXGRcXGRcXGRcXGQ/LywgLy8gICA5OTk5OSAtIDk5OTk5OVxuICAgICAgICBtYXRjaDF0bzMgPSAvXFxkezEsM30vLCAvLyAgICAgICAwIC0gOTk5XG4gICAgICAgIG1hdGNoMXRvNCA9IC9cXGR7MSw0fS8sIC8vICAgICAgIDAgLSA5OTk5XG4gICAgICAgIG1hdGNoMXRvNiA9IC9bKy1dP1xcZHsxLDZ9LywgLy8gLTk5OTk5OSAtIDk5OTk5OVxuICAgICAgICBtYXRjaFVuc2lnbmVkID0gL1xcZCsvLCAvLyAgICAgICAwIC0gaW5mXG4gICAgICAgIG1hdGNoU2lnbmVkID0gL1srLV0/XFxkKy8sIC8vICAgIC1pbmYgLSBpbmZcbiAgICAgICAgbWF0Y2hPZmZzZXQgPSAvWnxbKy1dXFxkXFxkOj9cXGRcXGQvZ2ksIC8vICswMDowMCAtMDA6MDAgKzAwMDAgLTAwMDAgb3IgWlxuICAgICAgICBtYXRjaFNob3J0T2Zmc2V0ID0gL1p8WystXVxcZFxcZCg/Ojo/XFxkXFxkKT8vZ2ksIC8vICswMCAtMDAgKzAwOjAwIC0wMDowMCArMDAwMCAtMDAwMCBvciBaXG4gICAgICAgIG1hdGNoVGltZXN0YW1wID0gL1srLV0/XFxkKyhcXC5cXGR7MSwzfSk/LywgLy8gMTIzNDU2Nzg5IDEyMzQ1Njc4OS4xMjNcbiAgICAgICAgLy8gYW55IHdvcmQgKG9yIHR3bykgY2hhcmFjdGVycyBvciBudW1iZXJzIGluY2x1ZGluZyB0d28vdGhyZWUgd29yZCBtb250aCBpbiBhcmFiaWMuXG4gICAgICAgIC8vIGluY2x1ZGVzIHNjb3R0aXNoIGdhZWxpYyB0d28gd29yZCBhbmQgaHlwaGVuYXRlZCBtb250aHNcbiAgICAgICAgbWF0Y2hXb3JkID0gL1swLTldezAsMjU2fVsnYS16XFx1MDBBMC1cXHUwNUZGXFx1MDcwMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRjA3XFx1RkYxMC1cXHVGRkVGXXsxLDI1Nn18W1xcdTA2MDAtXFx1MDZGRlxcL117MSwyNTZ9KFxccyo/W1xcdTA2MDAtXFx1MDZGRl17MSwyNTZ9KXsxLDJ9L2ksXG4gICAgICAgIHJlZ2V4ZXM7XG5cbiAgICByZWdleGVzID0ge307XG5cbiAgICBmdW5jdGlvbiBhZGRSZWdleFRva2VuKHRva2VuLCByZWdleCwgc3RyaWN0UmVnZXgpIHtcbiAgICAgICAgcmVnZXhlc1t0b2tlbl0gPSBpc0Z1bmN0aW9uKHJlZ2V4KVxuICAgICAgICAgICAgPyByZWdleFxuICAgICAgICAgICAgOiBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZURhdGEpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBpc1N0cmljdCAmJiBzdHJpY3RSZWdleCA/IHN0cmljdFJlZ2V4IDogcmVnZXg7XG4gICAgICAgICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0UGFyc2VSZWdleEZvclRva2VuKHRva2VuLCBjb25maWcpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHJlZ2V4ZXMsIHRva2VuKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAodW5lc2NhcGVGb3JtYXQodG9rZW4pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZWdleGVzW3Rva2VuXShjb25maWcuX3N0cmljdCwgY29uZmlnLl9sb2NhbGUpO1xuICAgIH1cblxuICAgIC8vIENvZGUgZnJvbSBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM1NjE0OTMvaXMtdGhlcmUtYS1yZWdleHAtZXNjYXBlLWZ1bmN0aW9uLWluLWphdmFzY3JpcHRcbiAgICBmdW5jdGlvbiB1bmVzY2FwZUZvcm1hdChzKSB7XG4gICAgICAgIHJldHVybiByZWdleEVzY2FwZShcbiAgICAgICAgICAgIHNcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgnXFxcXCcsICcnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcKFxcWyl8XFxcXChcXF0pfFxcWyhbXlxcXVxcW10qKVxcXXxcXFxcKC4pL2csIGZ1bmN0aW9uIChcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlZCxcbiAgICAgICAgICAgICAgICAgICAgcDEsXG4gICAgICAgICAgICAgICAgICAgIHAyLFxuICAgICAgICAgICAgICAgICAgICBwMyxcbiAgICAgICAgICAgICAgICAgICAgcDRcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHAxIHx8IHAyIHx8IHAzIHx8IHA0O1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVnZXhFc2NhcGUocykge1xuICAgICAgICByZXR1cm4gcy5yZXBsYWNlKC9bLVxcL1xcXFxeJCorPy4oKXxbXFxde31dL2csICdcXFxcJCYnKTtcbiAgICB9XG5cbiAgICB2YXIgdG9rZW5zID0ge307XG5cbiAgICBmdW5jdGlvbiBhZGRQYXJzZVRva2VuKHRva2VuLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgIGZ1bmMgPSBjYWxsYmFjaztcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRva2VuID0gW3Rva2VuXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNOdW1iZXIoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBmdW5jID0gZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICAgICAgICAgIGFycmF5W2NhbGxiYWNrXSA9IHRvSW50KGlucHV0KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRva2VuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0b2tlbnNbdG9rZW5baV1dID0gZnVuYztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFdlZWtQYXJzZVRva2VuKHRva2VuLCBjYWxsYmFjaykge1xuICAgICAgICBhZGRQYXJzZVRva2VuKHRva2VuLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcsIHRva2VuKSB7XG4gICAgICAgICAgICBjb25maWcuX3cgPSBjb25maWcuX3cgfHwge307XG4gICAgICAgICAgICBjYWxsYmFjayhpbnB1dCwgY29uZmlnLl93LCBjb25maWcsIHRva2VuKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkVGltZVRvQXJyYXlGcm9tVG9rZW4odG9rZW4sIGlucHV0LCBjb25maWcpIHtcbiAgICAgICAgaWYgKGlucHV0ICE9IG51bGwgJiYgaGFzT3duUHJvcCh0b2tlbnMsIHRva2VuKSkge1xuICAgICAgICAgICAgdG9rZW5zW3Rva2VuXShpbnB1dCwgY29uZmlnLl9hLCBjb25maWcsIHRva2VuKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBZRUFSID0gMCxcbiAgICAgICAgTU9OVEggPSAxLFxuICAgICAgICBEQVRFID0gMixcbiAgICAgICAgSE9VUiA9IDMsXG4gICAgICAgIE1JTlVURSA9IDQsXG4gICAgICAgIFNFQ09ORCA9IDUsXG4gICAgICAgIE1JTExJU0VDT05EID0gNixcbiAgICAgICAgV0VFSyA9IDcsXG4gICAgICAgIFdFRUtEQVkgPSA4O1xuXG4gICAgZnVuY3Rpb24gbW9kKG4sIHgpIHtcbiAgICAgICAgcmV0dXJuICgobiAlIHgpICsgeCkgJSB4O1xuICAgIH1cblxuICAgIHZhciBpbmRleE9mO1xuXG4gICAgaWYgKEFycmF5LnByb3RvdHlwZS5pbmRleE9mKSB7XG4gICAgICAgIGluZGV4T2YgPSBBcnJheS5wcm90b3R5cGUuaW5kZXhPZjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpbmRleE9mID0gZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgICAgIC8vIEkga25vd1xuICAgICAgICAgICAgdmFyIGk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzW2ldID09PSBvKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkYXlzSW5Nb250aCh5ZWFyLCBtb250aCkge1xuICAgICAgICBpZiAoaXNOYU4oeWVhcikgfHwgaXNOYU4obW9udGgpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtb2RNb250aCA9IG1vZChtb250aCwgMTIpO1xuICAgICAgICB5ZWFyICs9IChtb250aCAtIG1vZE1vbnRoKSAvIDEyO1xuICAgICAgICByZXR1cm4gbW9kTW9udGggPT09IDFcbiAgICAgICAgICAgID8gaXNMZWFwWWVhcih5ZWFyKVxuICAgICAgICAgICAgICAgID8gMjlcbiAgICAgICAgICAgICAgICA6IDI4XG4gICAgICAgICAgICA6IDMxIC0gKChtb2RNb250aCAlIDcpICUgMik7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ00nLCBbJ01NJywgMl0sICdNbycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9udGgoKSArIDE7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignTU1NJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzU2hvcnQodGhpcywgZm9ybWF0KTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdNTU1NJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzKHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ21vbnRoJywgJ00nKTtcblxuICAgIC8vIFBSSU9SSVRZXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ21vbnRoJywgOCk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdNJywgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdNTScsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbiAgICBhZGRSZWdleFRva2VuKCdNTU0nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLm1vbnRoc1Nob3J0UmVnZXgoaXNTdHJpY3QpO1xuICAgIH0pO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ01NTU0nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLm1vbnRoc1JlZ2V4KGlzU3RyaWN0KTtcbiAgICB9KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydNJywgJ01NJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgYXJyYXlbTU9OVEhdID0gdG9JbnQoaW5wdXQpIC0gMTtcbiAgICB9KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydNTU0nLCAnTU1NTSddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcsIHRva2VuKSB7XG4gICAgICAgIHZhciBtb250aCA9IGNvbmZpZy5fbG9jYWxlLm1vbnRoc1BhcnNlKGlucHV0LCB0b2tlbiwgY29uZmlnLl9zdHJpY3QpO1xuICAgICAgICAvLyBpZiB3ZSBkaWRuJ3QgZmluZCBhIG1vbnRoIG5hbWUsIG1hcmsgdGhlIGRhdGUgYXMgaW52YWxpZC5cbiAgICAgICAgaWYgKG1vbnRoICE9IG51bGwpIHtcbiAgICAgICAgICAgIGFycmF5W01PTlRIXSA9IG1vbnRoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZE1vbnRoID0gaW5wdXQ7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIExPQ0FMRVNcblxuICAgIHZhciBkZWZhdWx0TG9jYWxlTW9udGhzID0gJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIGRlZmF1bHRMb2NhbGVNb250aHNTaG9ydCA9ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgTU9OVEhTX0lOX0ZPUk1BVCA9IC9EW29EXT8oXFxbW15cXFtcXF1dKlxcXXxcXHMpK01NTU0/LyxcbiAgICAgICAgZGVmYXVsdE1vbnRoc1Nob3J0UmVnZXggPSBtYXRjaFdvcmQsXG4gICAgICAgIGRlZmF1bHRNb250aHNSZWdleCA9IG1hdGNoV29yZDtcblxuICAgIGZ1bmN0aW9uIGxvY2FsZU1vbnRocyhtLCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNBcnJheSh0aGlzLl9tb250aHMpXG4gICAgICAgICAgICAgICAgPyB0aGlzLl9tb250aHNcbiAgICAgICAgICAgICAgICA6IHRoaXMuX21vbnRoc1snc3RhbmRhbG9uZSddO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0FycmF5KHRoaXMuX21vbnRocylcbiAgICAgICAgICAgID8gdGhpcy5fbW9udGhzW20ubW9udGgoKV1cbiAgICAgICAgICAgIDogdGhpcy5fbW9udGhzW1xuICAgICAgICAgICAgICAgICAgKHRoaXMuX21vbnRocy5pc0Zvcm1hdCB8fCBNT05USFNfSU5fRk9STUFUKS50ZXN0KGZvcm1hdClcbiAgICAgICAgICAgICAgICAgICAgICA/ICdmb3JtYXQnXG4gICAgICAgICAgICAgICAgICAgICAgOiAnc3RhbmRhbG9uZSdcbiAgICAgICAgICAgICAgXVttLm1vbnRoKCldO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvY2FsZU1vbnRoc1Nob3J0KG0sIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgIHJldHVybiBpc0FycmF5KHRoaXMuX21vbnRoc1Nob3J0KVxuICAgICAgICAgICAgICAgID8gdGhpcy5fbW9udGhzU2hvcnRcbiAgICAgICAgICAgICAgICA6IHRoaXMuX21vbnRoc1Nob3J0WydzdGFuZGFsb25lJ107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzQXJyYXkodGhpcy5fbW9udGhzU2hvcnQpXG4gICAgICAgICAgICA/IHRoaXMuX21vbnRoc1Nob3J0W20ubW9udGgoKV1cbiAgICAgICAgICAgIDogdGhpcy5fbW9udGhzU2hvcnRbXG4gICAgICAgICAgICAgICAgICBNT05USFNfSU5fRk9STUFULnRlc3QoZm9ybWF0KSA/ICdmb3JtYXQnIDogJ3N0YW5kYWxvbmUnXG4gICAgICAgICAgICAgIF1bbS5tb250aCgpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVTdHJpY3RQYXJzZShtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgaWksXG4gICAgICAgICAgICBtb20sXG4gICAgICAgICAgICBsbGMgPSBtb250aE5hbWUudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKCF0aGlzLl9tb250aHNQYXJzZSkge1xuICAgICAgICAgICAgLy8gdGhpcyBpcyBub3QgdXNlZFxuICAgICAgICAgICAgdGhpcy5fbW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fc2hvcnRNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDEyOyArK2kpIHtcbiAgICAgICAgICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIGldKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlW2ldID0gdGhpcy5tb250aHNTaG9ydChcbiAgICAgICAgICAgICAgICAgICAgbW9tLFxuICAgICAgICAgICAgICAgICAgICAnJ1xuICAgICAgICAgICAgICAgICkudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb25nTW9udGhzUGFyc2VbaV0gPSB0aGlzLm1vbnRocyhtb20sICcnKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0cmljdCkge1xuICAgICAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ01NTScpIHtcbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydE1vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX2xvbmdNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ01NTScpIHtcbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydE1vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9sb25nTW9udGhzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbG9uZ01vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydE1vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVNb250aHNQYXJzZShtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgICAgIHZhciBpLCBtb20sIHJlZ2V4O1xuXG4gICAgICAgIGlmICh0aGlzLl9tb250aHNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlU3RyaWN0UGFyc2UuY2FsbCh0aGlzLCBtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5fbW9udGhzUGFyc2UpIHtcbiAgICAgICAgICAgIHRoaXMuX21vbnRoc1BhcnNlID0gW107XG4gICAgICAgICAgICB0aGlzLl9sb25nTW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0TW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRPRE86IGFkZCBzb3J0aW5nXG4gICAgICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgbW9udGggKG9yIGFiYnIpIGlzIGEgcHJlZml4IG9mIGFub3RoZXJcbiAgICAgICAgLy8gc2VlIHNvcnRpbmcgaW4gY29tcHV0ZU1vbnRoc1BhcnNlXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcbiAgICAgICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgaV0pO1xuICAgICAgICAgICAgaWYgKHN0cmljdCAmJiAhdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgICAgICAgJ14nICsgdGhpcy5tb250aHMobW9tLCAnJykucmVwbGFjZSgnLicsICcnKSArICckJyxcbiAgICAgICAgICAgICAgICAgICAgJ2knXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgICAgICAgJ14nICsgdGhpcy5tb250aHNTaG9ydChtb20sICcnKS5yZXBsYWNlKCcuJywgJycpICsgJyQnLFxuICAgICAgICAgICAgICAgICAgICAnaSdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFzdHJpY3QgJiYgIXRoaXMuX21vbnRoc1BhcnNlW2ldKSB7XG4gICAgICAgICAgICAgICAgcmVnZXggPVxuICAgICAgICAgICAgICAgICAgICAnXicgKyB0aGlzLm1vbnRocyhtb20sICcnKSArICd8XicgKyB0aGlzLm1vbnRoc1Nob3J0KG1vbSwgJycpO1xuICAgICAgICAgICAgICAgIHRoaXMuX21vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChyZWdleC5yZXBsYWNlKCcuJywgJycpLCAnaScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdGVzdCB0aGUgcmVnZXhcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBzdHJpY3QgJiZcbiAgICAgICAgICAgICAgICBmb3JtYXQgPT09ICdNTU1NJyAmJlxuICAgICAgICAgICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZVtpXS50ZXN0KG1vbnRoTmFtZSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICBzdHJpY3QgJiZcbiAgICAgICAgICAgICAgICBmb3JtYXQgPT09ICdNTU0nICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fc2hvcnRNb250aHNQYXJzZVtpXS50ZXN0KG1vbnRoTmFtZSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghc3RyaWN0ICYmIHRoaXMuX21vbnRoc1BhcnNlW2ldLnRlc3QobW9udGhOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gc2V0TW9udGgobW9tLCB2YWx1ZSkge1xuICAgICAgICB2YXIgZGF5T2ZNb250aDtcblxuICAgICAgICBpZiAoIW1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIC8vIE5vIG9wXG4gICAgICAgICAgICByZXR1cm4gbW9tO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGlmICgvXlxcZCskLy50ZXN0KHZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdG9JbnQodmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IG1vbS5sb2NhbGVEYXRhKCkubW9udGhzUGFyc2UodmFsdWUpO1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IEFub3RoZXIgc2lsZW50IGZhaWx1cmU/XG4gICAgICAgICAgICAgICAgaWYgKCFpc051bWJlcih2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1vbTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBkYXlPZk1vbnRoID0gTWF0aC5taW4obW9tLmRhdGUoKSwgZGF5c0luTW9udGgobW9tLnllYXIoKSwgdmFsdWUpKTtcbiAgICAgICAgbW9tLl9kWydzZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArICdNb250aCddKHZhbHVlLCBkYXlPZk1vbnRoKTtcbiAgICAgICAgcmV0dXJuIG1vbTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTZXRNb250aCh2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgc2V0TW9udGgodGhpcywgdmFsdWUpO1xuICAgICAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KHRoaXMsIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0KHRoaXMsICdNb250aCcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0RGF5c0luTW9udGgoKSB7XG4gICAgICAgIHJldHVybiBkYXlzSW5Nb250aCh0aGlzLnllYXIoKSwgdGhpcy5tb250aCgpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb250aHNTaG9ydFJlZ2V4KGlzU3RyaWN0KSB7XG4gICAgICAgIGlmICh0aGlzLl9tb250aHNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21vbnRoc1Nob3J0UmVnZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNTaG9ydFJlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNTaG9ydFJlZ2V4ID0gZGVmYXVsdE1vbnRoc1Nob3J0UmVnZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleCAmJiBpc1N0cmljdFxuICAgICAgICAgICAgICAgID8gdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleFxuICAgICAgICAgICAgICAgIDogdGhpcy5fbW9udGhzU2hvcnRSZWdleDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vbnRoc1JlZ2V4KGlzU3RyaWN0KSB7XG4gICAgICAgIGlmICh0aGlzLl9tb250aHNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX21vbnRoc1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNSZWdleCA9IGRlZmF1bHRNb250aHNSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNTdHJpY3RSZWdleCAmJiBpc1N0cmljdFxuICAgICAgICAgICAgICAgID8gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXhcbiAgICAgICAgICAgICAgICA6IHRoaXMuX21vbnRoc1JlZ2V4O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZU1vbnRoc1BhcnNlKCkge1xuICAgICAgICBmdW5jdGlvbiBjbXBMZW5SZXYoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGIubGVuZ3RoIC0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2hvcnRQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIGxvbmdQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIG1peGVkUGllY2VzID0gW10sXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgbW9tO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICAgICAgLy8gbWFrZSB0aGUgcmVnZXggaWYgd2UgZG9uJ3QgaGF2ZSBpdCBhbHJlYWR5XG4gICAgICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIGldKTtcbiAgICAgICAgICAgIHNob3J0UGllY2VzLnB1c2godGhpcy5tb250aHNTaG9ydChtb20sICcnKSk7XG4gICAgICAgICAgICBsb25nUGllY2VzLnB1c2godGhpcy5tb250aHMobW9tLCAnJykpO1xuICAgICAgICAgICAgbWl4ZWRQaWVjZXMucHVzaCh0aGlzLm1vbnRocyhtb20sICcnKSk7XG4gICAgICAgICAgICBtaXhlZFBpZWNlcy5wdXNoKHRoaXMubW9udGhzU2hvcnQobW9tLCAnJykpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgbW9udGggKG9yIGFiYnIpIGlzIGEgcHJlZml4IG9mIGFub3RoZXIgaXRcbiAgICAgICAgLy8gd2lsbCBtYXRjaCB0aGUgbG9uZ2VyIHBpZWNlLlxuICAgICAgICBzaG9ydFBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIGxvbmdQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgICAgICBtaXhlZFBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgICAgICBzaG9ydFBpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKHNob3J0UGllY2VzW2ldKTtcbiAgICAgICAgICAgIGxvbmdQaWVjZXNbaV0gPSByZWdleEVzY2FwZShsb25nUGllY2VzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMjQ7IGkrKykge1xuICAgICAgICAgICAgbWl4ZWRQaWVjZXNbaV0gPSByZWdleEVzY2FwZShtaXhlZFBpZWNlc1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9tb250aHNSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIG1peGVkUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICAgICAgdGhpcy5fbW9udGhzU2hvcnRSZWdleCA9IHRoaXMuX21vbnRoc1JlZ2V4O1xuICAgICAgICB0aGlzLl9tb250aHNTdHJpY3RSZWdleCA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAnXignICsgbG9uZ1BpZWNlcy5qb2luKCd8JykgKyAnKScsXG4gICAgICAgICAgICAnaSdcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleCA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAnXignICsgc2hvcnRQaWVjZXMuam9pbignfCcpICsgJyknLFxuICAgICAgICAgICAgJ2knXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ1knLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB5ID0gdGhpcy55ZWFyKCk7XG4gICAgICAgIHJldHVybiB5IDw9IDk5OTkgPyB6ZXJvRmlsbCh5LCA0KSA6ICcrJyArIHk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1lZJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueWVhcigpICUgMTAwO1xuICAgIH0pO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydZWVlZJywgNF0sIDAsICd5ZWFyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydZWVlZWScsIDVdLCAwLCAneWVhcicpO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnWVlZWVlZJywgNiwgdHJ1ZV0sIDAsICd5ZWFyJyk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ3llYXInLCAneScpO1xuXG4gICAgLy8gUFJJT1JJVElFU1xuXG4gICAgYWRkVW5pdFByaW9yaXR5KCd5ZWFyJywgMSk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdZJywgbWF0Y2hTaWduZWQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1lZJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1lZWVknLCBtYXRjaDF0bzQsIG1hdGNoNCk7XG4gICAgYWRkUmVnZXhUb2tlbignWVlZWVknLCBtYXRjaDF0bzYsIG1hdGNoNik7XG4gICAgYWRkUmVnZXhUb2tlbignWVlZWVlZJywgbWF0Y2gxdG82LCBtYXRjaDYpO1xuXG4gICAgYWRkUGFyc2VUb2tlbihbJ1lZWVlZJywgJ1lZWVlZWSddLCBZRUFSKTtcbiAgICBhZGRQYXJzZVRva2VuKCdZWVlZJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICBhcnJheVtZRUFSXSA9XG4gICAgICAgICAgICBpbnB1dC5sZW5ndGggPT09IDIgPyBob29rcy5wYXJzZVR3b0RpZ2l0WWVhcihpbnB1dCkgOiB0b0ludChpbnB1dCk7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbignWVknLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgICAgIGFycmF5W1lFQVJdID0gaG9va3MucGFyc2VUd29EaWdpdFllYXIoaW5wdXQpO1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oJ1knLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgICAgIGFycmF5W1lFQVJdID0gcGFyc2VJbnQoaW5wdXQsIDEwKTtcbiAgICB9KTtcblxuICAgIC8vIEhFTFBFUlNcblxuICAgIGZ1bmN0aW9uIGRheXNJblllYXIoeWVhcikge1xuICAgICAgICByZXR1cm4gaXNMZWFwWWVhcih5ZWFyKSA/IDM2NiA6IDM2NTtcbiAgICB9XG5cbiAgICAvLyBIT09LU1xuXG4gICAgaG9va3MucGFyc2VUd29EaWdpdFllYXIgPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIHRvSW50KGlucHV0KSArICh0b0ludChpbnB1dCkgPiA2OCA/IDE5MDAgOiAyMDAwKTtcbiAgICB9O1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgdmFyIGdldFNldFllYXIgPSBtYWtlR2V0U2V0KCdGdWxsWWVhcicsIHRydWUpO1xuXG4gICAgZnVuY3Rpb24gZ2V0SXNMZWFwWWVhcigpIHtcbiAgICAgICAgcmV0dXJuIGlzTGVhcFllYXIodGhpcy55ZWFyKCkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZURhdGUoeSwgbSwgZCwgaCwgTSwgcywgbXMpIHtcbiAgICAgICAgLy8gY2FuJ3QganVzdCBhcHBseSgpIHRvIGNyZWF0ZSBhIGRhdGU6XG4gICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcS8xODEzNDhcbiAgICAgICAgdmFyIGRhdGU7XG4gICAgICAgIC8vIHRoZSBkYXRlIGNvbnN0cnVjdG9yIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgICAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDApIHtcbiAgICAgICAgICAgIC8vIHByZXNlcnZlIGxlYXAgeWVhcnMgdXNpbmcgYSBmdWxsIDQwMCB5ZWFyIGN5Y2xlLCB0aGVuIHJlc2V0XG4gICAgICAgICAgICBkYXRlID0gbmV3IERhdGUoeSArIDQwMCwgbSwgZCwgaCwgTSwgcywgbXMpO1xuICAgICAgICAgICAgaWYgKGlzRmluaXRlKGRhdGUuZ2V0RnVsbFllYXIoKSkpIHtcbiAgICAgICAgICAgICAgICBkYXRlLnNldEZ1bGxZZWFyKHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0ZSA9IG5ldyBEYXRlKHksIG0sIGQsIGgsIE0sIHMsIG1zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVVUQ0RhdGUoeSkge1xuICAgICAgICB2YXIgZGF0ZSwgYXJncztcbiAgICAgICAgLy8gdGhlIERhdGUuVVRDIGZ1bmN0aW9uIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgICAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDApIHtcbiAgICAgICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICAgICAgLy8gcHJlc2VydmUgbGVhcCB5ZWFycyB1c2luZyBhIGZ1bGwgNDAwIHllYXIgY3ljbGUsIHRoZW4gcmVzZXRcbiAgICAgICAgICAgIGFyZ3NbMF0gPSB5ICsgNDAwO1xuICAgICAgICAgICAgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDLmFwcGx5KG51bGwsIGFyZ3MpKTtcbiAgICAgICAgICAgIGlmIChpc0Zpbml0ZShkYXRlLmdldFVUQ0Z1bGxZZWFyKCkpKSB7XG4gICAgICAgICAgICAgICAgZGF0ZS5zZXRVVENGdWxsWWVhcih5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQy5hcHBseShudWxsLCBhcmd1bWVudHMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cblxuICAgIC8vIHN0YXJ0LW9mLWZpcnN0LXdlZWsgLSBzdGFydC1vZi15ZWFyXG4gICAgZnVuY3Rpb24gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSB7XG4gICAgICAgIHZhciAvLyBmaXJzdC13ZWVrIGRheSAtLSB3aGljaCBqYW51YXJ5IGlzIGFsd2F5cyBpbiB0aGUgZmlyc3Qgd2VlayAoNCBmb3IgaXNvLCAxIGZvciBvdGhlcilcbiAgICAgICAgICAgIGZ3ZCA9IDcgKyBkb3cgLSBkb3ksXG4gICAgICAgICAgICAvLyBmaXJzdC13ZWVrIGRheSBsb2NhbCB3ZWVrZGF5IC0tIHdoaWNoIGxvY2FsIHdlZWtkYXkgaXMgZndkXG4gICAgICAgICAgICBmd2RsdyA9ICg3ICsgY3JlYXRlVVRDRGF0ZSh5ZWFyLCAwLCBmd2QpLmdldFVUQ0RheSgpIC0gZG93KSAlIDc7XG5cbiAgICAgICAgcmV0dXJuIC1md2RsdyArIGZ3ZCAtIDE7XG4gICAgfVxuXG4gICAgLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPX3dlZWtfZGF0ZSNDYWxjdWxhdGluZ19hX2RhdGVfZ2l2ZW5fdGhlX3llYXIuMkNfd2Vla19udW1iZXJfYW5kX3dlZWtkYXlcbiAgICBmdW5jdGlvbiBkYXlPZlllYXJGcm9tV2Vla3MoeWVhciwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpIHtcbiAgICAgICAgdmFyIGxvY2FsV2Vla2RheSA9ICg3ICsgd2Vla2RheSAtIGRvdykgJSA3LFxuICAgICAgICAgICAgd2Vla09mZnNldCA9IGZpcnN0V2Vla09mZnNldCh5ZWFyLCBkb3csIGRveSksXG4gICAgICAgICAgICBkYXlPZlllYXIgPSAxICsgNyAqICh3ZWVrIC0gMSkgKyBsb2NhbFdlZWtkYXkgKyB3ZWVrT2Zmc2V0LFxuICAgICAgICAgICAgcmVzWWVhcixcbiAgICAgICAgICAgIHJlc0RheU9mWWVhcjtcblxuICAgICAgICBpZiAoZGF5T2ZZZWFyIDw9IDApIHtcbiAgICAgICAgICAgIHJlc1llYXIgPSB5ZWFyIC0gMTtcbiAgICAgICAgICAgIHJlc0RheU9mWWVhciA9IGRheXNJblllYXIocmVzWWVhcikgKyBkYXlPZlllYXI7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF5T2ZZZWFyID4gZGF5c0luWWVhcih5ZWFyKSkge1xuICAgICAgICAgICAgcmVzWWVhciA9IHllYXIgKyAxO1xuICAgICAgICAgICAgcmVzRGF5T2ZZZWFyID0gZGF5T2ZZZWFyIC0gZGF5c0luWWVhcih5ZWFyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc1llYXIgPSB5ZWFyO1xuICAgICAgICAgICAgcmVzRGF5T2ZZZWFyID0gZGF5T2ZZZWFyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHllYXI6IHJlc1llYXIsXG4gICAgICAgICAgICBkYXlPZlllYXI6IHJlc0RheU9mWWVhcixcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB3ZWVrT2ZZZWFyKG1vbSwgZG93LCBkb3kpIHtcbiAgICAgICAgdmFyIHdlZWtPZmZzZXQgPSBmaXJzdFdlZWtPZmZzZXQobW9tLnllYXIoKSwgZG93LCBkb3kpLFxuICAgICAgICAgICAgd2VlayA9IE1hdGguZmxvb3IoKG1vbS5kYXlPZlllYXIoKSAtIHdlZWtPZmZzZXQgLSAxKSAvIDcpICsgMSxcbiAgICAgICAgICAgIHJlc1dlZWssXG4gICAgICAgICAgICByZXNZZWFyO1xuXG4gICAgICAgIGlmICh3ZWVrIDwgMSkge1xuICAgICAgICAgICAgcmVzWWVhciA9IG1vbS55ZWFyKCkgLSAxO1xuICAgICAgICAgICAgcmVzV2VlayA9IHdlZWsgKyB3ZWVrc0luWWVhcihyZXNZZWFyLCBkb3csIGRveSk7XG4gICAgICAgIH0gZWxzZSBpZiAod2VlayA+IHdlZWtzSW5ZZWFyKG1vbS55ZWFyKCksIGRvdywgZG95KSkge1xuICAgICAgICAgICAgcmVzV2VlayA9IHdlZWsgLSB3ZWVrc0luWWVhcihtb20ueWVhcigpLCBkb3csIGRveSk7XG4gICAgICAgICAgICByZXNZZWFyID0gbW9tLnllYXIoKSArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNZZWFyID0gbW9tLnllYXIoKTtcbiAgICAgICAgICAgIHJlc1dlZWsgPSB3ZWVrO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHdlZWs6IHJlc1dlZWssXG4gICAgICAgICAgICB5ZWFyOiByZXNZZWFyLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHdlZWtzSW5ZZWFyKHllYXIsIGRvdywgZG95KSB7XG4gICAgICAgIHZhciB3ZWVrT2Zmc2V0ID0gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSxcbiAgICAgICAgICAgIHdlZWtPZmZzZXROZXh0ID0gZmlyc3RXZWVrT2Zmc2V0KHllYXIgKyAxLCBkb3csIGRveSk7XG4gICAgICAgIHJldHVybiAoZGF5c0luWWVhcih5ZWFyKSAtIHdlZWtPZmZzZXQgKyB3ZWVrT2Zmc2V0TmV4dCkgLyA3O1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCd3JywgWyd3dycsIDJdLCAnd28nLCAnd2VlaycpO1xuICAgIGFkZEZvcm1hdFRva2VuKCdXJywgWydXVycsIDJdLCAnV28nLCAnaXNvV2VlaycpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCd3ZWVrJywgJ3cnKTtcbiAgICBhZGRVbml0QWxpYXMoJ2lzb1dlZWsnLCAnVycpO1xuXG4gICAgLy8gUFJJT1JJVElFU1xuXG4gICAgYWRkVW5pdFByaW9yaXR5KCd3ZWVrJywgNSk7XG4gICAgYWRkVW5pdFByaW9yaXR5KCdpc29XZWVrJywgNSk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCd3JywgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCd3dycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbiAgICBhZGRSZWdleFRva2VuKCdXJywgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdXVycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcblxuICAgIGFkZFdlZWtQYXJzZVRva2VuKFsndycsICd3dycsICdXJywgJ1dXJ10sIGZ1bmN0aW9uIChcbiAgICAgICAgaW5wdXQsXG4gICAgICAgIHdlZWssXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgdG9rZW5cbiAgICApIHtcbiAgICAgICAgd2Vla1t0b2tlbi5zdWJzdHIoMCwgMSldID0gdG9JbnQoaW5wdXQpO1xuICAgIH0pO1xuXG4gICAgLy8gSEVMUEVSU1xuXG4gICAgLy8gTE9DQUxFU1xuXG4gICAgZnVuY3Rpb24gbG9jYWxlV2Vlayhtb20pIHtcbiAgICAgICAgcmV0dXJuIHdlZWtPZlllYXIobW9tLCB0aGlzLl93ZWVrLmRvdywgdGhpcy5fd2Vlay5kb3kpLndlZWs7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb2NhbGVXZWVrID0ge1xuICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3k6IDYsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9jYWxlRmlyc3REYXlPZldlZWsoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl93ZWVrLmRvdztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVGaXJzdERheU9mWWVhcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWsuZG95O1xuICAgIH1cblxuICAgIC8vIE1PTUVOVFNcblxuICAgIGZ1bmN0aW9uIGdldFNldFdlZWsoaW5wdXQpIHtcbiAgICAgICAgdmFyIHdlZWsgPSB0aGlzLmxvY2FsZURhdGEoKS53ZWVrKHRoaXMpO1xuICAgICAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IHdlZWsgOiB0aGlzLmFkZCgoaW5wdXQgLSB3ZWVrKSAqIDcsICdkJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0SVNPV2VlayhpbnB1dCkge1xuICAgICAgICB2YXIgd2VlayA9IHdlZWtPZlllYXIodGhpcywgMSwgNCkud2VlaztcbiAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB3ZWVrIDogdGhpcy5hZGQoKGlucHV0IC0gd2VlaykgKiA3LCAnZCcpO1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdkJywgMCwgJ2RvJywgJ2RheScpO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ2RkJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkud2Vla2RheXNNaW4odGhpcywgZm9ybWF0KTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdkZGQnLCAwLCAwLCBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS53ZWVrZGF5c1Nob3J0KHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignZGRkZCcsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLndlZWtkYXlzKHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignZScsIDAsIDAsICd3ZWVrZGF5Jyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ0UnLCAwLCAwLCAnaXNvV2Vla2RheScpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCdkYXknLCAnZCcpO1xuICAgIGFkZFVuaXRBbGlhcygnd2Vla2RheScsICdlJyk7XG4gICAgYWRkVW5pdEFsaWFzKCdpc29XZWVrZGF5JywgJ0UnKTtcblxuICAgIC8vIFBSSU9SSVRZXG4gICAgYWRkVW5pdFByaW9yaXR5KCdkYXknLCAxMSk7XG4gICAgYWRkVW5pdFByaW9yaXR5KCd3ZWVrZGF5JywgMTEpO1xuICAgIGFkZFVuaXRQcmlvcml0eSgnaXNvV2Vla2RheScsIDExKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ2QnLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2UnLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0UnLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2RkJywgZnVuY3Rpb24gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c01pblJlZ2V4KGlzU3RyaWN0KTtcbiAgICB9KTtcbiAgICBhZGRSZWdleFRva2VuKCdkZGQnLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLndlZWtkYXlzU2hvcnRSZWdleChpc1N0cmljdCk7XG4gICAgfSk7XG4gICAgYWRkUmVnZXhUb2tlbignZGRkZCcsIGZ1bmN0aW9uIChpc1N0cmljdCwgbG9jYWxlKSB7XG4gICAgICAgIHJldHVybiBsb2NhbGUud2Vla2RheXNSZWdleChpc1N0cmljdCk7XG4gICAgfSk7XG5cbiAgICBhZGRXZWVrUGFyc2VUb2tlbihbJ2RkJywgJ2RkZCcsICdkZGRkJ10sIGZ1bmN0aW9uIChpbnB1dCwgd2VlaywgY29uZmlnLCB0b2tlbikge1xuICAgICAgICB2YXIgd2Vla2RheSA9IGNvbmZpZy5fbG9jYWxlLndlZWtkYXlzUGFyc2UoaW5wdXQsIHRva2VuLCBjb25maWcuX3N0cmljdCk7XG4gICAgICAgIC8vIGlmIHdlIGRpZG4ndCBnZXQgYSB3ZWVrZGF5IG5hbWUsIG1hcmsgdGhlIGRhdGUgYXMgaW52YWxpZFxuICAgICAgICBpZiAod2Vla2RheSAhPSBudWxsKSB7XG4gICAgICAgICAgICB3ZWVrLmQgPSB3ZWVrZGF5O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZFdlZWtkYXkgPSBpbnB1dDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgYWRkV2Vla1BhcnNlVG9rZW4oWydkJywgJ2UnLCAnRSddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICAgICAgd2Vla1t0b2tlbl0gPSB0b0ludChpbnB1dCk7XG4gICAgfSk7XG5cbiAgICAvLyBIRUxQRVJTXG5cbiAgICBmdW5jdGlvbiBwYXJzZVdlZWtkYXkoaW5wdXQsIGxvY2FsZSkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpc05hTihpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUludChpbnB1dCwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgaW5wdXQgPSBsb2NhbGUud2Vla2RheXNQYXJzZShpbnB1dCk7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzZUlzb1dlZWtkYXkoaW5wdXQsIGxvY2FsZSkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c1BhcnNlKGlucHV0KSAlIDcgfHwgNztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNOYU4oaW5wdXQpID8gbnVsbCA6IGlucHV0O1xuICAgIH1cblxuICAgIC8vIExPQ0FMRVNcbiAgICBmdW5jdGlvbiBzaGlmdFdlZWtkYXlzKHdzLCBuKSB7XG4gICAgICAgIHJldHVybiB3cy5zbGljZShuLCA3KS5jb25jYXQod3Muc2xpY2UoMCwgbikpO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0TG9jYWxlV2Vla2RheXMgPSAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIGRlZmF1bHRMb2NhbGVXZWVrZGF5c1Nob3J0ID0gJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgZGVmYXVsdExvY2FsZVdlZWtkYXlzTWluID0gJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICBkZWZhdWx0V2Vla2RheXNSZWdleCA9IG1hdGNoV29yZCxcbiAgICAgICAgZGVmYXVsdFdlZWtkYXlzU2hvcnRSZWdleCA9IG1hdGNoV29yZCxcbiAgICAgICAgZGVmYXVsdFdlZWtkYXlzTWluUmVnZXggPSBtYXRjaFdvcmQ7XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVXZWVrZGF5cyhtLCBmb3JtYXQpIHtcbiAgICAgICAgdmFyIHdlZWtkYXlzID0gaXNBcnJheSh0aGlzLl93ZWVrZGF5cylcbiAgICAgICAgICAgID8gdGhpcy5fd2Vla2RheXNcbiAgICAgICAgICAgIDogdGhpcy5fd2Vla2RheXNbXG4gICAgICAgICAgICAgICAgICBtICYmIG0gIT09IHRydWUgJiYgdGhpcy5fd2Vla2RheXMuaXNGb3JtYXQudGVzdChmb3JtYXQpXG4gICAgICAgICAgICAgICAgICAgICAgPyAnZm9ybWF0J1xuICAgICAgICAgICAgICAgICAgICAgIDogJ3N0YW5kYWxvbmUnXG4gICAgICAgICAgICAgIF07XG4gICAgICAgIHJldHVybiBtID09PSB0cnVlXG4gICAgICAgICAgICA/IHNoaWZ0V2Vla2RheXMod2Vla2RheXMsIHRoaXMuX3dlZWsuZG93KVxuICAgICAgICAgICAgOiBtXG4gICAgICAgICAgICA/IHdlZWtkYXlzW20uZGF5KCldXG4gICAgICAgICAgICA6IHdlZWtkYXlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzU2hvcnQobSkge1xuICAgICAgICByZXR1cm4gbSA9PT0gdHJ1ZVxuICAgICAgICAgICAgPyBzaGlmdFdlZWtkYXlzKHRoaXMuX3dlZWtkYXlzU2hvcnQsIHRoaXMuX3dlZWsuZG93KVxuICAgICAgICAgICAgOiBtXG4gICAgICAgICAgICA/IHRoaXMuX3dlZWtkYXlzU2hvcnRbbS5kYXkoKV1cbiAgICAgICAgICAgIDogdGhpcy5fd2Vla2RheXNTaG9ydDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVXZWVrZGF5c01pbihtKSB7XG4gICAgICAgIHJldHVybiBtID09PSB0cnVlXG4gICAgICAgICAgICA/IHNoaWZ0V2Vla2RheXModGhpcy5fd2Vla2RheXNNaW4sIHRoaXMuX3dlZWsuZG93KVxuICAgICAgICAgICAgOiBtXG4gICAgICAgICAgICA/IHRoaXMuX3dlZWtkYXlzTWluW20uZGF5KCldXG4gICAgICAgICAgICA6IHRoaXMuX3dlZWtkYXlzTWluO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhbmRsZVN0cmljdFBhcnNlJDEod2Vla2RheU5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgaWksXG4gICAgICAgICAgICBtb20sXG4gICAgICAgICAgICBsbGMgPSB3ZWVrZGF5TmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAoIXRoaXMuX3dlZWtkYXlzUGFyc2UpIHtcbiAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZSA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgKytpKSB7XG4gICAgICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCAxXSkuZGF5KGkpO1xuICAgICAgICAgICAgICAgIHRoaXMuX21pbldlZWtkYXlzUGFyc2VbaV0gPSB0aGlzLndlZWtkYXlzTWluKFxuICAgICAgICAgICAgICAgICAgICBtb20sXG4gICAgICAgICAgICAgICAgICAgICcnXG4gICAgICAgICAgICAgICAgKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXNTaG9ydChcbiAgICAgICAgICAgICAgICAgICAgbW9tLFxuICAgICAgICAgICAgICAgICAgICAnJ1xuICAgICAgICAgICAgICAgICkudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1BhcnNlW2ldID0gdGhpcy53ZWVrZGF5cyhtb20sICcnKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0cmljdCkge1xuICAgICAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ2RkZGQnKSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fd2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICdkZGQnKSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChmb3JtYXQgPT09ICdkZGRkJykge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3dlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbWluV2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICdkZGQnKSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9taW5XZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3dlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9jYWxlV2Vla2RheXNQYXJzZSh3ZWVrZGF5TmFtZSwgZm9ybWF0LCBzdHJpY3QpIHtcbiAgICAgICAgdmFyIGksIG1vbSwgcmVnZXg7XG5cbiAgICAgICAgaWYgKHRoaXMuX3dlZWtkYXlzUGFyc2VFeGFjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZVN0cmljdFBhcnNlJDEuY2FsbCh0aGlzLCB3ZWVrZGF5TmFtZSwgZm9ybWF0LCBzdHJpY3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl93ZWVrZGF5c1BhcnNlKSB7XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1BhcnNlID0gW107XG4gICAgICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlID0gW107XG4gICAgICAgICAgICB0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2Z1bGxXZWVrZGF5c1BhcnNlID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcblxuICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCAxXSkuZGF5KGkpO1xuICAgICAgICAgICAgaWYgKHN0cmljdCAmJiAhdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9mdWxsV2Vla2RheXNQYXJzZVtpXSA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgICAgICAgICdeJyArIHRoaXMud2Vla2RheXMobW9tLCAnJykucmVwbGFjZSgnLicsICdcXFxcLj8nKSArICckJyxcbiAgICAgICAgICAgICAgICAgICAgJ2knXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgICAgICAgICAnXicgKyB0aGlzLndlZWtkYXlzU2hvcnQobW9tLCAnJykucmVwbGFjZSgnLicsICdcXFxcLj8nKSArICckJyxcbiAgICAgICAgICAgICAgICAgICAgJ2knXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgICAgICAgJ14nICsgdGhpcy53ZWVrZGF5c01pbihtb20sICcnKS5yZXBsYWNlKCcuJywgJ1xcXFwuPycpICsgJyQnLFxuICAgICAgICAgICAgICAgICAgICAnaSdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl93ZWVrZGF5c1BhcnNlW2ldKSB7XG4gICAgICAgICAgICAgICAgcmVnZXggPVxuICAgICAgICAgICAgICAgICAgICAnXicgK1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndlZWtkYXlzKG1vbSwgJycpICtcbiAgICAgICAgICAgICAgICAgICAgJ3xeJyArXG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2Vla2RheXNTaG9ydChtb20sICcnKSArXG4gICAgICAgICAgICAgICAgICAgICd8XicgK1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKHJlZ2V4LnJlcGxhY2UoJy4nLCAnJyksICdpJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB0ZXN0IHRoZSByZWdleFxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHN0cmljdCAmJlxuICAgICAgICAgICAgICAgIGZvcm1hdCA9PT0gJ2RkZGQnICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2VbaV0udGVzdCh3ZWVrZGF5TmFtZSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICBzdHJpY3QgJiZcbiAgICAgICAgICAgICAgICBmb3JtYXQgPT09ICdkZGQnICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlW2ldLnRlc3Qod2Vla2RheU5hbWUpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgc3RyaWN0ICYmXG4gICAgICAgICAgICAgICAgZm9ybWF0ID09PSAnZGQnICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFzdHJpY3QgJiYgdGhpcy5fd2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gZ2V0U2V0RGF5T2ZXZWVrKGlucHV0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsID8gdGhpcyA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF5ID0gdGhpcy5faXNVVEMgPyB0aGlzLl9kLmdldFVUQ0RheSgpIDogdGhpcy5fZC5nZXREYXkoKTtcbiAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlucHV0ID0gcGFyc2VXZWVrZGF5KGlucHV0LCB0aGlzLmxvY2FsZURhdGEoKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoaW5wdXQgLSBkYXksICdkJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZGF5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0TG9jYWxlRGF5T2ZXZWVrKGlucHV0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsID8gdGhpcyA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgd2Vla2RheSA9ICh0aGlzLmRheSgpICsgNyAtIHRoaXMubG9jYWxlRGF0YSgpLl93ZWVrLmRvdykgJSA3O1xuICAgICAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IHdlZWtkYXkgOiB0aGlzLmFkZChpbnB1dCAtIHdlZWtkYXksICdkJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0SVNPRGF5T2ZXZWVrKGlucHV0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsID8gdGhpcyA6IE5hTjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGJlaGF2ZXMgdGhlIHNhbWUgYXMgbW9tZW50I2RheSBleGNlcHRcbiAgICAgICAgLy8gYXMgYSBnZXR0ZXIsIHJldHVybnMgNyBpbnN0ZWFkIG9mIDAgKDEtNyByYW5nZSBpbnN0ZWFkIG9mIDAtNilcbiAgICAgICAgLy8gYXMgYSBzZXR0ZXIsIHN1bmRheSBzaG91bGQgYmVsb25nIHRvIHRoZSBwcmV2aW91cyB3ZWVrLlxuXG4gICAgICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgd2Vla2RheSA9IHBhcnNlSXNvV2Vla2RheShpbnB1dCwgdGhpcy5sb2NhbGVEYXRhKCkpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF5KHRoaXMuZGF5KCkgJSA3ID8gd2Vla2RheSA6IHdlZWtkYXkgLSA3KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRheSgpIHx8IDc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB3ZWVrZGF5c1JlZ2V4KGlzU3RyaWN0KSB7XG4gICAgICAgIGlmICh0aGlzLl93ZWVrZGF5c1BhcnNlRXhhY3QpIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzUmVnZXgnKSkge1xuICAgICAgICAgICAgICAgIGNvbXB1dGVXZWVrZGF5c1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzUmVnZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1JlZ2V4ID0gZGVmYXVsdFdlZWtkYXlzUmVnZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleCAmJiBpc1N0cmljdFxuICAgICAgICAgICAgICAgID8gdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleFxuICAgICAgICAgICAgICAgIDogdGhpcy5fd2Vla2RheXNSZWdleDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHdlZWtkYXlzU2hvcnRSZWdleChpc1N0cmljdCkge1xuICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU2hvcnRTdHJpY3RSZWdleDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU2hvcnRSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzU2hvcnRSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4ID0gZGVmYXVsdFdlZWtkYXlzU2hvcnRSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggJiYgaXNTdHJpY3RcbiAgICAgICAgICAgICAgICA/IHRoaXMuX3dlZWtkYXlzU2hvcnRTdHJpY3RSZWdleFxuICAgICAgICAgICAgICAgIDogdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gd2Vla2RheXNNaW5SZWdleChpc1N0cmljdCkge1xuICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNNaW5SZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNNaW5SZWdleCA9IGRlZmF1bHRXZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXggJiYgaXNTdHJpY3RcbiAgICAgICAgICAgICAgICA/IHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXhcbiAgICAgICAgICAgICAgICA6IHRoaXMuX3dlZWtkYXlzTWluUmVnZXg7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb21wdXRlV2Vla2RheXNQYXJzZSgpIHtcbiAgICAgICAgZnVuY3Rpb24gY21wTGVuUmV2KGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiBiLmxlbmd0aCAtIGEubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1pblBpZWNlcyA9IFtdLFxuICAgICAgICAgICAgc2hvcnRQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIGxvbmdQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIG1peGVkUGllY2VzID0gW10sXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgbW9tLFxuICAgICAgICAgICAgbWlucCxcbiAgICAgICAgICAgIHNob3J0cCxcbiAgICAgICAgICAgIGxvbmdwO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcbiAgICAgICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgMV0pLmRheShpKTtcbiAgICAgICAgICAgIG1pbnAgPSByZWdleEVzY2FwZSh0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpKTtcbiAgICAgICAgICAgIHNob3J0cCA9IHJlZ2V4RXNjYXBlKHRoaXMud2Vla2RheXNTaG9ydChtb20sICcnKSk7XG4gICAgICAgICAgICBsb25ncCA9IHJlZ2V4RXNjYXBlKHRoaXMud2Vla2RheXMobW9tLCAnJykpO1xuICAgICAgICAgICAgbWluUGllY2VzLnB1c2gobWlucCk7XG4gICAgICAgICAgICBzaG9ydFBpZWNlcy5wdXNoKHNob3J0cCk7XG4gICAgICAgICAgICBsb25nUGllY2VzLnB1c2gobG9uZ3ApO1xuICAgICAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChtaW5wKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2goc2hvcnRwKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2gobG9uZ3ApO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgd2Vla2RheSAob3IgYWJicikgaXMgYSBwcmVmaXggb2YgYW5vdGhlciBpdFxuICAgICAgICAvLyB3aWxsIG1hdGNoIHRoZSBsb25nZXIgcGllY2UuXG4gICAgICAgIG1pblBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIHNob3J0UGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICAgICAgbG9uZ1BpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIG1peGVkUGllY2VzLnNvcnQoY21wTGVuUmV2KTtcblxuICAgICAgICB0aGlzLl93ZWVrZGF5c1JlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgbWl4ZWRQaWVjZXMuam9pbignfCcpICsgJyknLCAnaScpO1xuICAgICAgICB0aGlzLl93ZWVrZGF5c1Nob3J0UmVnZXggPSB0aGlzLl93ZWVrZGF5c1JlZ2V4O1xuICAgICAgICB0aGlzLl93ZWVrZGF5c01pblJlZ2V4ID0gdGhpcy5fd2Vla2RheXNSZWdleDtcblxuICAgICAgICB0aGlzLl93ZWVrZGF5c1N0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICdeKCcgKyBsb25nUGllY2VzLmpvaW4oJ3wnKSArICcpJyxcbiAgICAgICAgICAgICdpJ1xuICAgICAgICApO1xuICAgICAgICB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgJ14oJyArIHNob3J0UGllY2VzLmpvaW4oJ3wnKSArICcpJyxcbiAgICAgICAgICAgICdpJ1xuICAgICAgICApO1xuICAgICAgICB0aGlzLl93ZWVrZGF5c01pblN0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICdeKCcgKyBtaW5QaWVjZXMuam9pbignfCcpICsgJyknLFxuICAgICAgICAgICAgJ2knXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgZnVuY3Rpb24gaEZvcm1hdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaG91cnMoKSAlIDEyIHx8IDEyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGtGb3JtYXQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhvdXJzKCkgfHwgMjQ7XG4gICAgfVxuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ0gnLCBbJ0hIJywgMl0sIDAsICdob3VyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ2gnLCBbJ2hoJywgMl0sIDAsIGhGb3JtYXQpO1xuICAgIGFkZEZvcm1hdFRva2VuKCdrJywgWydraycsIDJdLCAwLCBrRm9ybWF0KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdobW0nLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAnJyArIGhGb3JtYXQuYXBwbHkodGhpcykgKyB6ZXJvRmlsbCh0aGlzLm1pbnV0ZXMoKSwgMik7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignaG1tc3MnLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAnJyArXG4gICAgICAgICAgICBoRm9ybWF0LmFwcGx5KHRoaXMpICtcbiAgICAgICAgICAgIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKSArXG4gICAgICAgICAgICB6ZXJvRmlsbCh0aGlzLnNlY29uZHMoKSwgMilcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdIbW0nLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAnJyArIHRoaXMuaG91cnMoKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdIbW1zcycsIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICcnICtcbiAgICAgICAgICAgIHRoaXMuaG91cnMoKSArXG4gICAgICAgICAgICB6ZXJvRmlsbCh0aGlzLm1pbnV0ZXMoKSwgMikgK1xuICAgICAgICAgICAgemVyb0ZpbGwodGhpcy5zZWNvbmRzKCksIDIpXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBtZXJpZGllbSh0b2tlbiwgbG93ZXJjYXNlKSB7XG4gICAgICAgIGFkZEZvcm1hdFRva2VuKHRva2VuLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubWVyaWRpZW0oXG4gICAgICAgICAgICAgICAgdGhpcy5ob3VycygpLFxuICAgICAgICAgICAgICAgIHRoaXMubWludXRlcygpLFxuICAgICAgICAgICAgICAgIGxvd2VyY2FzZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgbWVyaWRpZW0oJ2EnLCB0cnVlKTtcbiAgICBtZXJpZGllbSgnQScsIGZhbHNlKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnaG91cicsICdoJyk7XG5cbiAgICAvLyBQUklPUklUWVxuICAgIGFkZFVuaXRQcmlvcml0eSgnaG91cicsIDEzKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGZ1bmN0aW9uIG1hdGNoTWVyaWRpZW0oaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLl9tZXJpZGllbVBhcnNlO1xuICAgIH1cblxuICAgIGFkZFJlZ2V4VG9rZW4oJ2EnLCBtYXRjaE1lcmlkaWVtKTtcbiAgICBhZGRSZWdleFRva2VuKCdBJywgbWF0Y2hNZXJpZGllbSk7XG4gICAgYWRkUmVnZXhUb2tlbignSCcsIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignaCcsIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignaycsIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignSEgnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbignaGgnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbigna2snLCBtYXRjaDF0bzIsIG1hdGNoMik7XG5cbiAgICBhZGRSZWdleFRva2VuKCdobW0nLCBtYXRjaDN0bzQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2htbXNzJywgbWF0Y2g1dG82KTtcbiAgICBhZGRSZWdleFRva2VuKCdIbW0nLCBtYXRjaDN0bzQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0htbXNzJywgbWF0Y2g1dG82KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydIJywgJ0hIJ10sIEhPVVIpO1xuICAgIGFkZFBhcnNlVG9rZW4oWydrJywgJ2trJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICB2YXIga0lucHV0ID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICBhcnJheVtIT1VSXSA9IGtJbnB1dCA9PT0gMjQgPyAwIDoga0lucHV0O1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oWydhJywgJ0EnXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZy5faXNQbSA9IGNvbmZpZy5fbG9jYWxlLmlzUE0oaW5wdXQpO1xuICAgICAgICBjb25maWcuX21lcmlkaWVtID0gaW5wdXQ7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbihbJ2gnLCAnaGgnXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID0gdHJ1ZTtcbiAgICB9KTtcbiAgICBhZGRQYXJzZVRva2VuKCdobW0nLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgdmFyIHBvcyA9IGlucHV0Lmxlbmd0aCAtIDI7XG4gICAgICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvcykpO1xuICAgICAgICBhcnJheVtNSU5VVEVdID0gdG9JbnQoaW5wdXQuc3Vic3RyKHBvcykpO1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID0gdHJ1ZTtcbiAgICB9KTtcbiAgICBhZGRQYXJzZVRva2VuKCdobW1zcycsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICB2YXIgcG9zMSA9IGlucHV0Lmxlbmd0aCAtIDQsXG4gICAgICAgICAgICBwb3MyID0gaW5wdXQubGVuZ3RoIC0gMjtcbiAgICAgICAgYXJyYXlbSE9VUl0gPSB0b0ludChpbnB1dC5zdWJzdHIoMCwgcG9zMSkpO1xuICAgICAgICBhcnJheVtNSU5VVEVdID0gdG9JbnQoaW5wdXQuc3Vic3RyKHBvczEsIDIpKTtcbiAgICAgICAgYXJyYXlbU0VDT05EXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MyKSk7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmJpZ0hvdXIgPSB0cnVlO1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oJ0htbScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICB2YXIgcG9zID0gaW5wdXQubGVuZ3RoIC0gMjtcbiAgICAgICAgYXJyYXlbSE9VUl0gPSB0b0ludChpbnB1dC5zdWJzdHIoMCwgcG9zKSk7XG4gICAgICAgIGFycmF5W01JTlVURV0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zKSk7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbignSG1tc3MnLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgdmFyIHBvczEgPSBpbnB1dC5sZW5ndGggLSA0LFxuICAgICAgICAgICAgcG9zMiA9IGlucHV0Lmxlbmd0aCAtIDI7XG4gICAgICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvczEpKTtcbiAgICAgICAgYXJyYXlbTUlOVVRFXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MxLCAyKSk7XG4gICAgICAgIGFycmF5W1NFQ09ORF0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zMikpO1xuICAgIH0pO1xuXG4gICAgLy8gTE9DQUxFU1xuXG4gICAgZnVuY3Rpb24gbG9jYWxlSXNQTShpbnB1dCkge1xuICAgICAgICAvLyBJRTggUXVpcmtzIE1vZGUgJiBJRTcgU3RhbmRhcmRzIE1vZGUgZG8gbm90IGFsbG93IGFjY2Vzc2luZyBzdHJpbmdzIGxpa2UgYXJyYXlzXG4gICAgICAgIC8vIFVzaW5nIGNoYXJBdCBzaG91bGQgYmUgbW9yZSBjb21wYXRpYmxlLlxuICAgICAgICByZXR1cm4gKGlucHV0ICsgJycpLnRvTG93ZXJDYXNlKCkuY2hhckF0KDApID09PSAncCc7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb2NhbGVNZXJpZGllbVBhcnNlID0gL1thcF1cXC4/bT9cXC4/L2ksXG4gICAgICAgIC8vIFNldHRpbmcgdGhlIGhvdXIgc2hvdWxkIGtlZXAgdGhlIHRpbWUsIGJlY2F1c2UgdGhlIHVzZXIgZXhwbGljaXRseVxuICAgICAgICAvLyBzcGVjaWZpZWQgd2hpY2ggaG91ciB0aGV5IHdhbnQuIFNvIHRyeWluZyB0byBtYWludGFpbiB0aGUgc2FtZSBob3VyIChpblxuICAgICAgICAvLyBhIG5ldyB0aW1lem9uZSkgbWFrZXMgc2Vuc2UuIEFkZGluZy9zdWJ0cmFjdGluZyBob3VycyBkb2VzIG5vdCBmb2xsb3dcbiAgICAgICAgLy8gdGhpcyBydWxlLlxuICAgICAgICBnZXRTZXRIb3VyID0gbWFrZUdldFNldCgnSG91cnMnLCB0cnVlKTtcblxuICAgIGZ1bmN0aW9uIGxvY2FsZU1lcmlkaWVtKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VycyA+IDExKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdwbScgOiAnUE0nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnYW0nIDogJ0FNJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBiYXNlQ29uZmlnID0ge1xuICAgICAgICBjYWxlbmRhcjogZGVmYXVsdENhbGVuZGFyLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDogZGVmYXVsdExvbmdEYXRlRm9ybWF0LFxuICAgICAgICBpbnZhbGlkRGF0ZTogZGVmYXVsdEludmFsaWREYXRlLFxuICAgICAgICBvcmRpbmFsOiBkZWZhdWx0T3JkaW5hbCxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogZGVmYXVsdERheU9mTW9udGhPcmRpbmFsUGFyc2UsXG4gICAgICAgIHJlbGF0aXZlVGltZTogZGVmYXVsdFJlbGF0aXZlVGltZSxcblxuICAgICAgICBtb250aHM6IGRlZmF1bHRMb2NhbGVNb250aHMsXG4gICAgICAgIG1vbnRoc1Nob3J0OiBkZWZhdWx0TG9jYWxlTW9udGhzU2hvcnQsXG5cbiAgICAgICAgd2VlazogZGVmYXVsdExvY2FsZVdlZWssXG5cbiAgICAgICAgd2Vla2RheXM6IGRlZmF1bHRMb2NhbGVXZWVrZGF5cyxcbiAgICAgICAgd2Vla2RheXNNaW46IGRlZmF1bHRMb2NhbGVXZWVrZGF5c01pbixcbiAgICAgICAgd2Vla2RheXNTaG9ydDogZGVmYXVsdExvY2FsZVdlZWtkYXlzU2hvcnQsXG5cbiAgICAgICAgbWVyaWRpZW1QYXJzZTogZGVmYXVsdExvY2FsZU1lcmlkaWVtUGFyc2UsXG4gICAgfTtcblxuICAgIC8vIGludGVybmFsIHN0b3JhZ2UgZm9yIGxvY2FsZSBjb25maWcgZmlsZXNcbiAgICB2YXIgbG9jYWxlcyA9IHt9LFxuICAgICAgICBsb2NhbGVGYW1pbGllcyA9IHt9LFxuICAgICAgICBnbG9iYWxMb2NhbGU7XG5cbiAgICBmdW5jdGlvbiBjb21tb25QcmVmaXgoYXJyMSwgYXJyMikge1xuICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgIG1pbmwgPSBNYXRoLm1pbihhcnIxLmxlbmd0aCwgYXJyMi5sZW5ndGgpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbWlubDsgaSArPSAxKSB7XG4gICAgICAgICAgICBpZiAoYXJyMVtpXSAhPT0gYXJyMltpXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtaW5sO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZUxvY2FsZShrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleSA/IGtleS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoJ18nLCAnLScpIDoga2V5O1xuICAgIH1cblxuICAgIC8vIHBpY2sgdGhlIGxvY2FsZSBmcm9tIHRoZSBhcnJheVxuICAgIC8vIHRyeSBbJ2VuLWF1JywgJ2VuLWdiJ10gYXMgJ2VuLWF1JywgJ2VuLWdiJywgJ2VuJywgYXMgaW4gbW92ZSB0aHJvdWdoIHRoZSBsaXN0IHRyeWluZyBlYWNoXG4gICAgLy8gc3Vic3RyaW5nIGZyb20gbW9zdCBzcGVjaWZpYyB0byBsZWFzdCwgYnV0IG1vdmUgdG8gdGhlIG5leHQgYXJyYXkgaXRlbSBpZiBpdCdzIGEgbW9yZSBzcGVjaWZpYyB2YXJpYW50IHRoYW4gdGhlIGN1cnJlbnQgcm9vdFxuICAgIGZ1bmN0aW9uIGNob29zZUxvY2FsZShuYW1lcykge1xuICAgICAgICB2YXIgaSA9IDAsXG4gICAgICAgICAgICBqLFxuICAgICAgICAgICAgbmV4dCxcbiAgICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICAgIHNwbGl0O1xuXG4gICAgICAgIHdoaWxlIChpIDwgbmFtZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBzcGxpdCA9IG5vcm1hbGl6ZUxvY2FsZShuYW1lc1tpXSkuc3BsaXQoJy0nKTtcbiAgICAgICAgICAgIGogPSBzcGxpdC5sZW5ndGg7XG4gICAgICAgICAgICBuZXh0ID0gbm9ybWFsaXplTG9jYWxlKG5hbWVzW2kgKyAxXSk7XG4gICAgICAgICAgICBuZXh0ID0gbmV4dCA/IG5leHQuc3BsaXQoJy0nKSA6IG51bGw7XG4gICAgICAgICAgICB3aGlsZSAoaiA+IDApIHtcbiAgICAgICAgICAgICAgICBsb2NhbGUgPSBsb2FkTG9jYWxlKHNwbGl0LnNsaWNlKDAsIGopLmpvaW4oJy0nKSk7XG4gICAgICAgICAgICAgICAgaWYgKGxvY2FsZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbG9jYWxlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIG5leHQgJiZcbiAgICAgICAgICAgICAgICAgICAgbmV4dC5sZW5ndGggPj0gaiAmJlxuICAgICAgICAgICAgICAgICAgICBjb21tb25QcmVmaXgoc3BsaXQsIG5leHQpID49IGogLSAxXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vdGhlIG5leHQgYXJyYXkgaXRlbSBpcyBiZXR0ZXIgdGhhbiBhIHNoYWxsb3dlciBzdWJzdHJpbmcgb2YgdGhpcyBvbmVcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGotLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZ2xvYmFsTG9jYWxlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvYWRMb2NhbGUobmFtZSkge1xuICAgICAgICB2YXIgb2xkTG9jYWxlID0gbnVsbCxcbiAgICAgICAgICAgIGFsaWFzZWRSZXF1aXJlO1xuICAgICAgICAvLyBUT0RPOiBGaW5kIGEgYmV0dGVyIHdheSB0byByZWdpc3RlciBhbmQgbG9hZCBhbGwgdGhlIGxvY2FsZXMgaW4gTm9kZVxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBsb2NhbGVzW25hbWVdID09PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICBtb2R1bGUgJiZcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzXG4gICAgICAgICkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBvbGRMb2NhbGUgPSBnbG9iYWxMb2NhbGUuX2FiYnI7XG4gICAgICAgICAgICAgICAgYWxpYXNlZFJlcXVpcmUgPSByZXF1aXJlO1xuICAgICAgICAgICAgICAgIGFsaWFzZWRSZXF1aXJlKCcuL2xvY2FsZS8nICsgbmFtZSk7XG4gICAgICAgICAgICAgICAgZ2V0U2V0R2xvYmFsTG9jYWxlKG9sZExvY2FsZSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gbWFyayBhcyBub3QgZm91bmQgdG8gYXZvaWQgcmVwZWF0aW5nIGV4cGVuc2l2ZSBmaWxlIHJlcXVpcmUgY2FsbCBjYXVzaW5nIGhpZ2ggQ1BVXG4gICAgICAgICAgICAgICAgLy8gd2hlbiB0cnlpbmcgdG8gZmluZCBlbi1VUywgZW5fVVMsIGVuLXVzIGZvciBldmVyeSBmb3JtYXQgY2FsbFxuICAgICAgICAgICAgICAgIGxvY2FsZXNbbmFtZV0gPSBudWxsOyAvLyBudWxsIG1lYW5zIG5vdCBmb3VuZFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsb2NhbGVzW25hbWVdO1xuICAgIH1cblxuICAgIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBsb2FkIGxvY2FsZSBhbmQgdGhlbiBzZXQgdGhlIGdsb2JhbCBsb2NhbGUuICBJZlxuICAgIC8vIG5vIGFyZ3VtZW50cyBhcmUgcGFzc2VkIGluLCBpdCB3aWxsIHNpbXBseSByZXR1cm4gdGhlIGN1cnJlbnQgZ2xvYmFsXG4gICAgLy8gbG9jYWxlIGtleS5cbiAgICBmdW5jdGlvbiBnZXRTZXRHbG9iYWxMb2NhbGUoa2V5LCB2YWx1ZXMpIHtcbiAgICAgICAgdmFyIGRhdGE7XG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgIGlmIChpc1VuZGVmaW5lZCh2YWx1ZXMpKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9IGdldExvY2FsZShrZXkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gZGVmaW5lTG9jYWxlKGtleSwgdmFsdWVzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAvLyBtb21lbnQuZHVyYXRpb24uX2xvY2FsZSA9IG1vbWVudC5fbG9jYWxlID0gZGF0YTtcbiAgICAgICAgICAgICAgICBnbG9iYWxMb2NhbGUgPSBkYXRhO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgICAgICAgICAgICAvL3dhcm4gdXNlciBpZiBhcmd1bWVudHMgYXJlIHBhc3NlZCBidXQgdGhlIGxvY2FsZSBjb3VsZCBub3QgYmUgc2V0XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICAgICAgICAgICdMb2NhbGUgJyArIGtleSArICcgbm90IGZvdW5kLiBEaWQgeW91IGZvcmdldCB0byBsb2FkIGl0PydcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZ2xvYmFsTG9jYWxlLl9hYmJyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlZmluZUxvY2FsZShuYW1lLCBjb25maWcpIHtcbiAgICAgICAgaWYgKGNvbmZpZyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGxvY2FsZSxcbiAgICAgICAgICAgICAgICBwYXJlbnRDb25maWcgPSBiYXNlQ29uZmlnO1xuICAgICAgICAgICAgY29uZmlnLmFiYnIgPSBuYW1lO1xuICAgICAgICAgICAgaWYgKGxvY2FsZXNbbmFtZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRlcHJlY2F0ZVNpbXBsZShcbiAgICAgICAgICAgICAgICAgICAgJ2RlZmluZUxvY2FsZU92ZXJyaWRlJyxcbiAgICAgICAgICAgICAgICAgICAgJ3VzZSBtb21lbnQudXBkYXRlTG9jYWxlKGxvY2FsZU5hbWUsIGNvbmZpZykgdG8gY2hhbmdlICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ2FuIGV4aXN0aW5nIGxvY2FsZS4gbW9tZW50LmRlZmluZUxvY2FsZShsb2NhbGVOYW1lLCAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdjb25maWcpIHNob3VsZCBvbmx5IGJlIHVzZWQgZm9yIGNyZWF0aW5nIGEgbmV3IGxvY2FsZSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdTZWUgaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9kZWZpbmUtbG9jYWxlLyBmb3IgbW9yZSBpbmZvLidcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHBhcmVudENvbmZpZyA9IGxvY2FsZXNbbmFtZV0uX2NvbmZpZztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29uZmlnLnBhcmVudExvY2FsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvY2FsZXNbY29uZmlnLnBhcmVudExvY2FsZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnRDb25maWcgPSBsb2NhbGVzW2NvbmZpZy5wYXJlbnRMb2NhbGVdLl9jb25maWc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbG9jYWxlID0gbG9hZExvY2FsZShjb25maWcucGFyZW50TG9jYWxlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxvY2FsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRDb25maWcgPSBsb2NhbGUuX2NvbmZpZztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbG9jYWxlRmFtaWxpZXNbY29uZmlnLnBhcmVudExvY2FsZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGVGYW1pbGllc1tjb25maWcucGFyZW50TG9jYWxlXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxlRmFtaWxpZXNbY29uZmlnLnBhcmVudExvY2FsZV0ucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IGNvbmZpZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsb2NhbGVzW25hbWVdID0gbmV3IExvY2FsZShtZXJnZUNvbmZpZ3MocGFyZW50Q29uZmlnLCBjb25maWcpKTtcblxuICAgICAgICAgICAgaWYgKGxvY2FsZUZhbWlsaWVzW25hbWVdKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxlRmFtaWxpZXNbbmFtZV0uZm9yRWFjaChmdW5jdGlvbiAoeCkge1xuICAgICAgICAgICAgICAgICAgICBkZWZpbmVMb2NhbGUoeC5uYW1lLCB4LmNvbmZpZyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGJhY2t3YXJkcyBjb21wYXQgZm9yIG5vdzogYWxzbyBzZXQgdGhlIGxvY2FsZVxuICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHdlIHNldCB0aGUgbG9jYWxlIEFGVEVSIGFsbCBjaGlsZCBsb2NhbGVzIGhhdmUgYmVlblxuICAgICAgICAgICAgLy8gY3JlYXRlZCwgc28gd2Ugd29uJ3QgZW5kIHVwIHdpdGggdGhlIGNoaWxkIGxvY2FsZSBzZXQuXG4gICAgICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG5cbiAgICAgICAgICAgIHJldHVybiBsb2NhbGVzW25hbWVdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdXNlZnVsIGZvciB0ZXN0aW5nXG4gICAgICAgICAgICBkZWxldGUgbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlTG9jYWxlKG5hbWUsIGNvbmZpZykge1xuICAgICAgICBpZiAoY29uZmlnICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBsb2NhbGUsXG4gICAgICAgICAgICAgICAgdG1wTG9jYWxlLFxuICAgICAgICAgICAgICAgIHBhcmVudENvbmZpZyA9IGJhc2VDb25maWc7XG5cbiAgICAgICAgICAgIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwgJiYgbG9jYWxlc1tuYW1lXS5wYXJlbnRMb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBjaGlsZCBsb2NhbGUgaW4tcGxhY2UgdG8gYXZvaWQgbWVtb3J5LWxlYWtzXG4gICAgICAgICAgICAgICAgbG9jYWxlc1tuYW1lXS5zZXQobWVyZ2VDb25maWdzKGxvY2FsZXNbbmFtZV0uX2NvbmZpZywgY29uZmlnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIE1FUkdFXG4gICAgICAgICAgICAgICAgdG1wTG9jYWxlID0gbG9hZExvY2FsZShuYW1lKTtcbiAgICAgICAgICAgICAgICBpZiAodG1wTG9jYWxlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Q29uZmlnID0gdG1wTG9jYWxlLl9jb25maWc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbmZpZyA9IG1lcmdlQ29uZmlncyhwYXJlbnRDb25maWcsIGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgaWYgKHRtcExvY2FsZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHVwZGF0ZUxvY2FsZSBpcyBjYWxsZWQgZm9yIGNyZWF0aW5nIGEgbmV3IGxvY2FsZVxuICAgICAgICAgICAgICAgICAgICAvLyBTZXQgYWJiciBzbyBpdCB3aWxsIGhhdmUgYSBuYW1lIChnZXR0ZXJzIHJldHVyblxuICAgICAgICAgICAgICAgICAgICAvLyB1bmRlZmluZWQgb3RoZXJ3aXNlKS5cbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLmFiYnIgPSBuYW1lO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsb2NhbGUgPSBuZXcgTG9jYWxlKGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgbG9jYWxlLnBhcmVudExvY2FsZSA9IGxvY2FsZXNbbmFtZV07XG4gICAgICAgICAgICAgICAgbG9jYWxlc1tuYW1lXSA9IGxvY2FsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gYmFja3dhcmRzIGNvbXBhdCBmb3Igbm93OiBhbHNvIHNldCB0aGUgbG9jYWxlXG4gICAgICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBwYXNzIG51bGwgZm9yIGNvbmZpZyB0byB1bnVwZGF0ZSwgdXNlZnVsIGZvciB0ZXN0c1xuICAgICAgICAgICAgaWYgKGxvY2FsZXNbbmFtZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmIChsb2NhbGVzW25hbWVdLnBhcmVudExvY2FsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvY2FsZXNbbmFtZV0gPSBsb2NhbGVzW25hbWVdLnBhcmVudExvY2FsZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgPT09IGdldFNldEdsb2JhbExvY2FsZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGxvY2FsZXNbbmFtZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxvY2FsZXNbbmFtZV07XG4gICAgfVxuXG4gICAgLy8gcmV0dXJucyBsb2NhbGUgZGF0YVxuICAgIGZ1bmN0aW9uIGdldExvY2FsZShrZXkpIHtcbiAgICAgICAgdmFyIGxvY2FsZTtcblxuICAgICAgICBpZiAoa2V5ICYmIGtleS5fbG9jYWxlICYmIGtleS5fbG9jYWxlLl9hYmJyKSB7XG4gICAgICAgICAgICBrZXkgPSBrZXkuX2xvY2FsZS5fYWJicjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgha2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gZ2xvYmFsTG9jYWxlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpc0FycmF5KGtleSkpIHtcbiAgICAgICAgICAgIC8vc2hvcnQtY2lyY3VpdCBldmVyeXRoaW5nIGVsc2VcbiAgICAgICAgICAgIGxvY2FsZSA9IGxvYWRMb2NhbGUoa2V5KTtcbiAgICAgICAgICAgIGlmIChsb2NhbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9jYWxlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAga2V5ID0gW2tleV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2hvb3NlTG9jYWxlKGtleSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdExvY2FsZXMoKSB7XG4gICAgICAgIHJldHVybiBrZXlzKGxvY2FsZXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNoZWNrT3ZlcmZsb3cobSkge1xuICAgICAgICB2YXIgb3ZlcmZsb3csXG4gICAgICAgICAgICBhID0gbS5fYTtcblxuICAgICAgICBpZiAoYSAmJiBnZXRQYXJzaW5nRmxhZ3MobSkub3ZlcmZsb3cgPT09IC0yKSB7XG4gICAgICAgICAgICBvdmVyZmxvdyA9XG4gICAgICAgICAgICAgICAgYVtNT05USF0gPCAwIHx8IGFbTU9OVEhdID4gMTFcbiAgICAgICAgICAgICAgICAgICAgPyBNT05USFxuICAgICAgICAgICAgICAgICAgICA6IGFbREFURV0gPCAxIHx8IGFbREFURV0gPiBkYXlzSW5Nb250aChhW1lFQVJdLCBhW01PTlRIXSlcbiAgICAgICAgICAgICAgICAgICAgPyBEQVRFXG4gICAgICAgICAgICAgICAgICAgIDogYVtIT1VSXSA8IDAgfHxcbiAgICAgICAgICAgICAgICAgICAgICBhW0hPVVJdID4gMjQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAoYVtIT1VSXSA9PT0gMjQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKGFbTUlOVVRFXSAhPT0gMCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYVtTRUNPTkRdICE9PSAwIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhW01JTExJU0VDT05EXSAhPT0gMCkpXG4gICAgICAgICAgICAgICAgICAgID8gSE9VUlxuICAgICAgICAgICAgICAgICAgICA6IGFbTUlOVVRFXSA8IDAgfHwgYVtNSU5VVEVdID4gNTlcbiAgICAgICAgICAgICAgICAgICAgPyBNSU5VVEVcbiAgICAgICAgICAgICAgICAgICAgOiBhW1NFQ09ORF0gPCAwIHx8IGFbU0VDT05EXSA+IDU5XG4gICAgICAgICAgICAgICAgICAgID8gU0VDT05EXG4gICAgICAgICAgICAgICAgICAgIDogYVtNSUxMSVNFQ09ORF0gPCAwIHx8IGFbTUlMTElTRUNPTkRdID4gOTk5XG4gICAgICAgICAgICAgICAgICAgID8gTUlMTElTRUNPTkRcbiAgICAgICAgICAgICAgICAgICAgOiAtMTtcblxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhtKS5fb3ZlcmZsb3dEYXlPZlllYXIgJiZcbiAgICAgICAgICAgICAgICAob3ZlcmZsb3cgPCBZRUFSIHx8IG92ZXJmbG93ID4gREFURSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIG92ZXJmbG93ID0gREFURTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChnZXRQYXJzaW5nRmxhZ3MobSkuX292ZXJmbG93V2Vla3MgJiYgb3ZlcmZsb3cgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgb3ZlcmZsb3cgPSBXRUVLO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdldFBhcnNpbmdGbGFncyhtKS5fb3ZlcmZsb3dXZWVrZGF5ICYmIG92ZXJmbG93ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIG92ZXJmbG93ID0gV0VFS0RBWTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKG0pLm92ZXJmbG93ID0gb3ZlcmZsb3c7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbTtcbiAgICB9XG5cbiAgICAvLyBpc28gODYwMSByZWdleFxuICAgIC8vIDAwMDAtMDAtMDAgMDAwMC1XMDAgb3IgMDAwMC1XMDAtMCArIFQgKyAwMCBvciAwMDowMCBvciAwMDowMDowMCBvciAwMDowMDowMC4wMDAgKyArMDA6MDAgb3IgKzAwMDAgb3IgKzAwKVxuICAgIHZhciBleHRlbmRlZElzb1JlZ2V4ID0gL15cXHMqKCg/OlsrLV1cXGR7Nn18XFxkezR9KS0oPzpcXGRcXGQtXFxkXFxkfFdcXGRcXGQtXFxkfFdcXGRcXGR8XFxkXFxkXFxkfFxcZFxcZCkpKD86KFR8ICkoXFxkXFxkKD86OlxcZFxcZCg/OjpcXGRcXGQoPzpbLixdXFxkKyk/KT8pPykoWystXVxcZFxcZCg/Ojo/XFxkXFxkKT98XFxzKlopPyk/JC8sXG4gICAgICAgIGJhc2ljSXNvUmVnZXggPSAvXlxccyooKD86WystXVxcZHs2fXxcXGR7NH0pKD86XFxkXFxkXFxkXFxkfFdcXGRcXGRcXGR8V1xcZFxcZHxcXGRcXGRcXGR8XFxkXFxkfCkpKD86KFR8ICkoXFxkXFxkKD86XFxkXFxkKD86XFxkXFxkKD86Wy4sXVxcZCspPyk/KT8pKFsrLV1cXGRcXGQoPzo6P1xcZFxcZCk/fFxccypaKT8pPyQvLFxuICAgICAgICB0elJlZ2V4ID0gL1p8WystXVxcZFxcZCg/Ojo/XFxkXFxkKT8vLFxuICAgICAgICBpc29EYXRlcyA9IFtcbiAgICAgICAgICAgIFsnWVlZWVlZLU1NLUREJywgL1srLV1cXGR7Nn0tXFxkXFxkLVxcZFxcZC9dLFxuICAgICAgICAgICAgWydZWVlZLU1NLUREJywgL1xcZHs0fS1cXGRcXGQtXFxkXFxkL10sXG4gICAgICAgICAgICBbJ0dHR0ctW1ddV1ctRScsIC9cXGR7NH0tV1xcZFxcZC1cXGQvXSxcbiAgICAgICAgICAgIFsnR0dHRy1bV11XVycsIC9cXGR7NH0tV1xcZFxcZC8sIGZhbHNlXSxcbiAgICAgICAgICAgIFsnWVlZWS1EREQnLCAvXFxkezR9LVxcZHszfS9dLFxuICAgICAgICAgICAgWydZWVlZLU1NJywgL1xcZHs0fS1cXGRcXGQvLCBmYWxzZV0sXG4gICAgICAgICAgICBbJ1lZWVlZWU1NREQnLCAvWystXVxcZHsxMH0vXSxcbiAgICAgICAgICAgIFsnWVlZWU1NREQnLCAvXFxkezh9L10sXG4gICAgICAgICAgICBbJ0dHR0dbV11XV0UnLCAvXFxkezR9V1xcZHszfS9dLFxuICAgICAgICAgICAgWydHR0dHW1ddV1cnLCAvXFxkezR9V1xcZHsyfS8sIGZhbHNlXSxcbiAgICAgICAgICAgIFsnWVlZWURERCcsIC9cXGR7N30vXSxcbiAgICAgICAgICAgIFsnWVlZWU1NJywgL1xcZHs2fS8sIGZhbHNlXSxcbiAgICAgICAgICAgIFsnWVlZWScsIC9cXGR7NH0vLCBmYWxzZV0sXG4gICAgICAgIF0sXG4gICAgICAgIC8vIGlzbyB0aW1lIGZvcm1hdHMgYW5kIHJlZ2V4ZXNcbiAgICAgICAgaXNvVGltZXMgPSBbXG4gICAgICAgICAgICBbJ0hIOm1tOnNzLlNTU1MnLCAvXFxkXFxkOlxcZFxcZDpcXGRcXGRcXC5cXGQrL10sXG4gICAgICAgICAgICBbJ0hIOm1tOnNzLFNTU1MnLCAvXFxkXFxkOlxcZFxcZDpcXGRcXGQsXFxkKy9dLFxuICAgICAgICAgICAgWydISDptbTpzcycsIC9cXGRcXGQ6XFxkXFxkOlxcZFxcZC9dLFxuICAgICAgICAgICAgWydISDptbScsIC9cXGRcXGQ6XFxkXFxkL10sXG4gICAgICAgICAgICBbJ0hIbW1zcy5TU1NTJywgL1xcZFxcZFxcZFxcZFxcZFxcZFxcLlxcZCsvXSxcbiAgICAgICAgICAgIFsnSEhtbXNzLFNTU1MnLCAvXFxkXFxkXFxkXFxkXFxkXFxkLFxcZCsvXSxcbiAgICAgICAgICAgIFsnSEhtbXNzJywgL1xcZFxcZFxcZFxcZFxcZFxcZC9dLFxuICAgICAgICAgICAgWydISG1tJywgL1xcZFxcZFxcZFxcZC9dLFxuICAgICAgICAgICAgWydISCcsIC9cXGRcXGQvXSxcbiAgICAgICAgXSxcbiAgICAgICAgYXNwTmV0SnNvblJlZ2V4ID0gL15cXC8/RGF0ZVxcKCgtP1xcZCspL2ksXG4gICAgICAgIC8vIFJGQyAyODIyIHJlZ2V4OiBGb3IgZGV0YWlscyBzZWUgaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzI4MjIjc2VjdGlvbi0zLjNcbiAgICAgICAgcmZjMjgyMiA9IC9eKD86KE1vbnxUdWV8V2VkfFRodXxGcml8U2F0fFN1biksP1xccyk/KFxcZHsxLDJ9KVxccyhKYW58RmVifE1hcnxBcHJ8TWF5fEp1bnxKdWx8QXVnfFNlcHxPY3R8Tm92fERlYylcXHMoXFxkezIsNH0pXFxzKFxcZFxcZCk6KFxcZFxcZCkoPzo6KFxcZFxcZCkpP1xccyg/OihVVHxHTVR8W0VDTVBdW1NEXVQpfChbWnpdKXwoWystXVxcZHs0fSkpJC8sXG4gICAgICAgIG9ic09mZnNldHMgPSB7XG4gICAgICAgICAgICBVVDogMCxcbiAgICAgICAgICAgIEdNVDogMCxcbiAgICAgICAgICAgIEVEVDogLTQgKiA2MCxcbiAgICAgICAgICAgIEVTVDogLTUgKiA2MCxcbiAgICAgICAgICAgIENEVDogLTUgKiA2MCxcbiAgICAgICAgICAgIENTVDogLTYgKiA2MCxcbiAgICAgICAgICAgIE1EVDogLTYgKiA2MCxcbiAgICAgICAgICAgIE1TVDogLTcgKiA2MCxcbiAgICAgICAgICAgIFBEVDogLTcgKiA2MCxcbiAgICAgICAgICAgIFBTVDogLTggKiA2MCxcbiAgICAgICAgfTtcblxuICAgIC8vIGRhdGUgZnJvbSBpc28gZm9ybWF0XG4gICAgZnVuY3Rpb24gY29uZmlnRnJvbUlTTyhjb25maWcpIHtcbiAgICAgICAgdmFyIGksXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgc3RyaW5nID0gY29uZmlnLl9pLFxuICAgICAgICAgICAgbWF0Y2ggPSBleHRlbmRlZElzb1JlZ2V4LmV4ZWMoc3RyaW5nKSB8fCBiYXNpY0lzb1JlZ2V4LmV4ZWMoc3RyaW5nKSxcbiAgICAgICAgICAgIGFsbG93VGltZSxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQsXG4gICAgICAgICAgICB0aW1lRm9ybWF0LFxuICAgICAgICAgICAgdHpGb3JtYXQ7XG5cbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5pc28gPSB0cnVlO1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsID0gaXNvRGF0ZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzb0RhdGVzW2ldWzFdLmV4ZWMobWF0Y2hbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGVGb3JtYXQgPSBpc29EYXRlc1tpXVswXTtcbiAgICAgICAgICAgICAgICAgICAgYWxsb3dUaW1lID0gaXNvRGF0ZXNbaV1bMl0gIT09IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGF0ZUZvcm1hdCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1hdGNoWzNdKSB7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMCwgbCA9IGlzb1RpbWVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNvVGltZXNbaV1bMV0uZXhlYyhtYXRjaFszXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1hdGNoWzJdIHNob3VsZCBiZSAnVCcgb3Igc3BhY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVGb3JtYXQgPSAobWF0Y2hbMl0gfHwgJyAnKSArIGlzb1RpbWVzW2ldWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRpbWVGb3JtYXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghYWxsb3dUaW1lICYmIHRpbWVGb3JtYXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtYXRjaFs0XSkge1xuICAgICAgICAgICAgICAgIGlmICh0elJlZ2V4LmV4ZWMobWF0Y2hbNF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHR6Rm9ybWF0ID0gJ1onO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uZmlnLl9mID0gZGF0ZUZvcm1hdCArICh0aW1lRm9ybWF0IHx8ICcnKSArICh0ekZvcm1hdCB8fCAnJyk7XG4gICAgICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4dHJhY3RGcm9tUkZDMjgyMlN0cmluZ3MoXG4gICAgICAgIHllYXJTdHIsXG4gICAgICAgIG1vbnRoU3RyLFxuICAgICAgICBkYXlTdHIsXG4gICAgICAgIGhvdXJTdHIsXG4gICAgICAgIG1pbnV0ZVN0cixcbiAgICAgICAgc2Vjb25kU3RyXG4gICAgKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXG4gICAgICAgICAgICB1bnRydW5jYXRlWWVhcih5ZWFyU3RyKSxcbiAgICAgICAgICAgIGRlZmF1bHRMb2NhbGVNb250aHNTaG9ydC5pbmRleE9mKG1vbnRoU3RyKSxcbiAgICAgICAgICAgIHBhcnNlSW50KGRheVN0ciwgMTApLFxuICAgICAgICAgICAgcGFyc2VJbnQoaG91clN0ciwgMTApLFxuICAgICAgICAgICAgcGFyc2VJbnQobWludXRlU3RyLCAxMCksXG4gICAgICAgIF07XG5cbiAgICAgICAgaWYgKHNlY29uZFN0cikge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gocGFyc2VJbnQoc2Vjb25kU3RyLCAxMCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1bnRydW5jYXRlWWVhcih5ZWFyU3RyKSB7XG4gICAgICAgIHZhciB5ZWFyID0gcGFyc2VJbnQoeWVhclN0ciwgMTApO1xuICAgICAgICBpZiAoeWVhciA8PSA0OSkge1xuICAgICAgICAgICAgcmV0dXJuIDIwMDAgKyB5ZWFyO1xuICAgICAgICB9IGVsc2UgaWYgKHllYXIgPD0gOTk5KSB7XG4gICAgICAgICAgICByZXR1cm4gMTkwMCArIHllYXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHllYXI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJlcHJvY2Vzc1JGQzI4MjIocykge1xuICAgICAgICAvLyBSZW1vdmUgY29tbWVudHMgYW5kIGZvbGRpbmcgd2hpdGVzcGFjZSBhbmQgcmVwbGFjZSBtdWx0aXBsZS1zcGFjZXMgd2l0aCBhIHNpbmdsZSBzcGFjZVxuICAgICAgICByZXR1cm4gc1xuICAgICAgICAgICAgLnJlcGxhY2UoL1xcKFteKV0qXFwpfFtcXG5cXHRdL2csICcgJylcbiAgICAgICAgICAgIC5yZXBsYWNlKC8oXFxzXFxzKykvZywgJyAnKVxuICAgICAgICAgICAgLnJlcGxhY2UoL15cXHNcXHMqLywgJycpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFxzXFxzKiQvLCAnJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2hlY2tXZWVrZGF5KHdlZWtkYXlTdHIsIHBhcnNlZElucHV0LCBjb25maWcpIHtcbiAgICAgICAgaWYgKHdlZWtkYXlTdHIpIHtcbiAgICAgICAgICAgIC8vIFRPRE86IFJlcGxhY2UgdGhlIHZhbmlsbGEgSlMgRGF0ZSBvYmplY3Qgd2l0aCBhbiBpbmRlcGVuZGVudCBkYXktb2Ytd2VlayBjaGVjay5cbiAgICAgICAgICAgIHZhciB3ZWVrZGF5UHJvdmlkZWQgPSBkZWZhdWx0TG9jYWxlV2Vla2RheXNTaG9ydC5pbmRleE9mKHdlZWtkYXlTdHIpLFxuICAgICAgICAgICAgICAgIHdlZWtkYXlBY3R1YWwgPSBuZXcgRGF0ZShcbiAgICAgICAgICAgICAgICAgICAgcGFyc2VkSW5wdXRbMF0sXG4gICAgICAgICAgICAgICAgICAgIHBhcnNlZElucHV0WzFdLFxuICAgICAgICAgICAgICAgICAgICBwYXJzZWRJbnB1dFsyXVxuICAgICAgICAgICAgICAgICkuZ2V0RGF5KCk7XG4gICAgICAgICAgICBpZiAod2Vla2RheVByb3ZpZGVkICE9PSB3ZWVrZGF5QWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykud2Vla2RheU1pc21hdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2FsY3VsYXRlT2Zmc2V0KG9ic09mZnNldCwgbWlsaXRhcnlPZmZzZXQsIG51bU9mZnNldCkge1xuICAgICAgICBpZiAob2JzT2Zmc2V0KSB7XG4gICAgICAgICAgICByZXR1cm4gb2JzT2Zmc2V0c1tvYnNPZmZzZXRdO1xuICAgICAgICB9IGVsc2UgaWYgKG1pbGl0YXJ5T2Zmc2V0KSB7XG4gICAgICAgICAgICAvLyB0aGUgb25seSBhbGxvd2VkIG1pbGl0YXJ5IHR6IGlzIFpcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGhtID0gcGFyc2VJbnQobnVtT2Zmc2V0LCAxMCksXG4gICAgICAgICAgICAgICAgbSA9IGhtICUgMTAwLFxuICAgICAgICAgICAgICAgIGggPSAoaG0gLSBtKSAvIDEwMDtcbiAgICAgICAgICAgIHJldHVybiBoICogNjAgKyBtO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZGF0ZSBhbmQgdGltZSBmcm9tIHJlZiAyODIyIGZvcm1hdFxuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21SRkMyODIyKGNvbmZpZykge1xuICAgICAgICB2YXIgbWF0Y2ggPSByZmMyODIyLmV4ZWMocHJlcHJvY2Vzc1JGQzI4MjIoY29uZmlnLl9pKSksXG4gICAgICAgICAgICBwYXJzZWRBcnJheTtcbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICBwYXJzZWRBcnJheSA9IGV4dHJhY3RGcm9tUkZDMjgyMlN0cmluZ3MoXG4gICAgICAgICAgICAgICAgbWF0Y2hbNF0sXG4gICAgICAgICAgICAgICAgbWF0Y2hbM10sXG4gICAgICAgICAgICAgICAgbWF0Y2hbMl0sXG4gICAgICAgICAgICAgICAgbWF0Y2hbNV0sXG4gICAgICAgICAgICAgICAgbWF0Y2hbNl0sXG4gICAgICAgICAgICAgICAgbWF0Y2hbN11cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoIWNoZWNrV2Vla2RheShtYXRjaFsxXSwgcGFyc2VkQXJyYXksIGNvbmZpZykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbmZpZy5fYSA9IHBhcnNlZEFycmF5O1xuICAgICAgICAgICAgY29uZmlnLl90em0gPSBjYWxjdWxhdGVPZmZzZXQobWF0Y2hbOF0sIG1hdGNoWzldLCBtYXRjaFsxMF0pO1xuXG4gICAgICAgICAgICBjb25maWcuX2QgPSBjcmVhdGVVVENEYXRlLmFwcGx5KG51bGwsIGNvbmZpZy5fYSk7XG4gICAgICAgICAgICBjb25maWcuX2Quc2V0VVRDTWludXRlcyhjb25maWcuX2QuZ2V0VVRDTWludXRlcygpIC0gY29uZmlnLl90em0pO1xuXG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5yZmMyODIyID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZGF0ZSBmcm9tIDEpIEFTUC5ORVQsIDIpIElTTywgMykgUkZDIDI4MjIgZm9ybWF0cywgb3IgNCkgb3B0aW9uYWwgZmFsbGJhY2sgaWYgcGFyc2luZyBpc24ndCBzdHJpY3RcbiAgICBmdW5jdGlvbiBjb25maWdGcm9tU3RyaW5nKGNvbmZpZykge1xuICAgICAgICB2YXIgbWF0Y2hlZCA9IGFzcE5ldEpzb25SZWdleC5leGVjKGNvbmZpZy5faSk7XG4gICAgICAgIGlmIChtYXRjaGVkICE9PSBudWxsKSB7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZSgrbWF0Y2hlZFsxXSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25maWdGcm9tSVNPKGNvbmZpZyk7XG4gICAgICAgIGlmIChjb25maWcuX2lzVmFsaWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBkZWxldGUgY29uZmlnLl9pc1ZhbGlkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uZmlnRnJvbVJGQzI4MjIoY29uZmlnKTtcbiAgICAgICAgaWYgKGNvbmZpZy5faXNWYWxpZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBjb25maWcuX2lzVmFsaWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnLl9zdHJpY3QpIHtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gRmluYWwgYXR0ZW1wdCwgdXNlIElucHV0IEZhbGxiYWNrXG4gICAgICAgICAgICBob29rcy5jcmVhdGVGcm9tSW5wdXRGYWxsYmFjayhjb25maWcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuY3JlYXRlRnJvbUlucHV0RmFsbGJhY2sgPSBkZXByZWNhdGUoXG4gICAgICAgICd2YWx1ZSBwcm92aWRlZCBpcyBub3QgaW4gYSByZWNvZ25pemVkIFJGQzI4MjIgb3IgSVNPIGZvcm1hdC4gbW9tZW50IGNvbnN0cnVjdGlvbiBmYWxscyBiYWNrIHRvIGpzIERhdGUoKSwgJyArXG4gICAgICAgICAgICAnd2hpY2ggaXMgbm90IHJlbGlhYmxlIGFjcm9zcyBhbGwgYnJvd3NlcnMgYW5kIHZlcnNpb25zLiBOb24gUkZDMjgyMi9JU08gZGF0ZSBmb3JtYXRzIGFyZSAnICtcbiAgICAgICAgICAgICdkaXNjb3VyYWdlZC4gUGxlYXNlIHJlZmVyIHRvIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvanMtZGF0ZS8gZm9yIG1vcmUgaW5mby4nLFxuICAgICAgICBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShjb25maWcuX2kgKyAoY29uZmlnLl91c2VVVEMgPyAnIFVUQycgOiAnJykpO1xuICAgICAgICB9XG4gICAgKTtcblxuICAgIC8vIFBpY2sgdGhlIGZpcnN0IGRlZmluZWQgb2YgdHdvIG9yIHRocmVlIGFyZ3VtZW50cy5cbiAgICBmdW5jdGlvbiBkZWZhdWx0cyhhLCBiLCBjKSB7XG4gICAgICAgIGlmIChhICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBhO1xuICAgICAgICB9XG4gICAgICAgIGlmIChiICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGN1cnJlbnREYXRlQXJyYXkoY29uZmlnKSB7XG4gICAgICAgIC8vIGhvb2tzIGlzIGFjdHVhbGx5IHRoZSBleHBvcnRlZCBtb21lbnQgb2JqZWN0XG4gICAgICAgIHZhciBub3dWYWx1ZSA9IG5ldyBEYXRlKGhvb2tzLm5vdygpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5fdXNlVVRDKSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIG5vd1ZhbHVlLmdldFVUQ0Z1bGxZZWFyKCksXG4gICAgICAgICAgICAgICAgbm93VmFsdWUuZ2V0VVRDTW9udGgoKSxcbiAgICAgICAgICAgICAgICBub3dWYWx1ZS5nZXRVVENEYXRlKCksXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbbm93VmFsdWUuZ2V0RnVsbFllYXIoKSwgbm93VmFsdWUuZ2V0TW9udGgoKSwgbm93VmFsdWUuZ2V0RGF0ZSgpXTtcbiAgICB9XG5cbiAgICAvLyBjb252ZXJ0IGFuIGFycmF5IHRvIGEgZGF0ZS5cbiAgICAvLyB0aGUgYXJyYXkgc2hvdWxkIG1pcnJvciB0aGUgcGFyYW1ldGVycyBiZWxvd1xuICAgIC8vIG5vdGU6IGFsbCB2YWx1ZXMgcGFzdCB0aGUgeWVhciBhcmUgb3B0aW9uYWwgYW5kIHdpbGwgZGVmYXVsdCB0byB0aGUgbG93ZXN0IHBvc3NpYmxlIHZhbHVlLlxuICAgIC8vIFt5ZWFyLCBtb250aCwgZGF5ICwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1pbGxpc2Vjb25kXVxuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21BcnJheShjb25maWcpIHtcbiAgICAgICAgdmFyIGksXG4gICAgICAgICAgICBkYXRlLFxuICAgICAgICAgICAgaW5wdXQgPSBbXSxcbiAgICAgICAgICAgIGN1cnJlbnREYXRlLFxuICAgICAgICAgICAgZXhwZWN0ZWRXZWVrZGF5LFxuICAgICAgICAgICAgeWVhclRvVXNlO1xuXG4gICAgICAgIGlmIChjb25maWcuX2QpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGN1cnJlbnREYXRlID0gY3VycmVudERhdGVBcnJheShjb25maWcpO1xuXG4gICAgICAgIC8vY29tcHV0ZSBkYXkgb2YgdGhlIHllYXIgZnJvbSB3ZWVrcyBhbmQgd2Vla2RheXNcbiAgICAgICAgaWYgKGNvbmZpZy5fdyAmJiBjb25maWcuX2FbREFURV0gPT0gbnVsbCAmJiBjb25maWcuX2FbTU9OVEhdID09IG51bGwpIHtcbiAgICAgICAgICAgIGRheU9mWWVhckZyb21XZWVrSW5mbyhjb25maWcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9pZiB0aGUgZGF5IG9mIHRoZSB5ZWFyIGlzIHNldCwgZmlndXJlIG91dCB3aGF0IGl0IGlzXG4gICAgICAgIGlmIChjb25maWcuX2RheU9mWWVhciAhPSBudWxsKSB7XG4gICAgICAgICAgICB5ZWFyVG9Vc2UgPSBkZWZhdWx0cyhjb25maWcuX2FbWUVBUl0sIGN1cnJlbnREYXRlW1lFQVJdKTtcblxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIGNvbmZpZy5fZGF5T2ZZZWFyID4gZGF5c0luWWVhcih5ZWFyVG9Vc2UpIHx8XG4gICAgICAgICAgICAgICAgY29uZmlnLl9kYXlPZlllYXIgPT09IDBcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLl9vdmVyZmxvd0RheU9mWWVhciA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGUgPSBjcmVhdGVVVENEYXRlKHllYXJUb1VzZSwgMCwgY29uZmlnLl9kYXlPZlllYXIpO1xuICAgICAgICAgICAgY29uZmlnLl9hW01PTlRIXSA9IGRhdGUuZ2V0VVRDTW9udGgoKTtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtEQVRFXSA9IGRhdGUuZ2V0VVRDRGF0ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmYXVsdCB0byBjdXJyZW50IGRhdGUuXG4gICAgICAgIC8vICogaWYgbm8geWVhciwgbW9udGgsIGRheSBvZiBtb250aCBhcmUgZ2l2ZW4sIGRlZmF1bHQgdG8gdG9kYXlcbiAgICAgICAgLy8gKiBpZiBkYXkgb2YgbW9udGggaXMgZ2l2ZW4sIGRlZmF1bHQgbW9udGggYW5kIHllYXJcbiAgICAgICAgLy8gKiBpZiBtb250aCBpcyBnaXZlbiwgZGVmYXVsdCBvbmx5IHllYXJcbiAgICAgICAgLy8gKiBpZiB5ZWFyIGlzIGdpdmVuLCBkb24ndCBkZWZhdWx0IGFueXRoaW5nXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAzICYmIGNvbmZpZy5fYVtpXSA9PSBudWxsOyArK2kpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtpXSA9IGlucHV0W2ldID0gY3VycmVudERhdGVbaV07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBaZXJvIG91dCB3aGF0ZXZlciB3YXMgbm90IGRlZmF1bHRlZCwgaW5jbHVkaW5nIHRpbWVcbiAgICAgICAgZm9yICg7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtpXSA9IGlucHV0W2ldID1cbiAgICAgICAgICAgICAgICBjb25maWcuX2FbaV0gPT0gbnVsbCA/IChpID09PSAyID8gMSA6IDApIDogY29uZmlnLl9hW2ldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgZm9yIDI0OjAwOjAwLjAwMFxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBjb25maWcuX2FbSE9VUl0gPT09IDI0ICYmXG4gICAgICAgICAgICBjb25maWcuX2FbTUlOVVRFXSA9PT0gMCAmJlxuICAgICAgICAgICAgY29uZmlnLl9hW1NFQ09ORF0gPT09IDAgJiZcbiAgICAgICAgICAgIGNvbmZpZy5fYVtNSUxMSVNFQ09ORF0gPT09IDBcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25maWcuX25leHREYXkgPSB0cnVlO1xuICAgICAgICAgICAgY29uZmlnLl9hW0hPVVJdID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbmZpZy5fZCA9IChjb25maWcuX3VzZVVUQyA/IGNyZWF0ZVVUQ0RhdGUgOiBjcmVhdGVEYXRlKS5hcHBseShcbiAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICBpbnB1dFxuICAgICAgICApO1xuICAgICAgICBleHBlY3RlZFdlZWtkYXkgPSBjb25maWcuX3VzZVVUQ1xuICAgICAgICAgICAgPyBjb25maWcuX2QuZ2V0VVRDRGF5KClcbiAgICAgICAgICAgIDogY29uZmlnLl9kLmdldERheSgpO1xuXG4gICAgICAgIC8vIEFwcGx5IHRpbWV6b25lIG9mZnNldCBmcm9tIGlucHV0LiBUaGUgYWN0dWFsIHV0Y09mZnNldCBjYW4gYmUgY2hhbmdlZFxuICAgICAgICAvLyB3aXRoIHBhcnNlWm9uZS5cbiAgICAgICAgaWYgKGNvbmZpZy5fdHptICE9IG51bGwpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fZC5zZXRVVENNaW51dGVzKGNvbmZpZy5fZC5nZXRVVENNaW51dGVzKCkgLSBjb25maWcuX3R6bSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnLl9uZXh0RGF5KSB7XG4gICAgICAgICAgICBjb25maWcuX2FbSE9VUl0gPSAyNDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIGZvciBtaXNtYXRjaGluZyBkYXkgb2Ygd2Vla1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBjb25maWcuX3cgJiZcbiAgICAgICAgICAgIHR5cGVvZiBjb25maWcuX3cuZCAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgIGNvbmZpZy5fdy5kICE9PSBleHBlY3RlZFdlZWtkYXlcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS53ZWVrZGF5TWlzbWF0Y2ggPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGF5T2ZZZWFyRnJvbVdlZWtJbmZvKGNvbmZpZykge1xuICAgICAgICB2YXIgdywgd2Vla1llYXIsIHdlZWssIHdlZWtkYXksIGRvdywgZG95LCB0ZW1wLCB3ZWVrZGF5T3ZlcmZsb3csIGN1cldlZWs7XG5cbiAgICAgICAgdyA9IGNvbmZpZy5fdztcbiAgICAgICAgaWYgKHcuR0cgIT0gbnVsbCB8fCB3LlcgIT0gbnVsbCB8fCB3LkUgIT0gbnVsbCkge1xuICAgICAgICAgICAgZG93ID0gMTtcbiAgICAgICAgICAgIGRveSA9IDQ7XG5cbiAgICAgICAgICAgIC8vIFRPRE86IFdlIG5lZWQgdG8gdGFrZSB0aGUgY3VycmVudCBpc29XZWVrWWVhciwgYnV0IHRoYXQgZGVwZW5kcyBvblxuICAgICAgICAgICAgLy8gaG93IHdlIGludGVycHJldCBub3cgKGxvY2FsLCB1dGMsIGZpeGVkIG9mZnNldCkuIFNvIGNyZWF0ZVxuICAgICAgICAgICAgLy8gYSBub3cgdmVyc2lvbiBvZiBjdXJyZW50IGNvbmZpZyAodGFrZSBsb2NhbC91dGMvb2Zmc2V0IGZsYWdzLCBhbmRcbiAgICAgICAgICAgIC8vIGNyZWF0ZSBub3cpLlxuICAgICAgICAgICAgd2Vla1llYXIgPSBkZWZhdWx0cyhcbiAgICAgICAgICAgICAgICB3LkdHLFxuICAgICAgICAgICAgICAgIGNvbmZpZy5fYVtZRUFSXSxcbiAgICAgICAgICAgICAgICB3ZWVrT2ZZZWFyKGNyZWF0ZUxvY2FsKCksIDEsIDQpLnllYXJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB3ZWVrID0gZGVmYXVsdHMody5XLCAxKTtcbiAgICAgICAgICAgIHdlZWtkYXkgPSBkZWZhdWx0cyh3LkUsIDEpO1xuICAgICAgICAgICAgaWYgKHdlZWtkYXkgPCAxIHx8IHdlZWtkYXkgPiA3KSB7XG4gICAgICAgICAgICAgICAgd2Vla2RheU92ZXJmbG93ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRvdyA9IGNvbmZpZy5fbG9jYWxlLl93ZWVrLmRvdztcbiAgICAgICAgICAgIGRveSA9IGNvbmZpZy5fbG9jYWxlLl93ZWVrLmRveTtcblxuICAgICAgICAgICAgY3VyV2VlayA9IHdlZWtPZlllYXIoY3JlYXRlTG9jYWwoKSwgZG93LCBkb3kpO1xuXG4gICAgICAgICAgICB3ZWVrWWVhciA9IGRlZmF1bHRzKHcuZ2csIGNvbmZpZy5fYVtZRUFSXSwgY3VyV2Vlay55ZWFyKTtcblxuICAgICAgICAgICAgLy8gRGVmYXVsdCB0byBjdXJyZW50IHdlZWsuXG4gICAgICAgICAgICB3ZWVrID0gZGVmYXVsdHMody53LCBjdXJXZWVrLndlZWspO1xuXG4gICAgICAgICAgICBpZiAody5kICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyB3ZWVrZGF5IC0tIGxvdyBkYXkgbnVtYmVycyBhcmUgY29uc2lkZXJlZCBuZXh0IHdlZWtcbiAgICAgICAgICAgICAgICB3ZWVrZGF5ID0gdy5kO1xuICAgICAgICAgICAgICAgIGlmICh3ZWVrZGF5IDwgMCB8fCB3ZWVrZGF5ID4gNikge1xuICAgICAgICAgICAgICAgICAgICB3ZWVrZGF5T3ZlcmZsb3cgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAody5lICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBsb2NhbCB3ZWVrZGF5IC0tIGNvdW50aW5nIHN0YXJ0cyBmcm9tIGJlZ2lubmluZyBvZiB3ZWVrXG4gICAgICAgICAgICAgICAgd2Vla2RheSA9IHcuZSArIGRvdztcbiAgICAgICAgICAgICAgICBpZiAody5lIDwgMCB8fCB3LmUgPiA2KSB7XG4gICAgICAgICAgICAgICAgICAgIHdlZWtkYXlPdmVyZmxvdyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBkZWZhdWx0IHRvIGJlZ2lubmluZyBvZiB3ZWVrXG4gICAgICAgICAgICAgICAgd2Vla2RheSA9IGRvdztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAod2VlayA8IDEgfHwgd2VlayA+IHdlZWtzSW5ZZWFyKHdlZWtZZWFyLCBkb3csIGRveSkpIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLl9vdmVyZmxvd1dlZWtzID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIGlmICh3ZWVrZGF5T3ZlcmZsb3cgIT0gbnVsbCkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuX292ZXJmbG93V2Vla2RheSA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ZW1wID0gZGF5T2ZZZWFyRnJvbVdlZWtzKHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSk7XG4gICAgICAgICAgICBjb25maWcuX2FbWUVBUl0gPSB0ZW1wLnllYXI7XG4gICAgICAgICAgICBjb25maWcuX2RheU9mWWVhciA9IHRlbXAuZGF5T2ZZZWFyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gY29uc3RhbnQgdGhhdCByZWZlcnMgdG8gdGhlIElTTyBzdGFuZGFyZFxuICAgIGhvb2tzLklTT184NjAxID0gZnVuY3Rpb24gKCkge307XG5cbiAgICAvLyBjb25zdGFudCB0aGF0IHJlZmVycyB0byB0aGUgUkZDIDI4MjIgZm9ybVxuICAgIGhvb2tzLlJGQ18yODIyID0gZnVuY3Rpb24gKCkge307XG5cbiAgICAvLyBkYXRlIGZyb20gc3RyaW5nIGFuZCBmb3JtYXQgc3RyaW5nXG4gICAgZnVuY3Rpb24gY29uZmlnRnJvbVN0cmluZ0FuZEZvcm1hdChjb25maWcpIHtcbiAgICAgICAgLy8gVE9ETzogTW92ZSB0aGlzIHRvIGFub3RoZXIgcGFydCBvZiB0aGUgY3JlYXRpb24gZmxvdyB0byBwcmV2ZW50IGNpcmN1bGFyIGRlcHNcbiAgICAgICAgaWYgKGNvbmZpZy5fZiA9PT0gaG9va3MuSVNPXzg2MDEpIHtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21JU08oY29uZmlnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29uZmlnLl9mID09PSBob29rcy5SRkNfMjgyMikge1xuICAgICAgICAgICAgY29uZmlnRnJvbVJGQzI4MjIoY29uZmlnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25maWcuX2EgPSBbXTtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuZW1wdHkgPSB0cnVlO1xuXG4gICAgICAgIC8vIFRoaXMgYXJyYXkgaXMgdXNlZCB0byBtYWtlIGEgRGF0ZSwgZWl0aGVyIHdpdGggYG5ldyBEYXRlYCBvciBgRGF0ZS5VVENgXG4gICAgICAgIHZhciBzdHJpbmcgPSAnJyArIGNvbmZpZy5faSxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICBwYXJzZWRJbnB1dCxcbiAgICAgICAgICAgIHRva2VucyxcbiAgICAgICAgICAgIHRva2VuLFxuICAgICAgICAgICAgc2tpcHBlZCxcbiAgICAgICAgICAgIHN0cmluZ0xlbmd0aCA9IHN0cmluZy5sZW5ndGgsXG4gICAgICAgICAgICB0b3RhbFBhcnNlZElucHV0TGVuZ3RoID0gMCxcbiAgICAgICAgICAgIGVyYTtcblxuICAgICAgICB0b2tlbnMgPVxuICAgICAgICAgICAgZXhwYW5kRm9ybWF0KGNvbmZpZy5fZiwgY29uZmlnLl9sb2NhbGUpLm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpIHx8IFtdO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRva2VuID0gdG9rZW5zW2ldO1xuICAgICAgICAgICAgcGFyc2VkSW5wdXQgPSAoc3RyaW5nLm1hdGNoKGdldFBhcnNlUmVnZXhGb3JUb2tlbih0b2tlbiwgY29uZmlnKSkgfHxcbiAgICAgICAgICAgICAgICBbXSlbMF07XG4gICAgICAgICAgICBpZiAocGFyc2VkSW5wdXQpIHtcbiAgICAgICAgICAgICAgICBza2lwcGVkID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZihwYXJzZWRJbnB1dCkpO1xuICAgICAgICAgICAgICAgIGlmIChza2lwcGVkLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykudW51c2VkSW5wdXQucHVzaChza2lwcGVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3RyaW5nID0gc3RyaW5nLnNsaWNlKFxuICAgICAgICAgICAgICAgICAgICBzdHJpbmcuaW5kZXhPZihwYXJzZWRJbnB1dCkgKyBwYXJzZWRJbnB1dC5sZW5ndGhcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRvdGFsUGFyc2VkSW5wdXRMZW5ndGggKz0gcGFyc2VkSW5wdXQubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZG9uJ3QgcGFyc2UgaWYgaXQncyBub3QgYSBrbm93biB0b2tlblxuICAgICAgICAgICAgaWYgKGZvcm1hdFRva2VuRnVuY3Rpb25zW3Rva2VuXSkge1xuICAgICAgICAgICAgICAgIGlmIChwYXJzZWRJbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5lbXB0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZFRva2Vucy5wdXNoKHRva2VuKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYWRkVGltZVRvQXJyYXlGcm9tVG9rZW4odG9rZW4sIHBhcnNlZElucHV0LCBjb25maWcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb25maWcuX3N0cmljdCAmJiAhcGFyc2VkSW5wdXQpIHtcbiAgICAgICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS51bnVzZWRUb2tlbnMucHVzaCh0b2tlbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGQgcmVtYWluaW5nIHVucGFyc2VkIGlucHV0IGxlbmd0aCB0byB0aGUgc3RyaW5nXG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmNoYXJzTGVmdE92ZXIgPVxuICAgICAgICAgICAgc3RyaW5nTGVuZ3RoIC0gdG90YWxQYXJzZWRJbnB1dExlbmd0aDtcbiAgICAgICAgaWYgKHN0cmluZy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS51bnVzZWRJbnB1dC5wdXNoKHN0cmluZyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjbGVhciBfMTJoIGZsYWcgaWYgaG91ciBpcyA8PSAxMlxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBjb25maWcuX2FbSE9VUl0gPD0gMTIgJiZcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmJpZ0hvdXIgPT09IHRydWUgJiZcbiAgICAgICAgICAgIGNvbmZpZy5fYVtIT1VSXSA+IDBcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykucGFyc2VkRGF0ZVBhcnRzID0gY29uZmlnLl9hLnNsaWNlKDApO1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5tZXJpZGllbSA9IGNvbmZpZy5fbWVyaWRpZW07XG4gICAgICAgIC8vIGhhbmRsZSBtZXJpZGllbVxuICAgICAgICBjb25maWcuX2FbSE9VUl0gPSBtZXJpZGllbUZpeFdyYXAoXG4gICAgICAgICAgICBjb25maWcuX2xvY2FsZSxcbiAgICAgICAgICAgIGNvbmZpZy5fYVtIT1VSXSxcbiAgICAgICAgICAgIGNvbmZpZy5fbWVyaWRpZW1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBoYW5kbGUgZXJhXG4gICAgICAgIGVyYSA9IGdldFBhcnNpbmdGbGFncyhjb25maWcpLmVyYTtcbiAgICAgICAgaWYgKGVyYSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uZmlnLl9hW1lFQVJdID0gY29uZmlnLl9sb2NhbGUuZXJhc0NvbnZlcnRZZWFyKGVyYSwgY29uZmlnLl9hW1lFQVJdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbmZpZ0Zyb21BcnJheShjb25maWcpO1xuICAgICAgICBjaGVja092ZXJmbG93KGNvbmZpZyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWVyaWRpZW1GaXhXcmFwKGxvY2FsZSwgaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgdmFyIGlzUG07XG5cbiAgICAgICAgaWYgKG1lcmlkaWVtID09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIG5vdGhpbmcgdG8gZG9cbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsb2NhbGUubWVyaWRpZW1Ib3VyICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBsb2NhbGUubWVyaWRpZW1Ib3VyKGhvdXIsIG1lcmlkaWVtKTtcbiAgICAgICAgfSBlbHNlIGlmIChsb2NhbGUuaXNQTSAhPSBudWxsKSB7XG4gICAgICAgICAgICAvLyBGYWxsYmFja1xuICAgICAgICAgICAgaXNQbSA9IGxvY2FsZS5pc1BNKG1lcmlkaWVtKTtcbiAgICAgICAgICAgIGlmIChpc1BtICYmIGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgKz0gMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzUG0gJiYgaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdGhpcyBpcyBub3Qgc3VwcG9zZWQgdG8gaGFwcGVuXG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGRhdGUgZnJvbSBzdHJpbmcgYW5kIGFycmF5IG9mIGZvcm1hdCBzdHJpbmdzXG4gICAgZnVuY3Rpb24gY29uZmlnRnJvbVN0cmluZ0FuZEFycmF5KGNvbmZpZykge1xuICAgICAgICB2YXIgdGVtcENvbmZpZyxcbiAgICAgICAgICAgIGJlc3RNb21lbnQsXG4gICAgICAgICAgICBzY29yZVRvQmVhdCxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICBjdXJyZW50U2NvcmUsXG4gICAgICAgICAgICB2YWxpZEZvcm1hdEZvdW5kLFxuICAgICAgICAgICAgYmVzdEZvcm1hdElzVmFsaWQgPSBmYWxzZTtcblxuICAgICAgICBpZiAoY29uZmlnLl9mLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZEZvcm1hdCA9IHRydWU7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShOYU4pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbmZpZy5fZi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY3VycmVudFNjb3JlID0gMDtcbiAgICAgICAgICAgIHZhbGlkRm9ybWF0Rm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRlbXBDb25maWcgPSBjb3B5Q29uZmlnKHt9LCBjb25maWcpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5fdXNlVVRDICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0ZW1wQ29uZmlnLl91c2VVVEMgPSBjb25maWcuX3VzZVVUQztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRlbXBDb25maWcuX2YgPSBjb25maWcuX2ZbaV07XG4gICAgICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KHRlbXBDb25maWcpO1xuXG4gICAgICAgICAgICBpZiAoaXNWYWxpZCh0ZW1wQ29uZmlnKSkge1xuICAgICAgICAgICAgICAgIHZhbGlkRm9ybWF0Rm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiB0aGVyZSBpcyBhbnkgaW5wdXQgdGhhdCB3YXMgbm90IHBhcnNlZCBhZGQgYSBwZW5hbHR5IGZvciB0aGF0IGZvcm1hdFxuICAgICAgICAgICAgY3VycmVudFNjb3JlICs9IGdldFBhcnNpbmdGbGFncyh0ZW1wQ29uZmlnKS5jaGFyc0xlZnRPdmVyO1xuXG4gICAgICAgICAgICAvL29yIHRva2Vuc1xuICAgICAgICAgICAgY3VycmVudFNjb3JlICs9IGdldFBhcnNpbmdGbGFncyh0ZW1wQ29uZmlnKS51bnVzZWRUb2tlbnMubGVuZ3RoICogMTA7XG5cbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyh0ZW1wQ29uZmlnKS5zY29yZSA9IGN1cnJlbnRTY29yZTtcblxuICAgICAgICAgICAgaWYgKCFiZXN0Rm9ybWF0SXNWYWxpZCkge1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgc2NvcmVUb0JlYXQgPT0gbnVsbCB8fFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2NvcmUgPCBzY29yZVRvQmVhdCB8fFxuICAgICAgICAgICAgICAgICAgICB2YWxpZEZvcm1hdEZvdW5kXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjb3JlVG9CZWF0ID0gY3VycmVudFNjb3JlO1xuICAgICAgICAgICAgICAgICAgICBiZXN0TW9tZW50ID0gdGVtcENvbmZpZztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbGlkRm9ybWF0Rm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlc3RGb3JtYXRJc1ZhbGlkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRTY29yZSA8IHNjb3JlVG9CZWF0KSB7XG4gICAgICAgICAgICAgICAgICAgIHNjb3JlVG9CZWF0ID0gY3VycmVudFNjb3JlO1xuICAgICAgICAgICAgICAgICAgICBiZXN0TW9tZW50ID0gdGVtcENvbmZpZztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBleHRlbmQoY29uZmlnLCBiZXN0TW9tZW50IHx8IHRlbXBDb25maWcpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21PYmplY3QoY29uZmlnKSB7XG4gICAgICAgIGlmIChjb25maWcuX2QpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpID0gbm9ybWFsaXplT2JqZWN0VW5pdHMoY29uZmlnLl9pKSxcbiAgICAgICAgICAgIGRheU9yRGF0ZSA9IGkuZGF5ID09PSB1bmRlZmluZWQgPyBpLmRhdGUgOiBpLmRheTtcbiAgICAgICAgY29uZmlnLl9hID0gbWFwKFxuICAgICAgICAgICAgW2kueWVhciwgaS5tb250aCwgZGF5T3JEYXRlLCBpLmhvdXIsIGkubWludXRlLCBpLnNlY29uZCwgaS5taWxsaXNlY29uZF0sXG4gICAgICAgICAgICBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBwYXJzZUludChvYmosIDEwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25maWdGcm9tQXJyYXkoY29uZmlnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGcm9tQ29uZmlnKGNvbmZpZykge1xuICAgICAgICB2YXIgcmVzID0gbmV3IE1vbWVudChjaGVja092ZXJmbG93KHByZXBhcmVDb25maWcoY29uZmlnKSkpO1xuICAgICAgICBpZiAocmVzLl9uZXh0RGF5KSB7XG4gICAgICAgICAgICAvLyBBZGRpbmcgaXMgc21hcnQgZW5vdWdoIGFyb3VuZCBEU1RcbiAgICAgICAgICAgIHJlcy5hZGQoMSwgJ2QnKTtcbiAgICAgICAgICAgIHJlcy5fbmV4dERheSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJlcGFyZUNvbmZpZyhjb25maWcpIHtcbiAgICAgICAgdmFyIGlucHV0ID0gY29uZmlnLl9pLFxuICAgICAgICAgICAgZm9ybWF0ID0gY29uZmlnLl9mO1xuXG4gICAgICAgIGNvbmZpZy5fbG9jYWxlID0gY29uZmlnLl9sb2NhbGUgfHwgZ2V0TG9jYWxlKGNvbmZpZy5fbCk7XG5cbiAgICAgICAgaWYgKGlucHV0ID09PSBudWxsIHx8IChmb3JtYXQgPT09IHVuZGVmaW5lZCAmJiBpbnB1dCA9PT0gJycpKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlSW52YWxpZCh7IG51bGxJbnB1dDogdHJ1ZSB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25maWcuX2kgPSBpbnB1dCA9IGNvbmZpZy5fbG9jYWxlLnByZXBhcnNlKGlucHV0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc01vbWVudChpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTW9tZW50KGNoZWNrT3ZlcmZsb3coaW5wdXQpKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0RhdGUoaW5wdXQpKSB7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBpbnB1dDtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGZvcm1hdCkpIHtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21TdHJpbmdBbmRBcnJheShjb25maWcpO1xuICAgICAgICB9IGVsc2UgaWYgKGZvcm1hdCkge1xuICAgICAgICAgICAgY29uZmlnRnJvbVN0cmluZ0FuZEZvcm1hdChjb25maWcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uZmlnRnJvbUlucHV0KGNvbmZpZyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWlzVmFsaWQoY29uZmlnKSkge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb25maWc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29uZmlnRnJvbUlucHV0KGNvbmZpZykge1xuICAgICAgICB2YXIgaW5wdXQgPSBjb25maWcuX2k7XG4gICAgICAgIGlmIChpc1VuZGVmaW5lZChpbnB1dCkpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKGhvb2tzLm5vdygpKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0RhdGUoaW5wdXQpKSB7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShpbnB1dC52YWx1ZU9mKCkpO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21TdHJpbmcoY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGlucHV0KSkge1xuICAgICAgICAgICAgY29uZmlnLl9hID0gbWFwKGlucHV0LnNsaWNlKDApLCBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlSW50KG9iaiwgMTApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25maWdGcm9tQXJyYXkoY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChpbnB1dCkpIHtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21PYmplY3QoY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc051bWJlcihpbnB1dCkpIHtcbiAgICAgICAgICAgIC8vIGZyb20gbWlsbGlzZWNvbmRzXG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShpbnB1dCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBob29rcy5jcmVhdGVGcm9tSW5wdXRGYWxsYmFjayhjb25maWcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlTG9jYWxPclVUQyhpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCwgaXNVVEMpIHtcbiAgICAgICAgdmFyIGMgPSB7fTtcblxuICAgICAgICBpZiAoZm9ybWF0ID09PSB0cnVlIHx8IGZvcm1hdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHN0cmljdCA9IGZvcm1hdDtcbiAgICAgICAgICAgIGZvcm1hdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsb2NhbGUgPT09IHRydWUgfHwgbG9jYWxlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgc3RyaWN0ID0gbG9jYWxlO1xuICAgICAgICAgICAgbG9jYWxlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgKGlzT2JqZWN0KGlucHV0KSAmJiBpc09iamVjdEVtcHR5KGlucHV0KSkgfHxcbiAgICAgICAgICAgIChpc0FycmF5KGlucHV0KSAmJiBpbnB1dC5sZW5ndGggPT09IDApXG4gICAgICAgICkge1xuICAgICAgICAgICAgaW5wdXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gb2JqZWN0IGNvbnN0cnVjdGlvbiBtdXN0IGJlIGRvbmUgdGhpcyB3YXkuXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L2lzc3Vlcy8xNDIzXG4gICAgICAgIGMuX2lzQU1vbWVudE9iamVjdCA9IHRydWU7XG4gICAgICAgIGMuX3VzZVVUQyA9IGMuX2lzVVRDID0gaXNVVEM7XG4gICAgICAgIGMuX2wgPSBsb2NhbGU7XG4gICAgICAgIGMuX2kgPSBpbnB1dDtcbiAgICAgICAgYy5fZiA9IGZvcm1hdDtcbiAgICAgICAgYy5fc3RyaWN0ID0gc3RyaWN0O1xuXG4gICAgICAgIHJldHVybiBjcmVhdGVGcm9tQ29uZmlnKGMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUxvY2FsKGlucHV0LCBmb3JtYXQsIGxvY2FsZSwgc3RyaWN0KSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVMb2NhbE9yVVRDKGlucHV0LCBmb3JtYXQsIGxvY2FsZSwgc3RyaWN0LCBmYWxzZSk7XG4gICAgfVxuXG4gICAgdmFyIHByb3RvdHlwZU1pbiA9IGRlcHJlY2F0ZShcbiAgICAgICAgICAgICdtb21lbnQoKS5taW4gaXMgZGVwcmVjYXRlZCwgdXNlIG1vbWVudC5tYXggaW5zdGVhZC4gaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9taW4tbWF4LycsXG4gICAgICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIG90aGVyID0gY3JlYXRlTG9jYWwuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1ZhbGlkKCkgJiYgb3RoZXIuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdGhlciA8IHRoaXMgPyB0aGlzIDogb3RoZXI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUludmFsaWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICksXG4gICAgICAgIHByb3RvdHlwZU1heCA9IGRlcHJlY2F0ZShcbiAgICAgICAgICAgICdtb21lbnQoKS5tYXggaXMgZGVwcmVjYXRlZCwgdXNlIG1vbWVudC5taW4gaW5zdGVhZC4gaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9taW4tbWF4LycsXG4gICAgICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIG90aGVyID0gY3JlYXRlTG9jYWwuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1ZhbGlkKCkgJiYgb3RoZXIuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdGhlciA+IHRoaXMgPyB0aGlzIDogb3RoZXI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUludmFsaWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAvLyBQaWNrIGEgbW9tZW50IG0gZnJvbSBtb21lbnRzIHNvIHRoYXQgbVtmbl0ob3RoZXIpIGlzIHRydWUgZm9yIGFsbFxuICAgIC8vIG90aGVyLiBUaGlzIHJlbGllcyBvbiB0aGUgZnVuY3Rpb24gZm4gdG8gYmUgdHJhbnNpdGl2ZS5cbiAgICAvL1xuICAgIC8vIG1vbWVudHMgc2hvdWxkIGVpdGhlciBiZSBhbiBhcnJheSBvZiBtb21lbnQgb2JqZWN0cyBvciBhbiBhcnJheSwgd2hvc2VcbiAgICAvLyBmaXJzdCBlbGVtZW50IGlzIGFuIGFycmF5IG9mIG1vbWVudCBvYmplY3RzLlxuICAgIGZ1bmN0aW9uIHBpY2tCeShmbiwgbW9tZW50cykge1xuICAgICAgICB2YXIgcmVzLCBpO1xuICAgICAgICBpZiAobW9tZW50cy5sZW5ndGggPT09IDEgJiYgaXNBcnJheShtb21lbnRzWzBdKSkge1xuICAgICAgICAgICAgbW9tZW50cyA9IG1vbWVudHNbMF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFtb21lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzID0gbW9tZW50c1swXTtcbiAgICAgICAgZm9yIChpID0gMTsgaSA8IG1vbWVudHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIGlmICghbW9tZW50c1tpXS5pc1ZhbGlkKCkgfHwgbW9tZW50c1tpXVtmbl0ocmVzKSkge1xuICAgICAgICAgICAgICAgIHJlcyA9IG1vbWVudHNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBVc2UgW10uc29ydCBpbnN0ZWFkP1xuICAgIGZ1bmN0aW9uIG1pbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCk7XG5cbiAgICAgICAgcmV0dXJuIHBpY2tCeSgnaXNCZWZvcmUnLCBhcmdzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYXgoKSB7XG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuXG4gICAgICAgIHJldHVybiBwaWNrQnkoJ2lzQWZ0ZXInLCBhcmdzKTtcbiAgICB9XG5cbiAgICB2YXIgbm93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gRGF0ZS5ub3cgPyBEYXRlLm5vdygpIDogK25ldyBEYXRlKCk7XG4gICAgfTtcblxuICAgIHZhciBvcmRlcmluZyA9IFtcbiAgICAgICAgJ3llYXInLFxuICAgICAgICAncXVhcnRlcicsXG4gICAgICAgICdtb250aCcsXG4gICAgICAgICd3ZWVrJyxcbiAgICAgICAgJ2RheScsXG4gICAgICAgICdob3VyJyxcbiAgICAgICAgJ21pbnV0ZScsXG4gICAgICAgICdzZWNvbmQnLFxuICAgICAgICAnbWlsbGlzZWNvbmQnLFxuICAgIF07XG5cbiAgICBmdW5jdGlvbiBpc0R1cmF0aW9uVmFsaWQobSkge1xuICAgICAgICB2YXIga2V5LFxuICAgICAgICAgICAgdW5pdEhhc0RlY2ltYWwgPSBmYWxzZSxcbiAgICAgICAgICAgIGk7XG4gICAgICAgIGZvciAoa2V5IGluIG0pIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBoYXNPd25Qcm9wKG0sIGtleSkgJiZcbiAgICAgICAgICAgICAgICAhKFxuICAgICAgICAgICAgICAgICAgICBpbmRleE9mLmNhbGwob3JkZXJpbmcsIGtleSkgIT09IC0xICYmXG4gICAgICAgICAgICAgICAgICAgIChtW2tleV0gPT0gbnVsbCB8fCAhaXNOYU4obVtrZXldKSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgb3JkZXJpbmcubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIGlmIChtW29yZGVyaW5nW2ldXSkge1xuICAgICAgICAgICAgICAgIGlmICh1bml0SGFzRGVjaW1hbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7IC8vIG9ubHkgYWxsb3cgbm9uLWludGVnZXJzIGZvciBzbWFsbGVzdCB1bml0XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwYXJzZUZsb2F0KG1bb3JkZXJpbmdbaV1dKSAhPT0gdG9JbnQobVtvcmRlcmluZ1tpXV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHVuaXRIYXNEZWNpbWFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkJDEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1ZhbGlkO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUludmFsaWQkMSgpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKE5hTik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gRHVyYXRpb24oZHVyYXRpb24pIHtcbiAgICAgICAgdmFyIG5vcm1hbGl6ZWRJbnB1dCA9IG5vcm1hbGl6ZU9iamVjdFVuaXRzKGR1cmF0aW9uKSxcbiAgICAgICAgICAgIHllYXJzID0gbm9ybWFsaXplZElucHV0LnllYXIgfHwgMCxcbiAgICAgICAgICAgIHF1YXJ0ZXJzID0gbm9ybWFsaXplZElucHV0LnF1YXJ0ZXIgfHwgMCxcbiAgICAgICAgICAgIG1vbnRocyA9IG5vcm1hbGl6ZWRJbnB1dC5tb250aCB8fCAwLFxuICAgICAgICAgICAgd2Vla3MgPSBub3JtYWxpemVkSW5wdXQud2VlayB8fCBub3JtYWxpemVkSW5wdXQuaXNvV2VlayB8fCAwLFxuICAgICAgICAgICAgZGF5cyA9IG5vcm1hbGl6ZWRJbnB1dC5kYXkgfHwgMCxcbiAgICAgICAgICAgIGhvdXJzID0gbm9ybWFsaXplZElucHV0LmhvdXIgfHwgMCxcbiAgICAgICAgICAgIG1pbnV0ZXMgPSBub3JtYWxpemVkSW5wdXQubWludXRlIHx8IDAsXG4gICAgICAgICAgICBzZWNvbmRzID0gbm9ybWFsaXplZElucHV0LnNlY29uZCB8fCAwLFxuICAgICAgICAgICAgbWlsbGlzZWNvbmRzID0gbm9ybWFsaXplZElucHV0Lm1pbGxpc2Vjb25kIHx8IDA7XG5cbiAgICAgICAgdGhpcy5faXNWYWxpZCA9IGlzRHVyYXRpb25WYWxpZChub3JtYWxpemVkSW5wdXQpO1xuXG4gICAgICAgIC8vIHJlcHJlc2VudGF0aW9uIGZvciBkYXRlQWRkUmVtb3ZlXG4gICAgICAgIHRoaXMuX21pbGxpc2Vjb25kcyA9XG4gICAgICAgICAgICArbWlsbGlzZWNvbmRzICtcbiAgICAgICAgICAgIHNlY29uZHMgKiAxZTMgKyAvLyAxMDAwXG4gICAgICAgICAgICBtaW51dGVzICogNmU0ICsgLy8gMTAwMCAqIDYwXG4gICAgICAgICAgICBob3VycyAqIDEwMDAgKiA2MCAqIDYwOyAvL3VzaW5nIDEwMDAgKiA2MCAqIDYwIGluc3RlYWQgb2YgMzZlNSB0byBhdm9pZCBmbG9hdGluZyBwb2ludCByb3VuZGluZyBlcnJvcnMgaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzI5NzhcbiAgICAgICAgLy8gQmVjYXVzZSBvZiBkYXRlQWRkUmVtb3ZlIHRyZWF0cyAyNCBob3VycyBhcyBkaWZmZXJlbnQgZnJvbSBhXG4gICAgICAgIC8vIGRheSB3aGVuIHdvcmtpbmcgYXJvdW5kIERTVCwgd2UgbmVlZCB0byBzdG9yZSB0aGVtIHNlcGFyYXRlbHlcbiAgICAgICAgdGhpcy5fZGF5cyA9ICtkYXlzICsgd2Vla3MgKiA3O1xuICAgICAgICAvLyBJdCBpcyBpbXBvc3NpYmxlIHRvIHRyYW5zbGF0ZSBtb250aHMgaW50byBkYXlzIHdpdGhvdXQga25vd2luZ1xuICAgICAgICAvLyB3aGljaCBtb250aHMgeW91IGFyZSBhcmUgdGFsa2luZyBhYm91dCwgc28gd2UgaGF2ZSB0byBzdG9yZVxuICAgICAgICAvLyBpdCBzZXBhcmF0ZWx5LlxuICAgICAgICB0aGlzLl9tb250aHMgPSArbW9udGhzICsgcXVhcnRlcnMgKiAzICsgeWVhcnMgKiAxMjtcblxuICAgICAgICB0aGlzLl9kYXRhID0ge307XG5cbiAgICAgICAgdGhpcy5fbG9jYWxlID0gZ2V0TG9jYWxlKCk7XG5cbiAgICAgICAgdGhpcy5fYnViYmxlKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNEdXJhdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiBpbnN0YW5jZW9mIER1cmF0aW9uO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFic1JvdW5kKG51bWJlcikge1xuICAgICAgICBpZiAobnVtYmVyIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoLTEgKiBudW1iZXIpICogLTE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gY29tcGFyZSB0d28gYXJyYXlzLCByZXR1cm4gdGhlIG51bWJlciBvZiBkaWZmZXJlbmNlc1xuICAgIGZ1bmN0aW9uIGNvbXBhcmVBcnJheXMoYXJyYXkxLCBhcnJheTIsIGRvbnRDb252ZXJ0KSB7XG4gICAgICAgIHZhciBsZW4gPSBNYXRoLm1pbihhcnJheTEubGVuZ3RoLCBhcnJheTIubGVuZ3RoKSxcbiAgICAgICAgICAgIGxlbmd0aERpZmYgPSBNYXRoLmFicyhhcnJheTEubGVuZ3RoIC0gYXJyYXkyLmxlbmd0aCksXG4gICAgICAgICAgICBkaWZmcyA9IDAsXG4gICAgICAgICAgICBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAoZG9udENvbnZlcnQgJiYgYXJyYXkxW2ldICE9PSBhcnJheTJbaV0pIHx8XG4gICAgICAgICAgICAgICAgKCFkb250Q29udmVydCAmJiB0b0ludChhcnJheTFbaV0pICE9PSB0b0ludChhcnJheTJbaV0pKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgZGlmZnMrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlmZnMgKyBsZW5ndGhEaWZmO1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGZ1bmN0aW9uIG9mZnNldCh0b2tlbiwgc2VwYXJhdG9yKSB7XG4gICAgICAgIGFkZEZvcm1hdFRva2VuKHRva2VuLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgb2Zmc2V0ID0gdGhpcy51dGNPZmZzZXQoKSxcbiAgICAgICAgICAgICAgICBzaWduID0gJysnO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDApIHtcbiAgICAgICAgICAgICAgICBvZmZzZXQgPSAtb2Zmc2V0O1xuICAgICAgICAgICAgICAgIHNpZ24gPSAnLSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHNpZ24gK1xuICAgICAgICAgICAgICAgIHplcm9GaWxsKH5+KG9mZnNldCAvIDYwKSwgMikgK1xuICAgICAgICAgICAgICAgIHNlcGFyYXRvciArXG4gICAgICAgICAgICAgICAgemVyb0ZpbGwofn5vZmZzZXQgJSA2MCwgMilcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG9mZnNldCgnWicsICc6Jyk7XG4gICAgb2Zmc2V0KCdaWicsICcnKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ1onLCBtYXRjaFNob3J0T2Zmc2V0KTtcbiAgICBhZGRSZWdleFRva2VuKCdaWicsIG1hdGNoU2hvcnRPZmZzZXQpO1xuICAgIGFkZFBhcnNlVG9rZW4oWydaJywgJ1paJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICBjb25maWcuX3VzZVVUQyA9IHRydWU7XG4gICAgICAgIGNvbmZpZy5fdHptID0gb2Zmc2V0RnJvbVN0cmluZyhtYXRjaFNob3J0T2Zmc2V0LCBpbnB1dCk7XG4gICAgfSk7XG5cbiAgICAvLyBIRUxQRVJTXG5cbiAgICAvLyB0aW1lem9uZSBjaHVua2VyXG4gICAgLy8gJysxMDowMCcgPiBbJzEwJywgICcwMCddXG4gICAgLy8gJy0xNTMwJyAgPiBbJy0xNScsICczMCddXG4gICAgdmFyIGNodW5rT2Zmc2V0ID0gLyhbXFwrXFwtXXxcXGRcXGQpL2dpO1xuXG4gICAgZnVuY3Rpb24gb2Zmc2V0RnJvbVN0cmluZyhtYXRjaGVyLCBzdHJpbmcpIHtcbiAgICAgICAgdmFyIG1hdGNoZXMgPSAoc3RyaW5nIHx8ICcnKS5tYXRjaChtYXRjaGVyKSxcbiAgICAgICAgICAgIGNodW5rLFxuICAgICAgICAgICAgcGFydHMsXG4gICAgICAgICAgICBtaW51dGVzO1xuXG4gICAgICAgIGlmIChtYXRjaGVzID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNodW5rID0gbWF0Y2hlc1ttYXRjaGVzLmxlbmd0aCAtIDFdIHx8IFtdO1xuICAgICAgICBwYXJ0cyA9IChjaHVuayArICcnKS5tYXRjaChjaHVua09mZnNldCkgfHwgWyctJywgMCwgMF07XG4gICAgICAgIG1pbnV0ZXMgPSArKHBhcnRzWzFdICogNjApICsgdG9JbnQocGFydHNbMl0pO1xuXG4gICAgICAgIHJldHVybiBtaW51dGVzID09PSAwID8gMCA6IHBhcnRzWzBdID09PSAnKycgPyBtaW51dGVzIDogLW1pbnV0ZXM7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJuIGEgbW9tZW50IGZyb20gaW5wdXQsIHRoYXQgaXMgbG9jYWwvdXRjL3pvbmUgZXF1aXZhbGVudCB0byBtb2RlbC5cbiAgICBmdW5jdGlvbiBjbG9uZVdpdGhPZmZzZXQoaW5wdXQsIG1vZGVsKSB7XG4gICAgICAgIHZhciByZXMsIGRpZmY7XG4gICAgICAgIGlmIChtb2RlbC5faXNVVEMpIHtcbiAgICAgICAgICAgIHJlcyA9IG1vZGVsLmNsb25lKCk7XG4gICAgICAgICAgICBkaWZmID1cbiAgICAgICAgICAgICAgICAoaXNNb21lbnQoaW5wdXQpIHx8IGlzRGF0ZShpbnB1dClcbiAgICAgICAgICAgICAgICAgICAgPyBpbnB1dC52YWx1ZU9mKClcbiAgICAgICAgICAgICAgICAgICAgOiBjcmVhdGVMb2NhbChpbnB1dCkudmFsdWVPZigpKSAtIHJlcy52YWx1ZU9mKCk7XG4gICAgICAgICAgICAvLyBVc2UgbG93LWxldmVsIGFwaSwgYmVjYXVzZSB0aGlzIGZuIGlzIGxvdy1sZXZlbCBhcGkuXG4gICAgICAgICAgICByZXMuX2Quc2V0VGltZShyZXMuX2QudmFsdWVPZigpICsgZGlmZik7XG4gICAgICAgICAgICBob29rcy51cGRhdGVPZmZzZXQocmVzLCBmYWxzZSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsKGlucHV0KS5sb2NhbCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0RGF0ZU9mZnNldChtKSB7XG4gICAgICAgIC8vIE9uIEZpcmVmb3guMjQgRGF0ZSNnZXRUaW1lem9uZU9mZnNldCByZXR1cm5zIGEgZmxvYXRpbmcgcG9pbnQuXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L3B1bGwvMTg3MVxuICAgICAgICByZXR1cm4gLU1hdGgucm91bmQobS5fZC5nZXRUaW1lem9uZU9mZnNldCgpKTtcbiAgICB9XG5cbiAgICAvLyBIT09LU1xuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCB3aGVuZXZlciBhIG1vbWVudCBpcyBtdXRhdGVkLlxuICAgIC8vIEl0IGlzIGludGVuZGVkIHRvIGtlZXAgdGhlIG9mZnNldCBpbiBzeW5jIHdpdGggdGhlIHRpbWV6b25lLlxuICAgIGhvb2tzLnVwZGF0ZU9mZnNldCA9IGZ1bmN0aW9uICgpIHt9O1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgLy8ga2VlcExvY2FsVGltZSA9IHRydWUgbWVhbnMgb25seSBjaGFuZ2UgdGhlIHRpbWV6b25lLCB3aXRob3V0XG4gICAgLy8gYWZmZWN0aW5nIHRoZSBsb2NhbCBob3VyLiBTbyA1OjMxOjI2ICswMzAwIC0tW3V0Y09mZnNldCgyLCB0cnVlKV0tLT5cbiAgICAvLyA1OjMxOjI2ICswMjAwIEl0IGlzIHBvc3NpYmxlIHRoYXQgNTozMToyNiBkb2Vzbid0IGV4aXN0IHdpdGggb2Zmc2V0XG4gICAgLy8gKzAyMDAsIHNvIHdlIGFkanVzdCB0aGUgdGltZSBhcyBuZWVkZWQsIHRvIGJlIHZhbGlkLlxuICAgIC8vXG4gICAgLy8gS2VlcGluZyB0aGUgdGltZSBhY3R1YWxseSBhZGRzL3N1YnRyYWN0cyAob25lIGhvdXIpXG4gICAgLy8gZnJvbSB0aGUgYWN0dWFsIHJlcHJlc2VudGVkIHRpbWUuIFRoYXQgaXMgd2h5IHdlIGNhbGwgdXBkYXRlT2Zmc2V0XG4gICAgLy8gYSBzZWNvbmQgdGltZS4gSW4gY2FzZSBpdCB3YW50cyB1cyB0byBjaGFuZ2UgdGhlIG9mZnNldCBhZ2FpblxuICAgIC8vIF9jaGFuZ2VJblByb2dyZXNzID09IHRydWUgY2FzZSwgdGhlbiB3ZSBoYXZlIHRvIGFkanVzdCwgYmVjYXVzZVxuICAgIC8vIHRoZXJlIGlzIG5vIHN1Y2ggdGltZSBpbiB0aGUgZ2l2ZW4gdGltZXpvbmUuXG4gICAgZnVuY3Rpb24gZ2V0U2V0T2Zmc2V0KGlucHV0LCBrZWVwTG9jYWxUaW1lLCBrZWVwTWludXRlcykge1xuICAgICAgICB2YXIgb2Zmc2V0ID0gdGhpcy5fb2Zmc2V0IHx8IDAsXG4gICAgICAgICAgICBsb2NhbEFkanVzdDtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ICE9IG51bGwgPyB0aGlzIDogTmFOO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlucHV0ID0gb2Zmc2V0RnJvbVN0cmluZyhtYXRjaFNob3J0T2Zmc2V0LCBpbnB1dCk7XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoTWF0aC5hYnMoaW5wdXQpIDwgMTYgJiYgIWtlZXBNaW51dGVzKSB7XG4gICAgICAgICAgICAgICAgaW5wdXQgPSBpbnB1dCAqIDYwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1VUQyAmJiBrZWVwTG9jYWxUaW1lKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxBZGp1c3QgPSBnZXREYXRlT2Zmc2V0KHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb2Zmc2V0ID0gaW5wdXQ7XG4gICAgICAgICAgICB0aGlzLl9pc1VUQyA9IHRydWU7XG4gICAgICAgICAgICBpZiAobG9jYWxBZGp1c3QgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkKGxvY2FsQWRqdXN0LCAnbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9mZnNldCAhPT0gaW5wdXQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWtlZXBMb2NhbFRpbWUgfHwgdGhpcy5fY2hhbmdlSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgICAgICAgICBhZGRTdWJ0cmFjdChcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVEdXJhdGlvbihpbnB1dCAtIG9mZnNldCwgJ20nKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBmYWxzZVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX2NoYW5nZUluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2hhbmdlSW5Qcm9ncmVzcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2hhbmdlSW5Qcm9ncmVzcyA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNVVEMgPyBvZmZzZXQgOiBnZXREYXRlT2Zmc2V0KHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0Wm9uZShpbnB1dCwga2VlcExvY2FsVGltZSkge1xuICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpbnB1dCA9IC1pbnB1dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQoaW5wdXQsIGtlZXBMb2NhbFRpbWUpO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAtdGhpcy51dGNPZmZzZXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldE9mZnNldFRvVVRDKGtlZXBMb2NhbFRpbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudXRjT2Zmc2V0KDAsIGtlZXBMb2NhbFRpbWUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldE9mZnNldFRvTG9jYWwoa2VlcExvY2FsVGltZSkge1xuICAgICAgICBpZiAodGhpcy5faXNVVEMpIHtcbiAgICAgICAgICAgIHRoaXMudXRjT2Zmc2V0KDAsIGtlZXBMb2NhbFRpbWUpO1xuICAgICAgICAgICAgdGhpcy5faXNVVEMgPSBmYWxzZTtcblxuICAgICAgICAgICAgaWYgKGtlZXBMb2NhbFRpbWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN1YnRyYWN0KGdldERhdGVPZmZzZXQodGhpcyksICdtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0T2Zmc2V0VG9QYXJzZWRPZmZzZXQoKSB7XG4gICAgICAgIGlmICh0aGlzLl90em0gIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQodGhpcy5fdHptLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMuX2kgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB2YXIgdFpvbmUgPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoT2Zmc2V0LCB0aGlzLl9pKTtcbiAgICAgICAgICAgIGlmICh0Wm9uZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQodFpvbmUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnV0Y09mZnNldCgwLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYXNBbGlnbmVkSG91ck9mZnNldChpbnB1dCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaW5wdXQgPSBpbnB1dCA/IGNyZWF0ZUxvY2FsKGlucHV0KS51dGNPZmZzZXQoKSA6IDA7XG5cbiAgICAgICAgcmV0dXJuICh0aGlzLnV0Y09mZnNldCgpIC0gaW5wdXQpICUgNjAgPT09IDA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNEYXlsaWdodFNhdmluZ1RpbWUoKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLnV0Y09mZnNldCgpID4gdGhpcy5jbG9uZSgpLm1vbnRoKDApLnV0Y09mZnNldCgpIHx8XG4gICAgICAgICAgICB0aGlzLnV0Y09mZnNldCgpID4gdGhpcy5jbG9uZSgpLm1vbnRoKDUpLnV0Y09mZnNldCgpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNEYXlsaWdodFNhdmluZ1RpbWVTaGlmdGVkKCkge1xuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKHRoaXMuX2lzRFNUU2hpZnRlZCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc0RTVFNoaWZ0ZWQ7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYyA9IHt9LFxuICAgICAgICAgICAgb3RoZXI7XG5cbiAgICAgICAgY29weUNvbmZpZyhjLCB0aGlzKTtcbiAgICAgICAgYyA9IHByZXBhcmVDb25maWcoYyk7XG5cbiAgICAgICAgaWYgKGMuX2EpIHtcbiAgICAgICAgICAgIG90aGVyID0gYy5faXNVVEMgPyBjcmVhdGVVVEMoYy5fYSkgOiBjcmVhdGVMb2NhbChjLl9hKTtcbiAgICAgICAgICAgIHRoaXMuX2lzRFNUU2hpZnRlZCA9XG4gICAgICAgICAgICAgICAgdGhpcy5pc1ZhbGlkKCkgJiYgY29tcGFyZUFycmF5cyhjLl9hLCBvdGhlci50b0FycmF5KCkpID4gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2lzRFNUU2hpZnRlZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzRFNUU2hpZnRlZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0xvY2FsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyAhdGhpcy5faXNVVEMgOiBmYWxzZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1V0Y09mZnNldCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gdGhpcy5faXNVVEMgOiBmYWxzZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1V0YygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gdGhpcy5faXNVVEMgJiYgdGhpcy5fb2Zmc2V0ID09PSAwIDogZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gQVNQLk5FVCBqc29uIGRhdGUgZm9ybWF0IHJlZ2V4XG4gICAgdmFyIGFzcE5ldFJlZ2V4ID0gL14oLXxcXCspPyg/OihcXGQqKVsuIF0pPyhcXGQrKTooXFxkKykoPzo6KFxcZCspKFxcLlxcZCopPyk/JC8sXG4gICAgICAgIC8vIGZyb20gaHR0cDovL2RvY3MuY2xvc3VyZS1saWJyYXJ5Lmdvb2dsZWNvZGUuY29tL2dpdC9jbG9zdXJlX2dvb2dfZGF0ZV9kYXRlLmpzLnNvdXJjZS5odG1sXG4gICAgICAgIC8vIHNvbWV3aGF0IG1vcmUgaW4gbGluZSB3aXRoIDQuNC4zLjIgMjAwNCBzcGVjLCBidXQgYWxsb3dzIGRlY2ltYWwgYW55d2hlcmVcbiAgICAgICAgLy8gYW5kIGZ1cnRoZXIgbW9kaWZpZWQgdG8gYWxsb3cgZm9yIHN0cmluZ3MgY29udGFpbmluZyBib3RoIHdlZWsgYW5kIGRheVxuICAgICAgICBpc29SZWdleCA9IC9eKC18XFwrKT9QKD86KFstK10/WzAtOSwuXSopWSk/KD86KFstK10/WzAtOSwuXSopTSk/KD86KFstK10/WzAtOSwuXSopVyk/KD86KFstK10/WzAtOSwuXSopRCk/KD86VCg/OihbLStdP1swLTksLl0qKUgpPyg/OihbLStdP1swLTksLl0qKU0pPyg/OihbLStdP1swLTksLl0qKVMpPyk/JC87XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVEdXJhdGlvbihpbnB1dCwga2V5KSB7XG4gICAgICAgIHZhciBkdXJhdGlvbiA9IGlucHV0LFxuICAgICAgICAgICAgLy8gbWF0Y2hpbmcgYWdhaW5zdCByZWdleHAgaXMgZXhwZW5zaXZlLCBkbyBpdCBvbiBkZW1hbmRcbiAgICAgICAgICAgIG1hdGNoID0gbnVsbCxcbiAgICAgICAgICAgIHNpZ24sXG4gICAgICAgICAgICByZXQsXG4gICAgICAgICAgICBkaWZmUmVzO1xuXG4gICAgICAgIGlmIChpc0R1cmF0aW9uKGlucHV0KSkge1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgbXM6IGlucHV0Ll9taWxsaXNlY29uZHMsXG4gICAgICAgICAgICAgICAgZDogaW5wdXQuX2RheXMsXG4gICAgICAgICAgICAgICAgTTogaW5wdXQuX21vbnRocyxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSBpZiAoaXNOdW1iZXIoaW5wdXQpIHx8ICFpc05hTigraW5wdXQpKSB7XG4gICAgICAgICAgICBkdXJhdGlvbiA9IHt9O1xuICAgICAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uW2tleV0gPSAraW5wdXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uLm1pbGxpc2Vjb25kcyA9ICtpbnB1dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICgobWF0Y2ggPSBhc3BOZXRSZWdleC5leGVjKGlucHV0KSkpIHtcbiAgICAgICAgICAgIHNpZ24gPSBtYXRjaFsxXSA9PT0gJy0nID8gLTEgOiAxO1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgICAgICBkOiB0b0ludChtYXRjaFtEQVRFXSkgKiBzaWduLFxuICAgICAgICAgICAgICAgIGg6IHRvSW50KG1hdGNoW0hPVVJdKSAqIHNpZ24sXG4gICAgICAgICAgICAgICAgbTogdG9JbnQobWF0Y2hbTUlOVVRFXSkgKiBzaWduLFxuICAgICAgICAgICAgICAgIHM6IHRvSW50KG1hdGNoW1NFQ09ORF0pICogc2lnbixcbiAgICAgICAgICAgICAgICBtczogdG9JbnQoYWJzUm91bmQobWF0Y2hbTUlMTElTRUNPTkRdICogMTAwMCkpICogc2lnbiwgLy8gdGhlIG1pbGxpc2Vjb25kIGRlY2ltYWwgcG9pbnQgaXMgaW5jbHVkZWQgaW4gdGhlIG1hdGNoXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2UgaWYgKChtYXRjaCA9IGlzb1JlZ2V4LmV4ZWMoaW5wdXQpKSkge1xuICAgICAgICAgICAgc2lnbiA9IG1hdGNoWzFdID09PSAnLScgPyAtMSA6IDE7XG4gICAgICAgICAgICBkdXJhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICB5OiBwYXJzZUlzbyhtYXRjaFsyXSwgc2lnbiksXG4gICAgICAgICAgICAgICAgTTogcGFyc2VJc28obWF0Y2hbM10sIHNpZ24pLFxuICAgICAgICAgICAgICAgIHc6IHBhcnNlSXNvKG1hdGNoWzRdLCBzaWduKSxcbiAgICAgICAgICAgICAgICBkOiBwYXJzZUlzbyhtYXRjaFs1XSwgc2lnbiksXG4gICAgICAgICAgICAgICAgaDogcGFyc2VJc28obWF0Y2hbNl0sIHNpZ24pLFxuICAgICAgICAgICAgICAgIG06IHBhcnNlSXNvKG1hdGNoWzddLCBzaWduKSxcbiAgICAgICAgICAgICAgICBzOiBwYXJzZUlzbyhtYXRjaFs4XSwgc2lnbiksXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2UgaWYgKGR1cmF0aW9uID09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIGNoZWNrcyBmb3IgbnVsbCBvciB1bmRlZmluZWRcbiAgICAgICAgICAgIGR1cmF0aW9uID0ge307XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICB0eXBlb2YgZHVyYXRpb24gPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgICAoJ2Zyb20nIGluIGR1cmF0aW9uIHx8ICd0bycgaW4gZHVyYXRpb24pXG4gICAgICAgICkge1xuICAgICAgICAgICAgZGlmZlJlcyA9IG1vbWVudHNEaWZmZXJlbmNlKFxuICAgICAgICAgICAgICAgIGNyZWF0ZUxvY2FsKGR1cmF0aW9uLmZyb20pLFxuICAgICAgICAgICAgICAgIGNyZWF0ZUxvY2FsKGR1cmF0aW9uLnRvKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgZHVyYXRpb24gPSB7fTtcbiAgICAgICAgICAgIGR1cmF0aW9uLm1zID0gZGlmZlJlcy5taWxsaXNlY29uZHM7XG4gICAgICAgICAgICBkdXJhdGlvbi5NID0gZGlmZlJlcy5tb250aHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXQgPSBuZXcgRHVyYXRpb24oZHVyYXRpb24pO1xuXG4gICAgICAgIGlmIChpc0R1cmF0aW9uKGlucHV0KSAmJiBoYXNPd25Qcm9wKGlucHV0LCAnX2xvY2FsZScpKSB7XG4gICAgICAgICAgICByZXQuX2xvY2FsZSA9IGlucHV0Ll9sb2NhbGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNEdXJhdGlvbihpbnB1dCkgJiYgaGFzT3duUHJvcChpbnB1dCwgJ19pc1ZhbGlkJykpIHtcbiAgICAgICAgICAgIHJldC5faXNWYWxpZCA9IGlucHV0Ll9pc1ZhbGlkO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG5cbiAgICBjcmVhdGVEdXJhdGlvbi5mbiA9IER1cmF0aW9uLnByb3RvdHlwZTtcbiAgICBjcmVhdGVEdXJhdGlvbi5pbnZhbGlkID0gY3JlYXRlSW52YWxpZCQxO1xuXG4gICAgZnVuY3Rpb24gcGFyc2VJc28oaW5wLCBzaWduKSB7XG4gICAgICAgIC8vIFdlJ2Qgbm9ybWFsbHkgdXNlIH5+aW5wIGZvciB0aGlzLCBidXQgdW5mb3J0dW5hdGVseSBpdCBhbHNvXG4gICAgICAgIC8vIGNvbnZlcnRzIGZsb2F0cyB0byBpbnRzLlxuICAgICAgICAvLyBpbnAgbWF5IGJlIHVuZGVmaW5lZCwgc28gY2FyZWZ1bCBjYWxsaW5nIHJlcGxhY2Ugb24gaXQuXG4gICAgICAgIHZhciByZXMgPSBpbnAgJiYgcGFyc2VGbG9hdChpbnAucmVwbGFjZSgnLCcsICcuJykpO1xuICAgICAgICAvLyBhcHBseSBzaWduIHdoaWxlIHdlJ3JlIGF0IGl0XG4gICAgICAgIHJldHVybiAoaXNOYU4ocmVzKSA/IDAgOiByZXMpICogc2lnbjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwb3NpdGl2ZU1vbWVudHNEaWZmZXJlbmNlKGJhc2UsIG90aGVyKSB7XG4gICAgICAgIHZhciByZXMgPSB7fTtcblxuICAgICAgICByZXMubW9udGhzID1cbiAgICAgICAgICAgIG90aGVyLm1vbnRoKCkgLSBiYXNlLm1vbnRoKCkgKyAob3RoZXIueWVhcigpIC0gYmFzZS55ZWFyKCkpICogMTI7XG4gICAgICAgIGlmIChiYXNlLmNsb25lKCkuYWRkKHJlcy5tb250aHMsICdNJykuaXNBZnRlcihvdGhlcikpIHtcbiAgICAgICAgICAgIC0tcmVzLm1vbnRocztcbiAgICAgICAgfVxuXG4gICAgICAgIHJlcy5taWxsaXNlY29uZHMgPSArb3RoZXIgLSArYmFzZS5jbG9uZSgpLmFkZChyZXMubW9udGhzLCAnTScpO1xuXG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbW9tZW50c0RpZmZlcmVuY2UoYmFzZSwgb3RoZXIpIHtcbiAgICAgICAgdmFyIHJlcztcbiAgICAgICAgaWYgKCEoYmFzZS5pc1ZhbGlkKCkgJiYgb3RoZXIuaXNWYWxpZCgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgbWlsbGlzZWNvbmRzOiAwLCBtb250aHM6IDAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIG90aGVyID0gY2xvbmVXaXRoT2Zmc2V0KG90aGVyLCBiYXNlKTtcbiAgICAgICAgaWYgKGJhc2UuaXNCZWZvcmUob3RoZXIpKSB7XG4gICAgICAgICAgICByZXMgPSBwb3NpdGl2ZU1vbWVudHNEaWZmZXJlbmNlKGJhc2UsIG90aGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcyA9IHBvc2l0aXZlTW9tZW50c0RpZmZlcmVuY2Uob3RoZXIsIGJhc2UpO1xuICAgICAgICAgICAgcmVzLm1pbGxpc2Vjb25kcyA9IC1yZXMubWlsbGlzZWNvbmRzO1xuICAgICAgICAgICAgcmVzLm1vbnRocyA9IC1yZXMubW9udGhzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvLyBUT0RPOiByZW1vdmUgJ25hbWUnIGFyZyBhZnRlciBkZXByZWNhdGlvbiBpcyByZW1vdmVkXG4gICAgZnVuY3Rpb24gY3JlYXRlQWRkZXIoZGlyZWN0aW9uLCBuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAodmFsLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHZhciBkdXIsIHRtcDtcbiAgICAgICAgICAgIC8vaW52ZXJ0IHRoZSBhcmd1bWVudHMsIGJ1dCBjb21wbGFpbiBhYm91dCBpdFxuICAgICAgICAgICAgaWYgKHBlcmlvZCAhPT0gbnVsbCAmJiAhaXNOYU4oK3BlcmlvZCkpIHtcbiAgICAgICAgICAgICAgICBkZXByZWNhdGVTaW1wbGUoXG4gICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgICdtb21lbnQoKS4nICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJyhwZXJpb2QsIG51bWJlcikgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBtb21lbnQoKS4nICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJyhudW1iZXIsIHBlcmlvZCkuICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ1NlZSBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL2FkZC1pbnZlcnRlZC1wYXJhbS8gZm9yIG1vcmUgaW5mby4nXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0bXAgPSB2YWw7XG4gICAgICAgICAgICAgICAgdmFsID0gcGVyaW9kO1xuICAgICAgICAgICAgICAgIHBlcmlvZCA9IHRtcDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZHVyID0gY3JlYXRlRHVyYXRpb24odmFsLCBwZXJpb2QpO1xuICAgICAgICAgICAgYWRkU3VidHJhY3QodGhpcywgZHVyLCBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkU3VidHJhY3QobW9tLCBkdXJhdGlvbiwgaXNBZGRpbmcsIHVwZGF0ZU9mZnNldCkge1xuICAgICAgICB2YXIgbWlsbGlzZWNvbmRzID0gZHVyYXRpb24uX21pbGxpc2Vjb25kcyxcbiAgICAgICAgICAgIGRheXMgPSBhYnNSb3VuZChkdXJhdGlvbi5fZGF5cyksXG4gICAgICAgICAgICBtb250aHMgPSBhYnNSb3VuZChkdXJhdGlvbi5fbW9udGhzKTtcblxuICAgICAgICBpZiAoIW1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIC8vIE5vIG9wXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB1cGRhdGVPZmZzZXQgPSB1cGRhdGVPZmZzZXQgPT0gbnVsbCA/IHRydWUgOiB1cGRhdGVPZmZzZXQ7XG5cbiAgICAgICAgaWYgKG1vbnRocykge1xuICAgICAgICAgICAgc2V0TW9udGgobW9tLCBnZXQobW9tLCAnTW9udGgnKSArIG1vbnRocyAqIGlzQWRkaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF5cykge1xuICAgICAgICAgICAgc2V0JDEobW9tLCAnRGF0ZScsIGdldChtb20sICdEYXRlJykgKyBkYXlzICogaXNBZGRpbmcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtaWxsaXNlY29uZHMpIHtcbiAgICAgICAgICAgIG1vbS5fZC5zZXRUaW1lKG1vbS5fZC52YWx1ZU9mKCkgKyBtaWxsaXNlY29uZHMgKiBpc0FkZGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVwZGF0ZU9mZnNldCkge1xuICAgICAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KG1vbSwgZGF5cyB8fCBtb250aHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGFkZCA9IGNyZWF0ZUFkZGVyKDEsICdhZGQnKSxcbiAgICAgICAgc3VidHJhY3QgPSBjcmVhdGVBZGRlcigtMSwgJ3N1YnRyYWN0Jyk7XG5cbiAgICBmdW5jdGlvbiBpc1N0cmluZyhpbnB1dCkge1xuICAgICAgICByZXR1cm4gdHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJyB8fCBpbnB1dCBpbnN0YW5jZW9mIFN0cmluZztcbiAgICB9XG5cbiAgICAvLyB0eXBlIE1vbWVudElucHV0ID0gTW9tZW50IHwgRGF0ZSB8IHN0cmluZyB8IG51bWJlciB8IChudW1iZXIgfCBzdHJpbmcpW10gfCBNb21lbnRJbnB1dE9iamVjdCB8IHZvaWQ7IC8vIG51bGwgfCB1bmRlZmluZWRcbiAgICBmdW5jdGlvbiBpc01vbWVudElucHV0KGlucHV0KSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBpc01vbWVudChpbnB1dCkgfHxcbiAgICAgICAgICAgIGlzRGF0ZShpbnB1dCkgfHxcbiAgICAgICAgICAgIGlzU3RyaW5nKGlucHV0KSB8fFxuICAgICAgICAgICAgaXNOdW1iZXIoaW5wdXQpIHx8XG4gICAgICAgICAgICBpc051bWJlck9yU3RyaW5nQXJyYXkoaW5wdXQpIHx8XG4gICAgICAgICAgICBpc01vbWVudElucHV0T2JqZWN0KGlucHV0KSB8fFxuICAgICAgICAgICAgaW5wdXQgPT09IG51bGwgfHxcbiAgICAgICAgICAgIGlucHV0ID09PSB1bmRlZmluZWRcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc01vbWVudElucHV0T2JqZWN0KGlucHV0KSB7XG4gICAgICAgIHZhciBvYmplY3RUZXN0ID0gaXNPYmplY3QoaW5wdXQpICYmICFpc09iamVjdEVtcHR5KGlucHV0KSxcbiAgICAgICAgICAgIHByb3BlcnR5VGVzdCA9IGZhbHNlLFxuICAgICAgICAgICAgcHJvcGVydGllcyA9IFtcbiAgICAgICAgICAgICAgICAneWVhcnMnLFxuICAgICAgICAgICAgICAgICd5ZWFyJyxcbiAgICAgICAgICAgICAgICAneScsXG4gICAgICAgICAgICAgICAgJ21vbnRocycsXG4gICAgICAgICAgICAgICAgJ21vbnRoJyxcbiAgICAgICAgICAgICAgICAnTScsXG4gICAgICAgICAgICAgICAgJ2RheXMnLFxuICAgICAgICAgICAgICAgICdkYXknLFxuICAgICAgICAgICAgICAgICdkJyxcbiAgICAgICAgICAgICAgICAnZGF0ZXMnLFxuICAgICAgICAgICAgICAgICdkYXRlJyxcbiAgICAgICAgICAgICAgICAnRCcsXG4gICAgICAgICAgICAgICAgJ2hvdXJzJyxcbiAgICAgICAgICAgICAgICAnaG91cicsXG4gICAgICAgICAgICAgICAgJ2gnLFxuICAgICAgICAgICAgICAgICdtaW51dGVzJyxcbiAgICAgICAgICAgICAgICAnbWludXRlJyxcbiAgICAgICAgICAgICAgICAnbScsXG4gICAgICAgICAgICAgICAgJ3NlY29uZHMnLFxuICAgICAgICAgICAgICAgICdzZWNvbmQnLFxuICAgICAgICAgICAgICAgICdzJyxcbiAgICAgICAgICAgICAgICAnbWlsbGlzZWNvbmRzJyxcbiAgICAgICAgICAgICAgICAnbWlsbGlzZWNvbmQnLFxuICAgICAgICAgICAgICAgICdtcycsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIHByb3BlcnR5O1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBwcm9wZXJ0aWVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbaV07XG4gICAgICAgICAgICBwcm9wZXJ0eVRlc3QgPSBwcm9wZXJ0eVRlc3QgfHwgaGFzT3duUHJvcChpbnB1dCwgcHJvcGVydHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG9iamVjdFRlc3QgJiYgcHJvcGVydHlUZXN0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzTnVtYmVyT3JTdHJpbmdBcnJheShpbnB1dCkge1xuICAgICAgICB2YXIgYXJyYXlUZXN0ID0gaXNBcnJheShpbnB1dCksXG4gICAgICAgICAgICBkYXRhVHlwZVRlc3QgPSBmYWxzZTtcbiAgICAgICAgaWYgKGFycmF5VGVzdCkge1xuICAgICAgICAgICAgZGF0YVR5cGVUZXN0ID1cbiAgICAgICAgICAgICAgICBpbnB1dC5maWx0ZXIoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICFpc051bWJlcihpdGVtKSAmJiBpc1N0cmluZyhpbnB1dCk7XG4gICAgICAgICAgICAgICAgfSkubGVuZ3RoID09PSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcnJheVRlc3QgJiYgZGF0YVR5cGVUZXN0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzQ2FsZW5kYXJTcGVjKGlucHV0KSB7XG4gICAgICAgIHZhciBvYmplY3RUZXN0ID0gaXNPYmplY3QoaW5wdXQpICYmICFpc09iamVjdEVtcHR5KGlucHV0KSxcbiAgICAgICAgICAgIHByb3BlcnR5VGVzdCA9IGZhbHNlLFxuICAgICAgICAgICAgcHJvcGVydGllcyA9IFtcbiAgICAgICAgICAgICAgICAnc2FtZURheScsXG4gICAgICAgICAgICAgICAgJ25leHREYXknLFxuICAgICAgICAgICAgICAgICdsYXN0RGF5JyxcbiAgICAgICAgICAgICAgICAnbmV4dFdlZWsnLFxuICAgICAgICAgICAgICAgICdsYXN0V2VlaycsXG4gICAgICAgICAgICAgICAgJ3NhbWVFbHNlJyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgcHJvcGVydHk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHByb3BlcnRpZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHByb3BlcnR5ID0gcHJvcGVydGllc1tpXTtcbiAgICAgICAgICAgIHByb3BlcnR5VGVzdCA9IHByb3BlcnR5VGVzdCB8fCBoYXNPd25Qcm9wKGlucHV0LCBwcm9wZXJ0eSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb2JqZWN0VGVzdCAmJiBwcm9wZXJ0eVRlc3Q7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q2FsZW5kYXJGb3JtYXQobXlNb21lbnQsIG5vdykge1xuICAgICAgICB2YXIgZGlmZiA9IG15TW9tZW50LmRpZmYobm93LCAnZGF5cycsIHRydWUpO1xuICAgICAgICByZXR1cm4gZGlmZiA8IC02XG4gICAgICAgICAgICA/ICdzYW1lRWxzZSdcbiAgICAgICAgICAgIDogZGlmZiA8IC0xXG4gICAgICAgICAgICA/ICdsYXN0V2VlaydcbiAgICAgICAgICAgIDogZGlmZiA8IDBcbiAgICAgICAgICAgID8gJ2xhc3REYXknXG4gICAgICAgICAgICA6IGRpZmYgPCAxXG4gICAgICAgICAgICA/ICdzYW1lRGF5J1xuICAgICAgICAgICAgOiBkaWZmIDwgMlxuICAgICAgICAgICAgPyAnbmV4dERheSdcbiAgICAgICAgICAgIDogZGlmZiA8IDdcbiAgICAgICAgICAgID8gJ25leHRXZWVrJ1xuICAgICAgICAgICAgOiAnc2FtZUVsc2UnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNhbGVuZGFyJDEodGltZSwgZm9ybWF0cykge1xuICAgICAgICAvLyBTdXBwb3J0IGZvciBzaW5nbGUgcGFyYW1ldGVyLCBmb3JtYXRzIG9ubHkgb3ZlcmxvYWQgdG8gdGhlIGNhbGVuZGFyIGZ1bmN0aW9uXG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICBpZiAoIWFyZ3VtZW50c1swXSkge1xuICAgICAgICAgICAgICAgIHRpbWUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgZm9ybWF0cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNNb21lbnRJbnB1dChhcmd1bWVudHNbMF0pKSB7XG4gICAgICAgICAgICAgICAgdGltZSA9IGFyZ3VtZW50c1swXTtcbiAgICAgICAgICAgICAgICBmb3JtYXRzID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NhbGVuZGFyU3BlYyhhcmd1bWVudHNbMF0pKSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0cyA9IGFyZ3VtZW50c1swXTtcbiAgICAgICAgICAgICAgICB0aW1lID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIFdlIHdhbnQgdG8gY29tcGFyZSB0aGUgc3RhcnQgb2YgdG9kYXksIHZzIHRoaXMuXG4gICAgICAgIC8vIEdldHRpbmcgc3RhcnQtb2YtdG9kYXkgZGVwZW5kcyBvbiB3aGV0aGVyIHdlJ3JlIGxvY2FsL3V0Yy9vZmZzZXQgb3Igbm90LlxuICAgICAgICB2YXIgbm93ID0gdGltZSB8fCBjcmVhdGVMb2NhbCgpLFxuICAgICAgICAgICAgc29kID0gY2xvbmVXaXRoT2Zmc2V0KG5vdywgdGhpcykuc3RhcnRPZignZGF5JyksXG4gICAgICAgICAgICBmb3JtYXQgPSBob29rcy5jYWxlbmRhckZvcm1hdCh0aGlzLCBzb2QpIHx8ICdzYW1lRWxzZScsXG4gICAgICAgICAgICBvdXRwdXQgPVxuICAgICAgICAgICAgICAgIGZvcm1hdHMgJiZcbiAgICAgICAgICAgICAgICAoaXNGdW5jdGlvbihmb3JtYXRzW2Zvcm1hdF0pXG4gICAgICAgICAgICAgICAgICAgID8gZm9ybWF0c1tmb3JtYXRdLmNhbGwodGhpcywgbm93KVxuICAgICAgICAgICAgICAgICAgICA6IGZvcm1hdHNbZm9ybWF0XSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0KFxuICAgICAgICAgICAgb3V0cHV0IHx8IHRoaXMubG9jYWxlRGF0YSgpLmNhbGVuZGFyKGZvcm1hdCwgdGhpcywgY3JlYXRlTG9jYWwobm93KSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbG9uZSgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNb21lbnQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNBZnRlcihpbnB1dCwgdW5pdHMpIHtcbiAgICAgICAgdmFyIGxvY2FsSW5wdXQgPSBpc01vbWVudChpbnB1dCkgPyBpbnB1dCA6IGNyZWF0ZUxvY2FsKGlucHV0KTtcbiAgICAgICAgaWYgKCEodGhpcy5pc1ZhbGlkKCkgJiYgbG9jYWxJbnB1dC5pc1ZhbGlkKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cykgfHwgJ21pbGxpc2Vjb25kJztcbiAgICAgICAgaWYgKHVuaXRzID09PSAnbWlsbGlzZWNvbmQnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZU9mKCkgPiBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBsb2NhbElucHV0LnZhbHVlT2YoKSA8IHRoaXMuY2xvbmUoKS5zdGFydE9mKHVuaXRzKS52YWx1ZU9mKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0JlZm9yZShpbnB1dCwgdW5pdHMpIHtcbiAgICAgICAgdmFyIGxvY2FsSW5wdXQgPSBpc01vbWVudChpbnB1dCkgPyBpbnB1dCA6IGNyZWF0ZUxvY2FsKGlucHV0KTtcbiAgICAgICAgaWYgKCEodGhpcy5pc1ZhbGlkKCkgJiYgbG9jYWxJbnB1dC5pc1ZhbGlkKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cykgfHwgJ21pbGxpc2Vjb25kJztcbiAgICAgICAgaWYgKHVuaXRzID09PSAnbWlsbGlzZWNvbmQnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZU9mKCkgPCBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNsb25lKCkuZW5kT2YodW5pdHMpLnZhbHVlT2YoKSA8IGxvY2FsSW5wdXQudmFsdWVPZigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNCZXR3ZWVuKGZyb20sIHRvLCB1bml0cywgaW5jbHVzaXZpdHkpIHtcbiAgICAgICAgdmFyIGxvY2FsRnJvbSA9IGlzTW9tZW50KGZyb20pID8gZnJvbSA6IGNyZWF0ZUxvY2FsKGZyb20pLFxuICAgICAgICAgICAgbG9jYWxUbyA9IGlzTW9tZW50KHRvKSA/IHRvIDogY3JlYXRlTG9jYWwodG8pO1xuICAgICAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbEZyb20uaXNWYWxpZCgpICYmIGxvY2FsVG8uaXNWYWxpZCgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGluY2x1c2l2aXR5ID0gaW5jbHVzaXZpdHkgfHwgJygpJztcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIChpbmNsdXNpdml0eVswXSA9PT0gJygnXG4gICAgICAgICAgICAgICAgPyB0aGlzLmlzQWZ0ZXIobG9jYWxGcm9tLCB1bml0cylcbiAgICAgICAgICAgICAgICA6ICF0aGlzLmlzQmVmb3JlKGxvY2FsRnJvbSwgdW5pdHMpKSAmJlxuICAgICAgICAgICAgKGluY2x1c2l2aXR5WzFdID09PSAnKSdcbiAgICAgICAgICAgICAgICA/IHRoaXMuaXNCZWZvcmUobG9jYWxUbywgdW5pdHMpXG4gICAgICAgICAgICAgICAgOiAhdGhpcy5pc0FmdGVyKGxvY2FsVG8sIHVuaXRzKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1NhbWUoaW5wdXQsIHVuaXRzKSB7XG4gICAgICAgIHZhciBsb2NhbElucHV0ID0gaXNNb21lbnQoaW5wdXQpID8gaW5wdXQgOiBjcmVhdGVMb2NhbChpbnB1dCksXG4gICAgICAgICAgICBpbnB1dE1zO1xuICAgICAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbElucHV0LmlzVmFsaWQoKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKSB8fCAnbWlsbGlzZWNvbmQnO1xuICAgICAgICBpZiAodW5pdHMgPT09ICdtaWxsaXNlY29uZCcpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlT2YoKSA9PT0gbG9jYWxJbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbnB1dE1zID0gbG9jYWxJbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHRoaXMuY2xvbmUoKS5zdGFydE9mKHVuaXRzKS52YWx1ZU9mKCkgPD0gaW5wdXRNcyAmJlxuICAgICAgICAgICAgICAgIGlucHV0TXMgPD0gdGhpcy5jbG9uZSgpLmVuZE9mKHVuaXRzKS52YWx1ZU9mKClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1NhbWVPckFmdGVyKGlucHV0LCB1bml0cykge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1NhbWUoaW5wdXQsIHVuaXRzKSB8fCB0aGlzLmlzQWZ0ZXIoaW5wdXQsIHVuaXRzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1NhbWVPckJlZm9yZShpbnB1dCwgdW5pdHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNTYW1lKGlucHV0LCB1bml0cykgfHwgdGhpcy5pc0JlZm9yZShpbnB1dCwgdW5pdHMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRpZmYoaW5wdXQsIHVuaXRzLCBhc0Zsb2F0KSB7XG4gICAgICAgIHZhciB0aGF0LCB6b25lRGVsdGEsIG91dHB1dDtcblxuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhhdCA9IGNsb25lV2l0aE9mZnNldChpbnB1dCwgdGhpcyk7XG5cbiAgICAgICAgaWYgKCF0aGF0LmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuXG4gICAgICAgIHpvbmVEZWx0YSA9ICh0aGF0LnV0Y09mZnNldCgpIC0gdGhpcy51dGNPZmZzZXQoKSkgKiA2ZTQ7XG5cbiAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG5cbiAgICAgICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICAgICAgY2FzZSAneWVhcic6XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gbW9udGhEaWZmKHRoaXMsIHRoYXQpIC8gMTI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtb250aCc6XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gbW9udGhEaWZmKHRoaXMsIHRoYXQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncXVhcnRlcic6XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gbW9udGhEaWZmKHRoaXMsIHRoYXQpIC8gMztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NlY29uZCc6XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKHRoaXMgLSB0aGF0KSAvIDFlMztcbiAgICAgICAgICAgICAgICBicmVhazsgLy8gMTAwMFxuICAgICAgICAgICAgY2FzZSAnbWludXRlJzpcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAodGhpcyAtIHRoYXQpIC8gNmU0O1xuICAgICAgICAgICAgICAgIGJyZWFrOyAvLyAxMDAwICogNjBcbiAgICAgICAgICAgIGNhc2UgJ2hvdXInOlxuICAgICAgICAgICAgICAgIG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyAzNmU1O1xuICAgICAgICAgICAgICAgIGJyZWFrOyAvLyAxMDAwICogNjAgKiA2MFxuICAgICAgICAgICAgY2FzZSAnZGF5JzpcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAodGhpcyAtIHRoYXQgLSB6b25lRGVsdGEpIC8gODY0ZTU7XG4gICAgICAgICAgICAgICAgYnJlYWs7IC8vIDEwMDAgKiA2MCAqIDYwICogMjQsIG5lZ2F0ZSBkc3RcbiAgICAgICAgICAgIGNhc2UgJ3dlZWsnOlxuICAgICAgICAgICAgICAgIG91dHB1dCA9ICh0aGlzIC0gdGhhdCAtIHpvbmVEZWx0YSkgLyA2MDQ4ZTU7XG4gICAgICAgICAgICAgICAgYnJlYWs7IC8vIDEwMDAgKiA2MCAqIDYwICogMjQgKiA3LCBuZWdhdGUgZHN0XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIG91dHB1dCA9IHRoaXMgLSB0aGF0O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFzRmxvYXQgPyBvdXRwdXQgOiBhYnNGbG9vcihvdXRwdXQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vbnRoRGlmZihhLCBiKSB7XG4gICAgICAgIGlmIChhLmRhdGUoKSA8IGIuZGF0ZSgpKSB7XG4gICAgICAgICAgICAvLyBlbmQtb2YtbW9udGggY2FsY3VsYXRpb25zIHdvcmsgY29ycmVjdCB3aGVuIHRoZSBzdGFydCBtb250aCBoYXMgbW9yZVxuICAgICAgICAgICAgLy8gZGF5cyB0aGFuIHRoZSBlbmQgbW9udGguXG4gICAgICAgICAgICByZXR1cm4gLW1vbnRoRGlmZihiLCBhKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBkaWZmZXJlbmNlIGluIG1vbnRoc1xuICAgICAgICB2YXIgd2hvbGVNb250aERpZmYgPSAoYi55ZWFyKCkgLSBhLnllYXIoKSkgKiAxMiArIChiLm1vbnRoKCkgLSBhLm1vbnRoKCkpLFxuICAgICAgICAgICAgLy8gYiBpcyBpbiAoYW5jaG9yIC0gMSBtb250aCwgYW5jaG9yICsgMSBtb250aClcbiAgICAgICAgICAgIGFuY2hvciA9IGEuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYsICdtb250aHMnKSxcbiAgICAgICAgICAgIGFuY2hvcjIsXG4gICAgICAgICAgICBhZGp1c3Q7XG5cbiAgICAgICAgaWYgKGIgLSBhbmNob3IgPCAwKSB7XG4gICAgICAgICAgICBhbmNob3IyID0gYS5jbG9uZSgpLmFkZCh3aG9sZU1vbnRoRGlmZiAtIDEsICdtb250aHMnKTtcbiAgICAgICAgICAgIC8vIGxpbmVhciBhY3Jvc3MgdGhlIG1vbnRoXG4gICAgICAgICAgICBhZGp1c3QgPSAoYiAtIGFuY2hvcikgLyAoYW5jaG9yIC0gYW5jaG9yMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhbmNob3IyID0gYS5jbG9uZSgpLmFkZCh3aG9sZU1vbnRoRGlmZiArIDEsICdtb250aHMnKTtcbiAgICAgICAgICAgIC8vIGxpbmVhciBhY3Jvc3MgdGhlIG1vbnRoXG4gICAgICAgICAgICBhZGp1c3QgPSAoYiAtIGFuY2hvcikgLyAoYW5jaG9yMiAtIGFuY2hvcik7XG4gICAgICAgIH1cblxuICAgICAgICAvL2NoZWNrIGZvciBuZWdhdGl2ZSB6ZXJvLCByZXR1cm4gemVybyBpZiBuZWdhdGl2ZSB6ZXJvXG4gICAgICAgIHJldHVybiAtKHdob2xlTW9udGhEaWZmICsgYWRqdXN0KSB8fCAwO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmF1bHRGb3JtYXQgPSAnWVlZWS1NTS1ERFRISDptbTpzc1onO1xuICAgIGhvb2tzLmRlZmF1bHRGb3JtYXRVdGMgPSAnWVlZWS1NTS1ERFRISDptbTpzc1taXSc7XG5cbiAgICBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5sb2NhbGUoJ2VuJykuZm9ybWF0KCdkZGQgTU1NIEREIFlZWVkgSEg6bW06c3MgW0dNVF1aWicpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvSVNPU3RyaW5nKGtlZXBPZmZzZXQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHV0YyA9IGtlZXBPZmZzZXQgIT09IHRydWUsXG4gICAgICAgICAgICBtID0gdXRjID8gdGhpcy5jbG9uZSgpLnV0YygpIDogdGhpcztcbiAgICAgICAgaWYgKG0ueWVhcigpIDwgMCB8fCBtLnllYXIoKSA+IDk5OTkpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXRNb21lbnQoXG4gICAgICAgICAgICAgICAgbSxcbiAgICAgICAgICAgICAgICB1dGNcbiAgICAgICAgICAgICAgICAgICAgPyAnWVlZWVlZLU1NLUREW1RdSEg6bW06c3MuU1NTW1pdJ1xuICAgICAgICAgICAgICAgICAgICA6ICdZWVlZWVktTU0tRERbVF1ISDptbTpzcy5TU1NaJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNGdW5jdGlvbihEYXRlLnByb3RvdHlwZS50b0lTT1N0cmluZykpIHtcbiAgICAgICAgICAgIC8vIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbiBpcyB+NTB4IGZhc3RlciwgdXNlIGl0IHdoZW4gd2UgY2FuXG4gICAgICAgICAgICBpZiAodXRjKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9EYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHRoaXMudmFsdWVPZigpICsgdGhpcy51dGNPZmZzZXQoKSAqIDYwICogMTAwMClcbiAgICAgICAgICAgICAgICAgICAgLnRvSVNPU3RyaW5nKClcbiAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoJ1onLCBmb3JtYXRNb21lbnQobSwgJ1onKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZvcm1hdE1vbWVudChcbiAgICAgICAgICAgIG0sXG4gICAgICAgICAgICB1dGMgPyAnWVlZWS1NTS1ERFtUXUhIOm1tOnNzLlNTU1taXScgOiAnWVlZWS1NTS1ERFtUXUhIOm1tOnNzLlNTU1onXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGEgaHVtYW4gcmVhZGFibGUgcmVwcmVzZW50YXRpb24gb2YgYSBtb21lbnQgdGhhdCBjYW5cbiAgICAgKiBhbHNvIGJlIGV2YWx1YXRlZCB0byBnZXQgYSBuZXcgbW9tZW50IHdoaWNoIGlzIHRoZSBzYW1lXG4gICAgICpcbiAgICAgKiBAbGluayBodHRwczovL25vZGVqcy5vcmcvZGlzdC9sYXRlc3QvZG9jcy9hcGkvdXRpbC5odG1sI3V0aWxfY3VzdG9tX2luc3BlY3RfZnVuY3Rpb25fb25fb2JqZWN0c1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluc3BlY3QoKSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiAnbW9tZW50LmludmFsaWQoLyogJyArIHRoaXMuX2kgKyAnICovKSc7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZ1bmMgPSAnbW9tZW50JyxcbiAgICAgICAgICAgIHpvbmUgPSAnJyxcbiAgICAgICAgICAgIHByZWZpeCxcbiAgICAgICAgICAgIHllYXIsXG4gICAgICAgICAgICBkYXRldGltZSxcbiAgICAgICAgICAgIHN1ZmZpeDtcbiAgICAgICAgaWYgKCF0aGlzLmlzTG9jYWwoKSkge1xuICAgICAgICAgICAgZnVuYyA9IHRoaXMudXRjT2Zmc2V0KCkgPT09IDAgPyAnbW9tZW50LnV0YycgOiAnbW9tZW50LnBhcnNlWm9uZSc7XG4gICAgICAgICAgICB6b25lID0gJ1onO1xuICAgICAgICB9XG4gICAgICAgIHByZWZpeCA9ICdbJyArIGZ1bmMgKyAnKFwiXSc7XG4gICAgICAgIHllYXIgPSAwIDw9IHRoaXMueWVhcigpICYmIHRoaXMueWVhcigpIDw9IDk5OTkgPyAnWVlZWScgOiAnWVlZWVlZJztcbiAgICAgICAgZGF0ZXRpbWUgPSAnLU1NLUREW1RdSEg6bW06c3MuU1NTJztcbiAgICAgICAgc3VmZml4ID0gem9uZSArICdbXCIpXSc7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0KHByZWZpeCArIHllYXIgKyBkYXRldGltZSArIHN1ZmZpeCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0KGlucHV0U3RyaW5nKSB7XG4gICAgICAgIGlmICghaW5wdXRTdHJpbmcpIHtcbiAgICAgICAgICAgIGlucHV0U3RyaW5nID0gdGhpcy5pc1V0YygpXG4gICAgICAgICAgICAgICAgPyBob29rcy5kZWZhdWx0Rm9ybWF0VXRjXG4gICAgICAgICAgICAgICAgOiBob29rcy5kZWZhdWx0Rm9ybWF0O1xuICAgICAgICB9XG4gICAgICAgIHZhciBvdXRwdXQgPSBmb3JtYXRNb21lbnQodGhpcywgaW5wdXRTdHJpbmcpO1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkucG9zdGZvcm1hdChvdXRwdXQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZyb20odGltZSwgd2l0aG91dFN1ZmZpeCkge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLmlzVmFsaWQoKSAmJlxuICAgICAgICAgICAgKChpc01vbWVudCh0aW1lKSAmJiB0aW1lLmlzVmFsaWQoKSkgfHwgY3JlYXRlTG9jYWwodGltZSkuaXNWYWxpZCgpKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbih7IHRvOiB0aGlzLCBmcm9tOiB0aW1lIH0pXG4gICAgICAgICAgICAgICAgLmxvY2FsZSh0aGlzLmxvY2FsZSgpKVxuICAgICAgICAgICAgICAgIC5odW1hbml6ZSghd2l0aG91dFN1ZmZpeCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkuaW52YWxpZERhdGUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZyb21Ob3cod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mcm9tKGNyZWF0ZUxvY2FsKCksIHdpdGhvdXRTdWZmaXgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvKHRpbWUsIHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5pc1ZhbGlkKCkgJiZcbiAgICAgICAgICAgICgoaXNNb21lbnQodGltZSkgJiYgdGltZS5pc1ZhbGlkKCkpIHx8IGNyZWF0ZUxvY2FsKHRpbWUpLmlzVmFsaWQoKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oeyBmcm9tOiB0aGlzLCB0bzogdGltZSB9KVxuICAgICAgICAgICAgICAgIC5sb2NhbGUodGhpcy5sb2NhbGUoKSlcbiAgICAgICAgICAgICAgICAuaHVtYW5pemUoIXdpdGhvdXRTdWZmaXgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b05vdyh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRvKGNyZWF0ZUxvY2FsKCksIHdpdGhvdXRTdWZmaXgpO1xuICAgIH1cblxuICAgIC8vIElmIHBhc3NlZCBhIGxvY2FsZSBrZXksIGl0IHdpbGwgc2V0IHRoZSBsb2NhbGUgZm9yIHRoaXNcbiAgICAvLyBpbnN0YW5jZS4gIE90aGVyd2lzZSwgaXQgd2lsbCByZXR1cm4gdGhlIGxvY2FsZSBjb25maWd1cmF0aW9uXG4gICAgLy8gdmFyaWFibGVzIGZvciB0aGlzIGluc3RhbmNlLlxuICAgIGZ1bmN0aW9uIGxvY2FsZShrZXkpIHtcbiAgICAgICAgdmFyIG5ld0xvY2FsZURhdGE7XG5cbiAgICAgICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbG9jYWxlLl9hYmJyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3TG9jYWxlRGF0YSA9IGdldExvY2FsZShrZXkpO1xuICAgICAgICAgICAgaWYgKG5ld0xvY2FsZURhdGEgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2xvY2FsZSA9IG5ld0xvY2FsZURhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsYW5nID0gZGVwcmVjYXRlKFxuICAgICAgICAnbW9tZW50KCkubGFuZygpIGlzIGRlcHJlY2F0ZWQuIEluc3RlYWQsIHVzZSBtb21lbnQoKS5sb2NhbGVEYXRhKCkgdG8gZ2V0IHRoZSBsYW5ndWFnZSBjb25maWd1cmF0aW9uLiBVc2UgbW9tZW50KCkubG9jYWxlKCkgdG8gY2hhbmdlIGxhbmd1YWdlcy4nLFxuICAgICAgICBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICBpZiAoa2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgKTtcblxuICAgIGZ1bmN0aW9uIGxvY2FsZURhdGEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2NhbGU7XG4gICAgfVxuXG4gICAgdmFyIE1TX1BFUl9TRUNPTkQgPSAxMDAwLFxuICAgICAgICBNU19QRVJfTUlOVVRFID0gNjAgKiBNU19QRVJfU0VDT05ELFxuICAgICAgICBNU19QRVJfSE9VUiA9IDYwICogTVNfUEVSX01JTlVURSxcbiAgICAgICAgTVNfUEVSXzQwMF9ZRUFSUyA9ICgzNjUgKiA0MDAgKyA5NykgKiAyNCAqIE1TX1BFUl9IT1VSO1xuXG4gICAgLy8gYWN0dWFsIG1vZHVsbyAtIGhhbmRsZXMgbmVnYXRpdmUgbnVtYmVycyAoZm9yIGRhdGVzIGJlZm9yZSAxOTcwKTpcbiAgICBmdW5jdGlvbiBtb2QkMShkaXZpZGVuZCwgZGl2aXNvcikge1xuICAgICAgICByZXR1cm4gKChkaXZpZGVuZCAlIGRpdmlzb3IpICsgZGl2aXNvcikgJSBkaXZpc29yO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvY2FsU3RhcnRPZkRhdGUoeSwgbSwgZCkge1xuICAgICAgICAvLyB0aGUgZGF0ZSBjb25zdHJ1Y3RvciByZW1hcHMgeWVhcnMgMC05OSB0byAxOTAwLTE5OTlcbiAgICAgICAgaWYgKHkgPCAxMDAgJiYgeSA+PSAwKSB7XG4gICAgICAgICAgICAvLyBwcmVzZXJ2ZSBsZWFwIHllYXJzIHVzaW5nIGEgZnVsbCA0MDAgeWVhciBjeWNsZSwgdGhlbiByZXNldFxuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHkgKyA0MDAsIG0sIGQpIC0gTVNfUEVSXzQwMF9ZRUFSUztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGF0ZSh5LCBtLCBkKS52YWx1ZU9mKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1dGNTdGFydE9mRGF0ZSh5LCBtLCBkKSB7XG4gICAgICAgIC8vIERhdGUuVVRDIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgICAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDApIHtcbiAgICAgICAgICAgIC8vIHByZXNlcnZlIGxlYXAgeWVhcnMgdXNpbmcgYSBmdWxsIDQwMCB5ZWFyIGN5Y2xlLCB0aGVuIHJlc2V0XG4gICAgICAgICAgICByZXR1cm4gRGF0ZS5VVEMoeSArIDQwMCwgbSwgZCkgLSBNU19QRVJfNDAwX1lFQVJTO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIERhdGUuVVRDKHksIG0sIGQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3RhcnRPZih1bml0cykge1xuICAgICAgICB2YXIgdGltZSwgc3RhcnRPZkRhdGU7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICBpZiAodW5pdHMgPT09IHVuZGVmaW5lZCB8fCB1bml0cyA9PT0gJ21pbGxpc2Vjb25kJyB8fCAhdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RhcnRPZkRhdGUgPSB0aGlzLl9pc1VUQyA/IHV0Y1N0YXJ0T2ZEYXRlIDogbG9jYWxTdGFydE9mRGF0ZTtcblxuICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgICAgICBjYXNlICd5ZWFyJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIDAsIDEpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncXVhcnRlcic6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnllYXIoKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb250aCgpIC0gKHRoaXMubW9udGgoKSAlIDMpLFxuICAgICAgICAgICAgICAgICAgICAxXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSwgMSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd3ZWVrJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMueWVhcigpLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLm1vbnRoKCksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZSgpIC0gdGhpcy53ZWVrZGF5KClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaXNvV2Vlayc6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnllYXIoKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb250aCgpLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoKSAtICh0aGlzLmlzb1dlZWtkYXkoKSAtIDEpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2RheSc6XG4gICAgICAgICAgICBjYXNlICdkYXRlJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSwgdGhpcy5kYXRlKCkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaG91cic6XG4gICAgICAgICAgICAgICAgdGltZSA9IHRoaXMuX2QudmFsdWVPZigpO1xuICAgICAgICAgICAgICAgIHRpbWUgLT0gbW9kJDEoXG4gICAgICAgICAgICAgICAgICAgIHRpbWUgKyAodGhpcy5faXNVVEMgPyAwIDogdGhpcy51dGNPZmZzZXQoKSAqIE1TX1BFUl9NSU5VVEUpLFxuICAgICAgICAgICAgICAgICAgICBNU19QRVJfSE9VUlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtaW51dGUnOlxuICAgICAgICAgICAgICAgIHRpbWUgPSB0aGlzLl9kLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICB0aW1lIC09IG1vZCQxKHRpbWUsIE1TX1BFUl9NSU5VVEUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2Vjb25kJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gdGhpcy5fZC52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgdGltZSAtPSBtb2QkMSh0aW1lLCBNU19QRVJfU0VDT05EKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2Quc2V0VGltZSh0aW1lKTtcbiAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KHRoaXMsIHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbmRPZih1bml0cykge1xuICAgICAgICB2YXIgdGltZSwgc3RhcnRPZkRhdGU7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICBpZiAodW5pdHMgPT09IHVuZGVmaW5lZCB8fCB1bml0cyA9PT0gJ21pbGxpc2Vjb25kJyB8fCAhdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RhcnRPZkRhdGUgPSB0aGlzLl9pc1VUQyA/IHV0Y1N0YXJ0T2ZEYXRlIDogbG9jYWxTdGFydE9mRGF0ZTtcblxuICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgICAgICBjYXNlICd5ZWFyJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCkgKyAxLCAwLCAxKSAtIDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdxdWFydGVyJzpcbiAgICAgICAgICAgICAgICB0aW1lID1cbiAgICAgICAgICAgICAgICAgICAgc3RhcnRPZkRhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnllYXIoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubW9udGgoKSAtICh0aGlzLm1vbnRoKCkgJSAzKSArIDMsXG4gICAgICAgICAgICAgICAgICAgICAgICAxXG4gICAgICAgICAgICAgICAgICAgICkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbW9udGgnOlxuICAgICAgICAgICAgICAgIHRpbWUgPSBzdGFydE9mRGF0ZSh0aGlzLnllYXIoKSwgdGhpcy5tb250aCgpICsgMSwgMSkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnd2Vlayc6XG4gICAgICAgICAgICAgICAgdGltZSA9XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0T2ZEYXRlKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy55ZWFyKCksXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1vbnRoKCksXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoKSAtIHRoaXMud2Vla2RheSgpICsgN1xuICAgICAgICAgICAgICAgICAgICApIC0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2lzb1dlZWsnOlxuICAgICAgICAgICAgICAgIHRpbWUgPVxuICAgICAgICAgICAgICAgICAgICBzdGFydE9mRGF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueWVhcigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tb250aCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKCkgLSAodGhpcy5pc29XZWVrZGF5KCkgLSAxKSArIDdcbiAgICAgICAgICAgICAgICAgICAgKSAtIDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkYXknOlxuICAgICAgICAgICAgY2FzZSAnZGF0ZSc6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpLCB0aGlzLm1vbnRoKCksIHRoaXMuZGF0ZSgpICsgMSkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaG91cic6XG4gICAgICAgICAgICAgICAgdGltZSA9IHRoaXMuX2QudmFsdWVPZigpO1xuICAgICAgICAgICAgICAgIHRpbWUgKz1cbiAgICAgICAgICAgICAgICAgICAgTVNfUEVSX0hPVVIgLVxuICAgICAgICAgICAgICAgICAgICBtb2QkMShcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWUgKyAodGhpcy5faXNVVEMgPyAwIDogdGhpcy51dGNPZmZzZXQoKSAqIE1TX1BFUl9NSU5VVEUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgTVNfUEVSX0hPVVJcbiAgICAgICAgICAgICAgICAgICAgKSAtXG4gICAgICAgICAgICAgICAgICAgIDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtaW51dGUnOlxuICAgICAgICAgICAgICAgIHRpbWUgPSB0aGlzLl9kLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICB0aW1lICs9IE1TX1BFUl9NSU5VVEUgLSBtb2QkMSh0aW1lLCBNU19QRVJfTUlOVVRFKSAtIDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzZWNvbmQnOlxuICAgICAgICAgICAgICAgIHRpbWUgPSB0aGlzLl9kLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICB0aW1lICs9IE1TX1BFUl9TRUNPTkQgLSBtb2QkMSh0aW1lLCBNU19QRVJfU0VDT05EKSAtIDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9kLnNldFRpbWUodGltZSk7XG4gICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmFsdWVPZigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2QudmFsdWVPZigpIC0gKHRoaXMuX29mZnNldCB8fCAwKSAqIDYwMDAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVuaXgoKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKHRoaXMudmFsdWVPZigpIC8gMTAwMCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdG9EYXRlKCkge1xuICAgICAgICByZXR1cm4gbmV3IERhdGUodGhpcy52YWx1ZU9mKCkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvQXJyYXkoKSB7XG4gICAgICAgIHZhciBtID0gdGhpcztcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIG0ueWVhcigpLFxuICAgICAgICAgICAgbS5tb250aCgpLFxuICAgICAgICAgICAgbS5kYXRlKCksXG4gICAgICAgICAgICBtLmhvdXIoKSxcbiAgICAgICAgICAgIG0ubWludXRlKCksXG4gICAgICAgICAgICBtLnNlY29uZCgpLFxuICAgICAgICAgICAgbS5taWxsaXNlY29uZCgpLFxuICAgICAgICBdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvT2JqZWN0KCkge1xuICAgICAgICB2YXIgbSA9IHRoaXM7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB5ZWFyczogbS55ZWFyKCksXG4gICAgICAgICAgICBtb250aHM6IG0ubW9udGgoKSxcbiAgICAgICAgICAgIGRhdGU6IG0uZGF0ZSgpLFxuICAgICAgICAgICAgaG91cnM6IG0uaG91cnMoKSxcbiAgICAgICAgICAgIG1pbnV0ZXM6IG0ubWludXRlcygpLFxuICAgICAgICAgICAgc2Vjb25kczogbS5zZWNvbmRzKCksXG4gICAgICAgICAgICBtaWxsaXNlY29uZHM6IG0ubWlsbGlzZWNvbmRzKCksXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAvLyBuZXcgRGF0ZShOYU4pLnRvSlNPTigpID09PSBudWxsXG4gICAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMudG9JU09TdHJpbmcoKSA6IG51bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNWYWxpZCQyKCkge1xuICAgICAgICByZXR1cm4gaXNWYWxpZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzaW5nRmxhZ3MoKSB7XG4gICAgICAgIHJldHVybiBleHRlbmQoe30sIGdldFBhcnNpbmdGbGFncyh0aGlzKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW52YWxpZEF0KCkge1xuICAgICAgICByZXR1cm4gZ2V0UGFyc2luZ0ZsYWdzKHRoaXMpLm92ZXJmbG93O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0aW9uRGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGlucHV0OiB0aGlzLl9pLFxuICAgICAgICAgICAgZm9ybWF0OiB0aGlzLl9mLFxuICAgICAgICAgICAgbG9jYWxlOiB0aGlzLl9sb2NhbGUsXG4gICAgICAgICAgICBpc1VUQzogdGhpcy5faXNVVEMsXG4gICAgICAgICAgICBzdHJpY3Q6IHRoaXMuX3N0cmljdCxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBhZGRGb3JtYXRUb2tlbignTicsIDAsIDAsICdlcmFBYmJyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ05OJywgMCwgMCwgJ2VyYUFiYnInKTtcbiAgICBhZGRGb3JtYXRUb2tlbignTk5OJywgMCwgMCwgJ2VyYUFiYnInKTtcbiAgICBhZGRGb3JtYXRUb2tlbignTk5OTicsIDAsIDAsICdlcmFOYW1lJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ05OTk5OJywgMCwgMCwgJ2VyYU5hcnJvdycpO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ3knLCBbJ3knLCAxXSwgJ3lvJywgJ2VyYVllYXInKTtcbiAgICBhZGRGb3JtYXRUb2tlbigneScsIFsneXknLCAyXSwgMCwgJ2VyYVllYXInKTtcbiAgICBhZGRGb3JtYXRUb2tlbigneScsIFsneXl5JywgM10sIDAsICdlcmFZZWFyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ3knLCBbJ3l5eXknLCA0XSwgMCwgJ2VyYVllYXInKTtcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ04nLCBtYXRjaEVyYUFiYnIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ05OJywgbWF0Y2hFcmFBYmJyKTtcbiAgICBhZGRSZWdleFRva2VuKCdOTk4nLCBtYXRjaEVyYUFiYnIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ05OTk4nLCBtYXRjaEVyYU5hbWUpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ05OTk5OJywgbWF0Y2hFcmFOYXJyb3cpO1xuXG4gICAgYWRkUGFyc2VUb2tlbihbJ04nLCAnTk4nLCAnTk5OJywgJ05OTk4nLCAnTk5OTk4nXSwgZnVuY3Rpb24gKFxuICAgICAgICBpbnB1dCxcbiAgICAgICAgYXJyYXksXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgdG9rZW5cbiAgICApIHtcbiAgICAgICAgdmFyIGVyYSA9IGNvbmZpZy5fbG9jYWxlLmVyYXNQYXJzZShpbnB1dCwgdG9rZW4sIGNvbmZpZy5fc3RyaWN0KTtcbiAgICAgICAgaWYgKGVyYSkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuZXJhID0gZXJhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZEVyYSA9IGlucHV0O1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBhZGRSZWdleFRva2VuKCd5JywgbWF0Y2hVbnNpZ25lZCk7XG4gICAgYWRkUmVnZXhUb2tlbigneXknLCBtYXRjaFVuc2lnbmVkKTtcbiAgICBhZGRSZWdleFRva2VuKCd5eXknLCBtYXRjaFVuc2lnbmVkKTtcbiAgICBhZGRSZWdleFRva2VuKCd5eXl5JywgbWF0Y2hVbnNpZ25lZCk7XG4gICAgYWRkUmVnZXhUb2tlbigneW8nLCBtYXRjaEVyYVllYXJPcmRpbmFsKTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWyd5JywgJ3l5JywgJ3l5eScsICd5eXl5J10sIFlFQVIpO1xuICAgIGFkZFBhcnNlVG9rZW4oWyd5byddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcsIHRva2VuKSB7XG4gICAgICAgIHZhciBtYXRjaDtcbiAgICAgICAgaWYgKGNvbmZpZy5fbG9jYWxlLl9lcmFZZWFyT3JkaW5hbFJlZ2V4KSB7XG4gICAgICAgICAgICBtYXRjaCA9IGlucHV0Lm1hdGNoKGNvbmZpZy5fbG9jYWxlLl9lcmFZZWFyT3JkaW5hbFJlZ2V4KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb25maWcuX2xvY2FsZS5lcmFZZWFyT3JkaW5hbFBhcnNlKSB7XG4gICAgICAgICAgICBhcnJheVtZRUFSXSA9IGNvbmZpZy5fbG9jYWxlLmVyYVllYXJPcmRpbmFsUGFyc2UoaW5wdXQsIG1hdGNoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFycmF5W1lFQVJdID0gcGFyc2VJbnQoaW5wdXQsIDEwKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gbG9jYWxlRXJhcyhtLCBmb3JtYXQpIHtcbiAgICAgICAgdmFyIGksXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgZGF0ZSxcbiAgICAgICAgICAgIGVyYXMgPSB0aGlzLl9lcmFzIHx8IGdldExvY2FsZSgnZW4nKS5fZXJhcztcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGVyYXMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHR5cGVvZiBlcmFzW2ldLnNpbmNlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgICAgICAgICAgICAgLy8gdHJ1bmNhdGUgdGltZVxuICAgICAgICAgICAgICAgICAgICBkYXRlID0gaG9va3MoZXJhc1tpXS5zaW5jZSkuc3RhcnRPZignZGF5Jyk7XG4gICAgICAgICAgICAgICAgICAgIGVyYXNbaV0uc2luY2UgPSBkYXRlLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN3aXRjaCAodHlwZW9mIGVyYXNbaV0udW50aWwpIHtcbiAgICAgICAgICAgICAgICBjYXNlICd1bmRlZmluZWQnOlxuICAgICAgICAgICAgICAgICAgICBlcmFzW2ldLnVudGlsID0gK0luZmluaXR5O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgICAgICAgICAgICAgICAvLyB0cnVuY2F0ZSB0aW1lXG4gICAgICAgICAgICAgICAgICAgIGRhdGUgPSBob29rcyhlcmFzW2ldLnVudGlsKS5zdGFydE9mKCdkYXknKS52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgICAgIGVyYXNbaV0udW50aWwgPSBkYXRlLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVyYXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9jYWxlRXJhc1BhcnNlKGVyYU5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgbCxcbiAgICAgICAgICAgIGVyYXMgPSB0aGlzLmVyYXMoKSxcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBhYmJyLFxuICAgICAgICAgICAgbmFycm93O1xuICAgICAgICBlcmFOYW1lID0gZXJhTmFtZS50b1VwcGVyQ2FzZSgpO1xuXG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBlcmFzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgbmFtZSA9IGVyYXNbaV0ubmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgYWJiciA9IGVyYXNbaV0uYWJici50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgbmFycm93ID0gZXJhc1tpXS5uYXJyb3cudG9VcHBlckNhc2UoKTtcblxuICAgICAgICAgICAgaWYgKHN0cmljdCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ04nOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdOTic6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ05OTic6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWJiciA9PT0gZXJhTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlcmFzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnTk5OTic6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobmFtZSA9PT0gZXJhTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlcmFzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnTk5OTk4nOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hcnJvdyA9PT0gZXJhTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlcmFzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChbbmFtZSwgYWJiciwgbmFycm93XS5pbmRleE9mKGVyYU5hbWUpID49IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXJhc1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvY2FsZUVyYXNDb252ZXJ0WWVhcihlcmEsIHllYXIpIHtcbiAgICAgICAgdmFyIGRpciA9IGVyYS5zaW5jZSA8PSBlcmEudW50aWwgPyArMSA6IC0xO1xuICAgICAgICBpZiAoeWVhciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gaG9va3MoZXJhLnNpbmNlKS55ZWFyKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaG9va3MoZXJhLnNpbmNlKS55ZWFyKCkgKyAoeWVhciAtIGVyYS5vZmZzZXQpICogZGlyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0RXJhTmFtZSgpIHtcbiAgICAgICAgdmFyIGksXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgdmFsLFxuICAgICAgICAgICAgZXJhcyA9IHRoaXMubG9jYWxlRGF0YSgpLmVyYXMoKTtcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGVyYXMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAvLyB0cnVuY2F0ZSB0aW1lXG4gICAgICAgICAgICB2YWwgPSB0aGlzLmNsb25lKCkuc3RhcnRPZignZGF5JykudmFsdWVPZigpO1xuXG4gICAgICAgICAgICBpZiAoZXJhc1tpXS5zaW5jZSA8PSB2YWwgJiYgdmFsIDw9IGVyYXNbaV0udW50aWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXJhc1tpXS5uYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVyYXNbaV0udW50aWwgPD0gdmFsICYmIHZhbCA8PSBlcmFzW2ldLnNpbmNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVyYXNbaV0ubmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRFcmFOYXJyb3coKSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgbCxcbiAgICAgICAgICAgIHZhbCxcbiAgICAgICAgICAgIGVyYXMgPSB0aGlzLmxvY2FsZURhdGEoKS5lcmFzKCk7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBlcmFzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgLy8gdHJ1bmNhdGUgdGltZVxuICAgICAgICAgICAgdmFsID0gdGhpcy5jbG9uZSgpLnN0YXJ0T2YoJ2RheScpLnZhbHVlT2YoKTtcblxuICAgICAgICAgICAgaWYgKGVyYXNbaV0uc2luY2UgPD0gdmFsICYmIHZhbCA8PSBlcmFzW2ldLnVudGlsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVyYXNbaV0ubmFycm93O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVyYXNbaV0udW50aWwgPD0gdmFsICYmIHZhbCA8PSBlcmFzW2ldLnNpbmNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVyYXNbaV0ubmFycm93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEVyYUFiYnIoKSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgbCxcbiAgICAgICAgICAgIHZhbCxcbiAgICAgICAgICAgIGVyYXMgPSB0aGlzLmxvY2FsZURhdGEoKS5lcmFzKCk7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBlcmFzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgLy8gdHJ1bmNhdGUgdGltZVxuICAgICAgICAgICAgdmFsID0gdGhpcy5jbG9uZSgpLnN0YXJ0T2YoJ2RheScpLnZhbHVlT2YoKTtcblxuICAgICAgICAgICAgaWYgKGVyYXNbaV0uc2luY2UgPD0gdmFsICYmIHZhbCA8PSBlcmFzW2ldLnVudGlsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVyYXNbaV0uYWJicjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlcmFzW2ldLnVudGlsIDw9IHZhbCAmJiB2YWwgPD0gZXJhc1tpXS5zaW5jZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlcmFzW2ldLmFiYnI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0RXJhWWVhcigpIHtcbiAgICAgICAgdmFyIGksXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgZGlyLFxuICAgICAgICAgICAgdmFsLFxuICAgICAgICAgICAgZXJhcyA9IHRoaXMubG9jYWxlRGF0YSgpLmVyYXMoKTtcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGVyYXMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBkaXIgPSBlcmFzW2ldLnNpbmNlIDw9IGVyYXNbaV0udW50aWwgPyArMSA6IC0xO1xuXG4gICAgICAgICAgICAvLyB0cnVuY2F0ZSB0aW1lXG4gICAgICAgICAgICB2YWwgPSB0aGlzLmNsb25lKCkuc3RhcnRPZignZGF5JykudmFsdWVPZigpO1xuXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgKGVyYXNbaV0uc2luY2UgPD0gdmFsICYmIHZhbCA8PSBlcmFzW2ldLnVudGlsKSB8fFxuICAgICAgICAgICAgICAgIChlcmFzW2ldLnVudGlsIDw9IHZhbCAmJiB2YWwgPD0gZXJhc1tpXS5zaW5jZSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLnllYXIoKSAtIGhvb2tzKGVyYXNbaV0uc2luY2UpLnllYXIoKSkgKiBkaXIgK1xuICAgICAgICAgICAgICAgICAgICBlcmFzW2ldLm9mZnNldFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy55ZWFyKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXJhc05hbWVSZWdleChpc1N0cmljdCkge1xuICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19lcmFzTmFtZVJlZ2V4JykpIHtcbiAgICAgICAgICAgIGNvbXB1dGVFcmFzUGFyc2UuY2FsbCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNTdHJpY3QgPyB0aGlzLl9lcmFzTmFtZVJlZ2V4IDogdGhpcy5fZXJhc1JlZ2V4O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVyYXNBYmJyUmVnZXgoaXNTdHJpY3QpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfZXJhc0FiYnJSZWdleCcpKSB7XG4gICAgICAgICAgICBjb21wdXRlRXJhc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzU3RyaWN0ID8gdGhpcy5fZXJhc0FiYnJSZWdleCA6IHRoaXMuX2VyYXNSZWdleDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlcmFzTmFycm93UmVnZXgoaXNTdHJpY3QpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfZXJhc05hcnJvd1JlZ2V4JykpIHtcbiAgICAgICAgICAgIGNvbXB1dGVFcmFzUGFyc2UuY2FsbCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNTdHJpY3QgPyB0aGlzLl9lcmFzTmFycm93UmVnZXggOiB0aGlzLl9lcmFzUmVnZXg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWF0Y2hFcmFBYmJyKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS5lcmFzQWJiclJlZ2V4KGlzU3RyaWN0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYXRjaEVyYU5hbWUoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLmVyYXNOYW1lUmVnZXgoaXNTdHJpY3QpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1hdGNoRXJhTmFycm93KGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS5lcmFzTmFycm93UmVnZXgoaXNTdHJpY3QpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1hdGNoRXJhWWVhck9yZGluYWwoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLl9lcmFZZWFyT3JkaW5hbFJlZ2V4IHx8IG1hdGNoVW5zaWduZWQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZUVyYXNQYXJzZSgpIHtcbiAgICAgICAgdmFyIGFiYnJQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIG5hbWVQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIG5hcnJvd1BpZWNlcyA9IFtdLFxuICAgICAgICAgICAgbWl4ZWRQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgZXJhcyA9IHRoaXMuZXJhcygpO1xuXG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBlcmFzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgbmFtZVBpZWNlcy5wdXNoKHJlZ2V4RXNjYXBlKGVyYXNbaV0ubmFtZSkpO1xuICAgICAgICAgICAgYWJiclBpZWNlcy5wdXNoKHJlZ2V4RXNjYXBlKGVyYXNbaV0uYWJicikpO1xuICAgICAgICAgICAgbmFycm93UGllY2VzLnB1c2gocmVnZXhFc2NhcGUoZXJhc1tpXS5uYXJyb3cpKTtcblxuICAgICAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChyZWdleEVzY2FwZShlcmFzW2ldLm5hbWUpKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2gocmVnZXhFc2NhcGUoZXJhc1tpXS5hYmJyKSk7XG4gICAgICAgICAgICBtaXhlZFBpZWNlcy5wdXNoKHJlZ2V4RXNjYXBlKGVyYXNbaV0ubmFycm93KSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9lcmFzUmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBtaXhlZFBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgICAgIHRoaXMuX2VyYXNOYW1lUmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBuYW1lUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICAgICAgdGhpcy5fZXJhc0FiYnJSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIGFiYnJQaWVjZXMuam9pbignfCcpICsgJyknLCAnaScpO1xuICAgICAgICB0aGlzLl9lcmFzTmFycm93UmVnZXggPSBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgJ14oJyArIG5hcnJvd1BpZWNlcy5qb2luKCd8JykgKyAnKScsXG4gICAgICAgICAgICAnaSdcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ2dnJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2Vla1llYXIoKSAlIDEwMDtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnR0cnLCAyXSwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc29XZWVrWWVhcigpICUgMTAwO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gYWRkV2Vla1llYXJGb3JtYXRUb2tlbih0b2tlbiwgZ2V0dGVyKSB7XG4gICAgICAgIGFkZEZvcm1hdFRva2VuKDAsIFt0b2tlbiwgdG9rZW4ubGVuZ3RoXSwgMCwgZ2V0dGVyKTtcbiAgICB9XG5cbiAgICBhZGRXZWVrWWVhckZvcm1hdFRva2VuKCdnZ2dnJywgJ3dlZWtZZWFyJyk7XG4gICAgYWRkV2Vla1llYXJGb3JtYXRUb2tlbignZ2dnZ2cnLCAnd2Vla1llYXInKTtcbiAgICBhZGRXZWVrWWVhckZvcm1hdFRva2VuKCdHR0dHJywgJ2lzb1dlZWtZZWFyJyk7XG4gICAgYWRkV2Vla1llYXJGb3JtYXRUb2tlbignR0dHR0cnLCAnaXNvV2Vla1llYXInKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnd2Vla1llYXInLCAnZ2cnKTtcbiAgICBhZGRVbml0QWxpYXMoJ2lzb1dlZWtZZWFyJywgJ0dHJyk7XG5cbiAgICAvLyBQUklPUklUWVxuXG4gICAgYWRkVW5pdFByaW9yaXR5KCd3ZWVrWWVhcicsIDEpO1xuICAgIGFkZFVuaXRQcmlvcml0eSgnaXNvV2Vla1llYXInLCAxKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ0cnLCBtYXRjaFNpZ25lZCk7XG4gICAgYWRkUmVnZXhUb2tlbignZycsIG1hdGNoU2lnbmVkKTtcbiAgICBhZGRSZWdleFRva2VuKCdHRycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbiAgICBhZGRSZWdleFRva2VuKCdnZycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbiAgICBhZGRSZWdleFRva2VuKCdHR0dHJywgbWF0Y2gxdG80LCBtYXRjaDQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2dnZ2cnLCBtYXRjaDF0bzQsIG1hdGNoNCk7XG4gICAgYWRkUmVnZXhUb2tlbignR0dHR0cnLCBtYXRjaDF0bzYsIG1hdGNoNik7XG4gICAgYWRkUmVnZXhUb2tlbignZ2dnZ2cnLCBtYXRjaDF0bzYsIG1hdGNoNik7XG5cbiAgICBhZGRXZWVrUGFyc2VUb2tlbihbJ2dnZ2cnLCAnZ2dnZ2cnLCAnR0dHRycsICdHR0dHRyddLCBmdW5jdGlvbiAoXG4gICAgICAgIGlucHV0LFxuICAgICAgICB3ZWVrLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIHRva2VuXG4gICAgKSB7XG4gICAgICAgIHdlZWtbdG9rZW4uc3Vic3RyKDAsIDIpXSA9IHRvSW50KGlucHV0KTtcbiAgICB9KTtcblxuICAgIGFkZFdlZWtQYXJzZVRva2VuKFsnZ2cnLCAnR0cnXSwgZnVuY3Rpb24gKGlucHV0LCB3ZWVrLCBjb25maWcsIHRva2VuKSB7XG4gICAgICAgIHdlZWtbdG9rZW5dID0gaG9va3MucGFyc2VUd29EaWdpdFllYXIoaW5wdXQpO1xuICAgIH0pO1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gZ2V0U2V0V2Vla1llYXIoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGdldFNldFdlZWtZZWFySGVscGVyLmNhbGwoXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgaW5wdXQsXG4gICAgICAgICAgICB0aGlzLndlZWsoKSxcbiAgICAgICAgICAgIHRoaXMud2Vla2RheSgpLFxuICAgICAgICAgICAgdGhpcy5sb2NhbGVEYXRhKCkuX3dlZWsuZG93LFxuICAgICAgICAgICAgdGhpcy5sb2NhbGVEYXRhKCkuX3dlZWsuZG95XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0SVNPV2Vla1llYXIoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGdldFNldFdlZWtZZWFySGVscGVyLmNhbGwoXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgaW5wdXQsXG4gICAgICAgICAgICB0aGlzLmlzb1dlZWsoKSxcbiAgICAgICAgICAgIHRoaXMuaXNvV2Vla2RheSgpLFxuICAgICAgICAgICAgMSxcbiAgICAgICAgICAgIDRcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRJU09XZWVrc0luWWVhcigpIHtcbiAgICAgICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMueWVhcigpLCAxLCA0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRJU09XZWVrc0luSVNPV2Vla1llYXIoKSB7XG4gICAgICAgIHJldHVybiB3ZWVrc0luWWVhcih0aGlzLmlzb1dlZWtZZWFyKCksIDEsIDQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFdlZWtzSW5ZZWFyKCkge1xuICAgICAgICB2YXIgd2Vla0luZm8gPSB0aGlzLmxvY2FsZURhdGEoKS5fd2VlaztcbiAgICAgICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMueWVhcigpLCB3ZWVrSW5mby5kb3csIHdlZWtJbmZvLmRveSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0V2Vla3NJbldlZWtZZWFyKCkge1xuICAgICAgICB2YXIgd2Vla0luZm8gPSB0aGlzLmxvY2FsZURhdGEoKS5fd2VlaztcbiAgICAgICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMud2Vla1llYXIoKSwgd2Vla0luZm8uZG93LCB3ZWVrSW5mby5kb3kpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFNldFdlZWtZZWFySGVscGVyKGlucHV0LCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgICAgICB2YXIgd2Vla3NUYXJnZXQ7XG4gICAgICAgIGlmIChpbnB1dCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gd2Vla09mWWVhcih0aGlzLCBkb3csIGRveSkueWVhcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdlZWtzVGFyZ2V0ID0gd2Vla3NJblllYXIoaW5wdXQsIGRvdywgZG95KTtcbiAgICAgICAgICAgIGlmICh3ZWVrID4gd2Vla3NUYXJnZXQpIHtcbiAgICAgICAgICAgICAgICB3ZWVrID0gd2Vla3NUYXJnZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc2V0V2Vla0FsbC5jYWxsKHRoaXMsIGlucHV0LCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRXZWVrQWxsKHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgICAgICB2YXIgZGF5T2ZZZWFyRGF0YSA9IGRheU9mWWVhckZyb21XZWVrcyh3ZWVrWWVhciwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpLFxuICAgICAgICAgICAgZGF0ZSA9IGNyZWF0ZVVUQ0RhdGUoZGF5T2ZZZWFyRGF0YS55ZWFyLCAwLCBkYXlPZlllYXJEYXRhLmRheU9mWWVhcik7XG5cbiAgICAgICAgdGhpcy55ZWFyKGRhdGUuZ2V0VVRDRnVsbFllYXIoKSk7XG4gICAgICAgIHRoaXMubW9udGgoZGF0ZS5nZXRVVENNb250aCgpKTtcbiAgICAgICAgdGhpcy5kYXRlKGRhdGUuZ2V0VVRDRGF0ZSgpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ1EnLCAwLCAnUW8nLCAncXVhcnRlcicpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCdxdWFydGVyJywgJ1EnKTtcblxuICAgIC8vIFBSSU9SSVRZXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ3F1YXJ0ZXInLCA3KTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ1EnLCBtYXRjaDEpO1xuICAgIGFkZFBhcnNlVG9rZW4oJ1EnLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgICAgIGFycmF5W01PTlRIXSA9ICh0b0ludChpbnB1dCkgLSAxKSAqIDM7XG4gICAgfSk7XG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICBmdW5jdGlvbiBnZXRTZXRRdWFydGVyKGlucHV0KSB7XG4gICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsXG4gICAgICAgICAgICA/IE1hdGguY2VpbCgodGhpcy5tb250aCgpICsgMSkgLyAzKVxuICAgICAgICAgICAgOiB0aGlzLm1vbnRoKChpbnB1dCAtIDEpICogMyArICh0aGlzLm1vbnRoKCkgJSAzKSk7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ0QnLCBbJ0REJywgMl0sICdEbycsICdkYXRlJyk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ2RhdGUnLCAnRCcpO1xuXG4gICAgLy8gUFJJT1JJVFlcbiAgICBhZGRVbml0UHJpb3JpdHkoJ2RhdGUnLCA5KTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ0QnLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0REJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0RvJywgZnVuY3Rpb24gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICAgICAgLy8gVE9ETzogUmVtb3ZlIFwib3JkaW5hbFBhcnNlXCIgZmFsbGJhY2sgaW4gbmV4dCBtYWpvciByZWxlYXNlLlxuICAgICAgICByZXR1cm4gaXNTdHJpY3RcbiAgICAgICAgICAgID8gbG9jYWxlLl9kYXlPZk1vbnRoT3JkaW5hbFBhcnNlIHx8IGxvY2FsZS5fb3JkaW5hbFBhcnNlXG4gICAgICAgICAgICA6IGxvY2FsZS5fZGF5T2ZNb250aE9yZGluYWxQYXJzZUxlbmllbnQ7XG4gICAgfSk7XG5cbiAgICBhZGRQYXJzZVRva2VuKFsnRCcsICdERCddLCBEQVRFKTtcbiAgICBhZGRQYXJzZVRva2VuKCdEbycsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgYXJyYXlbREFURV0gPSB0b0ludChpbnB1dC5tYXRjaChtYXRjaDF0bzIpWzBdKTtcbiAgICB9KTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIHZhciBnZXRTZXREYXlPZk1vbnRoID0gbWFrZUdldFNldCgnRGF0ZScsIHRydWUpO1xuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ0RERCcsIFsnRERERCcsIDNdLCAnREREbycsICdkYXlPZlllYXInKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnZGF5T2ZZZWFyJywgJ0RERCcpO1xuXG4gICAgLy8gUFJJT1JJVFlcbiAgICBhZGRVbml0UHJpb3JpdHkoJ2RheU9mWWVhcicsIDQpO1xuXG4gICAgLy8gUEFSU0lOR1xuXG4gICAgYWRkUmVnZXhUb2tlbignREREJywgbWF0Y2gxdG8zKTtcbiAgICBhZGRSZWdleFRva2VuKCdEREREJywgbWF0Y2gzKTtcbiAgICBhZGRQYXJzZVRva2VuKFsnREREJywgJ0REREQnXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZy5fZGF5T2ZZZWFyID0gdG9JbnQoaW5wdXQpO1xuICAgIH0pO1xuXG4gICAgLy8gSEVMUEVSU1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gZ2V0U2V0RGF5T2ZZZWFyKGlucHV0KSB7XG4gICAgICAgIHZhciBkYXlPZlllYXIgPVxuICAgICAgICAgICAgTWF0aC5yb3VuZChcbiAgICAgICAgICAgICAgICAodGhpcy5jbG9uZSgpLnN0YXJ0T2YoJ2RheScpIC0gdGhpcy5jbG9uZSgpLnN0YXJ0T2YoJ3llYXInKSkgLyA4NjRlNVxuICAgICAgICAgICAgKSArIDE7XG4gICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gZGF5T2ZZZWFyIDogdGhpcy5hZGQoaW5wdXQgLSBkYXlPZlllYXIsICdkJyk7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ20nLCBbJ21tJywgMl0sIDAsICdtaW51dGUnKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnbWludXRlJywgJ20nKTtcblxuICAgIC8vIFBSSU9SSVRZXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ21pbnV0ZScsIDE0KTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ20nLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ21tJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFBhcnNlVG9rZW4oWydtJywgJ21tJ10sIE1JTlVURSk7XG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICB2YXIgZ2V0U2V0TWludXRlID0gbWFrZUdldFNldCgnTWludXRlcycsIGZhbHNlKTtcblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdzJywgWydzcycsIDJdLCAwLCAnc2Vjb25kJyk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ3NlY29uZCcsICdzJyk7XG5cbiAgICAvLyBQUklPUklUWVxuXG4gICAgYWRkVW5pdFByaW9yaXR5KCdzZWNvbmQnLCAxNSk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdzJywgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdzcycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbiAgICBhZGRQYXJzZVRva2VuKFsncycsICdzcyddLCBTRUNPTkQpO1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgdmFyIGdldFNldFNlY29uZCA9IG1ha2VHZXRTZXQoJ1NlY29uZHMnLCBmYWxzZSk7XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbignUycsIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIH5+KHRoaXMubWlsbGlzZWNvbmQoKSAvIDEwMCk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIH5+KHRoaXMubWlsbGlzZWNvbmQoKSAvIDEwKTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTJywgM10sIDAsICdtaWxsaXNlY29uZCcpO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTUycsIDRdLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDtcbiAgICB9KTtcbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTU1NTJywgNV0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWlsbGlzZWNvbmQoKSAqIDEwMDtcbiAgICB9KTtcbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTU1NTUycsIDZdLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDAwO1xuICAgIH0pO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTUycsIDddLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDAwMDtcbiAgICB9KTtcbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTU1NTU1NTJywgOF0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWlsbGlzZWNvbmQoKSAqIDEwMDAwMDtcbiAgICB9KTtcbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTU1NTU1NTUycsIDldLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDAwMDAwO1xuICAgIH0pO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCdtaWxsaXNlY29uZCcsICdtcycpO1xuXG4gICAgLy8gUFJJT1JJVFlcblxuICAgIGFkZFVuaXRQcmlvcml0eSgnbWlsbGlzZWNvbmQnLCAxNik7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdTJywgbWF0Y2gxdG8zLCBtYXRjaDEpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1NTJywgbWF0Y2gxdG8zLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1NTUycsIG1hdGNoMXRvMywgbWF0Y2gzKTtcblxuICAgIHZhciB0b2tlbiwgZ2V0U2V0TWlsbGlzZWNvbmQ7XG4gICAgZm9yICh0b2tlbiA9ICdTU1NTJzsgdG9rZW4ubGVuZ3RoIDw9IDk7IHRva2VuICs9ICdTJykge1xuICAgICAgICBhZGRSZWdleFRva2VuKHRva2VuLCBtYXRjaFVuc2lnbmVkKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzZU1zKGlucHV0LCBhcnJheSkge1xuICAgICAgICBhcnJheVtNSUxMSVNFQ09ORF0gPSB0b0ludCgoJzAuJyArIGlucHV0KSAqIDEwMDApO1xuICAgIH1cblxuICAgIGZvciAodG9rZW4gPSAnUyc7IHRva2VuLmxlbmd0aCA8PSA5OyB0b2tlbiArPSAnUycpIHtcbiAgICAgICAgYWRkUGFyc2VUb2tlbih0b2tlbiwgcGFyc2VNcyk7XG4gICAgfVxuXG4gICAgZ2V0U2V0TWlsbGlzZWNvbmQgPSBtYWtlR2V0U2V0KCdNaWxsaXNlY29uZHMnLCBmYWxzZSk7XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbigneicsIDAsIDAsICd6b25lQWJicicpO1xuICAgIGFkZEZvcm1hdFRva2VuKCd6eicsIDAsIDAsICd6b25lTmFtZScpO1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gZ2V0Wm9uZUFiYnIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1VUQyA/ICdVVEMnIDogJyc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Wm9uZU5hbWUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1VUQyA/ICdDb29yZGluYXRlZCBVbml2ZXJzYWwgVGltZScgOiAnJztcbiAgICB9XG5cbiAgICB2YXIgcHJvdG8gPSBNb21lbnQucHJvdG90eXBlO1xuXG4gICAgcHJvdG8uYWRkID0gYWRkO1xuICAgIHByb3RvLmNhbGVuZGFyID0gY2FsZW5kYXIkMTtcbiAgICBwcm90by5jbG9uZSA9IGNsb25lO1xuICAgIHByb3RvLmRpZmYgPSBkaWZmO1xuICAgIHByb3RvLmVuZE9mID0gZW5kT2Y7XG4gICAgcHJvdG8uZm9ybWF0ID0gZm9ybWF0O1xuICAgIHByb3RvLmZyb20gPSBmcm9tO1xuICAgIHByb3RvLmZyb21Ob3cgPSBmcm9tTm93O1xuICAgIHByb3RvLnRvID0gdG87XG4gICAgcHJvdG8udG9Ob3cgPSB0b05vdztcbiAgICBwcm90by5nZXQgPSBzdHJpbmdHZXQ7XG4gICAgcHJvdG8uaW52YWxpZEF0ID0gaW52YWxpZEF0O1xuICAgIHByb3RvLmlzQWZ0ZXIgPSBpc0FmdGVyO1xuICAgIHByb3RvLmlzQmVmb3JlID0gaXNCZWZvcmU7XG4gICAgcHJvdG8uaXNCZXR3ZWVuID0gaXNCZXR3ZWVuO1xuICAgIHByb3RvLmlzU2FtZSA9IGlzU2FtZTtcbiAgICBwcm90by5pc1NhbWVPckFmdGVyID0gaXNTYW1lT3JBZnRlcjtcbiAgICBwcm90by5pc1NhbWVPckJlZm9yZSA9IGlzU2FtZU9yQmVmb3JlO1xuICAgIHByb3RvLmlzVmFsaWQgPSBpc1ZhbGlkJDI7XG4gICAgcHJvdG8ubGFuZyA9IGxhbmc7XG4gICAgcHJvdG8ubG9jYWxlID0gbG9jYWxlO1xuICAgIHByb3RvLmxvY2FsZURhdGEgPSBsb2NhbGVEYXRhO1xuICAgIHByb3RvLm1heCA9IHByb3RvdHlwZU1heDtcbiAgICBwcm90by5taW4gPSBwcm90b3R5cGVNaW47XG4gICAgcHJvdG8ucGFyc2luZ0ZsYWdzID0gcGFyc2luZ0ZsYWdzO1xuICAgIHByb3RvLnNldCA9IHN0cmluZ1NldDtcbiAgICBwcm90by5zdGFydE9mID0gc3RhcnRPZjtcbiAgICBwcm90by5zdWJ0cmFjdCA9IHN1YnRyYWN0O1xuICAgIHByb3RvLnRvQXJyYXkgPSB0b0FycmF5O1xuICAgIHByb3RvLnRvT2JqZWN0ID0gdG9PYmplY3Q7XG4gICAgcHJvdG8udG9EYXRlID0gdG9EYXRlO1xuICAgIHByb3RvLnRvSVNPU3RyaW5nID0gdG9JU09TdHJpbmc7XG4gICAgcHJvdG8uaW5zcGVjdCA9IGluc3BlY3Q7XG4gICAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC5mb3IgIT0gbnVsbCkge1xuICAgICAgICBwcm90b1tTeW1ib2wuZm9yKCdub2RlanMudXRpbC5pbnNwZWN0LmN1c3RvbScpXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnTW9tZW50PCcgKyB0aGlzLmZvcm1hdCgpICsgJz4nO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBwcm90by50b0pTT04gPSB0b0pTT047XG4gICAgcHJvdG8udG9TdHJpbmcgPSB0b1N0cmluZztcbiAgICBwcm90by51bml4ID0gdW5peDtcbiAgICBwcm90by52YWx1ZU9mID0gdmFsdWVPZjtcbiAgICBwcm90by5jcmVhdGlvbkRhdGEgPSBjcmVhdGlvbkRhdGE7XG4gICAgcHJvdG8uZXJhTmFtZSA9IGdldEVyYU5hbWU7XG4gICAgcHJvdG8uZXJhTmFycm93ID0gZ2V0RXJhTmFycm93O1xuICAgIHByb3RvLmVyYUFiYnIgPSBnZXRFcmFBYmJyO1xuICAgIHByb3RvLmVyYVllYXIgPSBnZXRFcmFZZWFyO1xuICAgIHByb3RvLnllYXIgPSBnZXRTZXRZZWFyO1xuICAgIHByb3RvLmlzTGVhcFllYXIgPSBnZXRJc0xlYXBZZWFyO1xuICAgIHByb3RvLndlZWtZZWFyID0gZ2V0U2V0V2Vla1llYXI7XG4gICAgcHJvdG8uaXNvV2Vla1llYXIgPSBnZXRTZXRJU09XZWVrWWVhcjtcbiAgICBwcm90by5xdWFydGVyID0gcHJvdG8ucXVhcnRlcnMgPSBnZXRTZXRRdWFydGVyO1xuICAgIHByb3RvLm1vbnRoID0gZ2V0U2V0TW9udGg7XG4gICAgcHJvdG8uZGF5c0luTW9udGggPSBnZXREYXlzSW5Nb250aDtcbiAgICBwcm90by53ZWVrID0gcHJvdG8ud2Vla3MgPSBnZXRTZXRXZWVrO1xuICAgIHByb3RvLmlzb1dlZWsgPSBwcm90by5pc29XZWVrcyA9IGdldFNldElTT1dlZWs7XG4gICAgcHJvdG8ud2Vla3NJblllYXIgPSBnZXRXZWVrc0luWWVhcjtcbiAgICBwcm90by53ZWVrc0luV2Vla1llYXIgPSBnZXRXZWVrc0luV2Vla1llYXI7XG4gICAgcHJvdG8uaXNvV2Vla3NJblllYXIgPSBnZXRJU09XZWVrc0luWWVhcjtcbiAgICBwcm90by5pc29XZWVrc0luSVNPV2Vla1llYXIgPSBnZXRJU09XZWVrc0luSVNPV2Vla1llYXI7XG4gICAgcHJvdG8uZGF0ZSA9IGdldFNldERheU9mTW9udGg7XG4gICAgcHJvdG8uZGF5ID0gcHJvdG8uZGF5cyA9IGdldFNldERheU9mV2VlaztcbiAgICBwcm90by53ZWVrZGF5ID0gZ2V0U2V0TG9jYWxlRGF5T2ZXZWVrO1xuICAgIHByb3RvLmlzb1dlZWtkYXkgPSBnZXRTZXRJU09EYXlPZldlZWs7XG4gICAgcHJvdG8uZGF5T2ZZZWFyID0gZ2V0U2V0RGF5T2ZZZWFyO1xuICAgIHByb3RvLmhvdXIgPSBwcm90by5ob3VycyA9IGdldFNldEhvdXI7XG4gICAgcHJvdG8ubWludXRlID0gcHJvdG8ubWludXRlcyA9IGdldFNldE1pbnV0ZTtcbiAgICBwcm90by5zZWNvbmQgPSBwcm90by5zZWNvbmRzID0gZ2V0U2V0U2Vjb25kO1xuICAgIHByb3RvLm1pbGxpc2Vjb25kID0gcHJvdG8ubWlsbGlzZWNvbmRzID0gZ2V0U2V0TWlsbGlzZWNvbmQ7XG4gICAgcHJvdG8udXRjT2Zmc2V0ID0gZ2V0U2V0T2Zmc2V0O1xuICAgIHByb3RvLnV0YyA9IHNldE9mZnNldFRvVVRDO1xuICAgIHByb3RvLmxvY2FsID0gc2V0T2Zmc2V0VG9Mb2NhbDtcbiAgICBwcm90by5wYXJzZVpvbmUgPSBzZXRPZmZzZXRUb1BhcnNlZE9mZnNldDtcbiAgICBwcm90by5oYXNBbGlnbmVkSG91ck9mZnNldCA9IGhhc0FsaWduZWRIb3VyT2Zmc2V0O1xuICAgIHByb3RvLmlzRFNUID0gaXNEYXlsaWdodFNhdmluZ1RpbWU7XG4gICAgcHJvdG8uaXNMb2NhbCA9IGlzTG9jYWw7XG4gICAgcHJvdG8uaXNVdGNPZmZzZXQgPSBpc1V0Y09mZnNldDtcbiAgICBwcm90by5pc1V0YyA9IGlzVXRjO1xuICAgIHByb3RvLmlzVVRDID0gaXNVdGM7XG4gICAgcHJvdG8uem9uZUFiYnIgPSBnZXRab25lQWJicjtcbiAgICBwcm90by56b25lTmFtZSA9IGdldFpvbmVOYW1lO1xuICAgIHByb3RvLmRhdGVzID0gZGVwcmVjYXRlKFxuICAgICAgICAnZGF0ZXMgYWNjZXNzb3IgaXMgZGVwcmVjYXRlZC4gVXNlIGRhdGUgaW5zdGVhZC4nLFxuICAgICAgICBnZXRTZXREYXlPZk1vbnRoXG4gICAgKTtcbiAgICBwcm90by5tb250aHMgPSBkZXByZWNhdGUoXG4gICAgICAgICdtb250aHMgYWNjZXNzb3IgaXMgZGVwcmVjYXRlZC4gVXNlIG1vbnRoIGluc3RlYWQnLFxuICAgICAgICBnZXRTZXRNb250aFxuICAgICk7XG4gICAgcHJvdG8ueWVhcnMgPSBkZXByZWNhdGUoXG4gICAgICAgICd5ZWFycyBhY2Nlc3NvciBpcyBkZXByZWNhdGVkLiBVc2UgeWVhciBpbnN0ZWFkJyxcbiAgICAgICAgZ2V0U2V0WWVhclxuICAgICk7XG4gICAgcHJvdG8uem9uZSA9IGRlcHJlY2F0ZShcbiAgICAgICAgJ21vbWVudCgpLnpvbmUgaXMgZGVwcmVjYXRlZCwgdXNlIG1vbWVudCgpLnV0Y09mZnNldCBpbnN0ZWFkLiBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL3pvbmUvJyxcbiAgICAgICAgZ2V0U2V0Wm9uZVxuICAgICk7XG4gICAgcHJvdG8uaXNEU1RTaGlmdGVkID0gZGVwcmVjYXRlKFxuICAgICAgICAnaXNEU1RTaGlmdGVkIGlzIGRlcHJlY2F0ZWQuIFNlZSBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL2RzdC1zaGlmdGVkLyBmb3IgbW9yZSBpbmZvcm1hdGlvbicsXG4gICAgICAgIGlzRGF5bGlnaHRTYXZpbmdUaW1lU2hpZnRlZFxuICAgICk7XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVVbml4KGlucHV0KSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVMb2NhbChpbnB1dCAqIDEwMDApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUluWm9uZSgpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsLmFwcGx5KG51bGwsIGFyZ3VtZW50cykucGFyc2Vab25lKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJlUGFyc2VQb3N0Rm9ybWF0KHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgIH1cblxuICAgIHZhciBwcm90byQxID0gTG9jYWxlLnByb3RvdHlwZTtcblxuICAgIHByb3RvJDEuY2FsZW5kYXIgPSBjYWxlbmRhcjtcbiAgICBwcm90byQxLmxvbmdEYXRlRm9ybWF0ID0gbG9uZ0RhdGVGb3JtYXQ7XG4gICAgcHJvdG8kMS5pbnZhbGlkRGF0ZSA9IGludmFsaWREYXRlO1xuICAgIHByb3RvJDEub3JkaW5hbCA9IG9yZGluYWw7XG4gICAgcHJvdG8kMS5wcmVwYXJzZSA9IHByZVBhcnNlUG9zdEZvcm1hdDtcbiAgICBwcm90byQxLnBvc3Rmb3JtYXQgPSBwcmVQYXJzZVBvc3RGb3JtYXQ7XG4gICAgcHJvdG8kMS5yZWxhdGl2ZVRpbWUgPSByZWxhdGl2ZVRpbWU7XG4gICAgcHJvdG8kMS5wYXN0RnV0dXJlID0gcGFzdEZ1dHVyZTtcbiAgICBwcm90byQxLnNldCA9IHNldDtcbiAgICBwcm90byQxLmVyYXMgPSBsb2NhbGVFcmFzO1xuICAgIHByb3RvJDEuZXJhc1BhcnNlID0gbG9jYWxlRXJhc1BhcnNlO1xuICAgIHByb3RvJDEuZXJhc0NvbnZlcnRZZWFyID0gbG9jYWxlRXJhc0NvbnZlcnRZZWFyO1xuICAgIHByb3RvJDEuZXJhc0FiYnJSZWdleCA9IGVyYXNBYmJyUmVnZXg7XG4gICAgcHJvdG8kMS5lcmFzTmFtZVJlZ2V4ID0gZXJhc05hbWVSZWdleDtcbiAgICBwcm90byQxLmVyYXNOYXJyb3dSZWdleCA9IGVyYXNOYXJyb3dSZWdleDtcblxuICAgIHByb3RvJDEubW9udGhzID0gbG9jYWxlTW9udGhzO1xuICAgIHByb3RvJDEubW9udGhzU2hvcnQgPSBsb2NhbGVNb250aHNTaG9ydDtcbiAgICBwcm90byQxLm1vbnRoc1BhcnNlID0gbG9jYWxlTW9udGhzUGFyc2U7XG4gICAgcHJvdG8kMS5tb250aHNSZWdleCA9IG1vbnRoc1JlZ2V4O1xuICAgIHByb3RvJDEubW9udGhzU2hvcnRSZWdleCA9IG1vbnRoc1Nob3J0UmVnZXg7XG4gICAgcHJvdG8kMS53ZWVrID0gbG9jYWxlV2VlaztcbiAgICBwcm90byQxLmZpcnN0RGF5T2ZZZWFyID0gbG9jYWxlRmlyc3REYXlPZlllYXI7XG4gICAgcHJvdG8kMS5maXJzdERheU9mV2VlayA9IGxvY2FsZUZpcnN0RGF5T2ZXZWVrO1xuXG4gICAgcHJvdG8kMS53ZWVrZGF5cyA9IGxvY2FsZVdlZWtkYXlzO1xuICAgIHByb3RvJDEud2Vla2RheXNNaW4gPSBsb2NhbGVXZWVrZGF5c01pbjtcbiAgICBwcm90byQxLndlZWtkYXlzU2hvcnQgPSBsb2NhbGVXZWVrZGF5c1Nob3J0O1xuICAgIHByb3RvJDEud2Vla2RheXNQYXJzZSA9IGxvY2FsZVdlZWtkYXlzUGFyc2U7XG5cbiAgICBwcm90byQxLndlZWtkYXlzUmVnZXggPSB3ZWVrZGF5c1JlZ2V4O1xuICAgIHByb3RvJDEud2Vla2RheXNTaG9ydFJlZ2V4ID0gd2Vla2RheXNTaG9ydFJlZ2V4O1xuICAgIHByb3RvJDEud2Vla2RheXNNaW5SZWdleCA9IHdlZWtkYXlzTWluUmVnZXg7XG5cbiAgICBwcm90byQxLmlzUE0gPSBsb2NhbGVJc1BNO1xuICAgIHByb3RvJDEubWVyaWRpZW0gPSBsb2NhbGVNZXJpZGllbTtcblxuICAgIGZ1bmN0aW9uIGdldCQxKGZvcm1hdCwgaW5kZXgsIGZpZWxkLCBzZXR0ZXIpIHtcbiAgICAgICAgdmFyIGxvY2FsZSA9IGdldExvY2FsZSgpLFxuICAgICAgICAgICAgdXRjID0gY3JlYXRlVVRDKCkuc2V0KHNldHRlciwgaW5kZXgpO1xuICAgICAgICByZXR1cm4gbG9jYWxlW2ZpZWxkXSh1dGMsIGZvcm1hdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdE1vbnRoc0ltcGwoZm9ybWF0LCBpbmRleCwgZmllbGQpIHtcbiAgICAgICAgaWYgKGlzTnVtYmVyKGZvcm1hdCkpIHtcbiAgICAgICAgICAgIGluZGV4ID0gZm9ybWF0O1xuICAgICAgICAgICAgZm9ybWF0ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0IHx8ICcnO1xuXG4gICAgICAgIGlmIChpbmRleCAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0JDEoZm9ybWF0LCBpbmRleCwgZmllbGQsICdtb250aCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGksXG4gICAgICAgICAgICBvdXQgPSBbXTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgICAgIG91dFtpXSA9IGdldCQxKGZvcm1hdCwgaSwgZmllbGQsICdtb250aCcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuXG4gICAgLy8gKClcbiAgICAvLyAoNSlcbiAgICAvLyAoZm10LCA1KVxuICAgIC8vIChmbXQpXG4gICAgLy8gKHRydWUpXG4gICAgLy8gKHRydWUsIDUpXG4gICAgLy8gKHRydWUsIGZtdCwgNSlcbiAgICAvLyAodHJ1ZSwgZm10KVxuICAgIGZ1bmN0aW9uIGxpc3RXZWVrZGF5c0ltcGwobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4LCBmaWVsZCkge1xuICAgICAgICBpZiAodHlwZW9mIGxvY2FsZVNvcnRlZCA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICBpZiAoaXNOdW1iZXIoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gZm9ybWF0O1xuICAgICAgICAgICAgICAgIGZvcm1hdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9ybWF0ID0gZm9ybWF0IHx8ICcnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9ybWF0ID0gbG9jYWxlU29ydGVkO1xuICAgICAgICAgICAgaW5kZXggPSBmb3JtYXQ7XG4gICAgICAgICAgICBsb2NhbGVTb3J0ZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgaWYgKGlzTnVtYmVyKGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGZvcm1hdDtcbiAgICAgICAgICAgICAgICBmb3JtYXQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcm1hdCA9IGZvcm1hdCB8fCAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsb2NhbGUgPSBnZXRMb2NhbGUoKSxcbiAgICAgICAgICAgIHNoaWZ0ID0gbG9jYWxlU29ydGVkID8gbG9jYWxlLl93ZWVrLmRvdyA6IDAsXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgb3V0ID0gW107XG5cbiAgICAgICAgaWYgKGluZGV4ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBnZXQkMShmb3JtYXQsIChpbmRleCArIHNoaWZ0KSAlIDcsIGZpZWxkLCAnZGF5Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICBvdXRbaV0gPSBnZXQkMShmb3JtYXQsIChpICsgc2hpZnQpICUgNywgZmllbGQsICdkYXknKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpc3RNb250aHMoZm9ybWF0LCBpbmRleCkge1xuICAgICAgICByZXR1cm4gbGlzdE1vbnRoc0ltcGwoZm9ybWF0LCBpbmRleCwgJ21vbnRocycpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpc3RNb250aHNTaG9ydChmb3JtYXQsIGluZGV4KSB7XG4gICAgICAgIHJldHVybiBsaXN0TW9udGhzSW1wbChmb3JtYXQsIGluZGV4LCAnbW9udGhzU2hvcnQnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaXN0V2Vla2RheXMobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4KSB7XG4gICAgICAgIHJldHVybiBsaXN0V2Vla2RheXNJbXBsKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCwgJ3dlZWtkYXlzJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdFdlZWtkYXlzU2hvcnQobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4KSB7XG4gICAgICAgIHJldHVybiBsaXN0V2Vla2RheXNJbXBsKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCwgJ3dlZWtkYXlzU2hvcnQnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaXN0V2Vla2RheXNNaW4obG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4KSB7XG4gICAgICAgIHJldHVybiBsaXN0V2Vla2RheXNJbXBsKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCwgJ3dlZWtkYXlzTWluJyk7XG4gICAgfVxuXG4gICAgZ2V0U2V0R2xvYmFsTG9jYWxlKCdlbicsIHtcbiAgICAgICAgZXJhczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHNpbmNlOiAnMDAwMS0wMS0wMScsXG4gICAgICAgICAgICAgICAgdW50aWw6ICtJbmZpbml0eSxcbiAgICAgICAgICAgICAgICBvZmZzZXQ6IDEsXG4gICAgICAgICAgICAgICAgbmFtZTogJ0Fubm8gRG9taW5pJyxcbiAgICAgICAgICAgICAgICBuYXJyb3c6ICdBRCcsXG4gICAgICAgICAgICAgICAgYWJicjogJ0FEJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgc2luY2U6ICcwMDAwLTEyLTMxJyxcbiAgICAgICAgICAgICAgICB1bnRpbDogLUluZmluaXR5LFxuICAgICAgICAgICAgICAgIG9mZnNldDogMSxcbiAgICAgICAgICAgICAgICBuYW1lOiAnQmVmb3JlIENocmlzdCcsXG4gICAgICAgICAgICAgICAgbmFycm93OiAnQkMnLFxuICAgICAgICAgICAgICAgIGFiYnI6ICdCQycsXG4gICAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0odGh8c3R8bmR8cmQpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPVxuICAgICAgICAgICAgICAgICAgICB0b0ludCgobnVtYmVyICUgMTAwKSAvIDEwKSA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAndGgnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3N0J1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAyXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICduZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gM1xuICAgICAgICAgICAgICAgICAgICAgICAgPyAncmQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6ICd0aCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gU2lkZSBlZmZlY3QgaW1wb3J0c1xuXG4gICAgaG9va3MubGFuZyA9IGRlcHJlY2F0ZShcbiAgICAgICAgJ21vbWVudC5sYW5nIGlzIGRlcHJlY2F0ZWQuIFVzZSBtb21lbnQubG9jYWxlIGluc3RlYWQuJyxcbiAgICAgICAgZ2V0U2V0R2xvYmFsTG9jYWxlXG4gICAgKTtcbiAgICBob29rcy5sYW5nRGF0YSA9IGRlcHJlY2F0ZShcbiAgICAgICAgJ21vbWVudC5sYW5nRGF0YSBpcyBkZXByZWNhdGVkLiBVc2UgbW9tZW50LmxvY2FsZURhdGEgaW5zdGVhZC4nLFxuICAgICAgICBnZXRMb2NhbGVcbiAgICApO1xuXG4gICAgdmFyIG1hdGhBYnMgPSBNYXRoLmFicztcblxuICAgIGZ1bmN0aW9uIGFicygpIHtcbiAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9kYXRhO1xuXG4gICAgICAgIHRoaXMuX21pbGxpc2Vjb25kcyA9IG1hdGhBYnModGhpcy5fbWlsbGlzZWNvbmRzKTtcbiAgICAgICAgdGhpcy5fZGF5cyA9IG1hdGhBYnModGhpcy5fZGF5cyk7XG4gICAgICAgIHRoaXMuX21vbnRocyA9IG1hdGhBYnModGhpcy5fbW9udGhzKTtcblxuICAgICAgICBkYXRhLm1pbGxpc2Vjb25kcyA9IG1hdGhBYnMoZGF0YS5taWxsaXNlY29uZHMpO1xuICAgICAgICBkYXRhLnNlY29uZHMgPSBtYXRoQWJzKGRhdGEuc2Vjb25kcyk7XG4gICAgICAgIGRhdGEubWludXRlcyA9IG1hdGhBYnMoZGF0YS5taW51dGVzKTtcbiAgICAgICAgZGF0YS5ob3VycyA9IG1hdGhBYnMoZGF0YS5ob3Vycyk7XG4gICAgICAgIGRhdGEubW9udGhzID0gbWF0aEFicyhkYXRhLm1vbnRocyk7XG4gICAgICAgIGRhdGEueWVhcnMgPSBtYXRoQWJzKGRhdGEueWVhcnMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFN1YnRyYWN0JDEoZHVyYXRpb24sIGlucHV0LCB2YWx1ZSwgZGlyZWN0aW9uKSB7XG4gICAgICAgIHZhciBvdGhlciA9IGNyZWF0ZUR1cmF0aW9uKGlucHV0LCB2YWx1ZSk7XG5cbiAgICAgICAgZHVyYXRpb24uX21pbGxpc2Vjb25kcyArPSBkaXJlY3Rpb24gKiBvdGhlci5fbWlsbGlzZWNvbmRzO1xuICAgICAgICBkdXJhdGlvbi5fZGF5cyArPSBkaXJlY3Rpb24gKiBvdGhlci5fZGF5cztcbiAgICAgICAgZHVyYXRpb24uX21vbnRocyArPSBkaXJlY3Rpb24gKiBvdGhlci5fbW9udGhzO1xuXG4gICAgICAgIHJldHVybiBkdXJhdGlvbi5fYnViYmxlKCk7XG4gICAgfVxuXG4gICAgLy8gc3VwcG9ydHMgb25seSAyLjAtc3R5bGUgYWRkKDEsICdzJykgb3IgYWRkKGR1cmF0aW9uKVxuICAgIGZ1bmN0aW9uIGFkZCQxKGlucHV0LCB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gYWRkU3VidHJhY3QkMSh0aGlzLCBpbnB1dCwgdmFsdWUsIDEpO1xuICAgIH1cblxuICAgIC8vIHN1cHBvcnRzIG9ubHkgMi4wLXN0eWxlIHN1YnRyYWN0KDEsICdzJykgb3Igc3VidHJhY3QoZHVyYXRpb24pXG4gICAgZnVuY3Rpb24gc3VidHJhY3QkMShpbnB1dCwgdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGFkZFN1YnRyYWN0JDEodGhpcywgaW5wdXQsIHZhbHVlLCAtMSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWJzQ2VpbChudW1iZXIpIHtcbiAgICAgICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKG51bWJlcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKG51bWJlcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWJibGUoKSB7XG4gICAgICAgIHZhciBtaWxsaXNlY29uZHMgPSB0aGlzLl9taWxsaXNlY29uZHMsXG4gICAgICAgICAgICBkYXlzID0gdGhpcy5fZGF5cyxcbiAgICAgICAgICAgIG1vbnRocyA9IHRoaXMuX21vbnRocyxcbiAgICAgICAgICAgIGRhdGEgPSB0aGlzLl9kYXRhLFxuICAgICAgICAgICAgc2Vjb25kcyxcbiAgICAgICAgICAgIG1pbnV0ZXMsXG4gICAgICAgICAgICBob3VycyxcbiAgICAgICAgICAgIHllYXJzLFxuICAgICAgICAgICAgbW9udGhzRnJvbURheXM7XG5cbiAgICAgICAgLy8gaWYgd2UgaGF2ZSBhIG1peCBvZiBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWVzLCBidWJibGUgZG93biBmaXJzdFxuICAgICAgICAvLyBjaGVjazogaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzIxNjZcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgICAobWlsbGlzZWNvbmRzID49IDAgJiYgZGF5cyA+PSAwICYmIG1vbnRocyA+PSAwKSB8fFxuICAgICAgICAgICAgICAgIChtaWxsaXNlY29uZHMgPD0gMCAmJiBkYXlzIDw9IDAgJiYgbW9udGhzIDw9IDApXG4gICAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgICAgbWlsbGlzZWNvbmRzICs9IGFic0NlaWwobW9udGhzVG9EYXlzKG1vbnRocykgKyBkYXlzKSAqIDg2NGU1O1xuICAgICAgICAgICAgZGF5cyA9IDA7XG4gICAgICAgICAgICBtb250aHMgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhlIGZvbGxvd2luZyBjb2RlIGJ1YmJsZXMgdXAgdmFsdWVzLCBzZWUgdGhlIHRlc3RzIGZvclxuICAgICAgICAvLyBleGFtcGxlcyBvZiB3aGF0IHRoYXQgbWVhbnMuXG4gICAgICAgIGRhdGEubWlsbGlzZWNvbmRzID0gbWlsbGlzZWNvbmRzICUgMTAwMDtcblxuICAgICAgICBzZWNvbmRzID0gYWJzRmxvb3IobWlsbGlzZWNvbmRzIC8gMTAwMCk7XG4gICAgICAgIGRhdGEuc2Vjb25kcyA9IHNlY29uZHMgJSA2MDtcblxuICAgICAgICBtaW51dGVzID0gYWJzRmxvb3Ioc2Vjb25kcyAvIDYwKTtcbiAgICAgICAgZGF0YS5taW51dGVzID0gbWludXRlcyAlIDYwO1xuXG4gICAgICAgIGhvdXJzID0gYWJzRmxvb3IobWludXRlcyAvIDYwKTtcbiAgICAgICAgZGF0YS5ob3VycyA9IGhvdXJzICUgMjQ7XG5cbiAgICAgICAgZGF5cyArPSBhYnNGbG9vcihob3VycyAvIDI0KTtcblxuICAgICAgICAvLyBjb252ZXJ0IGRheXMgdG8gbW9udGhzXG4gICAgICAgIG1vbnRoc0Zyb21EYXlzID0gYWJzRmxvb3IoZGF5c1RvTW9udGhzKGRheXMpKTtcbiAgICAgICAgbW9udGhzICs9IG1vbnRoc0Zyb21EYXlzO1xuICAgICAgICBkYXlzIC09IGFic0NlaWwobW9udGhzVG9EYXlzKG1vbnRoc0Zyb21EYXlzKSk7XG5cbiAgICAgICAgLy8gMTIgbW9udGhzIC0+IDEgeWVhclxuICAgICAgICB5ZWFycyA9IGFic0Zsb29yKG1vbnRocyAvIDEyKTtcbiAgICAgICAgbW9udGhzICU9IDEyO1xuXG4gICAgICAgIGRhdGEuZGF5cyA9IGRheXM7XG4gICAgICAgIGRhdGEubW9udGhzID0gbW9udGhzO1xuICAgICAgICBkYXRhLnllYXJzID0geWVhcnM7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGF5c1RvTW9udGhzKGRheXMpIHtcbiAgICAgICAgLy8gNDAwIHllYXJzIGhhdmUgMTQ2MDk3IGRheXMgKHRha2luZyBpbnRvIGFjY291bnQgbGVhcCB5ZWFyIHJ1bGVzKVxuICAgICAgICAvLyA0MDAgeWVhcnMgaGF2ZSAxMiBtb250aHMgPT09IDQ4MDBcbiAgICAgICAgcmV0dXJuIChkYXlzICogNDgwMCkgLyAxNDYwOTc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbW9udGhzVG9EYXlzKG1vbnRocykge1xuICAgICAgICAvLyB0aGUgcmV2ZXJzZSBvZiBkYXlzVG9Nb250aHNcbiAgICAgICAgcmV0dXJuIChtb250aHMgKiAxNDYwOTcpIC8gNDgwMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcyh1bml0cykge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkYXlzLFxuICAgICAgICAgICAgbW9udGhzLFxuICAgICAgICAgICAgbWlsbGlzZWNvbmRzID0gdGhpcy5fbWlsbGlzZWNvbmRzO1xuXG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuXG4gICAgICAgIGlmICh1bml0cyA9PT0gJ21vbnRoJyB8fCB1bml0cyA9PT0gJ3F1YXJ0ZXInIHx8IHVuaXRzID09PSAneWVhcicpIHtcbiAgICAgICAgICAgIGRheXMgPSB0aGlzLl9kYXlzICsgbWlsbGlzZWNvbmRzIC8gODY0ZTU7XG4gICAgICAgICAgICBtb250aHMgPSB0aGlzLl9tb250aHMgKyBkYXlzVG9Nb250aHMoZGF5cyk7XG4gICAgICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnbW9udGgnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3F1YXJ0ZXInOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzIC8gMztcbiAgICAgICAgICAgICAgICBjYXNlICd5ZWFyJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRocyAvIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gaGFuZGxlIG1pbGxpc2Vjb25kcyBzZXBhcmF0ZWx5IGJlY2F1c2Ugb2YgZmxvYXRpbmcgcG9pbnQgbWF0aCBlcnJvcnMgKGlzc3VlICMxODY3KVxuICAgICAgICAgICAgZGF5cyA9IHRoaXMuX2RheXMgKyBNYXRoLnJvdW5kKG1vbnRoc1RvRGF5cyh0aGlzLl9tb250aHMpKTtcbiAgICAgICAgICAgIHN3aXRjaCAodW5pdHMpIHtcbiAgICAgICAgICAgICAgICBjYXNlICd3ZWVrJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRheXMgLyA3ICsgbWlsbGlzZWNvbmRzIC8gNjA0OGU1O1xuICAgICAgICAgICAgICAgIGNhc2UgJ2RheSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXlzICsgbWlsbGlzZWNvbmRzIC8gODY0ZTU7XG4gICAgICAgICAgICAgICAgY2FzZSAnaG91cic6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXlzICogMjQgKyBtaWxsaXNlY29uZHMgLyAzNmU1O1xuICAgICAgICAgICAgICAgIGNhc2UgJ21pbnV0ZSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXlzICogMTQ0MCArIG1pbGxpc2Vjb25kcyAvIDZlNDtcbiAgICAgICAgICAgICAgICBjYXNlICdzZWNvbmQnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF5cyAqIDg2NDAwICsgbWlsbGlzZWNvbmRzIC8gMTAwMDtcbiAgICAgICAgICAgICAgICAvLyBNYXRoLmZsb29yIHByZXZlbnRzIGZsb2F0aW5nIHBvaW50IG1hdGggZXJyb3JzIGhlcmVcbiAgICAgICAgICAgICAgICBjYXNlICdtaWxsaXNlY29uZCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKGRheXMgKiA4NjRlNSkgKyBtaWxsaXNlY29uZHM7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIHVuaXQgJyArIHVuaXRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE86IFVzZSB0aGlzLmFzKCdtcycpP1xuICAgIGZ1bmN0aW9uIHZhbHVlT2YkMSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdGhpcy5fbWlsbGlzZWNvbmRzICtcbiAgICAgICAgICAgIHRoaXMuX2RheXMgKiA4NjRlNSArXG4gICAgICAgICAgICAodGhpcy5fbW9udGhzICUgMTIpICogMjU5MmU2ICtcbiAgICAgICAgICAgIHRvSW50KHRoaXMuX21vbnRocyAvIDEyKSAqIDMxNTM2ZTZcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlQXMoYWxpYXMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFzKGFsaWFzKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgYXNNaWxsaXNlY29uZHMgPSBtYWtlQXMoJ21zJyksXG4gICAgICAgIGFzU2Vjb25kcyA9IG1ha2VBcygncycpLFxuICAgICAgICBhc01pbnV0ZXMgPSBtYWtlQXMoJ20nKSxcbiAgICAgICAgYXNIb3VycyA9IG1ha2VBcygnaCcpLFxuICAgICAgICBhc0RheXMgPSBtYWtlQXMoJ2QnKSxcbiAgICAgICAgYXNXZWVrcyA9IG1ha2VBcygndycpLFxuICAgICAgICBhc01vbnRocyA9IG1ha2VBcygnTScpLFxuICAgICAgICBhc1F1YXJ0ZXJzID0gbWFrZUFzKCdRJyksXG4gICAgICAgIGFzWWVhcnMgPSBtYWtlQXMoJ3knKTtcblxuICAgIGZ1bmN0aW9uIGNsb25lJDEoKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbih0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXQkMih1bml0cykge1xuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gdGhpc1t1bml0cyArICdzJ10oKSA6IE5hTjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlR2V0dGVyKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMuX2RhdGFbbmFtZV0gOiBOYU47XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIG1pbGxpc2Vjb25kcyA9IG1ha2VHZXR0ZXIoJ21pbGxpc2Vjb25kcycpLFxuICAgICAgICBzZWNvbmRzID0gbWFrZUdldHRlcignc2Vjb25kcycpLFxuICAgICAgICBtaW51dGVzID0gbWFrZUdldHRlcignbWludXRlcycpLFxuICAgICAgICBob3VycyA9IG1ha2VHZXR0ZXIoJ2hvdXJzJyksXG4gICAgICAgIGRheXMgPSBtYWtlR2V0dGVyKCdkYXlzJyksXG4gICAgICAgIG1vbnRocyA9IG1ha2VHZXR0ZXIoJ21vbnRocycpLFxuICAgICAgICB5ZWFycyA9IG1ha2VHZXR0ZXIoJ3llYXJzJyk7XG5cbiAgICBmdW5jdGlvbiB3ZWVrcygpIHtcbiAgICAgICAgcmV0dXJuIGFic0Zsb29yKHRoaXMuZGF5cygpIC8gNyk7XG4gICAgfVxuXG4gICAgdmFyIHJvdW5kID0gTWF0aC5yb3VuZCxcbiAgICAgICAgdGhyZXNob2xkcyA9IHtcbiAgICAgICAgICAgIHNzOiA0NCwgLy8gYSBmZXcgc2Vjb25kcyB0byBzZWNvbmRzXG4gICAgICAgICAgICBzOiA0NSwgLy8gc2Vjb25kcyB0byBtaW51dGVcbiAgICAgICAgICAgIG06IDQ1LCAvLyBtaW51dGVzIHRvIGhvdXJcbiAgICAgICAgICAgIGg6IDIyLCAvLyBob3VycyB0byBkYXlcbiAgICAgICAgICAgIGQ6IDI2LCAvLyBkYXlzIHRvIG1vbnRoL3dlZWtcbiAgICAgICAgICAgIHc6IG51bGwsIC8vIHdlZWtzIHRvIG1vbnRoXG4gICAgICAgICAgICBNOiAxMSwgLy8gbW9udGhzIHRvIHllYXJcbiAgICAgICAgfTtcblxuICAgIC8vIGhlbHBlciBmdW5jdGlvbiBmb3IgbW9tZW50LmZuLmZyb20sIG1vbWVudC5mbi5mcm9tTm93LCBhbmQgbW9tZW50LmR1cmF0aW9uLmZuLmh1bWFuaXplXG4gICAgZnVuY3Rpb24gc3Vic3RpdHV0ZVRpbWVBZ28oc3RyaW5nLCBudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGlzRnV0dXJlLCBsb2NhbGUpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS5yZWxhdGl2ZVRpbWUobnVtYmVyIHx8IDEsICEhd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lJDEocG9zTmVnRHVyYXRpb24sIHdpdGhvdXRTdWZmaXgsIHRocmVzaG9sZHMsIGxvY2FsZSkge1xuICAgICAgICB2YXIgZHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbihwb3NOZWdEdXJhdGlvbikuYWJzKCksXG4gICAgICAgICAgICBzZWNvbmRzID0gcm91bmQoZHVyYXRpb24uYXMoJ3MnKSksXG4gICAgICAgICAgICBtaW51dGVzID0gcm91bmQoZHVyYXRpb24uYXMoJ20nKSksXG4gICAgICAgICAgICBob3VycyA9IHJvdW5kKGR1cmF0aW9uLmFzKCdoJykpLFxuICAgICAgICAgICAgZGF5cyA9IHJvdW5kKGR1cmF0aW9uLmFzKCdkJykpLFxuICAgICAgICAgICAgbW9udGhzID0gcm91bmQoZHVyYXRpb24uYXMoJ00nKSksXG4gICAgICAgICAgICB3ZWVrcyA9IHJvdW5kKGR1cmF0aW9uLmFzKCd3JykpLFxuICAgICAgICAgICAgeWVhcnMgPSByb3VuZChkdXJhdGlvbi5hcygneScpKSxcbiAgICAgICAgICAgIGEgPVxuICAgICAgICAgICAgICAgIChzZWNvbmRzIDw9IHRocmVzaG9sZHMuc3MgJiYgWydzJywgc2Vjb25kc10pIHx8XG4gICAgICAgICAgICAgICAgKHNlY29uZHMgPCB0aHJlc2hvbGRzLnMgJiYgWydzcycsIHNlY29uZHNdKSB8fFxuICAgICAgICAgICAgICAgIChtaW51dGVzIDw9IDEgJiYgWydtJ10pIHx8XG4gICAgICAgICAgICAgICAgKG1pbnV0ZXMgPCB0aHJlc2hvbGRzLm0gJiYgWydtbScsIG1pbnV0ZXNdKSB8fFxuICAgICAgICAgICAgICAgIChob3VycyA8PSAxICYmIFsnaCddKSB8fFxuICAgICAgICAgICAgICAgIChob3VycyA8IHRocmVzaG9sZHMuaCAmJiBbJ2hoJywgaG91cnNdKSB8fFxuICAgICAgICAgICAgICAgIChkYXlzIDw9IDEgJiYgWydkJ10pIHx8XG4gICAgICAgICAgICAgICAgKGRheXMgPCB0aHJlc2hvbGRzLmQgJiYgWydkZCcsIGRheXNdKTtcblxuICAgICAgICBpZiAodGhyZXNob2xkcy53ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGEgPVxuICAgICAgICAgICAgICAgIGEgfHxcbiAgICAgICAgICAgICAgICAod2Vla3MgPD0gMSAmJiBbJ3cnXSkgfHxcbiAgICAgICAgICAgICAgICAod2Vla3MgPCB0aHJlc2hvbGRzLncgJiYgWyd3dycsIHdlZWtzXSk7XG4gICAgICAgIH1cbiAgICAgICAgYSA9IGEgfHxcbiAgICAgICAgICAgIChtb250aHMgPD0gMSAmJiBbJ00nXSkgfHxcbiAgICAgICAgICAgIChtb250aHMgPCB0aHJlc2hvbGRzLk0gJiYgWydNTScsIG1vbnRoc10pIHx8XG4gICAgICAgICAgICAoeWVhcnMgPD0gMSAmJiBbJ3knXSkgfHwgWyd5eScsIHllYXJzXTtcblxuICAgICAgICBhWzJdID0gd2l0aG91dFN1ZmZpeDtcbiAgICAgICAgYVszXSA9ICtwb3NOZWdEdXJhdGlvbiA+IDA7XG4gICAgICAgIGFbNF0gPSBsb2NhbGU7XG4gICAgICAgIHJldHVybiBzdWJzdGl0dXRlVGltZUFnby5hcHBseShudWxsLCBhKTtcbiAgICB9XG5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gc2V0IHRoZSByb3VuZGluZyBmdW5jdGlvbiBmb3IgcmVsYXRpdmUgdGltZSBzdHJpbmdzXG4gICAgZnVuY3Rpb24gZ2V0U2V0UmVsYXRpdmVUaW1lUm91bmRpbmcocm91bmRpbmdGdW5jdGlvbikge1xuICAgICAgICBpZiAocm91bmRpbmdGdW5jdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gcm91bmQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiByb3VuZGluZ0Z1bmN0aW9uID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByb3VuZCA9IHJvdW5kaW5nRnVuY3Rpb247XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBhbGxvd3MgeW91IHRvIHNldCBhIHRocmVzaG9sZCBmb3IgcmVsYXRpdmUgdGltZSBzdHJpbmdzXG4gICAgZnVuY3Rpb24gZ2V0U2V0UmVsYXRpdmVUaW1lVGhyZXNob2xkKHRocmVzaG9sZCwgbGltaXQpIHtcbiAgICAgICAgaWYgKHRocmVzaG9sZHNbdGhyZXNob2xkXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxpbWl0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aHJlc2hvbGRzW3RocmVzaG9sZF07XG4gICAgICAgIH1cbiAgICAgICAgdGhyZXNob2xkc1t0aHJlc2hvbGRdID0gbGltaXQ7XG4gICAgICAgIGlmICh0aHJlc2hvbGQgPT09ICdzJykge1xuICAgICAgICAgICAgdGhyZXNob2xkcy5zcyA9IGxpbWl0IC0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBodW1hbml6ZShhcmdXaXRoU3VmZml4LCBhcmdUaHJlc2hvbGRzKSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5pbnZhbGlkRGF0ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHdpdGhTdWZmaXggPSBmYWxzZSxcbiAgICAgICAgICAgIHRoID0gdGhyZXNob2xkcyxcbiAgICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICAgIG91dHB1dDtcblxuICAgICAgICBpZiAodHlwZW9mIGFyZ1dpdGhTdWZmaXggPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBhcmdUaHJlc2hvbGRzID0gYXJnV2l0aFN1ZmZpeDtcbiAgICAgICAgICAgIGFyZ1dpdGhTdWZmaXggPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGFyZ1dpdGhTdWZmaXggPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgd2l0aFN1ZmZpeCA9IGFyZ1dpdGhTdWZmaXg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBhcmdUaHJlc2hvbGRzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgdGggPSBPYmplY3QuYXNzaWduKHt9LCB0aHJlc2hvbGRzLCBhcmdUaHJlc2hvbGRzKTtcbiAgICAgICAgICAgIGlmIChhcmdUaHJlc2hvbGRzLnMgIT0gbnVsbCAmJiBhcmdUaHJlc2hvbGRzLnNzID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aC5zcyA9IGFyZ1RocmVzaG9sZHMucyAtIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsb2NhbGUgPSB0aGlzLmxvY2FsZURhdGEoKTtcbiAgICAgICAgb3V0cHV0ID0gcmVsYXRpdmVUaW1lJDEodGhpcywgIXdpdGhTdWZmaXgsIHRoLCBsb2NhbGUpO1xuXG4gICAgICAgIGlmICh3aXRoU3VmZml4KSB7XG4gICAgICAgICAgICBvdXRwdXQgPSBsb2NhbGUucGFzdEZ1dHVyZSgrdGhpcywgb3V0cHV0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBsb2NhbGUucG9zdGZvcm1hdChvdXRwdXQpO1xuICAgIH1cblxuICAgIHZhciBhYnMkMSA9IE1hdGguYWJzO1xuXG4gICAgZnVuY3Rpb24gc2lnbih4KSB7XG4gICAgICAgIHJldHVybiAoeCA+IDApIC0gKHggPCAwKSB8fCAreDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b0lTT1N0cmluZyQxKCkge1xuICAgICAgICAvLyBmb3IgSVNPIHN0cmluZ3Mgd2UgZG8gbm90IHVzZSB0aGUgbm9ybWFsIGJ1YmJsaW5nIHJ1bGVzOlxuICAgICAgICAvLyAgKiBtaWxsaXNlY29uZHMgYnViYmxlIHVwIHVudGlsIHRoZXkgYmVjb21lIGhvdXJzXG4gICAgICAgIC8vICAqIGRheXMgZG8gbm90IGJ1YmJsZSBhdCBhbGxcbiAgICAgICAgLy8gICogbW9udGhzIGJ1YmJsZSB1cCB1bnRpbCB0aGV5IGJlY29tZSB5ZWFyc1xuICAgICAgICAvLyBUaGlzIGlzIGJlY2F1c2UgdGhlcmUgaXMgbm8gY29udGV4dC1mcmVlIGNvbnZlcnNpb24gYmV0d2VlbiBob3VycyBhbmQgZGF5c1xuICAgICAgICAvLyAodGhpbmsgb2YgY2xvY2sgY2hhbmdlcylcbiAgICAgICAgLy8gYW5kIGFsc28gbm90IGJldHdlZW4gZGF5cyBhbmQgbW9udGhzICgyOC0zMSBkYXlzIHBlciBtb250aClcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2Vjb25kcyA9IGFicyQxKHRoaXMuX21pbGxpc2Vjb25kcykgLyAxMDAwLFxuICAgICAgICAgICAgZGF5cyA9IGFicyQxKHRoaXMuX2RheXMpLFxuICAgICAgICAgICAgbW9udGhzID0gYWJzJDEodGhpcy5fbW9udGhzKSxcbiAgICAgICAgICAgIG1pbnV0ZXMsXG4gICAgICAgICAgICBob3VycyxcbiAgICAgICAgICAgIHllYXJzLFxuICAgICAgICAgICAgcyxcbiAgICAgICAgICAgIHRvdGFsID0gdGhpcy5hc1NlY29uZHMoKSxcbiAgICAgICAgICAgIHRvdGFsU2lnbixcbiAgICAgICAgICAgIHltU2lnbixcbiAgICAgICAgICAgIGRheXNTaWduLFxuICAgICAgICAgICAgaG1zU2lnbjtcblxuICAgICAgICBpZiAoIXRvdGFsKSB7XG4gICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSBzYW1lIGFzIEMjJ3MgKE5vZGEpIGFuZCBweXRob24gKGlzb2RhdGUpLi4uXG4gICAgICAgICAgICAvLyBidXQgbm90IG90aGVyIEpTIChnb29nLmRhdGUpXG4gICAgICAgICAgICByZXR1cm4gJ1AwRCc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAzNjAwIHNlY29uZHMgLT4gNjAgbWludXRlcyAtPiAxIGhvdXJcbiAgICAgICAgbWludXRlcyA9IGFic0Zsb29yKHNlY29uZHMgLyA2MCk7XG4gICAgICAgIGhvdXJzID0gYWJzRmxvb3IobWludXRlcyAvIDYwKTtcbiAgICAgICAgc2Vjb25kcyAlPSA2MDtcbiAgICAgICAgbWludXRlcyAlPSA2MDtcblxuICAgICAgICAvLyAxMiBtb250aHMgLT4gMSB5ZWFyXG4gICAgICAgIHllYXJzID0gYWJzRmxvb3IobW9udGhzIC8gMTIpO1xuICAgICAgICBtb250aHMgJT0gMTI7XG5cbiAgICAgICAgLy8gaW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL2RvcmRpbGxlL21vbWVudC1pc29kdXJhdGlvbi9ibG9iL21hc3Rlci9tb21lbnQuaXNvZHVyYXRpb24uanNcbiAgICAgICAgcyA9IHNlY29uZHMgPyBzZWNvbmRzLnRvRml4ZWQoMykucmVwbGFjZSgvXFwuPzArJC8sICcnKSA6ICcnO1xuXG4gICAgICAgIHRvdGFsU2lnbiA9IHRvdGFsIDwgMCA/ICctJyA6ICcnO1xuICAgICAgICB5bVNpZ24gPSBzaWduKHRoaXMuX21vbnRocykgIT09IHNpZ24odG90YWwpID8gJy0nIDogJyc7XG4gICAgICAgIGRheXNTaWduID0gc2lnbih0aGlzLl9kYXlzKSAhPT0gc2lnbih0b3RhbCkgPyAnLScgOiAnJztcbiAgICAgICAgaG1zU2lnbiA9IHNpZ24odGhpcy5fbWlsbGlzZWNvbmRzKSAhPT0gc2lnbih0b3RhbCkgPyAnLScgOiAnJztcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdG90YWxTaWduICtcbiAgICAgICAgICAgICdQJyArXG4gICAgICAgICAgICAoeWVhcnMgPyB5bVNpZ24gKyB5ZWFycyArICdZJyA6ICcnKSArXG4gICAgICAgICAgICAobW9udGhzID8geW1TaWduICsgbW9udGhzICsgJ00nIDogJycpICtcbiAgICAgICAgICAgIChkYXlzID8gZGF5c1NpZ24gKyBkYXlzICsgJ0QnIDogJycpICtcbiAgICAgICAgICAgIChob3VycyB8fCBtaW51dGVzIHx8IHNlY29uZHMgPyAnVCcgOiAnJykgK1xuICAgICAgICAgICAgKGhvdXJzID8gaG1zU2lnbiArIGhvdXJzICsgJ0gnIDogJycpICtcbiAgICAgICAgICAgIChtaW51dGVzID8gaG1zU2lnbiArIG1pbnV0ZXMgKyAnTScgOiAnJykgK1xuICAgICAgICAgICAgKHNlY29uZHMgPyBobXNTaWduICsgcyArICdTJyA6ICcnKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHZhciBwcm90byQyID0gRHVyYXRpb24ucHJvdG90eXBlO1xuXG4gICAgcHJvdG8kMi5pc1ZhbGlkID0gaXNWYWxpZCQxO1xuICAgIHByb3RvJDIuYWJzID0gYWJzO1xuICAgIHByb3RvJDIuYWRkID0gYWRkJDE7XG4gICAgcHJvdG8kMi5zdWJ0cmFjdCA9IHN1YnRyYWN0JDE7XG4gICAgcHJvdG8kMi5hcyA9IGFzO1xuICAgIHByb3RvJDIuYXNNaWxsaXNlY29uZHMgPSBhc01pbGxpc2Vjb25kcztcbiAgICBwcm90byQyLmFzU2Vjb25kcyA9IGFzU2Vjb25kcztcbiAgICBwcm90byQyLmFzTWludXRlcyA9IGFzTWludXRlcztcbiAgICBwcm90byQyLmFzSG91cnMgPSBhc0hvdXJzO1xuICAgIHByb3RvJDIuYXNEYXlzID0gYXNEYXlzO1xuICAgIHByb3RvJDIuYXNXZWVrcyA9IGFzV2Vla3M7XG4gICAgcHJvdG8kMi5hc01vbnRocyA9IGFzTW9udGhzO1xuICAgIHByb3RvJDIuYXNRdWFydGVycyA9IGFzUXVhcnRlcnM7XG4gICAgcHJvdG8kMi5hc1llYXJzID0gYXNZZWFycztcbiAgICBwcm90byQyLnZhbHVlT2YgPSB2YWx1ZU9mJDE7XG4gICAgcHJvdG8kMi5fYnViYmxlID0gYnViYmxlO1xuICAgIHByb3RvJDIuY2xvbmUgPSBjbG9uZSQxO1xuICAgIHByb3RvJDIuZ2V0ID0gZ2V0JDI7XG4gICAgcHJvdG8kMi5taWxsaXNlY29uZHMgPSBtaWxsaXNlY29uZHM7XG4gICAgcHJvdG8kMi5zZWNvbmRzID0gc2Vjb25kcztcbiAgICBwcm90byQyLm1pbnV0ZXMgPSBtaW51dGVzO1xuICAgIHByb3RvJDIuaG91cnMgPSBob3VycztcbiAgICBwcm90byQyLmRheXMgPSBkYXlzO1xuICAgIHByb3RvJDIud2Vla3MgPSB3ZWVrcztcbiAgICBwcm90byQyLm1vbnRocyA9IG1vbnRocztcbiAgICBwcm90byQyLnllYXJzID0geWVhcnM7XG4gICAgcHJvdG8kMi5odW1hbml6ZSA9IGh1bWFuaXplO1xuICAgIHByb3RvJDIudG9JU09TdHJpbmcgPSB0b0lTT1N0cmluZyQxO1xuICAgIHByb3RvJDIudG9TdHJpbmcgPSB0b0lTT1N0cmluZyQxO1xuICAgIHByb3RvJDIudG9KU09OID0gdG9JU09TdHJpbmckMTtcbiAgICBwcm90byQyLmxvY2FsZSA9IGxvY2FsZTtcbiAgICBwcm90byQyLmxvY2FsZURhdGEgPSBsb2NhbGVEYXRhO1xuXG4gICAgcHJvdG8kMi50b0lzb1N0cmluZyA9IGRlcHJlY2F0ZShcbiAgICAgICAgJ3RvSXNvU3RyaW5nKCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSB0b0lTT1N0cmluZygpIGluc3RlYWQgKG5vdGljZSB0aGUgY2FwaXRhbHMpJyxcbiAgICAgICAgdG9JU09TdHJpbmckMVxuICAgICk7XG4gICAgcHJvdG8kMi5sYW5nID0gbGFuZztcblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdYJywgMCwgMCwgJ3VuaXgnKTtcbiAgICBhZGRGb3JtYXRUb2tlbigneCcsIDAsIDAsICd2YWx1ZU9mJyk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCd4JywgbWF0Y2hTaWduZWQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1gnLCBtYXRjaFRpbWVzdGFtcCk7XG4gICAgYWRkUGFyc2VUb2tlbignWCcsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShwYXJzZUZsb2F0KGlucHV0KSAqIDEwMDApO1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oJ3gnLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUodG9JbnQoaW5wdXQpKTtcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanNcblxuICAgIGhvb2tzLnZlcnNpb24gPSAnMi4yOS4xJztcblxuICAgIHNldEhvb2tDYWxsYmFjayhjcmVhdGVMb2NhbCk7XG5cbiAgICBob29rcy5mbiA9IHByb3RvO1xuICAgIGhvb2tzLm1pbiA9IG1pbjtcbiAgICBob29rcy5tYXggPSBtYXg7XG4gICAgaG9va3Mubm93ID0gbm93O1xuICAgIGhvb2tzLnV0YyA9IGNyZWF0ZVVUQztcbiAgICBob29rcy51bml4ID0gY3JlYXRlVW5peDtcbiAgICBob29rcy5tb250aHMgPSBsaXN0TW9udGhzO1xuICAgIGhvb2tzLmlzRGF0ZSA9IGlzRGF0ZTtcbiAgICBob29rcy5sb2NhbGUgPSBnZXRTZXRHbG9iYWxMb2NhbGU7XG4gICAgaG9va3MuaW52YWxpZCA9IGNyZWF0ZUludmFsaWQ7XG4gICAgaG9va3MuZHVyYXRpb24gPSBjcmVhdGVEdXJhdGlvbjtcbiAgICBob29rcy5pc01vbWVudCA9IGlzTW9tZW50O1xuICAgIGhvb2tzLndlZWtkYXlzID0gbGlzdFdlZWtkYXlzO1xuICAgIGhvb2tzLnBhcnNlWm9uZSA9IGNyZWF0ZUluWm9uZTtcbiAgICBob29rcy5sb2NhbGVEYXRhID0gZ2V0TG9jYWxlO1xuICAgIGhvb2tzLmlzRHVyYXRpb24gPSBpc0R1cmF0aW9uO1xuICAgIGhvb2tzLm1vbnRoc1Nob3J0ID0gbGlzdE1vbnRoc1Nob3J0O1xuICAgIGhvb2tzLndlZWtkYXlzTWluID0gbGlzdFdlZWtkYXlzTWluO1xuICAgIGhvb2tzLmRlZmluZUxvY2FsZSA9IGRlZmluZUxvY2FsZTtcbiAgICBob29rcy51cGRhdGVMb2NhbGUgPSB1cGRhdGVMb2NhbGU7XG4gICAgaG9va3MubG9jYWxlcyA9IGxpc3RMb2NhbGVzO1xuICAgIGhvb2tzLndlZWtkYXlzU2hvcnQgPSBsaXN0V2Vla2RheXNTaG9ydDtcbiAgICBob29rcy5ub3JtYWxpemVVbml0cyA9IG5vcm1hbGl6ZVVuaXRzO1xuICAgIGhvb2tzLnJlbGF0aXZlVGltZVJvdW5kaW5nID0gZ2V0U2V0UmVsYXRpdmVUaW1lUm91bmRpbmc7XG4gICAgaG9va3MucmVsYXRpdmVUaW1lVGhyZXNob2xkID0gZ2V0U2V0UmVsYXRpdmVUaW1lVGhyZXNob2xkO1xuICAgIGhvb2tzLmNhbGVuZGFyRm9ybWF0ID0gZ2V0Q2FsZW5kYXJGb3JtYXQ7XG4gICAgaG9va3MucHJvdG90eXBlID0gcHJvdG87XG5cbiAgICAvLyBjdXJyZW50bHkgSFRNTDUgaW5wdXQgdHlwZSBvbmx5IHN1cHBvcnRzIDI0LWhvdXIgZm9ybWF0c1xuICAgIGhvb2tzLkhUTUw1X0ZNVCA9IHtcbiAgICAgICAgREFURVRJTUVfTE9DQUw6ICdZWVlZLU1NLUREVEhIOm1tJywgLy8gPGlucHV0IHR5cGU9XCJkYXRldGltZS1sb2NhbFwiIC8+XG4gICAgICAgIERBVEVUSU1FX0xPQ0FMX1NFQ09ORFM6ICdZWVlZLU1NLUREVEhIOm1tOnNzJywgLy8gPGlucHV0IHR5cGU9XCJkYXRldGltZS1sb2NhbFwiIHN0ZXA9XCIxXCIgLz5cbiAgICAgICAgREFURVRJTUVfTE9DQUxfTVM6ICdZWVlZLU1NLUREVEhIOm1tOnNzLlNTUycsIC8vIDxpbnB1dCB0eXBlPVwiZGF0ZXRpbWUtbG9jYWxcIiBzdGVwPVwiMC4wMDFcIiAvPlxuICAgICAgICBEQVRFOiAnWVlZWS1NTS1ERCcsIC8vIDxpbnB1dCB0eXBlPVwiZGF0ZVwiIC8+XG4gICAgICAgIFRJTUU6ICdISDptbScsIC8vIDxpbnB1dCB0eXBlPVwidGltZVwiIC8+XG4gICAgICAgIFRJTUVfU0VDT05EUzogJ0hIOm1tOnNzJywgLy8gPGlucHV0IHR5cGU9XCJ0aW1lXCIgc3RlcD1cIjFcIiAvPlxuICAgICAgICBUSU1FX01TOiAnSEg6bW06c3MuU1NTJywgLy8gPGlucHV0IHR5cGU9XCJ0aW1lXCIgc3RlcD1cIjAuMDAxXCIgLz5cbiAgICAgICAgV0VFSzogJ0dHR0ctW1ddV1cnLCAvLyA8aW5wdXQgdHlwZT1cIndlZWtcIiAvPlxuICAgICAgICBNT05USDogJ1lZWVktTU0nLCAvLyA8aW5wdXQgdHlwZT1cIm1vbnRoXCIgLz5cbiAgICB9O1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdhZicsIHtcbiAgICAgICAgbW9udGhzOiAnSmFudWFyaWVfRmVicnVhcmllX01hYXJ0X0FwcmlsX01laV9KdW5pZV9KdWxpZV9BdWd1c3R1c19TZXB0ZW1iZXJfT2t0b2Jlcl9Ob3ZlbWJlcl9EZXNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRmViX01ydF9BcHJfTWVpX0p1bl9KdWxfQXVnX1NlcF9Pa3RfTm92X0Rlcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdTb25kYWdfTWFhbmRhZ19EaW5zZGFnX1dvZW5zZGFnX0RvbmRlcmRhZ19WcnlkYWdfU2F0ZXJkYWcnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTb25fTWFhX0Rpbl9Xb2VfRG9uX1ZyeV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU29fTWFfRGlfV29fRG9fVnJfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC92bXxubS9pLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiAvXm5tJC9pLnRlc3QoaW5wdXQpO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ3ZtJyA6ICdWTSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ25tJyA6ICdOTSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbVmFuZGFnIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW03DtHJlIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW29tXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0dpc3RlciBvbV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbTGFhc10gZGRkZCBbb21dIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnb29yICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBnZWxlZGUnLFxuICAgICAgICAgICAgczogXCInbiBwYWFyIHNla29uZGVzXCIsXG4gICAgICAgICAgICBzczogJyVkIHNla29uZGVzJyxcbiAgICAgICAgICAgIG06IFwiJ24gbWludXV0XCIsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0ZScsXG4gICAgICAgICAgICBoOiBcIiduIHV1clwiLFxuICAgICAgICAgICAgaGg6ICclZCB1cmUnLFxuICAgICAgICAgICAgZDogXCInbiBkYWdcIixcbiAgICAgICAgICAgIGRkOiAnJWQgZGFlJyxcbiAgICAgICAgICAgIE06IFwiJ24gbWFhbmRcIixcbiAgICAgICAgICAgIE1NOiAnJWQgbWFhbmRlJyxcbiAgICAgICAgICAgIHk6IFwiJ24gamFhclwiLFxuICAgICAgICAgICAgeXk6ICclZCBqYWFyJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIG51bWJlciArXG4gICAgICAgICAgICAgICAgKG51bWJlciA9PT0gMSB8fCBudW1iZXIgPT09IDggfHwgbnVtYmVyID49IDIwID8gJ3N0ZScgOiAnZGUnKVxuICAgICAgICAgICAgKTsgLy8gVGhhbmtzIHRvIEpvcmlzIFLDtmxpbmcgOiBodHRwczovL2dpdGh1Yi5jb20vamp1cGl0ZXJcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNYWFuZGFnIGlzIGRpZSBlZXJzdGUgZGFnIHZhbiBkaWUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gRGllIHdlZWsgd2F0IGRpZSA0ZGUgSmFudWFyaWUgYmV2YXQgaXMgZGllIGVlcnN0ZSB3ZWVrIHZhbiBkaWUgamFhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBwbHVyYWxGb3JtID0gZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgIHJldHVybiBuID09PSAwXG4gICAgICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICAgICAgOiBuID09PSAxXG4gICAgICAgICAgICAgICAgPyAxXG4gICAgICAgICAgICAgICAgOiBuID09PSAyXG4gICAgICAgICAgICAgICAgPyAyXG4gICAgICAgICAgICAgICAgOiBuICUgMTAwID49IDMgJiYgbiAlIDEwMCA8PSAxMFxuICAgICAgICAgICAgICAgID8gM1xuICAgICAgICAgICAgICAgIDogbiAlIDEwMCA+PSAxMVxuICAgICAgICAgICAgICAgID8gNFxuICAgICAgICAgICAgICAgIDogNTtcbiAgICAgICAgfSxcbiAgICAgICAgcGx1cmFscyA9IHtcbiAgICAgICAgICAgIHM6IFtcbiAgICAgICAgICAgICAgICAn2KPZgtmEINmF2YYg2KvYp9mG2YrYqScsXG4gICAgICAgICAgICAgICAgJ9ir2KfZhtmK2Kkg2YjYp9it2K/YqScsXG4gICAgICAgICAgICAgICAgWyfYq9in2YbZitiq2KfZhicsICfYq9in2YbZitiq2YrZhiddLFxuICAgICAgICAgICAgICAgICclZCDYq9mI2KfZhicsXG4gICAgICAgICAgICAgICAgJyVkINir2KfZhtmK2KknLFxuICAgICAgICAgICAgICAgICclZCDYq9in2YbZitipJyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBtOiBbXG4gICAgICAgICAgICAgICAgJ9ij2YLZhCDZhdmGINiv2YLZitmC2KknLFxuICAgICAgICAgICAgICAgICfYr9mC2YrZgtipINmI2KfYrdiv2KknLFxuICAgICAgICAgICAgICAgIFsn2K/ZgtmK2YLYqtin2YYnLCAn2K/ZgtmK2YLYqtmK2YYnXSxcbiAgICAgICAgICAgICAgICAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgICAgICAgICAgJyVkINiv2YLZitmC2KknLFxuICAgICAgICAgICAgICAgICclZCDYr9mC2YrZgtipJyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBoOiBbXG4gICAgICAgICAgICAgICAgJ9ij2YLZhCDZhdmGINiz2KfYudipJyxcbiAgICAgICAgICAgICAgICAn2LPYp9i52Kkg2YjYp9it2K/YqScsXG4gICAgICAgICAgICAgICAgWyfYs9in2LnYqtin2YYnLCAn2LPYp9i52KrZitmGJ10sXG4gICAgICAgICAgICAgICAgJyVkINiz2KfYudin2KonLFxuICAgICAgICAgICAgICAgICclZCDYs9in2LnYqScsXG4gICAgICAgICAgICAgICAgJyVkINiz2KfYudipJyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBkOiBbXG4gICAgICAgICAgICAgICAgJ9ij2YLZhCDZhdmGINmK2YjZhScsXG4gICAgICAgICAgICAgICAgJ9mK2YjZhSDZiNin2K3YrycsXG4gICAgICAgICAgICAgICAgWyfZitmI2YXYp9mGJywgJ9mK2YjZhdmK2YYnXSxcbiAgICAgICAgICAgICAgICAnJWQg2KPZitin2YUnLFxuICAgICAgICAgICAgICAgICclZCDZitmI2YXZi9inJyxcbiAgICAgICAgICAgICAgICAnJWQg2YrZiNmFJyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBNOiBbXG4gICAgICAgICAgICAgICAgJ9ij2YLZhCDZhdmGINi02YfYsScsXG4gICAgICAgICAgICAgICAgJ9i02YfYsSDZiNin2K3YrycsXG4gICAgICAgICAgICAgICAgWyfYtNmH2LHYp9mGJywgJ9i02YfYsdmK2YYnXSxcbiAgICAgICAgICAgICAgICAnJWQg2KPYtNmH2LEnLFxuICAgICAgICAgICAgICAgICclZCDYtNmH2LHYpycsXG4gICAgICAgICAgICAgICAgJyVkINi02YfYsScsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgeTogW1xuICAgICAgICAgICAgICAgICfYo9mC2YQg2YXZhiDYudin2YUnLFxuICAgICAgICAgICAgICAgICfYudin2YUg2YjYp9it2K8nLFxuICAgICAgICAgICAgICAgIFsn2LnYp9mF2KfZhicsICfYudin2YXZitmGJ10sXG4gICAgICAgICAgICAgICAgJyVkINij2LnZiNin2YUnLFxuICAgICAgICAgICAgICAgICclZCDYudin2YXZi9inJyxcbiAgICAgICAgICAgICAgICAnJWQg2LnYp9mFJyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIHBsdXJhbGl6ZSA9IGZ1bmN0aW9uICh1KSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgIHZhciBmID0gcGx1cmFsRm9ybShudW1iZXIpLFxuICAgICAgICAgICAgICAgICAgICBzdHIgPSBwbHVyYWxzW3VdW3BsdXJhbEZvcm0obnVtYmVyKV07XG4gICAgICAgICAgICAgICAgaWYgKGYgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyID0gc3RyW3dpdGhvdXRTdWZmaXggPyAwIDogMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBzdHIucmVwbGFjZSgvJWQvaSwgbnVtYmVyKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRocyQxID0gW1xuICAgICAgICAgICAgJ9is2KfZhtmB2YonLFxuICAgICAgICAgICAgJ9mB2YrZgdix2YonLFxuICAgICAgICAgICAgJ9mF2KfYsdizJyxcbiAgICAgICAgICAgICfYo9mB2LHZitmEJyxcbiAgICAgICAgICAgICfZhdin2YonLFxuICAgICAgICAgICAgJ9is2YjYp9mGJyxcbiAgICAgICAgICAgICfYrNmI2YrZhNmK2KknLFxuICAgICAgICAgICAgJ9ij2YjYqicsXG4gICAgICAgICAgICAn2LPYqNiq2YXYqNixJyxcbiAgICAgICAgICAgICfYo9mD2KrZiNio2LEnLFxuICAgICAgICAgICAgJ9mG2YjZgdmF2KjYsScsXG4gICAgICAgICAgICAn2K/Zitiz2YXYqNixJyxcbiAgICAgICAgXTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYXItZHonLCB7XG4gICAgICAgIG1vbnRoczogbW9udGhzJDEsXG4gICAgICAgIG1vbnRoc1Nob3J0OiBtb250aHMkMSxcbiAgICAgICAgd2Vla2RheXM6ICfYp9mE2KPYrdivX9in2YTYpdir2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfYo9it2K9f2KXYq9mG2YrZhl/Yq9mE2KfYq9in2KFf2KPYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnRC9cXHUyMDBGTS9cXHUyMDBGWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9i1fNmFLyxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9mFJyA9PT0gaW5wdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfYtSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2YUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9mL2Kcg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9ij2YXYsyDYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW9i52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAn2KjYudivICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICfZhdmG2LAgJXMnLFxuICAgICAgICAgICAgczogcGx1cmFsaXplKCdzJyksXG4gICAgICAgICAgICBzczogcGx1cmFsaXplKCdzJyksXG4gICAgICAgICAgICBtOiBwbHVyYWxpemUoJ20nKSxcbiAgICAgICAgICAgIG1tOiBwbHVyYWxpemUoJ20nKSxcbiAgICAgICAgICAgIGg6IHBsdXJhbGl6ZSgnaCcpLFxuICAgICAgICAgICAgaGg6IHBsdXJhbGl6ZSgnaCcpLFxuICAgICAgICAgICAgZDogcGx1cmFsaXplKCdkJyksXG4gICAgICAgICAgICBkZDogcGx1cmFsaXplKCdkJyksXG4gICAgICAgICAgICBNOiBwbHVyYWxpemUoJ00nKSxcbiAgICAgICAgICAgIE1NOiBwbHVyYWxpemUoJ00nKSxcbiAgICAgICAgICAgIHk6IHBsdXJhbGl6ZSgneScpLFxuICAgICAgICAgICAgeXk6IHBsdXJhbGl6ZSgneScpLFxuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYXIta3cnLCB7XG4gICAgICAgIG1vbnRoczogJ9mK2YbYp9mK2LFf2YHYqNix2KfZitixX9mF2KfYsdizX9ij2KjYsdmK2YRf2YXYp9mKX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiNiyX9i62LTYql/YtNiq2YbYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YbYqNixX9iv2KzZhtio2LEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2Ypf2YrZiNmG2YrZiF/ZitmI2YTZitmI2LJf2LrYtNiqX9i02KrZhtio2LFf2KPZg9iq2YjYqNixX9mG2YjZhtio2LFf2K/YrNmG2KjYsScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfYp9mE2KPYrdivX9in2YTYpdiq2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfYp9it2K9f2KfYqtmG2YrZhl/Yq9mE2KfYq9in2KFf2KfYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9i62K/YpyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW9i52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICfZgdmKICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICfZhdmG2LAgJXMnLFxuICAgICAgICAgICAgczogJ9ir2YjYp9mGJyxcbiAgICAgICAgICAgIHNzOiAnJWQg2KvYp9mG2YrYqScsXG4gICAgICAgICAgICBtOiAn2K/ZgtmK2YLYqScsXG4gICAgICAgICAgICBtbTogJyVkINiv2YLYp9im2YInLFxuICAgICAgICAgICAgaDogJ9iz2KfYudipJyxcbiAgICAgICAgICAgIGhoOiAnJWQg2LPYp9i52KfYqicsXG4gICAgICAgICAgICBkOiAn2YrZiNmFJyxcbiAgICAgICAgICAgIGRkOiAnJWQg2KPZitin2YUnLFxuICAgICAgICAgICAgTTogJ9i02YfYsScsXG4gICAgICAgICAgICBNTTogJyVkINij2LTZh9ixJyxcbiAgICAgICAgICAgIHk6ICfYs9mG2KknLFxuICAgICAgICAgICAgeXk6ICclZCDYs9mG2YjYp9iqJyxcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogMTIsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDEydGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwID0ge1xuICAgICAgICAgICAgMTogJzEnLFxuICAgICAgICAgICAgMjogJzInLFxuICAgICAgICAgICAgMzogJzMnLFxuICAgICAgICAgICAgNDogJzQnLFxuICAgICAgICAgICAgNTogJzUnLFxuICAgICAgICAgICAgNjogJzYnLFxuICAgICAgICAgICAgNzogJzcnLFxuICAgICAgICAgICAgODogJzgnLFxuICAgICAgICAgICAgOTogJzknLFxuICAgICAgICAgICAgMDogJzAnLFxuICAgICAgICB9LFxuICAgICAgICBwbHVyYWxGb3JtJDEgPSBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgcmV0dXJuIG4gPT09IDBcbiAgICAgICAgICAgICAgICA/IDBcbiAgICAgICAgICAgICAgICA6IG4gPT09IDFcbiAgICAgICAgICAgICAgICA/IDFcbiAgICAgICAgICAgICAgICA6IG4gPT09IDJcbiAgICAgICAgICAgICAgICA/IDJcbiAgICAgICAgICAgICAgICA6IG4gJSAxMDAgPj0gMyAmJiBuICUgMTAwIDw9IDEwXG4gICAgICAgICAgICAgICAgPyAzXG4gICAgICAgICAgICAgICAgOiBuICUgMTAwID49IDExXG4gICAgICAgICAgICAgICAgPyA0XG4gICAgICAgICAgICAgICAgOiA1O1xuICAgICAgICB9LFxuICAgICAgICBwbHVyYWxzJDEgPSB7XG4gICAgICAgICAgICBzOiBbXG4gICAgICAgICAgICAgICAgJ9ij2YLZhCDZhdmGINir2KfZhtmK2KknLFxuICAgICAgICAgICAgICAgICfYq9in2YbZitipINmI2KfYrdiv2KknLFxuICAgICAgICAgICAgICAgIFsn2KvYp9mG2YrYqtin2YYnLCAn2KvYp9mG2YrYqtmK2YYnXSxcbiAgICAgICAgICAgICAgICAnJWQg2KvZiNin2YYnLFxuICAgICAgICAgICAgICAgICclZCDYq9in2YbZitipJyxcbiAgICAgICAgICAgICAgICAnJWQg2KvYp9mG2YrYqScsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgbTogW1xuICAgICAgICAgICAgICAgICfYo9mC2YQg2YXZhiDYr9mC2YrZgtipJyxcbiAgICAgICAgICAgICAgICAn2K/ZgtmK2YLYqSDZiNin2K3Yr9ipJyxcbiAgICAgICAgICAgICAgICBbJ9iv2YLZitmC2KrYp9mGJywgJ9iv2YLZitmC2KrZitmGJ10sXG4gICAgICAgICAgICAgICAgJyVkINiv2YLYp9im2YInLFxuICAgICAgICAgICAgICAgICclZCDYr9mC2YrZgtipJyxcbiAgICAgICAgICAgICAgICAnJWQg2K/ZgtmK2YLYqScsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgaDogW1xuICAgICAgICAgICAgICAgICfYo9mC2YQg2YXZhiDYs9in2LnYqScsXG4gICAgICAgICAgICAgICAgJ9iz2KfYudipINmI2KfYrdiv2KknLFxuICAgICAgICAgICAgICAgIFsn2LPYp9i52KrYp9mGJywgJ9iz2KfYudiq2YrZhiddLFxuICAgICAgICAgICAgICAgICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgICAgICAgICAnJWQg2LPYp9i52KknLFxuICAgICAgICAgICAgICAgICclZCDYs9in2LnYqScsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgZDogW1xuICAgICAgICAgICAgICAgICfYo9mC2YQg2YXZhiDZitmI2YUnLFxuICAgICAgICAgICAgICAgICfZitmI2YUg2YjYp9it2K8nLFxuICAgICAgICAgICAgICAgIFsn2YrZiNmF2KfZhicsICfZitmI2YXZitmGJ10sXG4gICAgICAgICAgICAgICAgJyVkINij2YrYp9mFJyxcbiAgICAgICAgICAgICAgICAnJWQg2YrZiNmF2YvYpycsXG4gICAgICAgICAgICAgICAgJyVkINmK2YjZhScsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgTTogW1xuICAgICAgICAgICAgICAgICfYo9mC2YQg2YXZhiDYtNmH2LEnLFxuICAgICAgICAgICAgICAgICfYtNmH2LEg2YjYp9it2K8nLFxuICAgICAgICAgICAgICAgIFsn2LTZh9ix2KfZhicsICfYtNmH2LHZitmGJ10sXG4gICAgICAgICAgICAgICAgJyVkINij2LTZh9ixJyxcbiAgICAgICAgICAgICAgICAnJWQg2LTZh9ix2KcnLFxuICAgICAgICAgICAgICAgICclZCDYtNmH2LEnLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIHk6IFtcbiAgICAgICAgICAgICAgICAn2KPZgtmEINmF2YYg2LnYp9mFJyxcbiAgICAgICAgICAgICAgICAn2LnYp9mFINmI2KfYrdivJyxcbiAgICAgICAgICAgICAgICBbJ9i52KfZhdin2YYnLCAn2LnYp9mF2YrZhiddLFxuICAgICAgICAgICAgICAgICclZCDYo9i52YjYp9mFJyxcbiAgICAgICAgICAgICAgICAnJWQg2LnYp9mF2YvYpycsXG4gICAgICAgICAgICAgICAgJyVkINi52KfZhScsXG4gICAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBwbHVyYWxpemUkMSA9IGZ1bmN0aW9uICh1KSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgIHZhciBmID0gcGx1cmFsRm9ybSQxKG51bWJlciksXG4gICAgICAgICAgICAgICAgICAgIHN0ciA9IHBsdXJhbHMkMVt1XVtwbHVyYWxGb3JtJDEobnVtYmVyKV07XG4gICAgICAgICAgICAgICAgaWYgKGYgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyID0gc3RyW3dpdGhvdXRTdWZmaXggPyAwIDogMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBzdHIucmVwbGFjZSgvJWQvaSwgbnVtYmVyKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRocyQyID0gW1xuICAgICAgICAgICAgJ9mK2YbYp9mK2LEnLFxuICAgICAgICAgICAgJ9mB2KjYsdin2YrYsScsXG4gICAgICAgICAgICAn2YXYp9ix2LMnLFxuICAgICAgICAgICAgJ9ij2KjYsdmK2YQnLFxuICAgICAgICAgICAgJ9mF2KfZitmIJyxcbiAgICAgICAgICAgICfZitmI2YbZitmIJyxcbiAgICAgICAgICAgICfZitmI2YTZitmIJyxcbiAgICAgICAgICAgICfYo9i62LPYt9izJyxcbiAgICAgICAgICAgICfYs9io2KrZhdio2LEnLFxuICAgICAgICAgICAgJ9ij2YPYqtmI2KjYsScsXG4gICAgICAgICAgICAn2YbZiNmB2YXYqNixJyxcbiAgICAgICAgICAgICfYr9mK2LPZhdio2LEnLFxuICAgICAgICBdO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdhci1seScsIHtcbiAgICAgICAgbW9udGhzOiBtb250aHMkMixcbiAgICAgICAgbW9udGhzU2hvcnQ6IG1vbnRocyQyLFxuICAgICAgICB3ZWVrZGF5czogJ9in2YTYo9it2K9f2KfZhNil2KvZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9ij2K3Yr1/Ypdir2YbZitmGX9ir2YTYp9ir2KfYoV/Yo9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdEL1xcdTIwMEZNL1xcdTIwMEZZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv2LV82YUvLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiAn2YUnID09PSBpbnB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9i1JztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfZhSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9in2YTZitmI2YUg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vYutiv2YvYpyDYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW9i52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICfYqNi52K8gJXMnLFxuICAgICAgICAgICAgcGFzdDogJ9mF2YbYsCAlcycsXG4gICAgICAgICAgICBzOiBwbHVyYWxpemUkMSgncycpLFxuICAgICAgICAgICAgc3M6IHBsdXJhbGl6ZSQxKCdzJyksXG4gICAgICAgICAgICBtOiBwbHVyYWxpemUkMSgnbScpLFxuICAgICAgICAgICAgbW06IHBsdXJhbGl6ZSQxKCdtJyksXG4gICAgICAgICAgICBoOiBwbHVyYWxpemUkMSgnaCcpLFxuICAgICAgICAgICAgaGg6IHBsdXJhbGl6ZSQxKCdoJyksXG4gICAgICAgICAgICBkOiBwbHVyYWxpemUkMSgnZCcpLFxuICAgICAgICAgICAgZGQ6IHBsdXJhbGl6ZSQxKCdkJyksXG4gICAgICAgICAgICBNOiBwbHVyYWxpemUkMSgnTScpLFxuICAgICAgICAgICAgTU06IHBsdXJhbGl6ZSQxKCdNJyksXG4gICAgICAgICAgICB5OiBwbHVyYWxpemUkMSgneScpLFxuICAgICAgICAgICAgeXk6IHBsdXJhbGl6ZSQxKCd5JyksXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwW21hdGNoXTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDEyLCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxMnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdhci1tYScsIHtcbiAgICAgICAgbW9udGhzOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2Ypf2YrZiNmG2YrZiF/ZitmI2YTZitmI2LJf2LrYtNiqX9i02KrZhtio2LFf2KPZg9iq2YjYqNixX9mG2YjZhtio2LFf2K/YrNmG2KjYsScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfZitmG2KfZitixX9mB2KjYsdin2YrYsV/Zhdin2LHYs1/Yo9io2LHZitmEX9mF2KfZil/ZitmI2YbZitmIX9mK2YjZhNmK2YjYsl/Yuti02Kpf2LTYqtmG2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmG2KjYsV/Yr9is2YbYqNixJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ9in2YTYo9it2K9f2KfZhNil2KvZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9in2K3Yr1/Yp9ir2YbZitmGX9ir2YTYp9ir2KfYoV/Yp9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9mB2YogJXMnLFxuICAgICAgICAgICAgcGFzdDogJ9mF2YbYsCAlcycsXG4gICAgICAgICAgICBzOiAn2KvZiNin2YYnLFxuICAgICAgICAgICAgc3M6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgICAgIG06ICfYr9mC2YrZgtipJyxcbiAgICAgICAgICAgIG1tOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgICAgICBoOiAn2LPYp9i52KknLFxuICAgICAgICAgICAgaGg6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgICAgIGQ6ICfZitmI2YUnLFxuICAgICAgICAgICAgZGQ6ICclZCDYo9mK2KfZhScsXG4gICAgICAgICAgICBNOiAn2LTZh9ixJyxcbiAgICAgICAgICAgIE1NOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICAgICAgeTogJ9iz2YbYqScsXG4gICAgICAgICAgICB5eTogJyVkINiz2YbZiNin2KonLFxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJDEgPSB7XG4gICAgICAgICAgICAxOiAn2aEnLFxuICAgICAgICAgICAgMjogJ9miJyxcbiAgICAgICAgICAgIDM6ICfZoycsXG4gICAgICAgICAgICA0OiAn2aQnLFxuICAgICAgICAgICAgNTogJ9mlJyxcbiAgICAgICAgICAgIDY6ICfZpicsXG4gICAgICAgICAgICA3OiAn2acnLFxuICAgICAgICAgICAgODogJ9moJyxcbiAgICAgICAgICAgIDk6ICfZqScsXG4gICAgICAgICAgICAwOiAn2aAnLFxuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAgPSB7XG4gICAgICAgICAgICAn2aEnOiAnMScsXG4gICAgICAgICAgICAn2aInOiAnMicsXG4gICAgICAgICAgICAn2aMnOiAnMycsXG4gICAgICAgICAgICAn2aQnOiAnNCcsXG4gICAgICAgICAgICAn2aUnOiAnNScsXG4gICAgICAgICAgICAn2aYnOiAnNicsXG4gICAgICAgICAgICAn2acnOiAnNycsXG4gICAgICAgICAgICAn2agnOiAnOCcsXG4gICAgICAgICAgICAn2aknOiAnOScsXG4gICAgICAgICAgICAn2aAnOiAnMCcsXG4gICAgICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2FyLXNhJywge1xuICAgICAgICBtb250aHM6ICfZitmG2KfZitixX9mB2KjYsdin2YrYsV/Zhdin2LHYs1/Yo9io2LHZitmEX9mF2KfZitmIX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiF/Yo9i62LPYt9izX9iz2KjYqtmF2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmB2YXYqNixX9iv2YrYs9mF2KjYsScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfZitmG2KfZitixX9mB2KjYsdin2YrYsV/Zhdin2LHYs1/Yo9io2LHZitmEX9mF2KfZitmIX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiF/Yo9i62LPYt9izX9iz2KjYqtmF2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmB2YXYqNixX9iv2YrYs9mF2KjYsScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfYp9mE2KPYrdivX9in2YTYpdir2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfYo9it2K9f2KXYq9mG2YrZhl/Yq9mE2KfYq9in2KFf2KPYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9i1fNmFLyxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9mFJyA9PT0gaW5wdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfYtSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2YUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9mB2YogJXMnLFxuICAgICAgICAgICAgcGFzdDogJ9mF2YbYsCAlcycsXG4gICAgICAgICAgICBzOiAn2KvZiNin2YYnLFxuICAgICAgICAgICAgc3M6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgICAgIG06ICfYr9mC2YrZgtipJyxcbiAgICAgICAgICAgIG1tOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgICAgICBoOiAn2LPYp9i52KknLFxuICAgICAgICAgICAgaGg6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgICAgIGQ6ICfZitmI2YUnLFxuICAgICAgICAgICAgZGQ6ICclZCDYo9mK2KfZhScsXG4gICAgICAgICAgICBNOiAn2LTZh9ixJyxcbiAgICAgICAgICAgIE1NOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICAgICAgeTogJ9iz2YbYqScsXG4gICAgICAgICAgICB5eTogJyVkINiz2YbZiNin2KonLFxuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1xuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9b2aHZotmj2aTZpdmm2afZqNmp2aBdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwW21hdGNoXTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC/YjC9nLCAnLCcpO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQxW21hdGNoXTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA2LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA2dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2FyLXRuJywge1xuICAgICAgICBtb250aHM6ICfYrNin2YbZgdmKX9mB2YrZgdix2Ypf2YXYp9ix2LNf2KPZgdix2YrZhF/Zhdin2Ypf2KzZiNin2YZf2KzZiNmK2YTZitipX9ij2YjYql/Ys9io2KrZhdio2LFf2KPZg9iq2YjYqNixX9mG2YjZgdmF2KjYsV/Yr9mK2LPZhdio2LEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn2KzYp9mG2YHZil/ZgdmK2YHYsdmKX9mF2KfYsdizX9ij2YHYsdmK2YRf2YXYp9mKX9is2YjYp9mGX9is2YjZitmE2YrYqV/Yo9mI2Kpf2LPYqNiq2YXYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YHZhdio2LFf2K/Zitiz2YXYqNixJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ9in2YTYo9it2K9f2KfZhNil2KvZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9ij2K3Yr1/Ypdir2YbZitmGX9ir2YTYp9ir2KfYoV/Yo9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9mB2YogJXMnLFxuICAgICAgICAgICAgcGFzdDogJ9mF2YbYsCAlcycsXG4gICAgICAgICAgICBzOiAn2KvZiNin2YYnLFxuICAgICAgICAgICAgc3M6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgICAgIG06ICfYr9mC2YrZgtipJyxcbiAgICAgICAgICAgIG1tOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgICAgICBoOiAn2LPYp9i52KknLFxuICAgICAgICAgICAgaGg6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgICAgIGQ6ICfZitmI2YUnLFxuICAgICAgICAgICAgZGQ6ICclZCDYo9mK2KfZhScsXG4gICAgICAgICAgICBNOiAn2LTZh9ixJyxcbiAgICAgICAgICAgIE1NOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICAgICAgeTogJ9iz2YbYqScsXG4gICAgICAgICAgICB5eTogJyVkINiz2YbZiNin2KonLFxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJDIgPSB7XG4gICAgICAgICAgICAxOiAn2aEnLFxuICAgICAgICAgICAgMjogJ9miJyxcbiAgICAgICAgICAgIDM6ICfZoycsXG4gICAgICAgICAgICA0OiAn2aQnLFxuICAgICAgICAgICAgNTogJ9mlJyxcbiAgICAgICAgICAgIDY6ICfZpicsXG4gICAgICAgICAgICA3OiAn2acnLFxuICAgICAgICAgICAgODogJ9moJyxcbiAgICAgICAgICAgIDk6ICfZqScsXG4gICAgICAgICAgICAwOiAn2aAnLFxuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAkMSA9IHtcbiAgICAgICAgICAgICfZoSc6ICcxJyxcbiAgICAgICAgICAgICfZoic6ICcyJyxcbiAgICAgICAgICAgICfZoyc6ICczJyxcbiAgICAgICAgICAgICfZpCc6ICc0JyxcbiAgICAgICAgICAgICfZpSc6ICc1JyxcbiAgICAgICAgICAgICfZpic6ICc2JyxcbiAgICAgICAgICAgICfZpyc6ICc3JyxcbiAgICAgICAgICAgICfZqCc6ICc4JyxcbiAgICAgICAgICAgICfZqSc6ICc5JyxcbiAgICAgICAgICAgICfZoCc6ICcwJyxcbiAgICAgICAgfSxcbiAgICAgICAgcGx1cmFsRm9ybSQyID0gZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgIHJldHVybiBuID09PSAwXG4gICAgICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICAgICAgOiBuID09PSAxXG4gICAgICAgICAgICAgICAgPyAxXG4gICAgICAgICAgICAgICAgOiBuID09PSAyXG4gICAgICAgICAgICAgICAgPyAyXG4gICAgICAgICAgICAgICAgOiBuICUgMTAwID49IDMgJiYgbiAlIDEwMCA8PSAxMFxuICAgICAgICAgICAgICAgID8gM1xuICAgICAgICAgICAgICAgIDogbiAlIDEwMCA+PSAxMVxuICAgICAgICAgICAgICAgID8gNFxuICAgICAgICAgICAgICAgIDogNTtcbiAgICAgICAgfSxcbiAgICAgICAgcGx1cmFscyQyID0ge1xuICAgICAgICAgICAgczogW1xuICAgICAgICAgICAgICAgICfYo9mC2YQg2YXZhiDYq9in2YbZitipJyxcbiAgICAgICAgICAgICAgICAn2KvYp9mG2YrYqSDZiNin2K3Yr9ipJyxcbiAgICAgICAgICAgICAgICBbJ9ir2KfZhtmK2KrYp9mGJywgJ9ir2KfZhtmK2KrZitmGJ10sXG4gICAgICAgICAgICAgICAgJyVkINir2YjYp9mGJyxcbiAgICAgICAgICAgICAgICAnJWQg2KvYp9mG2YrYqScsXG4gICAgICAgICAgICAgICAgJyVkINir2KfZhtmK2KknLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIG06IFtcbiAgICAgICAgICAgICAgICAn2KPZgtmEINmF2YYg2K/ZgtmK2YLYqScsXG4gICAgICAgICAgICAgICAgJ9iv2YLZitmC2Kkg2YjYp9it2K/YqScsXG4gICAgICAgICAgICAgICAgWyfYr9mC2YrZgtiq2KfZhicsICfYr9mC2YrZgtiq2YrZhiddLFxuICAgICAgICAgICAgICAgICclZCDYr9mC2KfYptmCJyxcbiAgICAgICAgICAgICAgICAnJWQg2K/ZgtmK2YLYqScsXG4gICAgICAgICAgICAgICAgJyVkINiv2YLZitmC2KknLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGg6IFtcbiAgICAgICAgICAgICAgICAn2KPZgtmEINmF2YYg2LPYp9i52KknLFxuICAgICAgICAgICAgICAgICfYs9in2LnYqSDZiNin2K3Yr9ipJyxcbiAgICAgICAgICAgICAgICBbJ9iz2KfYudiq2KfZhicsICfYs9in2LnYqtmK2YYnXSxcbiAgICAgICAgICAgICAgICAnJWQg2LPYp9i52KfYqicsXG4gICAgICAgICAgICAgICAgJyVkINiz2KfYudipJyxcbiAgICAgICAgICAgICAgICAnJWQg2LPYp9i52KknLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGQ6IFtcbiAgICAgICAgICAgICAgICAn2KPZgtmEINmF2YYg2YrZiNmFJyxcbiAgICAgICAgICAgICAgICAn2YrZiNmFINmI2KfYrdivJyxcbiAgICAgICAgICAgICAgICBbJ9mK2YjZhdin2YYnLCAn2YrZiNmF2YrZhiddLFxuICAgICAgICAgICAgICAgICclZCDYo9mK2KfZhScsXG4gICAgICAgICAgICAgICAgJyVkINmK2YjZhdmL2KcnLFxuICAgICAgICAgICAgICAgICclZCDZitmI2YUnLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIE06IFtcbiAgICAgICAgICAgICAgICAn2KPZgtmEINmF2YYg2LTZh9ixJyxcbiAgICAgICAgICAgICAgICAn2LTZh9ixINmI2KfYrdivJyxcbiAgICAgICAgICAgICAgICBbJ9i02YfYsdin2YYnLCAn2LTZh9ix2YrZhiddLFxuICAgICAgICAgICAgICAgICclZCDYo9i02YfYsScsXG4gICAgICAgICAgICAgICAgJyVkINi02YfYsdinJyxcbiAgICAgICAgICAgICAgICAnJWQg2LTZh9ixJyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB5OiBbXG4gICAgICAgICAgICAgICAgJ9ij2YLZhCDZhdmGINi52KfZhScsXG4gICAgICAgICAgICAgICAgJ9i52KfZhSDZiNin2K3YrycsXG4gICAgICAgICAgICAgICAgWyfYudin2YXYp9mGJywgJ9i52KfZhdmK2YYnXSxcbiAgICAgICAgICAgICAgICAnJWQg2KPYudmI2KfZhScsXG4gICAgICAgICAgICAgICAgJyVkINi52KfZhdmL2KcnLFxuICAgICAgICAgICAgICAgICclZCDYudin2YUnLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgcGx1cmFsaXplJDIgPSBmdW5jdGlvbiAodSkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZiA9IHBsdXJhbEZvcm0kMihudW1iZXIpLFxuICAgICAgICAgICAgICAgICAgICBzdHIgPSBwbHVyYWxzJDJbdV1bcGx1cmFsRm9ybSQyKG51bWJlcildO1xuICAgICAgICAgICAgICAgIGlmIChmID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ciA9IHN0clt3aXRob3V0U3VmZml4ID8gMCA6IDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UoLyVkL2ksIG51bWJlcik7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgICBtb250aHMkMyA9IFtcbiAgICAgICAgICAgICfZitmG2KfZitixJyxcbiAgICAgICAgICAgICfZgdio2LHYp9mK2LEnLFxuICAgICAgICAgICAgJ9mF2KfYsdizJyxcbiAgICAgICAgICAgICfYo9io2LHZitmEJyxcbiAgICAgICAgICAgICfZhdin2YrZiCcsXG4gICAgICAgICAgICAn2YrZiNmG2YrZiCcsXG4gICAgICAgICAgICAn2YrZiNmE2YrZiCcsXG4gICAgICAgICAgICAn2KPYutiz2LfYsycsXG4gICAgICAgICAgICAn2LPYqNiq2YXYqNixJyxcbiAgICAgICAgICAgICfYo9mD2KrZiNio2LEnLFxuICAgICAgICAgICAgJ9mG2YjZgdmF2KjYsScsXG4gICAgICAgICAgICAn2K/Zitiz2YXYqNixJyxcbiAgICAgICAgXTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYXInLCB7XG4gICAgICAgIG1vbnRoczogbW9udGhzJDMsXG4gICAgICAgIG1vbnRoc1Nob3J0OiBtb250aHMkMyxcbiAgICAgICAgd2Vla2RheXM6ICfYp9mE2KPYrdivX9in2YTYpdir2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfYo9it2K9f2KXYq9mG2YrZhl/Yq9mE2KfYq9in2KFf2KPYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnRC9cXHUyMDBGTS9cXHUyMDBGWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9i1fNmFLyxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9mFJyA9PT0gaW5wdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfYtSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2YUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9mL2Kcg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9ij2YXYsyDYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW9i52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAn2KjYudivICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICfZhdmG2LAgJXMnLFxuICAgICAgICAgICAgczogcGx1cmFsaXplJDIoJ3MnKSxcbiAgICAgICAgICAgIHNzOiBwbHVyYWxpemUkMigncycpLFxuICAgICAgICAgICAgbTogcGx1cmFsaXplJDIoJ20nKSxcbiAgICAgICAgICAgIG1tOiBwbHVyYWxpemUkMignbScpLFxuICAgICAgICAgICAgaDogcGx1cmFsaXplJDIoJ2gnKSxcbiAgICAgICAgICAgIGhoOiBwbHVyYWxpemUkMignaCcpLFxuICAgICAgICAgICAgZDogcGx1cmFsaXplJDIoJ2QnKSxcbiAgICAgICAgICAgIGRkOiBwbHVyYWxpemUkMignZCcpLFxuICAgICAgICAgICAgTTogcGx1cmFsaXplJDIoJ00nKSxcbiAgICAgICAgICAgIE1NOiBwbHVyYWxpemUkMignTScpLFxuICAgICAgICAgICAgeTogcGx1cmFsaXplJDIoJ3knKSxcbiAgICAgICAgICAgIHl5OiBwbHVyYWxpemUkMigneScpLFxuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1xuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9b2aHZotmj2aTZpdmm2afZqNmp2aBdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDFbbWF0Y2hdO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDJbbWF0Y2hdO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogNiwgLy8gU2F0dXJkYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogMTIsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDEydGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3VmZml4ZXMgPSB7XG4gICAgICAgIDE6ICctaW5jaScsXG4gICAgICAgIDU6ICctaW5jaScsXG4gICAgICAgIDg6ICctaW5jaScsXG4gICAgICAgIDcwOiAnLWluY2knLFxuICAgICAgICA4MDogJy1pbmNpJyxcbiAgICAgICAgMjogJy1uY2knLFxuICAgICAgICA3OiAnLW5jaScsXG4gICAgICAgIDIwOiAnLW5jaScsXG4gICAgICAgIDUwOiAnLW5jaScsXG4gICAgICAgIDM6ICctw7xuY8O8JyxcbiAgICAgICAgNDogJy3DvG5jw7wnLFxuICAgICAgICAxMDA6ICctw7xuY8O8JyxcbiAgICAgICAgNjogJy1uY8SxJyxcbiAgICAgICAgOTogJy11bmN1JyxcbiAgICAgICAgMTA6ICctdW5jdScsXG4gICAgICAgIDMwOiAnLXVuY3UnLFxuICAgICAgICA2MDogJy3EsW5jxLEnLFxuICAgICAgICA5MDogJy3EsW5jxLEnLFxuICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2F6Jywge1xuICAgICAgICBtb250aHM6ICd5YW52YXJfZmV2cmFsX21hcnRfYXByZWxfbWF5X2l5dW5faXl1bF9hdnF1c3Rfc2VudHlhYnJfb2t0eWFicl9ub3lhYnJfZGVrYWJyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ3lhbl9mZXZfbWFyX2Fwcl9tYXlfaXluX2l5bF9hdnFfc2VuX29rdF9ub3lfZGVrJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ0JhemFyX0JhemFyIGVydMmZc2lfw4fJmXLFn8mZbmLJmSBheMWfYW3EsV/Dh8mZcsWfyZluYsmZX0PDvG3JmSBheMWfYW3EsV9Dw7xtyZlfxZ7JmW5iyZknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdCYXpfQnpFX8OHQXhfw4fJmXJfQ0F4X0PDvG1fxZ7JmW4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnQnpfQkVfw4dBX8OHyZlfQ0FfQ8O8X8WeyZknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tidWfDvG4gc2FhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tzYWJhaCBzYWF0XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1tnyZlsyZluIGjJmWZ0yZldIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbZMO8bsmZbl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdba2XDp8mZbiBoyZlmdMmZXSBkZGRkIFtzYWF0XSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJyVzIHNvbnJhJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDJmXZ2yZlsJyxcbiAgICAgICAgICAgIHM6ICdiaXIgbmXDp8mZIHNhbml5yZknLFxuICAgICAgICAgICAgc3M6ICclZCBzYW5pecmZJyxcbiAgICAgICAgICAgIG06ICdiaXIgZMmZcWlxyZknLFxuICAgICAgICAgICAgbW06ICclZCBkyZlxaXHJmScsXG4gICAgICAgICAgICBoOiAnYmlyIHNhYXQnLFxuICAgICAgICAgICAgaGg6ICclZCBzYWF0JyxcbiAgICAgICAgICAgIGQ6ICdiaXIgZ8O8bicsXG4gICAgICAgICAgICBkZDogJyVkIGfDvG4nLFxuICAgICAgICAgICAgTTogJ2JpciBheScsXG4gICAgICAgICAgICBNTTogJyVkIGF5JyxcbiAgICAgICAgICAgIHk6ICdiaXIgaWwnLFxuICAgICAgICAgICAgeXk6ICclZCBpbCcsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9nZWPJmXxzyZloyZlyfGfDvG5kw7x6fGF4xZ9hbS8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIC9eKGfDvG5kw7x6fGF4xZ9hbSkkLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZ2VjyZknO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3PJmWjJmXInO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2fDvG5kw7x6JztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdheMWfYW0nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKMSxbmPEsXxpbmNpfG5jaXzDvG5jw7x8bmPEsXx1bmN1KS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBzcGVjaWFsIGNhc2UgZm9yIHplcm9cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3EsW5jxLEnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGEgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBiID0gKG51bWJlciAlIDEwMCkgLSBhLFxuICAgICAgICAgICAgICAgIGMgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAoc3VmZml4ZXNbYV0gfHwgc3VmZml4ZXNbYl0gfHwgc3VmZml4ZXNbY10pO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA3LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwbHVyYWwod29yZCwgbnVtKSB7XG4gICAgICAgIHZhciBmb3JtcyA9IHdvcmQuc3BsaXQoJ18nKTtcbiAgICAgICAgcmV0dXJuIG51bSAlIDEwID09PSAxICYmIG51bSAlIDEwMCAhPT0gMTFcbiAgICAgICAgICAgID8gZm9ybXNbMF1cbiAgICAgICAgICAgIDogbnVtICUgMTAgPj0gMiAmJiBudW0gJSAxMCA8PSA0ICYmIChudW0gJSAxMDAgPCAxMCB8fCBudW0gJSAxMDAgPj0gMjApXG4gICAgICAgICAgICA/IGZvcm1zWzFdXG4gICAgICAgICAgICA6IGZvcm1zWzJdO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICBzczogd2l0aG91dFN1ZmZpeCA/ICfRgdC10LrRg9C90LTQsF/RgdC10LrRg9C90LTRi1/RgdC10LrRg9C90LQnIDogJ9GB0LXQutGD0L3QtNGDX9GB0LXQutGD0L3QtNGLX9GB0LXQutGD0L3QtCcsXG4gICAgICAgICAgICBtbTogd2l0aG91dFN1ZmZpeCA/ICfRhdCy0ZbQu9GW0L3QsF/RhdCy0ZbQu9GW0L3Ri1/RhdCy0ZbQu9GW0L0nIDogJ9GF0LLRltC70ZbQvdGDX9GF0LLRltC70ZbQvdGLX9GF0LLRltC70ZbQvScsXG4gICAgICAgICAgICBoaDogd2l0aG91dFN1ZmZpeCA/ICfQs9Cw0LTQt9GW0L3QsF/Qs9Cw0LTQt9GW0L3Ri1/Qs9Cw0LTQt9GW0L0nIDogJ9Cz0LDQtNC30ZbQvdGDX9Cz0LDQtNC30ZbQvdGLX9Cz0LDQtNC30ZbQvScsXG4gICAgICAgICAgICBkZDogJ9C00LfQtdC90Yxf0LTQvdGWX9C00LfRkdC9JyxcbiAgICAgICAgICAgIE1NOiAn0LzQtdGB0Y/Rhl/QvNC10YHRj9GG0Ytf0LzQtdGB0Y/RhtCw0Z4nLFxuICAgICAgICAgICAgeXk6ICfQs9C+0LRf0LPQsNC00Ytf0LPQsNC00L7RnicsXG4gICAgICAgIH07XG4gICAgICAgIGlmIChrZXkgPT09ICdtJykge1xuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAn0YXQstGW0LvRltC90LAnIDogJ9GF0LLRltC70ZbQvdGDJztcbiAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09ICdoJykge1xuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAn0LPQsNC00LfRltC90LAnIDogJ9Cz0LDQtNC30ZbQvdGDJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnICcgKyBwbHVyYWwoZm9ybWF0W2tleV0sICtudW1iZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdiZScsIHtcbiAgICAgICAgbW9udGhzOiB7XG4gICAgICAgICAgICBmb3JtYXQ6ICfRgdGC0YPQtNC30LXQvdGPX9C70Y7RgtCw0LPQsF/RgdCw0LrQsNCy0ZbQutCwX9C60YDQsNGB0LDQstGW0LrQsF/RgtGA0LDRntC90Y9f0YfRjdGA0LLQtdC90Y9f0LvRltC/0LXQvdGPX9C20L3RltGe0L3Rj1/QstC10YDQsNGB0L3Rj1/QutCw0YHRgtGA0YvRh9C90ZbQutCwX9C70ZbRgdGC0LDQv9Cw0LTQsF/RgdC90LXQttC90Y8nLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICfRgdGC0YPQtNC30LXQvdGMX9C70Y7RgtGLX9GB0LDQutCw0LLRltC6X9C60YDQsNGB0LDQstGW0Lpf0YLRgNCw0LLQtdC90Yxf0YfRjdGA0LLQtdC90Yxf0LvRltC/0LXQvdGMX9C20L3RltCy0LXQvdGMX9Cy0LXRgNCw0YHQtdC90Yxf0LrQsNGB0YLRgNGL0YfQvdGW0Lpf0LvRltGB0YLQsNC/0LDQtF/RgdC90LXQttCw0L3RjCcuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydDogJ9GB0YLRg9C0X9C70Y7Rgl/RgdCw0Lpf0LrRgNCw0YFf0YLRgNCw0LJf0YfRjdGA0LJf0LvRltC/X9C20L3RltCyX9Cy0LXRgF/QutCw0YHRgl/Qu9GW0YHRgl/RgdC90LXQticuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ9C90Y/QtNC30LXQu9GOX9C/0LDQvdGP0LTQt9C10LvQsNC6X9Cw0Z7RgtC+0YDQsNC6X9GB0LXRgNCw0LTRg1/Rh9Cw0YbQstC10YBf0L/Rj9GC0L3RltGG0YNf0YHRg9Cx0L7RgtGDJy5zcGxpdChcbiAgICAgICAgICAgICAgICAnXydcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBzdGFuZGFsb25lOiAn0L3Rj9C00LfQtdC70Y9f0L/QsNC90Y/QtNC30LXQu9Cw0Lpf0LDRntGC0L7RgNCw0Lpf0YHQtdGA0LDQtNCwX9GH0LDRhtCy0LXRgF/Qv9GP0YLQvdGW0YbQsF/RgdGD0LHQvtGC0LAnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGlzRm9ybWF0OiAvXFxbID9b0KPRg9GeXSA/KD860LzRltC90YPQu9GD0Y580L3QsNGB0YLRg9C/0L3Rg9GOKT8gP1xcXSA/ZGRkZC8sXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfQvdC0X9C/0L1f0LDRgl/RgdGAX9GH0YZf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9C90LRf0L/QvV/QsNGCX9GB0YBf0YfRhl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVkg0LMuJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZINCzLiwgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZINCzLiwgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vQodGR0L3QvdGPINGeXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9CX0LDRntGC0YDQsCDRnl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vQo9GH0L7RgNCwINGeXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW9CjXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CjINC80ZbQvdGD0LvRg9GOXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0KMg0LzRltC90YPQu9GLXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9C/0YDQsNC3ICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDRgtCw0LzRgycsXG4gICAgICAgICAgICBzOiAn0L3QtdC60LDQu9GM0LrRliDRgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgbTogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgICAgIG1tOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICAgICAgaDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgICAgIGhoOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICAgICAgZDogJ9C00LfQtdC90YwnLFxuICAgICAgICAgICAgZGQ6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgICAgICBNOiAn0LzQtdGB0Y/RhicsXG4gICAgICAgICAgICBNTTogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgICAgIHk6ICfQs9C+0LQnLFxuICAgICAgICAgICAgeXk6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/QvdC+0YfRi3zRgNCw0L3RltGG0Yt80LTQvdGPfNCy0LXRh9Cw0YDQsC8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIC9eKNC00L3Rj3zQstC10YfQsNGA0LApJC8udGVzdChpbnB1dCk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9C90L7Rh9GLJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfRgNCw0L3RltGG0YsnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9C00L3Rjyc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0LLQtdGH0LDRgNCwJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjRlnzRi3zQs9CwKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKG51bWJlciAlIDEwID09PSAyIHx8IG51bWJlciAlIDEwID09PSAzKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyICUgMTAwICE9PSAxMiAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyICUgMTAwICE9PSAxM1xuICAgICAgICAgICAgICAgICAgICAgICAgPyBudW1iZXIgKyAnLdGWJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBudW1iZXIgKyAnLdGLJztcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LPQsCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNywgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdiZycsIHtcbiAgICAgICAgbW9udGhzOiAn0Y/QvdGD0LDRgNC4X9GE0LXQstGA0YPQsNGA0Lhf0LzQsNGA0YJf0LDQv9GA0LjQu1/QvNCw0Llf0Y7QvdC4X9GO0LvQuF/QsNCy0LPRg9GB0YJf0YHQtdC/0YLQtdC80LLRgNC4X9C+0LrRgtC+0LzQstGA0Lhf0L3QvtC10LzQstGA0Lhf0LTQtdC60LXQvNCy0YDQuCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfRj9C90YNf0YTQtdCyX9C80LDRgF/QsNC/0YBf0LzQsNC5X9GO0L3QuF/RjtC70Lhf0LDQstCzX9GB0LXQv1/QvtC60YJf0L3QvtC1X9C00LXQuicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICfQvdC10LTQtdC70Y9f0L/QvtC90LXQtNC10LvQvdC40Lpf0LLRgtC+0YDQvdC40Lpf0YHRgNGP0LTQsF/Rh9C10YLQstGK0YDRgtGK0Lpf0L/QtdGC0YrQul/RgdGK0LHQvtGC0LAnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfQvdC10LRf0L/QvtC9X9Cy0YLQvl/RgdGA0Y9f0YfQtdGCX9C/0LXRgl/RgdGK0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn0L3QtF/Qv9C9X9Cy0YJf0YHRgF/Rh9GCX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb0JTQvdC10YEg0LJdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb0KPRgtGA0LUg0LJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb0LJdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb0JLRh9C10YDQsCDQsl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9Cc0LjQvdCw0LvQsNGC0LBdIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9Cc0LjQvdCw0LvQuNGPXSBkZGRkIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9GB0LvQtdC0ICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICfQv9GA0LXQtNC4ICVzJyxcbiAgICAgICAgICAgIHM6ICfQvdGP0LrQvtC70LrQviDRgdC10LrRg9C90LTQuCcsXG4gICAgICAgICAgICBzczogJyVkINGB0LXQutGD0L3QtNC4JyxcbiAgICAgICAgICAgIG06ICfQvNC40L3Rg9GC0LAnLFxuICAgICAgICAgICAgbW06ICclZCDQvNC40L3Rg9GC0LgnLFxuICAgICAgICAgICAgaDogJ9GH0LDRgScsXG4gICAgICAgICAgICBoaDogJyVkINGH0LDRgdCwJyxcbiAgICAgICAgICAgIGQ6ICfQtNC10L0nLFxuICAgICAgICAgICAgZGQ6ICclZCDQtNC10L3QsCcsXG4gICAgICAgICAgICB3OiAn0YHQtdC00LzQuNGG0LAnLFxuICAgICAgICAgICAgd3c6ICclZCDRgdC10LTQvNC40YbQuCcsXG4gICAgICAgICAgICBNOiAn0LzQtdGB0LXRhicsXG4gICAgICAgICAgICBNTTogJyVkINC80LXRgdC10YbQsCcsXG4gICAgICAgICAgICB5OiAn0LPQvtC00LjQvdCwJyxcbiAgICAgICAgICAgIHl5OiAnJWQg0LPQvtC00LjQvdC4JyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjQtdCyfNC10L180YLQuHzQstC4fNGA0Lh80LzQuCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgbGFzdERpZ2l0ID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgbGFzdDJEaWdpdHMgPSBudW1iZXIgJSAxMDA7XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LXQsic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxhc3QyRGlnaXRzID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LXQvSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxhc3QyRGlnaXRzID4gMTAgJiYgbGFzdDJEaWdpdHMgPCAyMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0RGlnaXQgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QstC4JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGFzdERpZ2l0ID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0YDQuCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxhc3REaWdpdCA9PT0gNyB8fCBsYXN0RGlnaXQgPT09IDgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QvNC4JztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0YLQuCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYm0nLCB7XG4gICAgICAgIG1vbnRoczogJ1phbnd1eWVrYWxvX0Zld3VydXlla2Fsb19NYXJpc2lrYWxvX0F3aXJpbGlrYWxvX03Jm2thbG9fWnV3yZtua2Fsb19adWx1eWVrYWxvX1V0aWthbG9fU8mbdGFuYnVydWthbG9fyZRrdXTJlGJ1cnVrYWxvX05vd2FuYnVydWthbG9fRGVzYW5idXJ1a2Fsbycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdaYW5fRmV3X01hcl9Bd2lfTcmbX1p1d19adWxfVXRpX1PJm3RfyZRrdV9Ob3dfRGVzJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ0thcmlfTnTJm27Jm25fVGFyYXRhX0FyYWJhX0FsYW1pc2FfSnVtYV9TaWJpcmknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdLYXJfTnTJm19UYXJfQXJhX0FsYV9KdW1fU2liJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ0thX050X1RhX0FyX0FsX0p1X1NpJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ01NTU0gW3RpbGVdIEQgW3Nhbl0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdNTU1NIFt0aWxlXSBEIFtzYW5dIFlZWVkgW2zJm3LJm10gSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgTU1NTSBbdGlsZV0gRCBbc2FuXSBZWVlZIFtsyZtyyZtdIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbQmkgbMmbcsmbXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW1NpbmkgbMmbcsmbXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2RvbiBsyZtyyZtdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbS3VudSBsyZtyyZtdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbdMmbbcmbbmVuIGzJm3LJm10gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclcyBryZRuyZQnLFxuICAgICAgICAgICAgcGFzdDogJ2EgYsmbICVzIGLJlCcsXG4gICAgICAgICAgICBzOiAnc2FuZ2EgZGFtYSBkYW1hJyxcbiAgICAgICAgICAgIHNzOiAnc2Vrb25kaSAlZCcsXG4gICAgICAgICAgICBtOiAnbWluaXRpIGtlbGVuJyxcbiAgICAgICAgICAgIG1tOiAnbWluaXRpICVkJyxcbiAgICAgICAgICAgIGg6ICdsyZtyyZsga2VsZW4nLFxuICAgICAgICAgICAgaGg6ICdsyZtyyZsgJWQnLFxuICAgICAgICAgICAgZDogJ3RpbGUga2VsZW4nLFxuICAgICAgICAgICAgZGQ6ICd0aWxlICVkJyxcbiAgICAgICAgICAgIE06ICdrYWxvIGtlbGVuJyxcbiAgICAgICAgICAgIE1NOiAna2FsbyAlZCcsXG4gICAgICAgICAgICB5OiAnc2FuIGtlbGVuJyxcbiAgICAgICAgICAgIHl5OiAnc2FuICVkJyxcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCQzID0ge1xuICAgICAgICAgICAgMTogJ+CnpycsXG4gICAgICAgICAgICAyOiAn4KeoJyxcbiAgICAgICAgICAgIDM6ICfgp6knLFxuICAgICAgICAgICAgNDogJ+CnqicsXG4gICAgICAgICAgICA1OiAn4KerJyxcbiAgICAgICAgICAgIDY6ICfgp6wnLFxuICAgICAgICAgICAgNzogJ+CnrScsXG4gICAgICAgICAgICA4OiAn4KeuJyxcbiAgICAgICAgICAgIDk6ICfgp68nLFxuICAgICAgICAgICAgMDogJ+CnpicsXG4gICAgICAgIH0sXG4gICAgICAgIG51bWJlck1hcCQyID0ge1xuICAgICAgICAgICAgJ+Cnpyc6ICcxJyxcbiAgICAgICAgICAgICfgp6gnOiAnMicsXG4gICAgICAgICAgICAn4KepJzogJzMnLFxuICAgICAgICAgICAgJ+Cnqic6ICc0JyxcbiAgICAgICAgICAgICfgp6snOiAnNScsXG4gICAgICAgICAgICAn4KesJzogJzYnLFxuICAgICAgICAgICAgJ+CnrSc6ICc3JyxcbiAgICAgICAgICAgICfgp64nOiAnOCcsXG4gICAgICAgICAgICAn4KevJzogJzknLFxuICAgICAgICAgICAgJ+Cnpic6ICcwJyxcbiAgICAgICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYm4tYmQnLCB7XG4gICAgICAgIG1vbnRoczogJ+CmnOCmvuCmqOCngeCnn+CmvuCmsOCmv1/gpqvgp4fgpqzgp43gprDgp4Hgp5/gpr7gprDgpr9f4Kau4Ka+4Kaw4KeN4KaaX+Cmj+CmquCnjeCmsOCmv+Cmsl/gpq7gp4df4Kac4KeB4KaoX+CmnOCngeCmsuCmvuCmh1/gpobgppfgprjgp43gpp9f4Ka44KeH4Kaq4KeN4Kaf4KeH4Kau4KeN4Kas4KawX+CmheCmleCnjeCmn+Cni+CmrOCmsF/gpqjgpq3gp4fgpq7gp43gpqzgprBf4Kah4Ka/4Ka44KeH4Kau4KeN4Kas4KawJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ+CmnOCmvuCmqOCngV/gpqvgp4fgpqzgp43gprDgp4Ff4Kau4Ka+4Kaw4KeN4KaaX+Cmj+CmquCnjeCmsOCmv+Cmsl/gpq7gp4df4Kac4KeB4KaoX+CmnOCngeCmsuCmvuCmh1/gpobgppfgprjgp43gpp9f4Ka44KeH4Kaq4KeN4KafX+CmheCmleCnjeCmn+Cni1/gpqjgpq3gp4df4Kah4Ka/4Ka44KeHJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ+CmsOCmrOCmv+CmrOCmvuCmsF/gprjgp4vgpq7gpqzgpr7gprBf4Kau4KaZ4KeN4KaX4Kay4Kas4Ka+4KawX+CmrOCngeCmp+CmrOCmvuCmsF/gpqzgp4Pgprngprjgp43gpqrgpqTgpr/gpqzgpr7gprBf4Ka24KeB4KaV4KeN4Kaw4Kas4Ka+4KawX+CmtuCmqOCmv+CmrOCmvuCmsCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+CmsOCmrOCmv1/gprjgp4vgpq5f4Kau4KaZ4KeN4KaX4KayX+CmrOCngeCmp1/gpqzgp4Pgprngprjgp43gpqrgpqTgpr9f4Ka24KeB4KaV4KeN4KawX+CmtuCmqOCmvycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfgprDgpqzgpr9f4Ka44KeL4KauX+CmruCmmeCnjeCml+Cmsl/gpqzgp4Hgpqdf4Kas4KeD4Ka5X+CmtuCngeCmleCnjeCmsF/gprbgpqjgpr8nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0EgaDptbSDgprjgpq7gp58nLFxuICAgICAgICAgICAgTFRTOiAnQSBoOm1tOnNzIOCmuOCmruCnnycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0g4Ka44Kau4KefJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tIOCmuOCmruCnnycsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+CmhuCmnF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vgpobgppfgpr7gpq7gp4DgppXgpr7gprJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCwgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vgppfgpqTgppXgpr7gprJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+Cml+CmpF0gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclcyDgpqrgprDgp4cnLFxuICAgICAgICAgICAgcGFzdDogJyVzIOCmhuCml+CnhycsXG4gICAgICAgICAgICBzOiAn4KaV4Kef4KeH4KaVIOCmuOCnh+CmleCnh+CmqOCnjeCmoScsXG4gICAgICAgICAgICBzczogJyVkIOCmuOCnh+CmleCnh+CmqOCnjeCmoScsXG4gICAgICAgICAgICBtOiAn4KaP4KaVIOCmruCmv+CmqOCmv+CmnycsXG4gICAgICAgICAgICBtbTogJyVkIOCmruCmv+CmqOCmv+CmnycsXG4gICAgICAgICAgICBoOiAn4KaP4KaVIOCmmOCmqOCnjeCmn+CmvicsXG4gICAgICAgICAgICBoaDogJyVkIOCmmOCmqOCnjeCmn+CmvicsXG4gICAgICAgICAgICBkOiAn4KaP4KaVIOCmpuCmv+CmqCcsXG4gICAgICAgICAgICBkZDogJyVkIOCmpuCmv+CmqCcsXG4gICAgICAgICAgICBNOiAn4KaP4KaVIOCmruCmvuCmuCcsXG4gICAgICAgICAgICBNTTogJyVkIOCmruCmvuCmuCcsXG4gICAgICAgICAgICB5OiAn4KaP4KaVIOCmrOCmm+CmsCcsXG4gICAgICAgICAgICB5eTogJyVkIOCmrOCmm+CmsCcsXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgp6fgp6jgp6ngp6rgp6vgp6zgp63gp67gp6/gp6ZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkMlttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQzW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gprDgpr7gpqR84Kat4KeL4KawfOCmuOCmleCmvuCmsnzgpqbgp4Hgpqrgp4HgprB84Kas4Ka/4KaV4Ka+4KayfOCmuOCmqOCnjeCmp+CnjeCmr+CmvnzgprDgpr7gpqQvLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgprDgpr7gpqQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgpq3gp4vgprAnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Ka44KaV4Ka+4KayJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CmpuCngeCmquCngeCmsCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAzID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgpqzgpr/gppXgpr7gprInKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgprjgpqjgp43gpqfgp43gpq/gpr4nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgprDgpr7gpqQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgNikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kat4KeL4KawJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgprjgppXgpr7gprInO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CmpuCngeCmquCngeCmsCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxOCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kas4Ka/4KaV4Ka+4KayJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgprjgpqjgp43gpqfgp43gpq/gpr4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CmsOCmvuCmpCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDYsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkNCA9IHtcbiAgICAgICAgICAgIDE6ICfgp6cnLFxuICAgICAgICAgICAgMjogJ+CnqCcsXG4gICAgICAgICAgICAzOiAn4KepJyxcbiAgICAgICAgICAgIDQ6ICfgp6onLFxuICAgICAgICAgICAgNTogJ+CnqycsXG4gICAgICAgICAgICA2OiAn4KesJyxcbiAgICAgICAgICAgIDc6ICfgp60nLFxuICAgICAgICAgICAgODogJ+CnricsXG4gICAgICAgICAgICA5OiAn4KevJyxcbiAgICAgICAgICAgIDA6ICfgp6YnLFxuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAkMyA9IHtcbiAgICAgICAgICAgICfgp6cnOiAnMScsXG4gICAgICAgICAgICAn4KeoJzogJzInLFxuICAgICAgICAgICAgJ+CnqSc6ICczJyxcbiAgICAgICAgICAgICfgp6onOiAnNCcsXG4gICAgICAgICAgICAn4KerJzogJzUnLFxuICAgICAgICAgICAgJ+CnrCc6ICc2JyxcbiAgICAgICAgICAgICfgp60nOiAnNycsXG4gICAgICAgICAgICAn4KeuJzogJzgnLFxuICAgICAgICAgICAgJ+Cnryc6ICc5JyxcbiAgICAgICAgICAgICfgp6YnOiAnMCcsXG4gICAgICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2JuJywge1xuICAgICAgICBtb250aHM6ICfgppzgpr7gpqjgp4Hgp5/gpr7gprDgpr9f4Kar4KeH4Kas4KeN4Kaw4KeB4Kef4Ka+4Kaw4Ka/X+CmruCmvuCmsOCnjeCmml/gpo/gpqrgp43gprDgpr/gprJf4Kau4KeHX+CmnOCngeCmqF/gppzgp4HgprLgpr7gpodf4KaG4KaX4Ka44KeN4KafX+CmuOCnh+CmquCnjeCmn+Cnh+CmruCnjeCmrOCmsF/gpoXgppXgp43gpp/gp4vgpqzgprBf4Kao4Kat4KeH4Kau4KeN4Kas4KawX+CmoeCmv+CmuOCnh+CmruCnjeCmrOCmsCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgppzgpr7gpqjgp4Ff4Kar4KeH4Kas4KeN4Kaw4KeBX+CmruCmvuCmsOCnjeCmml/gpo/gpqrgp43gprDgpr/gprJf4Kau4KeHX+CmnOCngeCmqF/gppzgp4HgprLgpr7gpodf4KaG4KaX4Ka44KeN4KafX+CmuOCnh+CmquCnjeCmn1/gpoXgppXgp43gpp/gp4tf4Kao4Kat4KeHX+CmoeCmv+CmuOCnhycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfgprDgpqzgpr/gpqzgpr7gprBf4Ka44KeL4Kau4Kas4Ka+4KawX+CmruCmmeCnjeCml+CmsuCmrOCmvuCmsF/gpqzgp4Hgpqfgpqzgpr7gprBf4Kas4KeD4Ka54Ka44KeN4Kaq4Kak4Ka/4Kas4Ka+4KawX+CmtuCngeCmleCnjeCmsOCmrOCmvuCmsF/gprbgpqjgpr/gpqzgpr7gprAnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfgprDgpqzgpr9f4Ka44KeL4KauX+CmruCmmeCnjeCml+Cmsl/gpqzgp4Hgpqdf4Kas4KeD4Ka54Ka44KeN4Kaq4Kak4Ka/X+CmtuCngeCmleCnjeCmsF/gprbgpqjgpr8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4Kaw4Kas4Ka/X+CmuOCni+Cmrl/gpq7gppngp43gppfgprJf4Kas4KeB4KanX+CmrOCng+CmuV/gprbgp4HgppXgp43gprBf4Ka24Kao4Ka/Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdBIGg6bW0g4Ka44Kau4KefJyxcbiAgICAgICAgICAgIExUUzogJ0EgaDptbTpzcyDgprjgpq7gp58nLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCmuOCmruCnnycsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgprjgpq7gp58nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vgpobgppxdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4KaG4KaX4Ka+4Kau4KeA4KaV4Ka+4KayXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQsIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4KaX4Kak4KaV4Ka+4KayXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vgppfgpqRdIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg4Kaq4Kaw4KeHJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDgpobgppfgp4cnLFxuICAgICAgICAgICAgczogJ+CmleCnn+Cnh+CmlSDgprjgp4fgppXgp4fgpqjgp43gpqEnLFxuICAgICAgICAgICAgc3M6ICclZCDgprjgp4fgppXgp4fgpqjgp43gpqEnLFxuICAgICAgICAgICAgbTogJ+Cmj+CmlSDgpq7gpr/gpqjgpr/gpp8nLFxuICAgICAgICAgICAgbW06ICclZCDgpq7gpr/gpqjgpr/gpp8nLFxuICAgICAgICAgICAgaDogJ+Cmj+CmlSDgppjgpqjgp43gpp/gpr4nLFxuICAgICAgICAgICAgaGg6ICclZCDgppjgpqjgp43gpp/gpr4nLFxuICAgICAgICAgICAgZDogJ+Cmj+CmlSDgpqbgpr/gpqgnLFxuICAgICAgICAgICAgZGQ6ICclZCDgpqbgpr/gpqgnLFxuICAgICAgICAgICAgTTogJ+Cmj+CmlSDgpq7gpr7gprgnLFxuICAgICAgICAgICAgTU06ICclZCDgpq7gpr7gprgnLFxuICAgICAgICAgICAgeTogJ+Cmj+CmlSDgpqzgppvgprAnLFxuICAgICAgICAgICAgeXk6ICclZCDgpqzgppvgprAnLFxuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4Ken4Keo4Kep4Keq4Ker4Kes4Ket4Keu4Kev4KemXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDNbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXAkNFttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+CmsOCmvuCmpHzgprjgppXgpr7gprJ84Kam4KeB4Kaq4KeB4KawfOCmrOCmv+CmleCmvuCmsnzgprDgpr7gpqQvLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgKG1lcmlkaWVtID09PSAn4Kaw4Ka+4KakJyAmJiBob3VyID49IDQpIHx8XG4gICAgICAgICAgICAgICAgKG1lcmlkaWVtID09PSAn4Kam4KeB4Kaq4KeB4KawJyAmJiBob3VyIDwgNSkgfHxcbiAgICAgICAgICAgICAgICBtZXJpZGllbSA9PT0gJ+CmrOCmv+CmleCmvuCmsidcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgprDgpr7gpqQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CmuOCmleCmvuCmsic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kam4KeB4Kaq4KeB4KawJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpqzgpr/gppXgpr7gprInO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CmsOCmvuCmpCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDYsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkNSA9IHtcbiAgICAgICAgICAgIDE6ICfgvKEnLFxuICAgICAgICAgICAgMjogJ+C8oicsXG4gICAgICAgICAgICAzOiAn4LyjJyxcbiAgICAgICAgICAgIDQ6ICfgvKQnLFxuICAgICAgICAgICAgNTogJ+C8pScsXG4gICAgICAgICAgICA2OiAn4LymJyxcbiAgICAgICAgICAgIDc6ICfgvKcnLFxuICAgICAgICAgICAgODogJ+C8qCcsXG4gICAgICAgICAgICA5OiAn4LypJyxcbiAgICAgICAgICAgIDA6ICfgvKAnLFxuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAkNCA9IHtcbiAgICAgICAgICAgICfgvKEnOiAnMScsXG4gICAgICAgICAgICAn4LyiJzogJzInLFxuICAgICAgICAgICAgJ+C8oyc6ICczJyxcbiAgICAgICAgICAgICfgvKQnOiAnNCcsXG4gICAgICAgICAgICAn4LylJzogJzUnLFxuICAgICAgICAgICAgJ+C8pic6ICc2JyxcbiAgICAgICAgICAgICfgvKcnOiAnNycsXG4gICAgICAgICAgICAn4LyoJzogJzgnLFxuICAgICAgICAgICAgJ+C8qSc6ICc5JyxcbiAgICAgICAgICAgICfgvKAnOiAnMCcsXG4gICAgICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2JvJywge1xuICAgICAgICBtb250aHM6ICfgvZ/gvrPgvIvgvZbgvIvgvZHgvYTgvIvgvZTgvbxf4L2f4L6z4LyL4L2W4LyL4L2C4L2J4L2y4L2m4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9guC9puC9tOC9mOC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvZ7gvbLgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2j4L6U4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9keC+suC9tOC9guC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvZHgvbTgvZPgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2i4L6S4L6x4L2R4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9keC9guC9tOC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvYXgvbTgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2F4L204LyL4L2C4L2F4L2y4L2C4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9luC9heC9tOC8i+C9guC9ieC9suC9puC8i+C9lCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgvZ/gvrPgvIsxX+C9n+C+s+C8izJf4L2f4L6z4LyLM1/gvZ/gvrPgvIs0X+C9n+C+s+C8izVf4L2f4L6z4LyLNl/gvZ/gvrPgvIs3X+C9n+C+s+C8izhf4L2f4L6z4LyLOV/gvZ/gvrPgvIsxMF/gvZ/gvrPgvIsxMV/gvZ/gvrPgvIsxMicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnRSZWdleDogL14o4L2f4L6z4LyLXFxkezEsMn0pLyxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6ICfgvYLgvZ/gvaDgvIvgvYngvbLgvIvgvZjgvItf4L2C4L2f4L2g4LyL4L2f4L6z4LyL4L2W4LyLX+C9guC9n+C9oOC8i+C9mOC9suC9guC8i+C9keC9mOC9ouC8i1/gvYLgvZ/gvaDgvIvgvaPgvrfgvYLgvIvgvZTgvItf4L2C4L2f4L2g4LyL4L2V4L204L2i4LyL4L2W4L20X+C9guC9n+C9oOC8i+C9lOC8i+C9puC9hOC9puC8i1/gvYLgvZ/gvaDgvIvgvabgvqTgvbrgvZPgvIvgvZTgvIsnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfgvYngvbLgvIvgvZjgvItf4L2f4L6z4LyL4L2W4LyLX+C9mOC9suC9guC8i+C9keC9mOC9ouC8i1/gvaPgvrfgvYLgvIvgvZTgvItf4L2V4L204L2i4LyL4L2W4L20X+C9lOC8i+C9puC9hOC9puC8i1/gvabgvqTgvbrgvZPgvIvgvZTgvIsnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4L2J4L2yX+C9n+C+s1/gvZjgvbLgvYJf4L2j4L634L2CX+C9leC9tOC9ol/gvabgvYTgvaZf4L2m4L6k4L264L2TJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdBIGg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVksIEEgaDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+C9keC9suC8i+C9ouC9suC9hF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vgvabgvYTgvIvgvYngvbLgvZNdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW+C9luC9keC9tOC9k+C8i+C9leC+suC9guC8i+C9ouC+l+C9uuC9puC8i+C9mF0sIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4L2B4LyL4L2m4L2EXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vgvZbgvZHgvbTgvZPgvIvgvZXgvrLgvYLgvIvgvZjgvZDgvaDgvIvgvZhdIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg4L2j4LyLJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDgvabgvpTgvZPgvIvgvaMnLFxuICAgICAgICAgICAgczogJ+C9o+C9mOC8i+C9puC9hCcsXG4gICAgICAgICAgICBzczogJyVkIOC9puC+kOC9ouC8i+C9huC8jScsXG4gICAgICAgICAgICBtOiAn4L2m4L6Q4L2i4LyL4L2Y4LyL4L2C4L2F4L2y4L2CJyxcbiAgICAgICAgICAgIG1tOiAnJWQg4L2m4L6Q4L2i4LyL4L2YJyxcbiAgICAgICAgICAgIGg6ICfgvYbgvbTgvIvgvZrgvbzgvZHgvIvgvYLgvYXgvbLgvYInLFxuICAgICAgICAgICAgaGg6ICclZCDgvYbgvbTgvIvgvZrgvbzgvZEnLFxuICAgICAgICAgICAgZDogJ+C9ieC9suC9k+C8i+C9guC9heC9suC9gicsXG4gICAgICAgICAgICBkZDogJyVkIOC9ieC9suC9k+C8iycsXG4gICAgICAgICAgICBNOiAn4L2f4L6z4LyL4L2W4LyL4L2C4L2F4L2y4L2CJyxcbiAgICAgICAgICAgIE1NOiAnJWQg4L2f4L6z4LyL4L2WJyxcbiAgICAgICAgICAgIHk6ICfgvaPgvbzgvIvgvYLgvYXgvbLgvYInLFxuICAgICAgICAgICAgeXk6ICclZCDgvaPgvbwnLFxuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4Lyh4Lyi4Lyj4Lyk4Lyl4Lym4Lyn4Lyo4Lyp4LygXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDRbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXAkNVttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+C9mOC9muC9k+C8i+C9mOC9vHzgvZ7gvbzgvYLgvabgvIvgvYDgvaZ84L2J4L2y4L2T4LyL4L2C4L204L2EfOC9keC9guC9vOC9hOC8i+C9keC9gnzgvZjgvZrgvZPgvIvgvZjgvbwvLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgKG1lcmlkaWVtID09PSAn4L2Y4L2a4L2T4LyL4L2Y4L28JyAmJiBob3VyID49IDQpIHx8XG4gICAgICAgICAgICAgICAgKG1lcmlkaWVtID09PSAn4L2J4L2y4L2T4LyL4L2C4L204L2EJyAmJiBob3VyIDwgNSkgfHxcbiAgICAgICAgICAgICAgICBtZXJpZGllbSA9PT0gJ+C9keC9guC9vOC9hOC8i+C9keC9gidcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgvZjgvZrgvZPgvIvgvZjgvbwnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C9nuC9vOC9guC9puC8i+C9gOC9pic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4L2J4L2y4L2T4LyL4L2C4L204L2EJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgvZHgvYLgvbzgvYTgvIvgvZHgvYInO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C9mOC9muC9k+C8i+C9mOC9vCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDYsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIHJlbGF0aXZlVGltZVdpdGhNdXRhdGlvbihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgbW06ICdtdW51dGVubicsXG4gICAgICAgICAgICBNTTogJ21peicsXG4gICAgICAgICAgICBkZDogJ2RldmV6aCcsXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAnICcgKyBtdXRhdGlvbihmb3JtYXRba2V5XSwgbnVtYmVyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc3BlY2lhbE11dGF0aW9uRm9yWWVhcnMobnVtYmVyKSB7XG4gICAgICAgIHN3aXRjaCAobGFzdE51bWJlcihudW1iZXIpKSB7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICBjYXNlIDk6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgYmxvYXonO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyB2bG9heic7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gbGFzdE51bWJlcihudW1iZXIpIHtcbiAgICAgICAgaWYgKG51bWJlciA+IDkpIHtcbiAgICAgICAgICAgIHJldHVybiBsYXN0TnVtYmVyKG51bWJlciAlIDEwKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBtdXRhdGlvbih0ZXh0LCBudW1iZXIpIHtcbiAgICAgICAgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgcmV0dXJuIHNvZnRNdXRhdGlvbih0ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGV4dDtcbiAgICB9XG4gICAgZnVuY3Rpb24gc29mdE11dGF0aW9uKHRleHQpIHtcbiAgICAgICAgdmFyIG11dGF0aW9uVGFibGUgPSB7XG4gICAgICAgICAgICBtOiAndicsXG4gICAgICAgICAgICBiOiAndicsXG4gICAgICAgICAgICBkOiAneicsXG4gICAgICAgIH07XG4gICAgICAgIGlmIChtdXRhdGlvblRhYmxlW3RleHQuY2hhckF0KDApXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbXV0YXRpb25UYWJsZVt0ZXh0LmNoYXJBdCgwKV0gKyB0ZXh0LnN1YnN0cmluZygxKTtcbiAgICB9XG5cbiAgICB2YXIgbW9udGhzUGFyc2UgPSBbXG4gICAgICAgICAgICAvXmdlbi9pLFxuICAgICAgICAgICAgL15jW8q8XFwnXWh3ZS9pLFxuICAgICAgICAgICAgL15tZXUvaSxcbiAgICAgICAgICAgIC9eZWJyL2ksXG4gICAgICAgICAgICAvXm1hZS9pLFxuICAgICAgICAgICAgL14obWV6fGV2ZSkvaSxcbiAgICAgICAgICAgIC9eZ291L2ksXG4gICAgICAgICAgICAvXmVvcy9pLFxuICAgICAgICAgICAgL15nd2UvaSxcbiAgICAgICAgICAgIC9eaGVyL2ksXG4gICAgICAgICAgICAvXmR1L2ksXG4gICAgICAgICAgICAvXmtlci9pLFxuICAgICAgICBdLFxuICAgICAgICBtb250aHNSZWdleCQxID0gL14oZ2VudmVyfGNbyrxcXCddaHdldnJlcnxtZXVyemh8ZWJyZWx8bWFlfG1lemhldmVufGdvdWVyZXxlb3N0fGd3ZW5nb2xvfGhlcmV8ZHV8a2VyenV8Z2VufGNbyrxcXCddaHdlfG1ldXxlYnJ8bWFlfGV2ZXxnb3V8ZW9zfGd3ZXxoZXJ8ZHV8a2VyKS9pLFxuICAgICAgICBtb250aHNTdHJpY3RSZWdleCA9IC9eKGdlbnZlcnxjW8q8XFwnXWh3ZXZyZXJ8bWV1cnpofGVicmVsfG1hZXxtZXpoZXZlbnxnb3VlcmV8ZW9zdHxnd2VuZ29sb3xoZXJlfGR1fGtlcnp1KS9pLFxuICAgICAgICBtb250aHNTaG9ydFN0cmljdFJlZ2V4ID0gL14oZ2VufGNbyrxcXCddaHdlfG1ldXxlYnJ8bWFlfGV2ZXxnb3V8ZW9zfGd3ZXxoZXJ8ZHV8a2VyKS9pLFxuICAgICAgICBmdWxsV2Vla2RheXNQYXJzZSA9IFtcbiAgICAgICAgICAgIC9ec3VsL2ksXG4gICAgICAgICAgICAvXmx1bi9pLFxuICAgICAgICAgICAgL15tZXVyemgvaSxcbiAgICAgICAgICAgIC9ebWVyY1vKvFxcJ11oZXIvaSxcbiAgICAgICAgICAgIC9eeWFvdS9pLFxuICAgICAgICAgICAgL15nd2VuZXIvaSxcbiAgICAgICAgICAgIC9ec2Fkb3JuL2ksXG4gICAgICAgIF0sXG4gICAgICAgIHNob3J0V2Vla2RheXNQYXJzZSA9IFtcbiAgICAgICAgICAgIC9eU3VsL2ksXG4gICAgICAgICAgICAvXkx1bi9pLFxuICAgICAgICAgICAgL15NZXUvaSxcbiAgICAgICAgICAgIC9eTWVyL2ksXG4gICAgICAgICAgICAvXllhby9pLFxuICAgICAgICAgICAgL15Hd2UvaSxcbiAgICAgICAgICAgIC9eU2FkL2ksXG4gICAgICAgIF0sXG4gICAgICAgIG1pbldlZWtkYXlzUGFyc2UgPSBbXG4gICAgICAgICAgICAvXlN1L2ksXG4gICAgICAgICAgICAvXkx1L2ksXG4gICAgICAgICAgICAvXk1lKFtecl18JCkvaSxcbiAgICAgICAgICAgIC9eTWVyL2ksXG4gICAgICAgICAgICAvXllhL2ksXG4gICAgICAgICAgICAvXkd3L2ksXG4gICAgICAgICAgICAvXlNhL2ksXG4gICAgICAgIF07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2JyJywge1xuICAgICAgICBtb250aHM6ICdHZW52ZXJfQ8q8aHdldnJlcl9NZXVyemhfRWJyZWxfTWFlX01lemhldmVuX0dvdWVyZV9Fb3N0X0d3ZW5nb2xvX0hlcmVfRHVfS2VyenUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnR2VuX0PKvGh3ZV9NZXVfRWJyX01hZV9FdmVfR291X0Vvc19Hd2VfSGVyX0R1X0tlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdTdWxfTHVuX01ldXJ6aF9NZXJjyrxoZXJfWWFvdV9Hd2VuZXJfU2Fkb3JuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnU3VsX0x1bl9NZXVfTWVyX1lhb19Hd2VfU2FkJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1N1X0x1X01lX01lcl9ZYV9Hd19TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZTogbWluV2Vla2RheXNQYXJzZSxcbiAgICAgICAgZnVsbFdlZWtkYXlzUGFyc2U6IGZ1bGxXZWVrZGF5c1BhcnNlLFxuICAgICAgICBzaG9ydFdlZWtkYXlzUGFyc2U6IHNob3J0V2Vla2RheXNQYXJzZSxcbiAgICAgICAgbWluV2Vla2RheXNQYXJzZTogbWluV2Vla2RheXNQYXJzZSxcblxuICAgICAgICBtb250aHNSZWdleDogbW9udGhzUmVnZXgkMSxcbiAgICAgICAgbW9udGhzU2hvcnRSZWdleDogbW9udGhzUmVnZXgkMSxcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IG1vbnRoc1N0cmljdFJlZ2V4LFxuICAgICAgICBtb250aHNTaG9ydFN0cmljdFJlZ2V4OiBtb250aHNTaG9ydFN0cmljdFJlZ2V4LFxuICAgICAgICBtb250aHNQYXJzZTogbW9udGhzUGFyc2UsXG4gICAgICAgIGxvbmdNb250aHNQYXJzZTogbW9udGhzUGFyc2UsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlLFxuXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBbYSB2aXpdIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIFthIHZpel0gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIFthIHZpel0gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSGl6aXYgZGFdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbV2FyY8q8aG9hemggZGFdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbZGFdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbRGVjyrxoIGRhXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW3Bhc2V0IGRhXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2EtYmVubiAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgyrx6bycsXG4gICAgICAgICAgICBzOiAndW4gbmViZXVkIHNlZ29uZGVubm/DuScsXG4gICAgICAgICAgICBzczogJyVkIGVpbGVubicsXG4gICAgICAgICAgICBtOiAndXIgdnVudXRlbm4nLFxuICAgICAgICAgICAgbW06IHJlbGF0aXZlVGltZVdpdGhNdXRhdGlvbixcbiAgICAgICAgICAgIGg6ICd1biBldXInLFxuICAgICAgICAgICAgaGg6ICclZCBldXInLFxuICAgICAgICAgICAgZDogJ3VuIGRldmV6aCcsXG4gICAgICAgICAgICBkZDogcmVsYXRpdmVUaW1lV2l0aE11dGF0aW9uLFxuICAgICAgICAgICAgTTogJ3VyIG1peicsXG4gICAgICAgICAgICBNTTogcmVsYXRpdmVUaW1lV2l0aE11dGF0aW9uLFxuICAgICAgICAgICAgeTogJ3VyIGJsb2F6JyxcbiAgICAgICAgICAgIHl5OiBzcGVjaWFsTXV0YXRpb25Gb3JZZWFycyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGHDsXx2ZXQpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIG91dHB1dCA9IG51bWJlciA9PT0gMSA/ICdhw7EnIDogJ3ZldCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9hLm0ufGcubS4vLCAvLyBnb3VkZSBtZXJlbm4gfCBhLXJhb2sgbWVyZW5uXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uICh0b2tlbikge1xuICAgICAgICAgICAgcmV0dXJuIHRva2VuID09PSAnZy5tLic7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA8IDEyID8gJ2EubS4nIDogJ2cubS4nO1xuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICBjYXNlICdzcyc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3Nla3VuZGEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmRlJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3Nla3VuZGknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnamVkbmEgbWludXRhJyA6ICdqZWRuZSBtaW51dGUnO1xuICAgICAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtaW51dGEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtaW51dGUnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRhJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2plZGFuIHNhdCcgOiAnamVkbm9nIHNhdGEnO1xuICAgICAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXQnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXRhJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3NhdGknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdkYW4nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZGFuYSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21qZXNlYyc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21qZXNlY2EnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWplc2VjaSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2dvZGluYSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2dvZGluZSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdicycsIHtcbiAgICAgICAgbW9udGhzOiAnamFudWFyX2ZlYnJ1YXJfbWFydF9hcHJpbF9tYWpfanVuaV9qdWxpX2F1Z3VzdF9zZXB0ZW1iYXJfb2t0b2Jhcl9ub3ZlbWJhcl9kZWNlbWJhcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdqYW4uX2ZlYi5fbWFyLl9hcHIuX21hai5fanVuLl9qdWwuX2F1Zy5fc2VwLl9va3QuX25vdi5fZGVjLicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6ICduZWRqZWxqYV9wb25lZGplbGpha191dG9yYWtfc3JpamVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnbmVkLl9wb24uX3V0by5fc3JpLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnbmVfcG9fdXRfc3JfxI1lX3BlX3N1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tkYW5hcyB1XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW3N1dHJhIHVdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtuZWRqZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3NyaWplZHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzdWJvdHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogJ1tqdcSNZXIgdV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcm/FoWx1XSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbGVdIFtzdWJvdGVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbGldIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICd6YSAlcycsXG4gICAgICAgICAgICBwYXN0OiAncHJpamUgJXMnLFxuICAgICAgICAgICAgczogJ3BhciBzZWt1bmRpJyxcbiAgICAgICAgICAgIHNzOiB0cmFuc2xhdGUsXG4gICAgICAgICAgICBtOiB0cmFuc2xhdGUsXG4gICAgICAgICAgICBtbTogdHJhbnNsYXRlLFxuICAgICAgICAgICAgaDogdHJhbnNsYXRlLFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGQ6ICdkYW4nLFxuICAgICAgICAgICAgZGQ6IHRyYW5zbGF0ZSxcbiAgICAgICAgICAgIE06ICdtamVzZWMnLFxuICAgICAgICAgICAgTU06IHRyYW5zbGF0ZSxcbiAgICAgICAgICAgIHk6ICdnb2RpbnUnLFxuICAgICAgICAgICAgeXk6IHRyYW5zbGF0ZSxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbDogJyVkLicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnY2EnLCB7XG4gICAgICAgIG1vbnRoczoge1xuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ2dlbmVyX2ZlYnJlcl9tYXLDp19hYnJpbF9tYWlnX2p1bnlfanVsaW9sX2Fnb3N0X3NldGVtYnJlX29jdHVicmVfbm92ZW1icmVfZGVzZW1icmUnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGZvcm1hdDogXCJkZSBnZW5lcl9kZSBmZWJyZXJfZGUgbWFyw6dfZCdhYnJpbF9kZSBtYWlnX2RlIGp1bnlfZGUganVsaW9sX2QnYWdvc3RfZGUgc2V0ZW1icmVfZCdvY3R1YnJlX2RlIG5vdmVtYnJlX2RlIGRlc2VtYnJlXCIuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IC9EW29EXT8oXFxzKStNTU1NLyxcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdnZW4uX2ZlYnIuX21hcsOnX2Fici5fbWFpZ19qdW55X2p1bC5fYWcuX3NldC5fb2N0Ll9ub3YuX2Rlcy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnZGl1bWVuZ2VfZGlsbHVuc19kaW1hcnRzX2RpbWVjcmVzX2Rpam91c19kaXZlbmRyZXNfZGlzc2FidGUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdkZy5fZGwuX2R0Ll9kYy5fZGouX2R2Ll9kcy4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnZGdfZGxfZHRfZGNfZGpfZHZfZHMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgICAgICBsbDogJ0QgTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFtkZV0gWVlZWSBbYSBsZXNdIEg6bW0nLFxuICAgICAgICAgICAgbGxsOiAnRCBNTU0gWVlZWSwgSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCBEIE1NTU0gW2RlXSBZWVlZIFthIGxlc10gSDptbScsXG4gICAgICAgICAgICBsbGxsOiAnZGRkIEQgTU1NIFlZWVksIEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2F2dWkgYSAnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICdsZXMnIDogJ2xhJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dERheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2RlbcOgIGEgJyArICh0aGlzLmhvdXJzKCkgIT09IDEgPyAnbGVzJyA6ICdsYScpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdkZGRkIFthICcgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ2xlcycgOiAnbGEnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbYWhpciBhICcgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ2xlcycgOiAnbGEnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICdbZWxdIGRkZGQgW3Bhc3NhdCBhICcgK1xuICAgICAgICAgICAgICAgICAgICAodGhpcy5ob3VycygpICE9PSAxID8gJ2xlcycgOiAnbGEnKSArXG4gICAgICAgICAgICAgICAgICAgICddIExUJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6IFwiZCdhcXXDrSAlc1wiLFxuICAgICAgICAgICAgcGFzdDogJ2ZhICVzJyxcbiAgICAgICAgICAgIHM6ICd1bnMgc2Vnb25zJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vnb25zJyxcbiAgICAgICAgICAgIG06ICd1biBtaW51dCcsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0cycsXG4gICAgICAgICAgICBoOiAndW5hIGhvcmEnLFxuICAgICAgICAgICAgaGg6ICclZCBob3JlcycsXG4gICAgICAgICAgICBkOiAndW4gZGlhJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGllcycsXG4gICAgICAgICAgICBNOiAndW4gbWVzJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWVzb3MnLFxuICAgICAgICAgICAgeTogJ3VuIGFueScsXG4gICAgICAgICAgICB5eTogJyVkIGFueXMnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0ocnxufHR8w6h8YSkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPVxuICAgICAgICAgICAgICAgIG51bWJlciA9PT0gMVxuICAgICAgICAgICAgICAgICAgICA/ICdyJ1xuICAgICAgICAgICAgICAgICAgICA6IG51bWJlciA9PT0gMlxuICAgICAgICAgICAgICAgICAgICA/ICduJ1xuICAgICAgICAgICAgICAgICAgICA6IG51bWJlciA9PT0gM1xuICAgICAgICAgICAgICAgICAgICA/ICdyJ1xuICAgICAgICAgICAgICAgICAgICA6IG51bWJlciA9PT0gNFxuICAgICAgICAgICAgICAgICAgICA/ICd0J1xuICAgICAgICAgICAgICAgICAgICA6ICfDqCc7XG4gICAgICAgICAgICBpZiAocGVyaW9kID09PSAndycgfHwgcGVyaW9kID09PSAnVycpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAnYSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzJDQgPSAnbGVkZW5fw7pub3JfYsWZZXplbl9kdWJlbl9rdsSbdGVuX8SNZXJ2ZW5fxI1lcnZlbmVjX3NycGVuX3rDocWZw61fxZnDrWplbl9saXN0b3BhZF9wcm9zaW5lYycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQgPSAnbGVkX8O6bm9fYsWZZV9kdWJfa3bEm1/EjXZuX8SNdmNfc3JwX3rDocWZX8WZw61qX2xpc19wcm8nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlJDEgPSBbXG4gICAgICAgICAgICAvXmxlZC9pLFxuICAgICAgICAgICAgL17Dum5vL2ksXG4gICAgICAgICAgICAvXmLFmWUvaSxcbiAgICAgICAgICAgIC9eZHViL2ksXG4gICAgICAgICAgICAvXmt2xJsvaSxcbiAgICAgICAgICAgIC9eKMSNdm58xI1lcnZlbiR8xI1lcnZuYSkvaSxcbiAgICAgICAgICAgIC9eKMSNdmN8xI1lcnZlbmVjfMSNZXJ2ZW5jZSkvaSxcbiAgICAgICAgICAgIC9ec3JwL2ksXG4gICAgICAgICAgICAvXnrDocWZL2ksXG4gICAgICAgICAgICAvXsWZw61qL2ksXG4gICAgICAgICAgICAvXmxpcy9pLFxuICAgICAgICAgICAgL15wcm8vaSxcbiAgICAgICAgXSxcbiAgICAgICAgLy8gTk9URTogJ8SNZXJ2ZW4nIGlzIHN1YnN0cmluZyBvZiAnxI1lcnZlbmVjJzsgdGhlcmVmb3JlICfEjWVydmVuZWMnIG11c3QgcHJlY2VkZSAnxI1lcnZlbicgaW4gdGhlIHJlZ2V4IHRvIGJlIGZ1bGx5IG1hdGNoZWQuXG4gICAgICAgIC8vIE90aGVyd2lzZSBwYXJzZXIgbWF0Y2hlcyAnMS4gxI1lcnZlbmVjJyBhcyAnMS4gxI1lcnZlbicgKyAnZWMnLlxuICAgICAgICBtb250aHNSZWdleCQyID0gL14obGVkZW58w7pub3J8YsWZZXplbnxkdWJlbnxrdsSbdGVufMSNZXJ2ZW5lY3zEjWVydmVuY2V8xI1lcnZlbnzEjWVydm5hfHNycGVufHrDocWZw618xZnDrWplbnxsaXN0b3BhZHxwcm9zaW5lY3xsZWR8w7pub3xixZllfGR1YnxrdsSbfMSNdm58xI12Y3xzcnB8esOhxZl8xZnDrWp8bGlzfHBybykvaTtcblxuICAgIGZ1bmN0aW9uIHBsdXJhbCQxKG4pIHtcbiAgICAgICAgcmV0dXJuIG4gPiAxICYmIG4gPCA1ICYmIH5+KG4gLyAxMCkgIT09IDE7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZSQxKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAncyc6IC8vIGEgZmV3IHNlY29uZHMgLyBpbiBhIGZldyBzZWNvbmRzIC8gYSBmZXcgc2Vjb25kcyBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdww6FyIHNla3VuZCcgOiAncMOhciBzZWt1bmRhbWknO1xuICAgICAgICAgICAgY2FzZSAnc3MnOiAvLyA5IHNlY29uZHMgLyBpbiA5IHNlY29uZHMgLyA5IHNlY29uZHMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ3Nla3VuZHknIDogJ3Nla3VuZCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnc2VrdW5kYW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlICdtJzogLy8gYSBtaW51dGUgLyBpbiBhIG1pbnV0ZSAvIGEgbWludXRlIGFnb1xuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ21pbnV0YScgOiBpc0Z1dHVyZSA/ICdtaW51dHUnIDogJ21pbnV0b3UnO1xuICAgICAgICAgICAgY2FzZSAnbW0nOiAvLyA5IG1pbnV0ZXMgLyBpbiA5IG1pbnV0ZXMgLyA5IG1pbnV0ZXMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ21pbnV0eScgOiAnbWludXQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ21pbnV0YW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlICdoJzogLy8gYW4gaG91ciAvIGluIGFuIGhvdXIgLyBhbiBob3VyIGFnb1xuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2hvZGluYScgOiBpc0Z1dHVyZSA/ICdob2RpbnUnIDogJ2hvZGlub3UnO1xuICAgICAgICAgICAgY2FzZSAnaGgnOiAvLyA5IGhvdXJzIC8gaW4gOSBob3VycyAvIDkgaG91cnMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ2hvZGlueScgOiAnaG9kaW4nKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2hvZGluYW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlICdkJzogLy8gYSBkYXkgLyBpbiBhIGRheSAvIGEgZGF5IGFnb1xuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2RlbicgOiAnZG5lbSc7XG4gICAgICAgICAgICBjYXNlICdkZCc6IC8vIDkgZGF5cyAvIGluIDkgZGF5cyAvIDkgZGF5cyBhZ29cbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQxKG51bWJlcikgPyAnZG55JyA6ICdkbsOtJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdkbnknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgJ00nOiAvLyBhIG1vbnRoIC8gaW4gYSBtb250aCAvIGEgbW9udGggYWdvXG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbcSbc8OtYycgOiAnbcSbc8OtY2VtJztcbiAgICAgICAgICAgIGNhc2UgJ01NJzogLy8gOSBtb250aHMgLyBpbiA5IG1vbnRocyAvIDkgbW9udGhzIGFnb1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDEobnVtYmVyKSA/ICdtxJtzw61jZScgOiAnbcSbc8OtY8WvJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdtxJtzw61jaSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSAneSc6IC8vIGEgeWVhciAvIGluIGEgeWVhciAvIGEgeWVhciBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdyb2snIDogJ3Jva2VtJztcbiAgICAgICAgICAgIGNhc2UgJ3l5JzogLy8gOSB5ZWFycyAvIGluIDkgeWVhcnMgLyA5IHllYXJzIGFnb1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDEobnVtYmVyKSA/ICdyb2t5JyA6ICdsZXQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2xldHknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnY3MnLCB7XG4gICAgICAgIG1vbnRoczogbW9udGhzJDQsXG4gICAgICAgIG1vbnRoc1Nob3J0OiBtb250aHNTaG9ydCxcbiAgICAgICAgbW9udGhzUmVnZXg6IG1vbnRoc1JlZ2V4JDIsXG4gICAgICAgIG1vbnRoc1Nob3J0UmVnZXg6IG1vbnRoc1JlZ2V4JDIsXG4gICAgICAgIC8vIE5PVEU6ICfEjWVydmVuJyBpcyBzdWJzdHJpbmcgb2YgJ8SNZXJ2ZW5lYyc7IHRoZXJlZm9yZSAnxI1lcnZlbmVjJyBtdXN0IHByZWNlZGUgJ8SNZXJ2ZW4nIGluIHRoZSByZWdleCB0byBiZSBmdWxseSBtYXRjaGVkLlxuICAgICAgICAvLyBPdGhlcndpc2UgcGFyc2VyIG1hdGNoZXMgJzEuIMSNZXJ2ZW5lYycgYXMgJzEuIMSNZXJ2ZW4nICsgJ2VjJy5cbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGxlZGVufGxlZG5hfMO6bm9yYXzDum5vcnxixZllemVufGLFmWV6bmF8ZHViZW58ZHVibmF8a3bEm3RlbnxrdsSbdG5hfMSNZXJ2ZW5lY3zEjWVydmVuY2V8xI1lcnZlbnzEjWVydm5hfHNycGVufHNycG5hfHrDocWZw618xZnDrWplbnzFmcOtam5hfGxpc3RvcGFkdXxsaXN0b3BhZHxwcm9zaW5lY3xwcm9zaW5jZSkvaSxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14obGVkfMO6bm98YsWZZXxkdWJ8a3bEm3zEjXZufMSNdmN8c3JwfHrDocWZfMWZw61qfGxpc3xwcm8pL2ksXG4gICAgICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQxLFxuICAgICAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDEsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDEsXG4gICAgICAgIHdlZWtkYXlzOiAnbmVkxJtsZV9wb25kxJtsw61fw7p0ZXLDvV9zdMWZZWRhX8SNdHZydGVrX3DDoXRla19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICduZV9wb1/DunRfc3RfxI10X3DDoV9zbycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICduZV9wb1/DunRfc3RfxI10X3DDoV9zbycuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIGw6ICdELiBNLiBZWVlZJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbZG5lcyB2XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW3rDrXRyYSB2XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IG5lZMSbbGkgdl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIGRkZGQgW3ZdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdmUgc3TFmWVkdSB2XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZlIMSNdHZydGVrIHZdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBww6F0ZWsgdl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IHNvYm90dSB2XSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbdsSNZXJhIHZdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsb3UgbmVkxJtsaSB2XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDqV0gZGRkZCBbdl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bG91IHN0xZllZHUgdl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw71dIGRkZGQgW3ZdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWxvdSBzb2JvdHUgdl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ3phICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICdwxZllZCAlcycsXG4gICAgICAgICAgICBzOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgICAgIHNzOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgICAgIG06IHRyYW5zbGF0ZSQxLFxuICAgICAgICAgICAgbW06IHRyYW5zbGF0ZSQxLFxuICAgICAgICAgICAgaDogdHJhbnNsYXRlJDEsXG4gICAgICAgICAgICBoaDogdHJhbnNsYXRlJDEsXG4gICAgICAgICAgICBkOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgICAgIGRkOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgICAgIE06IHRyYW5zbGF0ZSQxLFxuICAgICAgICAgICAgTU06IHRyYW5zbGF0ZSQxLFxuICAgICAgICAgICAgeTogdHJhbnNsYXRlJDEsXG4gICAgICAgICAgICB5eTogdHJhbnNsYXRlJDEsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2N2Jywge1xuICAgICAgICBtb250aHM6ICfQutOR0YDQu9Cw0Ydf0L3QsNGA05HRgV/Qv9GD0Yhf0LDQutCwX9C80LDQuV/Sq9OX0YDRgtC80LVf0YPRgtORX9Kr0YPRgNC70LBf0LDQstOR0L1f0Y7Qv9CwX9GH07PQul/RgNCw0YjRgtCw0LInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn0LrTkdGAX9C90LDRgF/Qv9GD0Yhf0LDQutCwX9C80LDQuV/Sq9OX0YBf0YPRgtORX9Kr0YPRgF/QsNCy0L1f0Y7Qv9CwX9GH07PQul/RgNCw0YgnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAn0LLRi9GA0YHQsNGA0L3QuNC60YPQvV/RgtGD0L3RgtC40LrRg9C9X9GL0YLQu9Cw0YDQuNC60YPQvV/RjtC90LrRg9C9X9C605fSq9C90LXRgNC90LjQutGD0L1f0Y3RgNC90LXQutGD0L1f0YjTkdC80LDRgtC60YPQvScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9Cy0YvRgF/RgtGD0L1f0YvRgtC7X9GO0L1f0LrTl9KrX9GN0YDQvV/RiNOR0LwnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn0LLRgF/RgtC9X9GL0YJf0Y7QvV/QutKrX9GN0YBf0YjQvCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELU1NLVlZWVknLFxuICAgICAgICAgICAgTEw6ICdZWVlZIFvSq9GD0LvRhdC4XSBNTU1NIFvRg9C505HRhdOX0L1dIERbLdC805fRiNOXXScsXG4gICAgICAgICAgICBMTEw6ICdZWVlZIFvSq9GD0LvRhdC4XSBNTU1NIFvRg9C505HRhdOX0L1dIERbLdC805fRiNOXXSwgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIFlZWVkgW9Kr0YPQu9GF0LhdIE1NTU0gW9GD0LnTkdGF05fQvV0gRFst0LzTl9GI05ddLCBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9Cf0LDRj9C9XSBMVCBb0YHQtdGF0LXRgtGA0LVdJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb0KvRgNCw0L1dIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1vTltC90LXRgF0gTFQgW9GB0LXRhdC10YLRgNC1XScsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1vSqtC40YLQtdGBXSBkZGRkIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdb0JjRgNGC0L3Tl10gZGRkZCBMVCBb0YHQtdGF0LXRgtGA0LVdJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiBmdW5jdGlvbiAob3V0cHV0KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFmZml4ID0gL9GB0LXRhdC10YIkL2kuZXhlYyhvdXRwdXQpXG4gICAgICAgICAgICAgICAgICAgID8gJ9GA0LXQvSdcbiAgICAgICAgICAgICAgICAgICAgOiAv0qvRg9C7JC9pLmV4ZWMob3V0cHV0KVxuICAgICAgICAgICAgICAgICAgICA/ICfRgtCw0L0nXG4gICAgICAgICAgICAgICAgICAgIDogJ9GA0LDQvSc7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dCArIGFmZml4O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDQutCw0Y/Qu9C70LAnLFxuICAgICAgICAgICAgczogJ9C/05fRgC3QuNC6INKr0LXQutC60YPQvdGCJyxcbiAgICAgICAgICAgIHNzOiAnJWQg0qvQtdC60LrRg9C90YInLFxuICAgICAgICAgICAgbTogJ9C/05fRgCDQvNC40L3Rg9GCJyxcbiAgICAgICAgICAgIG1tOiAnJWQg0LzQuNC90YPRgicsXG4gICAgICAgICAgICBoOiAn0L/Tl9GAINGB0LXRhdC10YInLFxuICAgICAgICAgICAgaGg6ICclZCDRgdC10YXQtdGCJyxcbiAgICAgICAgICAgIGQ6ICfQv9OX0YAg0LrRg9C9JyxcbiAgICAgICAgICAgIGRkOiAnJWQg0LrRg9C9JyxcbiAgICAgICAgICAgIE06ICfQv9OX0YAg0YPQudOR0YUnLFxuICAgICAgICAgICAgTU06ICclZCDRg9C505HRhScsXG4gICAgICAgICAgICB5OiAn0L/Tl9GAINKr0YPQuycsXG4gICAgICAgICAgICB5eTogJyVkINKr0YPQuycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS3QvNOX0YgvLFxuICAgICAgICBvcmRpbmFsOiAnJWQt0LzTl9GIJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNywgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdjeScsIHtcbiAgICAgICAgbW9udGhzOiAnSW9uYXdyX0Nod2Vmcm9yX01hd3J0aF9FYnJpbGxfTWFpX01laGVmaW5fR29yZmZlbm5hZl9Bd3N0X01lZGlfSHlkcmVmX1RhY2h3ZWRkX1JoYWdmeXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSW9uX0Nod2VfTWF3X0Vicl9NYWlfTWVoX0dvcl9Bd3NfTWVkX0h5ZF9UYWNoX1JoYWcnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzOiAnRHlkZCBTdWxfRHlkZCBMbHVuX0R5ZGQgTWF3cnRoX0R5ZGQgTWVyY2hlcl9EeWRkIElhdV9EeWRkIEd3ZW5lcl9EeWRkIFNhZHdybicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ1N1bF9MbHVuX01hd19NZXJfSWF1X0d3ZV9TYWQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU3VfTGxfTWFfTWVfSWFfR3dfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgLy8gdGltZSBmb3JtYXRzIGFyZSB0aGUgc2FtZSBhcyBlbi1nYlxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0hlZGRpdyBhbV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tZZm9yeSBhbV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFthbV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tEZG9lIGFtXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW2Rpd2V0aGFmIGFtXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ21ld24gJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIHluIMO0bCcsXG4gICAgICAgICAgICBzOiAneWNoeWRpZyBlaWxpYWRhdScsXG4gICAgICAgICAgICBzczogJyVkIGVpbGlhZCcsXG4gICAgICAgICAgICBtOiAnbXVudWQnLFxuICAgICAgICAgICAgbW06ICclZCBtdW51ZCcsXG4gICAgICAgICAgICBoOiAnYXdyJyxcbiAgICAgICAgICAgIGhoOiAnJWQgYXdyJyxcbiAgICAgICAgICAgIGQ6ICdkaXdybm9kJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGl3cm5vZCcsXG4gICAgICAgICAgICBNOiAnbWlzJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWlzJyxcbiAgICAgICAgICAgIHk6ICdibHd5ZGR5bicsXG4gICAgICAgICAgICB5eTogJyVkIGZseW5lZGQnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZmVkfGFpbnxhZnxpbHx5ZGR8ZWR8ZWcpLyxcbiAgICAgICAgLy8gdHJhZGl0aW9uYWwgb3JkaW5hbCBudW1iZXJzIGFib3ZlIDMxIGFyZSBub3QgY29tbW9ubHkgdXNlZCBpbiBjb2xsb3F1aWFsIFdlbHNoXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyLFxuICAgICAgICAgICAgICAgIG91dHB1dCA9ICcnLFxuICAgICAgICAgICAgICAgIGxvb2t1cCA9IFtcbiAgICAgICAgICAgICAgICAgICAgJycsXG4gICAgICAgICAgICAgICAgICAgICdhZicsXG4gICAgICAgICAgICAgICAgICAgICdpbCcsXG4gICAgICAgICAgICAgICAgICAgICd5ZGQnLFxuICAgICAgICAgICAgICAgICAgICAneWRkJyxcbiAgICAgICAgICAgICAgICAgICAgJ2VkJyxcbiAgICAgICAgICAgICAgICAgICAgJ2VkJyxcbiAgICAgICAgICAgICAgICAgICAgJ2VkJyxcbiAgICAgICAgICAgICAgICAgICAgJ2ZlZCcsXG4gICAgICAgICAgICAgICAgICAgICdmZWQnLFxuICAgICAgICAgICAgICAgICAgICAnZmVkJywgLy8gMWFmIHRvIDEwZmVkXG4gICAgICAgICAgICAgICAgICAgICdlZycsXG4gICAgICAgICAgICAgICAgICAgICdmZWQnLFxuICAgICAgICAgICAgICAgICAgICAnZWcnLFxuICAgICAgICAgICAgICAgICAgICAnZWcnLFxuICAgICAgICAgICAgICAgICAgICAnZmVkJyxcbiAgICAgICAgICAgICAgICAgICAgJ2VnJyxcbiAgICAgICAgICAgICAgICAgICAgJ2VnJyxcbiAgICAgICAgICAgICAgICAgICAgJ2ZlZCcsXG4gICAgICAgICAgICAgICAgICAgICdlZycsXG4gICAgICAgICAgICAgICAgICAgICdmZWQnLCAvLyAxMWVnIHRvIDIwZmVkXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGlmIChiID4gMjApIHtcbiAgICAgICAgICAgICAgICBpZiAoYiA9PT0gNDAgfHwgYiA9PT0gNTAgfHwgYiA9PT0gNjAgfHwgYiA9PT0gODAgfHwgYiA9PT0gMTAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dCA9ICdmZWQnOyAvLyBub3QgMzBhaW4sIDcwYWluIG9yIDkwYWluXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gJ2Fpbic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChiID4gMCkge1xuICAgICAgICAgICAgICAgIG91dHB1dCA9IGxvb2t1cFtiXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZGEnLCB7XG4gICAgICAgIG1vbnRoczogJ2phbnVhcl9mZWJydWFyX21hcnRzX2FwcmlsX21hal9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2phbl9mZWJfbWFyX2Fwcl9tYWpfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ3PDuG5kYWdfbWFuZGFnX3RpcnNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2zDuHJkYWcnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdzw7huX21hbl90aXJfb25zX3Rvcl9mcmVfbMO4cicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdzw7hfbWFfdGlfb25fdG9fZnJfbMO4Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgW2QuXSBELiBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tpIGRhZyBrbC5dIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbaSBtb3JnZW4ga2wuXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ3DDpSBkZGRkIFtrbC5dIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbaSBnw6VyIGtsLl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbaV0gZGRkZFtzIGtsLl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdvbSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgc2lkZW4nLFxuICAgICAgICAgICAgczogJ2bDpSBzZWt1bmRlcicsXG4gICAgICAgICAgICBzczogJyVkIHNla3VuZGVyJyxcbiAgICAgICAgICAgIG06ICdldCBtaW51dCcsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0dGVyJyxcbiAgICAgICAgICAgIGg6ICdlbiB0aW1lJyxcbiAgICAgICAgICAgIGhoOiAnJWQgdGltZXInLFxuICAgICAgICAgICAgZDogJ2VuIGRhZycsXG4gICAgICAgICAgICBkZDogJyVkIGRhZ2UnLFxuICAgICAgICAgICAgTTogJ2VuIG3DpW5lZCcsXG4gICAgICAgICAgICBNTTogJyVkIG3DpW5lZGVyJyxcbiAgICAgICAgICAgIHk6ICdldCDDpXInLFxuICAgICAgICAgICAgeXk6ICclZCDDpXInLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgICAgIG06IFsnZWluZSBNaW51dGUnLCAnZWluZXIgTWludXRlJ10sXG4gICAgICAgICAgICBoOiBbJ2VpbmUgU3R1bmRlJywgJ2VpbmVyIFN0dW5kZSddLFxuICAgICAgICAgICAgZDogWydlaW4gVGFnJywgJ2VpbmVtIFRhZyddLFxuICAgICAgICAgICAgZGQ6IFtudW1iZXIgKyAnIFRhZ2UnLCBudW1iZXIgKyAnIFRhZ2VuJ10sXG4gICAgICAgICAgICB3OiBbJ2VpbmUgV29jaGUnLCAnZWluZXIgV29jaGUnXSxcbiAgICAgICAgICAgIE06IFsnZWluIE1vbmF0JywgJ2VpbmVtIE1vbmF0J10sXG4gICAgICAgICAgICBNTTogW251bWJlciArICcgTW9uYXRlJywgbnVtYmVyICsgJyBNb25hdGVuJ10sXG4gICAgICAgICAgICB5OiBbJ2VpbiBKYWhyJywgJ2VpbmVtIEphaHInXSxcbiAgICAgICAgICAgIHl5OiBbbnVtYmVyICsgJyBKYWhyZScsIG51bWJlciArICcgSmFocmVuJ10sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gZm9ybWF0W2tleV1bMF0gOiBmb3JtYXRba2V5XVsxXTtcbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2RlLWF0Jywge1xuICAgICAgICBtb250aHM6ICdKw6RubmVyX0ZlYnJ1YXJfTcOkcnpfQXByaWxfTWFpX0p1bmlfSnVsaV9BdWd1c3RfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGV6ZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSsOkbi5fRmViLl9Nw6Ryel9BcHIuX01haV9KdW5pX0p1bGlfQXVnLl9TZXAuX09rdC5fTm92Ll9EZXouJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ1Nvbm50YWdfTW9udGFnX0RpZW5zdGFnX01pdHR3b2NoX0Rvbm5lcnN0YWdfRnJlaXRhZ19TYW1zdGFnJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnU28uX01vLl9EaS5fTWkuX0RvLl9Gci5fU2EuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1NvX01vX0RpX01pX0RvX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbaGV1dGUgdW1dIExUIFtVaHJdJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1tnZXN0ZXJuIHVtXSBMVCBbVWhyXScsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tsZXR6dGVuXSBkZGRkIFt1bV0gTFQgW1Vocl0nLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICd2b3IgJXMnLFxuICAgICAgICAgICAgczogJ2VpbiBwYWFyIFNla3VuZGVuJyxcbiAgICAgICAgICAgIHNzOiAnJWQgU2VrdW5kZW4nLFxuICAgICAgICAgICAgbTogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgICAgIG1tOiAnJWQgTWludXRlbicsXG4gICAgICAgICAgICBoOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICAgICAgaGg6ICclZCBTdHVuZGVuJyxcbiAgICAgICAgICAgIGQ6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgICAgICBkZDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgICAgIHc6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgICAgICB3dzogJyVkIFdvY2hlbicsXG4gICAgICAgICAgICBNOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICAgICAgTU06IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgICAgICB5OiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICAgICAgeXk6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lJDEobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICBtOiBbJ2VpbmUgTWludXRlJywgJ2VpbmVyIE1pbnV0ZSddLFxuICAgICAgICAgICAgaDogWydlaW5lIFN0dW5kZScsICdlaW5lciBTdHVuZGUnXSxcbiAgICAgICAgICAgIGQ6IFsnZWluIFRhZycsICdlaW5lbSBUYWcnXSxcbiAgICAgICAgICAgIGRkOiBbbnVtYmVyICsgJyBUYWdlJywgbnVtYmVyICsgJyBUYWdlbiddLFxuICAgICAgICAgICAgdzogWydlaW5lIFdvY2hlJywgJ2VpbmVyIFdvY2hlJ10sXG4gICAgICAgICAgICBNOiBbJ2VpbiBNb25hdCcsICdlaW5lbSBNb25hdCddLFxuICAgICAgICAgICAgTU06IFtudW1iZXIgKyAnIE1vbmF0ZScsIG51bWJlciArICcgTW9uYXRlbiddLFxuICAgICAgICAgICAgeTogWydlaW4gSmFocicsICdlaW5lbSBKYWhyJ10sXG4gICAgICAgICAgICB5eTogW251bWJlciArICcgSmFocmUnLCBudW1iZXIgKyAnIEphaHJlbiddLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdkZS1jaCcsIHtcbiAgICAgICAgbW9udGhzOiAnSmFudWFyX0ZlYnJ1YXJfTcOkcnpfQXByaWxfTWFpX0p1bmlfSnVsaV9BdWd1c3RfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGV6ZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuLl9GZWIuX03DpHJ6X0Fwci5fTWFpX0p1bmlfSnVsaV9BdWcuX1NlcC5fT2t0Ll9Ob3YuX0Rlei4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnU29ubnRhZ19Nb250YWdfRGllbnN0YWdfTWl0dHdvY2hfRG9ubmVyc3RhZ19GcmVpdGFnX1NhbXN0YWcnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTb19Nb19EaV9NaV9Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdTb19Nb19EaV9NaV9Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2hldXRlIHVtXSBMVCBbVWhyXScsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICAgICAgbmV4dERheTogJ1ttb3JnZW4gdW1dIExUIFtVaHJdJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbdW1dIExUIFtVaHJdJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbZ2VzdGVybiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbbGV0enRlbl0gZGRkZCBbdW1dIExUIFtVaHJdJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0OiAndm9yICVzJyxcbiAgICAgICAgICAgIHM6ICdlaW4gcGFhciBTZWt1bmRlbicsXG4gICAgICAgICAgICBzczogJyVkIFNla3VuZGVuJyxcbiAgICAgICAgICAgIG06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIG1tOiAnJWQgTWludXRlbicsXG4gICAgICAgICAgICBoOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDEsXG4gICAgICAgICAgICBoaDogJyVkIFN0dW5kZW4nLFxuICAgICAgICAgICAgZDogcHJvY2Vzc1JlbGF0aXZlVGltZSQxLFxuICAgICAgICAgICAgZGQ6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIHc6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIHd3OiAnJWQgV29jaGVuJyxcbiAgICAgICAgICAgIE06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIE1NOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDEsXG4gICAgICAgICAgICB5OiBwcm9jZXNzUmVsYXRpdmVUaW1lJDEsXG4gICAgICAgICAgICB5eTogcHJvY2Vzc1JlbGF0aXZlVGltZSQxLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQyKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgbTogWydlaW5lIE1pbnV0ZScsICdlaW5lciBNaW51dGUnXSxcbiAgICAgICAgICAgIGg6IFsnZWluZSBTdHVuZGUnLCAnZWluZXIgU3R1bmRlJ10sXG4gICAgICAgICAgICBkOiBbJ2VpbiBUYWcnLCAnZWluZW0gVGFnJ10sXG4gICAgICAgICAgICBkZDogW251bWJlciArICcgVGFnZScsIG51bWJlciArICcgVGFnZW4nXSxcbiAgICAgICAgICAgIHc6IFsnZWluZSBXb2NoZScsICdlaW5lciBXb2NoZSddLFxuICAgICAgICAgICAgTTogWydlaW4gTW9uYXQnLCAnZWluZW0gTW9uYXQnXSxcbiAgICAgICAgICAgIE1NOiBbbnVtYmVyICsgJyBNb25hdGUnLCBudW1iZXIgKyAnIE1vbmF0ZW4nXSxcbiAgICAgICAgICAgIHk6IFsnZWluIEphaHInLCAnZWluZW0gSmFociddLFxuICAgICAgICAgICAgeXk6IFtudW1iZXIgKyAnIEphaHJlJywgbnVtYmVyICsgJyBKYWhyZW4nXSxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZGUnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcl9GZWJydWFyX03DpHJ6X0FwcmlsX01haV9KdW5pX0p1bGlfQXVndXN0X1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0RlemVtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ0phbi5fRmViLl9Nw6Ryel9BcHIuX01haV9KdW5pX0p1bGlfQXVnLl9TZXAuX09rdC5fTm92Ll9EZXouJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ1Nvbm50YWdfTW9udGFnX0RpZW5zdGFnX01pdHR3b2NoX0Rvbm5lcnN0YWdfRnJlaXRhZ19TYW1zdGFnJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnU28uX01vLl9EaS5fTWkuX0RvLl9Gci5fU2EuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1NvX01vX0RpX01pX0RvX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbaGV1dGUgdW1dIExUIFtVaHJdJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1tnZXN0ZXJuIHVtXSBMVCBbVWhyXScsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tsZXR6dGVuXSBkZGRkIFt1bV0gTFQgW1Vocl0nLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICd2b3IgJXMnLFxuICAgICAgICAgICAgczogJ2VpbiBwYWFyIFNla3VuZGVuJyxcbiAgICAgICAgICAgIHNzOiAnJWQgU2VrdW5kZW4nLFxuICAgICAgICAgICAgbTogcHJvY2Vzc1JlbGF0aXZlVGltZSQyLFxuICAgICAgICAgICAgbW06ICclZCBNaW51dGVuJyxcbiAgICAgICAgICAgIGg6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMixcbiAgICAgICAgICAgIGhoOiAnJWQgU3R1bmRlbicsXG4gICAgICAgICAgICBkOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIsXG4gICAgICAgICAgICBkZDogcHJvY2Vzc1JlbGF0aXZlVGltZSQyLFxuICAgICAgICAgICAgdzogcHJvY2Vzc1JlbGF0aXZlVGltZSQyLFxuICAgICAgICAgICAgd3c6ICclZCBXb2NoZW4nLFxuICAgICAgICAgICAgTTogcHJvY2Vzc1JlbGF0aXZlVGltZSQyLFxuICAgICAgICAgICAgTU06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMixcbiAgICAgICAgICAgIHk6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMixcbiAgICAgICAgICAgIHl5OiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzJDUgPSBbXG4gICAgICAgICAgICAn3pberN6C3qreh96m3oPeqScsXG4gICAgICAgICAgICAn3orerN6E3rDeg96q3ofept6D3qknLFxuICAgICAgICAgICAgJ96J3qfeg96o3pfeqicsXG4gICAgICAgICAgICAn3oferd6V3rDeg96p3o3eqicsXG4gICAgICAgICAgICAn3onerScsXG4gICAgICAgICAgICAn3pbeq96C3rAnLFxuICAgICAgICAgICAgJ96W3qrejd6m3ofeqCcsXG4gICAgICAgICAgICAn3ofer96O3qbekN6w3pPeqicsXG4gICAgICAgICAgICAn3pDerN6V3rDek96s3onesN6E3qbeg96qJyxcbiAgICAgICAgICAgICfeh96u3obesN6T3q/ehN6m3oPeqicsXG4gICAgICAgICAgICAn3oLert6I3qzeid6w3oTept6D3qonLFxuICAgICAgICAgICAgJ96R3qjekN6s3onesN6E3qbeg96qJyxcbiAgICAgICAgXSxcbiAgICAgICAgd2Vla2RheXMgPSBbXG4gICAgICAgICAgICAn3ofep96L3qjeh96w3ozepicsXG4gICAgICAgICAgICAn3oDer96J3qYnLFxuICAgICAgICAgICAgJ96H3qbegt6w3o7ep96D3qYnLFxuICAgICAgICAgICAgJ96E3qrei96mJyxcbiAgICAgICAgICAgICfehN6q3oPep96Q3rDeit6m3ozeqCcsXG4gICAgICAgICAgICAn3oDeqt6G3qreg96qJyxcbiAgICAgICAgICAgICfegN6u3oLeqN6A3qjeg96qJyxcbiAgICAgICAgXTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZHYnLCB7XG4gICAgICAgIG1vbnRoczogbW9udGhzJDUsXG4gICAgICAgIG1vbnRoc1Nob3J0OiBtb250aHMkNSxcbiAgICAgICAgd2Vla2RheXM6IHdlZWtkYXlzLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiB3ZWVrZGF5cyxcbiAgICAgICAgd2Vla2RheXNNaW46ICfeh96n3oveqF/egN6v3onepl/eh96m3oLesF/ehN6q3ovepl/ehN6q3oPep1/egN6q3obeql/egN6u3oLeqCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0QvTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv3onehnzeid6KLyxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ96J3oonID09PSBpbnB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ96J3oYnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ96J3oonO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1veid6o3ofept6L3qpdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb3onep96L3qbeid6nXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1veh96o3ofesN6U3qxdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW96K3qfeh96o3ozeqt6I3qhdIGRkZGQgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICfejN6s3oPerd6O3qbeh96oICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICfeht6q3oPeqN6C3rAgJXMnLFxuICAgICAgICAgICAgczogJ96Q3qjeht6q3oLesN6M3qreht6u3oXerN6H3rAnLFxuICAgICAgICAgICAgc3M6ICdkJSDekN6o3obeqt6C3rDejN6qJyxcbiAgICAgICAgICAgIG06ICfeid6o3oLeqN6T3qzeh96wJyxcbiAgICAgICAgICAgIG1tOiAn3oneqN6C3qjek96qICVkJyxcbiAgICAgICAgICAgIGg6ICfejt6m3pHeqN6H3qjeg96s3ofesCcsXG4gICAgICAgICAgICBoaDogJ96O3qbekd6o3ofeqN6D3qogJWQnLFxuICAgICAgICAgICAgZDogJ96L3qreiN6m3oDerN6H3rAnLFxuICAgICAgICAgICAgZGQ6ICfei96q3ojept6Q3rAgJWQnLFxuICAgICAgICAgICAgTTogJ96J3qbegN6s3ofesCcsXG4gICAgICAgICAgICBNTTogJ96J3qbekN6wICVkJyxcbiAgICAgICAgICAgIHk6ICfeh96m3oDept6D3qzeh96wJyxcbiAgICAgICAgICAgIHl5OiAn3ofept6A3qbeg96qICVkJyxcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDcsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiAxMiwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMTJ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIGlzRnVuY3Rpb24kMShpbnB1dCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgKHR5cGVvZiBGdW5jdGlvbiAhPT0gJ3VuZGVmaW5lZCcgJiYgaW5wdXQgaW5zdGFuY2VvZiBGdW5jdGlvbikgfHxcbiAgICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSdcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2VsJywge1xuICAgICAgICBtb250aHNOb21pbmF0aXZlRWw6ICfOmc6xzr3Ov8+FzqzPgc65zr/Pgl/Ops61zrLPgc6/z4XOrM+BzrnOv8+CX86czqzPgc+EzrnOv8+CX86Rz4DPgc6vzrvOuc6/z4JfzpzOrM65zr/Pgl/Omc6/z43Ovc65zr/Pgl/Omc6/z43Ou865zr/Pgl/Okc+NzrPOv8+Fz4PPhM6/z4JfzqPOtc+Az4TOrc68zrLPgc65zr/Pgl/On866z4TPjs6yz4HOuc6/z4Jfzp3Ov86tzrzOss+BzrnOv8+CX86UzrXOus6tzrzOss+BzrnOv8+CJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNHZW5pdGl2ZUVsOiAnzpnOsc69zr/Phc6xz4HOr86/z4VfzqbOtc6yz4HOv8+FzrHPgc6vzr/PhV/OnM6xz4HPhM6vzr/PhV/Okc+Az4HOuc67zq/Ov8+FX86czrHOkM6/z4VfzpnOv8+Fzr3Or86/z4VfzpnOv8+FzrvOr86/z4VfzpHPhc6zzr/Pjc+Dz4TOv8+FX86jzrXPgM+EzrXOvM6yz4HOr86/z4Vfzp/Ous+Ez4nOss+Bzq/Ov8+FX86dzr/Otc68zrLPgc6vzr/PhV/OlM61zrrOtc68zrLPgc6vzr/PhScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzOiBmdW5jdGlvbiAobW9tZW50VG9Gb3JtYXQsIGZvcm1hdCkge1xuICAgICAgICAgICAgaWYgKCFtb21lbnRUb0Zvcm1hdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNOb21pbmF0aXZlRWw7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgICAgIHR5cGVvZiBmb3JtYXQgPT09ICdzdHJpbmcnICYmXG4gICAgICAgICAgICAgICAgL0QvLnRlc3QoZm9ybWF0LnN1YnN0cmluZygwLCBmb3JtYXQuaW5kZXhPZignTU1NTScpKSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIC8vIGlmIHRoZXJlIGlzIGEgZGF5IG51bWJlciBiZWZvcmUgJ01NTU0nXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21vbnRoc0dlbml0aXZlRWxbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNOb21pbmF0aXZlRWxbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnzpnOsc69X86mzrXOsl/OnM6xz4FfzpHPgM+BX86czrHPil/Omc6/z4XOvV/Omc6/z4XOu1/Okc+FzrNfzqPOtc+AX86fzrrPhF/Onc6/zrVfzpTOtc66Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ86az4XPgc65zrHOus6uX86UzrXPhc+Ezq3Pgc6xX86kz4HOr8+EzrdfzqTOtc+EzqzPgc+EzrdfzqDOrc68z4DPhM63X86gzrHPgc6xz4POus61z4XOrl/Oo86szrLOss6xz4TOvycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ86az4XPgV/OlM61z4VfzqTPgc65X86kzrXPhF/OoM61zrxfzqDOsc+BX86jzrHOsicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfOms+FX86UzrVfzqTPgV/OpM61X86gzrVfzqDOsV/Oo86xJy5zcGxpdCgnXycpLFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ868zrwnIDogJ86czpwnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfPgM68JyA6ICfOoM6cJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gKGlucHV0ICsgJycpLnRvTG93ZXJDYXNlKClbMF0gPT09ICfOvCc7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9bzqDOnF1cXC4/zpw/XFwuPy9pLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdoOm1tIEEnLFxuICAgICAgICAgICAgTFRTOiAnaDptbTpzcyBBJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhckVsOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW86jzq7OvM61z4HOsSB7fV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vOkc+Nz4HOuc6/IHt9XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3t9XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW86nzrjOtc+CIHt9XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vPhM6/IM+Az4HOv863zrPOv8+NzrzOtc69zr9dIGRkZGQgW3t9XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vPhM63zr0gz4DPgc6/zrfOs86/z43OvM61zr3Ot10gZGRkZCBbe31dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IGZ1bmN0aW9uIChrZXksIG1vbSkge1xuICAgICAgICAgICAgdmFyIG91dHB1dCA9IHRoaXMuX2NhbGVuZGFyRWxba2V5XSxcbiAgICAgICAgICAgICAgICBob3VycyA9IG1vbSAmJiBtb20uaG91cnMoKTtcbiAgICAgICAgICAgIGlmIChpc0Z1bmN0aW9uJDEob3V0cHV0KSkge1xuICAgICAgICAgICAgICAgIG91dHB1dCA9IG91dHB1dC5hcHBseShtb20pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5yZXBsYWNlKCd7fScsIGhvdXJzICUgMTIgPT09IDEgPyAnz4PPhM63JyA6ICfPg8+EzrnPgicpO1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ8+DzrUgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIM+Az4HOuc69JyxcbiAgICAgICAgICAgIHM6ICfOu86vzrPOsSDOtM61z4XPhM61z4HPjM67zrXPgM+EzrEnLFxuICAgICAgICAgICAgc3M6ICclZCDOtM61z4XPhM61z4HPjM67zrXPgM+EzrEnLFxuICAgICAgICAgICAgbTogJ86tzr3OsSDOu861z4DPhM+MJyxcbiAgICAgICAgICAgIG1tOiAnJWQgzrvOtc+Az4TOrCcsXG4gICAgICAgICAgICBoOiAnzrzOr86xIM+Oz4HOsScsXG4gICAgICAgICAgICBoaDogJyVkIM+Oz4HOtc+CJyxcbiAgICAgICAgICAgIGQ6ICfOvM6vzrEgzrzOrc+BzrEnLFxuICAgICAgICAgICAgZGQ6ICclZCDOvM6tz4HOtc+CJyxcbiAgICAgICAgICAgIE06ICfOrc69zrHPgiDOvM6uzr3Osc+CJyxcbiAgICAgICAgICAgIE1NOiAnJWQgzrzOrs69zrXPgicsXG4gICAgICAgICAgICB5OiAnzq3Ovc6xz4Igz4fPgc+Mzr3Ov8+CJyxcbiAgICAgICAgICAgIHl5OiAnJWQgz4fPgc+Mzr3Ouc6xJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9zrcvLFxuICAgICAgICBvcmRpbmFsOiAnJWTOtycsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDRzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZW4tYXUnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ2g6bW0gQScsXG4gICAgICAgICAgICBMVFM6ICdoOm1tOnNzIEEnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBoOm1tIEEnLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW1RvZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW1RvbW9ycm93IGF0XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW1llc3RlcmRheSBhdF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbTGFzdF0gZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnaW4gJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIGFnbycsXG4gICAgICAgICAgICBzOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgICAgICBzczogJyVkIHNlY29uZHMnLFxuICAgICAgICAgICAgbTogJ2EgbWludXRlJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRlcycsXG4gICAgICAgICAgICBoOiAnYW4gaG91cicsXG4gICAgICAgICAgICBoaDogJyVkIGhvdXJzJyxcbiAgICAgICAgICAgIGQ6ICdhIGRheScsXG4gICAgICAgICAgICBkZDogJyVkIGRheXMnLFxuICAgICAgICAgICAgTTogJ2EgbW9udGgnLFxuICAgICAgICAgICAgTU06ICclZCBtb250aHMnLFxuICAgICAgICAgICAgeTogJ2EgeWVhcicsXG4gICAgICAgICAgICB5eTogJyVkIHllYXJzJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID1cbiAgICAgICAgICAgICAgICAgICAgfn4oKG51bWJlciAlIDEwMCkgLyAxMCkgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3RoJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdzdCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gMlxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnbmQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDNcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3JkJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiAndGgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlbi1jYScsIHtcbiAgICAgICAgbW9udGhzOiAnSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdTdV9Nb19UdV9XZV9UaF9Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnaDptbSBBJyxcbiAgICAgICAgICAgIExUUzogJ2g6bW06c3MgQScsXG4gICAgICAgICAgICBMOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgICAgICBMTDogJ01NTU0gRCwgWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdNTU1NIEQsIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBNTU1NIEQsIFlZWVkgaDptbSBBJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgYWdvJyxcbiAgICAgICAgICAgIHM6ICdhIGZldyBzZWNvbmRzJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vjb25kcycsXG4gICAgICAgICAgICBtOiAnYSBtaW51dGUnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGVzJyxcbiAgICAgICAgICAgIGg6ICdhbiBob3VyJyxcbiAgICAgICAgICAgIGhoOiAnJWQgaG91cnMnLFxuICAgICAgICAgICAgZDogJ2EgZGF5JyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGF5cycsXG4gICAgICAgICAgICBNOiAnYSBtb250aCcsXG4gICAgICAgICAgICBNTTogJyVkIG1vbnRocycsXG4gICAgICAgICAgICB5OiAnYSB5ZWFyJyxcbiAgICAgICAgICAgIHl5OiAnJWQgeWVhcnMnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPVxuICAgICAgICAgICAgICAgICAgICB+figobnVtYmVyICUgMTAwKSAvIDEwKSA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAndGgnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3N0J1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAyXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICduZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gM1xuICAgICAgICAgICAgICAgICAgICAgICAgPyAncmQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6ICd0aCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlbi1nYicsIHtcbiAgICAgICAgbW9udGhzOiAnSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdTdV9Nb19UdV9XZV9UaF9Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tUb21vcnJvdyBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW0xhc3RdIGRkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBhZ28nLFxuICAgICAgICAgICAgczogJ2EgZmV3IHNlY29uZHMnLFxuICAgICAgICAgICAgc3M6ICclZCBzZWNvbmRzJyxcbiAgICAgICAgICAgIG06ICdhIG1pbnV0ZScsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaDogJ2FuIGhvdXInLFxuICAgICAgICAgICAgaGg6ICclZCBob3VycycsXG4gICAgICAgICAgICBkOiAnYSBkYXknLFxuICAgICAgICAgICAgZGQ6ICclZCBkYXlzJyxcbiAgICAgICAgICAgIE06ICdhIG1vbnRoJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbW9udGhzJyxcbiAgICAgICAgICAgIHk6ICdhIHllYXInLFxuICAgICAgICAgICAgeXk6ICclZCB5ZWFycycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdHxuZHxyZHx0aCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIG91dHB1dCA9XG4gICAgICAgICAgICAgICAgICAgIH5+KChudW1iZXIgJSAxMDApIC8gMTApID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICd0aCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnc3QnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDJcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ25kJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAzXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdyZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZW4taWUnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tUb21vcnJvdyBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW0xhc3RdIGRkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBhZ28nLFxuICAgICAgICAgICAgczogJ2EgZmV3IHNlY29uZHMnLFxuICAgICAgICAgICAgc3M6ICclZCBzZWNvbmRzJyxcbiAgICAgICAgICAgIG06ICdhIG1pbnV0ZScsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaDogJ2FuIGhvdXInLFxuICAgICAgICAgICAgaGg6ICclZCBob3VycycsXG4gICAgICAgICAgICBkOiAnYSBkYXknLFxuICAgICAgICAgICAgZGQ6ICclZCBkYXlzJyxcbiAgICAgICAgICAgIE06ICdhIG1vbnRoJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbW9udGhzJyxcbiAgICAgICAgICAgIHk6ICdhIHllYXInLFxuICAgICAgICAgICAgeXk6ICclZCB5ZWFycycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdHxuZHxyZHx0aCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIG91dHB1dCA9XG4gICAgICAgICAgICAgICAgICAgIH5+KChudW1iZXIgJSAxMDApIC8gMTApID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICd0aCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnc3QnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDJcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ25kJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAzXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdyZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZW4taWwnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgYWdvJyxcbiAgICAgICAgICAgIHM6ICdhIGZldyBzZWNvbmRzJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vjb25kcycsXG4gICAgICAgICAgICBtOiAnYSBtaW51dGUnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGVzJyxcbiAgICAgICAgICAgIGg6ICdhbiBob3VyJyxcbiAgICAgICAgICAgIGhoOiAnJWQgaG91cnMnLFxuICAgICAgICAgICAgZDogJ2EgZGF5JyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGF5cycsXG4gICAgICAgICAgICBNOiAnYSBtb250aCcsXG4gICAgICAgICAgICBNTTogJyVkIG1vbnRocycsXG4gICAgICAgICAgICB5OiAnYSB5ZWFyJyxcbiAgICAgICAgICAgIHl5OiAnJWQgeWVhcnMnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPVxuICAgICAgICAgICAgICAgICAgICB+figobnVtYmVyICUgMTAwKSAvIDEwKSA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAndGgnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3N0J1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAyXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICduZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gM1xuICAgICAgICAgICAgICAgICAgICAgICAgPyAncmQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6ICd0aCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlbi1pbicsIHtcbiAgICAgICAgbW9udGhzOiAnSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdTdV9Nb19UdV9XZV9UaF9Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnaDptbSBBJyxcbiAgICAgICAgICAgIExUUzogJ2g6bW06c3MgQScsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgYWdvJyxcbiAgICAgICAgICAgIHM6ICdhIGZldyBzZWNvbmRzJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vjb25kcycsXG4gICAgICAgICAgICBtOiAnYSBtaW51dGUnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGVzJyxcbiAgICAgICAgICAgIGg6ICdhbiBob3VyJyxcbiAgICAgICAgICAgIGhoOiAnJWQgaG91cnMnLFxuICAgICAgICAgICAgZDogJ2EgZGF5JyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGF5cycsXG4gICAgICAgICAgICBNOiAnYSBtb250aCcsXG4gICAgICAgICAgICBNTTogJyVkIG1vbnRocycsXG4gICAgICAgICAgICB5OiAnYSB5ZWFyJyxcbiAgICAgICAgICAgIHl5OiAnJWQgeWVhcnMnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPVxuICAgICAgICAgICAgICAgICAgICB+figobnVtYmVyICUgMTAwKSAvIDEwKSA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAndGgnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3N0J1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAyXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICduZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gM1xuICAgICAgICAgICAgICAgICAgICAgICAgPyAncmQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6ICd0aCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA2LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2VuLW56Jywge1xuICAgICAgICBtb250aHM6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdoOm1tIEEnLFxuICAgICAgICAgICAgTFRTOiAnaDptbTpzcyBBJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tUb21vcnJvdyBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW0xhc3RdIGRkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBhZ28nLFxuICAgICAgICAgICAgczogJ2EgZmV3IHNlY29uZHMnLFxuICAgICAgICAgICAgc3M6ICclZCBzZWNvbmRzJyxcbiAgICAgICAgICAgIG06ICdhIG1pbnV0ZScsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaDogJ2FuIGhvdXInLFxuICAgICAgICAgICAgaGg6ICclZCBob3VycycsXG4gICAgICAgICAgICBkOiAnYSBkYXknLFxuICAgICAgICAgICAgZGQ6ICclZCBkYXlzJyxcbiAgICAgICAgICAgIE06ICdhIG1vbnRoJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbW9udGhzJyxcbiAgICAgICAgICAgIHk6ICdhIHllYXInLFxuICAgICAgICAgICAgeXk6ICclZCB5ZWFycycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdHxuZHxyZHx0aCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIG91dHB1dCA9XG4gICAgICAgICAgICAgICAgICAgIH5+KChudW1iZXIgJSAxMDApIC8gMTApID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICd0aCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnc3QnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDJcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ25kJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAzXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdyZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZW4tc2cnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgYWdvJyxcbiAgICAgICAgICAgIHM6ICdhIGZldyBzZWNvbmRzJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vjb25kcycsXG4gICAgICAgICAgICBtOiAnYSBtaW51dGUnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGVzJyxcbiAgICAgICAgICAgIGg6ICdhbiBob3VyJyxcbiAgICAgICAgICAgIGhoOiAnJWQgaG91cnMnLFxuICAgICAgICAgICAgZDogJ2EgZGF5JyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGF5cycsXG4gICAgICAgICAgICBNOiAnYSBtb250aCcsXG4gICAgICAgICAgICBNTTogJyVkIG1vbnRocycsXG4gICAgICAgICAgICB5OiAnYSB5ZWFyJyxcbiAgICAgICAgICAgIHl5OiAnJWQgeWVhcnMnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPVxuICAgICAgICAgICAgICAgICAgICB+figobnVtYmVyICUgMTAwKSAvIDEwKSA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAndGgnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3N0J1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAyXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICduZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gM1xuICAgICAgICAgICAgICAgICAgICAgICAgPyAncmQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6ICd0aCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2VvJywge1xuICAgICAgICBtb250aHM6ICdqYW51YXJvX2ZlYnJ1YXJvX21hcnRvX2Fwcmlsb19tYWpvX2p1bmlvX2p1bGlvX2HFrWd1c3RvX3NlcHRlbWJyb19va3RvYnJvX25vdmVtYnJvX2RlY2VtYnJvJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2phbl9mZWJfbWFydF9hcHJfbWFqX2p1bl9qdWxfYcWtZ19zZXB0X29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ2RpbWFuxIlvX2x1bmRvX21hcmRvX21lcmtyZWRvX8S1YcWtZG9fdmVuZHJlZG9fc2FiYXRvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnZGltX2x1bl9tYXJkX21lcmtfxLVhxa1fdmVuX3NhYicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdkaV9sdV9tYV9tZV/EtWFfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgICAgIExMOiAnW2xhXSBEWy1hbiBkZV0gTU1NTSwgWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdbbGFdIERbLWFuIGRlXSBNTU1NLCBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkW25dLCBbbGFdIERbLWFuIGRlXSBNTU1NLCBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGw6ICdkZGQsIFtsYV0gRFstYW4gZGVdIE1NTSwgWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9bYXBdXFwudFxcLm0vaSxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQuY2hhckF0KDApLnRvTG93ZXJDYXNlKCkgPT09ICdwJztcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXJzID4gMTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdwLnQubS4nIDogJ1AuVC5NLic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2EudC5tLicgOiAnQS5ULk0uJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSG9kaWHFrSBqZV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tNb3JnYcWtIGplXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGRbbiBqZV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tIaWVyYcWtIGplXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1twYXNpbnRhbl0gZGRkZFtuIGplXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ3Bvc3QgJXMnLFxuICAgICAgICAgICAgcGFzdDogJ2FudGHFrSAlcycsXG4gICAgICAgICAgICBzOiAna2Vsa2FqIHNla3VuZG9qJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2VrdW5kb2onLFxuICAgICAgICAgICAgbTogJ3VudSBtaW51dG8nLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dG9qJyxcbiAgICAgICAgICAgIGg6ICd1bnUgaG9ybycsXG4gICAgICAgICAgICBoaDogJyVkIGhvcm9qJyxcbiAgICAgICAgICAgIGQ6ICd1bnUgdGFnbycsIC8vbmUgJ2RpdXJubycsIMSJYXIgZXN0YXMgdXppdGEgcG9yIHByb2tzaW11bW9cbiAgICAgICAgICAgIGRkOiAnJWQgdGFnb2onLFxuICAgICAgICAgICAgTTogJ3VudSBtb25hdG8nLFxuICAgICAgICAgICAgTU06ICclZCBtb25hdG9qJyxcbiAgICAgICAgICAgIHk6ICd1bnUgamFybycsXG4gICAgICAgICAgICB5eTogJyVkIGphcm9qJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9YS8sXG4gICAgICAgIG9yZGluYWw6ICclZGEnLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA3LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzU2hvcnREb3QgPSAnZW5lLl9mZWIuX21hci5fYWJyLl9tYXkuX2p1bi5fanVsLl9hZ28uX3NlcC5fb2N0Ll9ub3YuX2RpYy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0JDEgPSAnZW5lX2ZlYl9tYXJfYWJyX21heV9qdW5fanVsX2Fnb19zZXBfb2N0X25vdl9kaWMnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlJDIgPSBbXG4gICAgICAgICAgICAvXmVuZS9pLFxuICAgICAgICAgICAgL15mZWIvaSxcbiAgICAgICAgICAgIC9ebWFyL2ksXG4gICAgICAgICAgICAvXmFici9pLFxuICAgICAgICAgICAgL15tYXkvaSxcbiAgICAgICAgICAgIC9eanVuL2ksXG4gICAgICAgICAgICAvXmp1bC9pLFxuICAgICAgICAgICAgL15hZ28vaSxcbiAgICAgICAgICAgIC9ec2VwL2ksXG4gICAgICAgICAgICAvXm9jdC9pLFxuICAgICAgICAgICAgL15ub3YvaSxcbiAgICAgICAgICAgIC9eZGljL2ksXG4gICAgICAgIF0sXG4gICAgICAgIG1vbnRoc1JlZ2V4JDMgPSAvXihlbmVyb3xmZWJyZXJvfG1hcnpvfGFicmlsfG1heW98anVuaW98anVsaW98YWdvc3RvfHNlcHRpZW1icmV8b2N0dWJyZXxub3ZpZW1icmV8ZGljaWVtYnJlfGVuZVxcLj98ZmViXFwuP3xtYXJcXC4/fGFiclxcLj98bWF5XFwuP3xqdW5cXC4/fGp1bFxcLj98YWdvXFwuP3xzZXBcXC4/fG9jdFxcLj98bm92XFwuP3xkaWNcXC4/KS9pO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlcy1kbycsIHtcbiAgICAgICAgbW9udGhzOiAnZW5lcm9fZmVicmVyb19tYXJ6b19hYnJpbF9tYXlvX2p1bmlvX2p1bGlvX2Fnb3N0b19zZXB0aWVtYnJlX29jdHVicmVfbm92aWVtYnJlX2RpY2llbWJyZScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6IGZ1bmN0aW9uIChtLCBmb3JtYXQpIHtcbiAgICAgICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnQkMVttLm1vbnRoKCldO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnREb3RbbS5tb250aCgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzUmVnZXg6IG1vbnRoc1JlZ2V4JDMsXG4gICAgICAgIG1vbnRoc1Nob3J0UmVnZXg6IG1vbnRoc1JlZ2V4JDMsXG4gICAgICAgIG1vbnRoc1N0cmljdFJlZ2V4OiAvXihlbmVyb3xmZWJyZXJvfG1hcnpvfGFicmlsfG1heW98anVuaW98anVsaW98YWdvc3RvfHNlcHRpZW1icmV8b2N0dWJyZXxub3ZpZW1icmV8ZGljaWVtYnJlKS9pLFxuICAgICAgICBtb250aHNTaG9ydFN0cmljdFJlZ2V4OiAvXihlbmVcXC4/fGZlYlxcLj98bWFyXFwuP3xhYnJcXC4/fG1heVxcLj98anVuXFwuP3xqdWxcXC4/fGFnb1xcLj98c2VwXFwuP3xvY3RcXC4/fG5vdlxcLj98ZGljXFwuPykvaSxcbiAgICAgICAgbW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDIsXG4gICAgICAgIGxvbmdNb250aHNQYXJzZTogbW9udGhzUGFyc2UkMixcbiAgICAgICAgc2hvcnRNb250aHNQYXJzZTogbW9udGhzUGFyc2UkMixcbiAgICAgICAgd2Vla2RheXM6ICdkb21pbmdvX2x1bmVzX21hcnRlc19tacOpcmNvbGVzX2p1ZXZlc192aWVybmVzX3PDoWJhZG8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdkb20uX2x1bi5fbWFyLl9tacOpLl9qdWUuX3ZpZS5fc8OhYi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnZG9fbHVfbWFfbWlfanVfdmlfc8OhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ2g6bW0gQScsXG4gICAgICAgICAgICBMVFM6ICdoOm1tOnNzIEEnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZIGg6bW0gQScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIGg6bW0gQScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbaG95IGEgbGEnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXh0RGF5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbbWHDsWFuYSBhIGxhJyArICh0aGlzLmhvdXJzKCkgIT09IDEgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2RkZGQgW2EgbGEnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbYXllciBhIGxhJyArICh0aGlzLmhvdXJzKCkgIT09IDEgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAnW2VsXSBkZGRkIFtwYXNhZG8gYSBsYScgK1xuICAgICAgICAgICAgICAgICAgICAodGhpcy5ob3VycygpICE9PSAxID8gJ3MnIDogJycpICtcbiAgICAgICAgICAgICAgICAgICAgJ10gTFQnXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2VuICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICdoYWNlICVzJyxcbiAgICAgICAgICAgIHM6ICd1bm9zIHNlZ3VuZG9zJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2VndW5kb3MnLFxuICAgICAgICAgICAgbTogJ3VuIG1pbnV0bycsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0b3MnLFxuICAgICAgICAgICAgaDogJ3VuYSBob3JhJyxcbiAgICAgICAgICAgIGhoOiAnJWQgaG9yYXMnLFxuICAgICAgICAgICAgZDogJ3VuIGTDrWEnLFxuICAgICAgICAgICAgZGQ6ICclZCBkw61hcycsXG4gICAgICAgICAgICB3OiAndW5hIHNlbWFuYScsXG4gICAgICAgICAgICB3dzogJyVkIHNlbWFuYXMnLFxuICAgICAgICAgICAgTTogJ3VuIG1lcycsXG4gICAgICAgICAgICBNTTogJyVkIG1lc2VzJyxcbiAgICAgICAgICAgIHk6ICd1biBhw7FvJyxcbiAgICAgICAgICAgIHl5OiAnJWQgYcOxb3MnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn3Cui8sXG4gICAgICAgIG9yZGluYWw6ICclZMK6JyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRoc1Nob3J0RG90JDEgPSAnZW5lLl9mZWIuX21hci5fYWJyLl9tYXkuX2p1bi5fanVsLl9hZ28uX3NlcC5fb2N0Ll9ub3YuX2RpYy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0JDIgPSAnZW5lX2ZlYl9tYXJfYWJyX21heV9qdW5fanVsX2Fnb19zZXBfb2N0X25vdl9kaWMnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlJDMgPSBbXG4gICAgICAgICAgICAvXmVuZS9pLFxuICAgICAgICAgICAgL15mZWIvaSxcbiAgICAgICAgICAgIC9ebWFyL2ksXG4gICAgICAgICAgICAvXmFici9pLFxuICAgICAgICAgICAgL15tYXkvaSxcbiAgICAgICAgICAgIC9eanVuL2ksXG4gICAgICAgICAgICAvXmp1bC9pLFxuICAgICAgICAgICAgL15hZ28vaSxcbiAgICAgICAgICAgIC9ec2VwL2ksXG4gICAgICAgICAgICAvXm9jdC9pLFxuICAgICAgICAgICAgL15ub3YvaSxcbiAgICAgICAgICAgIC9eZGljL2ksXG4gICAgICAgIF0sXG4gICAgICAgIG1vbnRoc1JlZ2V4JDQgPSAvXihlbmVyb3xmZWJyZXJvfG1hcnpvfGFicmlsfG1heW98anVuaW98anVsaW98YWdvc3RvfHNlcHRpZW1icmV8b2N0dWJyZXxub3ZpZW1icmV8ZGljaWVtYnJlfGVuZVxcLj98ZmViXFwuP3xtYXJcXC4/fGFiclxcLj98bWF5XFwuP3xqdW5cXC4/fGp1bFxcLj98YWdvXFwuP3xzZXBcXC4/fG9jdFxcLj98bm92XFwuP3xkaWNcXC4/KS9pO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlcy1teCcsIHtcbiAgICAgICAgbW9udGhzOiAnZW5lcm9fZmVicmVyb19tYXJ6b19hYnJpbF9tYXlvX2p1bmlvX2p1bGlvX2Fnb3N0b19zZXB0aWVtYnJlX29jdHVicmVfbm92aWVtYnJlX2RpY2llbWJyZScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6IGZ1bmN0aW9uIChtLCBmb3JtYXQpIHtcbiAgICAgICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdCQxO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydCQyW20ubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdCQxW20ubW9udGgoKV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1JlZ2V4OiBtb250aHNSZWdleCQ0LFxuICAgICAgICBtb250aHNTaG9ydFJlZ2V4OiBtb250aHNSZWdleCQ0LFxuICAgICAgICBtb250aHNTdHJpY3RSZWdleDogL14oZW5lcm98ZmVicmVyb3xtYXJ6b3xhYnJpbHxtYXlvfGp1bmlvfGp1bGlvfGFnb3N0b3xzZXB0aWVtYnJlfG9jdHVicmV8bm92aWVtYnJlfGRpY2llbWJyZSkvaSxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14oZW5lXFwuP3xmZWJcXC4/fG1hclxcLj98YWJyXFwuP3xtYXlcXC4/fGp1blxcLj98anVsXFwuP3xhZ29cXC4/fHNlcFxcLj98b2N0XFwuP3xub3ZcXC4/fGRpY1xcLj8pL2ksXG4gICAgICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQzLFxuICAgICAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDMsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDMsXG4gICAgICAgIHdlZWtkYXlzOiAnZG9taW5nb19sdW5lc19tYXJ0ZXNfbWnDqXJjb2xlc19qdWV2ZXNfdmllcm5lc19zw6FiYWRvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnZG9tLl9sdW4uX21hci5fbWnDqS5fanVlLl92aWUuX3PDoWIuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ2RvX2x1X21hX21pX2p1X3ZpX3PDoScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgW2RlXSBNTU1NIFtkZV0gWVlZWSBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1tob3kgYSBsYScgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5leHREYXk6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1ttYcOxYW5hIGEgbGEnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZGRkZCBbYSBsYScgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1theWVyIGEgbGEnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICdbZWxdIGRkZGQgW3Bhc2FkbyBhIGxhJyArXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLmhvdXJzKCkgIT09IDEgPyAncycgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAnXSBMVCdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnZW4gJXMnLFxuICAgICAgICAgICAgcGFzdDogJ2hhY2UgJXMnLFxuICAgICAgICAgICAgczogJ3Vub3Mgc2VndW5kb3MnLFxuICAgICAgICAgICAgc3M6ICclZCBzZWd1bmRvcycsXG4gICAgICAgICAgICBtOiAndW4gbWludXRvJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRvcycsXG4gICAgICAgICAgICBoOiAndW5hIGhvcmEnLFxuICAgICAgICAgICAgaGg6ICclZCBob3JhcycsXG4gICAgICAgICAgICBkOiAndW4gZMOtYScsXG4gICAgICAgICAgICBkZDogJyVkIGTDrWFzJyxcbiAgICAgICAgICAgIHc6ICd1bmEgc2VtYW5hJyxcbiAgICAgICAgICAgIHd3OiAnJWQgc2VtYW5hcycsXG4gICAgICAgICAgICBNOiAndW4gbWVzJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWVzZXMnLFxuICAgICAgICAgICAgeTogJ3VuIGHDsW8nLFxuICAgICAgICAgICAgeXk6ICclZCBhw7FvcycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbDogJyVkwronLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgICAgIGludmFsaWREYXRlOiAnRmVjaGEgaW52w6FsaWRhJyxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBtb250aHNTaG9ydERvdCQyID0gJ2VuZS5fZmViLl9tYXIuX2Fici5fbWF5Ll9qdW4uX2p1bC5fYWdvLl9zZXAuX29jdC5fbm92Ll9kaWMuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydCQzID0gJ2VuZV9mZWJfbWFyX2Ficl9tYXlfanVuX2p1bF9hZ29fc2VwX29jdF9ub3ZfZGljJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNQYXJzZSQ0ID0gW1xuICAgICAgICAgICAgL15lbmUvaSxcbiAgICAgICAgICAgIC9eZmViL2ksXG4gICAgICAgICAgICAvXm1hci9pLFxuICAgICAgICAgICAgL15hYnIvaSxcbiAgICAgICAgICAgIC9ebWF5L2ksXG4gICAgICAgICAgICAvXmp1bi9pLFxuICAgICAgICAgICAgL15qdWwvaSxcbiAgICAgICAgICAgIC9eYWdvL2ksXG4gICAgICAgICAgICAvXnNlcC9pLFxuICAgICAgICAgICAgL15vY3QvaSxcbiAgICAgICAgICAgIC9ebm92L2ksXG4gICAgICAgICAgICAvXmRpYy9pLFxuICAgICAgICBdLFxuICAgICAgICBtb250aHNSZWdleCQ1ID0gL14oZW5lcm98ZmVicmVyb3xtYXJ6b3xhYnJpbHxtYXlvfGp1bmlvfGp1bGlvfGFnb3N0b3xzZXB0aWVtYnJlfG9jdHVicmV8bm92aWVtYnJlfGRpY2llbWJyZXxlbmVcXC4/fGZlYlxcLj98bWFyXFwuP3xhYnJcXC4/fG1heVxcLj98anVuXFwuP3xqdWxcXC4/fGFnb1xcLj98c2VwXFwuP3xvY3RcXC4/fG5vdlxcLj98ZGljXFwuPykvaTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZXMtdXMnLCB7XG4gICAgICAgIG1vbnRoczogJ2VuZXJvX2ZlYnJlcm9fbWFyem9fYWJyaWxfbWF5b19qdW5pb19qdWxpb19hZ29zdG9fc2VwdGllbWJyZV9vY3R1YnJlX25vdmllbWJyZV9kaWNpZW1icmUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiBmdW5jdGlvbiAobSwgZm9ybWF0KSB7XG4gICAgICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnREb3QkMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnQkM1ttLm1vbnRoKCldO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnREb3QkMlttLm1vbnRoKCldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtb250aHNSZWdleDogbW9udGhzUmVnZXgkNSxcbiAgICAgICAgbW9udGhzU2hvcnRSZWdleDogbW9udGhzUmVnZXgkNSxcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGVuZXJvfGZlYnJlcm98bWFyem98YWJyaWx8bWF5b3xqdW5pb3xqdWxpb3xhZ29zdG98c2VwdGllbWJyZXxvY3R1YnJlfG5vdmllbWJyZXxkaWNpZW1icmUpL2ksXG4gICAgICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKGVuZVxcLj98ZmViXFwuP3xtYXJcXC4/fGFiclxcLj98bWF5XFwuP3xqdW5cXC4/fGp1bFxcLj98YWdvXFwuP3xzZXBcXC4/fG9jdFxcLj98bm92XFwuP3xkaWNcXC4/KS9pLFxuICAgICAgICBtb250aHNQYXJzZTogbW9udGhzUGFyc2UkNCxcbiAgICAgICAgbG9uZ01vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQ0LFxuICAgICAgICBzaG9ydE1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQ0LFxuICAgICAgICB3ZWVrZGF5czogJ2RvbWluZ29fbHVuZXNfbWFydGVzX21pw6lyY29sZXNfanVldmVzX3ZpZXJuZXNfc8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ2RvbS5fbHVuLl9tYXIuX21pw6kuX2p1ZS5fdmllLl9zw6FiLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdkb19sdV9tYV9taV9qdV92aV9zw6EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnaDptbSBBJyxcbiAgICAgICAgICAgIExUUzogJ2g6bW06c3MgQScsXG4gICAgICAgICAgICBMOiAnTU0vREQvWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIFtkZV0gTU1NTSBbZGVdIFlZWVkgaDptbSBBJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1tob3kgYSBsYScgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5leHREYXk6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1ttYcOxYW5hIGEgbGEnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZGRkZCBbYSBsYScgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1theWVyIGEgbGEnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICdbZWxdIGRkZGQgW3Bhc2FkbyBhIGxhJyArXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLmhvdXJzKCkgIT09IDEgPyAncycgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAnXSBMVCdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnZW4gJXMnLFxuICAgICAgICAgICAgcGFzdDogJ2hhY2UgJXMnLFxuICAgICAgICAgICAgczogJ3Vub3Mgc2VndW5kb3MnLFxuICAgICAgICAgICAgc3M6ICclZCBzZWd1bmRvcycsXG4gICAgICAgICAgICBtOiAndW4gbWludXRvJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRvcycsXG4gICAgICAgICAgICBoOiAndW5hIGhvcmEnLFxuICAgICAgICAgICAgaGg6ICclZCBob3JhcycsXG4gICAgICAgICAgICBkOiAndW4gZMOtYScsXG4gICAgICAgICAgICBkZDogJyVkIGTDrWFzJyxcbiAgICAgICAgICAgIHc6ICd1bmEgc2VtYW5hJyxcbiAgICAgICAgICAgIHd3OiAnJWQgc2VtYW5hcycsXG4gICAgICAgICAgICBNOiAndW4gbWVzJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWVzZXMnLFxuICAgICAgICAgICAgeTogJ3VuIGHDsW8nLFxuICAgICAgICAgICAgeXk6ICclZCBhw7FvcycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbDogJyVkwronLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA2LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA2dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzU2hvcnREb3QkMyA9ICdlbmUuX2ZlYi5fbWFyLl9hYnIuX21heS5fanVuLl9qdWwuX2Fnby5fc2VwLl9vY3QuX25vdi5fZGljLicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQkNCA9ICdlbmVfZmViX21hcl9hYnJfbWF5X2p1bl9qdWxfYWdvX3NlcF9vY3Rfbm92X2RpYycuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2UkNSA9IFtcbiAgICAgICAgICAgIC9eZW5lL2ksXG4gICAgICAgICAgICAvXmZlYi9pLFxuICAgICAgICAgICAgL15tYXIvaSxcbiAgICAgICAgICAgIC9eYWJyL2ksXG4gICAgICAgICAgICAvXm1heS9pLFxuICAgICAgICAgICAgL15qdW4vaSxcbiAgICAgICAgICAgIC9eanVsL2ksXG4gICAgICAgICAgICAvXmFnby9pLFxuICAgICAgICAgICAgL15zZXAvaSxcbiAgICAgICAgICAgIC9eb2N0L2ksXG4gICAgICAgICAgICAvXm5vdi9pLFxuICAgICAgICAgICAgL15kaWMvaSxcbiAgICAgICAgXSxcbiAgICAgICAgbW9udGhzUmVnZXgkNiA9IC9eKGVuZXJvfGZlYnJlcm98bWFyem98YWJyaWx8bWF5b3xqdW5pb3xqdWxpb3xhZ29zdG98c2VwdGllbWJyZXxvY3R1YnJlfG5vdmllbWJyZXxkaWNpZW1icmV8ZW5lXFwuP3xmZWJcXC4/fG1hclxcLj98YWJyXFwuP3xtYXlcXC4/fGp1blxcLj98anVsXFwuP3xhZ29cXC4/fHNlcFxcLj98b2N0XFwuP3xub3ZcXC4/fGRpY1xcLj8pL2k7XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2VzJywge1xuICAgICAgICBtb250aHM6ICdlbmVyb19mZWJyZXJvX21hcnpvX2FicmlsX21heW9fanVuaW9fanVsaW9fYWdvc3RvX3NlcHRpZW1icmVfb2N0dWJyZV9ub3ZpZW1icmVfZGljaWVtYnJlJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0RG90JDM7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKC8tTU1NLS8udGVzdChmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0JDRbbS5tb250aCgpXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0RG90JDNbbS5tb250aCgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzUmVnZXg6IG1vbnRoc1JlZ2V4JDYsXG4gICAgICAgIG1vbnRoc1Nob3J0UmVnZXg6IG1vbnRoc1JlZ2V4JDYsXG4gICAgICAgIG1vbnRoc1N0cmljdFJlZ2V4OiAvXihlbmVyb3xmZWJyZXJvfG1hcnpvfGFicmlsfG1heW98anVuaW98anVsaW98YWdvc3RvfHNlcHRpZW1icmV8b2N0dWJyZXxub3ZpZW1icmV8ZGljaWVtYnJlKS9pLFxuICAgICAgICBtb250aHNTaG9ydFN0cmljdFJlZ2V4OiAvXihlbmVcXC4/fGZlYlxcLj98bWFyXFwuP3xhYnJcXC4/fG1heVxcLj98anVuXFwuP3xqdWxcXC4/fGFnb1xcLj98c2VwXFwuP3xvY3RcXC4/fG5vdlxcLj98ZGljXFwuPykvaSxcbiAgICAgICAgbW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDUsXG4gICAgICAgIGxvbmdNb250aHNQYXJzZTogbW9udGhzUGFyc2UkNSxcbiAgICAgICAgc2hvcnRNb250aHNQYXJzZTogbW9udGhzUGFyc2UkNSxcbiAgICAgICAgd2Vla2RheXM6ICdkb21pbmdvX2x1bmVzX21hcnRlc19tacOpcmNvbGVzX2p1ZXZlc192aWVybmVzX3PDoWJhZG8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdkb20uX2x1bi5fbWFyLl9tacOpLl9qdWUuX3ZpZS5fc8OhYi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnZG9fbHVfbWFfbWlfanVfdmlfc8OhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2hveSBhIGxhJyArICh0aGlzLmhvdXJzKCkgIT09IDEgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dERheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW21hw7FhbmEgYSBsYScgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdkZGRkIFthIGxhJyArICh0aGlzLmhvdXJzKCkgIT09IDEgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2F5ZXIgYSBsYScgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgJ1tlbF0gZGRkZCBbcGFzYWRvIGEgbGEnICtcbiAgICAgICAgICAgICAgICAgICAgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICdzJyA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgICddIExUJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdlbiAlcycsXG4gICAgICAgICAgICBwYXN0OiAnaGFjZSAlcycsXG4gICAgICAgICAgICBzOiAndW5vcyBzZWd1bmRvcycsXG4gICAgICAgICAgICBzczogJyVkIHNlZ3VuZG9zJyxcbiAgICAgICAgICAgIG06ICd1biBtaW51dG8nLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dG9zJyxcbiAgICAgICAgICAgIGg6ICd1bmEgaG9yYScsXG4gICAgICAgICAgICBoaDogJyVkIGhvcmFzJyxcbiAgICAgICAgICAgIGQ6ICd1biBkw61hJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZMOtYXMnLFxuICAgICAgICAgICAgdzogJ3VuYSBzZW1hbmEnLFxuICAgICAgICAgICAgd3c6ICclZCBzZW1hbmFzJyxcbiAgICAgICAgICAgIE06ICd1biBtZXMnLFxuICAgICAgICAgICAgTU06ICclZCBtZXNlcycsXG4gICAgICAgICAgICB5OiAndW4gYcOxbycsXG4gICAgICAgICAgICB5eTogJyVkIGHDsW9zJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9wrovLFxuICAgICAgICBvcmRpbmFsOiAnJWTCuicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICAgICAgaW52YWxpZERhdGU6ICdGZWNoYSBpbnbDoWxpZGEnLFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQzKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgczogWydtw7VuZSBzZWt1bmRpJywgJ23DtW5pIHNla3VuZCcsICdwYWFyIHNla3VuZGl0J10sXG4gICAgICAgICAgICBzczogW251bWJlciArICdzZWt1bmRpJywgbnVtYmVyICsgJ3Nla3VuZGl0J10sXG4gICAgICAgICAgICBtOiBbJ8O8aGUgbWludXRpJywgJ8O8a3MgbWludXQnXSxcbiAgICAgICAgICAgIG1tOiBbbnVtYmVyICsgJyBtaW51dGknLCBudW1iZXIgKyAnIG1pbnV0aXQnXSxcbiAgICAgICAgICAgIGg6IFsnw7xoZSB0dW5uaScsICd0dW5kIGFlZ2EnLCAnw7xrcyB0dW5kJ10sXG4gICAgICAgICAgICBoaDogW251bWJlciArICcgdHVubmknLCBudW1iZXIgKyAnIHR1bmRpJ10sXG4gICAgICAgICAgICBkOiBbJ8O8aGUgcMOkZXZhJywgJ8O8a3MgcMOkZXYnXSxcbiAgICAgICAgICAgIE06IFsna3V1IGFqYScsICdrdXUgYWVnYScsICfDvGtzIGt1dSddLFxuICAgICAgICAgICAgTU06IFtudW1iZXIgKyAnIGt1dScsIG51bWJlciArICcga3V1ZCddLFxuICAgICAgICAgICAgeTogWyfDvGhlIGFhc3RhJywgJ2Fhc3RhJywgJ8O8a3MgYWFzdGEnXSxcbiAgICAgICAgICAgIHl5OiBbbnVtYmVyICsgJyBhYXN0YScsIG51bWJlciArICcgYWFzdGF0J10sXG4gICAgICAgIH07XG4gICAgICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0W2tleV1bMl0gPyBmb3JtYXRba2V5XVsyXSA6IGZvcm1hdFtrZXldWzFdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0Z1dHVyZSA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdldCcsIHtcbiAgICAgICAgbW9udGhzOiAnamFhbnVhcl92ZWVicnVhcl9tw6RydHNfYXByaWxsX21haV9qdXVuaV9qdXVsaV9hdWd1c3Rfc2VwdGVtYmVyX29rdG9vYmVyX25vdmVtYmVyX2RldHNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdqYWFuX3ZlZWJyX23DpHJ0c19hcHJfbWFpX2p1dW5pX2p1dWxpX2F1Z19zZXB0X29rdF9ub3ZfZGV0cycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICdww7xoYXDDpGV2X2VzbWFzcMOkZXZfdGVpc2lww6Rldl9rb2xtYXDDpGV2X25lbGphcMOkZXZfcmVlZGVfbGF1cMOkZXYnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdQX0VfVF9LX05fUl9MJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1BfRV9UX0tfTl9SX0wnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tUw6RuYSxdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbSG9tbWUsXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1tKw6RyZ21pbmVdIGRkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tFaWxlLF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbRWVsbWluZV0gZGRkZCBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJyVzIHDDpHJhc3QnLFxuICAgICAgICAgICAgcGFzdDogJyVzIHRhZ2FzaScsXG4gICAgICAgICAgICBzOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDMsXG4gICAgICAgICAgICBzczogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICAgICAgbTogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICAgICAgbW06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIGg6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIGhoOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDMsXG4gICAgICAgICAgICBkOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDMsXG4gICAgICAgICAgICBkZDogJyVkIHDDpGV2YScsXG4gICAgICAgICAgICBNOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDMsXG4gICAgICAgICAgICBNTTogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICAgICAgeTogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICAgICAgeXk6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbDogJyVkLicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZXUnLCB7XG4gICAgICAgIG1vbnRoczogJ3VydGFycmlsYV9vdHNhaWxhX21hcnR4b2FfYXBpcmlsYV9tYWlhdHphX2VrYWluYV91enRhaWxhX2FidXp0dWFfaXJhaWxhX3VycmlhX2F6YXJvYV9hYmVuZHVhJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ3VydC5fb3RzLl9tYXIuX2FwaS5fbWFpLl9la2EuX3V6dC5fYWJ1Ll9pcmEuX3Vyci5fYXphLl9hYmUuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ2lnYW5kZWFfYXN0ZWxlaGVuYV9hc3RlYXJ0ZWFfYXN0ZWF6a2VuYV9vc3RlZ3VuYV9vc3RpcmFsYV9sYXJ1bmJhdGEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdpZy5fYWwuX2FyLl9hei5fb2cuX29sLl9sci4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnaWdfYWxfYXJfYXpfb2dfb2xfbHInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ1lZWVktTU0tREQnLFxuICAgICAgICAgICAgTEw6ICdZWVlZW2tvXSBNTU1NW3Jlbl0gRFthXScsXG4gICAgICAgICAgICBMTEw6ICdZWVlZW2tvXSBNTU1NW3Jlbl0gRFthXSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgWVlZWVtrb10gTU1NTVtyZW5dIERbYV0gSEg6bW0nLFxuICAgICAgICAgICAgbDogJ1lZWVktTS1EJyxcbiAgICAgICAgICAgIGxsOiAnWVlZWVtrb10gTU1NIERbYV0nLFxuICAgICAgICAgICAgbGxsOiAnWVlZWVtrb10gTU1NIERbYV0gSEg6bW0nLFxuICAgICAgICAgICAgbGxsbDogJ2RkZCwgWVlZWVtrb10gTU1NIERbYV0gSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tnYXVyXSBMVFtldGFuXScsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW2JpaGFyXSBMVFtldGFuXScsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgTFRbZXRhbl0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1thdHpvXSBMVFtldGFuXScsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1thdXJyZWtvXSBkZGRkIExUW2V0YW5dJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMgYmFycnUnLFxuICAgICAgICAgICAgcGFzdDogJ2R1ZWxhICVzJyxcbiAgICAgICAgICAgIHM6ICdzZWd1bmRvIGJhdHp1aycsXG4gICAgICAgICAgICBzczogJyVkIHNlZ3VuZG8nLFxuICAgICAgICAgICAgbTogJ21pbnV0dSBiYXQnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dHUnLFxuICAgICAgICAgICAgaDogJ29yZHUgYmF0JyxcbiAgICAgICAgICAgIGhoOiAnJWQgb3JkdScsXG4gICAgICAgICAgICBkOiAnZWd1biBiYXQnLFxuICAgICAgICAgICAgZGQ6ICclZCBlZ3VuJyxcbiAgICAgICAgICAgIE06ICdoaWxhYmV0ZSBiYXQnLFxuICAgICAgICAgICAgTU06ICclZCBoaWxhYmV0ZScsXG4gICAgICAgICAgICB5OiAndXJ0ZSBiYXQnLFxuICAgICAgICAgICAgeXk6ICclZCB1cnRlJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbDogJyVkLicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkNiA9IHtcbiAgICAgICAgICAgIDE6ICfbsScsXG4gICAgICAgICAgICAyOiAn27InLFxuICAgICAgICAgICAgMzogJ9uzJyxcbiAgICAgICAgICAgIDQ6ICfbtCcsXG4gICAgICAgICAgICA1OiAn27UnLFxuICAgICAgICAgICAgNjogJ9u2JyxcbiAgICAgICAgICAgIDc6ICfbtycsXG4gICAgICAgICAgICA4OiAn27gnLFxuICAgICAgICAgICAgOTogJ9u5JyxcbiAgICAgICAgICAgIDA6ICfbsCcsXG4gICAgICAgIH0sXG4gICAgICAgIG51bWJlck1hcCQ1ID0ge1xuICAgICAgICAgICAgJ9uxJzogJzEnLFxuICAgICAgICAgICAgJ9uyJzogJzInLFxuICAgICAgICAgICAgJ9uzJzogJzMnLFxuICAgICAgICAgICAgJ9u0JzogJzQnLFxuICAgICAgICAgICAgJ9u1JzogJzUnLFxuICAgICAgICAgICAgJ9u2JzogJzYnLFxuICAgICAgICAgICAgJ9u3JzogJzcnLFxuICAgICAgICAgICAgJ9u4JzogJzgnLFxuICAgICAgICAgICAgJ9u5JzogJzknLFxuICAgICAgICAgICAgJ9uwJzogJzAnLFxuICAgICAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdmYScsIHtcbiAgICAgICAgbW9udGhzOiAn2pjYp9mG2YjbjNmHX9mB2YjYsduM2Ydf2YXYp9ix2LNf2KLZiNix24zZhF/ZhdmHX9qY2YjYptmGX9qY2YjYptuM2Ydf2KfZiNiqX9iz2b7Yqtin2YXYqNixX9in2qnYqtio2LFf2YbZiNin2YXYqNixX9iv2LPYp9mF2KjYsScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfamNin2YbZiNuM2Ydf2YHZiNix24zZh1/Zhdin2LHYs1/YotmI2LHbjNmEX9mF2Ydf2pjZiNim2YZf2pjZiNim24zZh1/Yp9mI2Kpf2LPZvtiq2KfZhdio2LFf2Kfaqdiq2KjYsV/ZhtmI2KfZhdio2LFf2K/Ys9in2YXYqNixJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ9uM2qlcXHUyMDBj2LTZhtio2Ydf2K/ZiNi02YbYqNmHX9iz2YdcXHUyMDBj2LTZhtio2Ydf2obZh9in2LHYtNmG2KjZh1/ZvtmG2KxcXHUyMDBj2LTZhtio2Ydf2KzZhdi52Ydf2LTZhtio2YcnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfbjNqpXFx1MjAwY9i02YbYqNmHX9iv2YjYtNmG2KjZh1/Ys9mHXFx1MjAwY9i02YbYqNmHX9qG2YfYp9ix2LTZhtio2Ydf2b7ZhtisXFx1MjAwY9i02YbYqNmHX9is2YXYudmHX9i02YbYqNmHJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9uMX9ivX9izX9qGX9m+X9isX9i0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9mC2KjZhCDYp9iyINi42YfYsXzYqNi52K8g2KfYsiDYuNmH2LEvLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiAv2KjYudivINin2LIg2LjZh9ixLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9mC2KjZhCDYp9iyINi42YfYsSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2KjYudivINin2LIg2LjZh9ixJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb2KfZhdix2YjYsiDYs9in2LnYql0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vZgdix2K/YpyDYs9in2LnYql0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYs9in2LnYql0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYr9uM2LHZiNiyINiz2KfYudiqXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW9m+24zYtF0gW9iz2KfYudiqXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9iv2LEgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzINm+24zYtCcsXG4gICAgICAgICAgICBzOiAn2obZhtivINir2KfZhtuM2YcnLFxuICAgICAgICAgICAgc3M6ICclZCDYq9in2YbbjNmHJyxcbiAgICAgICAgICAgIG06ICfbjNqpINiv2YLbjNmC2YcnLFxuICAgICAgICAgICAgbW06ICclZCDYr9mC24zZgtmHJyxcbiAgICAgICAgICAgIGg6ICfbjNqpINiz2KfYudiqJyxcbiAgICAgICAgICAgIGhoOiAnJWQg2LPYp9i52KonLFxuICAgICAgICAgICAgZDogJ9uM2qkg2LHZiNiyJyxcbiAgICAgICAgICAgIGRkOiAnJWQg2LHZiNiyJyxcbiAgICAgICAgICAgIE06ICfbjNqpINmF2KfZhycsXG4gICAgICAgICAgICBNTTogJyVkINmF2KfZhycsXG4gICAgICAgICAgICB5OiAn24zaqSDYs9in2YQnLFxuICAgICAgICAgICAgeXk6ICclZCDYs9in2YQnLFxuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1xuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9b27At27ldL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDVbbWF0Y2hdO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDZbbWF0Y2hdO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfdmFLyxcbiAgICAgICAgb3JkaW5hbDogJyVk2YUnLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDEyLCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxMnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG51bWJlcnNQYXN0ID0gJ25vbGxhIHlrc2kga2Frc2kga29sbWUgbmVsasOkIHZpaXNpIGt1dXNpIHNlaXRzZW3DpG4ga2FoZGVrc2FuIHloZGVrc8Okbicuc3BsaXQoXG4gICAgICAgICAgICAnICdcbiAgICAgICAgKSxcbiAgICAgICAgbnVtYmVyc0Z1dHVyZSA9IFtcbiAgICAgICAgICAgICdub2xsYScsXG4gICAgICAgICAgICAneWhkZW4nLFxuICAgICAgICAgICAgJ2thaGRlbicsXG4gICAgICAgICAgICAna29sbWVuJyxcbiAgICAgICAgICAgICduZWxqw6RuJyxcbiAgICAgICAgICAgICd2aWlkZW4nLFxuICAgICAgICAgICAgJ2t1dWRlbicsXG4gICAgICAgICAgICBudW1iZXJzUGFzdFs3XSxcbiAgICAgICAgICAgIG51bWJlcnNQYXN0WzhdLFxuICAgICAgICAgICAgbnVtYmVyc1Bhc3RbOV0sXG4gICAgICAgIF07XG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlJDIobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSAnJztcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdtdXV0YW1hbiBzZWt1bm5pbicgOiAnbXV1dGFtYSBzZWt1bnRpJztcbiAgICAgICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICdzZWt1bm5pbicgOiAnc2VrdW50aWEnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ21pbnV1dGluJyA6ICdtaW51dXR0aSc7XG4gICAgICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gaXNGdXR1cmUgPyAnbWludXV0aW4nIDogJ21pbnV1dHRpYSc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAndHVubmluJyA6ICd0dW50aSc7XG4gICAgICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gaXNGdXR1cmUgPyAndHVubmluJyA6ICd0dW50aWEnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ3DDpGl2w6RuJyA6ICdww6RpdsOkJztcbiAgICAgICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICdww6RpdsOkbicgOiAncMOkaXbDpMOkJztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdrdXVrYXVkZW4nIDogJ2t1dWthdXNpJztcbiAgICAgICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICdrdXVrYXVkZW4nIDogJ2t1dWthdXR0YSc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd5JzpcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAndnVvZGVuJyA6ICd2dW9zaSc7XG4gICAgICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gaXNGdXR1cmUgPyAndnVvZGVuJyA6ICd2dW90dGEnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdCA9IHZlcmJhbE51bWJlcihudW1iZXIsIGlzRnV0dXJlKSArICcgJyArIHJlc3VsdDtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgZnVuY3Rpb24gdmVyYmFsTnVtYmVyKG51bWJlciwgaXNGdXR1cmUpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciA8IDEwXG4gICAgICAgICAgICA/IGlzRnV0dXJlXG4gICAgICAgICAgICAgICAgPyBudW1iZXJzRnV0dXJlW251bWJlcl1cbiAgICAgICAgICAgICAgICA6IG51bWJlcnNQYXN0W251bWJlcl1cbiAgICAgICAgICAgIDogbnVtYmVyO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZmknLCB7XG4gICAgICAgIG1vbnRoczogJ3RhbW1pa3V1X2hlbG1pa3V1X21hYWxpc2t1dV9odWh0aWt1dV90b3Vrb2t1dV9rZXPDpGt1dV9oZWluw6RrdXVfZWxva3V1X3N5eXNrdXVfbG9rYWt1dV9tYXJyYXNrdXVfam91bHVrdXUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAndGFtbWlfaGVsbWlfbWFhbGlzX2h1aHRpX3RvdWtvX2tlc8OkX2hlaW7DpF9lbG9fc3l5c19sb2thX21hcnJhc19qb3VsdScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICdzdW5udW50YWlfbWFhbmFudGFpX3RpaXN0YWlfa2Vza2l2aWlra29fdG9yc3RhaV9wZXJqYW50YWlfbGF1YW50YWknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdzdV9tYV90aV9rZV90b19wZV9sYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdzdV9tYV90aV9rZV90b19wZV9sYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEgubW0nLFxuICAgICAgICAgICAgTFRTOiAnSEgubW0uc3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEbyBNTU1NW3RhXSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0RvIE1NTU1bdGFdIFlZWVksIFtrbG9dIEhILm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEbyBNTU1NW3RhXSBZWVlZLCBba2xvXSBISC5tbScsXG4gICAgICAgICAgICBsOiAnRC5NLllZWVknLFxuICAgICAgICAgICAgbGw6ICdEbyBNTU0gWVlZWScsXG4gICAgICAgICAgICBsbGw6ICdEbyBNTU0gWVlZWSwgW2tsb10gSEgubW0nLFxuICAgICAgICAgICAgbGxsbDogJ2RkZCwgRG8gTU1NIFlZWVksIFtrbG9dIEhILm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbdMOkbsOkw6RuXSBba2xvXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW2h1b21lbm5hXSBba2xvXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2tsb10gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tlaWxlbl0gW2tsb10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbdmlpbWVdIGRkZGRbbmFdIFtrbG9dIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMgcMOkw6RzdMOkJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBzaXR0ZW4nLFxuICAgICAgICAgICAgczogdHJhbnNsYXRlJDIsXG4gICAgICAgICAgICBzczogdHJhbnNsYXRlJDIsXG4gICAgICAgICAgICBtOiB0cmFuc2xhdGUkMixcbiAgICAgICAgICAgIG1tOiB0cmFuc2xhdGUkMixcbiAgICAgICAgICAgIGg6IHRyYW5zbGF0ZSQyLFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0ZSQyLFxuICAgICAgICAgICAgZDogdHJhbnNsYXRlJDIsXG4gICAgICAgICAgICBkZDogdHJhbnNsYXRlJDIsXG4gICAgICAgICAgICBNOiB0cmFuc2xhdGUkMixcbiAgICAgICAgICAgIE1NOiB0cmFuc2xhdGUkMixcbiAgICAgICAgICAgIHk6IHRyYW5zbGF0ZSQyLFxuICAgICAgICAgICAgeXk6IHRyYW5zbGF0ZSQyLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdmaWwnLCB7XG4gICAgICAgIG1vbnRoczogJ0VuZXJvX1BlYnJlcm9fTWFyc29fQWJyaWxfTWF5b19IdW55b19IdWx5b19BZ29zdG9fU2V0eWVtYnJlX09rdHVicmVfTm9ieWVtYnJlX0Rpc3llbWJyZScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdFbmVfUGViX01hcl9BYnJfTWF5X0h1bl9IdWxfQWdvX1NldF9Pa3RfTm9iX0Rpcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdMaW5nZ29fTHVuZXNfTWFydGVzX01peWVya3VsZXNfSHV3ZWJlc19CaXllcm5lc19TYWJhZG8nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdMaW5fTHVuX01hcl9NaXlfSHV3X0JpeV9TYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnTGlfTHVfTWFfTWlfSHVfQmlfU2FiJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnTU0vRC9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ01NTU0gRCwgWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgTU1NTSBERCwgWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnTFQgW25nYXlvbmcgYXJhd10nLFxuICAgICAgICAgICAgbmV4dERheTogJ1tCdWthcyBuZ10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdMVCBbc2Egc3VzdW5vZCBuYV0gZGRkZCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnTFQgW2thaGFwb25dJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnTFQgW25vb25nIG5ha2FyYWFuZ10gZGRkZCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ3NhIGxvb2IgbmcgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIGFuZyBuYWthbGlwYXMnLFxuICAgICAgICAgICAgczogJ2lsYW5nIHNlZ3VuZG8nLFxuICAgICAgICAgICAgc3M6ICclZCBzZWd1bmRvJyxcbiAgICAgICAgICAgIG06ICdpc2FuZyBtaW51dG8nLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dG8nLFxuICAgICAgICAgICAgaDogJ2lzYW5nIG9yYXMnLFxuICAgICAgICAgICAgaGg6ICclZCBvcmFzJyxcbiAgICAgICAgICAgIGQ6ICdpc2FuZyBhcmF3JyxcbiAgICAgICAgICAgIGRkOiAnJWQgYXJhdycsXG4gICAgICAgICAgICBNOiAnaXNhbmcgYnV3YW4nLFxuICAgICAgICAgICAgTU06ICclZCBidXdhbicsXG4gICAgICAgICAgICB5OiAnaXNhbmcgdGFvbicsXG4gICAgICAgICAgICB5eTogJyVkIHRhb24nLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0vLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2ZvJywge1xuICAgICAgICBtb250aHM6ICdqYW51YXJfZmVicnVhcl9tYXJzX2FwcsOtbF9tYWlfanVuaV9qdWxpX2F1Z3VzdF9zZXB0ZW1iZXJfb2t0b2Jlcl9ub3ZlbWJlcl9kZXNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdqYW5fZmViX21hcl9hcHJfbWFpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2Rlcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdzdW5udWRhZ3VyX23DoW5hZGFndXJfdMO9c2RhZ3VyX21pa3VkYWd1cl9ow7NzZGFndXJfZnLDrWdnamFkYWd1cl9sZXlnYXJkYWd1cicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ3N1bl9tw6FuX3TDvXNfbWlrX2jDs3NfZnLDrV9sZXknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnc3VfbcOhX3TDvV9taV9ow7NfZnJfbGUnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRC4gTU1NTSwgWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW8ONIGRhZyBrbC5dIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbw40gbW9yZ2luIGtsLl0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtrbC5dIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbw40gZ2rDoXIga2wuXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tzw63DsHN0dV0gZGRkZCBba2xdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAndW0gJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIHPDrcOwYW5pJyxcbiAgICAgICAgICAgIHM6ICdmw6Egc2VrdW5kJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2VrdW5kaXInLFxuICAgICAgICAgICAgbTogJ2VpbiBtaW51dHR1cicsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0dGlyJyxcbiAgICAgICAgICAgIGg6ICdlaW4gdMOtbWknLFxuICAgICAgICAgICAgaGg6ICclZCB0w61tYXInLFxuICAgICAgICAgICAgZDogJ2VpbiBkYWd1cicsXG4gICAgICAgICAgICBkZDogJyVkIGRhZ2FyJyxcbiAgICAgICAgICAgIE06ICdlaW4gbcOhbmHDsHVyJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbcOhbmHDsGlyJyxcbiAgICAgICAgICAgIHk6ICdlaXR0IMOhcicsXG4gICAgICAgICAgICB5eTogJyVkIMOhcicsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2ZyLWNhJywge1xuICAgICAgICBtb250aHM6ICdqYW52aWVyX2bDqXZyaWVyX21hcnNfYXZyaWxfbWFpX2p1aW5fanVpbGxldF9hb8O7dF9zZXB0ZW1icmVfb2N0b2JyZV9ub3ZlbWJyZV9kw6ljZW1icmUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnamFudi5fZsOpdnIuX21hcnNfYXZyLl9tYWlfanVpbl9qdWlsLl9hb8O7dF9zZXB0Ll9vY3QuX25vdi5fZMOpYy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnZGltYW5jaGVfbHVuZGlfbWFyZGlfbWVyY3JlZGlfamV1ZGlfdmVuZHJlZGlfc2FtZWRpJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnZGltLl9sdW4uX21hci5fbWVyLl9qZXUuX3Zlbi5fc2FtLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdkaV9sdV9tYV9tZV9qZV92ZV9zYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbQXVqb3VyZOKAmWh1aSDDoF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tEZW1haW4gw6BdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbw6BdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbSGllciDDoF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFtkZXJuaWVyIMOgXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2RhbnMgJXMnLFxuICAgICAgICAgICAgcGFzdDogJ2lsIHkgYSAlcycsXG4gICAgICAgICAgICBzOiAncXVlbHF1ZXMgc2Vjb25kZXMnLFxuICAgICAgICAgICAgc3M6ICclZCBzZWNvbmRlcycsXG4gICAgICAgICAgICBtOiAndW5lIG1pbnV0ZScsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaDogJ3VuZSBoZXVyZScsXG4gICAgICAgICAgICBoaDogJyVkIGhldXJlcycsXG4gICAgICAgICAgICBkOiAndW4gam91cicsXG4gICAgICAgICAgICBkZDogJyVkIGpvdXJzJyxcbiAgICAgICAgICAgIE06ICd1biBtb2lzJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbW9pcycsXG4gICAgICAgICAgICB5OiAndW4gYW4nLFxuICAgICAgICAgICAgeXk6ICclZCBhbnMnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZXJ8ZSkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgLy8gV29yZHMgd2l0aCBtYXNjdWxpbmUgZ3JhbW1hdGljYWwgZ2VuZGVyOiBtb2lzLCB0cmltZXN0cmUsIGpvdXJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1EnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ2VyJyA6ICdlJyk7XG5cbiAgICAgICAgICAgICAgICAvLyBXb3JkcyB3aXRoIGZlbWluaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogc2VtYWluZVxuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdyZScgOiAnZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdmci1jaCcsIHtcbiAgICAgICAgbW9udGhzOiAnamFudmllcl9mw6l2cmllcl9tYXJzX2F2cmlsX21haV9qdWluX2p1aWxsZXRfYW/Du3Rfc2VwdGVtYnJlX29jdG9icmVfbm92ZW1icmVfZMOpY2VtYnJlJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2phbnYuX2bDqXZyLl9tYXJzX2F2ci5fbWFpX2p1aW5fanVpbC5fYW/Du3Rfc2VwdC5fb2N0Ll9ub3YuX2TDqWMuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ2RpbWFuY2hlX2x1bmRpX21hcmRpX21lcmNyZWRpX2pldWRpX3ZlbmRyZWRpX3NhbWVkaScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ2RpbS5fbHVuLl9tYXIuX21lci5famV1Ll92ZW4uX3NhbS4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnZGlfbHVfbWFfbWVfamVfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0F1am91cmTigJlodWkgw6BdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbRGVtYWluIMOgXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW8OgXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0hpZXIgw6BdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbZGVybmllciDDoF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdkYW5zICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICdpbCB5IGEgJXMnLFxuICAgICAgICAgICAgczogJ3F1ZWxxdWVzIHNlY29uZGVzJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vjb25kZXMnLFxuICAgICAgICAgICAgbTogJ3VuZSBtaW51dGUnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGVzJyxcbiAgICAgICAgICAgIGg6ICd1bmUgaGV1cmUnLFxuICAgICAgICAgICAgaGg6ICclZCBoZXVyZXMnLFxuICAgICAgICAgICAgZDogJ3VuIGpvdXInLFxuICAgICAgICAgICAgZGQ6ICclZCBqb3VycycsXG4gICAgICAgICAgICBNOiAndW4gbW9pcycsXG4gICAgICAgICAgICBNTTogJyVkIG1vaXMnLFxuICAgICAgICAgICAgeTogJ3VuIGFuJyxcbiAgICAgICAgICAgIHl5OiAnJWQgYW5zJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGVyfGUpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggbWFzY3VsaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogbW9pcywgdHJpbWVzdHJlLCBqb3VyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICBjYXNlICdRJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdlcicgOiAnZScpO1xuXG4gICAgICAgICAgICAgICAgLy8gV29yZHMgd2l0aCBmZW1pbmluZSBncmFtbWF0aWNhbCBnZW5kZXI6IHNlbWFpbmVcbiAgICAgICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChudW1iZXIgPT09IDEgPyAncmUnIDogJ2UnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRoc1N0cmljdFJlZ2V4JDEgPSAvXihqYW52aWVyfGbDqXZyaWVyfG1hcnN8YXZyaWx8bWFpfGp1aW58anVpbGxldHxhb8O7dHxzZXB0ZW1icmV8b2N0b2JyZXxub3ZlbWJyZXxkw6ljZW1icmUpL2ksXG4gICAgICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXgkMSA9IC8oamFudlxcLj98ZsOpdnJcXC4/fG1hcnN8YXZyXFwuP3xtYWl8anVpbnxqdWlsXFwuP3xhb8O7dHxzZXB0XFwuP3xvY3RcXC4/fG5vdlxcLj98ZMOpY1xcLj8pL2ksXG4gICAgICAgIG1vbnRoc1JlZ2V4JDcgPSAvKGphbnZcXC4/fGbDqXZyXFwuP3xtYXJzfGF2clxcLj98bWFpfGp1aW58anVpbFxcLj98YW/Du3R8c2VwdFxcLj98b2N0XFwuP3xub3ZcXC4/fGTDqWNcXC4/fGphbnZpZXJ8ZsOpdnJpZXJ8bWFyc3xhdnJpbHxtYWl8anVpbnxqdWlsbGV0fGFvw7t0fHNlcHRlbWJyZXxvY3RvYnJlfG5vdmVtYnJlfGTDqWNlbWJyZSkvaSxcbiAgICAgICAgbW9udGhzUGFyc2UkNiA9IFtcbiAgICAgICAgICAgIC9eamFudi9pLFxuICAgICAgICAgICAgL15mw6l2ci9pLFxuICAgICAgICAgICAgL15tYXJzL2ksXG4gICAgICAgICAgICAvXmF2ci9pLFxuICAgICAgICAgICAgL15tYWkvaSxcbiAgICAgICAgICAgIC9eanVpbi9pLFxuICAgICAgICAgICAgL15qdWlsL2ksXG4gICAgICAgICAgICAvXmFvw7t0L2ksXG4gICAgICAgICAgICAvXnNlcHQvaSxcbiAgICAgICAgICAgIC9eb2N0L2ksXG4gICAgICAgICAgICAvXm5vdi9pLFxuICAgICAgICAgICAgL15kw6ljL2ksXG4gICAgICAgIF07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2ZyJywge1xuICAgICAgICBtb250aHM6ICdqYW52aWVyX2bDqXZyaWVyX21hcnNfYXZyaWxfbWFpX2p1aW5fanVpbGxldF9hb8O7dF9zZXB0ZW1icmVfb2N0b2JyZV9ub3ZlbWJyZV9kw6ljZW1icmUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnamFudi5fZsOpdnIuX21hcnNfYXZyLl9tYWlfanVpbl9qdWlsLl9hb8O7dF9zZXB0Ll9vY3QuX25vdi5fZMOpYy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1JlZ2V4OiBtb250aHNSZWdleCQ3LFxuICAgICAgICBtb250aHNTaG9ydFJlZ2V4OiBtb250aHNSZWdleCQ3LFxuICAgICAgICBtb250aHNTdHJpY3RSZWdleDogbW9udGhzU3RyaWN0UmVnZXgkMSxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogbW9udGhzU2hvcnRTdHJpY3RSZWdleCQxLFxuICAgICAgICBtb250aHNQYXJzZTogbW9udGhzUGFyc2UkNixcbiAgICAgICAgbG9uZ01vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQ2LFxuICAgICAgICBzaG9ydE1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQ2LFxuICAgICAgICB3ZWVrZGF5czogJ2RpbWFuY2hlX2x1bmRpX21hcmRpX21lcmNyZWRpX2pldWRpX3ZlbmRyZWRpX3NhbWVkaScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ2RpbS5fbHVuLl9tYXIuX21lci5famV1Ll92ZW4uX3NhbS4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnZGlfbHVfbWFfbWVfamVfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0F1am91cmTigJlodWkgw6BdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbRGVtYWluIMOgXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW8OgXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0hpZXIgw6BdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbZGVybmllciDDoF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdkYW5zICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICdpbCB5IGEgJXMnLFxuICAgICAgICAgICAgczogJ3F1ZWxxdWVzIHNlY29uZGVzJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vjb25kZXMnLFxuICAgICAgICAgICAgbTogJ3VuZSBtaW51dGUnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGVzJyxcbiAgICAgICAgICAgIGg6ICd1bmUgaGV1cmUnLFxuICAgICAgICAgICAgaGg6ICclZCBoZXVyZXMnLFxuICAgICAgICAgICAgZDogJ3VuIGpvdXInLFxuICAgICAgICAgICAgZGQ6ICclZCBqb3VycycsXG4gICAgICAgICAgICB3OiAndW5lIHNlbWFpbmUnLFxuICAgICAgICAgICAgd3c6ICclZCBzZW1haW5lcycsXG4gICAgICAgICAgICBNOiAndW4gbW9pcycsXG4gICAgICAgICAgICBNTTogJyVkIG1vaXMnLFxuICAgICAgICAgICAgeTogJ3VuIGFuJyxcbiAgICAgICAgICAgIHl5OiAnJWQgYW5zJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGVyfCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogUmV0dXJuICdlJyB3aGVuIGRheSBvZiBtb250aCA+IDEuIE1vdmUgdGhpcyBjYXNlIGluc2lkZVxuICAgICAgICAgICAgICAgIC8vIGJsb2NrIGZvciBtYXNjdWxpbmUgd29yZHMgYmVsb3cuXG4gICAgICAgICAgICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L2lzc3Vlcy8zMzc1XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ2VyJyA6ICcnKTtcblxuICAgICAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggbWFzY3VsaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogbW9pcywgdHJpbWVzdHJlLCBqb3VyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICBjYXNlICdRJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdlcicgOiAnZScpO1xuXG4gICAgICAgICAgICAgICAgLy8gV29yZHMgd2l0aCBmZW1pbmluZSBncmFtbWF0aWNhbCBnZW5kZXI6IHNlbWFpbmVcbiAgICAgICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChudW1iZXIgPT09IDEgPyAncmUnIDogJ2UnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRoc1Nob3J0V2l0aERvdHMgPSAnamFuLl9mZWIuX21ydC5fYXByLl9tYWlfanVuLl9qdWwuX2F1Zy5fc2VwLl9va3QuX25vdi5fZGVzLicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnRXaXRob3V0RG90cyA9ICdqYW5fZmViX21ydF9hcHJfbWFpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2Rlcycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZnknLCB7XG4gICAgICAgIG1vbnRoczogJ2phbm5ld2FyaXNfZmVicmV3YXJpc19tYWFydF9hcHJpbF9tYWFpZV9qdW55X2p1bHlfYXVndXN0dXNfc2VwdGltYmVyX29rdG9iZXJfbm92aW1iZXJfZGVzaW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiBmdW5jdGlvbiAobSwgZm9ybWF0KSB7XG4gICAgICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRoRG90cztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRob3V0RG90c1ttLm1vbnRoKCldO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRoRG90c1ttLm1vbnRoKCldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ3NuZWluX21vYW5kZWlfdGlpc2RlaV93b2Fuc2RlaV90b25nZXJzZGVpX2ZyZWVkX3NuZW9uJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnc2kuX21vLl90aS5fd28uX3RvLl9mci5fc28uJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1NpX01vX1RpX1dvX1RvX0ZyX1NvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC1NTS1ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1toam9lZCBvbV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1ttb2FybiBvbV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtvbV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tqdXN0ZXIgb21dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW8O0ZnLDu25lXSBkZGRkIFtvbV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdvZXIgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIGx5bicsXG4gICAgICAgICAgICBzOiAnaW4gcGVhciBzZWtvbmRlbicsXG4gICAgICAgICAgICBzczogJyVkIHNla29uZGVuJyxcbiAgICAgICAgICAgIG06ICdpZW4gbWluw7p0JyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRlbicsXG4gICAgICAgICAgICBoOiAnaWVuIG9lcmUnLFxuICAgICAgICAgICAgaGg6ICclZCBvZXJlbicsXG4gICAgICAgICAgICBkOiAnaWVuIGRlaScsXG4gICAgICAgICAgICBkZDogJyVkIGRhZ2VuJyxcbiAgICAgICAgICAgIE06ICdpZW4gbW9hbm5lJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbW9hbm5lbicsXG4gICAgICAgICAgICB5OiAnaWVuIGppZXInLFxuICAgICAgICAgICAgeXk6ICclZCBqaWVycmVuJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIG51bWJlciArXG4gICAgICAgICAgICAgICAgKG51bWJlciA9PT0gMSB8fCBudW1iZXIgPT09IDggfHwgbnVtYmVyID49IDIwID8gJ3N0ZScgOiAnZGUnKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRocyQ2ID0gW1xuICAgICAgICAgICAgJ0VhbsOhaXInLFxuICAgICAgICAgICAgJ0ZlYWJocmEnLFxuICAgICAgICAgICAgJ03DoXJ0YScsXG4gICAgICAgICAgICAnQWlicmXDoW4nLFxuICAgICAgICAgICAgJ0JlYWx0YWluZScsXG4gICAgICAgICAgICAnTWVpdGhlYW1oJyxcbiAgICAgICAgICAgICdJw7ppbCcsXG4gICAgICAgICAgICAnTMO6bmFzYScsXG4gICAgICAgICAgICAnTWXDoW4gRsOzbWhhaXInLFxuICAgICAgICAgICAgJ0RlaXJlYWRoIEbDs21oYWlyJyxcbiAgICAgICAgICAgICdTYW1oYWluJyxcbiAgICAgICAgICAgICdOb2xsYWlnJyxcbiAgICAgICAgXSxcbiAgICAgICAgbW9udGhzU2hvcnQkNSA9IFtcbiAgICAgICAgICAgICdFYW4nLFxuICAgICAgICAgICAgJ0ZlYWJoJyxcbiAgICAgICAgICAgICdNw6FydCcsXG4gICAgICAgICAgICAnQWliJyxcbiAgICAgICAgICAgICdCZWFsJyxcbiAgICAgICAgICAgICdNZWl0aCcsXG4gICAgICAgICAgICAnScO6aWwnLFxuICAgICAgICAgICAgJ0zDum4nLFxuICAgICAgICAgICAgJ00uRi4nLFxuICAgICAgICAgICAgJ0QuRi4nLFxuICAgICAgICAgICAgJ1NhbWgnLFxuICAgICAgICAgICAgJ05vbGwnLFxuICAgICAgICBdLFxuICAgICAgICB3ZWVrZGF5cyQxID0gW1xuICAgICAgICAgICAgJ0TDqSBEb21obmFpZ2gnLFxuICAgICAgICAgICAgJ0TDqSBMdWFpbicsXG4gICAgICAgICAgICAnRMOpIE3DoWlydCcsXG4gICAgICAgICAgICAnRMOpIEPDqWFkYW9pbicsXG4gICAgICAgICAgICAnRMOpYXJkYW9pbicsXG4gICAgICAgICAgICAnRMOpIGhBb2luZScsXG4gICAgICAgICAgICAnRMOpIFNhdGhhaXJuJyxcbiAgICAgICAgXSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA9IFsnRG9taCcsICdMdWFuJywgJ03DoWlydCcsICdDw6lhZCcsICdEw6lhcicsICdBb2luZScsICdTYXRoJ10sXG4gICAgICAgIHdlZWtkYXlzTWluID0gWydEbycsICdMdScsICdNw6EnLCAnQ8OpJywgJ0TDqScsICdBJywgJ1NhJ107XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2dhJywge1xuICAgICAgICBtb250aHM6IG1vbnRocyQ2LFxuICAgICAgICBtb250aHNTaG9ydDogbW9udGhzU2hvcnQkNSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6IHdlZWtkYXlzJDEsXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6IHdlZWtkYXlzU2hvcnQsXG4gICAgICAgIHdlZWtkYXlzTWluOiB3ZWVrZGF5c01pbixcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tJbm5pdSBhZ10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tBbcOhcmFjaCBhZ10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFthZ10gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tJbm7DqSBhZ10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFtzZW8gY2FpdGVdIFthZ10gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdpICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDDsyBzaGluJyxcbiAgICAgICAgICAgIHM6ICdjw7pwbGEgc29pY2luZCcsXG4gICAgICAgICAgICBzczogJyVkIHNvaWNpbmQnLFxuICAgICAgICAgICAgbTogJ27Ds2ltw6lhZCcsXG4gICAgICAgICAgICBtbTogJyVkIG7Ds2ltw6lhZCcsXG4gICAgICAgICAgICBoOiAndWFpciBhbiBjaGxvaWcnLFxuICAgICAgICAgICAgaGg6ICclZCB1YWlyIGFuIGNobG9pZycsXG4gICAgICAgICAgICBkOiAnbMOhJyxcbiAgICAgICAgICAgIGRkOiAnJWQgbMOhJyxcbiAgICAgICAgICAgIE06ICdtw60nLFxuICAgICAgICAgICAgTU06ICclZCBtw61vbm5hJyxcbiAgICAgICAgICAgIHk6ICdibGlhaW4nLFxuICAgICAgICAgICAgeXk6ICclZCBibGlhaW4nLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZHxuYXxtaCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgb3V0cHV0ID0gbnVtYmVyID09PSAxID8gJ2QnIDogbnVtYmVyICUgMTAgPT09IDIgPyAnbmEnIDogJ21oJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBtb250aHMkNyA9IFtcbiAgICAgICAgICAgICdBbSBGYW9pbGxlYWNoJyxcbiAgICAgICAgICAgICdBbiBHZWFycmFuJyxcbiAgICAgICAgICAgICdBbSBNw6BydCcsXG4gICAgICAgICAgICAnQW4gR2libGVhbicsXG4gICAgICAgICAgICAnQW4gQ8OoaXRlYW4nLFxuICAgICAgICAgICAgJ0FuIHQtw5JnbWhpb3MnLFxuICAgICAgICAgICAgJ0FuIHQtSXVjaGFyJyxcbiAgICAgICAgICAgICdBbiBMw7luYXN0YWwnLFxuICAgICAgICAgICAgJ0FuIHQtU3VsdGFpbicsXG4gICAgICAgICAgICAnQW4gRMOgbWhhaXInLFxuICAgICAgICAgICAgJ0FuIHQtU2FtaGFpbicsXG4gICAgICAgICAgICAnQW4gRMO5YmhsYWNoZCcsXG4gICAgICAgIF0sXG4gICAgICAgIG1vbnRoc1Nob3J0JDYgPSBbXG4gICAgICAgICAgICAnRmFvaScsXG4gICAgICAgICAgICAnR2VhcicsXG4gICAgICAgICAgICAnTcOgcnQnLFxuICAgICAgICAgICAgJ0dpYmwnLFxuICAgICAgICAgICAgJ0PDqGl0JyxcbiAgICAgICAgICAgICfDkmdtaCcsXG4gICAgICAgICAgICAnSXVjaCcsXG4gICAgICAgICAgICAnTMO5bicsXG4gICAgICAgICAgICAnU3VsdCcsXG4gICAgICAgICAgICAnRMOgbWgnLFxuICAgICAgICAgICAgJ1NhbWgnLFxuICAgICAgICAgICAgJ0TDuWJoJyxcbiAgICAgICAgXSxcbiAgICAgICAgd2Vla2RheXMkMiA9IFtcbiAgICAgICAgICAgICdEaWTDsm1obmFpY2gnLFxuICAgICAgICAgICAgJ0RpbHVhaW4nLFxuICAgICAgICAgICAgJ0RpbcOgaXJ0JyxcbiAgICAgICAgICAgICdEaWNpYWRhaW4nLFxuICAgICAgICAgICAgJ0RpYXJkYW9pbicsXG4gICAgICAgICAgICAnRGloYW9pbmUnLFxuICAgICAgICAgICAgJ0Rpc2F0aGFpcm5lJyxcbiAgICAgICAgXSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCQxID0gWydEaWQnLCAnRGlsJywgJ0RpbScsICdEaWMnLCAnRGlhJywgJ0RpaCcsICdEaXMnXSxcbiAgICAgICAgd2Vla2RheXNNaW4kMSA9IFsnRMOyJywgJ0x1JywgJ03DoCcsICdDaScsICdBcicsICdIYScsICdTYSddO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdnZCcsIHtcbiAgICAgICAgbW9udGhzOiBtb250aHMkNyxcbiAgICAgICAgbW9udGhzU2hvcnQ6IG1vbnRoc1Nob3J0JDYsXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiB3ZWVrZGF5cyQyLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiB3ZWVrZGF5c1Nob3J0JDEsXG4gICAgICAgIHdlZWtkYXlzTWluOiB3ZWVrZGF5c01pbiQxLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0FuLWRpdWdoIGFpZ10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tBLW3DoGlyZWFjaCBhaWddIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYWlnXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0FuLWTDqCBhaWddIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbc2VvIGNoYWlkaF0gW2FpZ10gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdhbm4gYW4gJXMnLFxuICAgICAgICAgICAgcGFzdDogJ2JobyBjaGlvbm4gJXMnLFxuICAgICAgICAgICAgczogJ2JlYWdhbiBkaW9nYW4nLFxuICAgICAgICAgICAgc3M6ICclZCBkaW9nYW4nLFxuICAgICAgICAgICAgbTogJ21pb25haWQnLFxuICAgICAgICAgICAgbW06ICclZCBtaW9uYWlkZWFuJyxcbiAgICAgICAgICAgIGg6ICd1YWlyJyxcbiAgICAgICAgICAgIGhoOiAnJWQgdWFpcmVhbicsXG4gICAgICAgICAgICBkOiAnbGF0aGEnLFxuICAgICAgICAgICAgZGQ6ICclZCBsYXRoYScsXG4gICAgICAgICAgICBNOiAnbcOsb3MnLFxuICAgICAgICAgICAgTU06ICclZCBtw6xvc2FuJyxcbiAgICAgICAgICAgIHk6ICdibGlhZGhuYScsXG4gICAgICAgICAgICB5eTogJyVkIGJsaWFkaG5hJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGR8bmF8bWgpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIG91dHB1dCA9IG51bWJlciA9PT0gMSA/ICdkJyA6IG51bWJlciAlIDEwID09PSAyID8gJ25hJyA6ICdtaCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2dsJywge1xuICAgICAgICBtb250aHM6ICd4YW5laXJvX2ZlYnJlaXJvX21hcnpvX2FicmlsX21haW9feHXDsW9feHVsbG9fYWdvc3RvX3NldGVtYnJvX291dHVicm9fbm92ZW1icm9fZGVjZW1icm8nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAneGFuLl9mZWIuX21hci5fYWJyLl9tYWkuX3h1w7EuX3h1bC5fYWdvLl9zZXQuX291dC5fbm92Ll9kZWMuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ2RvbWluZ29fbHVuc19tYXJ0ZXNfbcOpcmNvcmVzX3hvdmVzX3ZlbnJlc19zw6FiYWRvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnZG9tLl9sdW4uX21hci5fbcOpci5feG92Ll92ZW4uX3PDoWIuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ2RvX2x1X21hX23DqV94b192ZV9zw6EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIFtkZV0gTU1NTSBbZGVdIFlZWVkgSDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbaG94ZSAnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICfDoXMnIDogJ8OhJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dERheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW21hw7HDoSAnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICfDoXMnIDogJ8OhJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2RkZGQgWycgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ8OhcycgOiAnYScpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1tvbnRlICcgKyAodGhpcy5ob3VycygpICE9PSAxID8gJ8OhJyA6ICdhJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAnW29dIGRkZGQgW3Bhc2FkbyAnICsgKHRoaXMuaG91cnMoKSAhPT0gMSA/ICfDoXMnIDogJ2EnKSArICddIExUJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RyLmluZGV4T2YoJ3VuJykgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICduJyArIHN0cjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuICdlbiAnICsgc3RyO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhc3Q6ICdoYWkgJXMnLFxuICAgICAgICAgICAgczogJ3VucyBzZWd1bmRvcycsXG4gICAgICAgICAgICBzczogJyVkIHNlZ3VuZG9zJyxcbiAgICAgICAgICAgIG06ICd1biBtaW51dG8nLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dG9zJyxcbiAgICAgICAgICAgIGg6ICd1bmhhIGhvcmEnLFxuICAgICAgICAgICAgaGg6ICclZCBob3JhcycsXG4gICAgICAgICAgICBkOiAndW4gZMOtYScsXG4gICAgICAgICAgICBkZDogJyVkIGTDrWFzJyxcbiAgICAgICAgICAgIE06ICd1biBtZXMnLFxuICAgICAgICAgICAgTU06ICclZCBtZXNlcycsXG4gICAgICAgICAgICB5OiAndW4gYW5vJyxcbiAgICAgICAgICAgIHl5OiAnJWQgYW5vcycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbDogJyVkwronLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICBzOiBbJ+CkpeCli+CkoeCkr+CkviDgpLjgpYXgpJXgpILgpKHgpL7gpILgpKjgpYAnLCAn4KSl4KWL4KSh4KWHIOCkuOClheCkleCkguCkoSddLFxuICAgICAgICAgICAgc3M6IFtudW1iZXIgKyAnIOCkuOClheCkleCkguCkoeCkvuCkguCkqOClgCcsIG51bWJlciArICcg4KS44KWF4KSV4KSC4KShJ10sXG4gICAgICAgICAgICBtOiBbJ+Ckj+CkleCkviDgpK7gpL/gpKPgpJ/gpL7gpKgnLCAn4KSP4KSVIOCkruCkv+CkqOClguCknyddLFxuICAgICAgICAgICAgbW06IFtudW1iZXIgKyAnIOCkruCkv+Cko+Ckn+CkvuCkguCkqOClgCcsIG51bWJlciArICcg4KSu4KS/4KSj4KSf4KS+4KSCJ10sXG4gICAgICAgICAgICBoOiBbJ+Ckj+CkleCkviDgpLXgpLDgpL7gpKgnLCAn4KSP4KSVIOCkteCksCddLFxuICAgICAgICAgICAgaGg6IFtudW1iZXIgKyAnIOCkteCksOCkvuCkguCkqOClgCcsIG51bWJlciArICcg4KS14KSw4KS+4KSCJ10sXG4gICAgICAgICAgICBkOiBbJ+Ckj+CkleCkviDgpKbgpL/gpLjgpL7gpKgnLCAn4KSP4KSVIOCkpuClgOCkuCddLFxuICAgICAgICAgICAgZGQ6IFtudW1iZXIgKyAnIOCkpuCkv+CkuOCkvuCkguCkqOClgCcsIG51bWJlciArICcg4KSm4KWA4KS4J10sXG4gICAgICAgICAgICBNOiBbJ+Ckj+CkleCkviDgpK7gpY3gpLngpK/gpKjgpY3gpK/gpL7gpKgnLCAn4KSP4KSVIOCkruCljeCkueCkr+CkqOCliyddLFxuICAgICAgICAgICAgTU06IFtudW1iZXIgKyAnIOCkruCljeCkueCkr+CkqOCljeCkr+CkvuCkqOClgCcsIG51bWJlciArICcg4KSu4KWN4KS54KSv4KSo4KWHJ10sXG4gICAgICAgICAgICB5OiBbJ+Ckj+CkleCkviDgpLXgpLDgpY3gpLjgpL7gpKgnLCAn4KSP4KSVIOCkteCksOCljeCkuCddLFxuICAgICAgICAgICAgeXk6IFtudW1iZXIgKyAnIOCkteCksOCljeCkuOCkvuCkguCkqOClgCcsIG51bWJlciArICcg4KS14KSw4KWN4KS44KS+4KSCJ10sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBpc0Z1dHVyZSA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdnb20tZGV2YScsIHtcbiAgICAgICAgbW9udGhzOiB7XG4gICAgICAgICAgICBzdGFuZGFsb25lOiAn4KSc4KS+4KSo4KWH4KS14KS+4KSw4KWAX+Ckq+Clh+CkrOCljeCksOClgeCkteCkvuCksOClgF/gpK7gpL7gpLDgpY3gpJpf4KSP4KSq4KWN4KSw4KWA4KSyX+CkruClh1/gpJzgpYLgpKhf4KSc4KWB4KSy4KSvX+CkkeCkl+CkuOCljeCkn1/gpLjgpKrgpY3gpJ/gpYfgpILgpKzgpLBf4KSR4KSV4KWN4KSf4KWL4KSs4KSwX+CkqOCli+CkteCljeCkueClh+CkguCkrOCksF/gpKHgpL/gpLjgpYfgpILgpKzgpLAnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGZvcm1hdDogJ+CknOCkvuCkqOClh+CkteCkvuCksOClgOCkmuCljeCkr+Ckvl/gpKvgpYfgpKzgpY3gpLDgpYHgpLXgpL7gpLDgpYDgpJrgpY3gpK/gpL5f4KSu4KS+4KSw4KWN4KSa4KS+4KSa4KWN4KSv4KS+X+Ckj+CkquCljeCksOClgOCksuCkvuCkmuCljeCkr+Ckvl/gpK7gpYfgpK/gpL7gpJrgpY3gpK/gpL5f4KSc4KWC4KSo4KS+4KSa4KWN4KSv4KS+X+CknOClgeCksuCkr+CkvuCkmuCljeCkr+Ckvl/gpJHgpJfgpLjgpY3gpJ/gpL7gpJrgpY3gpK/gpL5f4KS44KSq4KWN4KSf4KWH4KSC4KSs4KSw4KS+4KSa4KWN4KSv4KS+X+CkkeCkleCljeCkn+Cli+CkrOCksOCkvuCkmuCljeCkr+Ckvl/gpKjgpYvgpLXgpY3gpLngpYfgpILgpKzgpLDgpL7gpJrgpY3gpK/gpL5f4KSh4KS/4KS44KWH4KSC4KSs4KSw4KS+4KSa4KWN4KSv4KS+Jy5zcGxpdChcbiAgICAgICAgICAgICAgICAnXydcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBpc0Zvcm1hdDogL01NTU0oXFxzKStEW29EXT8vLFxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydDogJ+CknOCkvuCkqOClhy5f4KSr4KWH4KSs4KWN4KSw4KWBLl/gpK7gpL7gpLDgpY3gpJpf4KSP4KSq4KWN4KSw4KWALl/gpK7gpYdf4KSc4KWC4KSoX+CknOClgeCksi5f4KSR4KSXLl/gpLjgpKrgpY3gpJ/gpYfgpIIuX+CkkeCkleCljeCkn+Cliy5f4KSo4KWL4KS14KWN4KS54KWH4KSCLl/gpKHgpL/gpLjgpYfgpIIuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ+CkhuCkr+CkpOCkvuCksF/gpLjgpYvgpK7gpL7gpLBf4KSu4KSC4KSX4KSz4KS+4KSwX+CkrOClgeCkp+CkteCkvuCksF/gpKzgpL/gpLDgpYfgpLjgpY3gpKTgpL7gpLBf4KS44KWB4KSV4KWN4KSw4KS+4KSwX+CktuClh+CkqOCkteCkvuCksCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+CkhuCkr+CkpC5f4KS44KWL4KSuLl/gpK7gpILgpJfgpLMuX+CkrOClgeCkpy5f4KSs4KWN4KSw4KWH4KS44KWN4KSkLl/gpLjgpYHgpJXgpY3gpLAuX+CktuClh+CkqC4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4KSGX+CkuOCli1/gpK7gpIJf4KSs4KWBX+CkrOCljeCksOClh1/gpLjgpYFf4KS24KWHJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0EgaDptbSBb4KS14KS+4KSc4KSk4KS+4KSCXScsXG4gICAgICAgICAgICBMVFM6ICdBIGg6bW06c3MgW+CkteCkvuCknOCkpOCkvuCkgl0nLFxuICAgICAgICAgICAgTDogJ0RELU1NLVlZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBBIGg6bW0gW+CkteCkvuCknOCkpOCkvuCkgl0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIE1NTU0gRG8sIFlZWVksIEEgaDptbSBb4KS14KS+4KSc4KSk4KS+4KSCXScsXG4gICAgICAgICAgICBsbGxsOiAnZGRkLCBEIE1NTSBZWVlZLCBBIGg6bW0gW+CkteCkvuCknOCkpOCkvuCkgl0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vgpIbgpK/gpJxdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4KSr4KS+4KSy4KWN4KSv4KS+4KSCXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1vgpKvgpYHgpKHgpLLgpYtdIGRkZGRbLF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vgpJXgpL7gpLJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+Ckq+CkvuCkn+CksuCli10gZGRkZFssXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJyVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDgpIbgpKbgpYDgpIInLFxuICAgICAgICAgICAgczogcHJvY2Vzc1JlbGF0aXZlVGltZSQ0LFxuICAgICAgICAgICAgc3M6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIG06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIG1tOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICBoOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICBoaDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ0LFxuICAgICAgICAgICAgZDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ0LFxuICAgICAgICAgICAgZGQ6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIE06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIE1NOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICB5OiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICB5eTogcHJvY2Vzc1JlbGF0aXZlVGltZSQ0LFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0o4KS14KWH4KSwKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGUgb3JkaW5hbCAn4KS14KWH4KSwJyBvbmx5IGFwcGxpZXMgdG8gZGF5IG9mIHRoZSBtb250aFxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+CkteClh+CksCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICBjYXNlICdRJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrXG4gICAgICAgICAgICBkb3k6IDMsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhciAoNyArIDAgLSA0KVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4KSw4KS+4KSk4KWAfOCkuOCkleCkvuCks+ClgOCkgnzgpKbgpKjgpKrgpL7gpLDgpL7gpIJ84KS44KS+4KSC4KSc4KWHLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSw4KS+4KSk4KWAJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS44KSV4KS+4KSz4KWA4KSCJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkpuCkqOCkquCkvuCksOCkvuCkgicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+IDEyID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgpLjgpL7gpILgpJzgpYcnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSk4KWAJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpLjgpJXgpL7gpLPgpYDgpIInO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CkpuCkqOCkquCkvuCksOCkvuCkgic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KS44KS+4KSC4KSc4KWHJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpLDgpL7gpKTgpYAnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQ1KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgczogWyd0aG9kZGVhIHNla29uZGFtbmknLCAndGhvZGRlIHNla29uZCddLFxuICAgICAgICAgICAgc3M6IFtudW1iZXIgKyAnIHNla29uZGFtbmknLCBudW1iZXIgKyAnIHNla29uZCddLFxuICAgICAgICAgICAgbTogWydla2EgbWludGFuJywgJ2VrIG1pbnV0J10sXG4gICAgICAgICAgICBtbTogW251bWJlciArICcgbWludGFtbmknLCBudW1iZXIgKyAnIG1pbnRhbSddLFxuICAgICAgICAgICAgaDogWydla2Egdm9yYW4nLCAnZWsgdm9yJ10sXG4gICAgICAgICAgICBoaDogW251bWJlciArICcgdm9yYW1uaScsIG51bWJlciArICcgdm9yYW0nXSxcbiAgICAgICAgICAgIGQ6IFsnZWthIGRpc2FuJywgJ2VrIGRpcyddLFxuICAgICAgICAgICAgZGQ6IFtudW1iZXIgKyAnIGRpc2FtbmknLCBudW1iZXIgKyAnIGRpcyddLFxuICAgICAgICAgICAgTTogWydla2EgbWhvaW5lYW4nLCAnZWsgbWhvaW5vJ10sXG4gICAgICAgICAgICBNTTogW251bWJlciArICcgbWhvaW5lYW1uaScsIG51bWJlciArICcgbWhvaW5lJ10sXG4gICAgICAgICAgICB5OiBbJ2VrYSB2b3JzYW4nLCAnZWsgdm9yb3MnXSxcbiAgICAgICAgICAgIHl5OiBbbnVtYmVyICsgJyB2b3JzYW1uaScsIG51bWJlciArICcgdm9yc2FtJ10sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBpc0Z1dHVyZSA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdnb20tbGF0bicsIHtcbiAgICAgICAgbW9udGhzOiB7XG4gICAgICAgICAgICBzdGFuZGFsb25lOiAnSmFuZXJfRmVicmVyX01hcnNfQWJyaWxfTWFpX0p1bl9KdWxhaV9BZ29zdF9TZXRlbWJyX090dWJyX05vdmVtYnJfRGV6ZW1icicuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZm9ybWF0OiAnSmFuZXJhY2hlYV9GZWJyZXJhY2hlYV9NYXJzYWNoZWFfQWJyaWxhY2hlYV9NYWlhY2hlYV9KdW5hY2hlYV9KdWxhaWFjaGVhX0Fnb3N0YWNoZWFfU2V0ZW1icmFjaGVhX090dWJyYWNoZWFfTm92ZW1icmFjaGVhX0RlemVtYnJhY2hlYScuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IC9NTU1NKFxccykrRFtvRF0/LyxcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW4uX0ZlYi5fTWFyc19BYnIuX01haV9KdW5fSnVsLl9BZ28uX1NldC5fT3R1Ll9Ob3YuX0Rlei4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiBcIkFpdGFyX1NvbWFyX01vbmdsbGFyX0J1ZGh2YXJfQmlyZXN0YXJfU3VrcmFyX1Nvbid2YXJcIi5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnQWl0Ll9Tb20uX01vbi5fQnVkLl9CcmUuX1N1ay5fU29uLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdBaV9TbV9Nb19CdV9Ccl9TdV9Tbicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdBIGg6bW0gW3ZhenRhXScsXG4gICAgICAgICAgICBMVFM6ICdBIGg6bW06c3MgW3ZhenRhXScsXG4gICAgICAgICAgICBMOiAnREQtTU0tWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEEgaDptbSBbdmF6dGFdJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBNTU1NIERvLCBZWVlZLCBBIGg6bW0gW3ZhenRhXScsXG4gICAgICAgICAgICBsbGxsOiAnZGRkLCBEIE1NTSBZWVlZLCBBIGg6bW0gW3ZhenRhXScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0Fpel0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tGYWxlYW1dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW0Z1ZGRsb10gZGRkZFssXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0thbF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbRmF0dGxvXSBkZGRkWyxdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIGFkaW0nLFxuICAgICAgICAgICAgczogcHJvY2Vzc1JlbGF0aXZlVGltZSQ1LFxuICAgICAgICAgICAgc3M6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNSxcbiAgICAgICAgICAgIG06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNSxcbiAgICAgICAgICAgIG1tOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDUsXG4gICAgICAgICAgICBoOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDUsXG4gICAgICAgICAgICBoaDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ1LFxuICAgICAgICAgICAgZDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ1LFxuICAgICAgICAgICAgZGQ6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNSxcbiAgICAgICAgICAgIE06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNSxcbiAgICAgICAgICAgIE1NOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDUsXG4gICAgICAgICAgICB5OiBwcm9jZXNzUmVsYXRpdmVUaW1lJDUsXG4gICAgICAgICAgICB5eTogcHJvY2Vzc1JlbGF0aXZlVGltZSQ1LFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZXIpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIC8vIHRoZSBvcmRpbmFsICdlcicgb25seSBhcHBsaWVzIHRvIGRheSBvZiB0aGUgbW9udGhcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICdlcic7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICBjYXNlICdRJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrXG4gICAgICAgICAgICBkb3k6IDMsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhciAoNyArIDAgLSA0KVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAvcmF0aXxzb2thbGxpbXxkb25wYXJhbXxzYW5qZS8sXG4gICAgICAgIG1lcmlkaWVtSG91cjogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ3JhdGknKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzb2thbGxpbScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdkb25wYXJhbScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+IDEyID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzYW5qZScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdyYXRpJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdzb2thbGxpbSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNikge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZG9ucGFyYW0nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3NhbmplJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdyYXRpJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkNyA9IHtcbiAgICAgICAgICAgIDE6ICfgq6cnLFxuICAgICAgICAgICAgMjogJ+CrqCcsXG4gICAgICAgICAgICAzOiAn4KupJyxcbiAgICAgICAgICAgIDQ6ICfgq6onLFxuICAgICAgICAgICAgNTogJ+CrqycsXG4gICAgICAgICAgICA2OiAn4KusJyxcbiAgICAgICAgICAgIDc6ICfgq60nLFxuICAgICAgICAgICAgODogJ+CrricsXG4gICAgICAgICAgICA5OiAn4KuvJyxcbiAgICAgICAgICAgIDA6ICfgq6YnLFxuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAkNiA9IHtcbiAgICAgICAgICAgICfgq6cnOiAnMScsXG4gICAgICAgICAgICAn4KuoJzogJzInLFxuICAgICAgICAgICAgJ+CrqSc6ICczJyxcbiAgICAgICAgICAgICfgq6onOiAnNCcsXG4gICAgICAgICAgICAn4KurJzogJzUnLFxuICAgICAgICAgICAgJ+CrrCc6ICc2JyxcbiAgICAgICAgICAgICfgq60nOiAnNycsXG4gICAgICAgICAgICAn4KuuJzogJzgnLFxuICAgICAgICAgICAgJ+Crryc6ICc5JyxcbiAgICAgICAgICAgICfgq6YnOiAnMCcsXG4gICAgICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2d1Jywge1xuICAgICAgICBtb250aHM6ICfgqpzgqr7gqqjgq43gqq/gq4HgqobgqrDgq4Bf4Kqr4KuH4Kqs4KuN4Kqw4KuB4KqG4Kqw4KuAX+CqruCqvuCqsOCrjeCqml/gqo/gqqrgq43gqrDgqr/gqrJf4Kqu4KuHX+CqnOCrguCqqF/gqpzgq4HgqrLgqr7gqohf4KqR4KqX4Kq44KuN4KqfX+CquOCqquCrjeCqn+Crh+CqruCrjeCqrOCqsF/gqpHgqpXgq43gqp/gq43gqqzgqrBf4Kqo4Kq14KuH4Kqu4KuN4Kqs4KqwX+CqoeCqv+CquOCrh+CqruCrjeCqrOCqsCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgqpzgqr7gqqjgq43gqq/gq4EuX+Cqq+Crh+CqrOCrjeCqsOCrgS5f4Kqu4Kq+4Kqw4KuN4KqaX+Cqj+CqquCrjeCqsOCqvy5f4Kqu4KuHX+CqnOCrguCqqF/gqpzgq4HgqrLgqr4uX+CqkeCqly5f4Kq44Kqq4KuN4Kqf4KuHLl/gqpHgqpXgq43gqp/gq40uX+CqqOCqteCrhy5f4Kqh4Kq/4Kq44KuHLicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6ICfgqrDgqrXgqr/gqrXgqr7gqrBf4Kq44KuL4Kqu4Kq14Kq+4KqwX+CqruCqguCql+Cqs+CqteCqvuCqsF/gqqzgq4Hgqqfgq43gqrXgqr7gqrBf4KqX4KuB4Kqw4KuB4Kq14Kq+4KqwX+CqtuCrgeCqleCrjeCqsOCqteCqvuCqsF/gqrbgqqjgqr/gqrXgqr7gqrAnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfgqrDgqrXgqr9f4Kq44KuL4KquX+CqruCqguCql+Cqs1/gqqzgq4Hgqqfgq41f4KqX4KuB4Kqw4KuBX+CqtuCrgeCqleCrjeCqsF/gqrbgqqjgqr8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4KqwX+CquOCri1/gqq7gqoJf4Kqs4KuBX+Cql+CrgV/gqrbgq4Ff4Kq2Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdBIGg6bW0g4Kq14Kq+4KqX4KuN4Kqv4KuHJyxcbiAgICAgICAgICAgIExUUzogJ0EgaDptbTpzcyDgqrXgqr7gqpfgq43gqq/gq4cnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCqteCqvuCql+CrjeCqr+CrhycsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgqrXgqr7gqpfgq43gqq/gq4cnLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vgqobgqpxdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4KqV4Kq+4Kqy4KuHXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQsIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4KqX4KqH4KqV4Kq+4Kqy4KuHXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vgqqrgqr7gqpvgqrLgqr5dIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg4Kqu4Kq+JyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDgqqrgqrngq4fgqrLgqr4nLFxuICAgICAgICAgICAgczogJ+CqheCqruCrgeCqlSDgqqrgqrPgq4snLFxuICAgICAgICAgICAgc3M6ICclZCDgqrjgq4fgqpXgqoLgqqEnLFxuICAgICAgICAgICAgbTogJ+Cqj+CqlSDgqq7gqr/gqqjgqr/gqp8nLFxuICAgICAgICAgICAgbW06ICclZCDgqq7gqr/gqqjgqr/gqp8nLFxuICAgICAgICAgICAgaDogJ+Cqj+CqlSDgqpXgqrLgqr7gqpUnLFxuICAgICAgICAgICAgaGg6ICclZCDgqpXgqrLgqr7gqpUnLFxuICAgICAgICAgICAgZDogJ+Cqj+CqlSDgqqbgqr/gqrXgqrgnLFxuICAgICAgICAgICAgZGQ6ICclZCDgqqbgqr/gqrXgqrgnLFxuICAgICAgICAgICAgTTogJ+Cqj+CqlSDgqq7gqrngqr/gqqjgq4snLFxuICAgICAgICAgICAgTU06ICclZCDgqq7gqrngqr/gqqjgq4snLFxuICAgICAgICAgICAgeTogJ+Cqj+CqlSDgqrXgqrDgq43gqrcnLFxuICAgICAgICAgICAgeXk6ICclZCDgqrXgqrDgq43gqrcnLFxuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4Kun4Kuo4Kup4Kuq4Kur4Kus4Kut4Kuu4Kuv4KumXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDZbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXAkN1ttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgLy8gR3VqYXJhdGkgbm90YXRpb24gZm9yIG1lcmlkaWVtcyBhcmUgcXVpdGUgZnV6enkgaW4gcHJhY3RpY2UuIFdoaWxlIHRoZXJlIGV4aXN0c1xuICAgICAgICAvLyBhIHJpZ2lkIG5vdGlvbiBvZiBhICdQYWhhcicgaXQgaXMgbm90IHVzZWQgYXMgcmlnaWRseSBpbiBtb2Rlcm4gR3VqYXJhdGkuXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gqrDgqr7gqqR84Kqs4Kqq4KuL4KqwfOCquOCqteCqvuCqsHzgqrjgqr7gqoLgqpwvLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgqrDgqr7gqqQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqrjgqrXgqr7gqrAnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Kqs4Kqq4KuL4KqwJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqrjgqr7gqoLgqpwnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kqw4Kq+4KqkJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgqrjgqrXgqr7gqrAnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CqrOCqquCri+CqsCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kq44Kq+4KqC4KqcJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgqrDgqr7gqqQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA2LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA2dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2hlJywge1xuICAgICAgICBtb250aHM6ICfXmdeg15XXkNeoX9ek15HXqNeV15DXqF/Xnteo16Vf15DXpNeo15nXnF/XnteQ15lf15nXldeg15lf15nXldec15lf15DXldeS15XXodeYX9eh16TXmNee15HXqF/XkNeV16fXmNeV15HXqF/XoNeV15HXnteR16hf15PXptee15HXqCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfXmdeg15XXs1/XpNeR16jXs1/Xnteo16Vf15DXpNeo17Nf157XkNeZX9eZ15XXoNeZX9eZ15XXnNeZX9eQ15XXktezX9eh16TXmNezX9eQ15XXp9ezX9eg15XXkdezX9eT16bXntezJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ9eo15DXqdeV159f16nXoNeZX9ep15zXmdep15lf16jXkdeZ16LXmV/Xl9ee15nXqdeZX9ep15nXqdeZX9ep15HXqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9eQ17Nf15HXs1/XktezX9eT17Nf15TXs1/XldezX9ep17MnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn15Bf15Ff15Jf15Nf15Rf15Vf16knLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBb15FdTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgW9eRXU1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBb15FdTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIGw6ICdEL00vWVlZWScsXG4gICAgICAgICAgICBsbDogJ0QgTU1NIFlZWVknLFxuICAgICAgICAgICAgbGxsOiAnRCBNTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBsbGxsOiAnZGRkLCBEIE1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb15TXmdeV150g15HWvl1MVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9ee15fXqCDXkda+XUxUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb15HXqdei15RdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb15DXqtee15XXnCDXkda+XUxUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW9eR15nXldedXSBkZGRkIFvXlNeQ15fXqNeV158g15HXqdei15RdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAn15HXoteV15MgJXMnLFxuICAgICAgICAgICAgcGFzdDogJ9ec16TXoNeZICVzJyxcbiAgICAgICAgICAgIHM6ICfXnteh16TXqCDXqdeg15nXldeqJyxcbiAgICAgICAgICAgIHNzOiAnJWQg16nXoNeZ15XXqicsXG4gICAgICAgICAgICBtOiAn15PXp9eUJyxcbiAgICAgICAgICAgIG1tOiAnJWQg15PXp9eV16onLFxuICAgICAgICAgICAgaDogJ9ep16LXlCcsXG4gICAgICAgICAgICBoaDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICfXqdei16rXmdeZ150nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXqdei15XXqic7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZDogJ9eZ15XXnScsXG4gICAgICAgICAgICBkZDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICfXmdeV157XmdeZ150nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXmdee15nXnSc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgTTogJ9eX15XXk9epJyxcbiAgICAgICAgICAgIE1NOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ9eX15XXk9ep15nXmdedJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcg15fXldeT16nXmdedJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB5OiAn16nXoNeUJyxcbiAgICAgICAgICAgIHl5OiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ9ep16DXqteZ15nXnSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgJSAxMCA9PT0gMCAmJiBudW1iZXIgIT09IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnINep16DXlCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnINep16DXmdedJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/XkNeX15RcItemfNec16TXoNeUXCLXpnzXkNeX16jXmSDXlNem15TXqNeZ15nXnXzXnNek16DXmSDXlNem15TXqNeZ15nXnXzXnNek16DXldeqINeR15XXp9eofNeR15HXlden16h815HXoteo15EvaSxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gL14o15DXl9eUXCLXpnzXkNeX16jXmSDXlNem15TXqNeZ15nXnXzXkdei16jXkSkkLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn15zXpNeg15XXqiDXkdeV16fXqCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn15HXkdeV16fXqCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ9ec16TXoNeUXCLXpicgOiAn15zXpNeg15kg15TXpteU16jXmdeZ150nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfXkNeX15RcItemJyA6ICfXkNeX16jXmSDXlNem15TXqNeZ15nXnSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn15HXoteo15EnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCQ4ID0ge1xuICAgICAgICAgICAgMTogJ+ClpycsXG4gICAgICAgICAgICAyOiAn4KWoJyxcbiAgICAgICAgICAgIDM6ICfgpaknLFxuICAgICAgICAgICAgNDogJ+ClqicsXG4gICAgICAgICAgICA1OiAn4KWrJyxcbiAgICAgICAgICAgIDY6ICfgpawnLFxuICAgICAgICAgICAgNzogJ+ClrScsXG4gICAgICAgICAgICA4OiAn4KWuJyxcbiAgICAgICAgICAgIDk6ICfgpa8nLFxuICAgICAgICAgICAgMDogJ+ClpicsXG4gICAgICAgIH0sXG4gICAgICAgIG51bWJlck1hcCQ3ID0ge1xuICAgICAgICAgICAgJ+Clpyc6ICcxJyxcbiAgICAgICAgICAgICfgpagnOiAnMicsXG4gICAgICAgICAgICAn4KWpJzogJzMnLFxuICAgICAgICAgICAgJ+Clqic6ICc0JyxcbiAgICAgICAgICAgICfgpasnOiAnNScsXG4gICAgICAgICAgICAn4KWsJzogJzYnLFxuICAgICAgICAgICAgJ+ClrSc6ICc3JyxcbiAgICAgICAgICAgICfgpa4nOiAnOCcsXG4gICAgICAgICAgICAn4KWvJzogJzknLFxuICAgICAgICAgICAgJ+Clpic6ICcwJyxcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzUGFyc2UkNyA9IFtcbiAgICAgICAgICAgIC9e4KSc4KSoL2ksXG4gICAgICAgICAgICAvXuCkq+CkvOCksHzgpKvgpLAvaSxcbiAgICAgICAgICAgIC9e4KSu4KS+4KSw4KWN4KSaL2ksXG4gICAgICAgICAgICAvXuCkheCkquCljeCksOCliC9pLFxuICAgICAgICAgICAgL17gpK7gpIgvaSxcbiAgICAgICAgICAgIC9e4KSc4KWC4KSoL2ksXG4gICAgICAgICAgICAvXuCknOClgeCksi9pLFxuICAgICAgICAgICAgL17gpIXgpJcvaSxcbiAgICAgICAgICAgIC9e4KS44KS/4KSk4KSCfOCkuOCkv+CkpC9pLFxuICAgICAgICAgICAgL17gpIXgpJXgpY3gpJ/gpYIvaSxcbiAgICAgICAgICAgIC9e4KSo4KS1fOCkqOCkteCkgi9pLFxuICAgICAgICAgICAgL17gpKbgpL/gpLjgpIJ84KSm4KS/4KS4L2ksXG4gICAgICAgIF0sXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2UgPSBbXG4gICAgICAgICAgICAvXuCknOCkqC9pLFxuICAgICAgICAgICAgL17gpKvgpLzgpLAvaSxcbiAgICAgICAgICAgIC9e4KSu4KS+4KSw4KWN4KSaL2ksXG4gICAgICAgICAgICAvXuCkheCkquCljeCksOCliC9pLFxuICAgICAgICAgICAgL17gpK7gpIgvaSxcbiAgICAgICAgICAgIC9e4KSc4KWC4KSoL2ksXG4gICAgICAgICAgICAvXuCknOClgeCksi9pLFxuICAgICAgICAgICAgL17gpIXgpJcvaSxcbiAgICAgICAgICAgIC9e4KS44KS/4KSkL2ksXG4gICAgICAgICAgICAvXuCkheCkleCljeCkn+Clgi9pLFxuICAgICAgICAgICAgL17gpKjgpLUvaSxcbiAgICAgICAgICAgIC9e4KSm4KS/4KS4L2ksXG4gICAgICAgIF07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2hpJywge1xuICAgICAgICBtb250aHM6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ+CknOCkqOCkteCksOClgF/gpKvgpLzgpLDgpLXgpLDgpYBf4KSu4KS+4KSw4KWN4KSaX+CkheCkquCljeCksOCliOCksl/gpK7gpIhf4KSc4KWC4KSoX+CknOClgeCksuCkvuCkiF/gpIXgpJfgpLjgpY3gpKRf4KS44KS/4KSk4KSu4KWN4KSs4KSwX+CkheCkleCljeCkn+ClguCkrOCksF/gpKjgpLXgpK7gpY3gpKzgpLBf4KSm4KS/4KS44KSu4KWN4KSs4KSwJy5zcGxpdChcbiAgICAgICAgICAgICAgICAnXydcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBzdGFuZGFsb25lOiAn4KSc4KSo4KS14KSw4KWAX+Ckq+CksOCkteCksOClgF/gpK7gpL7gpLDgpY3gpJpf4KSF4KSq4KWN4KSw4KWI4KSyX+CkruCkiF/gpJzgpYLgpKhf4KSc4KWB4KSy4KS+4KSIX+CkheCkl+CkuOCljeCkpF/gpLjgpL/gpKTgpILgpKzgpLBf4KSF4KSV4KWN4KSf4KWC4KSs4KSwX+CkqOCkteCkguCkrOCksF/gpKbgpL/gpLjgpILgpKzgpLAnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgpJzgpKguX+Ckq+CkvOCksC5f4KSu4KS+4KSw4KWN4KSaX+CkheCkquCljeCksOCliC5f4KSu4KSIX+CknOClguCkqF/gpJzgpYHgpLIuX+CkheCkly5f4KS44KS/4KSkLl/gpIXgpJXgpY3gpJ/gpYIuX+CkqOCktS5f4KSm4KS/4KS4Licuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfgpLDgpLXgpL/gpLXgpL7gpLBf4KS44KWL4KSu4KS14KS+4KSwX+CkruCkguCkl+CksuCkteCkvuCksF/gpKzgpYHgpKfgpLXgpL7gpLBf4KSX4KWB4KSw4KWC4KS14KS+4KSwX+CktuClgeCkleCljeCksOCkteCkvuCksF/gpLbgpKjgpL/gpLXgpL7gpLAnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfgpLDgpLXgpL9f4KS44KWL4KSuX+CkruCkguCkl+Cksl/gpKzgpYHgpKdf4KSX4KWB4KSw4KWCX+CktuClgeCkleCljeCksF/gpLbgpKjgpL8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4KSwX+CkuOCli1/gpK7gpIJf4KSs4KWBX+Ckl+ClgV/gpLbgpYFf4KS2Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdBIGg6bW0g4KSs4KSc4KWHJyxcbiAgICAgICAgICAgIExUUzogJ0EgaDptbTpzcyDgpKzgpJzgpYcnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCkrOCknOClhycsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgpKzgpJzgpYcnLFxuICAgICAgICB9LFxuXG4gICAgICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQ3LFxuICAgICAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDcsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IHNob3J0TW9udGhzUGFyc2UsXG5cbiAgICAgICAgbW9udGhzUmVnZXg6IC9eKOCknOCkqOCkteCksOClgHzgpJzgpKhcXC4/fOCkq+CkvOCksOCkteCksOClgHzgpKvgpLDgpLXgpLDgpYB84KSr4KS84KSwXFwuP3zgpK7gpL7gpLDgpY3gpJo/fOCkheCkquCljeCksOCliOCksnzgpIXgpKrgpY3gpLDgpYhcXC4/fOCkruCkiD984KSc4KWC4KSoP3zgpJzgpYHgpLLgpL7gpIh84KSc4KWB4KSyXFwuP3zgpIXgpJfgpLjgpY3gpKR84KSF4KSXXFwuP3zgpLjgpL/gpKTgpK7gpY3gpKzgpLB84KS44KS/4KSk4KSC4KSs4KSwfOCkuOCkv+CkpFxcLj984KSF4KSV4KWN4KSf4KWC4KSs4KSwfOCkheCkleCljeCkn+ClglxcLj984KSo4KS14KSu4KWN4KSs4KSwfOCkqOCkteCkguCkrOCksHzgpKjgpLVcXC4/fOCkpuCkv+CkuOCkruCljeCkrOCksHzgpKbgpL/gpLjgpILgpKzgpLB84KSm4KS/4KS4XFwuPykvaSxcblxuICAgICAgICBtb250aHNTaG9ydFJlZ2V4OiAvXijgpJzgpKjgpLXgpLDgpYB84KSc4KSoXFwuP3zgpKvgpLzgpLDgpLXgpLDgpYB84KSr4KSw4KS14KSw4KWAfOCkq+CkvOCksFxcLj984KSu4KS+4KSw4KWN4KSaP3zgpIXgpKrgpY3gpLDgpYjgpLJ84KSF4KSq4KWN4KSw4KWIXFwuP3zgpK7gpIg/fOCknOClguCkqD984KSc4KWB4KSy4KS+4KSIfOCknOClgeCkslxcLj984KSF4KSX4KS44KWN4KSkfOCkheCkl1xcLj984KS44KS/4KSk4KSu4KWN4KSs4KSwfOCkuOCkv+CkpOCkguCkrOCksHzgpLjgpL/gpKRcXC4/fOCkheCkleCljeCkn+ClguCkrOCksHzgpIXgpJXgpY3gpJ/gpYJcXC4/fOCkqOCkteCkruCljeCkrOCksHzgpKjgpLXgpILgpKzgpLB84KSo4KS1XFwuP3zgpKbgpL/gpLjgpK7gpY3gpKzgpLB84KSm4KS/4KS44KSC4KSs4KSwfOCkpuCkv+CkuFxcLj8pL2ksXG5cbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKOCknOCkqOCkteCksOClgD984KSr4KS84KSw4KS14KSw4KWAfOCkq+CksOCkteCksOClgD984KSu4KS+4KSw4KWN4KSaP3zgpIXgpKrgpY3gpLDgpYjgpLI/fOCkruCkiD984KSc4KWC4KSoP3zgpJzgpYHgpLLgpL7gpIg/fOCkheCkl+CkuOCljeCkpD984KS44KS/4KSk4KSu4KWN4KSs4KSwfOCkuOCkv+CkpOCkguCkrOCksHzgpLjgpL/gpKQ/XFwuP3zgpIXgpJXgpY3gpJ/gpYLgpKzgpLB84KSF4KSV4KWN4KSf4KWCXFwuP3zgpKjgpLXgpK7gpY3gpKzgpLB84KSo4KS14KSC4KSs4KSwP3zgpKbgpL/gpLjgpK7gpY3gpKzgpLB84KSm4KS/4KS44KSC4KSs4KSwPykvaSxcblxuICAgICAgICBtb250aHNTaG9ydFN0cmljdFJlZ2V4OiAvXijgpJzgpKhcXC4/fOCkq+CkvOCksFxcLj984KSu4KS+4KSw4KWN4KSaP3zgpIXgpKrgpY3gpLDgpYhcXC4/fOCkruCkiD984KSc4KWC4KSoP3zgpJzgpYHgpLJcXC4/fOCkheCkl1xcLj984KS44KS/4KSkXFwuP3zgpIXgpJXgpY3gpJ/gpYJcXC4/fOCkqOCktVxcLj984KSm4KS/4KS4XFwuPykvaSxcblxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vgpIbgpJxdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4KSV4KSyXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQsIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4KSV4KSyXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vgpKrgpL/gpJvgpLLgpYddIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg4KSu4KWH4KSCJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDgpKrgpLngpLLgpYcnLFxuICAgICAgICAgICAgczogJ+CkleClgeCkmyDgpLngpYAg4KSV4KWN4KS34KSjJyxcbiAgICAgICAgICAgIHNzOiAnJWQg4KS44KWH4KSV4KSC4KShJyxcbiAgICAgICAgICAgIG06ICfgpI/gpJUg4KSu4KS/4KSo4KSfJyxcbiAgICAgICAgICAgIG1tOiAnJWQg4KSu4KS/4KSo4KSfJyxcbiAgICAgICAgICAgIGg6ICfgpI/gpJUg4KSY4KSC4KSf4KS+JyxcbiAgICAgICAgICAgIGhoOiAnJWQg4KSY4KSC4KSf4KWHJyxcbiAgICAgICAgICAgIGQ6ICfgpI/gpJUg4KSm4KS/4KSoJyxcbiAgICAgICAgICAgIGRkOiAnJWQg4KSm4KS/4KSoJyxcbiAgICAgICAgICAgIE06ICfgpI/gpJUg4KSu4KS54KWA4KSo4KWHJyxcbiAgICAgICAgICAgIE1NOiAnJWQg4KSu4KS54KWA4KSo4KWHJyxcbiAgICAgICAgICAgIHk6ICfgpI/gpJUg4KS14KSw4KWN4KS3JyxcbiAgICAgICAgICAgIHl5OiAnJWQg4KS14KSw4KWN4KS3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Clp+ClqOClqeClquClq+ClrOClreClruClr+Clpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCQ3W21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDhbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIC8vIEhpbmRpIG5vdGF0aW9uIGZvciBtZXJpZGllbXMgYXJlIHF1aXRlIGZ1enp5IGluIHByYWN0aWNlLiBXaGlsZSB0aGVyZSBleGlzdHNcbiAgICAgICAgLy8gYSByaWdpZCBub3Rpb24gb2YgYSAnUGFoYXInIGl0IGlzIG5vdCB1c2VkIGFzIHJpZ2lkbHkgaW4gbW9kZXJuIEhpbmRpLlxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4KSw4KS+4KSkfOCkuOClgeCkrOCkuXzgpKbgpYvgpKrgpLngpLB84KS24KS+4KSuLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSw4KS+4KSkJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS44KWB4KSs4KS5Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkpuCli+CkquCkueCksCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS24KS+4KSuJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CksOCkvuCkpCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KS44KWB4KSs4KS5JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpKbgpYvgpKrgpLngpLAnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CktuCkvuCkric7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSkJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNiwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlJDMobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kYSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3Nla3VuZGUnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kaSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdqZWRuYSBtaW51dGEnIDogJ2plZG5lIG1pbnV0ZSc7XG4gICAgICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21pbnV0YSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21pbnV0ZSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtaW51dGEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnamVkYW4gc2F0JyA6ICdqZWRub2cgc2F0YSc7XG4gICAgICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3NhdCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3NhdGEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2F0aSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2Rhbic7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdkYW5hJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWplc2VjJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWplc2VjYSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWNpJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZ29kaW5hJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZ29kaW5lJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2dvZGluYSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2hyJywge1xuICAgICAgICBtb250aHM6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ3NpamXEjW5qYV92ZWxqYcSNZV9vxb51amthX3RyYXZuamFfc3ZpYm5qYV9saXBuamFfc3JwbmphX2tvbG92b3phX3J1am5hX2xpc3RvcGFkYV9zdHVkZW5vZ2FfcHJvc2luY2EnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICdzaWplxI1hbmpfdmVsamHEjWFfb8W+dWpha190cmF2YW5qX3N2aWJhbmpfbGlwYW5qX3NycGFual9rb2xvdm96X3J1amFuX2xpc3RvcGFkX3N0dWRlbmlfcHJvc2luYWMnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdzaWouX3ZlbGouX2/FvnUuX3RyYS5fc3ZpLl9saXAuX3NycC5fa29sLl9ydWouX2xpcy5fc3R1Ll9wcm8uJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ25lZGplbGphX3BvbmVkamVsamFrX3V0b3Jha19zcmlqZWRhX8SNZXR2cnRha19wZXRha19zdWJvdGEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICduZWQuX3Bvbi5fdXRvLl9zcmkuX8SNZXQuX3BldC5fc3ViLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICduZV9wb191dF9zcl/EjWVfcGVfc3UnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRG8gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0RvIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEbyBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2RhbmFzIHVdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbc3V0cmEgdV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW25lZGplbGp1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbc3JpamVkdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3N1Ym90dV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5OiAnW2p1xI1lciB1XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcm/FoWx1XSBbbmVkamVsanVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbHVdIFtzcmlqZWR1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcm/FoWxlXSBbc3Vib3RlXSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcm/FoWxpXSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnemEgJXMnLFxuICAgICAgICAgICAgcGFzdDogJ3ByaWplICVzJyxcbiAgICAgICAgICAgIHM6ICdwYXIgc2VrdW5kaScsXG4gICAgICAgICAgICBzczogdHJhbnNsYXRlJDMsXG4gICAgICAgICAgICBtOiB0cmFuc2xhdGUkMyxcbiAgICAgICAgICAgIG1tOiB0cmFuc2xhdGUkMyxcbiAgICAgICAgICAgIGg6IHRyYW5zbGF0ZSQzLFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0ZSQzLFxuICAgICAgICAgICAgZDogJ2RhbicsXG4gICAgICAgICAgICBkZDogdHJhbnNsYXRlJDMsXG4gICAgICAgICAgICBNOiAnbWplc2VjJyxcbiAgICAgICAgICAgIE1NOiB0cmFuc2xhdGUkMyxcbiAgICAgICAgICAgIHk6ICdnb2RpbnUnLFxuICAgICAgICAgICAgeXk6IHRyYW5zbGF0ZSQzLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNywgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHdlZWtFbmRpbmdzID0gJ3Zhc8Ohcm5hcCBow6l0ZsWRbiBrZWRkZW4gc3plcmTDoW4gY3PDvHTDtnJ0w7Zrw7ZuIHDDqW50ZWtlbiBzem9tYmF0b24nLnNwbGl0KFxuICAgICAgICAnICdcbiAgICApO1xuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZSQ0KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgbnVtID0gbnVtYmVyO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXhcbiAgICAgICAgICAgICAgICAgICAgPyAnbsOpaMOhbnkgbcOhc29kcGVyYydcbiAgICAgICAgICAgICAgICAgICAgOiAnbsOpaMOhbnkgbcOhc29kcGVyY2UnO1xuICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeClcbiAgICAgICAgICAgICAgICAgICAgPyAnIG3DoXNvZHBlcmMnXG4gICAgICAgICAgICAgICAgICAgIDogJyBtw6Fzb2RwZXJjZSc7XG4gICAgICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2VneScgKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgcGVyYycgOiAnIHBlcmNlJyk7XG4gICAgICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBwZXJjJyA6ICcgcGVyY2UnKTtcbiAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyDDs3JhJyA6ICcgw7Nyw6FqYScpO1xuICAgICAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgw7NyYScgOiAnIMOzcsOhamEnKTtcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBuYXAnIDogJyBuYXBqYScpO1xuICAgICAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgbmFwJyA6ICcgbmFwamEnKTtcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBow7NuYXAnIDogJyBow7NuYXBqYScpO1xuICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgaMOzbmFwJyA6ICcgaMOzbmFwamEnKTtcbiAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyDDqXYnIDogJyDDqXZlJyk7XG4gICAgICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyDDqXYnIDogJyDDqXZlJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICBmdW5jdGlvbiB3ZWVrKGlzRnV0dXJlKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAoaXNGdXR1cmUgPyAnJyA6ICdbbcO6bHRdICcpICtcbiAgICAgICAgICAgICdbJyArXG4gICAgICAgICAgICB3ZWVrRW5kaW5nc1t0aGlzLmRheSgpXSArXG4gICAgICAgICAgICAnXSBMVFsta29yXSdcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2h1Jywge1xuICAgICAgICBtb250aHM6ICdqYW51w6FyX2ZlYnJ1w6FyX23DoXJjaXVzX8OhcHJpbGlzX23DoWp1c19qw7puaXVzX2rDumxpdXNfYXVndXN6dHVzX3N6ZXB0ZW1iZXJfb2t0w7NiZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnamFuLl9mZWIuX23DoXJjLl/DoXByLl9tw6FqLl9qw7puLl9qw7psLl9hdWcuX3N6ZXB0Ll9va3QuX25vdi5fZGVjLicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6ICd2YXPDoXJuYXBfaMOpdGbFkV9rZWRkX3N6ZXJkYV9jc8O8dMO2cnTDtmtfcMOpbnRla19zem9tYmF0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAndmFzX2jDqXRfa2VkZF9zemVfY3PDvHRfcMOpbl9zem8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAndl9oX2tfc3plX2NzX3Bfc3pvJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTDogJ1lZWVkuTU0uREQuJyxcbiAgICAgICAgICAgIExMOiAnWVlZWS4gTU1NTSBELicsXG4gICAgICAgICAgICBMTEw6ICdZWVlZLiBNTU1NIEQuIEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ1lZWVkuIE1NTU0gRC4sIGRkZGQgSDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9kZXxkdS9pLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dC5jaGFyQXQoMSkudG9Mb3dlckNhc2UoKSA9PT0gJ3UnO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID09PSB0cnVlID8gJ2RlJyA6ICdERSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID09PSB0cnVlID8gJ2R1JyA6ICdEVSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW21hXSBMVFsta29yXScsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW2hvbG5hcF0gTFRbLWtvcl0nLFxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd2Vlay5jYWxsKHRoaXMsIHRydWUpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbdGVnbmFwXSBMVFsta29yXScsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ZWVrLmNhbGwodGhpcywgZmFsc2UpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMgbcO6bHZhJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcycsXG4gICAgICAgICAgICBzOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgICAgIHNzOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgICAgIG06IHRyYW5zbGF0ZSQ0LFxuICAgICAgICAgICAgbW06IHRyYW5zbGF0ZSQ0LFxuICAgICAgICAgICAgaDogdHJhbnNsYXRlJDQsXG4gICAgICAgICAgICBoaDogdHJhbnNsYXRlJDQsXG4gICAgICAgICAgICBkOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgICAgIGRkOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgICAgIE06IHRyYW5zbGF0ZSQ0LFxuICAgICAgICAgICAgTU06IHRyYW5zbGF0ZSQ0LFxuICAgICAgICAgICAgeTogdHJhbnNsYXRlJDQsXG4gICAgICAgICAgICB5eTogdHJhbnNsYXRlJDQsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2h5LWFtJywge1xuICAgICAgICBtb250aHM6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ9Ww1bjWgtW21b7VodaA1atf1oPVpdW/1oDVvtWh1oDVq1/VtNWh1oDVv9WrX9Wh1brWgNWr1azVq1/VtNWh1bXVq9W91atf1bDVuNaC1bbVq9W91atf1bDVuNaC1azVq9W91atf1oXVo9W41b3Vv9W41b3Vq1/VvdWl1brVv9Wl1bTVotWl1oDVq1/VsNW41a/Vv9Wl1bTVotWl1oDVq1/VttW41bXVpdW01aLVpdaA1atf1aTVpdWv1b/VpdW01aLVpdaA1asnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICfVsNW41oLVttW+1aHWgF/Wg9Wl1b/WgNW+1aHWgF/VtNWh1oDVv1/VodW61oDVq9WsX9W01aHVtdWr1b1f1bDVuNaC1bbVq9W9X9Ww1bjWgtWs1avVvV/WhdWj1bjVvdW/1bjVvV/VvdWl1brVv9Wl1bTVotWl1oBf1bDVuNWv1b/VpdW01aLVpdaAX9W21bjVtdWl1bTVotWl1oBf1aTVpdWv1b/VpdW01aLVpdaAJy5zcGxpdChcbiAgICAgICAgICAgICAgICAnXydcbiAgICAgICAgICAgICksXG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn1bDVttW+X9aD1b/WgF/VtNaA1b9f1aHVutaAX9W01bXVvV/VsNW21b1f1bDVrNW9X9aF1aPVvV/VvdW61b9f1bDVr9W/X9W21bTVol/VpNWv1b8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAn1a/Vq9aA1aHVr9WrX9Wl1oDVr9W41oLVt9Wh1aLVqdWrX9Wl1oDVpdaE1bfVodWi1anVq1/VudW41oDVpdaE1bfVodWi1anVq1/VsNWr1bbVo9W31aHVotWp1atf1bjWgtaA1aLVodWpX9W31aHVotWh1aknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfVr9aA1a9f1aXWgNWvX9Wl1oDWhF/VudaA1oRf1bDVttWjX9W41oLWgNWiX9W31aLVqScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfVr9aA1a9f1aXWgNWvX9Wl1oDWhF/VudaA1oRf1bDVttWjX9W41oLWgNWiX9W31aLVqScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWSDVqS4nLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkg1akuLCBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkg1akuLCBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9Wh1bXVvdaF1oBdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb1b7VodWy1ahdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb1aXWgNWl1a9dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdkZGRkIFvWhdaA1agg1arVodW01ahdIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW9Wh1bbWgdWh1a5dIGRkZGQgW9aF1oDVqCDVqtWh1bTVqF0gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg1bDVpdW/1bgnLFxuICAgICAgICAgICAgcGFzdDogJyVzINWh1bzVodW7JyxcbiAgICAgICAgICAgIHM6ICfVtNWrINaE1aHVttWrINW+1aHVtdaA1a/VtdWh1bYnLFxuICAgICAgICAgICAgc3M6ICclZCDVvtWh1bXWgNWv1bXVodW2JyxcbiAgICAgICAgICAgIG06ICfWgNW41brVpScsXG4gICAgICAgICAgICBtbTogJyVkINaA1bjVutWlJyxcbiAgICAgICAgICAgIGg6ICfVqtWh1bQnLFxuICAgICAgICAgICAgaGg6ICclZCDVqtWh1bQnLFxuICAgICAgICAgICAgZDogJ9aF1oAnLFxuICAgICAgICAgICAgZGQ6ICclZCDWhdaAJyxcbiAgICAgICAgICAgIE06ICfVodW01avVvScsXG4gICAgICAgICAgICBNTTogJyVkINWh1bTVq9W9JyxcbiAgICAgICAgICAgIHk6ICfVv9Wh1oDVqycsXG4gICAgICAgICAgICB5eTogJyVkINW/1aHWgNWrJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9Wj1avVt9Wl1oDVvtWhfNWh1bzVodW+1bjVv9W+1aF81oHVpdaA1aXVr9W+1aF81aXWgNWl1a/VuNW11aHVti8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIC9eKNaB1aXWgNWl1a/VvtWhfNWl1oDVpdWv1bjVtdWh1bYpJC8udGVzdChpbnB1dCk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91cikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfVo9Wr1bfVpdaA1b7VoSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn1aHVvNWh1b7VuNW/1b7VoSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn1oHVpdaA1aXVr9W+1aEnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9Wl1oDVpdWv1bjVtdWh1bYnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn18XFxkezEsMn0tKNWr1bZ81oDVpCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICBjYXNlICdERERvJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct1avVtic7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct1oDVpCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNywgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdpZCcsIHtcbiAgICAgICAgbW9udGhzOiAnSmFudWFyaV9GZWJydWFyaV9NYXJldF9BcHJpbF9NZWlfSnVuaV9KdWxpX0FndXN0dXNfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGVzZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuX0ZlYl9NYXJfQXByX01laV9KdW5fSnVsX0FndF9TZXBfT2t0X05vdl9EZXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnTWluZ2d1X1NlbmluX1NlbGFzYV9SYWJ1X0thbWlzX0p1bWF0X1NhYnR1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnTWluX1Nlbl9TZWxfUmFiX0thbV9KdW1fU2FiJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ01nX1NuX1NsX1JiX0ttX0ptX1NiJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISC5tbScsXG4gICAgICAgICAgICBMVFM6ICdISC5tbS5zcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAvcGFnaXxzaWFuZ3xzb3JlfG1hbGFtLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAncGFnaScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzaWFuZycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc29yZScgfHwgbWVyaWRpZW0gPT09ICdtYWxhbScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPCAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAncGFnaSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3NpYW5nJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnc29yZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAnbWFsYW0nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tIYXJpIGluaSBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tCZXNvayBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tLZW1hcmluIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW2xhbHUgcHVrdWxdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnZGFsYW0gJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIHlhbmcgbGFsdScsXG4gICAgICAgICAgICBzOiAnYmViZXJhcGEgZGV0aWsnLFxuICAgICAgICAgICAgc3M6ICclZCBkZXRpaycsXG4gICAgICAgICAgICBtOiAnc2VtZW5pdCcsXG4gICAgICAgICAgICBtbTogJyVkIG1lbml0JyxcbiAgICAgICAgICAgIGg6ICdzZWphbScsXG4gICAgICAgICAgICBoaDogJyVkIGphbScsXG4gICAgICAgICAgICBkOiAnc2VoYXJpJyxcbiAgICAgICAgICAgIGRkOiAnJWQgaGFyaScsXG4gICAgICAgICAgICBNOiAnc2VidWxhbicsXG4gICAgICAgICAgICBNTTogJyVkIGJ1bGFuJyxcbiAgICAgICAgICAgIHk6ICdzZXRhaHVuJyxcbiAgICAgICAgICAgIHl5OiAnJWQgdGFodW4nLFxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA2LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA2dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwbHVyYWwkMihuKSB7XG4gICAgICAgIGlmIChuICUgMTAwID09PSAxMSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAobiAlIDEwID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZSQ1KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmVcbiAgICAgICAgICAgICAgICAgICAgPyAnbm9ra3JhciBzZWvDum5kdXInXG4gICAgICAgICAgICAgICAgICAgIDogJ25va2tydW0gc2Vrw7puZHVtJztcbiAgICAgICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgICAgICBpZiAocGx1cmFsJDIobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICtcbiAgICAgICAgICAgICAgICAgICAgICAgICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ3Nla8O6bmR1cicgOiAnc2Vrw7puZHVtJylcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdzZWvDum5kYSc7XG4gICAgICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdtw61uw7p0YScgOiAnbcOtbsO6dHUnO1xuICAgICAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgICAgIGlmIChwbHVyYWwkMihudW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKyAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtw61uw7p0dXInIDogJ23DrW7DunR1bScpXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbcOtbsO6dGEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ23DrW7DunR1JztcbiAgICAgICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgICAgICBpZiAocGx1cmFsJDIobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICtcbiAgICAgICAgICAgICAgICAgICAgICAgICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyAna2x1a2t1c3R1bmRpcidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdrbHVra3VzdHVuZHVtJylcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdrbHVra3VzdHVuZCc7XG4gICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ2RhZ3VyJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ2RhZycgOiAnZGVnaSc7XG4gICAgICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICAgICAgaWYgKHBsdXJhbCQyKG51bWJlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnZGFnYXInO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoaXNGdXR1cmUgPyAnZGFnYScgOiAnZMO2Z3VtJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnZGFndXInO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKGlzRnV0dXJlID8gJ2RhZycgOiAnZGVnaScpO1xuICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdtw6FudcOwdXInO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAnbcOhbnXDsCcgOiAnbcOhbnXDsGknO1xuICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgIGlmIChwbHVyYWwkMihudW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ23DoW51w7Bpcic7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChpc0Z1dHVyZSA/ICdtw6FudcOwaScgOiAnbcOhbnXDsHVtJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbcOhbnXDsHVyJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChpc0Z1dHVyZSA/ICdtw6FudcOwJyA6ICdtw6FudcOwaScpO1xuICAgICAgICAgICAgY2FzZSAneSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnw6FyJyA6ICfDoXJpJztcbiAgICAgICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgICAgICBpZiAocGx1cmFsJDIobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnw6FyJyA6ICfDoXJ1bScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnw6FyJyA6ICfDoXJpJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2lzJywge1xuICAgICAgICBtb250aHM6ICdqYW7DumFyX2ZlYnLDumFyX21hcnNfYXByw61sX21hw61fasO6bsOtX2rDumzDrV/DoWfDunN0X3NlcHRlbWJlcl9va3TDs2Jlcl9uw7N2ZW1iZXJfZGVzZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnamFuX2ZlYl9tYXJfYXByX21hw61fasO6bl9qw7psX8OhZ8O6X3NlcF9va3RfbsOzdl9kZXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnc3VubnVkYWd1cl9tw6FudWRhZ3VyX8O+cmnDsGp1ZGFndXJfbWnDsHZpa3VkYWd1cl9maW1tdHVkYWd1cl9mw7ZzdHVkYWd1cl9sYXVnYXJkYWd1cicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ3N1bl9tw6FuX8O+cmlfbWnDsF9maW1fZsO2c19sYXUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU3VfTcOhX8Oecl9NaV9GaV9Gw7ZfTGEnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgW2tsLl0gSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZIFtrbC5dIEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vDrSBkYWcga2wuXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW8OhIG1vcmd1biBrbC5dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBba2wuXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW8OtIGfDpnIga2wuXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tzw63DsGFzdGFdIGRkZGQgW2tsLl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdlZnRpciAlcycsXG4gICAgICAgICAgICBwYXN0OiAnZnlyaXIgJXMgc8Otw7BhbicsXG4gICAgICAgICAgICBzOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgICAgIHNzOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgICAgIG06IHRyYW5zbGF0ZSQ1LFxuICAgICAgICAgICAgbW06IHRyYW5zbGF0ZSQ1LFxuICAgICAgICAgICAgaDogJ2tsdWtrdXN0dW5kJyxcbiAgICAgICAgICAgIGhoOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgICAgIGQ6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICAgICAgZGQ6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICAgICAgTTogdHJhbnNsYXRlJDUsXG4gICAgICAgICAgICBNTTogdHJhbnNsYXRlJDUsXG4gICAgICAgICAgICB5OiB0cmFuc2xhdGUkNSxcbiAgICAgICAgICAgIHl5OiB0cmFuc2xhdGUkNSxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbDogJyVkLicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnaXQtY2gnLCB7XG4gICAgICAgIG1vbnRoczogJ2dlbm5haW9fZmViYnJhaW9fbWFyem9fYXByaWxlX21hZ2dpb19naXVnbm9fbHVnbGlvX2Fnb3N0b19zZXR0ZW1icmVfb3R0b2JyZV9ub3ZlbWJyZV9kaWNlbWJyZScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdnZW5fZmViX21hcl9hcHJfbWFnX2dpdV9sdWdfYWdvX3NldF9vdHRfbm92X2RpYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdkb21lbmljYV9sdW5lZMOsX21hcnRlZMOsX21lcmNvbGVkw6xfZ2lvdmVkw6xfdmVuZXJkw6xfc2FiYXRvJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnZG9tX2x1bl9tYXJfbWVyX2dpb192ZW5fc2FiJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ2RvX2x1X21hX21lX2dpX3ZlX3NhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbT2dnaSBhbGxlXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0RvbWFuaSBhbGxlXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2FsbGVdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbSWVyaSBhbGxlXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tsYSBzY29yc2FdIGRkZGQgW2FsbGVdIExUJztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW2xvIHNjb3Jzb10gZGRkZCBbYWxsZV0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKC9eWzAtOV0uKyQvLnRlc3QocykgPyAndHJhJyA6ICdpbicpICsgJyAnICsgcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYXN0OiAnJXMgZmEnLFxuICAgICAgICAgICAgczogJ2FsY3VuaSBzZWNvbmRpJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vjb25kaScsXG4gICAgICAgICAgICBtOiAndW4gbWludXRvJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRpJyxcbiAgICAgICAgICAgIGg6IFwidW4nb3JhXCIsXG4gICAgICAgICAgICBoaDogJyVkIG9yZScsXG4gICAgICAgICAgICBkOiAndW4gZ2lvcm5vJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZ2lvcm5pJyxcbiAgICAgICAgICAgIE06ICd1biBtZXNlJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWVzaScsXG4gICAgICAgICAgICB5OiAndW4gYW5ubycsXG4gICAgICAgICAgICB5eTogJyVkIGFubmknLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn3Cui8sXG4gICAgICAgIG9yZGluYWw6ICclZMK6JyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdpdCcsIHtcbiAgICAgICAgbW9udGhzOiAnZ2VubmFpb19mZWJicmFpb19tYXJ6b19hcHJpbGVfbWFnZ2lvX2dpdWdub19sdWdsaW9fYWdvc3RvX3NldHRlbWJyZV9vdHRvYnJlX25vdmVtYnJlX2RpY2VtYnJlJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2dlbl9mZWJfbWFyX2Fwcl9tYWdfZ2l1X2x1Z19hZ29fc2V0X290dF9ub3ZfZGljJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ2RvbWVuaWNhX2x1bmVkw6xfbWFydGVkw6xfbWVyY29sZWTDrF9naW92ZWTDrF92ZW5lcmTDrF9zYWJhdG8nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdkb21fbHVuX21hcl9tZXJfZ2lvX3Zlbl9zYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnZG9fbHVfbWFfbWVfZ2lfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICdbT2dnaSBhJyArXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLmhvdXJzKCkgPiAxID8gJ2xsZSAnIDogdGhpcy5ob3VycygpID09PSAwID8gJyAnIDogXCJsbCdcIikgK1xuICAgICAgICAgICAgICAgICAgICAnXUxUJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dERheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICdbRG9tYW5pIGEnICtcbiAgICAgICAgICAgICAgICAgICAgKHRoaXMuaG91cnMoKSA+IDEgPyAnbGxlICcgOiB0aGlzLmhvdXJzKCkgPT09IDAgPyAnICcgOiBcImxsJ1wiKSArXG4gICAgICAgICAgICAgICAgICAgICddTFQnXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICdkZGRkIFthJyArXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLmhvdXJzKCkgPiAxID8gJ2xsZSAnIDogdGhpcy5ob3VycygpID09PSAwID8gJyAnIDogXCJsbCdcIikgK1xuICAgICAgICAgICAgICAgICAgICAnXUxUJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICdbSWVyaSBhJyArXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLmhvdXJzKCkgPiAxID8gJ2xsZSAnIDogdGhpcy5ob3VycygpID09PSAwID8gJyAnIDogXCJsbCdcIikgK1xuICAgICAgICAgICAgICAgICAgICAnXUxUJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnW0xhIHNjb3JzYV0gZGRkZCBbYScgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmhvdXJzKCkgPiAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gJ2xsZSAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdGhpcy5ob3VycygpID09PSAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gJyAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogXCJsbCdcIikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICddTFQnXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnW0xvIHNjb3Jzb10gZGRkZCBbYScgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmhvdXJzKCkgPiAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gJ2xsZSAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdGhpcy5ob3VycygpID09PSAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gJyAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogXCJsbCdcIikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICddTFQnXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ3RyYSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgZmEnLFxuICAgICAgICAgICAgczogJ2FsY3VuaSBzZWNvbmRpJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2Vjb25kaScsXG4gICAgICAgICAgICBtOiAndW4gbWludXRvJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRpJyxcbiAgICAgICAgICAgIGg6IFwidW4nb3JhXCIsXG4gICAgICAgICAgICBoaDogJyVkIG9yZScsXG4gICAgICAgICAgICBkOiAndW4gZ2lvcm5vJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZ2lvcm5pJyxcbiAgICAgICAgICAgIHc6ICd1bmEgc2V0dGltYW5hJyxcbiAgICAgICAgICAgIHd3OiAnJWQgc2V0dGltYW5lJyxcbiAgICAgICAgICAgIE06ICd1biBtZXNlJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWVzaScsXG4gICAgICAgICAgICB5OiAndW4gYW5ubycsXG4gICAgICAgICAgICB5eTogJyVkIGFubmknLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn3Cui8sXG4gICAgICAgIG9yZGluYWw6ICclZMK6JyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdqYScsIHtcbiAgICAgICAgZXJhczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHNpbmNlOiAnMjAxOS0wNS0wMScsXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgICAgIG5hbWU6ICfku6TlkownLFxuICAgICAgICAgICAgICAgIG5hcnJvdzogJ+OLvycsXG4gICAgICAgICAgICAgICAgYWJicjogJ1InLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzaW5jZTogJzE5ODktMDEtMDgnLFxuICAgICAgICAgICAgICAgIHVudGlsOiAnMjAxOS0wNC0zMCcsXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgICAgIG5hbWU6ICflubPmiJAnLFxuICAgICAgICAgICAgICAgIG5hcnJvdzogJ+ONuycsXG4gICAgICAgICAgICAgICAgYWJicjogJ0gnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzaW5jZTogJzE5MjYtMTItMjUnLFxuICAgICAgICAgICAgICAgIHVudGlsOiAnMTk4OS0wMS0wNycsXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgICAgIG5hbWU6ICfmmK3lkownLFxuICAgICAgICAgICAgICAgIG5hcnJvdzogJ+ONvCcsXG4gICAgICAgICAgICAgICAgYWJicjogJ1MnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzaW5jZTogJzE5MTItMDctMzAnLFxuICAgICAgICAgICAgICAgIHVudGlsOiAnMTkyNi0xMi0yNCcsXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgICAgIG5hbWU6ICflpKfmraMnLFxuICAgICAgICAgICAgICAgIG5hcnJvdzogJ+ONvScsXG4gICAgICAgICAgICAgICAgYWJicjogJ1QnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzaW5jZTogJzE4NzMtMDEtMDEnLFxuICAgICAgICAgICAgICAgIHVudGlsOiAnMTkxMi0wNy0yOScsXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiA2LFxuICAgICAgICAgICAgICAgIG5hbWU6ICfmmI7msrsnLFxuICAgICAgICAgICAgICAgIG5hcnJvdzogJ+ONvicsXG4gICAgICAgICAgICAgICAgYWJicjogJ00nLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzaW5jZTogJzAwMDEtMDEtMDEnLFxuICAgICAgICAgICAgICAgIHVudGlsOiAnMTg3My0xMi0zMScsXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgICAgIG5hbWU6ICfopb/mmqYnLFxuICAgICAgICAgICAgICAgIG5hcnJvdzogJ0FEJyxcbiAgICAgICAgICAgICAgICBhYmJyOiAnQUQnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzaW5jZTogJzAwMDAtMTItMzEnLFxuICAgICAgICAgICAgICAgIHVudGlsOiAtSW5maW5pdHksXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgICAgIG5hbWU6ICfntIDlhYPliY0nLFxuICAgICAgICAgICAgICAgIG5hcnJvdzogJ0JDJyxcbiAgICAgICAgICAgICAgICBhYmJyOiAnQkMnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgZXJhWWVhck9yZGluYWxSZWdleDogLyjlhYN8XFxkKynlubQvLFxuICAgICAgICBlcmFZZWFyT3JkaW5hbFBhcnNlOiBmdW5jdGlvbiAoaW5wdXQsIG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hbMV0gPT09ICflhYMnID8gMSA6IHBhcnNlSW50KG1hdGNoWzFdIHx8IGlucHV0LCAxMCk7XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoczogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ+aXpeabnOaXpV/mnIjmm5zml6Vf54Gr5puc5pelX+awtOabnOaXpV/mnKjmm5zml6Vf6YeR5puc5pelX+Wcn+abnOaXpScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+aXpV/mnIhf54GrX+awtF/mnKhf6YeRX+Wcnycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfml6Vf5pyIX+eBq1/msLRf5pyoX+mHkV/lnJ8nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdZWVlZL01NL0REJyxcbiAgICAgICAgICAgIExMOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgICAgIExMTDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnWVlZWeW5tE3mnIhE5pelIGRkZGQgSEg6bW0nLFxuICAgICAgICAgICAgbDogJ1lZWVkvTU0vREQnLFxuICAgICAgICAgICAgbGw6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICAgICAgbGxsOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGw6ICdZWVlZ5bm0TeaciETml6UoZGRkKSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/ljYjliY185Y2I5b6ML2ksXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn5Y2I5b6MJztcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+WNiOWJjSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5Y2I5b6MJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb5LuK5pelXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW+aYjuaXpV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uIChub3cpIHtcbiAgICAgICAgICAgICAgICBpZiAobm93LndlZWsoKSAhPT0gdGhpcy53ZWVrKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb5p2l6YCxXWRkZGQgTFQnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnZGRkZCBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb5pio5pelXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKG5vdykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndlZWsoKSAhPT0gbm93LndlZWsoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vlhYjpgLFdZGRkZCBMVCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdkZGRkIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ95pelLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyID09PSAxID8gJ+WFg+W5tCcgOiBudW1iZXIgKyAn5bm0JztcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aXpSc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclc+W+jCcsXG4gICAgICAgICAgICBwYXN0OiAnJXPliY0nLFxuICAgICAgICAgICAgczogJ+aVsOenkicsXG4gICAgICAgICAgICBzczogJyVk56eSJyxcbiAgICAgICAgICAgIG06ICcx5YiGJyxcbiAgICAgICAgICAgIG1tOiAnJWTliIYnLFxuICAgICAgICAgICAgaDogJzHmmYLplpMnLFxuICAgICAgICAgICAgaGg6ICclZOaZgumWkycsXG4gICAgICAgICAgICBkOiAnMeaXpScsXG4gICAgICAgICAgICBkZDogJyVk5pelJyxcbiAgICAgICAgICAgIE06ICcx44O25pyIJyxcbiAgICAgICAgICAgIE1NOiAnJWTjg7bmnIgnLFxuICAgICAgICAgICAgeTogJzHlubQnLFxuICAgICAgICAgICAgeXk6ICclZOW5tCcsXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2p2Jywge1xuICAgICAgICBtb250aHM6ICdKYW51YXJpX0ZlYnJ1YXJpX01hcmV0X0FwcmlsX01laV9KdW5pX0p1bGlfQWd1c3R1c19TZXB0ZW1iZXJfT2t0b2Jlcl9Ob3BlbWJlcl9EZXNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRmViX01hcl9BcHJfTWVpX0p1bl9KdWxfQWdzX1NlcF9Pa3RfTm9wX0Rlcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdNaW5nZ3VfU2VuZW5fU2Vsb3NvX1JlYnVfS2VtaXNfSmVtdXdhaF9TZXB0dScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ01pbl9TZW5fU2VsX1JlYl9LZW1fSmVtX1NlcCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdNZ19Tbl9TbF9SYl9LbV9KbV9TcCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEgubW0nLFxuICAgICAgICAgICAgTFRTOiAnSEgubW0uc3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL2VuamluZ3xzaXlhbmd8c29udGVufG5kYWx1LyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAnZW5qaW5nJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3NpeWFuZycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc29udGVuJyB8fCBtZXJpZGllbSA9PT0gJ25kYWx1Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VycyA8IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdlbmppbmcnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE1KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdzaXlhbmcnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdzb250ZW4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ25kYWx1JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbRGludGVuIHB1bmlrbyBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tNYmVuamFuZyBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tLYWxhIHdpbmdpIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW2tlcGVuZ2tlciBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICd3b250ZW4gaW5nICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBpbmdrYW5nIGtlcGVuZ2tlcicsXG4gICAgICAgICAgICBzOiAnc2F3ZXRhd2lzIGRldGlrJyxcbiAgICAgICAgICAgIHNzOiAnJWQgZGV0aWsnLFxuICAgICAgICAgICAgbTogJ3NldHVuZ2dhbCBtZW5pdCcsXG4gICAgICAgICAgICBtbTogJyVkIG1lbml0JyxcbiAgICAgICAgICAgIGg6ICdzZXR1bmdnYWwgamFtJyxcbiAgICAgICAgICAgIGhoOiAnJWQgamFtJyxcbiAgICAgICAgICAgIGQ6ICdzZWRpbnRlbicsXG4gICAgICAgICAgICBkZDogJyVkIGRpbnRlbicsXG4gICAgICAgICAgICBNOiAnc2V3dWxhbicsXG4gICAgICAgICAgICBNTTogJyVkIHd1bGFuJyxcbiAgICAgICAgICAgIHk6ICdzZXRhdW4nLFxuICAgICAgICAgICAgeXk6ICclZCB0YXVuJyxcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNywgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdrYScsIHtcbiAgICAgICAgbW9udGhzOiAn4YOY4YOQ4YOc4YOV4YOQ4YOg4YOYX+GDl+GDlOGDkeGDlOGDoOGDleGDkOGDmuGDmF/hg5vhg5Dhg6Dhg6Lhg5hf4YOQ4YOe4YOg4YOY4YOa4YOYX+GDm+GDkOGDmOGDoeGDmF/hg5jhg5Xhg5zhg5jhg6Hhg5hf4YOY4YOV4YOa4YOY4YOh4YOYX+GDkOGDkuGDleGDmOGDoeGDouGDnV/hg6Hhg5Thg6Xhg6Lhg5Thg5vhg5Hhg5Thg6Dhg5hf4YOd4YOl4YOi4YOd4YOb4YOR4YOU4YOg4YOYX+GDnOGDneGDlOGDm+GDkeGDlOGDoOGDmF/hg5Phg5Thg5nhg5Thg5vhg5Hhg5Thg6Dhg5gnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn4YOY4YOQ4YOcX+GDl+GDlOGDkV/hg5vhg5Dhg6Bf4YOQ4YOe4YOgX+GDm+GDkOGDmF/hg5jhg5Xhg5xf4YOY4YOV4YOaX+GDkOGDkuGDlV/hg6Hhg5Thg6Vf4YOd4YOl4YOiX+GDnOGDneGDlF/hg5Phg5Thg5knLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiB7XG4gICAgICAgICAgICBzdGFuZGFsb25lOiAn4YOZ4YOV4YOY4YOg4YOQX+GDneGDoOGDqOGDkOGDkeGDkOGDl+GDmF/hg6Hhg5Dhg5vhg6jhg5Dhg5Hhg5Dhg5fhg5hf4YOd4YOX4YOu4YOo4YOQ4YOR4YOQ4YOX4YOYX+GDruGDo+GDl+GDqOGDkOGDkeGDkOGDl+GDmF/hg57hg5Dhg6Dhg5Dhg6Hhg5nhg5Thg5Xhg5hf4YOo4YOQ4YOR4YOQ4YOX4YOYJy5zcGxpdChcbiAgICAgICAgICAgICAgICAnXydcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBmb3JtYXQ6ICfhg5nhg5Xhg5jhg6Dhg5Dhg6Ff4YOd4YOg4YOo4YOQ4YOR4YOQ4YOX4YOhX+GDoeGDkOGDm+GDqOGDkOGDkeGDkOGDl+GDoV/hg53hg5fhg67hg6jhg5Dhg5Hhg5Dhg5fhg6Ff4YOu4YOj4YOX4YOo4YOQ4YOR4YOQ4YOX4YOhX+GDnuGDkOGDoOGDkOGDoeGDmeGDlOGDleGDoV/hg6jhg5Dhg5Hhg5Dhg5fhg6EnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGlzRm9ybWF0OiAvKOGDrOGDmOGDnOGDkHzhg6jhg5Thg5vhg5Phg5Thg5IpLyxcbiAgICAgICAgfSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+GDmeGDleGDmF/hg53hg6Dhg6hf4YOh4YOQ4YObX+GDneGDl+GDrl/hg67hg6Phg5df4YOe4YOQ4YOgX+GDqOGDkOGDkScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfhg5nhg5Vf4YOd4YOgX+GDoeGDkF/hg53hg5df4YOu4YOjX+GDnuGDkF/hg6jhg5AnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb4YOT4YOm4YOU4YOhXSBMVFst4YOW4YOUXScsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW+GDruGDleGDkOGDml0gTFRbLeGDluGDlF0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1vhg5Lhg6Phg6jhg5jhg5xdIExUWy3hg5bhg5RdJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW+GDqOGDlOGDm+GDk+GDlOGDkl0gZGRkZCBMVFst4YOW4YOUXScsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vhg6zhg5jhg5zhg5BdIGRkZGQgTFQt4YOW4YOUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiBmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgIHJldHVybiBzLnJlcGxhY2UoLyjhg6zhg5Dhg5t84YOs4YOj4YOXfOGDoeGDkOGDkOGDl3zhg6zhg5Thg5p84YOT4YOmfOGDl+GDlSko4YOYfOGDlCkvLCBmdW5jdGlvbiAoXG4gICAgICAgICAgICAgICAgICAgICQwLFxuICAgICAgICAgICAgICAgICAgICAkMSxcbiAgICAgICAgICAgICAgICAgICAgJDJcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQyID09PSAn4YOYJyA/ICQxICsgJ+GDqOGDmCcgOiAkMSArICQyICsgJ+GDqOGDmCc7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFzdDogZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoLyjhg6zhg5Dhg5vhg5h84YOs4YOj4YOX4YOYfOGDoeGDkOGDkOGDl+GDmHzhg5Phg6bhg5R84YOX4YOV4YOUKS8udGVzdChzKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcy5yZXBsYWNlKC8o4YOYfOGDlCkkLywgJ+GDmOGDoSDhg6zhg5jhg5wnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKC/hg6zhg5Thg5rhg5gvLnRlc3QocykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMucmVwbGFjZSgv4YOs4YOU4YOa4YOYJC8sICfhg6zhg5rhg5jhg6Eg4YOs4YOY4YOcJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHM6ICfhg6Dhg5Dhg5vhg5Phg5Thg5zhg5jhg5vhg5Qg4YOs4YOQ4YOb4YOYJyxcbiAgICAgICAgICAgIHNzOiAnJWQg4YOs4YOQ4YOb4YOYJyxcbiAgICAgICAgICAgIG06ICfhg6zhg6Phg5fhg5gnLFxuICAgICAgICAgICAgbW06ICclZCDhg6zhg6Phg5fhg5gnLFxuICAgICAgICAgICAgaDogJ+GDoeGDkOGDkOGDl+GDmCcsXG4gICAgICAgICAgICBoaDogJyVkIOGDoeGDkOGDkOGDl+GDmCcsXG4gICAgICAgICAgICBkOiAn4YOT4YOm4YOUJyxcbiAgICAgICAgICAgIGRkOiAnJWQg4YOT4YOm4YOUJyxcbiAgICAgICAgICAgIE06ICfhg5fhg5Xhg5QnLFxuICAgICAgICAgICAgTU06ICclZCDhg5fhg5Xhg5QnLFxuICAgICAgICAgICAgeTogJ+GDrOGDlOGDmuGDmCcsXG4gICAgICAgICAgICB5eTogJyVkIOGDrOGDlOGDmuGDmCcsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC8wfDEt4YOa4YOYfOGDm+GDlC1cXGR7MSwyfXxcXGR7MSwyfS3hg5QvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3hg5rhg5gnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIG51bWJlciA8IDIwIHx8XG4gICAgICAgICAgICAgICAgKG51bWJlciA8PSAxMDAgJiYgbnVtYmVyICUgMjAgPT09IDApIHx8XG4gICAgICAgICAgICAgICAgbnVtYmVyICUgMTAwID09PSAwXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+GDm+GDlC0nICsgbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct4YOUJztcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLFxuICAgICAgICAgICAgZG95OiA3LFxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN1ZmZpeGVzJDEgPSB7XG4gICAgICAgIDA6ICct0YjRlicsXG4gICAgICAgIDE6ICct0YjRlicsXG4gICAgICAgIDI6ICct0YjRlicsXG4gICAgICAgIDM6ICct0YjRlicsXG4gICAgICAgIDQ6ICct0YjRlicsXG4gICAgICAgIDU6ICct0YjRlicsXG4gICAgICAgIDY6ICct0YjRiycsXG4gICAgICAgIDc6ICct0YjRlicsXG4gICAgICAgIDg6ICct0YjRlicsXG4gICAgICAgIDk6ICct0YjRiycsXG4gICAgICAgIDEwOiAnLdGI0YsnLFxuICAgICAgICAyMDogJy3RiNGLJyxcbiAgICAgICAgMzA6ICct0YjRiycsXG4gICAgICAgIDQwOiAnLdGI0YsnLFxuICAgICAgICA1MDogJy3RiNGWJyxcbiAgICAgICAgNjA6ICct0YjRiycsXG4gICAgICAgIDcwOiAnLdGI0ZYnLFxuICAgICAgICA4MDogJy3RiNGWJyxcbiAgICAgICAgOTA6ICct0YjRiycsXG4gICAgICAgIDEwMDogJy3RiNGWJyxcbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdraycsIHtcbiAgICAgICAgbW9udGhzOiAn0pvQsNKj0YLQsNGAX9Cw0pvQv9Cw0L1f0L3QsNGD0YDRi9C3X9GB05nRg9GW0YBf0LzQsNC80YvRgF/QvNCw0YPRgdGL0Lxf0YjRltC70LTQtV/RgtCw0LzRi9C3X9Kb0YvRgNC60q/QudC10Lpf0pvQsNC30LDQvV/Sm9Cw0YDQsNGI0LBf0LbQtdC70YLQvtKb0YHQsNC9Jy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ9Kb0LDSo1/QsNKb0L9f0L3QsNGDX9GB05nRg1/QvNCw0Lxf0LzQsNGDX9GI0ZbQu1/RgtCw0Lxf0pvRi9GAX9Kb0LDQt1/Sm9Cw0YBf0LbQtdC7Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ9C20LXQutGB0LXQvdCx0ZZf0LTSr9C50YHQtdC90LHRll/RgdC10LnRgdC10L3QsdGWX9GB05nRgNGB0LXQvdCx0ZZf0LHQtdC50YHQtdC90LHRll/QttKx0LzQsF/RgdC10L3QsdGWJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn0LbQtdC6X9C00q/QuV/RgdC10Llf0YHTmdGAX9Cx0LXQuV/QttKx0Lxf0YHQtdC9Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9C20Lpf0LTQuV/RgdC5X9GB0YBf0LHQuV/QttC8X9GB0L0nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb0JHSr9Cz0ZbQvSDRgdCw0pPQsNGCXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9CV0YDRgtC10qMg0YHQsNKT0LDRgl0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvRgdCw0pPQsNGCXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9Ca0LXRiNC1INGB0LDSk9Cw0YJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW9Oo0YLQutC10L0g0LDQv9GC0LDQvdGL0qNdIGRkZGQgW9GB0LDSk9Cw0YJdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg0ZbRiNGW0L3QtNC1JyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDQsdKx0YDRi9C9JyxcbiAgICAgICAgICAgIHM6ICfQsdGW0YDQvdC10YjQtSDRgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgc3M6ICclZCDRgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgbTogJ9Cx0ZbRgCDQvNC40L3Rg9GCJyxcbiAgICAgICAgICAgIG1tOiAnJWQg0LzQuNC90YPRgicsXG4gICAgICAgICAgICBoOiAn0LHRltGAINGB0LDSk9Cw0YInLFxuICAgICAgICAgICAgaGg6ICclZCDRgdCw0pPQsNGCJyxcbiAgICAgICAgICAgIGQ6ICfQsdGW0YAg0LrSr9C9JyxcbiAgICAgICAgICAgIGRkOiAnJWQg0LrSr9C9JyxcbiAgICAgICAgICAgIE06ICfQsdGW0YAg0LDQuScsXG4gICAgICAgICAgICBNTTogJyVkINCw0LknLFxuICAgICAgICAgICAgeTogJ9Cx0ZbRgCDQttGL0LsnLFxuICAgICAgICAgICAgeXk6ICclZCDQttGL0LsnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNGI0ZZ80YjRiykvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIGIgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAoc3VmZml4ZXMkMVtudW1iZXJdIHx8IHN1ZmZpeGVzJDFbYV0gfHwgc3VmZml4ZXMkMVtiXSk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkOSA9IHtcbiAgICAgICAgICAgIDE6ICfhn6EnLFxuICAgICAgICAgICAgMjogJ+GfoicsXG4gICAgICAgICAgICAzOiAn4Z+jJyxcbiAgICAgICAgICAgIDQ6ICfhn6QnLFxuICAgICAgICAgICAgNTogJ+GfpScsXG4gICAgICAgICAgICA2OiAn4Z+mJyxcbiAgICAgICAgICAgIDc6ICfhn6cnLFxuICAgICAgICAgICAgODogJ+GfqCcsXG4gICAgICAgICAgICA5OiAn4Z+pJyxcbiAgICAgICAgICAgIDA6ICfhn6AnLFxuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAkOCA9IHtcbiAgICAgICAgICAgICfhn6EnOiAnMScsXG4gICAgICAgICAgICAn4Z+iJzogJzInLFxuICAgICAgICAgICAgJ+Gfoyc6ICczJyxcbiAgICAgICAgICAgICfhn6QnOiAnNCcsXG4gICAgICAgICAgICAn4Z+lJzogJzUnLFxuICAgICAgICAgICAgJ+Gfpic6ICc2JyxcbiAgICAgICAgICAgICfhn6cnOiAnNycsXG4gICAgICAgICAgICAn4Z+oJzogJzgnLFxuICAgICAgICAgICAgJ+GfqSc6ICc5JyxcbiAgICAgICAgICAgICfhn6AnOiAnMCcsXG4gICAgICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2ttJywge1xuICAgICAgICBtb250aHM6ICfhnpjhnoDhnprhnrZf4Z6A4Z674Z6Y4Z+S4Z6X4Z+IX+GemOGeuOGek+Getl/hnpjhn4Hhnp/hnrZf4Z6n4Z6f4Z6X4Z62X+GemOGet+GekOGeu+Gek+Getl/hnoDhnoDhn5LhnoDhnorhnrZf4Z6f4Z644Z6g4Z62X+GegOGeieGfkuGeieGetl/hno/hnrvhnpvhnrZf4Z6c4Z634Z6F4Z+S4Z6G4Z634Z6A4Z62X+GekuGfkuGek+GevCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfhnpjhnoDhnprhnrZf4Z6A4Z674Z6Y4Z+S4Z6X4Z+IX+GemOGeuOGek+Getl/hnpjhn4Hhnp/hnrZf4Z6n4Z6f4Z6X4Z62X+GemOGet+GekOGeu+Gek+Getl/hnoDhnoDhn5LhnoDhnorhnrZf4Z6f4Z644Z6g4Z62X+GegOGeieGfkuGeieGetl/hno/hnrvhnpvhnrZf4Z6c4Z634Z6F4Z+S4Z6G4Z634Z6A4Z62X+GekuGfkuGek+GevCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfhnqLhnrbhnpHhnrfhno/hn5Lhnplf4Z6F4Z+Q4Z6T4Z+S4Z6RX+GeouGehOGfkuGeguGetuGeml/hnpbhnrvhnpJf4Z6W4Z+S4Z6a4Z6g4Z6f4Z+S4Z6U4Z6P4Z634Z+NX+Gen+Geu+GegOGfkuGeml/hnp/hn4Xhnprhn40nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfhnqLhnrZf4Z6FX+Geol/hnpZf4Z6W4Z+S4Z6aX+Gen+Geu1/hnp8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4Z6i4Z62X+GehV/hnqJf4Z6WX+GeluGfkuGeml/hnp/hnrtf4Z6fJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+GeluGfkuGemuGeueGegHzhnpvhn5LhnoThnrbhnoUvLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PT0gJ+Gem+GfkuGehOGetuGehSc7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfhnpbhn5LhnprhnrnhnoAnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+Gem+GfkuGehOGetuGehSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+GekOGfkuGehOGfg+Gek+GfgeGfhyDhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4Z6f4Z+S4Z6i4Z+C4Z6AIOGemOGfieGfhOGehF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4Z6Y4Z+S4Z6f4Z634Z6b4Z6Y4Z634Z6JIOGemOGfieGfhOGehF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvhnp/hnpThn5Lhno/hnrbhnqDhn43hnpjhnrvhnpNdIFvhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXPhnpHhn4Dhno8nLFxuICAgICAgICAgICAgcGFzdDogJyVz4Z6Y4Z674Z6TJyxcbiAgICAgICAgICAgIHM6ICfhnpThn4nhnrvhnpPhn5LhnpjhnrbhnpPhnpzhnrfhnpPhnrbhnpHhnrgnLFxuICAgICAgICAgICAgc3M6ICclZCDhnpzhnrfhnpPhnrbhnpHhnrgnLFxuICAgICAgICAgICAgbTogJ+GemOGeveGemeGek+GetuGekeGeuCcsXG4gICAgICAgICAgICBtbTogJyVkIOGek+GetuGekeGeuCcsXG4gICAgICAgICAgICBoOiAn4Z6Y4Z694Z6Z4Z6Y4Z+J4Z+E4Z6EJyxcbiAgICAgICAgICAgIGhoOiAnJWQg4Z6Y4Z+J4Z+E4Z6EJyxcbiAgICAgICAgICAgIGQ6ICfhnpjhnr3hnpnhnpDhn5LhnoThn4MnLFxuICAgICAgICAgICAgZGQ6ICclZCDhnpDhn5LhnoThn4MnLFxuICAgICAgICAgICAgTTogJ+GemOGeveGemeGegeGfgicsXG4gICAgICAgICAgICBNTTogJyVkIOGegeGfgicsXG4gICAgICAgICAgICB5OiAn4Z6Y4Z694Z6Z4Z6G4Z+S4Z6T4Z624Z+GJyxcbiAgICAgICAgICAgIHl5OiAnJWQg4Z6G4Z+S4Z6T4Z624Z+GJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL+GekeGeuFxcZHsxLDJ9LyxcbiAgICAgICAgb3JkaW5hbDogJ+GekeGeuCVkJyxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+GfoeGfouGfo+GfpOGfpeGfpuGfp+GfqOGfqeGfoF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCQ4W21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDlbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkYSA9IHtcbiAgICAgICAgICAgIDE6ICfgs6cnLFxuICAgICAgICAgICAgMjogJ+CzqCcsXG4gICAgICAgICAgICAzOiAn4LOpJyxcbiAgICAgICAgICAgIDQ6ICfgs6onLFxuICAgICAgICAgICAgNTogJ+CzqycsXG4gICAgICAgICAgICA2OiAn4LOsJyxcbiAgICAgICAgICAgIDc6ICfgs60nLFxuICAgICAgICAgICAgODogJ+CzricsXG4gICAgICAgICAgICA5OiAn4LOvJyxcbiAgICAgICAgICAgIDA6ICfgs6YnLFxuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAkOSA9IHtcbiAgICAgICAgICAgICfgs6cnOiAnMScsXG4gICAgICAgICAgICAn4LOoJzogJzInLFxuICAgICAgICAgICAgJ+CzqSc6ICczJyxcbiAgICAgICAgICAgICfgs6onOiAnNCcsXG4gICAgICAgICAgICAn4LOrJzogJzUnLFxuICAgICAgICAgICAgJ+CzrCc6ICc2JyxcbiAgICAgICAgICAgICfgs60nOiAnNycsXG4gICAgICAgICAgICAn4LOuJzogJzgnLFxuICAgICAgICAgICAgJ+Czryc6ICc5JyxcbiAgICAgICAgICAgICfgs6YnOiAnMCcsXG4gICAgICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2tuJywge1xuICAgICAgICBtb250aHM6ICfgspzgsqjgsrXgsrDgsr9f4LKr4LOG4LKs4LON4LKw4LK14LKw4LK/X+CyruCyvuCysOCzjeCymuCzjV/gso/gsqrgs43gsrDgsr/gsrLgs41f4LKu4LOG4LOVX+CynOCzguCyqOCzjV/gspzgs4HgsrLgs4bgs5Zf4LKG4LKX4LK44LON4LKf4LONX+CyuOCzhuCyquCzjeCyn+CzhuCyguCyrOCysOCzjV/gsoXgspXgs43gsp/gs4bgs4Lgs5XgsqzgsrDgs41f4LKo4LK14LOG4LKC4LKs4LKw4LONX+CyoeCyv+CyuOCzhuCyguCyrOCysOCzjScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgspzgsqhf4LKr4LOG4LKs4LON4LKwX+CyruCyvuCysOCzjeCymuCzjV/gso/gsqrgs43gsrDgsr/gsrLgs41f4LKu4LOG4LOVX+CynOCzguCyqOCzjV/gspzgs4HgsrLgs4bgs5Zf4LKG4LKX4LK44LON4LKf4LONX+CyuOCzhuCyquCzjeCyn+CzhuCygl/gsoXgspXgs43gsp/gs4bgs4Lgs5Vf4LKo4LK14LOG4LKCX+CyoeCyv+CyuOCzhuCygicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6ICfgsq3gsr7gsqjgs4HgsrXgsr7gsrBf4LK44LOG4LOC4LOV4LKu4LK14LK+4LKwX+CyruCyguCyl+Cys+CyteCyvuCysF/gsqzgs4HgsqfgsrXgsr7gsrBf4LKX4LOB4LKw4LOB4LK14LK+4LKwX+CytuCzgeCyleCzjeCysOCyteCyvuCysF/gsrbgsqjgsr/gsrXgsr7gsrAnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfgsq3gsr7gsqjgs4Ff4LK44LOG4LOC4LOV4LKuX+CyruCyguCyl+Cys1/gsqzgs4Hgsqdf4LKX4LOB4LKw4LOBX+CytuCzgeCyleCzjeCysF/gsrbgsqjgsr8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4LKt4LK+X+CyuOCzhuCzguCzlV/gsq7gsoJf4LKs4LOBX+Cyl+CzgV/gsrbgs4Ff4LK2Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdBIGg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVksIEEgaDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+Cyh+CyguCypuCzgV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vgsqjgsr7gsrPgs4ZdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCwgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vgsqjgsr/gsqjgs43gsqjgs4ZdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+CyleCzhuCzguCyqOCzhuCyr10gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclcyDgsqjgsoLgsqTgsrAnLFxuICAgICAgICAgICAgcGFzdDogJyVzIOCyueCyv+CyguCypuCzhicsXG4gICAgICAgICAgICBzOiAn4LKV4LOG4LKy4LK14LOBIOCyleCzjeCyt+Cyo+Cyl+Cys+CzgScsXG4gICAgICAgICAgICBzczogJyVkIOCyuOCzhuCyleCzhuCyguCyoeCzgeCyl+Cys+CzgScsXG4gICAgICAgICAgICBtOiAn4LKS4LKC4LKm4LOBIOCyqOCyv+CyruCyv+CytycsXG4gICAgICAgICAgICBtbTogJyVkIOCyqOCyv+CyruCyv+CytycsXG4gICAgICAgICAgICBoOiAn4LKS4LKC4LKm4LOBIOCyl+CyguCyn+CzhicsXG4gICAgICAgICAgICBoaDogJyVkIOCyl+CyguCyn+CzhicsXG4gICAgICAgICAgICBkOiAn4LKS4LKC4LKm4LOBIOCypuCyv+CyqCcsXG4gICAgICAgICAgICBkZDogJyVkIOCypuCyv+CyqCcsXG4gICAgICAgICAgICBNOiAn4LKS4LKC4LKm4LOBIOCypOCyv+CyguCyl+Cys+CzgScsXG4gICAgICAgICAgICBNTTogJyVkIOCypOCyv+CyguCyl+Cys+CzgScsXG4gICAgICAgICAgICB5OiAn4LKS4LKC4LKm4LOBIOCyteCysOCzjeCytycsXG4gICAgICAgICAgICB5eTogJyVkIOCyteCysOCzjeCytycsXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgs6fgs6jgs6ngs6rgs6vgs6zgs63gs67gs6/gs6ZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkOVttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCRhW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4LKw4LK+4LKk4LON4LKw4LK/fOCyrOCzhuCys+Cyv+Cyl+CzjeCyl+Czhnzgsq7gsqfgs43gsq/gsr7gsrngs43gsqh84LK44LKC4LKc4LOGLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4LKw4LK+4LKk4LON4LKw4LK/Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LKs4LOG4LKz4LK/4LKX4LON4LKX4LOGJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CyruCyp+CzjeCyr+CyvuCyueCzjeCyqCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LK44LKC4LKc4LOGJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CysOCyvuCypOCzjeCysOCyvyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LKs4LOG4LKz4LK/4LKX4LON4LKX4LOGJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgsq7gsqfgs43gsq/gsr7gsrngs43gsqgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CyuOCyguCynOCzhic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LKw4LK+4LKk4LON4LKw4LK/JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KOCyqOCzhuCzlSkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+CyqOCzhuCzlSc7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDYsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgna28nLCB7XG4gICAgICAgIG1vbnRoczogJzHsm5RfMuyblF8z7JuUXzTsm5RfNeyblF827JuUXzfsm5RfOOyblF857JuUXzEw7JuUXzEx7JuUXzEy7JuUJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydDogJzHsm5RfMuyblF8z7JuUXzTsm5RfNeyblF827JuUXzfsm5RfOOyblF857JuUXzEw7JuUXzEx7JuUXzEy7JuUJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ+ydvOyalOydvF/sm5TsmpTsnbxf7ZmU7JqU7J28X+yImOyalOydvF/rqqnsmpTsnbxf6riI7JqU7J28X+2GoOyalOydvCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+ydvF/sm5Rf7ZmUX+yImF/rqqlf6riIX+2GoCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfsnbxf7JuUX+2ZlF/siJhf66qpX+q4iF/thqAnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0EgaDptbScsXG4gICAgICAgICAgICBMVFM6ICdBIGg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ1lZWVkuTU0uREQuJyxcbiAgICAgICAgICAgIExMOiAnWVlZWeuFhCBNTU1NIETsnbwnLFxuICAgICAgICAgICAgTExMOiAnWVlZWeuFhCBNTU1NIETsnbwgQSBoOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdZWVlZ64WEIE1NTU0gROydvCBkZGRkIEEgaDptbScsXG4gICAgICAgICAgICBsOiAnWVlZWS5NTS5ERC4nLFxuICAgICAgICAgICAgbGw6ICdZWVlZ64WEIE1NTU0gROydvCcsXG4gICAgICAgICAgICBsbGw6ICdZWVlZ64WEIE1NTU0gROydvCBBIGg6bW0nLFxuICAgICAgICAgICAgbGxsbDogJ1lZWVnrhYQgTU1NTSBE7J28IGRkZGQgQSBoOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICfsmKTripggTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ+uCtOydvCBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ+yWtOygnCBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ+yngOuCnOyjvCBkZGRkIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg7ZuEJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDsoIQnLFxuICAgICAgICAgICAgczogJ+uqhyDstIgnLFxuICAgICAgICAgICAgc3M6ICclZOy0iCcsXG4gICAgICAgICAgICBtOiAnMeu2hCcsXG4gICAgICAgICAgICBtbTogJyVk67aEJyxcbiAgICAgICAgICAgIGg6ICftlZwg7Iuc6rCEJyxcbiAgICAgICAgICAgIGhoOiAnJWTsi5zqsIQnLFxuICAgICAgICAgICAgZDogJ+2VmOujqCcsXG4gICAgICAgICAgICBkZDogJyVk7J28JyxcbiAgICAgICAgICAgIE06ICftlZwg64usJyxcbiAgICAgICAgICAgIE1NOiAnJWTri6wnLFxuICAgICAgICAgICAgeTogJ+ydvCDrhYQnLFxuICAgICAgICAgICAgeXk6ICclZOuFhCcsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSjsnbx87JuUfOyjvCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfsnbwnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+yblCc7XG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn7KO8JztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv7Jik7KCEfOyYpO2bhC8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uICh0b2tlbikge1xuICAgICAgICAgICAgcmV0dXJuIHRva2VuID09PSAn7Jik7ZuEJztcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzVXBwZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyIDwgMTIgPyAn7Jik7KCEJyA6ICfsmKTtm4QnO1xuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCRiID0ge1xuICAgICAgICAgICAgMTogJ9mhJyxcbiAgICAgICAgICAgIDI6ICfZoicsXG4gICAgICAgICAgICAzOiAn2aMnLFxuICAgICAgICAgICAgNDogJ9mkJyxcbiAgICAgICAgICAgIDU6ICfZpScsXG4gICAgICAgICAgICA2OiAn2aYnLFxuICAgICAgICAgICAgNzogJ9mnJyxcbiAgICAgICAgICAgIDg6ICfZqCcsXG4gICAgICAgICAgICA5OiAn2aknLFxuICAgICAgICAgICAgMDogJ9mgJyxcbiAgICAgICAgfSxcbiAgICAgICAgbnVtYmVyTWFwJGEgPSB7XG4gICAgICAgICAgICAn2aEnOiAnMScsXG4gICAgICAgICAgICAn2aInOiAnMicsXG4gICAgICAgICAgICAn2aMnOiAnMycsXG4gICAgICAgICAgICAn2aQnOiAnNCcsXG4gICAgICAgICAgICAn2aUnOiAnNScsXG4gICAgICAgICAgICAn2aYnOiAnNicsXG4gICAgICAgICAgICAn2acnOiAnNycsXG4gICAgICAgICAgICAn2agnOiAnOCcsXG4gICAgICAgICAgICAn2aknOiAnOScsXG4gICAgICAgICAgICAn2aAnOiAnMCcsXG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRocyQ4ID0gW1xuICAgICAgICAgICAgJ9qp2KfZhtmI2YbbjCDYr9mI2YjbldmFJyxcbiAgICAgICAgICAgICfYtNmI2KjYp9iqJyxcbiAgICAgICAgICAgICfYptin2LLYp9ixJyxcbiAgICAgICAgICAgICfZhtuM2LPYp9mGJyxcbiAgICAgICAgICAgICfYptin24zYp9ixJyxcbiAgICAgICAgICAgICfYrdmI2LLblduM2LHYp9mGJyxcbiAgICAgICAgICAgICfYqtuV2YXZhdmI2LInLFxuICAgICAgICAgICAgJ9im2KfYqCcsXG4gICAgICAgICAgICAn2KbblduM2YTZiNmI2YQnLFxuICAgICAgICAgICAgJ9iq2LTYsduM2YbbjCDbjNuV2YPbldmFJyxcbiAgICAgICAgICAgICfYqti02LHbjNmG24wg2K/ZiNmI25XZhScsXG4gICAgICAgICAgICAn2YPYp9mG2YjZhtuMINuM25XaqduV2YUnLFxuICAgICAgICBdO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdrdScsIHtcbiAgICAgICAgbW9udGhzOiBtb250aHMkOCxcbiAgICAgICAgbW9udGhzU2hvcnQ6IG1vbnRocyQ4LFxuICAgICAgICB3ZWVrZGF5czogJ9uM2YfigIzZg9i02YfigIzZhdmF2YfigIxf2K/ZiNmI2LTZh+KAjNmF2YXZh+KAjF/Ys9uO2LTZh+KAjNmF2YXZh+KAjF/ahtmI2KfYsdi02YfigIzZhdmF2YfigIxf2b7bjtmG2KzYtNmH4oCM2YXZhdmH4oCMX9mH2YfigIzbjNmG24xf2LTZh+KAjNmF2YXZh+KAjCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9uM2YfigIzZg9i02YfigIzZhV/Yr9mI2YjYtNmH4oCM2YVf2LPbjti02YfigIzZhV/ahtmI2KfYsdi02YfigIzZhV/ZvtuO2YbYrNi02YfigIzZhV/Zh9mH4oCM24zZhtuMX9i02YfigIzZhdmF2YfigIwnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn24xf2K9f2LNf2oZf2b5f2Ydf2LQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv2KbbjtmI2KfYsdmH4oCMfNio2YfigIzbjNin2YbbjC8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIC/YptuO2YjYp9ix2YfigIwvLnRlc3QoaW5wdXQpO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2KjZh+KAjNuM2KfZhtuMJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfYptuO2YjYp9ix2YfigIwnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYptmH4oCM2YXYsduGINmD2KfYqtqY2YXbjtixXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9io2YfigIzbjNin2YbbjCDZg9in2KramNmF247YsV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvZg9in2KramNmF247YsV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYr9mI247ZhtuOINmD2KfYqtqY2YXbjtixXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW9mD2KfYqtqY2YXbjtixXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9mE2YfigIwgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzJyxcbiAgICAgICAgICAgIHM6ICfahtmH4oCM2YbYryDahtix2YPZh+KAjNuM2YfigIzZgycsXG4gICAgICAgICAgICBzczogJ9qG2LHZg9mH4oCMICVkJyxcbiAgICAgICAgICAgIG06ICfbjNmH4oCM2YMg2K7ZiNmE2YfigIzZgycsXG4gICAgICAgICAgICBtbTogJyVkINiu2YjZhNmH4oCM2YMnLFxuICAgICAgICAgICAgaDogJ9uM2YfigIzZgyDZg9in2KramNmF247YsScsXG4gICAgICAgICAgICBoaDogJyVkINmD2KfYqtqY2YXbjtixJyxcbiAgICAgICAgICAgIGQ6ICfbjNmH4oCM2YMg2pXbhtqYJyxcbiAgICAgICAgICAgIGRkOiAnJWQg2pXbhtqYJyxcbiAgICAgICAgICAgIE06ICfbjNmH4oCM2YMg2YXYp9mG2q8nLFxuICAgICAgICAgICAgTU06ICclZCDZhdin2YbarycsXG4gICAgICAgICAgICB5OiAn24zZh+KAjNmDINiz2KfatScsXG4gICAgICAgICAgICB5eTogJyVkINiz2KfatScsXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL1vZodmi2aPZpNml2abZp9mo2anZoF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkYVttYXRjaF07XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1xuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXAkYlttYXRjaF07XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiA2LCAvLyBTYXR1cmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiAxMiwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMTJ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzdWZmaXhlcyQyID0ge1xuICAgICAgICAwOiAnLdGH0q8nLFxuICAgICAgICAxOiAnLdGH0LgnLFxuICAgICAgICAyOiAnLdGH0LgnLFxuICAgICAgICAzOiAnLdGH0q8nLFxuICAgICAgICA0OiAnLdGH0q8nLFxuICAgICAgICA1OiAnLdGH0LgnLFxuICAgICAgICA2OiAnLdGH0YsnLFxuICAgICAgICA3OiAnLdGH0LgnLFxuICAgICAgICA4OiAnLdGH0LgnLFxuICAgICAgICA5OiAnLdGH0YMnLFxuICAgICAgICAxMDogJy3Rh9GDJyxcbiAgICAgICAgMjA6ICct0YfRiycsXG4gICAgICAgIDMwOiAnLdGH0YMnLFxuICAgICAgICA0MDogJy3Rh9GLJyxcbiAgICAgICAgNTA6ICct0YfSrycsXG4gICAgICAgIDYwOiAnLdGH0YsnLFxuICAgICAgICA3MDogJy3Rh9C4JyxcbiAgICAgICAgODA6ICct0YfQuCcsXG4gICAgICAgIDkwOiAnLdGH0YMnLFxuICAgICAgICAxMDA6ICct0YfSrycsXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgna3knLCB7XG4gICAgICAgIG1vbnRoczogJ9GP0L3QstCw0YDRjF/RhNC10LLRgNCw0LvRjF/QvNCw0YDRgl/QsNC/0YDQtdC70Yxf0LzQsNC5X9C40Y7QvdGMX9C40Y7Qu9GMX9Cw0LLQs9GD0YHRgl/RgdC10L3RgtGP0LHRgNGMX9C+0LrRgtGP0LHRgNGMX9C90L7Rj9Cx0YDRjF/QtNC10LrQsNCx0YDRjCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfRj9C90LJf0YTQtdCyX9C80LDRgNGCX9Cw0L/RgF/QvNCw0Llf0LjRjtC90Yxf0LjRjtC70Yxf0LDQstCzX9GB0LXQvV/QvtC60YJf0L3QvtGPX9C00LXQuicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfQltC10LrRiNC10LzQsdC4X9CU0q/QudGI06nQvNCx0q9f0KjQtdC50YjQtdC80LHQuF/QqNCw0YDRiNC10LzQsdC4X9CR0LXQudGI0LXQvNCx0Lhf0JbRg9C80LBf0JjRiNC10LzQsdC4Jy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn0JbQtdC6X9CU0q/QuV/QqNC10Llf0KjQsNGAX9CR0LXQuV/QltGD0Lxf0JjRiNC1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9CW0Lpf0JTQuV/QqNC5X9Co0YBf0JHQuV/QltC8X9CY0YgnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb0JHSr9Cz0q/QvSDRgdCw0LDRgl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vQrdGA0YLQtdKjINGB0LDQsNGCXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW9GB0LDQsNGCXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9Ca0LXRh9GN0Y0g0YHQsNCw0YJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW9Oo0YLQutOp0L0g0LDQv9GC0LDQvdGL0L1dIGRkZGQgW9C60q/QvdKvXSBb0YHQsNCw0YJdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg0LjRh9C40L3QtNC1JyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDQvNGD0YDRg9C9JyxcbiAgICAgICAgICAgIHM6ICfQsdC40YDQvdC10YfQtSDRgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgc3M6ICclZCDRgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgbTogJ9Cx0LjRgCDQvNKv0L3TqdGCJyxcbiAgICAgICAgICAgIG1tOiAnJWQg0LzSr9C906nRgicsXG4gICAgICAgICAgICBoOiAn0LHQuNGAINGB0LDQsNGCJyxcbiAgICAgICAgICAgIGhoOiAnJWQg0YHQsNCw0YInLFxuICAgICAgICAgICAgZDogJ9Cx0LjRgCDQutKv0L0nLFxuICAgICAgICAgICAgZGQ6ICclZCDQutKv0L0nLFxuICAgICAgICAgICAgTTogJ9Cx0LjRgCDQsNC5JyxcbiAgICAgICAgICAgIE1NOiAnJWQg0LDQuScsXG4gICAgICAgICAgICB5OiAn0LHQuNGAINC20YvQuycsXG4gICAgICAgICAgICB5eTogJyVkINC20YvQuycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0YfQuHzRh9GLfNGH0q980YfRgykvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIGIgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAoc3VmZml4ZXMkMltudW1iZXJdIHx8IHN1ZmZpeGVzJDJbYV0gfHwgc3VmZml4ZXMkMltiXSk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUkNihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgICAgIG06IFsnZW5nIE1pbnV0dCcsICdlbmdlciBNaW51dHQnXSxcbiAgICAgICAgICAgIGg6IFsnZW5nIFN0b25uJywgJ2VuZ2VyIFN0b25uJ10sXG4gICAgICAgICAgICBkOiBbJ2VlbiBEYWcnLCAnZW5nZW0gRGFnJ10sXG4gICAgICAgICAgICBNOiBbJ2VlIE1vdW50JywgJ2VuZ2VtIE1vdW50J10sXG4gICAgICAgICAgICB5OiBbJ2VlIEpvZXInLCAnZW5nZW0gSm9lciddLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHByb2Nlc3NGdXR1cmVUaW1lKHN0cmluZykge1xuICAgICAgICB2YXIgbnVtYmVyID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZignICcpKTtcbiAgICAgICAgaWYgKGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihudW1iZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gJ2EgJyArIHN0cmluZztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJ2FuICcgKyBzdHJpbmc7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHByb2Nlc3NQYXN0VGltZShzdHJpbmcpIHtcbiAgICAgICAgdmFyIG51bWJlciA9IHN0cmluZy5zdWJzdHIoMCwgc3RyaW5nLmluZGV4T2YoJyAnKSk7XG4gICAgICAgIGlmIChlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIobnVtYmVyKSkge1xuICAgICAgICAgICAgcmV0dXJuICd2aXJ1ICcgKyBzdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICd2aXJ1biAnICsgc3RyaW5nO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdvcmQgYmVmb3JlIHRoZSBnaXZlbiBudW1iZXIgbG9zZXMgdGhlICctbicgZW5kaW5nLlxuICAgICAqIGUuZy4gJ2FuIDEwIERlZWcnIGJ1dCAnYSA1IERlZWcnXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbnVtYmVyIHtpbnRlZ2VyfVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihudW1iZXIpIHtcbiAgICAgICAgbnVtYmVyID0gcGFyc2VJbnQobnVtYmVyLCAxMCk7XG4gICAgICAgIGlmIChpc05hTihudW1iZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgICAgICAgIC8vIE5lZ2F0aXZlIE51bWJlciAtLT4gYWx3YXlzIHRydWVcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDEwKSB7XG4gICAgICAgICAgICAvLyBPbmx5IDEgZGlnaXRcbiAgICAgICAgICAgIGlmICg0IDw9IG51bWJlciAmJiBudW1iZXIgPD0gNykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDEwMCkge1xuICAgICAgICAgICAgLy8gMiBkaWdpdHNcbiAgICAgICAgICAgIHZhciBsYXN0RGlnaXQgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBmaXJzdERpZ2l0ID0gbnVtYmVyIC8gMTA7XG4gICAgICAgICAgICBpZiAobGFzdERpZ2l0ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihmaXJzdERpZ2l0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIobGFzdERpZ2l0KTtcbiAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPCAxMDAwMCkge1xuICAgICAgICAgICAgLy8gMyBvciA0IGRpZ2l0cyAtLT4gcmVjdXJzaXZlbHkgY2hlY2sgZmlyc3QgZGlnaXRcbiAgICAgICAgICAgIHdoaWxlIChudW1iZXIgPj0gMTApIHtcbiAgICAgICAgICAgICAgICBudW1iZXIgPSBudW1iZXIgLyAxMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIobnVtYmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEFueXRoaW5nIGxhcmdlciB0aGFuIDQgZGlnaXRzOiByZWN1cnNpdmVseSBjaGVjayBmaXJzdCBuLTMgZGlnaXRzXG4gICAgICAgICAgICBudW1iZXIgPSBudW1iZXIgLyAxMDAwO1xuICAgICAgICAgICAgcmV0dXJuIGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihudW1iZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdsYicsIHtcbiAgICAgICAgbW9udGhzOiAnSmFudWFyX0ZlYnJ1YXJfTcOkZXJ6X0FicsOrbGxfTWVlX0p1bmlfSnVsaV9BdWd1c3RfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGV6ZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuLl9GZWJyLl9NcnouX0Fici5fTWVlX0p1bi5fSnVsLl9BdWcuX1NlcHQuX09rdC5fTm92Ll9EZXouJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ1Nvbm5kZWdfTcOpaW5kZWdfRMOrbnNjaGRlZ19Nw6t0dHdvY2hfRG9ubmVzY2hkZWdfRnJlaWRlZ19TYW1zY2hkZWcnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTby5fTcOpLl9Ew6suX03Dqy5fRG8uX0ZyLl9TYS4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU29fTcOpX0TDq19Nw6tfRG9fRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbSBbQXVlcl0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcyBbQXVlcl0nLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRC4gTU1NTSBZWVlZIEg6bW0gW0F1ZXJdJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSBbQXVlcl0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tIYXV0IHVtXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tNdWVyIHVtXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3VtXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0fDq3NjaHRlciB1bV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAvLyBEaWZmZXJlbnQgZGF0ZSBzdHJpbmcgZm9yICdEw6tuc2NoZGVnJyAoVHVlc2RheSkgYW5kICdEb25uZXNjaGRlZycgKFRodXJzZGF5KSBkdWUgdG8gcGhvbm9sb2dpY2FsIHJ1bGVcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tMZXNjaHRlbl0gZGRkZCBbdW1dIExUJztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW0xlc2NodGVdIGRkZGQgW3VtXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6IHByb2Nlc3NGdXR1cmVUaW1lLFxuICAgICAgICAgICAgcGFzdDogcHJvY2Vzc1Bhc3RUaW1lLFxuICAgICAgICAgICAgczogJ2UgcHVlciBTZWtvbm5lbicsXG4gICAgICAgICAgICBzczogJyVkIFNla29ubmVuJyxcbiAgICAgICAgICAgIG06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNixcbiAgICAgICAgICAgIG1tOiAnJWQgTWludXR0ZW4nLFxuICAgICAgICAgICAgaDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgaGg6ICclZCBTdG9ubmVuJyxcbiAgICAgICAgICAgIGQ6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNixcbiAgICAgICAgICAgIGRkOiAnJWQgRGVlZycsXG4gICAgICAgICAgICBNOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDYsXG4gICAgICAgICAgICBNTTogJyVkIE3DqWludCcsXG4gICAgICAgICAgICB5OiBwcm9jZXNzUmVsYXRpdmVUaW1lJDYsXG4gICAgICAgICAgICB5eTogJyVkIEpvZXInLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdsbycsIHtcbiAgICAgICAgbW9udGhzOiAn4Lqh4Lqx4LqH4LqB4Lqt4LqZX+C6geC6uOC6oeC6nuC6sl/guqHgurXgupngurJf4LuA4Lqh4Lqq4LqyX+C6nuC6tuC6lOC6quC6sOC6nuC6sl/guqHgurTgupbgurjgupngurJf4LqB4LuN4Lql4Lqw4LqB4Lq74LqUX+C6quC6tOC6h+C6q+C6sl/guoHgurHgupnguo3gurJf4LqV4Lq44Lql4LqyX+C6nuC6sOC6iOC6tOC6gV/gupfgurHgupnguqfgurInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn4Lqh4Lqx4LqH4LqB4Lqt4LqZX+C6geC6uOC6oeC6nuC6sl/guqHgurXgupngurJf4LuA4Lqh4Lqq4LqyX+C6nuC6tuC6lOC6quC6sOC6nuC6sl/guqHgurTgupbgurjgupngurJf4LqB4LuN4Lql4Lqw4LqB4Lq74LqUX+C6quC6tOC6h+C6q+C6sl/guoHgurHgupnguo3gurJf4LqV4Lq44Lql4LqyX+C6nuC6sOC6iOC6tOC6gV/gupfgurHgupnguqfgurInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzOiAn4Lqt4Lqy4LqX4Lq04LqUX+C6iOC6seC6mV/guq3gurHguofguoTgurLguplf4Lqe4Lq44LqUX+C6nuC6sOC6q+C6seC6lF/guqrgurjguoFf4LuA4Lqq4Lq74LqyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn4LqX4Lq04LqUX+C6iOC6seC6mV/guq3gurHguofguoTgurLguplf4Lqe4Lq44LqUX+C6nuC6sOC6q+C6seC6lF/guqrgurjguoFf4LuA4Lqq4Lq74LqyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ+C6l1/guohf4Lqt4LqEX+C6nl/gup7guqtf4Lqq4LqBX+C6qicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICfguqfgurHguplkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+C6leC6reC6meC7gOC6iuC6u+C7ieC6snzgupXguq3gupngu4HguqXguocvLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PT0gJ+C6leC6reC6meC7geC6peC6hyc7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgupXguq3gupngu4Dguorgurvgu4ngurInO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C6leC6reC6meC7geC6peC6hyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+C6oeC6t+C7ieC6meC6teC7ieC7gOC6p+C6peC6sl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vguqHgurfgu4nguq3gurfgu4jgupngu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW+C6p+C6seC6mV1kZGRkW+C7nOC7ieC6suC7gOC6p+C6peC6sl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vguqHgurfgu4nguqfgurLgupngupngurXgu4ngu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+C6p+C6seC6mV1kZGRkW+C7geC6peC7ieC6p+C6meC6teC7ieC7gOC6p+C6peC6sl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICfguq3gurXguoEgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVz4Lqc4LuI4Lqy4LqZ4Lqh4LqyJyxcbiAgICAgICAgICAgIHM6ICfguprgu43gu4jgu4Dgupfgurvgu4jgurLgu4PgupTguqfgurTgupngurLgupfgurUnLFxuICAgICAgICAgICAgc3M6ICclZCDguqfgurTgupngurLgupfgurUnLFxuICAgICAgICAgICAgbTogJzEg4LqZ4Lqy4LqX4Lq1JyxcbiAgICAgICAgICAgIG1tOiAnJWQg4LqZ4Lqy4LqX4Lq1JyxcbiAgICAgICAgICAgIGg6ICcxIOC6iuC6u+C7iOC6p+C7guC6oeC6hycsXG4gICAgICAgICAgICBoaDogJyVkIOC6iuC6u+C7iOC6p+C7guC6oeC6hycsXG4gICAgICAgICAgICBkOiAnMSDguqHgurfgu4knLFxuICAgICAgICAgICAgZGQ6ICclZCDguqHgurfgu4knLFxuICAgICAgICAgICAgTTogJzEg4LuA4LqU4Lq34Lqt4LqZJyxcbiAgICAgICAgICAgIE1NOiAnJWQg4LuA4LqU4Lq34Lqt4LqZJyxcbiAgICAgICAgICAgIHk6ICcxIOC6m+C6tScsXG4gICAgICAgICAgICB5eTogJyVkIOC6m+C6tScsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC8o4LqX4Lq14LuIKVxcZHsxLDJ9LyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuICfgupfgurXgu4gnICsgbnVtYmVyO1xuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHVuaXRzID0ge1xuICAgICAgICBzczogJ3Nla3VuZMSXX3Nla3VuZMW+acWzX3Nla3VuZGVzJyxcbiAgICAgICAgbTogJ21pbnV0xJdfbWludXTEl3NfbWludXTEmScsXG4gICAgICAgIG1tOiAnbWludXTEl3NfbWludcSNacWzX21pbnV0ZXMnLFxuICAgICAgICBoOiAndmFsYW5kYV92YWxhbmRvc192YWxhbmTEhScsXG4gICAgICAgIGhoOiAndmFsYW5kb3NfdmFsYW5kxbNfdmFsYW5kYXMnLFxuICAgICAgICBkOiAnZGllbmFfZGllbm9zX2RpZW7EhScsXG4gICAgICAgIGRkOiAnZGllbm9zX2RpZW7Fs19kaWVuYXMnLFxuICAgICAgICBNOiAnbcSXbnVvX23El25lc2lvX23El25lc8SvJyxcbiAgICAgICAgTU06ICdtxJduZXNpYWlfbcSXbmVzacWzX23El25lc2l1cycsXG4gICAgICAgIHk6ICdtZXRhaV9tZXTFs19tZXR1cycsXG4gICAgICAgIHl5OiAnbWV0YWlfbWV0xbNfbWV0dXMnLFxuICAgIH07XG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlU2Vjb25kcyhudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgIHJldHVybiAna2VsaW9zIHNla3VuZMSXcyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAna2VsacWzIHNla3VuZMW+acWzJyA6ICdrZWxpYXMgc2VrdW5kZXMnO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZVNpbmd1bGFyKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeFxuICAgICAgICAgICAgPyBmb3JtcyhrZXkpWzBdXG4gICAgICAgICAgICA6IGlzRnV0dXJlXG4gICAgICAgICAgICA/IGZvcm1zKGtleSlbMV1cbiAgICAgICAgICAgIDogZm9ybXMoa2V5KVsyXTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc3BlY2lhbChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciAlIDEwID09PSAwIHx8IChudW1iZXIgPiAxMCAmJiBudW1iZXIgPCAyMCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGZvcm1zKGtleSkge1xuICAgICAgICByZXR1cm4gdW5pdHNba2V5XS5zcGxpdCgnXycpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkNihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICByZXN1bHQgKyB0cmFuc2xhdGVTaW5ndWxhcihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleVswXSwgaXNGdXR1cmUpXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoc3BlY2lhbChudW1iZXIpID8gZm9ybXMoa2V5KVsxXSA6IGZvcm1zKGtleSlbMF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIGZvcm1zKGtleSlbMV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoc3BlY2lhbChudW1iZXIpID8gZm9ybXMoa2V5KVsxXSA6IGZvcm1zKGtleSlbMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbHQnLCB7XG4gICAgICAgIG1vbnRoczoge1xuICAgICAgICAgICAgZm9ybWF0OiAnc2F1c2lvX3Zhc2FyaW9fa292b19iYWxhbmTFvmlvX2dlZ3XFvsSXc19iaXLFvmVsaW9fbGllcG9zX3J1Z3BqxavEjWlvX3J1Z3PEl2pvX3NwYWxpb19sYXBrcmnEjWlvX2dydW9kxb5pbycuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ3NhdXNpc192YXNhcmlzX2tvdmFzX2JhbGFuZGlzX2dlZ3XFvsSXX2JpcsW+ZWxpc19saWVwYV9ydWdwasWrdGlzX3J1Z3PEl2ppc19zcGFsaXNfbGFwa3JpdGlzX2dydW9kaXMnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGlzRm9ybWF0OiAvRFtvRF0/KFxcW1teXFxbXFxdXSpcXF18XFxzKStNTU1NP3xNTU1NPyhcXFtbXlxcW1xcXV0qXFxdfFxccykrRFtvRF0/LyxcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdzYXVfdmFzX2tvdl9iYWxfZ2VnX2Jpcl9saWVfcmdwX3Jnc19zcGFfbGFwX2dyZCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ3Nla21hZGllbsSvX3Bpcm1hZGllbsSvX2FudHJhZGllbsSvX3RyZcSNaWFkaWVuxK9fa2V0dmlydGFkaWVuxK9fcGVua3RhZGllbsSvX8WhZcWhdGFkaWVuxK8nLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICdzZWttYWRpZW5pc19waXJtYWRpZW5pc19hbnRyYWRpZW5pc190cmXEjWlhZGllbmlzX2tldHZpcnRhZGllbmlzX3Blbmt0YWRpZW5pc1/FoWXFoXRhZGllbmlzJy5zcGxpdChcbiAgICAgICAgICAgICAgICAnXydcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBpc0Zvcm1hdDogL2RkZGQgSEg6bW0vLFxuICAgICAgICB9LFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnU2VrX1Bpcl9BbnRfVHJlX0tldF9QZW5fxaBlxaEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU19QX0FfVF9LX1BuX8WgJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgICAgIExMOiAnWVlZWSBbbS5dIE1NTU0gRCBbZC5dJyxcbiAgICAgICAgICAgIExMTDogJ1lZWVkgW20uXSBNTU1NIEQgW2QuXSwgSEg6bW0gW3ZhbC5dJyxcbiAgICAgICAgICAgIExMTEw6ICdZWVlZIFttLl0gTU1NTSBEIFtkLl0sIGRkZGQsIEhIOm1tIFt2YWwuXScsXG4gICAgICAgICAgICBsOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgICAgICBsbDogJ1lZWVkgW20uXSBNTU1NIEQgW2QuXScsXG4gICAgICAgICAgICBsbGw6ICdZWVlZIFttLl0gTU1NTSBEIFtkLl0sIEhIOm1tIFt2YWwuXScsXG4gICAgICAgICAgICBsbGxsOiAnWVlZWSBbbS5dIE1NTU0gRCBbZC5dLCBkZGQsIEhIOm1tIFt2YWwuXScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW8WgaWFuZGllbl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tSeXRval0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbVmFrYXJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW1ByYcSXanVzxK9dIGRkZGQgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdwbyAlcycsXG4gICAgICAgICAgICBwYXN0OiAncHJpZcWhICVzJyxcbiAgICAgICAgICAgIHM6IHRyYW5zbGF0ZVNlY29uZHMsXG4gICAgICAgICAgICBzczogdHJhbnNsYXRlJDYsXG4gICAgICAgICAgICBtOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgICAgIG1tOiB0cmFuc2xhdGUkNixcbiAgICAgICAgICAgIGg6IHRyYW5zbGF0ZVNpbmd1bGFyLFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0ZSQ2LFxuICAgICAgICAgICAgZDogdHJhbnNsYXRlU2luZ3VsYXIsXG4gICAgICAgICAgICBkZDogdHJhbnNsYXRlJDYsXG4gICAgICAgICAgICBNOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgICAgIE1NOiB0cmFuc2xhdGUkNixcbiAgICAgICAgICAgIHk6IHRyYW5zbGF0ZVNpbmd1bGFyLFxuICAgICAgICAgICAgeXk6IHRyYW5zbGF0ZSQ2LFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tb2ppLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICctb2ppJztcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHVuaXRzJDEgPSB7XG4gICAgICAgIHNzOiAnc2VrdW5kZXNfc2VrdW5kxJNtX3Nla3VuZGVfc2VrdW5kZXMnLnNwbGl0KCdfJyksXG4gICAgICAgIG06ICdtaW7Fq3Rlc19taW7Fq3TEk21fbWluxat0ZV9taW7Fq3Rlcycuc3BsaXQoJ18nKSxcbiAgICAgICAgbW06ICdtaW7Fq3Rlc19taW7Fq3TEk21fbWluxat0ZV9taW7Fq3Rlcycuc3BsaXQoJ18nKSxcbiAgICAgICAgaDogJ3N0dW5kYXNfc3R1bmTEgW1fc3R1bmRhX3N0dW5kYXMnLnNwbGl0KCdfJyksXG4gICAgICAgIGhoOiAnc3R1bmRhc19zdHVuZMSBbV9zdHVuZGFfc3R1bmRhcycuc3BsaXQoJ18nKSxcbiAgICAgICAgZDogJ2RpZW5hc19kaWVuxIFtX2RpZW5hX2RpZW5hcycuc3BsaXQoJ18nKSxcbiAgICAgICAgZGQ6ICdkaWVuYXNfZGllbsSBbV9kaWVuYV9kaWVuYXMnLnNwbGl0KCdfJyksXG4gICAgICAgIE06ICdtxJNuZcWhYV9txJNuZcWhaWVtX23Ek25lc2lzX23Ek25lxaFpJy5zcGxpdCgnXycpLFxuICAgICAgICBNTTogJ23Ek25lxaFhX23Ek25lxaFpZW1fbcSTbmVzaXNfbcSTbmXFoWknLnNwbGl0KCdfJyksXG4gICAgICAgIHk6ICdnYWRhX2dhZGllbV9nYWRzX2dhZGknLnNwbGl0KCdfJyksXG4gICAgICAgIHl5OiAnZ2FkYV9nYWRpZW1fZ2Fkc19nYWRpJy5zcGxpdCgnXycpLFxuICAgIH07XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHdpdGhvdXRTdWZmaXggYm9vbGVhbiB0cnVlID0gYSBsZW5ndGggb2YgdGltZTsgZmFsc2UgPSBiZWZvcmUvYWZ0ZXIgYSBwZXJpb2Qgb2YgdGltZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JtYXQkMShmb3JtcywgbnVtYmVyLCB3aXRob3V0U3VmZml4KSB7XG4gICAgICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAvLyBFLmcuIFwiMjEgbWluxat0ZVwiLCBcIjMgbWluxat0ZXNcIi5cbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgJSAxMCA9PT0gMSAmJiBudW1iZXIgJSAxMDAgIT09IDExID8gZm9ybXNbMl0gOiBmb3Jtc1szXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEUuZy4gXCIyMSBtaW7Fq3Rlc1wiIGFzIGluIFwicMSTYyAyMSBtaW7Fq3Rlc1wiLlxuICAgICAgICAgICAgLy8gRS5nLiBcIjMgbWluxat0xJNtXCIgYXMgaW4gXCJwxJNjIDMgbWluxat0xJNtXCIuXG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICUgMTAgPT09IDEgJiYgbnVtYmVyICUgMTAwICE9PSAxMSA/IGZvcm1zWzBdIDogZm9ybXNbMV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQxKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAnICcgKyBmb3JtYXQkMSh1bml0cyQxW2tleV0sIG51bWJlciwgd2l0aG91dFN1ZmZpeCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICByZXR1cm4gZm9ybWF0JDEodW5pdHMkMVtrZXldLCBudW1iZXIsIHdpdGhvdXRTdWZmaXgpO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZWxhdGl2ZVNlY29uZHMobnVtYmVyLCB3aXRob3V0U3VmZml4KSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2Rhxb5hcyBzZWt1bmRlcycgOiAnZGHFvsSBbSBzZWt1bmTEk20nO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbHYnLCB7XG4gICAgICAgIG1vbnRoczogJ2phbnbEgXJpc19mZWJydcSBcmlzX21hcnRzX2FwcsSrbGlzX21haWpzX2rFq25panNfasWrbGlqc19hdWd1c3RzX3NlcHRlbWJyaXNfb2t0b2JyaXNfbm92ZW1icmlzX2RlY2VtYnJpcycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdqYW5fZmViX21hcl9hcHJfbWFpX2rFq25fasWrbF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ3N2xJN0ZGllbmFfcGlybWRpZW5hX290cmRpZW5hX3RyZcWhZGllbmFfY2V0dXJ0ZGllbmFfcGlla3RkaWVuYV9zZXN0ZGllbmEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTdl9QX09fVF9DX1BrX1MnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU3ZfUF9PX1RfQ19Qa19TJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZLicsXG4gICAgICAgICAgICBMTDogJ1lZWVkuIFtnYWRhXSBELiBNTU1NJyxcbiAgICAgICAgICAgIExMTDogJ1lZWVkuIFtnYWRhXSBELiBNTU1NLCBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnWVlZWS4gW2dhZGFdIEQuIE1NTU0sIGRkZGQsIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbxaBvZGllbiBwdWxrc3Rlbl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tSxKt0IHB1bGtzdGVuXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3B1bGtzdGVuXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW1Zha2FyIHB1bGtzdGVuXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tQYWfEgWp1xaHEgV0gZGRkZCBbcHVsa3N0ZW5dIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAncMSTYyAlcycsXG4gICAgICAgICAgICBwYXN0OiAncGlybXMgJXMnLFxuICAgICAgICAgICAgczogcmVsYXRpdmVTZWNvbmRzLFxuICAgICAgICAgICAgc3M6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMSxcbiAgICAgICAgICAgIG06IHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcixcbiAgICAgICAgICAgIG1tOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEsXG4gICAgICAgICAgICBoOiByZWxhdGl2ZVRpbWVXaXRoU2luZ3VsYXIsXG4gICAgICAgICAgICBoaDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQxLFxuICAgICAgICAgICAgZDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICAgICAgZGQ6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMSxcbiAgICAgICAgICAgIE06IHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcixcbiAgICAgICAgICAgIE1NOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEsXG4gICAgICAgICAgICB5OiByZWxhdGl2ZVRpbWVXaXRoU2luZ3VsYXIsXG4gICAgICAgICAgICB5eTogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQxLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHRyYW5zbGF0b3IgPSB7XG4gICAgICAgIHdvcmRzOiB7XG4gICAgICAgICAgICAvL0RpZmZlcmVudCBncmFtbWF0aWNhbCBjYXNlc1xuICAgICAgICAgICAgc3M6IFsnc2VrdW5kJywgJ3Nla3VuZGEnLCAnc2VrdW5kaSddLFxuICAgICAgICAgICAgbTogWydqZWRhbiBtaW51dCcsICdqZWRub2cgbWludXRhJ10sXG4gICAgICAgICAgICBtbTogWydtaW51dCcsICdtaW51dGEnLCAnbWludXRhJ10sXG4gICAgICAgICAgICBoOiBbJ2plZGFuIHNhdCcsICdqZWRub2cgc2F0YSddLFxuICAgICAgICAgICAgaGg6IFsnc2F0JywgJ3NhdGEnLCAnc2F0aSddLFxuICAgICAgICAgICAgZGQ6IFsnZGFuJywgJ2RhbmEnLCAnZGFuYSddLFxuICAgICAgICAgICAgTU06IFsnbWplc2VjJywgJ21qZXNlY2EnLCAnbWplc2VjaSddLFxuICAgICAgICAgICAgeXk6IFsnZ29kaW5hJywgJ2dvZGluZScsICdnb2RpbmEnXSxcbiAgICAgICAgfSxcbiAgICAgICAgY29ycmVjdEdyYW1tYXRpY2FsQ2FzZTogZnVuY3Rpb24gKG51bWJlciwgd29yZEtleSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciA9PT0gMVxuICAgICAgICAgICAgICAgID8gd29yZEtleVswXVxuICAgICAgICAgICAgICAgIDogbnVtYmVyID49IDIgJiYgbnVtYmVyIDw9IDRcbiAgICAgICAgICAgICAgICA/IHdvcmRLZXlbMV1cbiAgICAgICAgICAgICAgICA6IHdvcmRLZXlbMl07XG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zbGF0ZTogZnVuY3Rpb24gKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgICAgICB2YXIgd29yZEtleSA9IHRyYW5zbGF0b3Iud29yZHNba2V5XTtcbiAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyB3b3JkS2V5WzBdIDogd29yZEtleVsxXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgbnVtYmVyICtcbiAgICAgICAgICAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRvci5jb3JyZWN0R3JhbW1hdGljYWxDYXNlKG51bWJlciwgd29yZEtleSlcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ21lJywge1xuICAgICAgICBtb250aHM6ICdqYW51YXJfZmVicnVhcl9tYXJ0X2FwcmlsX21hal9qdW5fanVsX2F2Z3VzdF9zZXB0ZW1iYXJfb2t0b2Jhcl9ub3ZlbWJhcl9kZWNlbWJhcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdqYW4uX2ZlYi5fbWFyLl9hcHIuX21hal9qdW5fanVsX2F2Zy5fc2VwLl9va3QuX25vdi5fZGVjLicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6ICduZWRqZWxqYV9wb25lZGplbGpha191dG9yYWtfc3JpamVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnbmVkLl9wb24uX3V0by5fc3JpLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnbmVfcG9fdXRfc3JfxI1lX3BlX3N1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tkYW5hcyB1XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW3NqdXRyYSB1XSBMVCcsXG5cbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtuZWRqZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3NyaWplZHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzdWJvdHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogJ1tqdcSNZSB1XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBsYXN0V2Vla0RheXMgPSBbXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsZV0gW25lZGplbGplXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICAgICAnW3Byb8WhbG9nXSBbcG9uZWRqZWxqa2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFt1dG9ya2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsZV0gW3NyaWplZGVdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFvEjWV0dnJ0a2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFtwZXRrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3Vib3RlXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxhc3RXZWVrRGF5c1t0aGlzLmRheSgpXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ3phICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICdwcmlqZSAlcycsXG4gICAgICAgICAgICBzOiAnbmVrb2xpa28gc2VrdW5kaScsXG4gICAgICAgICAgICBzczogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgICAgICBtOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIG1tOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGg6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICAgICAgZDogJ2RhbicsXG4gICAgICAgICAgICBkZDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgICAgICBNOiAnbWplc2VjJyxcbiAgICAgICAgICAgIE1NOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIHk6ICdnb2RpbnUnLFxuICAgICAgICAgICAgeXk6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNywgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdtaScsIHtcbiAgICAgICAgbW9udGhzOiAnS29oaS10xIF0ZV9IdWktdGFuZ3VydV9Qb3V0xastdGUtcmFuZ2lfUGFlbmdhLXdoxIF3aMSBX0hhcmF0dWFfUGlwaXJpX0jFjW5nb2luZ29pX0hlcmUtdHVyaS1rxY1rxIFfTWFodXJ1X1doaXJpbmdhLcSBLW51a3VfV2hpcmluZ2EtxIEtcmFuZ2lfSGFraWhlYScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdLb2hpX0h1aV9Qb3VfUGFlX0hhcmFfUGlwaV9IxY1uZ29pX0hlcmVfTWFodV9XaGktbnVfV2hpLXJhX0hha2knLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1JlZ2V4OiAvKD86WydhLXpcXHUwMTAxXFx1MDE0RFxcdTAxNkJdK1xcLT8pezEsM30vaSxcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC8oPzpbJ2EtelxcdTAxMDFcXHUwMTREXFx1MDE2Ql0rXFwtPyl7MSwzfS9pLFxuICAgICAgICBtb250aHNTaG9ydFJlZ2V4OiAvKD86WydhLXpcXHUwMTAxXFx1MDE0RFxcdTAxNkJdK1xcLT8pezEsM30vaSxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogLyg/OlsnYS16XFx1MDEwMVxcdTAxNERcXHUwMTZCXStcXC0/KXsxLDJ9L2ksXG4gICAgICAgIHdlZWtkYXlzOiAnUsSBdGFwdV9NYW5lX1TFq3JlaV9XZW5lcmVpX1TEgWl0ZV9QYXJhaXJlX0jEgXRhcmVpJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnVGFfTWFfVMWrX1dlX1TEgWlfUGFfSMSBJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1RhX01hX1TFq19XZV9UxIFpX1BhX0jEgScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBbaV0gSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIFtpXSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2kgdGVpZSBtYWhhbmEsIGldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbYXBvcG8gaV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtpXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW2luYW5haGkgaV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFt3aGFrYW11dHVuZ2EgaV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdpIHJvdG8gaSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgaSBtdWEnLFxuICAgICAgICAgICAgczogJ3RlIGjEk2tvbmEgcnVhcnVhJyxcbiAgICAgICAgICAgIHNzOiAnJWQgaMSTa29uYScsXG4gICAgICAgICAgICBtOiAnaGUgbWVuZXRpJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWVuZXRpJyxcbiAgICAgICAgICAgIGg6ICd0ZSBoYW9yYScsXG4gICAgICAgICAgICBoaDogJyVkIGhhb3JhJyxcbiAgICAgICAgICAgIGQ6ICdoZSByYScsXG4gICAgICAgICAgICBkZDogJyVkIHJhJyxcbiAgICAgICAgICAgIE06ICdoZSBtYXJhbWEnLFxuICAgICAgICAgICAgTU06ICclZCBtYXJhbWEnLFxuICAgICAgICAgICAgeTogJ2hlIHRhdScsXG4gICAgICAgICAgICB5eTogJyVkIHRhdScsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbDogJyVkwronLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ21rJywge1xuICAgICAgICBtb250aHM6ICfRmNCw0L3Rg9Cw0YDQuF/RhNC10LLRgNGD0LDRgNC4X9C80LDRgNGCX9Cw0L/RgNC40Ltf0LzQsNGYX9GY0YPQvdC4X9GY0YPQu9C4X9Cw0LLQs9GD0YHRgl/RgdC10L/RgtC10LzQstGA0Lhf0L7QutGC0L7QvNCy0YDQuF/QvdC+0LXQvNCy0YDQuF/QtNC10LrQtdC80LLRgNC4Jy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ9GY0LDQvV/RhNC10LJf0LzQsNGAX9Cw0L/RgF/QvNCw0Zhf0ZjRg9C9X9GY0YPQu1/QsNCy0LNf0YHQtdC/X9C+0LrRgl/QvdC+0LVf0LTQtdC6Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ9C90LXQtNC10LvQsF/Qv9C+0L3QtdC00LXQu9C90LjQul/QstGC0L7RgNC90LjQul/RgdGA0LXQtNCwX9GH0LXRgtCy0YDRgtC+0Lpf0L/QtdGC0L7Qul/RgdCw0LHQvtGC0LAnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfQvdC10LRf0L/QvtC9X9Cy0YLQvl/RgdGA0LVf0YfQtdGCX9C/0LXRgl/RgdCw0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn0L1lX9C/b1/QstGCX9GB0YBf0YfQtV/Qv9C1X9GBYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb0JTQtdC90LXRgSDQstC+XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9Cj0YLRgNC1INCy0L5dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW9CS0L5dIGRkZGQgW9Cy0L5dIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb0JLRh9C10YDQsCDQstC+XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JjQt9C80LjQvdCw0YLQsNGC0LBdIGRkZGQgW9Cy0L5dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JjQt9C80LjQvdCw0YLQuNC+0YJdIGRkZGQgW9Cy0L5dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICfQt9CwICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICfQv9GA0LXQtCAlcycsXG4gICAgICAgICAgICBzOiAn0L3QtdC60L7Qu9C60YMg0YHQtdC60YPQvdC00LgnLFxuICAgICAgICAgICAgc3M6ICclZCDRgdC10LrRg9C90LTQuCcsXG4gICAgICAgICAgICBtOiAn0LXQtNC90LAg0LzQuNC90YPRgtCwJyxcbiAgICAgICAgICAgIG1tOiAnJWQg0LzQuNC90YPRgtC4JyxcbiAgICAgICAgICAgIGg6ICfQtdC00LXQvSDRh9Cw0YEnLFxuICAgICAgICAgICAgaGg6ICclZCDRh9Cw0YHQsCcsXG4gICAgICAgICAgICBkOiAn0LXQtNC10L0g0LTQtdC9JyxcbiAgICAgICAgICAgIGRkOiAnJWQg0LTQtdC90LAnLFxuICAgICAgICAgICAgTTogJ9C10LTQtdC9INC80LXRgdC10YYnLFxuICAgICAgICAgICAgTU06ICclZCDQvNC10YHQtdGG0LgnLFxuICAgICAgICAgICAgeTogJ9C10LTQvdCwINCz0L7QtNC40L3QsCcsXG4gICAgICAgICAgICB5eTogJyVkINCz0L7QtNC40L3QuCcsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0LXQsnzQtdC9fNGC0Lh80LLQuHzRgNC4fNC80LgpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGxhc3REaWdpdCA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIGxhc3QyRGlnaXRzID0gbnVtYmVyICUgMTAwO1xuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC10LInO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0MkRpZ2l0cyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC10L0nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0MkRpZ2l0cyA+IDEwICYmIGxhc3QyRGlnaXRzIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3RgtC4JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGFzdERpZ2l0ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LLQuCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxhc3REaWdpdCA9PT0gMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGA0LgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0RGlnaXQgPT09IDcgfHwgbGFzdERpZ2l0ID09PSA4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LzQuCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA3LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ21sJywge1xuICAgICAgICBtb250aHM6ICfgtJzgtKjgtYHgtLXgtLDgtL9f4LSr4LWG4LSs4LWN4LSw4LWB4LS14LSw4LS/X+C0ruC0vuC1vOC0muC1jeC0muC1jV/gtI/gtKrgtY3gtLDgtL/gtb1f4LSu4LWH4LSv4LWNX+C0nOC1guC1ul/gtJzgtYLgtLLgtYhf4LST4LSX4LS44LWN4LSx4LWN4LSx4LWNX+C0uOC1huC0quC1jeC0seC1jeC0seC0guC0rOC1vF/gtJLgtJXgtY3gtJ/gtYvgtKzgtbxf4LSo4LS14LSC4LSs4LW8X+C0oeC0v+C0uOC0guC0rOC1vCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgtJzgtKjgtYEuX+C0q+C1huC0rOC1jeC0sOC1gS5f4LSu4LS+4LW8Ll/gtI/gtKrgtY3gtLDgtL8uX+C0ruC1h+C0r+C1jV/gtJzgtYLgtbpf4LSc4LWC4LSy4LWILl/gtJPgtJcuX+C0uOC1huC0quC1jeC0seC1jeC0sS5f4LSS4LSV4LWN4LSf4LWLLl/gtKjgtLXgtIIuX+C0oeC0v+C0uOC0gi4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAn4LSe4LS+4LSv4LSx4LS+4LS04LWN4LSaX+C0pOC0v+C0meC1jeC0leC0s+C0vuC0tOC1jeC0ml/gtJrgtYrgtLXgtY3gtLXgtL7gtLTgtY3gtJpf4LSs4LWB4LSn4LSo4LS+4LS04LWN4LSaX+C0teC1jeC0r+C0vuC0tOC0vuC0tOC1jeC0ml/gtLXgtYbgtLPgtY3gtLPgtL/gtK/gtL7gtLTgtY3gtJpf4LS24LSo4LS/4LSv4LS+4LS04LWN4LSaJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn4LSe4LS+4LSv4LW8X+C0pOC0v+C0meC1jeC0leC1vl/gtJrgtYrgtLXgtY3gtLVf4LSs4LWB4LSn4LW7X+C0teC1jeC0r+C0vuC0tOC0gl/gtLXgtYbgtLPgtY3gtLPgtL9f4LS24LSo4LS/Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ+C0nuC0vl/gtKTgtL9f4LSa4LWKX+C0rOC1gV/gtLXgtY3gtK/gtL5f4LS14LWGX+C0ticuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnQSBoOm1tIC3gtKjgtYEnLFxuICAgICAgICAgICAgTFRTOiAnQSBoOm1tOnNzIC3gtKjgtYEnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIC3gtKjgtYEnLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0gLeC0qOC1gScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+C0h+C0qOC1jeC0qOC1jV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vgtKjgtL7gtLPgtYZdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCwgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vgtIfgtKjgtY3gtKjgtLLgtYZdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+C0leC0tOC0v+C0nuC1jeC0nl0gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclcyDgtJXgtLTgtL/gtJ7gtY3gtJ7gtY0nLFxuICAgICAgICAgICAgcGFzdDogJyVzIOC0ruC1geC1u+C0quC1jScsXG4gICAgICAgICAgICBzOiAn4LSF4LW94LSqIOC0qOC0v+C0ruC0v+C0t+C0meC1jeC0meC1vicsXG4gICAgICAgICAgICBzczogJyVkIOC0uOC1huC0leC1jeC0leC1u+C0oeC1jScsXG4gICAgICAgICAgICBtOiAn4LSS4LSw4LWBIOC0ruC0v+C0qOC0v+C0seC1jeC0seC1jScsXG4gICAgICAgICAgICBtbTogJyVkIOC0ruC0v+C0qOC0v+C0seC1jeC0seC1jScsXG4gICAgICAgICAgICBoOiAn4LSS4LSw4LWBIOC0ruC0o+C0v+C0leC1jeC0leC1guC1vCcsXG4gICAgICAgICAgICBoaDogJyVkIOC0ruC0o+C0v+C0leC1jeC0leC1guC1vCcsXG4gICAgICAgICAgICBkOiAn4LSS4LSw4LWBIOC0puC0v+C0teC0uOC0gicsXG4gICAgICAgICAgICBkZDogJyVkIOC0puC0v+C0teC0uOC0gicsXG4gICAgICAgICAgICBNOiAn4LSS4LSw4LWBIOC0ruC0vuC0uOC0gicsXG4gICAgICAgICAgICBNTTogJyVkIOC0ruC0vuC0uOC0gicsXG4gICAgICAgICAgICB5OiAn4LSS4LSw4LWBIOC0teC1vOC0t+C0gicsXG4gICAgICAgICAgICB5eTogJyVkIOC0teC1vOC0t+C0gicsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gtLDgtL7gtKTgtY3gtLDgtL984LSw4LS+4LS14LS/4LSy4LWGfOC0ieC0muC1jeC0miDgtJXgtLTgtL/gtJ7gtY3gtJ7gtY184LS14LWI4LSV4LWB4LSo4LWN4LSo4LWH4LSw4LSCfOC0sOC0vuC0pOC1jeC0sOC0vy9pLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgKG1lcmlkaWVtID09PSAn4LSw4LS+4LSk4LWN4LSw4LS/JyAmJiBob3VyID49IDQpIHx8XG4gICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfgtIngtJrgtY3gtJog4LSV4LS04LS/4LSe4LWN4LSe4LWNJyB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn4LS14LWI4LSV4LWB4LSo4LWN4LSo4LWH4LSw4LSCJ1xuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C0sOC0vuC0pOC1jeC0sOC0vyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LSw4LS+4LS14LS/4LSy4LWGJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgtIngtJrgtY3gtJog4LSV4LS04LS/4LSe4LWN4LSe4LWNJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgtLXgtYjgtJXgtYHgtKjgtY3gtKjgtYfgtLDgtIInO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C0sOC0vuC0pOC1jeC0sOC0vyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkNyhudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9GF0Y3QtNGF0Y3QvSDRgdC10LrRg9C90LQnIDogJ9GF0Y3QtNGF0Y3QvSDRgdC10LrRg9C90LTRi9C9JztcbiAgICAgICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKHdpdGhvdXRTdWZmaXggPyAnINGB0LXQutGD0L3QtCcgOiAnINGB0LXQutGD0L3QtNGL0L0nKTtcbiAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAod2l0aG91dFN1ZmZpeCA/ICcg0LzQuNC90YPRgicgOiAnINC80LjQvdGD0YLRi9C9Jyk7XG4gICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKHdpdGhvdXRTdWZmaXggPyAnINGG0LDQsycgOiAnINGG0LDQs9C40LnQvScpO1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICh3aXRob3V0U3VmZml4ID8gJyDTqdC006nRgCcgOiAnINOp0LTRgNC40LnQvScpO1xuICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICh3aXRob3V0U3VmZml4ID8gJyDRgdCw0YAnIDogJyDRgdCw0YDRi9C9Jyk7XG4gICAgICAgICAgICBjYXNlICd5JzpcbiAgICAgICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKHdpdGhvdXRTdWZmaXggPyAnINC20LjQuycgOiAnINC20LjQu9C40LnQvScpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdtbicsIHtcbiAgICAgICAgbW9udGhzOiAn0J3RjdCz0LTSr9Cz0Y3RjdGAINGB0LDRgF/QpdC+0ZHRgNC00YPQs9Cw0LDRgCDRgdCw0YBf0JPRg9GA0LDQstC00YPQs9Cw0LDRgCDRgdCw0YBf0JTTqdGA06nQstC00q/Qs9GN0Y3RgCDRgdCw0YBf0KLQsNCy0LTRg9Cz0LDQsNGAINGB0LDRgF/Ql9GD0YDQs9Cw0LTRg9Cz0LDQsNGAINGB0LDRgF/QlNC+0LvQtNGD0LPQsNCw0YAg0YHQsNGAX9Cd0LDQudC80LTRg9Cz0LDQsNGAINGB0LDRgF/QldGB0LTSr9Cz0Y3RjdGAINGB0LDRgF/QkNGA0LDQstC00YPQs9Cw0LDRgCDRgdCw0YBf0JDRgNCy0LDQvSDQvdGN0LPQtNKv0LPRjdGN0YAg0YHQsNGAX9CQ0YDQstCw0L0g0YXQvtGR0YDQtNGD0LPQsNCw0YAg0YHQsNGAJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJzEg0YHQsNGAXzIg0YHQsNGAXzMg0YHQsNGAXzQg0YHQsNGAXzUg0YHQsNGAXzYg0YHQsNGAXzcg0YHQsNGAXzgg0YHQsNGAXzkg0YHQsNGAXzEwINGB0LDRgF8xMSDRgdCw0YBfMTIg0YHQsNGAJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ9Cd0Y/QvF/QlNCw0LLQsNCwX9Cc0Y/Qs9C80LDRgF/Qm9GF0LDQs9Cy0LBf0J/Sr9GA0Y3Qsl/QkdCw0LDRgdCw0L1f0JHRj9C80LHQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9Cd0Y/QvF/QlNCw0LJf0JzRj9CzX9Cb0YXQsF/Qn9Kv0YBf0JHQsNCwX9CR0Y/QvCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfQndGPX9CU0LBf0JzRj1/Qm9GFX9Cf0q9f0JHQsF/QkdGPJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgICAgIExMOiAnWVlZWSDQvtC90YsgTU1NTdGL0L0gRCcsXG4gICAgICAgICAgICBMTEw6ICdZWVlZINC+0L3RiyBNTU1N0YvQvSBEIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBZWVlZINC+0L3RiyBNTU1N0YvQvSBEIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9Ku06h80q7QpS9pLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PT0gJ9Ku0KUnO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0q7TqCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0q7QpSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9Oo0L3TqdOp0LTTqdGAXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9Cc0LDRgNCz0LDQsNGIXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1vQmNGA0Y3RhV0gZGRkZCBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9Oo0YfQuNCz0LTTqdGAXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vTqNC90LPTqdGA0YHTqdC9XSBkZGRkIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg0LTQsNGA0LDQsCcsXG4gICAgICAgICAgICBwYXN0OiAnJXMg06nQvNC906knLFxuICAgICAgICAgICAgczogdHJhbnNsYXRlJDcsXG4gICAgICAgICAgICBzczogdHJhbnNsYXRlJDcsXG4gICAgICAgICAgICBtOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgICAgIG1tOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgICAgIGg6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICAgICAgZDogdHJhbnNsYXRlJDcsXG4gICAgICAgICAgICBkZDogdHJhbnNsYXRlJDcsXG4gICAgICAgICAgICBNOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgICAgIE1NOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgICAgIHk6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICAgICAgeXk6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0g06nQtNOp0YAvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcg06nQtNOp0YAnO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJGMgPSB7XG4gICAgICAgICAgICAxOiAn4KWnJyxcbiAgICAgICAgICAgIDI6ICfgpagnLFxuICAgICAgICAgICAgMzogJ+ClqScsXG4gICAgICAgICAgICA0OiAn4KWqJyxcbiAgICAgICAgICAgIDU6ICfgpasnLFxuICAgICAgICAgICAgNjogJ+ClrCcsXG4gICAgICAgICAgICA3OiAn4KWtJyxcbiAgICAgICAgICAgIDg6ICfgpa4nLFxuICAgICAgICAgICAgOTogJ+ClrycsXG4gICAgICAgICAgICAwOiAn4KWmJyxcbiAgICAgICAgfSxcbiAgICAgICAgbnVtYmVyTWFwJGIgPSB7XG4gICAgICAgICAgICAn4KWnJzogJzEnLFxuICAgICAgICAgICAgJ+ClqCc6ICcyJyxcbiAgICAgICAgICAgICfgpaknOiAnMycsXG4gICAgICAgICAgICAn4KWqJzogJzQnLFxuICAgICAgICAgICAgJ+Clqyc6ICc1JyxcbiAgICAgICAgICAgICfgpawnOiAnNicsXG4gICAgICAgICAgICAn4KWtJzogJzcnLFxuICAgICAgICAgICAgJ+Clric6ICc4JyxcbiAgICAgICAgICAgICfgpa8nOiAnOScsXG4gICAgICAgICAgICAn4KWmJzogJzAnLFxuICAgICAgICB9O1xuXG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lTXIobnVtYmVyLCB3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSAnJztcbiAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoc3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dCA9ICfgpJXgpL7gpLngpYAg4KS44KWH4KSV4KSC4KSmJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAnJWQg4KS44KWH4KSV4KSC4KSmJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dCA9ICfgpI/gpJUg4KSu4KS/4KSo4KS/4KSfJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAnJWQg4KSu4KS/4KSo4KS/4KSf4KWHJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dCA9ICfgpI/gpJUg4KSk4KS+4KS4JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAnJWQg4KSk4KS+4KS4JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dCA9ICfgpI/gpJUg4KSm4KS/4KS14KS4JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAnJWQg4KSm4KS/4KS14KS4JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dCA9ICfgpI/gpJUg4KSu4KS54KS/4KSo4KS+JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAnJWQg4KSu4KS54KS/4KSo4KWHJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAneSc6XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dCA9ICfgpI/gpJUg4KS14KSw4KWN4KS3JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAnJWQg4KS14KSw4KWN4KS34KWHJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHN0cmluZykge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAn4KSV4KS+4KS54KWAIOCkuOClh+CkleCkguCkpuCkvuCkgic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gJyVkIOCkuOClh+CkleCkguCkpuCkvuCkgic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAn4KSP4KSV4KS+IOCkruCkv+CkqOCkv+Ckn+Ckvic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gJyVkIOCkruCkv+CkqOCkv+Ckn+CkvuCkgic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAn4KSP4KSV4KS+IOCkpOCkvuCkuOCkvic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gJyVkIOCkpOCkvuCkuOCkvuCkgic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAn4KSP4KSV4KS+IOCkpuCkv+CkteCkuOCkvic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gJyVkIOCkpuCkv+CkteCkuOCkvuCkgic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAn4KSP4KSV4KS+IOCkruCkueCkv+CkqOCljeCkr+Ckvic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gJyVkIOCkruCkueCkv+CkqOCljeCkr+CkvuCkgic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAn4KSP4KSV4KS+IOCkteCksOCljeCkt+Ckvic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gJyVkIOCkteCksOCljeCkt+CkvuCkgic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXRwdXQucmVwbGFjZSgvJWQvaSwgbnVtYmVyKTtcbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ21yJywge1xuICAgICAgICBtb250aHM6ICfgpJzgpL7gpKjgpYfgpLXgpL7gpLDgpYBf4KSr4KWH4KSs4KWN4KSw4KWB4KS14KS+4KSw4KWAX+CkruCkvuCksOCljeCkml/gpI/gpKrgpY3gpLDgpL/gpLJf4KSu4KWHX+CknOClguCkqF/gpJzgpYHgpLLgpYhf4KSR4KSX4KS44KWN4KSfX+CkuOCkquCljeCkn+Clh+CkguCkrOCksF/gpJHgpJXgpY3gpJ/gpYvgpKzgpLBf4KSo4KWL4KS14KWN4KS54KWH4KSC4KSs4KSwX+CkoeCkv+CkuOClh+CkguCkrOCksCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgpJzgpL7gpKjgpYcuX+Ckq+Clh+CkrOCljeCksOClgS5f4KSu4KS+4KSw4KWN4KSaLl/gpI/gpKrgpY3gpLDgpL8uX+CkruClhy5f4KSc4KWC4KSoLl/gpJzgpYHgpLLgpYguX+CkkeCkly5f4KS44KSq4KWN4KSf4KWH4KSCLl/gpJHgpJXgpY3gpJ/gpYsuX+CkqOCli+CkteCljeCkueClh+Ckgi5f4KSh4KS/4KS44KWH4KSCLicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6ICfgpLDgpLXgpL/gpLXgpL7gpLBf4KS44KWL4KSu4KS14KS+4KSwX+CkruCkguCkl+Cks+CkteCkvuCksF/gpKzgpYHgpKfgpLXgpL7gpLBf4KSX4KWB4KSw4KWC4KS14KS+4KSwX+CktuClgeCkleCljeCksOCkteCkvuCksF/gpLbgpKjgpL/gpLXgpL7gpLAnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfgpLDgpLXgpL9f4KS44KWL4KSuX+CkruCkguCkl+Cks1/gpKzgpYHgpKdf4KSX4KWB4KSw4KWCX+CktuClgeCkleCljeCksF/gpLbgpKjgpL8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4KSwX+CkuOCli1/gpK7gpIJf4KSs4KWBX+Ckl+ClgV/gpLbgpYFf4KS2Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdBIGg6bW0g4KS14KS+4KSc4KSk4KS+JyxcbiAgICAgICAgICAgIExUUzogJ0EgaDptbTpzcyDgpLXgpL7gpJzgpKTgpL4nLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCkteCkvuCknOCkpOCkvicsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgpLXgpL7gpJzgpKTgpL4nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vgpIbgpJxdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4KSJ4KSm4KWN4KSv4KS+XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQsIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4KSV4KS+4KSyXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vgpK7gpL7gpJfgpYDgpLJdIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXPgpK7gpKfgpY3gpK/gpYcnLFxuICAgICAgICAgICAgcGFzdDogJyVz4KSq4KWC4KSw4KWN4KS14KWAJyxcbiAgICAgICAgICAgIHM6IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICAgICAgc3M6IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICAgICAgbTogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgICAgICBtbTogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgICAgICBoOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgICAgIGhoOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgICAgIGQ6IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICAgICAgZGQ6IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICAgICAgTTogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgICAgICBNTTogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgICAgICB5OiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgICAgIHl5OiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Clp+ClqOClqeClquClq+ClrOClreClruClr+Clpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCRiW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJGNbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gpKrgpLngpL7gpJ/gpYd84KS44KSV4KS+4KSz4KWAfOCkpuClgeCkquCkvuCksOClgHzgpLjgpL7gpK/gpILgpJXgpL7gpLPgpYB84KSw4KS+4KSk4KWN4KSw4KWALyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSq4KS54KS+4KSf4KWHJyB8fCBtZXJpZGllbSA9PT0gJ+CkuOCkleCkvuCks+ClgCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfgpKbgpYHgpKrgpL7gpLDgpYAnIHx8XG4gICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfgpLjgpL7gpK/gpILgpJXgpL7gpLPgpYAnIHx8XG4gICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfgpLDgpL7gpKTgpY3gpLDgpYAnXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMiA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA+PSAwICYmIGhvdXIgPCA2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpKrgpLngpL7gpJ/gpYcnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CkuOCkleCkvuCks+ClgCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KSm4KWB4KSq4KS+4KSw4KWAJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpLjgpL7gpK/gpILgpJXgpL7gpLPgpYAnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CksOCkvuCkpOCljeCksOClgCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDYsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbXMtbXknLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcmlfRmVicnVhcmlfTWFjX0FwcmlsX01laV9KdW5fSnVsYWlfT2dvc19TZXB0ZW1iZXJfT2t0b2Jlcl9Ob3ZlbWJlcl9EaXNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRmViX01hY19BcHJfTWVpX0p1bl9KdWxfT2dzX1NlcF9Pa3RfTm92X0Rpcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdBaGFkX0lzbmluX1NlbGFzYV9SYWJ1X0toYW1pc19KdW1hYXRfU2FidHUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdBaGRfSXNuX1NlbF9SYWJfS2hhX0p1bV9TYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnQWhfSXNfU2xfUmJfS21fSm1fU2InLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hILm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hILm1tLnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbScsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9wYWdpfHRlbmdhaGFyaXxwZXRhbmd8bWFsYW0vLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICdwYWdpJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3RlbmdhaGFyaScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAncGV0YW5nJyB8fCBtZXJpZGllbSA9PT0gJ21hbGFtJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VycyA8IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdwYWdpJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAndGVuZ2FoYXJpJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAncGV0YW5nJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdtYWxhbSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0hhcmkgaW5pIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0Vzb2sgcHVrdWxdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbS2VsbWFyaW4gcHVrdWxdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbbGVwYXMgcHVrdWxdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnZGFsYW0gJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIHlhbmcgbGVwYXMnLFxuICAgICAgICAgICAgczogJ2JlYmVyYXBhIHNhYXQnLFxuICAgICAgICAgICAgc3M6ICclZCBzYWF0JyxcbiAgICAgICAgICAgIG06ICdzZW1pbml0JyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWluaXQnLFxuICAgICAgICAgICAgaDogJ3NlamFtJyxcbiAgICAgICAgICAgIGhoOiAnJWQgamFtJyxcbiAgICAgICAgICAgIGQ6ICdzZWhhcmknLFxuICAgICAgICAgICAgZGQ6ICclZCBoYXJpJyxcbiAgICAgICAgICAgIE06ICdzZWJ1bGFuJyxcbiAgICAgICAgICAgIE1NOiAnJWQgYnVsYW4nLFxuICAgICAgICAgICAgeTogJ3NldGFodW4nLFxuICAgICAgICAgICAgeXk6ICclZCB0YWh1bicsXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbXMnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcmlfRmVicnVhcmlfTWFjX0FwcmlsX01laV9KdW5fSnVsYWlfT2dvc19TZXB0ZW1iZXJfT2t0b2Jlcl9Ob3ZlbWJlcl9EaXNlbWJlcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRmViX01hY19BcHJfTWVpX0p1bl9KdWxfT2dzX1NlcF9Pa3RfTm92X0Rpcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdBaGFkX0lzbmluX1NlbGFzYV9SYWJ1X0toYW1pc19KdW1hYXRfU2FidHUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdBaGRfSXNuX1NlbF9SYWJfS2hhX0p1bV9TYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnQWhfSXNfU2xfUmJfS21fSm1fU2InLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hILm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hILm1tLnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbScsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9wYWdpfHRlbmdhaGFyaXxwZXRhbmd8bWFsYW0vLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICdwYWdpJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3RlbmdhaGFyaScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAncGV0YW5nJyB8fCBtZXJpZGllbSA9PT0gJ21hbGFtJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VycyA8IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdwYWdpJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAndGVuZ2FoYXJpJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAncGV0YW5nJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdtYWxhbSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0hhcmkgaW5pIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0Vzb2sgcHVrdWxdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbS2VsbWFyaW4gcHVrdWxdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbbGVwYXMgcHVrdWxdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnZGFsYW0gJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIHlhbmcgbGVwYXMnLFxuICAgICAgICAgICAgczogJ2JlYmVyYXBhIHNhYXQnLFxuICAgICAgICAgICAgc3M6ICclZCBzYWF0JyxcbiAgICAgICAgICAgIG06ICdzZW1pbml0JyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWluaXQnLFxuICAgICAgICAgICAgaDogJ3NlamFtJyxcbiAgICAgICAgICAgIGhoOiAnJWQgamFtJyxcbiAgICAgICAgICAgIGQ6ICdzZWhhcmknLFxuICAgICAgICAgICAgZGQ6ICclZCBoYXJpJyxcbiAgICAgICAgICAgIE06ICdzZWJ1bGFuJyxcbiAgICAgICAgICAgIE1NOiAnJWQgYnVsYW4nLFxuICAgICAgICAgICAgeTogJ3NldGFodW4nLFxuICAgICAgICAgICAgeXk6ICclZCB0YWh1bicsXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbXQnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbm5hcl9GcmFyX01hcnp1X0FwcmlsX01lamp1X8SgdW5qdV9MdWxqdV9Bd3dpc3N1X1NldHRlbWJydV9PdHR1YnJ1X05vdmVtYnJ1X0RpxItlbWJydScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRnJhX01hcl9BcHJfTWVqX8SgdW5fTHVsX0F3d19TZXRfT3R0X05vdl9EacSLJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ0lsLcSmYWRkX0l0LVRuZWpuX0l0LVRsaWV0YV9MLUVyYmfEp2FfSWwtxKZhbWlzX0lsLcSgaW1nxKdhX0lzLVNpYnQnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfEpmFkX1RuZV9UbGlfRXJiX8SmYW1fxKBpbV9TaWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnxKZhX1RuX1RsX0VyX8SmYV/EoGlfU2knLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSWxsdW0gZmlsLV1MVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0fEp2FkYSBmaWwtXUxUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbZmlsLV1MVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0lsLWJpZXJhxKcgZmlsLV1MVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW2xpIGfEp2FkZGFdIFtmaWwtXUxUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnZuKAmSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgaWx1JyxcbiAgICAgICAgICAgIHM6ICdmdGl0IHNla29uZGknLFxuICAgICAgICAgICAgc3M6ICclZCBzZWtvbmRpJyxcbiAgICAgICAgICAgIG06ICdtaW51dGEnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGknLFxuICAgICAgICAgICAgaDogJ3NpZWfEp2EnLFxuICAgICAgICAgICAgaGg6ICclZCBzaWVnxKdhdCcsXG4gICAgICAgICAgICBkOiAnxKF1cm5hdGEnLFxuICAgICAgICAgICAgZGQ6ICclZCDEoXJhbmV0JyxcbiAgICAgICAgICAgIE06ICd4YWhhcicsXG4gICAgICAgICAgICBNTTogJyVkIHhodXInLFxuICAgICAgICAgICAgeTogJ3NlbmEnLFxuICAgICAgICAgICAgeXk6ICclZCBzbmknLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn3Cui8sXG4gICAgICAgIG9yZGluYWw6ICclZMK6JyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCRkID0ge1xuICAgICAgICAgICAgMTogJ+GBgScsXG4gICAgICAgICAgICAyOiAn4YGCJyxcbiAgICAgICAgICAgIDM6ICfhgYMnLFxuICAgICAgICAgICAgNDogJ+GBhCcsXG4gICAgICAgICAgICA1OiAn4YGFJyxcbiAgICAgICAgICAgIDY6ICfhgYYnLFxuICAgICAgICAgICAgNzogJ+GBhycsXG4gICAgICAgICAgICA4OiAn4YGIJyxcbiAgICAgICAgICAgIDk6ICfhgYknLFxuICAgICAgICAgICAgMDogJ+GBgCcsXG4gICAgICAgIH0sXG4gICAgICAgIG51bWJlck1hcCRjID0ge1xuICAgICAgICAgICAgJ+GBgSc6ICcxJyxcbiAgICAgICAgICAgICfhgYInOiAnMicsXG4gICAgICAgICAgICAn4YGDJzogJzMnLFxuICAgICAgICAgICAgJ+GBhCc6ICc0JyxcbiAgICAgICAgICAgICfhgYUnOiAnNScsXG4gICAgICAgICAgICAn4YGGJzogJzYnLFxuICAgICAgICAgICAgJ+GBhyc6ICc3JyxcbiAgICAgICAgICAgICfhgYgnOiAnOCcsXG4gICAgICAgICAgICAn4YGJJzogJzknLFxuICAgICAgICAgICAgJ+GBgCc6ICcwJyxcbiAgICAgICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbXknLCB7XG4gICAgICAgIG1vbnRoczogJ+GAh+GAlOGAuuGAlOGAneGAq+GAm+GArl/hgJbhgLHhgJbhgLHhgKzhgLrhgJ3hgKvhgJvhgK5f4YCZ4YCQ4YC6X+GAp+GAleGAvOGArl/hgJnhgLFf4YCH4YC94YCU4YC6X+GAh+GAsOGAnOGAreGAr+GAhOGAul/hgJ7hgLzhgILhgK/hgJDhgLpf4YCF4YCA4YC64YCQ4YCE4YC64YCY4YCsX+GAoeGAseGArOGAgOGAuuGAkOGAreGAr+GAmOGArF/hgJThgK3hgK/hgJ3hgIThgLrhgJjhgKxf4YCS4YCu4YCH4YCE4YC64YCY4YCsJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ+GAh+GAlOGAul/hgJbhgLFf4YCZ4YCQ4YC6X+GAleGAvOGArl/hgJnhgLFf4YCH4YC94YCU4YC6X+GAnOGAreGAr+GAhOGAul/hgJ7hgLxf4YCF4YCA4YC6X+GAoeGAseGArOGAgOGAul/hgJThgK3hgK9f4YCS4YCuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ+GAkOGAlOGAhOGAuuGAueGAguGAlOGAveGAsV/hgJDhgJThgIThgLrhgLnhgJzhgKxf4YCh4YCE4YC64YC54YCC4YCrX+GAl+GAr+GAkuGAueGAk+GAn+GAsOGAuF/hgIDhgLzhgKzhgJ7hgJXhgJDhgLHhgLhf4YCe4YCx4YCs4YCA4YC84YCsX+GAheGAlOGAsScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+GAlOGAveGAsV/hgJzhgKxf4YCC4YCrX+GAn+GAsOGAuF/hgIDhgLzhgKxf4YCe4YCx4YCsX+GAlOGAsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfhgJThgL3hgLFf4YCc4YCsX+GAguGAq1/hgJ/hgLDhgLhf4YCA4YC84YCsX+GAnuGAseGArF/hgJThgLEnLnNwbGl0KCdfJyksXG5cbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+GAmuGAlOGAsS5dIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4YCZ4YCU4YCA4YC64YCW4YC84YCU4YC6XSBMVCBb4YCZ4YC+4YCsXScsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgTFQgW+GAmeGAvuGArF0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1vhgJnhgJThgLEu4YCAXSBMVCBb4YCZ4YC+4YCsXScsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vhgJXhgLzhgK7hgLjhgIHhgLLhgLfhgJ7hgLHhgKxdIGRkZGQgTFQgW+GAmeGAvuGArF0nLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICfhgJzhgKzhgJnhgIrhgLrhgLcgJXMg4YCZ4YC+4YCsJyxcbiAgICAgICAgICAgIHBhc3Q6ICfhgJzhgL3hgJThgLrhgIHhgLLhgLfhgJ7hgLHhgKwgJXMg4YCAJyxcbiAgICAgICAgICAgIHM6ICfhgIXhgIDhgLnhgIDhgJThgLou4YCh4YCU4YCK4YC64YC44YCE4YCa4YC6JyxcbiAgICAgICAgICAgIHNzOiAnJWQg4YCF4YCA4YC54YCA4YCU4YC34YC6JyxcbiAgICAgICAgICAgIG06ICfhgJDhgIXhgLrhgJnhgK3hgJThgIXhgLonLFxuICAgICAgICAgICAgbW06ICclZCDhgJnhgK3hgJThgIXhgLonLFxuICAgICAgICAgICAgaDogJ+GAkOGAheGAuuGAlOGArOGAm+GAricsXG4gICAgICAgICAgICBoaDogJyVkIOGAlOGArOGAm+GAricsXG4gICAgICAgICAgICBkOiAn4YCQ4YCF4YC64YCb4YCA4YC6JyxcbiAgICAgICAgICAgIGRkOiAnJWQg4YCb4YCA4YC6JyxcbiAgICAgICAgICAgIE06ICfhgJDhgIXhgLrhgJwnLFxuICAgICAgICAgICAgTU06ICclZCDhgJwnLFxuICAgICAgICAgICAgeTogJ+GAkOGAheGAuuGAlOGAvuGAheGAuicsXG4gICAgICAgICAgICB5eTogJyVkIOGAlOGAvuGAheGAuicsXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vhgYHhgYLhgYPhgYThgYXhgYbhgYfhgYjhgYnhgYBdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkY1ttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCRkW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ25iJywge1xuICAgICAgICBtb250aHM6ICdqYW51YXJfZmVicnVhcl9tYXJzX2FwcmlsX21haV9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2Rlc2VtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2phbi5fZmViLl9tYXJzX2Fwci5fbWFpX2p1bmlfanVsaV9hdWcuX3NlcC5fb2t0Ll9ub3YuX2Rlcy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnc8O4bmRhZ19tYW5kYWdfdGlyc2RhZ19vbnNkYWdfdG9yc2RhZ19mcmVkYWdfbMO4cmRhZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ3PDuC5fbWEuX3RpLl9vbi5fdG8uX2ZyLl9sw7guJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ3PDuF9tYV90aV9vbl90b19mcl9sw7gnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRC4gTU1NTSBZWVlZIFtrbC5dIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQuIE1NTU0gWVlZWSBba2wuXSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2kgZGFnIGtsLl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tpIG1vcmdlbiBrbC5dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBba2wuXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW2kgZ8OlciBrbC5dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW2ZvcnJpZ2VdIGRkZGQgW2tsLl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdvbSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgc2lkZW4nLFxuICAgICAgICAgICAgczogJ25vZW4gc2VrdW5kZXInLFxuICAgICAgICAgICAgc3M6ICclZCBzZWt1bmRlcicsXG4gICAgICAgICAgICBtOiAnZXR0IG1pbnV0dCcsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0dGVyJyxcbiAgICAgICAgICAgIGg6ICdlbiB0aW1lJyxcbiAgICAgICAgICAgIGhoOiAnJWQgdGltZXInLFxuICAgICAgICAgICAgZDogJ2VuIGRhZycsXG4gICAgICAgICAgICBkZDogJyVkIGRhZ2VyJyxcbiAgICAgICAgICAgIHc6ICdlbiB1a2UnLFxuICAgICAgICAgICAgd3c6ICclZCB1a2VyJyxcbiAgICAgICAgICAgIE06ICdlbiBtw6VuZWQnLFxuICAgICAgICAgICAgTU06ICclZCBtw6VuZWRlcicsXG4gICAgICAgICAgICB5OiAnZXR0IMOlcicsXG4gICAgICAgICAgICB5eTogJyVkIMOlcicsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJGUgPSB7XG4gICAgICAgICAgICAxOiAn4KWnJyxcbiAgICAgICAgICAgIDI6ICfgpagnLFxuICAgICAgICAgICAgMzogJ+ClqScsXG4gICAgICAgICAgICA0OiAn4KWqJyxcbiAgICAgICAgICAgIDU6ICfgpasnLFxuICAgICAgICAgICAgNjogJ+ClrCcsXG4gICAgICAgICAgICA3OiAn4KWtJyxcbiAgICAgICAgICAgIDg6ICfgpa4nLFxuICAgICAgICAgICAgOTogJ+ClrycsXG4gICAgICAgICAgICAwOiAn4KWmJyxcbiAgICAgICAgfSxcbiAgICAgICAgbnVtYmVyTWFwJGQgPSB7XG4gICAgICAgICAgICAn4KWnJzogJzEnLFxuICAgICAgICAgICAgJ+ClqCc6ICcyJyxcbiAgICAgICAgICAgICfgpaknOiAnMycsXG4gICAgICAgICAgICAn4KWqJzogJzQnLFxuICAgICAgICAgICAgJ+Clqyc6ICc1JyxcbiAgICAgICAgICAgICfgpawnOiAnNicsXG4gICAgICAgICAgICAn4KWtJzogJzcnLFxuICAgICAgICAgICAgJ+Clric6ICc4JyxcbiAgICAgICAgICAgICfgpa8nOiAnOScsXG4gICAgICAgICAgICAn4KWmJzogJzAnLFxuICAgICAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCduZScsIHtcbiAgICAgICAgbW9udGhzOiAn4KSc4KSo4KS14KSw4KWAX+Ckq+Clh+CkrOCljeCksOClgeCkteCksOClgF/gpK7gpL7gpLDgpY3gpJpf4KSF4KSq4KWN4KSw4KS/4KSyX+CkruCkiF/gpJzgpYHgpKhf4KSc4KWB4KSy4KS+4KSIX+CkheCkl+Ckt+CljeCkn1/gpLjgpYfgpKrgpY3gpJ/gpYfgpK7gpY3gpKzgpLBf4KSF4KSV4KWN4KSf4KWL4KSs4KSwX+CkqOCli+CkreClh+CkruCljeCkrOCksF/gpKHgpL/gpLjgpYfgpK7gpY3gpKzgpLAnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn4KSc4KSoLl/gpKvgpYfgpKzgpY3gpLDgpYEuX+CkruCkvuCksOCljeCkml/gpIXgpKrgpY3gpLDgpL8uX+CkruCkiF/gpJzgpYHgpKhf4KSc4KWB4KSy4KS+4KSILl/gpIXgpJcuX+CkuOClh+CkquCljeCkny5f4KSF4KSV4KWN4KSf4KWLLl/gpKjgpYvgpK3gpYcuX+CkoeCkv+CkuOClhy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAn4KSG4KSH4KSk4KSs4KS+4KSwX+CkuOCli+CkruCkrOCkvuCksF/gpK7gpJngpY3gpJfgpLLgpKzgpL7gpLBf4KSs4KWB4KSn4KSs4KS+4KSwX+CkrOCkv+CkueCkv+CkrOCkvuCksF/gpLbgpYHgpJXgpY3gpLDgpKzgpL7gpLBf4KS24KSo4KS/4KSs4KS+4KSwJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn4KSG4KSH4KSkLl/gpLjgpYvgpK4uX+CkruCkmeCljeCkl+Cksi5f4KSs4KWB4KSnLl/gpKzgpL/gpLngpL8uX+CktuClgeCkleCljeCksC5f4KS24KSo4KS/Licuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfgpIYuX+CkuOCliy5f4KSu4KSCLl/gpKzgpYEuX+CkrOCkvy5f4KS24KWBLl/gpLYuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0HgpJXgpYsgaDptbSDgpKzgpJzgpYcnLFxuICAgICAgICAgICAgTFRTOiAnQeCkleCliyBoOm1tOnNzIOCkrOCknOClhycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZLCBB4KSV4KWLIGg6bW0g4KSs4KSc4KWHJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQeCkleCliyBoOm1tIOCkrOCknOClhycsXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgpafgpajgpangpargpavgpazgpa3gpa7gpa/gpaZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkZFttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCRlW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4KSw4KS+4KSk4KS/fOCkrOCkv+CkueCkvuCkqHzgpKbgpL/gpIngpIHgpLjgpYt84KS44KS+4KSB4KSdLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSw4KS+4KSk4KS/Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KSs4KS/4KS54KS+4KSoJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkpuCkv+CkieCkgeCkuOCliycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS44KS+4KSB4KSdJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CksOCkvuCkpOCkvyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KSs4KS/4KS54KS+4KSoJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpKbgpL/gpIngpIHgpLjgpYsnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CkuOCkvuCkgeCknSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSk4KS/JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb4KSG4KScXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW+CkreCli+CksuCkv10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdb4KSG4KSJ4KSB4KSm4KWLXSBkZGRkWyxdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4KS54KS/4KSc4KWLXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vgpJfgpI/gpJXgpYtdIGRkZGRbLF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclc+CkruCkvicsXG4gICAgICAgICAgICBwYXN0OiAnJXMg4KSF4KSX4KS+4KSh4KS/JyxcbiAgICAgICAgICAgIHM6ICfgpJXgpYfgpLngpYAg4KSV4KWN4KS34KSjJyxcbiAgICAgICAgICAgIHNzOiAnJWQg4KS44KWH4KSV4KWH4KSj4KWN4KShJyxcbiAgICAgICAgICAgIG06ICfgpI/gpJUg4KSu4KS/4KSo4KWH4KSfJyxcbiAgICAgICAgICAgIG1tOiAnJWQg4KSu4KS/4KSo4KWH4KSfJyxcbiAgICAgICAgICAgIGg6ICfgpI/gpJUg4KSY4KSj4KWN4KSf4KS+JyxcbiAgICAgICAgICAgIGhoOiAnJWQg4KSY4KSj4KWN4KSf4KS+JyxcbiAgICAgICAgICAgIGQ6ICfgpI/gpJUg4KSm4KS/4KSoJyxcbiAgICAgICAgICAgIGRkOiAnJWQg4KSm4KS/4KSoJyxcbiAgICAgICAgICAgIE06ICfgpI/gpJUg4KSu4KS54KS/4KSo4KS+JyxcbiAgICAgICAgICAgIE1NOiAnJWQg4KSu4KS54KS/4KSo4KS+JyxcbiAgICAgICAgICAgIHk6ICfgpI/gpJUg4KSs4KSw4KWN4KS3JyxcbiAgICAgICAgICAgIHl5OiAnJWQg4KSs4KSw4KWN4KS3JyxcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNiwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRoc1Nob3J0V2l0aERvdHMkMSA9ICdqYW4uX2ZlYi5fbXJ0Ll9hcHIuX21laV9qdW4uX2p1bC5fYXVnLl9zZXAuX29rdC5fbm92Ll9kZWMuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydFdpdGhvdXREb3RzJDEgPSAnamFuX2ZlYl9tcnRfYXByX21laV9qdW5fanVsX2F1Z19zZXBfb2t0X25vdl9kZWMnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlJDggPSBbXG4gICAgICAgICAgICAvXmphbi9pLFxuICAgICAgICAgICAgL15mZWIvaSxcbiAgICAgICAgICAgIC9ebWFhcnR8bXJ0Lj8kL2ksXG4gICAgICAgICAgICAvXmFwci9pLFxuICAgICAgICAgICAgL15tZWkkL2ksXG4gICAgICAgICAgICAvXmp1bltpLl0/JC9pLFxuICAgICAgICAgICAgL15qdWxbaS5dPyQvaSxcbiAgICAgICAgICAgIC9eYXVnL2ksXG4gICAgICAgICAgICAvXnNlcC9pLFxuICAgICAgICAgICAgL15va3QvaSxcbiAgICAgICAgICAgIC9ebm92L2ksXG4gICAgICAgICAgICAvXmRlYy9pLFxuICAgICAgICBdLFxuICAgICAgICBtb250aHNSZWdleCQ4ID0gL14oamFudWFyaXxmZWJydWFyaXxtYWFydHxhcHJpbHxtZWl8anVbbmxdaXxhdWd1c3R1c3xzZXB0ZW1iZXJ8b2t0b2Jlcnxub3ZlbWJlcnxkZWNlbWJlcnxqYW5cXC4/fGZlYlxcLj98bXJ0XFwuP3xhcHJcXC4/fGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdubC1iZScsIHtcbiAgICAgICAgbW9udGhzOiAnamFudWFyaV9mZWJydWFyaV9tYWFydF9hcHJpbF9tZWlfanVuaV9qdWxpX2F1Z3VzdHVzX3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHMkMTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRob3V0RG90cyQxW20ubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzJDFbbS5tb250aCgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBtb250aHNSZWdleDogbW9udGhzUmVnZXgkOCxcbiAgICAgICAgbW9udGhzU2hvcnRSZWdleDogbW9udGhzUmVnZXgkOCxcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXIpL2ksXG4gICAgICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKGphblxcLj98ZmViXFwuP3xtcnRcXC4/fGFwclxcLj98bWVpfGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pLFxuXG4gICAgICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQ4LFxuICAgICAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDgsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDgsXG5cbiAgICAgICAgd2Vla2RheXM6ICd6b25kYWdfbWFhbmRhZ19kaW5zZGFnX3dvZW5zZGFnX2RvbmRlcmRhZ192cmlqZGFnX3phdGVyZGFnJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnem8uX21hLl9kaS5fd28uX2RvLl92ci5femEuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ3pvX21hX2RpX3dvX2RvX3ZyX3phJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1t2YW5kYWFnIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiBvbV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtvbV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tnaXN0ZXJlbiBvbV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbYWZnZWxvcGVuXSBkZGRkIFtvbV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdvdmVyICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBnZWxlZGVuJyxcbiAgICAgICAgICAgIHM6ICdlZW4gcGFhciBzZWNvbmRlbicsXG4gICAgICAgICAgICBzczogJyVkIHNlY29uZGVuJyxcbiAgICAgICAgICAgIG06ICfDqcOpbiBtaW51dXQnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGVuJyxcbiAgICAgICAgICAgIGg6ICfDqcOpbiB1dXInLFxuICAgICAgICAgICAgaGg6ICclZCB1dXInLFxuICAgICAgICAgICAgZDogJ8Opw6luIGRhZycsXG4gICAgICAgICAgICBkZDogJyVkIGRhZ2VuJyxcbiAgICAgICAgICAgIE06ICfDqcOpbiBtYWFuZCcsXG4gICAgICAgICAgICBNTTogJyVkIG1hYW5kZW4nLFxuICAgICAgICAgICAgeTogJ8Opw6luIGphYXInLFxuICAgICAgICAgICAgeXk6ICclZCBqYWFyJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIG51bWJlciArXG4gICAgICAgICAgICAgICAgKG51bWJlciA9PT0gMSB8fCBudW1iZXIgPT09IDggfHwgbnVtYmVyID49IDIwID8gJ3N0ZScgOiAnZGUnKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRoc1Nob3J0V2l0aERvdHMkMiA9ICdqYW4uX2ZlYi5fbXJ0Ll9hcHIuX21laV9qdW4uX2p1bC5fYXVnLl9zZXAuX29rdC5fbm92Ll9kZWMuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydFdpdGhvdXREb3RzJDIgPSAnamFuX2ZlYl9tcnRfYXByX21laV9qdW5fanVsX2F1Z19zZXBfb2t0X25vdl9kZWMnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlJDkgPSBbXG4gICAgICAgICAgICAvXmphbi9pLFxuICAgICAgICAgICAgL15mZWIvaSxcbiAgICAgICAgICAgIC9ebWFhcnR8bXJ0Lj8kL2ksXG4gICAgICAgICAgICAvXmFwci9pLFxuICAgICAgICAgICAgL15tZWkkL2ksXG4gICAgICAgICAgICAvXmp1bltpLl0/JC9pLFxuICAgICAgICAgICAgL15qdWxbaS5dPyQvaSxcbiAgICAgICAgICAgIC9eYXVnL2ksXG4gICAgICAgICAgICAvXnNlcC9pLFxuICAgICAgICAgICAgL15va3QvaSxcbiAgICAgICAgICAgIC9ebm92L2ksXG4gICAgICAgICAgICAvXmRlYy9pLFxuICAgICAgICBdLFxuICAgICAgICBtb250aHNSZWdleCQ5ID0gL14oamFudWFyaXxmZWJydWFyaXxtYWFydHxhcHJpbHxtZWl8anVbbmxdaXxhdWd1c3R1c3xzZXB0ZW1iZXJ8b2t0b2Jlcnxub3ZlbWJlcnxkZWNlbWJlcnxqYW5cXC4/fGZlYlxcLj98bXJ0XFwuP3xhcHJcXC4/fGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdubCcsIHtcbiAgICAgICAgbW9udGhzOiAnamFudWFyaV9mZWJydWFyaV9tYWFydF9hcHJpbF9tZWlfanVuaV9qdWxpX2F1Z3VzdHVzX3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHMkMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRob3V0RG90cyQyW20ubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzJDJbbS5tb250aCgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBtb250aHNSZWdleDogbW9udGhzUmVnZXgkOSxcbiAgICAgICAgbW9udGhzU2hvcnRSZWdleDogbW9udGhzUmVnZXgkOSxcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXIpL2ksXG4gICAgICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKGphblxcLj98ZmViXFwuP3xtcnRcXC4/fGFwclxcLj98bWVpfGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pLFxuXG4gICAgICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQ5LFxuICAgICAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDksXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDksXG5cbiAgICAgICAgd2Vla2RheXM6ICd6b25kYWdfbWFhbmRhZ19kaW5zZGFnX3dvZW5zZGFnX2RvbmRlcmRhZ192cmlqZGFnX3phdGVyZGFnJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnem8uX21hLl9kaS5fd28uX2RvLl92ci5femEuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ3pvX21hX2RpX3dvX2RvX3ZyX3phJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC1NTS1ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1t2YW5kYWFnIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiBvbV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtvbV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tnaXN0ZXJlbiBvbV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbYWZnZWxvcGVuXSBkZGRkIFtvbV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdvdmVyICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBnZWxlZGVuJyxcbiAgICAgICAgICAgIHM6ICdlZW4gcGFhciBzZWNvbmRlbicsXG4gICAgICAgICAgICBzczogJyVkIHNlY29uZGVuJyxcbiAgICAgICAgICAgIG06ICfDqcOpbiBtaW51dXQnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dGVuJyxcbiAgICAgICAgICAgIGg6ICfDqcOpbiB1dXInLFxuICAgICAgICAgICAgaGg6ICclZCB1dXInLFxuICAgICAgICAgICAgZDogJ8Opw6luIGRhZycsXG4gICAgICAgICAgICBkZDogJyVkIGRhZ2VuJyxcbiAgICAgICAgICAgIHc6ICfDqcOpbiB3ZWVrJyxcbiAgICAgICAgICAgIHd3OiAnJWQgd2VrZW4nLFxuICAgICAgICAgICAgTTogJ8Opw6luIG1hYW5kJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWFhbmRlbicsXG4gICAgICAgICAgICB5OiAnw6nDqW4gamFhcicsXG4gICAgICAgICAgICB5eTogJyVkIGphYXInLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3RlfGRlKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgbnVtYmVyICtcbiAgICAgICAgICAgICAgICAobnVtYmVyID09PSAxIHx8IG51bWJlciA9PT0gOCB8fCBudW1iZXIgPj0gMjAgPyAnc3RlJyA6ICdkZScpXG4gICAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ25uJywge1xuICAgICAgICBtb250aHM6ICdqYW51YXJfZmVicnVhcl9tYXJzX2FwcmlsX21haV9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2Rlc2VtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2phbi5fZmViLl9tYXJzX2Fwci5fbWFpX2p1bmlfanVsaV9hdWcuX3NlcC5fb2t0Ll9ub3YuX2Rlcy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnc3VuZGFnX23DpW5kYWdfdHlzZGFnX29uc2RhZ190b3JzZGFnX2ZyZWRhZ19sYXVyZGFnJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnc3UuX23DpS5fdHkuX29uLl90by5fZnIuX2xhdS4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnc3VfbcOlX3R5X29uX3RvX2ZyX2xhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWSBba2wuXSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQuIE1NTU0gWVlZWSBba2wuXSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0kgZGFnIGtsb2trYV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tJIG1vcmdvbiBrbG9ra2FdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBba2xva2thXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0kgZ8OlciBrbG9ra2FdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW0bDuHJlZ8OlYW5kZV0gZGRkZCBba2xva2thXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ29tICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBzaWRhbicsXG4gICAgICAgICAgICBzOiAnbm9rcmUgc2VrdW5kJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2VrdW5kJyxcbiAgICAgICAgICAgIG06ICdlaXQgbWludXR0JyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXR0JyxcbiAgICAgICAgICAgIGg6ICdlaW4gdGltZScsXG4gICAgICAgICAgICBoaDogJyVkIHRpbWFyJyxcbiAgICAgICAgICAgIGQ6ICdlaW4gZGFnJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGFnYXInLFxuICAgICAgICAgICAgdzogJ2VpIHZla2UnLFxuICAgICAgICAgICAgd3c6ICclZCB2ZWtlcicsXG4gICAgICAgICAgICBNOiAnZWluIG3DpW5hZCcsXG4gICAgICAgICAgICBNTTogJyVkIG3DpW5hZGVyJyxcbiAgICAgICAgICAgIHk6ICdlaXQgw6VyJyxcbiAgICAgICAgICAgIHl5OiAnJWQgw6VyJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbDogJyVkLicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnb2MtbG5jJywge1xuICAgICAgICBtb250aHM6IHtcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICdnZW5pw6hyX2ZlYnJpw6hyX21hcsOnX2FicmlsX21haV9qdW5oX2p1bGhldF9hZ29zdF9zZXRlbWJyZV9vY3TDsmJyZV9ub3ZlbWJyZV9kZWNlbWJyZScuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZm9ybWF0OiBcImRlIGdlbmnDqHJfZGUgZmVicmnDqHJfZGUgbWFyw6dfZCdhYnJpbF9kZSBtYWlfZGUganVuaF9kZSBqdWxoZXRfZCdhZ29zdF9kZSBzZXRlbWJyZV9kJ29jdMOyYnJlX2RlIG5vdmVtYnJlX2RlIGRlY2VtYnJlXCIuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IC9EW29EXT8oXFxzKStNTU1NLyxcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdnZW4uX2ZlYnIuX21hcsOnX2Fici5fbWFpX2p1bmhfanVsaC5fYWdvLl9zZXQuX29jdC5fbm92Ll9kZWMuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ2RpbWVuZ2VfZGlsdW5zX2RpbWFyc19kaW3DqGNyZXNfZGlqw7J1c19kaXZlbmRyZXNfZGlzc2FidGUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdkZy5fZGwuX2RtLl9kYy5fZGouX2R2Ll9kcy4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnZGdfZGxfZG1fZGNfZGpfZHZfZHMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgICAgICBsbDogJ0QgTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFtkZV0gWVlZWSBbYV0gSDptbScsXG4gICAgICAgICAgICBsbGw6ICdEIE1NTSBZWVlZLCBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBbZGVdIFlZWVkgW2FdIEg6bW0nLFxuICAgICAgICAgICAgbGxsbDogJ2RkZCBEIE1NTSBZWVlZLCBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbdcOoaSBhXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW2RlbWFuIGFdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tpw6hyIGFdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbcGFzc2F0IGFdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiBcImQnYXF1w60gJXNcIixcbiAgICAgICAgICAgIHBhc3Q6ICdmYSAlcycsXG4gICAgICAgICAgICBzOiAndW5hcyBzZWdvbmRhcycsXG4gICAgICAgICAgICBzczogJyVkIHNlZ29uZGFzJyxcbiAgICAgICAgICAgIG06ICd1bmEgbWludXRhJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRhcycsXG4gICAgICAgICAgICBoOiAndW5hIG9yYScsXG4gICAgICAgICAgICBoaDogJyVkIG9yYXMnLFxuICAgICAgICAgICAgZDogJ3VuIGpvcm4nLFxuICAgICAgICAgICAgZGQ6ICclZCBqb3JucycsXG4gICAgICAgICAgICBNOiAndW4gbWVzJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWVzZXMnLFxuICAgICAgICAgICAgeTogJ3VuIGFuJyxcbiAgICAgICAgICAgIHl5OiAnJWQgYW5zJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHJ8bnx0fMOofGEpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICB2YXIgb3V0cHV0ID1cbiAgICAgICAgICAgICAgICBudW1iZXIgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgPyAncidcbiAgICAgICAgICAgICAgICAgICAgOiBudW1iZXIgPT09IDJcbiAgICAgICAgICAgICAgICAgICAgPyAnbidcbiAgICAgICAgICAgICAgICAgICAgOiBudW1iZXIgPT09IDNcbiAgICAgICAgICAgICAgICAgICAgPyAncidcbiAgICAgICAgICAgICAgICAgICAgOiBudW1iZXIgPT09IDRcbiAgICAgICAgICAgICAgICAgICAgPyAndCdcbiAgICAgICAgICAgICAgICAgICAgOiAnw6gnO1xuICAgICAgICAgICAgaWYgKHBlcmlvZCA9PT0gJ3cnIHx8IHBlcmlvZCA9PT0gJ1cnKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gJ2EnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCxcbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkZiA9IHtcbiAgICAgICAgICAgIDE6ICfgqacnLFxuICAgICAgICAgICAgMjogJ+CpqCcsXG4gICAgICAgICAgICAzOiAn4KmpJyxcbiAgICAgICAgICAgIDQ6ICfgqaonLFxuICAgICAgICAgICAgNTogJ+CpqycsXG4gICAgICAgICAgICA2OiAn4KmsJyxcbiAgICAgICAgICAgIDc6ICfgqa0nLFxuICAgICAgICAgICAgODogJ+CpricsXG4gICAgICAgICAgICA5OiAn4KmvJyxcbiAgICAgICAgICAgIDA6ICfgqaYnLFxuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAkZSA9IHtcbiAgICAgICAgICAgICfgqacnOiAnMScsXG4gICAgICAgICAgICAn4KmoJzogJzInLFxuICAgICAgICAgICAgJ+CpqSc6ICczJyxcbiAgICAgICAgICAgICfgqaonOiAnNCcsXG4gICAgICAgICAgICAn4KmrJzogJzUnLFxuICAgICAgICAgICAgJ+CprCc6ICc2JyxcbiAgICAgICAgICAgICfgqa0nOiAnNycsXG4gICAgICAgICAgICAn4KmuJzogJzgnLFxuICAgICAgICAgICAgJ+Cpryc6ICc5JyxcbiAgICAgICAgICAgICfgqaYnOiAnMCcsXG4gICAgICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3BhLWluJywge1xuICAgICAgICAvLyBUaGVyZSBhcmUgbW9udGhzIG5hbWUgYXMgcGVyIE5hbmFrc2hhaGkgQ2FsZW5kYXIgYnV0IHRoZXkgYXJlIG5vdCB1c2VkIGFzIHJpZ2lkbHkgaW4gbW9kZXJuIFB1bmphYmkuXG4gICAgICAgIG1vbnRoczogJ+ConOCoqOCoteCosOCpgF/gqKvgqLzgqLDgqLXgqLDgqYBf4Kiu4Ki+4Kiw4KiaX+CoheCoquCpjeCosOCpiOCosl/gqK7gqIhf4Kic4KmC4KioX+ConOCpgeCosuCovuCoiF/gqIXgqJfgqLjgqKRf4Ki44Kik4Kmw4Kis4KiwX+CoheColeCopOCpguCorOCosF/gqKjgqLXgqbDgqKzgqLBf4Kim4Ki44Kmw4Kis4KiwJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ+ConOCoqOCoteCosOCpgF/gqKvgqLzgqLDgqLXgqLDgqYBf4Kiu4Ki+4Kiw4KiaX+CoheCoquCpjeCosOCpiOCosl/gqK7gqIhf4Kic4KmC4KioX+ConOCpgeCosuCovuCoiF/gqIXgqJfgqLjgqKRf4Ki44Kik4Kmw4Kis4KiwX+CoheColeCopOCpguCorOCosF/gqKjgqLXgqbDgqKzgqLBf4Kim4Ki44Kmw4Kis4KiwJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ+CokOCopOCoteCovuCosF/gqLjgqYvgqK7gqLXgqL7gqLBf4Kiu4Kmw4KiX4Kiy4Ki14Ki+4KiwX+CorOCpgeCop+CoteCovuCosF/gqLXgqYDgqLDgqLXgqL7gqLBf4Ki44Ki84KmB4Kmx4KiV4Kiw4Ki14Ki+4KiwX+CouOCovOCoqOCpgOComuCosOCoteCovuCosCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+CokOCopF/gqLjgqYvgqK5f4Kiu4Kmw4KiX4KiyX+CorOCpgeCop1/gqLXgqYDgqLBf4Ki44Ki84KmB4KiV4KiwX+CouOCovOCoqOCpgCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfgqJDgqKRf4Ki44KmL4KiuX+CoruCpsOCol+Cosl/gqKzgqYHgqKdf4Ki14KmA4KiwX+CouOCovOCpgeColeCosF/gqLjgqLzgqKjgqYAnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0EgaDptbSDgqLXgqJzgqYcnLFxuICAgICAgICAgICAgTFRTOiAnQSBoOm1tOnNzIOCoteConOCphycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0g4Ki14Kic4KmHJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tIOCoteConOCphycsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+CoheConF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vgqJXgqLJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW+CoheCol+CosuCovl0gZGRkZCwgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vgqJXgqLJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+CoquCov+Com+CosuCph10gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclcyDgqLXgqL/gqbHgqJonLFxuICAgICAgICAgICAgcGFzdDogJyVzIOCoquCov+Com+CosuCphycsXG4gICAgICAgICAgICBzOiAn4KiV4KmB4KidIOCouOColeCov+CpsOConycsXG4gICAgICAgICAgICBzczogJyVkIOCouOColeCov+CpsOConycsXG4gICAgICAgICAgICBtOiAn4KiH4KiVIOCoruCov+CpsOConycsXG4gICAgICAgICAgICBtbTogJyVkIOCoruCov+CpsOConycsXG4gICAgICAgICAgICBoOiAn4KiH4Kmx4KiVIOComOCpsOCon+CovicsXG4gICAgICAgICAgICBoaDogJyVkIOComOCpsOCon+CphycsXG4gICAgICAgICAgICBkOiAn4KiH4Kmx4KiVIOCopuCov+CoqCcsXG4gICAgICAgICAgICBkZDogJyVkIOCopuCov+CoqCcsXG4gICAgICAgICAgICBNOiAn4KiH4Kmx4KiVIOCoruCoueCpgOCoqOCovicsXG4gICAgICAgICAgICBNTTogJyVkIOCoruCoueCpgOCoqOCphycsXG4gICAgICAgICAgICB5OiAn4KiH4Kmx4KiVIOCouOCovuCosicsXG4gICAgICAgICAgICB5eTogJyVkIOCouOCovuCosicsXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgqafgqajgqangqargqavgqazgqa3gqa7gqa/gqaZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkZVttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCRmW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICAvLyBQdW5qYWJpIG5vdGF0aW9uIGZvciBtZXJpZGllbXMgYXJlIHF1aXRlIGZ1enp5IGluIHByYWN0aWNlLiBXaGlsZSB0aGVyZSBleGlzdHNcbiAgICAgICAgLy8gYSByaWdpZCBub3Rpb24gb2YgYSAnUGFoYXInIGl0IGlzIG5vdCB1c2VkIGFzIHJpZ2lkbHkgaW4gbW9kZXJuIFB1bmphYmkuXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gqLDgqL7gqKR84Ki44Ki14KmH4KiwfOCopuCpgeCoquCoueCov+CosHzgqLjgqLzgqL7gqK4vLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgqLDgqL7gqKQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqLjgqLXgqYfgqLAnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Kim4KmB4Kiq4Ki54Ki/4KiwJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqLjgqLzgqL7gqK4nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kiw4Ki+4KikJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgqLjgqLXgqYfgqLAnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CopuCpgeCoquCoueCov+CosCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Ki44Ki84Ki+4KiuJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgqLDgqL7gqKQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA2LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA2dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzTm9taW5hdGl2ZSA9ICdzdHljemXFhF9sdXR5X21hcnplY19rd2llY2llxYRfbWFqX2N6ZXJ3aWVjX2xpcGllY19zaWVycGllxYRfd3J6ZXNpZcWEX3Bhxbpkemllcm5pa19saXN0b3BhZF9ncnVkemllxYQnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1N1YmplY3RpdmUgPSAnc3R5Y3puaWFfbHV0ZWdvX21hcmNhX2t3aWV0bmlhX21hamFfY3plcndjYV9saXBjYV9zaWVycG5pYV93cnplxZtuaWFfcGHFumR6aWVybmlrYV9saXN0b3BhZGFfZ3J1ZG5pYScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzUGFyc2UkYSA9IFtcbiAgICAgICAgICAgIC9ec3R5L2ksXG4gICAgICAgICAgICAvXmx1dC9pLFxuICAgICAgICAgICAgL15tYXIvaSxcbiAgICAgICAgICAgIC9ea3dpL2ksXG4gICAgICAgICAgICAvXm1hai9pLFxuICAgICAgICAgICAgL15jemUvaSxcbiAgICAgICAgICAgIC9ebGlwL2ksXG4gICAgICAgICAgICAvXnNpZS9pLFxuICAgICAgICAgICAgL153cnovaSxcbiAgICAgICAgICAgIC9ecGHFui9pLFxuICAgICAgICAgICAgL15saXMvaSxcbiAgICAgICAgICAgIC9eZ3J1L2ksXG4gICAgICAgIF07XG4gICAgZnVuY3Rpb24gcGx1cmFsJDMobikge1xuICAgICAgICByZXR1cm4gbiAlIDEwIDwgNSAmJiBuICUgMTAgPiAxICYmIH5+KG4gLyAxMCkgJSAxMCAhPT0gMTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlJDgobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQzKG51bWJlcikgPyAnc2VrdW5keScgOiAnc2VrdW5kJyk7XG4gICAgICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdtaW51dGEnIDogJ21pbnV0xJknO1xuICAgICAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDMobnVtYmVyKSA/ICdtaW51dHknIDogJ21pbnV0Jyk7XG4gICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdnb2R6aW5hJyA6ICdnb2R6aW7EmSc7XG4gICAgICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMyhudW1iZXIpID8gJ2dvZHppbnknIDogJ2dvZHppbicpO1xuICAgICAgICAgICAgY2FzZSAnd3cnOlxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDMobnVtYmVyKSA/ICd0eWdvZG5pZScgOiAndHlnb2RuaScpO1xuICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDMobnVtYmVyKSA/ICdtaWVzacSFY2UnIDogJ21pZXNpxJljeScpO1xuICAgICAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDMobnVtYmVyKSA/ICdsYXRhJyA6ICdsYXQnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgncGwnLCB7XG4gICAgICAgIG1vbnRoczogZnVuY3Rpb24gKG1vbWVudFRvRm9ybWF0LCBmb3JtYXQpIHtcbiAgICAgICAgICAgIGlmICghbW9tZW50VG9Gb3JtYXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzTm9taW5hdGl2ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoL0QgTU1NTS8udGVzdChmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1N1YmplY3RpdmVbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNOb21pbmF0aXZlW21vbWVudFRvRm9ybWF0Lm1vbnRoKCldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydDogJ3N0eV9sdXRfbWFyX2t3aV9tYWpfY3plX2xpcF9zaWVfd3J6X3BhxbpfbGlzX2dydScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJGEsXG4gICAgICAgIGxvbmdNb250aHNQYXJzZTogbW9udGhzUGFyc2UkYSxcbiAgICAgICAgc2hvcnRNb250aHNQYXJzZTogbW9udGhzUGFyc2UkYSxcbiAgICAgICAgd2Vla2RheXM6ICduaWVkemllbGFfcG9uaWVkemlhxYJla193dG9yZWtfxZtyb2RhX2N6d2FydGVrX3BpxIV0ZWtfc29ib3RhJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnbmR6X3Bvbl93dF/Fm3JfY3p3X3B0X3NvYicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdOZF9Qbl9XdF/FmnJfQ3pfUHRfU28nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbRHppxZsgb10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tKdXRybyBvXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIG5pZWR6aWVsxJkgb10gTFQnO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1dlIHd0b3JlayBvXSBMVCc7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbVyDFm3JvZMSZIG9dIExUJztcblxuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIHNvYm90xJkgb10gTFQnO1xuXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXXSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbV2N6b3JhaiBvXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIHplc3rFgsSFIG5pZWR6aWVsxJkgb10gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIHplc3rFgsSFIMWbcm9kxJkgb10gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIHplc3rFgsSFIHNvYm90xJkgb10gTFQnO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbVyB6ZXN6xYJ5XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnemEgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIHRlbXUnLFxuICAgICAgICAgICAgczogJ2tpbGthIHNla3VuZCcsXG4gICAgICAgICAgICBzczogdHJhbnNsYXRlJDgsXG4gICAgICAgICAgICBtOiB0cmFuc2xhdGUkOCxcbiAgICAgICAgICAgIG1tOiB0cmFuc2xhdGUkOCxcbiAgICAgICAgICAgIGg6IHRyYW5zbGF0ZSQ4LFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0ZSQ4LFxuICAgICAgICAgICAgZDogJzEgZHppZcWEJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZG5pJyxcbiAgICAgICAgICAgIHc6ICd0eWR6aWXFhCcsXG4gICAgICAgICAgICB3dzogdHJhbnNsYXRlJDgsXG4gICAgICAgICAgICBNOiAnbWllc2nEhWMnLFxuICAgICAgICAgICAgTU06IHRyYW5zbGF0ZSQ4LFxuICAgICAgICAgICAgeTogJ3JvaycsXG4gICAgICAgICAgICB5eTogdHJhbnNsYXRlJDgsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3B0LWJyJywge1xuICAgICAgICBtb250aHM6ICdqYW5laXJvX2ZldmVyZWlyb19tYXLDp29fYWJyaWxfbWFpb19qdW5ob19qdWxob19hZ29zdG9fc2V0ZW1icm9fb3V0dWJyb19ub3ZlbWJyb19kZXplbWJybycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdqYW5fZmV2X21hcl9hYnJfbWFpX2p1bl9qdWxfYWdvX3NldF9vdXRfbm92X2Rleicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdkb21pbmdvX3NlZ3VuZGEtZmVpcmFfdGVyw6dhLWZlaXJhX3F1YXJ0YS1mZWlyYV9xdWludGEtZmVpcmFfc2V4dGEtZmVpcmFfc8OhYmFkbycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ2RvbV9zZWdfdGVyX3F1YV9xdWlfc2V4X3PDoWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnZG9fMsKqXzPCql80wqpfNcKqXzbCql9zw6EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZIFvDoHNdIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIFtkZV0gTU1NTSBbZGVdIFlZWVkgW8Ogc10gSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tIb2plIMOgc10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tBbWFuaMOjIMOgc10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvDoHNdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbT250ZW0gw6BzXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRheSgpID09PSAwIHx8IHRoaXMuZGF5KCkgPT09IDZcbiAgICAgICAgICAgICAgICAgICAgPyAnW8OabHRpbW9dIGRkZGQgW8Ogc10gTFQnIC8vIFNhdHVyZGF5ICsgU3VuZGF5XG4gICAgICAgICAgICAgICAgICAgIDogJ1vDmmx0aW1hXSBkZGRkIFvDoHNdIExUJzsgLy8gTW9uZGF5IC0gRnJpZGF5XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdlbSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnaMOhICVzJyxcbiAgICAgICAgICAgIHM6ICdwb3Vjb3Mgc2VndW5kb3MnLFxuICAgICAgICAgICAgc3M6ICclZCBzZWd1bmRvcycsXG4gICAgICAgICAgICBtOiAndW0gbWludXRvJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRvcycsXG4gICAgICAgICAgICBoOiAndW1hIGhvcmEnLFxuICAgICAgICAgICAgaGg6ICclZCBob3JhcycsXG4gICAgICAgICAgICBkOiAndW0gZGlhJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGlhcycsXG4gICAgICAgICAgICBNOiAndW0gbcOqcycsXG4gICAgICAgICAgICBNTTogJyVkIG1lc2VzJyxcbiAgICAgICAgICAgIHk6ICd1bSBhbm8nLFxuICAgICAgICAgICAgeXk6ICclZCBhbm9zJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9wrovLFxuICAgICAgICBvcmRpbmFsOiAnJWTCuicsXG4gICAgICAgIGludmFsaWREYXRlOiAnRGF0YSBpbnbDoWxpZGEnLFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdwdCcsIHtcbiAgICAgICAgbW9udGhzOiAnamFuZWlyb19mZXZlcmVpcm9fbWFyw6dvX2FicmlsX21haW9fanVuaG9fanVsaG9fYWdvc3RvX3NldGVtYnJvX291dHVicm9fbm92ZW1icm9fZGV6ZW1icm8nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnamFuX2Zldl9tYXJfYWJyX21haV9qdW5fanVsX2Fnb19zZXRfb3V0X25vdl9kZXonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnRG9taW5nb19TZWd1bmRhLWZlaXJhX1RlcsOnYS1mZWlyYV9RdWFydGEtZmVpcmFfUXVpbnRhLWZlaXJhX1NleHRhLWZlaXJhX1PDoWJhZG8nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdEb21fU2VnX1Rlcl9RdWFfUXVpX1NleF9Tw6FiJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ0RvXzLCql8zwqpfNMKqXzXCql82wqpfU8OhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSG9qZSDDoHNdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbQW1hbmjDoyDDoHNdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbw6BzXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW09udGVtIMOgc10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kYXkoKSA9PT0gMCB8fCB0aGlzLmRheSgpID09PSA2XG4gICAgICAgICAgICAgICAgICAgID8gJ1vDmmx0aW1vXSBkZGRkIFvDoHNdIExUJyAvLyBTYXR1cmRheSArIFN1bmRheVxuICAgICAgICAgICAgICAgICAgICA6ICdbw5psdGltYV0gZGRkZCBbw6BzXSBMVCc7IC8vIE1vbmRheSAtIEZyaWRheVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnZW0gJXMnLFxuICAgICAgICAgICAgcGFzdDogJ2jDoSAlcycsXG4gICAgICAgICAgICBzOiAnc2VndW5kb3MnLFxuICAgICAgICAgICAgc3M6ICclZCBzZWd1bmRvcycsXG4gICAgICAgICAgICBtOiAndW0gbWludXRvJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXRvcycsXG4gICAgICAgICAgICBoOiAndW1hIGhvcmEnLFxuICAgICAgICAgICAgaGg6ICclZCBob3JhcycsXG4gICAgICAgICAgICBkOiAndW0gZGlhJyxcbiAgICAgICAgICAgIGRkOiAnJWQgZGlhcycsXG4gICAgICAgICAgICB3OiAndW1hIHNlbWFuYScsXG4gICAgICAgICAgICB3dzogJyVkIHNlbWFuYXMnLFxuICAgICAgICAgICAgTTogJ3VtIG3DqnMnLFxuICAgICAgICAgICAgTU06ICclZCBtZXNlcycsXG4gICAgICAgICAgICB5OiAndW0gYW5vJyxcbiAgICAgICAgICAgIHl5OiAnJWQgYW5vcycsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbDogJyVkwronLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgICAgICAgICBzczogJ3NlY3VuZGUnLFxuICAgICAgICAgICAgICAgIG1tOiAnbWludXRlJyxcbiAgICAgICAgICAgICAgICBoaDogJ29yZScsXG4gICAgICAgICAgICAgICAgZGQ6ICd6aWxlJyxcbiAgICAgICAgICAgICAgICB3dzogJ3PEg3B0xINtw6JuaScsXG4gICAgICAgICAgICAgICAgTU06ICdsdW5pJyxcbiAgICAgICAgICAgICAgICB5eTogJ2FuaScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2VwYXJhdG9yID0gJyAnO1xuICAgICAgICBpZiAobnVtYmVyICUgMTAwID49IDIwIHx8IChudW1iZXIgPj0gMTAwICYmIG51bWJlciAlIDEwMCA9PT0gMCkpIHtcbiAgICAgICAgICAgIHNlcGFyYXRvciA9ICcgZGUgJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVtYmVyICsgc2VwYXJhdG9yICsgZm9ybWF0W2tleV07XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdybycsIHtcbiAgICAgICAgbW9udGhzOiAnaWFudWFyaWVfZmVicnVhcmllX21hcnRpZV9hcHJpbGllX21haV9pdW5pZV9pdWxpZV9hdWd1c3Rfc2VwdGVtYnJpZV9vY3RvbWJyaWVfbm9pZW1icmllX2RlY2VtYnJpZScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdpYW4uX2ZlYi5fbWFydC5fYXByLl9tYWlfaXVuLl9pdWwuX2F1Zy5fc2VwdC5fb2N0Ll9ub3YuX2RlYy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnZHVtaW5pY8SDX2x1bmlfbWFyyJtpX21pZXJjdXJpX2pvaV92aW5lcmlfc8OibWLEg3TEgycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ0R1bV9MdW5fTWFyX01pZV9Kb2lfVmluX1PDom0nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnRHVfTHVfTWFfTWlfSm9fVmlfU8OiJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbYXppIGxhXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW23DomluZSBsYV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtsYV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tpZXJpIGxhXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tmb3N0YV0gZGRkZCBbbGFdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAncGVzdGUgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIMOubiB1cm3EgycsXG4gICAgICAgICAgICBzOiAnY8OidGV2YSBzZWN1bmRlJyxcbiAgICAgICAgICAgIHNzOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIsXG4gICAgICAgICAgICBtOiAndW4gbWludXQnLFxuICAgICAgICAgICAgbW06IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMixcbiAgICAgICAgICAgIGg6ICdvIG9yxIMnLFxuICAgICAgICAgICAgaGg6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMixcbiAgICAgICAgICAgIGQ6ICdvIHppJyxcbiAgICAgICAgICAgIGRkOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIsXG4gICAgICAgICAgICB3OiAnbyBzxINwdMSDbcOibsSDJyxcbiAgICAgICAgICAgIHd3OiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIsXG4gICAgICAgICAgICBNOiAnbyBsdW7EgycsXG4gICAgICAgICAgICBNTTogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQyLFxuICAgICAgICAgICAgeTogJ3VuIGFuJyxcbiAgICAgICAgICAgIHl5OiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIsXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIHBsdXJhbCQ0KHdvcmQsIG51bSkge1xuICAgICAgICB2YXIgZm9ybXMgPSB3b3JkLnNwbGl0KCdfJyk7XG4gICAgICAgIHJldHVybiBudW0gJSAxMCA9PT0gMSAmJiBudW0gJSAxMDAgIT09IDExXG4gICAgICAgICAgICA/IGZvcm1zWzBdXG4gICAgICAgICAgICA6IG51bSAlIDEwID49IDIgJiYgbnVtICUgMTAgPD0gNCAmJiAobnVtICUgMTAwIDwgMTAgfHwgbnVtICUgMTAwID49IDIwKVxuICAgICAgICAgICAgPyBmb3Jtc1sxXVxuICAgICAgICAgICAgOiBmb3Jtc1syXTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICBzczogd2l0aG91dFN1ZmZpeCA/ICfRgdC10LrRg9C90LTQsF/RgdC10LrRg9C90LTRi1/RgdC10LrRg9C90LQnIDogJ9GB0LXQutGD0L3QtNGDX9GB0LXQutGD0L3QtNGLX9GB0LXQutGD0L3QtCcsXG4gICAgICAgICAgICBtbTogd2l0aG91dFN1ZmZpeCA/ICfQvNC40L3Rg9GC0LBf0LzQuNC90YPRgtGLX9C80LjQvdGD0YInIDogJ9C80LjQvdGD0YLRg1/QvNC40L3Rg9GC0Ytf0LzQuNC90YPRgicsXG4gICAgICAgICAgICBoaDogJ9GH0LDRgV/Rh9Cw0YHQsF/Rh9Cw0YHQvtCyJyxcbiAgICAgICAgICAgIGRkOiAn0LTQtdC90Yxf0LTQvdGPX9C00L3QtdC5JyxcbiAgICAgICAgICAgIHd3OiAn0L3QtdC00LXQu9GPX9C90LXQtNC10LvQuF/QvdC10LTQtdC70YwnLFxuICAgICAgICAgICAgTU06ICfQvNC10YHRj9GGX9C80LXRgdGP0YbQsF/QvNC10YHRj9GG0LXQsicsXG4gICAgICAgICAgICB5eTogJ9Cz0L7QtF/Qs9C+0LTQsF/Qu9C10YInLFxuICAgICAgICB9O1xuICAgICAgICBpZiAoa2V5ID09PSAnbScpIHtcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9C80LjQvdGD0YLQsCcgOiAn0LzQuNC90YPRgtGDJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnICcgKyBwbHVyYWwkNChmb3JtYXRba2V5XSwgK251bWJlcik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdmFyIG1vbnRoc1BhcnNlJGIgPSBbXG4gICAgICAgIC9e0Y/QvdCyL2ksXG4gICAgICAgIC9e0YTQtdCyL2ksXG4gICAgICAgIC9e0LzQsNGAL2ksXG4gICAgICAgIC9e0LDQv9GAL2ksXG4gICAgICAgIC9e0LzQsFvQudGPXS9pLFxuICAgICAgICAvXtC40Y7QvS9pLFxuICAgICAgICAvXtC40Y7Quy9pLFxuICAgICAgICAvXtCw0LLQsy9pLFxuICAgICAgICAvXtGB0LXQvS9pLFxuICAgICAgICAvXtC+0LrRgi9pLFxuICAgICAgICAvXtC90L7Rjy9pLFxuICAgICAgICAvXtC00LXQui9pLFxuICAgIF07XG5cbiAgICAvLyBodHRwOi8vbmV3LmdyYW1vdGEucnUvc3ByYXZrYS9ydWxlcy8xMzktcHJvcCA6IMKnIDEwM1xuICAgIC8vINCh0L7QutGA0LDRidC10L3QuNGPINC80LXRgdGP0YbQtdCyOiBodHRwOi8vbmV3LmdyYW1vdGEucnUvc3ByYXZrYS9idXJvL3NlYXJjaC1hbnN3ZXI/cz0yNDI2MzdcbiAgICAvLyBDTERSIGRhdGE6ICAgICAgICAgIGh0dHA6Ly93d3cudW5pY29kZS5vcmcvY2xkci9jaGFydHMvMjgvc3VtbWFyeS9ydS5odG1sIzE3NTNcbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3J1Jywge1xuICAgICAgICBtb250aHM6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ9GP0L3QstCw0YDRj1/RhNC10LLRgNCw0LvRj1/QvNCw0YDRgtCwX9Cw0L/RgNC10LvRj1/QvNCw0Y9f0LjRjtC90Y9f0LjRjtC70Y9f0LDQstCz0YPRgdGC0LBf0YHQtdC90YLRj9Cx0YDRj1/QvtC60YLRj9Cx0YDRj1/QvdC+0Y/QsdGA0Y9f0LTQtdC60LDQsdGA0Y8nLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICfRj9C90LLQsNGA0Yxf0YTQtdCy0YDQsNC70Yxf0LzQsNGA0YJf0LDQv9GA0LXQu9GMX9C80LDQuV/QuNGO0L3RjF/QuNGO0LvRjF/QsNCy0LPRg9GB0YJf0YHQtdC90YLRj9Cx0YDRjF/QvtC60YLRj9Cx0YDRjF/QvdC+0Y/QsdGA0Yxf0LTQtdC60LDQsdGA0YwnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQ6IHtcbiAgICAgICAgICAgIC8vINC/0L4gQ0xEUiDQuNC80LXQvdC90L4gXCLQuNGO0LsuXCIg0LggXCLQuNGO0L0uXCIsINC90L4g0LrQsNC60L7QuSDRgdC80YvRgdC7INC80LXQvdGP0YLRjCDQsdGD0LrQstGDINC90LAg0YLQvtGH0LrRgz9cbiAgICAgICAgICAgIGZvcm1hdDogJ9GP0L3Qsi5f0YTQtdCy0YAuX9C80LDRgC5f0LDQv9GALl/QvNCw0Y9f0LjRjtC90Y9f0LjRjtC70Y9f0LDQstCzLl/RgdC10L3Rgi5f0L7QutGCLl/QvdC+0Y/QsS5f0LTQtdC6Licuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ9GP0L3Qsi5f0YTQtdCy0YAuX9C80LDRgNGCX9Cw0L/RgC5f0LzQsNC5X9C40Y7QvdGMX9C40Y7Qu9GMX9Cw0LLQsy5f0YHQtdC90YIuX9C+0LrRgi5f0L3QvtGP0LEuX9C00LXQui4nLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgd2Vla2RheXM6IHtcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICfQstC+0YHQutGA0LXRgdC10L3RjNC1X9C/0L7QvdC10LTQtdC70YzQvdC40Lpf0LLRgtC+0YDQvdC40Lpf0YHRgNC10LTQsF/Rh9C10YLQstC10YDQs1/Qv9GP0YLQvdC40YbQsF/RgdGD0LHQsdC+0YLQsCcuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZm9ybWF0OiAn0LLQvtGB0LrRgNC10YHQtdC90YzQtV/Qv9C+0L3QtdC00LXQu9GM0L3QuNC6X9Cy0YLQvtGA0L3QuNC6X9GB0YDQtdC00YNf0YfQtdGC0LLQtdGA0LNf0L/Rj9GC0L3QuNGG0YNf0YHRg9Cx0LHQvtGC0YMnLnNwbGl0KFxuICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGlzRm9ybWF0OiAvXFxbID9b0JLQsl0gPyg/OtC/0YDQvtGI0LvRg9GOfNGB0LvQtdC00YPRjtGJ0YPRjnzRjdGC0YMpPyA/XSA/ZGRkZC8sXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfQstGBX9C/0L1f0LLRgl/RgdGAX9GH0YJf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9Cy0YFf0L/QvV/QstGCX9GB0YBf0YfRgl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSRiLFxuICAgICAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJGIsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJGIsXG5cbiAgICAgICAgLy8g0L/QvtC70L3Ri9C1INC90LDQt9Cy0LDQvdC40Y8g0YEg0L/QsNC00LXQttCw0LzQuCwg0L/QviDRgtGA0Lgg0LHRg9C60LLRiywg0LTQu9GPINC90LXQutC+0YLQvtGA0YvRhSwg0L/QviA0INCx0YPQutCy0YssINGB0L7QutGA0LDRidC10L3QuNGPINGBINGC0L7Rh9C60L7QuSDQuCDQsdC10Lcg0YLQvtGH0LrQuFxuICAgICAgICBtb250aHNSZWdleDogL14o0Y/QvdCy0LDRgFvRjNGPXXzRj9C90LJcXC4/fNGE0LXQstGA0LDQu1vRjNGPXXzRhNC10LLRgD9cXC4/fNC80LDRgNGC0LA/fNC80LDRgFxcLj980LDQv9GA0LXQu1vRjNGPXXzQsNC/0YBcXC4/fNC80LBb0LnRj1180LjRjtC9W9GM0Y9dfNC40Y7QvVxcLj980LjRjtC7W9GM0Y9dfNC40Y7Qu1xcLj980LDQstCz0YPRgdGC0LA/fNCw0LLQs1xcLj980YHQtdC90YLRj9Cx0YBb0YzRj1180YHQtdC90YI/XFwuP3zQvtC60YLRj9Cx0YBb0YzRj1180L7QutGCXFwuP3zQvdC+0Y/QsdGAW9GM0Y9dfNC90L7Rj9CxP1xcLj980LTQtdC60LDQsdGAW9GM0Y9dfNC00LXQulxcLj8pL2ksXG5cbiAgICAgICAgLy8g0LrQvtC/0LjRjyDQv9GA0LXQtNGL0LTRg9GJ0LXQs9C+XG4gICAgICAgIG1vbnRoc1Nob3J0UmVnZXg6IC9eKNGP0L3QstCw0YBb0YzRj1180Y/QvdCyXFwuP3zRhNC10LLRgNCw0Ltb0YzRj1180YTQtdCy0YA/XFwuP3zQvNCw0YDRgtCwP3zQvNCw0YBcXC4/fNCw0L/RgNC10Ltb0YzRj1180LDQv9GAXFwuP3zQvNCwW9C50Y9dfNC40Y7QvVvRjNGPXXzQuNGO0L1cXC4/fNC40Y7Qu1vRjNGPXXzQuNGO0LtcXC4/fNCw0LLQs9GD0YHRgtCwP3zQsNCy0LNcXC4/fNGB0LXQvdGC0Y/QsdGAW9GM0Y9dfNGB0LXQvdGCP1xcLj980L7QutGC0Y/QsdGAW9GM0Y9dfNC+0LrRglxcLj980L3QvtGP0LHRgFvRjNGPXXzQvdC+0Y/QsT9cXC4/fNC00LXQutCw0LHRgFvRjNGPXXzQtNC10LpcXC4/KS9pLFxuXG4gICAgICAgIC8vINC/0L7Qu9C90YvQtSDQvdCw0LfQstCw0L3QuNGPINGBINC/0LDQtNC10LbQsNC80LhcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKNGP0L3QstCw0YBb0Y/RjF180YTQtdCy0YDQsNC7W9GP0YxdfNC80LDRgNGC0LA/fNCw0L/RgNC10Ltb0Y/RjF180LzQsFvRj9C5XXzQuNGO0L1b0Y/RjF180LjRjtC7W9GP0YxdfNCw0LLQs9GD0YHRgtCwP3zRgdC10L3RgtGP0LHRgFvRj9GMXXzQvtC60YLRj9Cx0YBb0Y/RjF180L3QvtGP0LHRgFvRj9GMXXzQtNC10LrQsNCx0YBb0Y/RjF0pL2ksXG5cbiAgICAgICAgLy8g0JLRi9GA0LDQttC10L3QuNC1LCDQutC+0YLQvtGA0L7QtSDRgdC+0L7RgtCy0LXRgtGB0YLQstGD0LXRgiDRgtC+0LvRjNC60L4g0YHQvtC60YDQsNGJ0ZHQvdC90YvQvCDRhNC+0YDQvNCw0LxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14o0Y/QvdCyXFwufNGE0LXQstGAP1xcLnzQvNCw0YBb0YIuXXzQsNC/0YBcXC580LzQsFvRj9C5XXzQuNGO0L1b0YzRjy5dfNC40Y7Qu1vRjNGPLl180LDQstCzXFwufNGB0LXQvdGCP1xcLnzQvtC60YJcXC580L3QvtGP0LE/XFwufNC00LXQulxcLikvaSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVkg0LMuJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZINCzLiwgSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkg0LMuLCBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb0KHQtdCz0L7QtNC90Y8sINCyXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9CX0LDQstGC0YDQsCwg0LJdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb0JLRh9C10YDQsCwg0LJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAobm93KSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vdy53ZWVrKCkgIT09IHRoaXMud2VlaygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINGB0LvQtdC00YPRjtGJ0LXQtV0gZGRkZCwgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JIg0YHQu9C10LTRg9GO0YnQuNC5XSBkZGRkLCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDRgdC70LXQtNGD0Y7RidGD0Y5dIGRkZGQsIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGF5KCkgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CS0L5dIGRkZGQsIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JJdIGRkZGQsIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAobm93KSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vdy53ZWVrKCkgIT09IHRoaXMud2VlaygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINC/0YDQvtGI0LvQvtC1XSBkZGRkLCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDQv9GA0L7RiNC70YvQuV0gZGRkZCwgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JIg0L/RgNC+0YjQu9GD0Y5dIGRkZGQsIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGF5KCkgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CS0L5dIGRkZGQsIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JJdIGRkZGQsIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAn0YfQtdGA0LXQtyAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMg0L3QsNC30LDQtCcsXG4gICAgICAgICAgICBzOiAn0L3QtdGB0LrQvtC70YzQutC+INGB0LXQutGD0L3QtCcsXG4gICAgICAgICAgICBzczogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzLFxuICAgICAgICAgICAgbTogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzLFxuICAgICAgICAgICAgbW06IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMyxcbiAgICAgICAgICAgIGg6ICfRh9Cw0YEnLFxuICAgICAgICAgICAgaGg6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMyxcbiAgICAgICAgICAgIGQ6ICfQtNC10L3RjCcsXG4gICAgICAgICAgICBkZDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzLFxuICAgICAgICAgICAgdzogJ9C90LXQtNC10LvRjycsXG4gICAgICAgICAgICB3dzogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzLFxuICAgICAgICAgICAgTTogJ9C80LXRgdGP0YYnLFxuICAgICAgICAgICAgTU06IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMyxcbiAgICAgICAgICAgIHk6ICfQs9C+0LQnLFxuICAgICAgICAgICAgeXk6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9C90L7Rh9C4fNGD0YLRgNCwfNC00L3Rj3zQstC10YfQtdGA0LAvaSxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gL14o0LTQvdGPfNCy0LXRh9C10YDQsCkkLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0L3QvtGH0LgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9GD0YLRgNCwJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfQtNC90Y8nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9Cy0LXRh9C10YDQsCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0Ll80LPQvnzRjykvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LknO1xuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3Qs9C+JztcbiAgICAgICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0Y8nO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBtb250aHMkOSA9IFtcbiAgICAgICAgICAgICfYrNmG2YjYsdmKJyxcbiAgICAgICAgICAgICfZgdmK2KjYsdmI2LHZiicsXG4gICAgICAgICAgICAn2YXYp9ix2oYnLFxuICAgICAgICAgICAgJ9in2b7YsdmK2YQnLFxuICAgICAgICAgICAgJ9mF2KbZiicsXG4gICAgICAgICAgICAn2KzZiNmGJyxcbiAgICAgICAgICAgICfYrNmI2YTYp9ih2ZAnLFxuICAgICAgICAgICAgJ9ii2q/Ys9m9JyxcbiAgICAgICAgICAgICfYs9mK2b7ZvdmF2KjYsScsXG4gICAgICAgICAgICAn2KLaqtm92YjYqNixJyxcbiAgICAgICAgICAgICfZhtmI2YXYqNixJyxcbiAgICAgICAgICAgICfaitiz2YXYqNixJyxcbiAgICAgICAgXSxcbiAgICAgICAgZGF5cyQxID0gWyfYotqG2LEnLCAn2LPZiNmF2LEnLCAn2Kfasdin2LHZiCcsICfYp9ix2KjYuScsICfYrtmF2YrYsycsICfYrNmF2LknLCAn2ofZhtqH2LEnXTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnc2QnLCB7XG4gICAgICAgIG1vbnRoczogbW9udGhzJDksXG4gICAgICAgIG1vbnRoc1Nob3J0OiBtb250aHMkOSxcbiAgICAgICAgd2Vla2RheXM6IGRheXMkMSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogZGF5cyQxLFxuICAgICAgICB3ZWVrZGF5c01pbjogZGF5cyQxLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRk2IwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv2LXYqNitfNi02KfZhS8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuICfYtNin2YUnID09PSBpbnB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9i12KjYrSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJ9i02KfZhSc7XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9in2oRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LPagNin2rvZil0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYp9qz2YrZhiDZh9mB2KrZiiDYqtmKXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9qq2KfZhNmH2YddIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW9qv2LLYsdmK2YQg2YfZgdiq2YpdIGRkZGQgW9iq2YpdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg2b7ZiNihJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDYp9qzJyxcbiAgICAgICAgICAgIHM6ICfahtmG2K8g2LPZitqq2YbaiicsXG4gICAgICAgICAgICBzczogJyVkINiz2YraqtmG2oonLFxuICAgICAgICAgICAgbTogJ9mH2qog2YXZhtm9JyxcbiAgICAgICAgICAgIG1tOiAnJWQg2YXZhtm9JyxcbiAgICAgICAgICAgIGg6ICfZh9qqINqq2YTYp9qqJyxcbiAgICAgICAgICAgIGhoOiAnJWQg2qrZhNin2qonLFxuICAgICAgICAgICAgZDogJ9mH2qog2o/ZitmG2YfZhicsXG4gICAgICAgICAgICBkZDogJyVkINqP2YrZhtmH2YYnLFxuICAgICAgICAgICAgTTogJ9mH2qog2YXZh9mK2YbZiCcsXG4gICAgICAgICAgICBNTTogJyVkINmF2YfZitmG2KcnLFxuICAgICAgICAgICAgeTogJ9mH2qog2LPYp9mEJyxcbiAgICAgICAgICAgIHl5OiAnJWQg2LPYp9mEJyxcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3NlJywge1xuICAgICAgICBtb250aHM6ICdvxJHEkWFqYWdlbcOhbm51X2d1b3Z2YW3DoW5udV9uanVrxI1hbcOhbm51X2N1b8WLb23DoW5udV9taWVzc2Vtw6FubnVfZ2Vhc3NlbcOhbm51X3N1b2lkbmVtw6FubnVfYm9yZ2Vtw6FubnVfxI1ha8SNYW3DoW5udV9nb2xnZ290bcOhbm51X3Nrw6FibWFtw6FubnVfanVvdmxhbcOhbm51Jy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2/EkcSRal9ndW92X25qdWtfY3VvX21pZXNfZ2Vhc19zdW9pX2JvcmdfxI1ha8SNX2dvbGdfc2vDoWJfanVvdicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICdzb3RuYWJlYWl2aV92dW9zc8OhcmdhX21hxYvFi2Viw6FyZ2FfZ2Fza2F2YWhra3VfZHVvcmFzdGF0X2JlYXJqYWRhdF9sw6F2dmFyZGF0Jy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnc290bl92dW9zX21hxYtfZ2Fza19kdW9yX2JlYXJfbMOhdicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdzX3ZfbV9nX2RfYl9MJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ01NTU0gRC4gW2IuXSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ01NTU0gRC4gW2IuXSBZWVlZIFt0aS5dIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBNTU1NIEQuIFtiLl0gWVlZWSBbdGkuXSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW290bmUgdGldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbaWh0dGluIHRpXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3RpXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW2lrdGUgdGldIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW292ZGRpdF0gZGRkZCBbdGldIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMgZ2Vhxb5lcycsXG4gICAgICAgICAgICBwYXN0OiAnbWHFi2l0ICVzJyxcbiAgICAgICAgICAgIHM6ICdtb2FkZGUgc2VrdW5kZGF0JyxcbiAgICAgICAgICAgIHNzOiAnJWQgc2VrdW5kZGF0JyxcbiAgICAgICAgICAgIG06ICdva3RhIG1pbnVodGEnLFxuICAgICAgICAgICAgbW06ICclZCBtaW51aHRhdCcsXG4gICAgICAgICAgICBoOiAnb2t0YSBkaWltbXUnLFxuICAgICAgICAgICAgaGg6ICclZCBkaWltbXV0JyxcbiAgICAgICAgICAgIGQ6ICdva3RhIGJlYWl2aScsXG4gICAgICAgICAgICBkZDogJyVkIGJlYWl2dml0JyxcbiAgICAgICAgICAgIE06ICdva3RhIG3DoW5udScsXG4gICAgICAgICAgICBNTTogJyVkIG3DoW51dCcsXG4gICAgICAgICAgICB5OiAnb2t0YSBqYWhraScsXG4gICAgICAgICAgICB5eTogJyVkIGphZ2l0JyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbDogJyVkLicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIC8qanNoaW50IC1XMTAwKi9cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3NpJywge1xuICAgICAgICBtb250aHM6ICfgtqLgtrHgt4Dgt4/gtrvgt5Jf4La04LeZ4La24La74LeA4LeP4La74LeSX+C2uOC3j+C2u+C3iuC2reC3lF/gtoXgtrTgt4rigI3gtrvgt5rgtr3gt4pf4La44LeQ4La64LeSX+C2ouC3luC2seC3kl/gtqLgt5bgtr3gt5Jf4LaF4Lac4Led4LeD4LeK4Lat4LeUX+C3g+C3kOC2tOC3iuC2reC3kOC2uOC3iuC2tuC2u+C3il/gtpTgtprgt4rgtq3gt53gtrbgtrvgt4pf4Lax4Lec4LeA4LeQ4La44LeK4La24La74LeKX+C2r+C3meC3g+C3kOC2uOC3iuC2tuC2u+C3iicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgtqLgtrFf4La04LeZ4La2X+C2uOC3j+C2u+C3il/gtoXgtrTgt4pf4La44LeQ4La64LeSX+C2ouC3luC2seC3kl/gtqLgt5bgtr3gt5Jf4LaF4Lac4LedX+C3g+C3kOC2tOC3il/gtpTgtprgt4pf4Lax4Lec4LeA4LeQX+C2r+C3meC3g+C3kCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfgtongtrvgt5Lgtq/gt49f4LeD4Laz4LeU4Lav4LePX+C2heC2n+C3hOC2u+C3lOC3gOC3j+C2r+C3j1/gtrbgtq/gt4/gtq/gt49f4La24LeK4oCN4La74LeE4LeD4LeK4La04Lat4LeS4Lax4LeK4Lav4LePX+C3g+C3kuC2muC3lOC2u+C3j+C2r+C3j1/gt4Pgt5ngtrHgt4Pgt5Tgtrvgt4/gtq/gt48nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfgtongtrvgt5Jf4LeD4Laz4LeUX+C2heC2n1/gtrbgtq/gt49f4La24LeK4oCN4La74LeEX+C3g+C3kuC2muC3lF/gt4Pgt5ngtrEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn4LaJX+C3g1/gtoVf4La2X+C2tuC3iuKAjeC2u1/gt4Pgt5Jf4LeD4LeZJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ2EgaDptbScsXG4gICAgICAgICAgICBMVFM6ICdhIGg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ1lZWVkvTU0vREQnLFxuICAgICAgICAgICAgTEw6ICdZWVlZIE1NTU0gRCcsXG4gICAgICAgICAgICBMTEw6ICdZWVlZIE1NTU0gRCwgYSBoOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdZWVlZIE1NTU0gRCBb4LeA4LeQ4Lax4LeSXSBkZGRkLCBhIGg6bW06c3MnLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vgtoXgtq9dIExUW+C2p10nLFxuICAgICAgICAgICAgbmV4dERheTogJ1vgt4Tgt5ngtqddIExUW+C2p10nLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIExUW+C2p10nLFxuICAgICAgICAgICAgbGFzdERheTogJ1vgtorgtrrgt5pdIExUW+C2p10nLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdb4La04LeD4LeU4Lac4LeS4La6XSBkZGRkIExUW+C2p10nLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclc+C2muC3kuC2seC3iicsXG4gICAgICAgICAgICBwYXN0OiAnJXPgtprgtqcg4La04LeZ4La7JyxcbiAgICAgICAgICAgIHM6ICfgtq3gtq3gt4rgtrTgtrsg4Laa4LeS4LeE4LeS4La04La6JyxcbiAgICAgICAgICAgIHNzOiAn4Lat4Lat4LeK4La04La7ICVkJyxcbiAgICAgICAgICAgIG06ICfgtrjgt5LgtrHgt5Lgtq3gt4rgtq3gt5Tgt4AnLFxuICAgICAgICAgICAgbW06ICfgtrjgt5LgtrHgt5Lgtq3gt4rgtq3gt5QgJWQnLFxuICAgICAgICAgICAgaDogJ+C2tOC3kOC2uicsXG4gICAgICAgICAgICBoaDogJ+C2tOC3kOC2uiAlZCcsXG4gICAgICAgICAgICBkOiAn4Lav4LeS4Lax4La6JyxcbiAgICAgICAgICAgIGRkOiAn4Lav4LeS4LaxICVkJyxcbiAgICAgICAgICAgIE06ICfgtrjgt4/gt4PgtronLFxuICAgICAgICAgICAgTU06ICfgtrjgt4/gt4MgJWQnLFxuICAgICAgICAgICAgeTogJ+C3gOC3g+C2uycsXG4gICAgICAgICAgICB5eTogJ+C3gOC3g+C2uyAlZCcsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSDgt4Dgt5DgtrHgt5IvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDgt4Dgt5DgtrHgt5InO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4La04LeZ4La7IOC3gOC2u+C3lHzgtrTgt4Pgt4og4LeA4La74LeUfOC2tOC3mS7gt4B84La0LuC3gC4vLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PT0gJ+C2tC7gt4AuJyB8fCBpbnB1dCA9PT0gJ+C2tOC3g+C3iiDgt4Dgtrvgt5QnO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ+C2tC7gt4AuJyA6ICfgtrTgt4Pgt4og4LeA4La74LeUJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAn4La04LeZLuC3gC4nIDogJ+C2tOC3meC2uyDgt4Dgtrvgt5QnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRocyRhID0gJ2phbnXDoXJfZmVicnXDoXJfbWFyZWNfYXByw61sX23DoWpfasO6bl9qw7psX2F1Z3VzdF9zZXB0ZW1iZXJfb2t0w7NiZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0JDcgPSAnamFuX2ZlYl9tYXJfYXByX23DoWpfasO6bl9qw7psX2F1Z19zZXBfb2t0X25vdl9kZWMnLnNwbGl0KCdfJyk7XG4gICAgZnVuY3Rpb24gcGx1cmFsJDUobikge1xuICAgICAgICByZXR1cm4gbiA+IDEgJiYgbiA8IDU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZSQ5KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAncyc6IC8vIGEgZmV3IHNlY29uZHMgLyBpbiBhIGZldyBzZWNvbmRzIC8gYSBmZXcgc2Vjb25kcyBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdww6FyIHNla8O6bmQnIDogJ3DDoXIgc2VrdW5kYW1pJztcbiAgICAgICAgICAgIGNhc2UgJ3NzJzogLy8gOSBzZWNvbmRzIC8gaW4gOSBzZWNvbmRzIC8gOSBzZWNvbmRzIGFnb1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDUobnVtYmVyKSA/ICdzZWt1bmR5JyA6ICdzZWvDum5kJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdzZWt1bmRhbWknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgJ20nOiAvLyBhIG1pbnV0ZSAvIGluIGEgbWludXRlIC8gYSBtaW51dGUgYWdvXG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnbWluw7p0YScgOiBpc0Z1dHVyZSA/ICdtaW7DunR1JyA6ICdtaW7DunRvdSc7XG4gICAgICAgICAgICBjYXNlICdtbSc6IC8vIDkgbWludXRlcyAvIGluIDkgbWludXRlcyAvIDkgbWludXRlcyBhZ29cbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAnbWluw7p0eScgOiAnbWluw7p0Jyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdtaW7DunRhbWknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgJ2gnOiAvLyBhbiBob3VyIC8gaW4gYW4gaG91ciAvIGFuIGhvdXIgYWdvXG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnaG9kaW5hJyA6IGlzRnV0dXJlID8gJ2hvZGludScgOiAnaG9kaW5vdSc7XG4gICAgICAgICAgICBjYXNlICdoaCc6IC8vIDkgaG91cnMgLyBpbiA5IGhvdXJzIC8gOSBob3VycyBhZ29cbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAnaG9kaW55JyA6ICdob2TDrW4nKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2hvZGluYW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlICdkJzogLy8gYSBkYXkgLyBpbiBhIGRheSAvIGEgZGF5IGFnb1xuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2RlxYgnIDogJ2TFiG9tJztcbiAgICAgICAgICAgIGNhc2UgJ2RkJzogLy8gOSBkYXlzIC8gaW4gOSBkYXlzIC8gOSBkYXlzIGFnb1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDUobnVtYmVyKSA/ICdkbmknIDogJ2Ruw60nKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2TFiGFtaSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSAnTSc6IC8vIGEgbW9udGggLyBpbiBhIG1vbnRoIC8gYSBtb250aCBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtZXNpYWMnIDogJ21lc2lhY29tJztcbiAgICAgICAgICAgIGNhc2UgJ01NJzogLy8gOSBtb250aHMgLyBpbiA5IG1vbnRocyAvIDkgbW9udGhzIGFnb1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDUobnVtYmVyKSA/ICdtZXNpYWNlJyA6ICdtZXNpYWNvdicpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbWVzaWFjbWknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgJ3knOiAvLyBhIHllYXIgLyBpbiBhIHllYXIgLyBhIHllYXIgYWdvXG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAncm9rJyA6ICdyb2tvbSc7XG4gICAgICAgICAgICBjYXNlICd5eSc6IC8vIDkgeWVhcnMgLyBpbiA5IHllYXJzIC8gOSB5ZWFycyBhZ29cbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAncm9reScgOiAncm9rb3YnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ3Jva21pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3NrJywge1xuICAgICAgICBtb250aHM6IG1vbnRocyRhLFxuICAgICAgICBtb250aHNTaG9ydDogbW9udGhzU2hvcnQkNyxcbiAgICAgICAgd2Vla2RheXM6ICduZWRlxL5hX3BvbmRlbG9rX3V0b3Jva19zdHJlZGFfxaF0dnJ0b2tfcGlhdG9rX3NvYm90YScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ25lX3BvX3V0X3N0X8WhdF9waV9zbycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICduZV9wb191dF9zdF/FoXRfcGlfc28nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCBELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2RuZXMgb10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1t6YWp0cmEgb10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBuZWRlxL51IG9dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Ygc3RyZWR1IG9dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdm8gxaF0dnJ0b2sgb10gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IHBpYXRvayBvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Ygc29ib3R1IG9dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogJ1t2xI1lcmEgb10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDuiBuZWRlxL51IG9dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO9XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw7ogc3RyZWR1IG9dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO9XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw7ogc29ib3R1IG9dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICd6YSAlcycsXG4gICAgICAgICAgICBwYXN0OiAncHJlZCAlcycsXG4gICAgICAgICAgICBzOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgICAgIHNzOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgICAgIG06IHRyYW5zbGF0ZSQ5LFxuICAgICAgICAgICAgbW06IHRyYW5zbGF0ZSQ5LFxuICAgICAgICAgICAgaDogdHJhbnNsYXRlJDksXG4gICAgICAgICAgICBoaDogdHJhbnNsYXRlJDksXG4gICAgICAgICAgICBkOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgICAgIGRkOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgICAgIE06IHRyYW5zbGF0ZSQ5LFxuICAgICAgICAgICAgTU06IHRyYW5zbGF0ZSQ5LFxuICAgICAgICAgICAgeTogdHJhbnNsYXRlJDksXG4gICAgICAgICAgICB5eTogdHJhbnNsYXRlJDksXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZVxuICAgICAgICAgICAgICAgICAgICA/ICduZWthaiBzZWt1bmQnXG4gICAgICAgICAgICAgICAgICAgIDogJ25la2FqIHNla3VuZGFtaSc7XG4gICAgICAgICAgICBjYXNlICdzcyc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCA/ICdzZWt1bmRvJyA6ICdzZWt1bmRpJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdzZWt1bmRpJyA6ICdzZWt1bmRhaCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPCA1KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ3Nla3VuZGUnIDogJ3Nla3VuZGFoJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3Nla3VuZCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdlbmEgbWludXRhJyA6ICdlbm8gbWludXRvJztcbiAgICAgICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4ID8gJ21pbnV0YScgOiAnbWludXRvJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtaW51dGknIDogJ21pbnV0YW1hJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWludXRlJyA6ICdtaW51dGFtaSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWludXQnIDogJ21pbnV0YW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2VuYSB1cmEnIDogJ2VubyB1cm8nO1xuICAgICAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggPyAndXJhJyA6ICd1cm8nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ3VyaScgOiAndXJhbWEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgNSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICd1cmUnIDogJ3VyYW1pJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICd1cicgOiAndXJhbWknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZW4gZGFuJyA6ICdlbmltIGRuZW0nO1xuICAgICAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZGFuJyA6ICdkbmVtJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdkbmknIDogJ2RuZXZvbWEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2RuaScgOiAnZG5ldmknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZW4gbWVzZWMnIDogJ2VuaW0gbWVzZWNlbSc7XG4gICAgICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtZXNlYycgOiAnbWVzZWNlbSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWVzZWNhJyA6ICdtZXNlY2VtYSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPCA1KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ21lc2VjZScgOiAnbWVzZWNpJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtZXNlY2V2JyA6ICdtZXNlY2knO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAneSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZW5vIGxldG8nIDogJ2VuaW0gbGV0b20nO1xuICAgICAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbGV0bycgOiAnbGV0b20nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2xldGknIDogJ2xldG9tYSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPCA1KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2xldGEnIDogJ2xldGknO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2xldCcgOiAnbGV0aSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3NsJywge1xuICAgICAgICBtb250aHM6ICdqYW51YXJfZmVicnVhcl9tYXJlY19hcHJpbF9tYWpfanVuaWpfanVsaWpfYXZndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2phbi5fZmViLl9tYXIuX2Fwci5fbWFqLl9qdW4uX2p1bC5fYXZnLl9zZXAuX29rdC5fbm92Ll9kZWMuJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ25lZGVsamFfcG9uZWRlbGpla190b3Jla19zcmVkYV/EjWV0cnRla19wZXRla19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICduZWQuX3Bvbi5fdG9yLl9zcmUuX8SNZXQuX3BldC5fc29iLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICduZV9wb190b19zcl/EjWVfcGVfc28nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC4gTU0uIFlZWVknLFxuICAgICAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbZGFuZXMgb2JdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbanV0cmkgb2JdIExUJyxcblxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdl0gW25lZGVsam9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBbc3JlZG9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBbc29ib3RvXSBbb2JdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdl0gZGRkZCBbb2JdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogJ1t2xI1lcmFqIG9iXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcmVqxaFuam9dIFtuZWRlbGpvXSBbb2JdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJlasWhbmpvXSBbc3JlZG9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcmVqxaFuam9dIFtzb2JvdG9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcmVqxaFuamldIGRkZGQgW29iXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnxI1leiAlcycsXG4gICAgICAgICAgICBwYXN0OiAncHJlZCAlcycsXG4gICAgICAgICAgICBzOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcsXG4gICAgICAgICAgICBzczogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgbTogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgbW06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIGg6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIGhoOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcsXG4gICAgICAgICAgICBkOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcsXG4gICAgICAgICAgICBkZDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgTTogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgTU06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIHk6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIHl5OiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA3LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3NxJywge1xuICAgICAgICBtb250aHM6ICdKYW5hcl9TaGt1cnRfTWFyc19QcmlsbF9NYWpfUWVyc2hvcl9Lb3JyaWtfR3VzaHRfU2h0YXRvcl9UZXRvcl9Ow6tudG9yX0RoamV0b3InLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuX1Noa19NYXJfUHJpX01hal9RZXJfS29yX0d1c19TaHRfVGV0X07Dq25fRGhqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ0UgRGllbF9FIEjDq27Dq19FIE1hcnTDq19FIE3Dq3JrdXLDq19FIEVuanRlX0UgUHJlbXRlX0UgU2h0dW7Dqycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ0RpZV9Iw6tuX01hcl9Nw6tyX0Vual9QcmVfU2h0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ0RfSF9NYV9Nw6tfRV9QX1NoJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9QRHxNRC8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0LmNoYXJBdCgwKSA9PT0gJ00nO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cnMgPCAxMiA/ICdQRCcgOiAnTUQnO1xuICAgICAgICB9LFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW1NvdCBuw6tdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbTmVzw6tyIG7Dq10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtuw6tdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbRGplIG7Dq10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFtlIGthbHVhciBuw6tdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnbsOrICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyBtw6sgcGFyw6snLFxuICAgICAgICAgICAgczogJ2Rpc2Egc2Vrb25kYScsXG4gICAgICAgICAgICBzczogJyVkIHNla29uZGEnLFxuICAgICAgICAgICAgbTogJ25qw6sgbWludXTDqycsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0YScsXG4gICAgICAgICAgICBoOiAnbmrDqyBvcsOrJyxcbiAgICAgICAgICAgIGhoOiAnJWQgb3LDqycsXG4gICAgICAgICAgICBkOiAnbmrDqyBkaXTDqycsXG4gICAgICAgICAgICBkZDogJyVkIGRpdMOrJyxcbiAgICAgICAgICAgIE06ICduasOrIG11YWonLFxuICAgICAgICAgICAgTU06ICclZCBtdWFqJyxcbiAgICAgICAgICAgIHk6ICduasOrIHZpdCcsXG4gICAgICAgICAgICB5eTogJyVkIHZpdGUnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHRyYW5zbGF0b3IkMSA9IHtcbiAgICAgICAgd29yZHM6IHtcbiAgICAgICAgICAgIC8vRGlmZmVyZW50IGdyYW1tYXRpY2FsIGNhc2VzXG4gICAgICAgICAgICBzczogWyfRgdC10LrRg9C90LTQsCcsICfRgdC10LrRg9C90LTQtScsICfRgdC10LrRg9C90LTQuCddLFxuICAgICAgICAgICAgbTogWyfRmNC10LTQsNC9INC80LjQvdGD0YInLCAn0ZjQtdC00L3QtSDQvNC40L3Rg9GC0LUnXSxcbiAgICAgICAgICAgIG1tOiBbJ9C80LjQvdGD0YInLCAn0LzQuNC90YPRgtC1JywgJ9C80LjQvdGD0YLQsCddLFxuICAgICAgICAgICAgaDogWyfRmNC10LTQsNC9INGB0LDRgicsICfRmNC10LTQvdC+0LMg0YHQsNGC0LAnXSxcbiAgICAgICAgICAgIGhoOiBbJ9GB0LDRgicsICfRgdCw0YLQsCcsICfRgdCw0YLQuCddLFxuICAgICAgICAgICAgZGQ6IFsn0LTQsNC9JywgJ9C00LDQvdCwJywgJ9C00LDQvdCwJ10sXG4gICAgICAgICAgICBNTTogWyfQvNC10YHQtdGGJywgJ9C80LXRgdC10YbQsCcsICfQvNC10YHQtdGG0LgnXSxcbiAgICAgICAgICAgIHl5OiBbJ9Cz0L7QtNC40L3QsCcsICfQs9C+0LTQuNC90LUnLCAn0LPQvtC00LjQvdCwJ10sXG4gICAgICAgIH0sXG4gICAgICAgIGNvcnJlY3RHcmFtbWF0aWNhbENhc2U6IGZ1bmN0aW9uIChudW1iZXIsIHdvcmRLZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgPT09IDFcbiAgICAgICAgICAgICAgICA/IHdvcmRLZXlbMF1cbiAgICAgICAgICAgICAgICA6IG51bWJlciA+PSAyICYmIG51bWJlciA8PSA0XG4gICAgICAgICAgICAgICAgPyB3b3JkS2V5WzFdXG4gICAgICAgICAgICAgICAgOiB3b3JkS2V5WzJdO1xuICAgICAgICB9LFxuICAgICAgICB0cmFuc2xhdGU6IGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICAgICAgdmFyIHdvcmRLZXkgPSB0cmFuc2xhdG9yJDEud29yZHNba2V5XTtcbiAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyB3b3JkS2V5WzBdIDogd29yZEtleVsxXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgbnVtYmVyICtcbiAgICAgICAgICAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRvciQxLmNvcnJlY3RHcmFtbWF0aWNhbENhc2UobnVtYmVyLCB3b3JkS2V5KVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnc3ItY3lybCcsIHtcbiAgICAgICAgbW9udGhzOiAn0ZjQsNC90YPQsNGAX9GE0LXQsdGA0YPQsNGAX9C80LDRgNGCX9Cw0L/RgNC40Ltf0LzQsNGYX9GY0YPQvV/RmNGD0Ltf0LDQstCz0YPRgdGCX9GB0LXQv9GC0LXQvNCx0LDRgF/QvtC60YLQvtCx0LDRgF/QvdC+0LLQtdC80LHQsNGAX9C00LXRhtC10LzQsdCw0YAnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn0ZjQsNC9Ll/RhNC10LEuX9C80LDRgC5f0LDQv9GALl/QvNCw0Zhf0ZjRg9C9X9GY0YPQu1/QsNCy0LMuX9GB0LXQvy5f0L7QutGCLl/QvdC+0LIuX9C00LXRhi4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAn0L3QtdC00LXRmdCwX9C/0L7QvdC10LTQtdGZ0LDQul/Rg9GC0L7RgNCw0Lpf0YHRgNC10LTQsF/Rh9C10YLQstGA0YLQsNC6X9C/0LXRgtCw0Lpf0YHRg9Cx0L7RgtCwJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn0L3QtdC0Ll/Qv9C+0L0uX9GD0YLQvi5f0YHRgNC1Ll/Rh9C10YIuX9C/0LXRgi5f0YHRg9CxLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfQvdC1X9C/0L5f0YPRgl/RgdGAX9GH0LVf0L/QtV/RgdGDJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMOiAnRC4gTS4gWVlZWS4nLFxuICAgICAgICAgICAgTEw6ICdELiBNTU1NIFlZWVkuJyxcbiAgICAgICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWS4gSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZLiBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb0LTQsNC90LDRgSDRg10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vRgdGD0YLRgNCwINGDXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vRg10gW9C90LXQtNC10ZnRg10gW9GDXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9GDXSBb0YHRgNC10LTRg10gW9GDXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9GDXSBb0YHRg9Cx0L7RgtGDXSBb0YNdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0YNdIGRkZGQgW9GDXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb0ZjRg9GH0LUg0YNdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RXZWVrRGF5cyA9IFtcbiAgICAgICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70LVdIFvQvdC10LTQtdGZ0LVdIFvRg10gTFQnLFxuICAgICAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQvtCzXSBb0L/QvtC90LXQtNC10ZnQutCwXSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70L7Qs10gW9GD0YLQvtGA0LrQsF0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdb0L/RgNC+0YjQu9C1XSBb0YHRgNC10LTQtV0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdb0L/RgNC+0YjQu9C+0LNdIFvRh9C10YLQstGA0YLQutCwXSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70L7Qs10gW9C/0LXRgtC60LBdIFvRg10gTFQnLFxuICAgICAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQtV0gW9GB0YPQsdC+0YLQtV0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFzdFdlZWtEYXlzW3RoaXMuZGF5KCldO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAn0LfQsCAlcycsXG4gICAgICAgICAgICBwYXN0OiAn0L/RgNC1ICVzJyxcbiAgICAgICAgICAgIHM6ICfQvdC10LrQvtC70LjQutC+INGB0LXQutGD0L3QtNC4JyxcbiAgICAgICAgICAgIHNzOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICAgICAgbTogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIG1tOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICAgICAgaDogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGhoOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICAgICAgZDogJ9C00LDQvScsXG4gICAgICAgICAgICBkZDogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIE06ICfQvNC10YHQtdGGJyxcbiAgICAgICAgICAgIE1NOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICAgICAgeTogJ9Cz0L7QtNC40L3RgycsXG4gICAgICAgICAgICB5eTogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZSxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbDogJyVkLicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciB0cmFuc2xhdG9yJDIgPSB7XG4gICAgICAgIHdvcmRzOiB7XG4gICAgICAgICAgICAvL0RpZmZlcmVudCBncmFtbWF0aWNhbCBjYXNlc1xuICAgICAgICAgICAgc3M6IFsnc2VrdW5kYScsICdzZWt1bmRlJywgJ3Nla3VuZGknXSxcbiAgICAgICAgICAgIG06IFsnamVkYW4gbWludXQnLCAnamVkbmUgbWludXRlJ10sXG4gICAgICAgICAgICBtbTogWydtaW51dCcsICdtaW51dGUnLCAnbWludXRhJ10sXG4gICAgICAgICAgICBoOiBbJ2plZGFuIHNhdCcsICdqZWRub2cgc2F0YSddLFxuICAgICAgICAgICAgaGg6IFsnc2F0JywgJ3NhdGEnLCAnc2F0aSddLFxuICAgICAgICAgICAgZGQ6IFsnZGFuJywgJ2RhbmEnLCAnZGFuYSddLFxuICAgICAgICAgICAgTU06IFsnbWVzZWMnLCAnbWVzZWNhJywgJ21lc2VjaSddLFxuICAgICAgICAgICAgeXk6IFsnZ29kaW5hJywgJ2dvZGluZScsICdnb2RpbmEnXSxcbiAgICAgICAgfSxcbiAgICAgICAgY29ycmVjdEdyYW1tYXRpY2FsQ2FzZTogZnVuY3Rpb24gKG51bWJlciwgd29yZEtleSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciA9PT0gMVxuICAgICAgICAgICAgICAgID8gd29yZEtleVswXVxuICAgICAgICAgICAgICAgIDogbnVtYmVyID49IDIgJiYgbnVtYmVyIDw9IDRcbiAgICAgICAgICAgICAgICA/IHdvcmRLZXlbMV1cbiAgICAgICAgICAgICAgICA6IHdvcmRLZXlbMl07XG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zbGF0ZTogZnVuY3Rpb24gKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgICAgICB2YXIgd29yZEtleSA9IHRyYW5zbGF0b3IkMi53b3Jkc1trZXldO1xuICAgICAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IHdvcmRLZXlbMF0gOiB3b3JkS2V5WzFdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICBudW1iZXIgK1xuICAgICAgICAgICAgICAgICAgICAnICcgK1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdG9yJDIuY29ycmVjdEdyYW1tYXRpY2FsQ2FzZShudW1iZXIsIHdvcmRLZXkpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzcicsIHtcbiAgICAgICAgbW9udGhzOiAnamFudWFyX2ZlYnJ1YXJfbWFydF9hcHJpbF9tYWpfanVuX2p1bF9hdmd1c3Rfc2VwdGVtYmFyX29rdG9iYXJfbm92ZW1iYXJfZGVjZW1iYXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnamFuLl9mZWIuX21hci5fYXByLl9tYWpfanVuX2p1bF9hdmcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnbmVkZWxqYV9wb25lZGVsamFrX3V0b3Jha19zcmVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnbmVkLl9wb24uX3V0by5fc3JlLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnbmVfcG9fdXRfc3JfxI1lX3BlX3N1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMOiAnRC4gTS4gWVlZWS4nLFxuICAgICAgICAgICAgTEw6ICdELiBNTU1NIFlZWVkuJyxcbiAgICAgICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWS4gSDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZLiBIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbZGFuYXMgdV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tzdXRyYSB1XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbbmVkZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3NyZWR1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbc3Vib3R1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbanXEjWUgdV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGFzdFdlZWtEYXlzID0gW1xuICAgICAgICAgICAgICAgICAgICAnW3Byb8WhbGVdIFtuZWRlbGplXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICAgICAnW3Byb8WhbG9nXSBbcG9uZWRlbGprYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1twcm/FoWxvZ10gW3V0b3JrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3JlZGVdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFvEjWV0dnJ0a2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFtwZXRrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3Vib3RlXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxhc3RXZWVrRGF5c1t0aGlzLmRheSgpXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ3phICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICdwcmUgJXMnLFxuICAgICAgICAgICAgczogJ25la29saWtvIHNla3VuZGknLFxuICAgICAgICAgICAgc3M6IHRyYW5zbGF0b3IkMi50cmFuc2xhdGUsXG4gICAgICAgICAgICBtOiB0cmFuc2xhdG9yJDIudHJhbnNsYXRlLFxuICAgICAgICAgICAgbW06IHRyYW5zbGF0b3IkMi50cmFuc2xhdGUsXG4gICAgICAgICAgICBoOiB0cmFuc2xhdG9yJDIudHJhbnNsYXRlLFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0b3IkMi50cmFuc2xhdGUsXG4gICAgICAgICAgICBkOiAnZGFuJyxcbiAgICAgICAgICAgIGRkOiB0cmFuc2xhdG9yJDIudHJhbnNsYXRlLFxuICAgICAgICAgICAgTTogJ21lc2VjJyxcbiAgICAgICAgICAgIE1NOiB0cmFuc2xhdG9yJDIudHJhbnNsYXRlLFxuICAgICAgICAgICAgeTogJ2dvZGludScsXG4gICAgICAgICAgICB5eTogdHJhbnNsYXRvciQyLnRyYW5zbGF0ZSxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbDogJyVkLicsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnc3MnLCB7XG4gICAgICAgIG1vbnRoczogXCJCaGltYmlkdndhbmVfSW5kbG92YW5hX0luZGxvdidsZW5raHVsdV9NYWJhc2FfSW5raHdla2h3ZXRpX0luaGxhYmFfS2hvbHdhbmVfSW5nY2lfSW55b25pX0ltcGhhbGFfTHdldGlfSW5nb25nb25pXCIuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdCaGlfSW5hX0ludV9NYWJfSW5rX0luaF9LaG9fSWdjX0lueV9JbXBfTHdlX0lnbycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdMaXNvbnRmb19VbXNvbWJ1bHVrb19MZXNpYmlsaV9MZXNpdHNhdGZ1X0xlc2luZV9MZXNpaGxhbnVfVW1nY2liZWxvJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnTGlzX1VtYl9Mc2JfTGVzX0xzaV9Mc2hfVW1nJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ0xpX1VzX0xiX0x0X0xzX0xoX1VnJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ2g6bW0gQScsXG4gICAgICAgICAgICBMVFM6ICdoOm1tOnNzIEEnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBoOm1tIEEnLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW05hbXVobGEgbmdhXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0t1c2FzYSBuZ2FdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbbmdhXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0l0b2xvIG5nYV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFtsZWxpcGhlbGlsZV0gW25nYV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICduZ2EgJXMnLFxuICAgICAgICAgICAgcGFzdDogJ3dlbnRla2EgbmdhICVzJyxcbiAgICAgICAgICAgIHM6ICdlbWl6dXp3YW5hIGxvbWNhbmUnLFxuICAgICAgICAgICAgc3M6ICclZCBtenV6d2FuYScsXG4gICAgICAgICAgICBtOiAndW16dXp1JyxcbiAgICAgICAgICAgIG1tOiAnJWQgZW1penV6dScsXG4gICAgICAgICAgICBoOiAnbGlob3JhJyxcbiAgICAgICAgICAgIGhoOiAnJWQgZW1haG9yYScsXG4gICAgICAgICAgICBkOiAnbGlsYW5nYScsXG4gICAgICAgICAgICBkZDogJyVkIGVtYWxhbmdhJyxcbiAgICAgICAgICAgIE06ICdpbnlhbmdhJyxcbiAgICAgICAgICAgIE1NOiAnJWQgdGlueWFuZ2EnLFxuICAgICAgICAgICAgeTogJ3Vtbnlha2EnLFxuICAgICAgICAgICAgeXk6ICclZCBpbWlueWFrYScsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9la3VzZW5pfGVtaW5pfGVudHNhbWJhbWF8ZWJ1c3VrdS8sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VycyA8IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdla3VzZW5pJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZW1pbmknO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdlbnRzYW1iYW1hJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdlYnVzdWt1JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAnZWt1c2VuaScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdlbWluaScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnZW50c2FtYmFtYScgfHwgbWVyaWRpZW0gPT09ICdlYnVzdWt1Jykge1xuICAgICAgICAgICAgICAgIGlmIChob3VyID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0vLFxuICAgICAgICBvcmRpbmFsOiAnJWQnLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3N2Jywge1xuICAgICAgICBtb250aHM6ICdqYW51YXJpX2ZlYnJ1YXJpX21hcnNfYXByaWxfbWFqX2p1bmlfanVsaV9hdWd1c3RpX3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2phbl9mZWJfbWFyX2Fwcl9tYWpfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ3PDtm5kYWdfbcOlbmRhZ190aXNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2zDtnJkYWcnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdzw7ZuX23DpW5fdGlzX29uc190b3JfZnJlX2zDtnInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnc8O2X23DpV90aV9vbl90b19mcl9sw7YnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nLFxuICAgICAgICAgICAgbGxsOiAnRCBNTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBsbGxsOiAnZGRkIEQgTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tJZGFnXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0ltb3Jnb25dIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbSWfDpXJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW1DDpV0gZGRkZCBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tJXSBkZGRkW3NdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnb20gJXMnLFxuICAgICAgICAgICAgcGFzdDogJ2bDtnIgJXMgc2VkYW4nLFxuICAgICAgICAgICAgczogJ27DpWdyYSBzZWt1bmRlcicsXG4gICAgICAgICAgICBzczogJyVkIHNla3VuZGVyJyxcbiAgICAgICAgICAgIG06ICdlbiBtaW51dCcsXG4gICAgICAgICAgICBtbTogJyVkIG1pbnV0ZXInLFxuICAgICAgICAgICAgaDogJ2VuIHRpbW1lJyxcbiAgICAgICAgICAgIGhoOiAnJWQgdGltbWFyJyxcbiAgICAgICAgICAgIGQ6ICdlbiBkYWcnLFxuICAgICAgICAgICAgZGQ6ICclZCBkYWdhcicsXG4gICAgICAgICAgICBNOiAnZW4gbcOlbmFkJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbcOlbmFkZXInLFxuICAgICAgICAgICAgeTogJ2V0dCDDpXInLFxuICAgICAgICAgICAgeXk6ICclZCDDpXInLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oXFw6ZXxcXDphKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID1cbiAgICAgICAgICAgICAgICAgICAgfn4oKG51bWJlciAlIDEwMCkgLyAxMCkgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJzplJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICc6YSdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gMlxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnOmEnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDNcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJzplJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiAnOmUnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzdycsIHtcbiAgICAgICAgbW9udGhzOiAnSmFudWFyaV9GZWJydWFyaV9NYWNoaV9BcHJpbGlfTWVpX0p1bmlfSnVsYWlfQWdvc3RpX1NlcHRlbWJhX09rdG9iYV9Ob3ZlbWJhX0Rlc2VtYmEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuX0ZlYl9NYWNfQXByX01laV9KdW5fSnVsX0Fnb19TZXBfT2t0X05vdl9EZXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnSnVtYXBpbGlfSnVtYXRhdHVfSnVtYW5uZV9KdW1hdGFub19BbGhhbWlzaV9JanVtYWFfSnVtYW1vc2knLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdKcGxfSnRhdF9Kbm5lX0p0YW5fQWxoX0lqbV9KbW9zJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ0oyX0ozX0o0X0o1X0FsX0lqX0oxJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ2hoOm1tIEEnLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tsZW8gc2FhXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW2tlc2hvIHNhYV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdbd2lraSBpamF5b10gZGRkZCBbc2FhdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tqYW5hXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1t3aWtpIGlsaXlvcGl0YV0gZGRkZCBbc2FhdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclcyBiYWFkYXllJyxcbiAgICAgICAgICAgIHBhc3Q6ICd0b2tlYSAlcycsXG4gICAgICAgICAgICBzOiAnaGl2aSBwdW5kZScsXG4gICAgICAgICAgICBzczogJ3Nla3VuZGUgJWQnLFxuICAgICAgICAgICAgbTogJ2Rha2lrYSBtb2phJyxcbiAgICAgICAgICAgIG1tOiAnZGFraWthICVkJyxcbiAgICAgICAgICAgIGg6ICdzYWEgbGltb2phJyxcbiAgICAgICAgICAgIGhoOiAnbWFzYWEgJWQnLFxuICAgICAgICAgICAgZDogJ3Npa3UgbW9qYScsXG4gICAgICAgICAgICBkZDogJ3Npa3UgJWQnLFxuICAgICAgICAgICAgTTogJ213ZXppIG1tb2phJyxcbiAgICAgICAgICAgIE1NOiAnbWllemkgJWQnLFxuICAgICAgICAgICAgeTogJ213YWthIG1tb2phJyxcbiAgICAgICAgICAgIHl5OiAnbWlha2EgJWQnLFxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA3LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJGcgPSB7XG4gICAgICAgICAgICAxOiAn4K+nJyxcbiAgICAgICAgICAgIDI6ICfgr6gnLFxuICAgICAgICAgICAgMzogJ+CvqScsXG4gICAgICAgICAgICA0OiAn4K+qJyxcbiAgICAgICAgICAgIDU6ICfgr6snLFxuICAgICAgICAgICAgNjogJ+CvrCcsXG4gICAgICAgICAgICA3OiAn4K+tJyxcbiAgICAgICAgICAgIDg6ICfgr64nLFxuICAgICAgICAgICAgOTogJ+CvrycsXG4gICAgICAgICAgICAwOiAn4K+mJyxcbiAgICAgICAgfSxcbiAgICAgICAgbnVtYmVyTWFwJGYgPSB7XG4gICAgICAgICAgICAn4K+nJzogJzEnLFxuICAgICAgICAgICAgJ+CvqCc6ICcyJyxcbiAgICAgICAgICAgICfgr6knOiAnMycsXG4gICAgICAgICAgICAn4K+qJzogJzQnLFxuICAgICAgICAgICAgJ+Cvqyc6ICc1JyxcbiAgICAgICAgICAgICfgr6wnOiAnNicsXG4gICAgICAgICAgICAn4K+tJzogJzcnLFxuICAgICAgICAgICAgJ+Cvric6ICc4JyxcbiAgICAgICAgICAgICfgr68nOiAnOScsXG4gICAgICAgICAgICAn4K+mJzogJzAnLFxuICAgICAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0YScsIHtcbiAgICAgICAgbW9udGhzOiAn4K6c4K6p4K614K6w4K6/X+CuquCuv+CuquCvjeCusOCuteCusOCuv1/grq7grr7grrDgr43grprgr41f4K6P4K6q4K+N4K6w4K6y4K+NX+CuruCvh1/grpzgr4Lgrqngr41f4K6c4K+C4K6y4K+IX+CuhuCuleCuuOCvjeCun+CvjV/grprgr4bgrqrgr43grp/gr4bgrq7gr43grqrgrrDgr41f4K6F4K6V4K+N4K6f4K+H4K6+4K6q4K6w4K+NX+CuqOCuteCuruCvjeCuquCusOCvjV/grp/grr/grprgrq7gr43grqrgrrDgr40nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn4K6c4K6p4K614K6w4K6/X+CuquCuv+CuquCvjeCusOCuteCusOCuv1/grq7grr7grrDgr43grprgr41f4K6P4K6q4K+N4K6w4K6y4K+NX+CuruCvh1/grpzgr4Lgrqngr41f4K6c4K+C4K6y4K+IX+CuhuCuleCuuOCvjeCun+CvjV/grprgr4bgrqrgr43grp/gr4bgrq7gr43grqrgrrDgr41f4K6F4K6V4K+N4K6f4K+H4K6+4K6q4K6w4K+NX+CuqOCuteCuruCvjeCuquCusOCvjV/grp/grr/grprgrq7gr43grqrgrrDgr40nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzOiAn4K6e4K6+4K6v4K6/4K6x4K+N4K6x4K+B4K6V4K+N4K6V4K6/4K604K6u4K+IX+CupOCuv+CumeCvjeCuleCun+CvjeCuleCuv+CutOCuruCviF/grprgr4bgrrXgr43grrXgrr7grq/gr43grpXgrr/grrTgrq7gr4hf4K6q4K+B4K6k4K6p4K+N4K6V4K6/4K604K6u4K+IX+CuteCuv+Cur+CuvuCutOCuleCvjeCuleCuv+CutOCuruCviF/grrXgr4bgrrPgr43grrPgrr/grpXgr43grpXgrr/grrTgrq7gr4hf4K6a4K6p4K6/4K6V4K+N4K6V4K6/4K604K6u4K+IJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn4K6e4K6+4K6v4K6/4K6x4K+BX+CupOCuv+CumeCvjeCuleCus+CvjV/grprgr4bgrrXgr43grrXgrr7grq/gr41f4K6q4K+B4K6k4K6p4K+NX+CuteCuv+Cur+CuvuCutOCuqeCvjV/grrXgr4bgrrPgr43grrPgrr9f4K6a4K6p4K6/Jy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ+CunuCuvl/grqTgrr9f4K6a4K+GX+CuquCvgV/grrXgrr9f4K614K+GX+Cumicuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSwgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+Cuh+CuqeCvjeCuseCvgV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vgrqjgrr7grrPgr4hdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCwgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vgrqjgr4fgrrHgr43grrHgr4FdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+CuleCun+CuqOCvjeCupCDgrrXgrr7grrDgrq7gr41dIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg4K6H4K6y4K+NJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDgrq7gr4Hgrqngr40nLFxuICAgICAgICAgICAgczogJ+CukuCusOCvgSDgrprgrr/grrIg4K614K6/4K6o4K6+4K6f4K6/4K6V4K6z4K+NJyxcbiAgICAgICAgICAgIHNzOiAnJWQg4K614K6/4K6o4K6+4K6f4K6/4K6V4K6z4K+NJyxcbiAgICAgICAgICAgIG06ICfgrpLgrrDgr4Eg4K6o4K6/4K6u4K6/4K6f4K6u4K+NJyxcbiAgICAgICAgICAgIG1tOiAnJWQg4K6o4K6/4K6u4K6/4K6f4K6Z4K+N4K6V4K6z4K+NJyxcbiAgICAgICAgICAgIGg6ICfgrpLgrrDgr4Eg4K6u4K6j4K6/IOCuqOCvh+CusOCuruCvjScsXG4gICAgICAgICAgICBoaDogJyVkIOCuruCuo+CuvyDgrqjgr4fgrrDgrq7gr40nLFxuICAgICAgICAgICAgZDogJ+CukuCusOCvgSDgrqjgrr7grrPgr40nLFxuICAgICAgICAgICAgZGQ6ICclZCDgrqjgrr7grp/gr43grpXgrrPgr40nLFxuICAgICAgICAgICAgTTogJ+CukuCusOCvgSDgrq7grr7grqTgrq7gr40nLFxuICAgICAgICAgICAgTU06ICclZCDgrq7grr7grqTgrpngr43grpXgrrPgr40nLFxuICAgICAgICAgICAgeTogJ+CukuCusOCvgSDgrrXgrrDgr4Hgrp/grq7gr40nLFxuICAgICAgICAgICAgeXk6ICclZCDgrobgrqPgr43grp/gr4HgrpXgrrPgr40nLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn3grrXgrqTgr4EvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+CuteCupOCvgSc7XG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgr6fgr6jgr6ngr6rgr6vgr6zgr63gr67gr6/gr6ZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkZlttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCRnW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICAvLyByZWZlciBodHRwOi8vdGEud2lraXBlZGlhLm9yZy9zLzFlcjFcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+Cur+CuvuCuruCuruCvjXzgrrXgr4jgrpXgrrHgr4h84K6V4K6+4K6y4K+IfOCuqOCuo+CvjeCuquCuleCusuCvjXzgro7grrHgr43grqrgrr7grp/gr4F84K6u4K6+4K6y4K+ILyxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAnIOCur+CuvuCuruCuruCvjSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCA2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcg4K614K+I4K6V4K6x4K+IJzsgLy8g4K614K+I4K6V4K6x4K+IXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnIOCuleCuvuCusuCviCc7IC8vIOCuleCuvuCusuCviFxuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyDgrqjgrqPgr43grqrgrpXgrrLgr40nOyAvLyDgrqjgrqPgr43grqrgrpXgrrLgr41cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcg4K6O4K6x4K+N4K6q4K6+4K6f4K+BJzsgLy8g4K6O4K6x4K+N4K6q4K6+4K6f4K+BXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAnIOCuruCuvuCusuCviCc7IC8vIOCuruCuvuCusuCviFxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyDgrq/grr7grq7grq7gr40nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgrq/grr7grq7grq7gr40nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCAyID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgrrXgr4jgrpXgrrHgr4gnIHx8IG1lcmlkaWVtID09PSAn4K6V4K6+4K6y4K+IJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CuqOCuo+CvjeCuquCuleCusuCvjScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDYsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndGUnLCB7XG4gICAgICAgIG1vbnRoczogJ+CwnOCwqOCwteCwsOCwv1/gsKvgsL/gsKzgsY3gsLDgsLXgsLDgsL9f4LCu4LC+4LCw4LGN4LCa4LC/X+Cwj+CwquCxjeCwsOCwv+CwsuCxjV/gsK7gsYdf4LCc4LGC4LCo4LGNX+CwnOCxgeCwsuCxiF/gsIbgsJfgsLjgsY3gsJ/gsYFf4LC44LGG4LCq4LGN4LCf4LGG4LCC4LCs4LCw4LGNX+CwheCwleCxjeCwn+Cxi+CwrOCwsOCxjV/gsKjgsLXgsILgsKzgsLDgsY1f4LCh4LC/4LC44LGG4LCC4LCs4LCw4LGNJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ+CwnOCwqC5f4LCr4LC/4LCs4LGN4LCwLl/gsK7gsL7gsLDgsY3gsJrgsL9f4LCP4LCq4LGN4LCw4LC/Ll/gsK7gsYdf4LCc4LGC4LCo4LGNX+CwnOCxgeCwsuCxiF/gsIbgsJcuX+CwuOCxhuCwquCxjS5f4LCF4LCV4LGN4LCf4LGLLl/gsKjgsLUuX+CwoeCwv+CwuOCxhi4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAn4LCG4LCm4LC/4LC14LC+4LCw4LCCX+CwuOCxi+CwruCwteCwvuCwsOCwgl/gsK7gsILgsJfgsLPgsLXgsL7gsLDgsIJf4LCs4LGB4LCn4LC14LC+4LCw4LCCX+Cwl+CxgeCwsOCxgeCwteCwvuCwsOCwgl/gsLbgsYHgsJXgsY3gsLDgsLXgsL7gsLDgsIJf4LC24LCo4LC/4LC14LC+4LCw4LCCJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn4LCG4LCm4LC/X+CwuOCxi+Cwrl/gsK7gsILgsJfgsLNf4LCs4LGB4LCnX+Cwl+CxgeCwsOCxgV/gsLbgsYHgsJXgsY3gsLBf4LC24LCo4LC/Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ+Cwhl/gsLjgsYtf4LCu4LCCX+CwrOCxgV/gsJfgsYFf4LC24LGBX+Cwticuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnQSBoOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0EgaDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vgsKjgsYfgsKHgsYFdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4LCw4LGH4LCq4LGBXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQsIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4LCo4LC/4LCo4LGN4LCoXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vgsJfgsKRdIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg4LCy4LGLJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDgsJXgsY3gsLDgsL/gsKTgsIInLFxuICAgICAgICAgICAgczogJ+CwleCxiuCwqOCxjeCwqOCwvyDgsJXgsY3gsLfgsKPgsL7gsLLgsYEnLFxuICAgICAgICAgICAgc3M6ICclZCDgsLjgsYbgsJXgsKjgsY3gsLLgsYEnLFxuICAgICAgICAgICAgbTogJ+CwkuCwlSDgsKjgsL/gsK7gsL/gsLfgsIInLFxuICAgICAgICAgICAgbW06ICclZCDgsKjgsL/gsK7gsL/gsLfgsL7gsLLgsYEnLFxuICAgICAgICAgICAgaDogJ+CwkuCwlSDgsJfgsILgsJ8nLFxuICAgICAgICAgICAgaGg6ICclZCDgsJfgsILgsJ/gsLLgsYEnLFxuICAgICAgICAgICAgZDogJ+CwkuCwlSDgsLDgsYvgsJzgsYEnLFxuICAgICAgICAgICAgZGQ6ICclZCDgsLDgsYvgsJzgsYHgsLLgsYEnLFxuICAgICAgICAgICAgTTogJ+CwkuCwlSDgsKjgsYbgsLInLFxuICAgICAgICAgICAgTU06ICclZCDgsKjgsYbgsLLgsLLgsYEnLFxuICAgICAgICAgICAgeTogJ+CwkuCwlSDgsLjgsILgsLXgsKTgsY3gsLjgsLDgsIInLFxuICAgICAgICAgICAgeXk6ICclZCDgsLjgsILgsLXgsKTgsY3gsLjgsLDgsL7gsLLgsYEnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn3gsLUvLFxuICAgICAgICBvcmRpbmFsOiAnJWTgsLUnLFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4LCw4LC+4LCk4LGN4LCw4LC/fOCwieCwpuCwr+CwgnzgsK7gsKfgsY3gsK/gsL7gsLngsY3gsKjgsIJ84LC44LC+4LCv4LCC4LCk4LGN4LCw4LCCLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4LCw4LC+4LCk4LGN4LCw4LC/Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LCJ4LCm4LCv4LCCJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CwruCwp+CxjeCwr+CwvuCwueCxjeCwqOCwgicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LC44LC+4LCv4LCC4LCk4LGN4LCw4LCCJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CwsOCwvuCwpOCxjeCwsOCwvyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LCJ4LCm4LCv4LCCJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgsK7gsKfgsY3gsK/gsL7gsLngsY3gsKjgsIInO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CwuOCwvuCwr+CwguCwpOCxjeCwsOCwgic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LCw4LC+4LCk4LGN4LCw4LC/JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNiwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0ZXQnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbmVpcnVfRmV2ZXJlaXJ1X01hcnN1X0FicmlsX01haXVfSnXDsXVfSnVsbHVfQWd1c3R1X1NldGVtYnJ1X091dHVicnVfTm92ZW1icnVfRGV6ZW1icnUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnSmFuX0Zldl9NYXJfQWJyX01haV9KdW5fSnVsX0Fnb19TZXRfT3V0X05vdl9EZXonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnRG9taW5ndV9TZWd1bmRhX1RlcnNhX0t1YXJ0YV9LaW50YV9TZXN0YV9TYWJhZHUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdEb21fU2VnX1RlcnNfS3VhX0tpbnRfU2VzdF9TYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnRG9fU2VnX1RlX0t1X0tpX1Nlc19TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tPaGluIGloYV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tBYmFuIGloYV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtpaGFdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbSG9yaXNlaWsgaWhhXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW3NlbWFuYSBrb3R1a10gW2loYV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdpaGEgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIGxpdWJhJyxcbiAgICAgICAgICAgIHM6ICdzZWd1bmR1IGJhbHVuJyxcbiAgICAgICAgICAgIHNzOiAnc2VndW5kdSAlZCcsXG4gICAgICAgICAgICBtOiAnbWludXR1IGlkYScsXG4gICAgICAgICAgICBtbTogJ21pbnV0dSAlZCcsXG4gICAgICAgICAgICBoOiAnb3JhcyBpZGEnLFxuICAgICAgICAgICAgaGg6ICdvcmFzICVkJyxcbiAgICAgICAgICAgIGQ6ICdsb3JvbiBpZGEnLFxuICAgICAgICAgICAgZGQ6ICdsb3JvbiAlZCcsXG4gICAgICAgICAgICBNOiAnZnVsYW4gaWRhJyxcbiAgICAgICAgICAgIE1NOiAnZnVsYW4gJWQnLFxuICAgICAgICAgICAgeTogJ3RpbmFuIGlkYScsXG4gICAgICAgICAgICB5eTogJ3RpbmFuICVkJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID1cbiAgICAgICAgICAgICAgICAgICAgfn4oKG51bWJlciAlIDEwMCkgLyAxMCkgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3RoJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdzdCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gMlxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnbmQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDNcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3JkJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiAndGgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN1ZmZpeGVzJDMgPSB7XG4gICAgICAgIDA6ICct0YPQvCcsXG4gICAgICAgIDE6ICct0YPQvCcsXG4gICAgICAgIDI6ICct0Y7QvCcsXG4gICAgICAgIDM6ICct0Y7QvCcsXG4gICAgICAgIDQ6ICct0YPQvCcsXG4gICAgICAgIDU6ICct0YPQvCcsXG4gICAgICAgIDY6ICct0YPQvCcsXG4gICAgICAgIDc6ICct0YPQvCcsXG4gICAgICAgIDg6ICct0YPQvCcsXG4gICAgICAgIDk6ICct0YPQvCcsXG4gICAgICAgIDEwOiAnLdGD0LwnLFxuICAgICAgICAxMjogJy3Rg9C8JyxcbiAgICAgICAgMTM6ICct0YPQvCcsXG4gICAgICAgIDIwOiAnLdGD0LwnLFxuICAgICAgICAzMDogJy3RjtC8JyxcbiAgICAgICAgNDA6ICct0YPQvCcsXG4gICAgICAgIDUwOiAnLdGD0LwnLFxuICAgICAgICA2MDogJy3Rg9C8JyxcbiAgICAgICAgNzA6ICct0YPQvCcsXG4gICAgICAgIDgwOiAnLdGD0LwnLFxuICAgICAgICA5MDogJy3Rg9C8JyxcbiAgICAgICAgMTAwOiAnLdGD0LwnLFxuICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3RnJywge1xuICAgICAgICBtb250aHM6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ9GP0L3QstCw0YDQuF/RhNC10LLRgNCw0LvQuF/QvNCw0YDRgtC4X9Cw0L/RgNC10LvQuF/QvNCw0LnQuF/QuNGO0L3QuF/QuNGO0LvQuF/QsNCy0LPRg9GB0YLQuF/RgdC10L3RgtGP0LHRgNC4X9C+0LrRgtGP0LHRgNC4X9C90L7Rj9Cx0YDQuF/QtNC10LrQsNCx0YDQuCcuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ9GP0L3QstCw0YBf0YTQtdCy0YDQsNC7X9C80LDRgNGCX9Cw0L/RgNC10Ltf0LzQsNC5X9C40Y7QvV/QuNGO0Ltf0LDQstCz0YPRgdGCX9GB0LXQvdGC0Y/QsdGAX9C+0LrRgtGP0LHRgF/QvdC+0Y/QsdGAX9C00LXQutCw0LHRgCcuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydDogJ9GP0L3Qsl/RhNC10LJf0LzQsNGAX9Cw0L/RgF/QvNCw0Llf0LjRjtC9X9C40Y7Qu1/QsNCy0LNf0YHQtdC9X9C+0LrRgl/QvdC+0Y9f0LTQtdC6Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ9GP0LrRiNCw0L3QsdC1X9C00YPRiNCw0L3QsdC1X9GB0LXRiNCw0L3QsdC1X9GH0L7RgNGI0LDQvdCx0LVf0L/QsNC90rfRiNCw0L3QsdC1X9K30YPQvNGK0LBf0YjQsNC90LHQtScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9GP0YjQsV/QtNGI0LFf0YHRiNCxX9GH0YjQsV/Qv9GI0LFf0rfRg9C8X9GI0L3QsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfRj9GIX9C00Yhf0YHRiF/Rh9GIX9C/0Yhf0rfQvF/RiNCxJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9CY0LzRgNOv0Lcg0YHQvtCw0YLQuF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vQpNCw0YDQtNC+INGB0L7QsNGC0LhdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb0JTQuNGA06/QtyDRgdC+0LDRgtC4XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGRb0LhdIFvSs9Cw0YTRgtCw0Lgg0L7Rj9C90LTQsCDRgdC+0LDRgtC4XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGRb0LhdIFvSs9Cw0YTRgtCw0Lgg0LPRg9C30LDRiNGC0LAg0YHQvtCw0YLQuF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICfQsdCw0YrQtNC4ICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDQv9C10YgnLFxuICAgICAgICAgICAgczogJ9GP0LrRh9Cw0L3QtCDRgdC+0L3QuNGPJyxcbiAgICAgICAgICAgIG06ICfRj9C6INC00LDSm9C40pvQsCcsXG4gICAgICAgICAgICBtbTogJyVkINC00LDSm9C40pvQsCcsXG4gICAgICAgICAgICBoOiAn0Y/QuiDRgdC+0LDRgicsXG4gICAgICAgICAgICBoaDogJyVkINGB0L7QsNGCJyxcbiAgICAgICAgICAgIGQ6ICfRj9C6INGA06/QtycsXG4gICAgICAgICAgICBkZDogJyVkINGA06/QtycsXG4gICAgICAgICAgICBNOiAn0Y/QuiDQvNC+0rMnLFxuICAgICAgICAgICAgTU06ICclZCDQvNC+0rMnLFxuICAgICAgICAgICAgeTogJ9GP0Log0YHQvtC7JyxcbiAgICAgICAgICAgIHl5OiAnJWQg0YHQvtC7JyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9GI0LDQsXzRgdGD0LHSs3zRgNOv0Ld80LHQtdCz0L7Ssy8sXG4gICAgICAgIG1lcmlkaWVtSG91cjogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ9GI0LDQsScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA8IDQgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ9GB0YPQsdKzJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ9GA06/QtycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn0LHQtdCz0L7SsycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfRiNCw0LEnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9GB0YPQsdKzJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfRgNOv0LcnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9Cx0LXQs9C+0rMnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9GI0LDQsSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0YPQvHzRjtC8KS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBhID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgYiA9IG51bWJlciA+PSAxMDAgPyAxMDAgOiBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChzdWZmaXhlcyQzW251bWJlcl0gfHwgc3VmZml4ZXMkM1thXSB8fCBzdWZmaXhlcyQzW2JdKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNywgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0aCcsIHtcbiAgICAgICAgbW9udGhzOiAn4Lih4LiB4Lij4Liy4LiE4LihX+C4geC4uOC4oeC4oOC4suC4nuC4seC4meC4mOC5jF/guKHguLXguJnguLLguITguKFf4LmA4Lih4Lip4Liy4Lii4LiZX+C4nuC4pOC4qeC4oOC4suC4hOC4oV/guKHguLTguJbguLjguJnguLLguKLguJlf4LiB4Lij4LiB4LiO4Liy4LiE4LihX+C4quC4tOC4h+C4q+C4suC4hOC4oV/guIHguLHguJnguKLguLLguKLguJlf4LiV4Li44Lil4Liy4LiE4LihX+C4nuC4pOC4qOC4iOC4tOC4geC4suC4ouC4mV/guJjguLHguJnguKfguLLguITguKEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn4LihLuC4hC5f4LiBLuC4ni5f4Lih4Li1LuC4hC5f4LmA4LihLuC4oi5f4LieLuC4hC5f4Lih4Li0LuC4oi5f4LiBLuC4hC5f4LiqLuC4hC5f4LiBLuC4oi5f4LiVLuC4hC5f4LieLuC4oi5f4LiYLuC4hC4nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAn4Lit4Liy4LiX4Li04LiV4Lii4LmMX+C4iOC4seC4meC4l+C4o+C5jF/guK3guLHguIfguITguLLguKNf4Lie4Li44LiYX+C4nuC4pOC4q+C4seC4quC4muC4lOC4tV/guKjguLjguIHguKPguYxf4LmA4Liq4Liy4Lij4LmMJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn4Lit4Liy4LiX4Li04LiV4Lii4LmMX+C4iOC4seC4meC4l+C4o+C5jF/guK3guLHguIfguITguLLguKNf4Lie4Li44LiYX+C4nuC4pOC4q+C4seC4ql/guKjguLjguIHguKPguYxf4LmA4Liq4Liy4Lij4LmMJy5zcGxpdCgnXycpLCAvLyB5ZXMsIHRocmVlIGNoYXJhY3RlcnMgZGlmZmVyZW5jZVxuICAgICAgICB3ZWVrZGF5c01pbjogJ+C4reC4si5f4LiILl/guK0uX+C4ni5f4Lie4LikLl/guKguX+C4qi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbScsXG4gICAgICAgICAgICBMVFM6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkg4LmA4Lin4Lil4LiyIEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ+C4p+C4seC4mWRkZGTguJfguLXguYggRCBNTU1NIFlZWVkg4LmA4Lin4Lil4LiyIEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4LiB4LmI4Lit4LiZ4LmA4LiX4Li14LmI4Lii4LiHfOC4q+C4peC4seC4h+C5gOC4l+C4teC5iOC4ouC4hy8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn4Lir4Lil4Lix4LiH4LmA4LiX4Li14LmI4Lii4LiHJztcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C4geC5iOC4reC4meC5gOC4l+C4teC5iOC4ouC4hyc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Lir4Lil4Lix4LiH4LmA4LiX4Li14LmI4Lii4LiHJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb4Lin4Lix4LiZ4LiZ4Li14LmJIOC5gOC4p+C4peC4sl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vguJ7guKPguLjguYjguIfguJnguLXguYkg4LmA4Lin4Lil4LiyXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGRb4Lir4LiZ4LmJ4LiyIOC5gOC4p+C4peC4sl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vguYDguKHguLfguYjguK3guKfguLLguJnguJnguLXguYkg4LmA4Lin4Lil4LiyXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vguKfguLHguJldZGRkZFvguJfguLXguYjguYHguKXguYnguKcg4LmA4Lin4Lil4LiyXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ+C4reC4teC4gSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXPguJfguLXguYjguYHguKXguYnguKcnLFxuICAgICAgICAgICAgczogJ+C5hOC4oeC5iOC4geC4teC5iOC4p+C4tOC4meC4suC4l+C4tScsXG4gICAgICAgICAgICBzczogJyVkIOC4p+C4tOC4meC4suC4l+C4tScsXG4gICAgICAgICAgICBtOiAnMSDguJnguLLguJfguLUnLFxuICAgICAgICAgICAgbW06ICclZCDguJnguLLguJfguLUnLFxuICAgICAgICAgICAgaDogJzEg4LiK4Lix4LmI4Lin4LmC4Lih4LiHJyxcbiAgICAgICAgICAgIGhoOiAnJWQg4LiK4Lix4LmI4Lin4LmC4Lih4LiHJyxcbiAgICAgICAgICAgIGQ6ICcxIOC4p+C4seC4mScsXG4gICAgICAgICAgICBkZDogJyVkIOC4p+C4seC4mScsXG4gICAgICAgICAgICB3OiAnMSDguKrguLHguJvguJTguLLguKvguYwnLFxuICAgICAgICAgICAgd3c6ICclZCDguKrguLHguJvguJTguLLguKvguYwnLFxuICAgICAgICAgICAgTTogJzEg4LmA4LiU4Li34Lit4LiZJyxcbiAgICAgICAgICAgIE1NOiAnJWQg4LmA4LiU4Li34Lit4LiZJyxcbiAgICAgICAgICAgIHk6ICcxIOC4m+C4tScsXG4gICAgICAgICAgICB5eTogJyVkIOC4m+C4tScsXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3VmZml4ZXMkNCA9IHtcbiAgICAgICAgMTogXCInaW5qaVwiLFxuICAgICAgICA1OiBcIidpbmppXCIsXG4gICAgICAgIDg6IFwiJ2luamlcIixcbiAgICAgICAgNzA6IFwiJ2luamlcIixcbiAgICAgICAgODA6IFwiJ2luamlcIixcbiAgICAgICAgMjogXCInbmppXCIsXG4gICAgICAgIDc6IFwiJ25qaVwiLFxuICAgICAgICAyMDogXCInbmppXCIsXG4gICAgICAgIDUwOiBcIiduamlcIixcbiAgICAgICAgMzogXCInw7xuamlcIixcbiAgICAgICAgNDogXCInw7xuamlcIixcbiAgICAgICAgMTAwOiBcIifDvG5qaVwiLFxuICAgICAgICA2OiBcIiduanlcIixcbiAgICAgICAgOTogXCIndW5qeVwiLFxuICAgICAgICAxMDogXCIndW5qeVwiLFxuICAgICAgICAzMDogXCIndW5qeVwiLFxuICAgICAgICA2MDogXCIneW5qeVwiLFxuICAgICAgICA5MDogXCIneW5qeVwiLFxuICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3RrJywge1xuICAgICAgICBtb250aHM6ICfDnWFud2FyX0Zld3JhbF9NYXJ0X0FwcmVsX01hw71fScO9dW5fScO9dWxfQXdndXN0X1NlbnTDvWFicl9Pa3TDvWFicl9Ob8O9YWJyX0Rla2Ficicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfDnWFuX0Zld19NYXJfQXByX01hw71fScO9bl9Jw71sX0F3Z19TZW5fT2t0X05vw71fRGVrJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ8OdZWvFn2VuYmVfRHXFn2VuYmVfU2nFn2VuYmVfw4dhcsWfZW5iZV9QZW7Fn2VuYmVfQW5uYV/FnmVuYmUnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfDnWVrX0R1xZ9fU2nFn1/Dh2FyX1Blbl9Bbm5fxZ5lbicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfDnWtfRMWfX1PFn1/Dh3JfUG5fQW5fxZ5uJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2J1Z8O8biBzYWdhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tlcnRpciBzYWdhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdbaW5kaWtpXSBkZGRkIFtzYWdhdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tkw7zDvW5dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW2dlw6dlbl0gZGRkZCBbc2FnYXRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMgc2/FiCcsXG4gICAgICAgICAgICBwYXN0OiAnJXMgw7bFiCcsXG4gICAgICAgICAgICBzOiAnYmlybsOkw6dlIHNla3VudCcsXG4gICAgICAgICAgICBtOiAnYmlyIG1pbnV0JyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludXQnLFxuICAgICAgICAgICAgaDogJ2JpciBzYWdhdCcsXG4gICAgICAgICAgICBoaDogJyVkIHNhZ2F0JyxcbiAgICAgICAgICAgIGQ6ICdiaXIgZ8O8bicsXG4gICAgICAgICAgICBkZDogJyVkIGfDvG4nLFxuICAgICAgICAgICAgTTogJ2JpciBhw70nLFxuICAgICAgICAgICAgTU06ICclZCBhw70nLFxuICAgICAgICAgICAgeTogJ2JpciDDvXlsJyxcbiAgICAgICAgICAgIHl5OiAnJWQgw715bCcsXG4gICAgICAgIH0sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEbyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREQnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNwZWNpYWwgY2FzZSBmb3IgemVyb1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIFwiJ3VuanlcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgYiA9IChudW1iZXIgJSAxMDApIC0gYSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChzdWZmaXhlcyQ0W2FdIHx8IHN1ZmZpeGVzJDRbYl0gfHwgc3VmZml4ZXMkNFtjXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndGwtcGgnLCB7XG4gICAgICAgIG1vbnRoczogJ0VuZXJvX1BlYnJlcm9fTWFyc29fQWJyaWxfTWF5b19IdW55b19IdWx5b19BZ29zdG9fU2V0eWVtYnJlX09rdHVicmVfTm9ieWVtYnJlX0Rpc3llbWJyZScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdFbmVfUGViX01hcl9BYnJfTWF5X0h1bl9IdWxfQWdvX1NldF9Pa3RfTm9iX0Rpcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICdMaW5nZ29fTHVuZXNfTWFydGVzX01peWVya3VsZXNfSHV3ZWJlc19CaXllcm5lc19TYWJhZG8nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdMaW5fTHVuX01hcl9NaXlfSHV3X0JpeV9TYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnTGlfTHVfTWFfTWlfSHVfQmlfU2FiJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnTU0vRC9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ01NTU0gRCwgWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgTU1NTSBERCwgWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnTFQgW25nYXlvbmcgYXJhd10nLFxuICAgICAgICAgICAgbmV4dERheTogJ1tCdWthcyBuZ10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdMVCBbc2Egc3VzdW5vZCBuYV0gZGRkZCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnTFQgW2thaGFwb25dJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnTFQgW25vb25nIG5ha2FyYWFuZ10gZGRkZCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ3NhIGxvb2IgbmcgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIGFuZyBuYWthbGlwYXMnLFxuICAgICAgICAgICAgczogJ2lsYW5nIHNlZ3VuZG8nLFxuICAgICAgICAgICAgc3M6ICclZCBzZWd1bmRvJyxcbiAgICAgICAgICAgIG06ICdpc2FuZyBtaW51dG8nLFxuICAgICAgICAgICAgbW06ICclZCBtaW51dG8nLFxuICAgICAgICAgICAgaDogJ2lzYW5nIG9yYXMnLFxuICAgICAgICAgICAgaGg6ICclZCBvcmFzJyxcbiAgICAgICAgICAgIGQ6ICdpc2FuZyBhcmF3JyxcbiAgICAgICAgICAgIGRkOiAnJWQgYXJhdycsXG4gICAgICAgICAgICBNOiAnaXNhbmcgYnV3YW4nLFxuICAgICAgICAgICAgTU06ICclZCBidXdhbicsXG4gICAgICAgICAgICB5OiAnaXNhbmcgdGFvbicsXG4gICAgICAgICAgICB5eTogJyVkIHRhb24nLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0vLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbnVtYmVyc05vdW5zID0gJ3BhZ2hfd2HigJlfY2hh4oCZX3dlal9sb1NfdmFnaF9qYXZfU29jaF9jaG9yZ2hfSHV0Jy5zcGxpdCgnXycpO1xuXG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlRnV0dXJlKG91dHB1dCkge1xuICAgICAgICB2YXIgdGltZSA9IG91dHB1dDtcbiAgICAgICAgdGltZSA9XG4gICAgICAgICAgICBvdXRwdXQuaW5kZXhPZignamFqJykgIT09IC0xXG4gICAgICAgICAgICAgICAgPyB0aW1lLnNsaWNlKDAsIC0zKSArICdsZVMnXG4gICAgICAgICAgICAgICAgOiBvdXRwdXQuaW5kZXhPZignamFyJykgIT09IC0xXG4gICAgICAgICAgICAgICAgPyB0aW1lLnNsaWNlKDAsIC0zKSArICd3YVEnXG4gICAgICAgICAgICAgICAgOiBvdXRwdXQuaW5kZXhPZignRElTJykgIT09IC0xXG4gICAgICAgICAgICAgICAgPyB0aW1lLnNsaWNlKDAsIC0zKSArICduZW0nXG4gICAgICAgICAgICAgICAgOiB0aW1lICsgJyBwSXEnO1xuICAgICAgICByZXR1cm4gdGltZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGVQYXN0KG91dHB1dCkge1xuICAgICAgICB2YXIgdGltZSA9IG91dHB1dDtcbiAgICAgICAgdGltZSA9XG4gICAgICAgICAgICBvdXRwdXQuaW5kZXhPZignamFqJykgIT09IC0xXG4gICAgICAgICAgICAgICAgPyB0aW1lLnNsaWNlKDAsIC0zKSArICdIdeKAmSdcbiAgICAgICAgICAgICAgICA6IG91dHB1dC5pbmRleE9mKCdqYXInKSAhPT0gLTFcbiAgICAgICAgICAgICAgICA/IHRpbWUuc2xpY2UoMCwgLTMpICsgJ3dlbidcbiAgICAgICAgICAgICAgICA6IG91dHB1dC5pbmRleE9mKCdESVMnKSAhPT0gLTFcbiAgICAgICAgICAgICAgICA/IHRpbWUuc2xpY2UoMCwgLTMpICsgJ2JlbidcbiAgICAgICAgICAgICAgICA6IHRpbWUgKyAnIHJldCc7XG4gICAgICAgIHJldHVybiB0aW1lO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZSRhKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgbnVtYmVyTm91biA9IG51bWJlckFzTm91bihudW1iZXIpO1xuICAgICAgICBzd2l0Y2ggKHN0cmluZykge1xuICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyBsdXAnO1xuICAgICAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyB0dXAnO1xuICAgICAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyByZXAnO1xuICAgICAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyBqYWonO1xuICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyBqYXInO1xuICAgICAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyBESVMnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbnVtYmVyQXNOb3VuKG51bWJlcikge1xuICAgICAgICB2YXIgaHVuZHJlZCA9IE1hdGguZmxvb3IoKG51bWJlciAlIDEwMDApIC8gMTAwKSxcbiAgICAgICAgICAgIHRlbiA9IE1hdGguZmxvb3IoKG51bWJlciAlIDEwMCkgLyAxMCksXG4gICAgICAgICAgICBvbmUgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIHdvcmQgPSAnJztcbiAgICAgICAgaWYgKGh1bmRyZWQgPiAwKSB7XG4gICAgICAgICAgICB3b3JkICs9IG51bWJlcnNOb3Vuc1todW5kcmVkXSArICd2YXRsaCc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRlbiA+IDApIHtcbiAgICAgICAgICAgIHdvcmQgKz0gKHdvcmQgIT09ICcnID8gJyAnIDogJycpICsgbnVtYmVyc05vdW5zW3Rlbl0gKyAnbWFIJztcbiAgICAgICAgfVxuICAgICAgICBpZiAob25lID4gMCkge1xuICAgICAgICAgICAgd29yZCArPSAod29yZCAhPT0gJycgPyAnICcgOiAnJykgKyBudW1iZXJzTm91bnNbb25lXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gd29yZCA9PT0gJycgPyAncGFnaCcgOiB3b3JkO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndGxoJywge1xuICAgICAgICBtb250aHM6ICd0ZXJh4oCZIGphciB3YeKAmV90ZXJh4oCZIGphciBjaGHigJlfdGVyYeKAmSBqYXIgd2VqX3RlcmHigJkgamFyIGxvU190ZXJh4oCZIGphciB2YWdoX3RlcmHigJkgamFyIGphdl90ZXJh4oCZIGphciBTb2NoX3RlcmHigJkgamFyIGNob3JnaF90ZXJh4oCZIGphciBIdXRfdGVyYeKAmSBqYXIgd2HigJltYUhfdGVyYeKAmSBqYXIgd2HigJltYUggd2HigJlfdGVyYeKAmSBqYXIgd2HigJltYUggY2hh4oCZJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ2phciB3YeKAmV9qYXIgY2hh4oCZX2phciB3ZWpfamFyIGxvU19qYXIgdmFnaF9qYXIgamF2X2phciBTb2NoX2phciBjaG9yZ2hfamFyIEh1dF9qYXIgd2HigJltYUhfamFyIHdh4oCZbWFIIHdh4oCZX2phciB3YeKAmW1hSCBjaGHigJknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnbG9qbUl0amFqX0RhU2phal9wb3ZqYWpfZ2hJdGxoamFqX2xvZ2hqYWpfYnVxamFqX2doSW5qYWonLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdsb2ptSXRqYWpfRGFTamFqX3Bvdmphal9naEl0bGhqYWpfbG9naGphal9idXFqYWpfZ2hJbmphaicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdsb2ptSXRqYWpfRGFTamFqX3Bvdmphal9naEl0bGhqYWpfbG9naGphal9idXFqYWpfZ2hJbmphaicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tEYUhqYWpdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbd2HigJlsZVNdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnTExMJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbd2HigJlIdeKAmV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdMTEwnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6IHRyYW5zbGF0ZUZ1dHVyZSxcbiAgICAgICAgICAgIHBhc3Q6IHRyYW5zbGF0ZVBhc3QsXG4gICAgICAgICAgICBzOiAncHVTIGx1cCcsXG4gICAgICAgICAgICBzczogdHJhbnNsYXRlJGEsXG4gICAgICAgICAgICBtOiAnd2HigJkgdHVwJyxcbiAgICAgICAgICAgIG1tOiB0cmFuc2xhdGUkYSxcbiAgICAgICAgICAgIGg6ICd3YeKAmSByZXAnLFxuICAgICAgICAgICAgaGg6IHRyYW5zbGF0ZSRhLFxuICAgICAgICAgICAgZDogJ3dh4oCZIGphaicsXG4gICAgICAgICAgICBkZDogdHJhbnNsYXRlJGEsXG4gICAgICAgICAgICBNOiAnd2HigJkgamFyJyxcbiAgICAgICAgICAgIE1NOiB0cmFuc2xhdGUkYSxcbiAgICAgICAgICAgIHk6ICd3YeKAmSBESVMnLFxuICAgICAgICAgICAgeXk6IHRyYW5zbGF0ZSRhLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN1ZmZpeGVzJDUgPSB7XG4gICAgICAgIDE6IFwiJ2luY2lcIixcbiAgICAgICAgNTogXCInaW5jaVwiLFxuICAgICAgICA4OiBcIidpbmNpXCIsXG4gICAgICAgIDcwOiBcIidpbmNpXCIsXG4gICAgICAgIDgwOiBcIidpbmNpXCIsXG4gICAgICAgIDI6IFwiJ25jaVwiLFxuICAgICAgICA3OiBcIiduY2lcIixcbiAgICAgICAgMjA6IFwiJ25jaVwiLFxuICAgICAgICA1MDogXCInbmNpXCIsXG4gICAgICAgIDM6IFwiJ8O8bmPDvFwiLFxuICAgICAgICA0OiBcIifDvG5jw7xcIixcbiAgICAgICAgMTAwOiBcIifDvG5jw7xcIixcbiAgICAgICAgNjogXCInbmPEsVwiLFxuICAgICAgICA5OiBcIid1bmN1XCIsXG4gICAgICAgIDEwOiBcIid1bmN1XCIsXG4gICAgICAgIDMwOiBcIid1bmN1XCIsXG4gICAgICAgIDYwOiBcIifEsW5jxLFcIixcbiAgICAgICAgOTA6IFwiJ8SxbmPEsVwiLFxuICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3RyJywge1xuICAgICAgICBtb250aHM6ICdPY2FrX8WedWJhdF9NYXJ0X05pc2FuX01hecSxc19IYXppcmFuX1RlbW11el9BxJ91c3Rvc19FeWzDvGxfRWtpbV9LYXPEsW1fQXJhbMSxaycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdPY2FfxZ51Yl9NYXJfTmlzX01heV9IYXpfVGVtX0HEn3VfRXlsX0VraV9LYXNfQXJhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ1BhemFyX1BhemFydGVzaV9TYWzEsV/Dh2FyxZ9hbWJhX1BlcsWfZW1iZV9DdW1hX0N1bWFydGVzaScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ1Bhel9QdHNfU2FsX8OHYXJfUGVyX0N1bV9DdHMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnUHpfUHRfU2Ffw4dhX1BlX0N1X0N0Jy5zcGxpdCgnXycpLFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ8O2w7YnIDogJ8OWw5YnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfDtnMnIDogJ8OWUyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/DtsO2fMOWw5Z8w7ZzfMOWUy8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09PSAnw7ZzJyB8fCBpbnB1dCA9PT0gJ8OWUyc7XG4gICAgICAgIH0sXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbYnVnw7xuIHNhYXRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbeWFyxLFuIHNhYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW2dlbGVjZWtdIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbZMO8bl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbZ2XDp2VuXSBkZGRkIFtzYWF0XSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJyVzIHNvbnJhJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDDtm5jZScsXG4gICAgICAgICAgICBzOiAnYmlya2HDpyBzYW5peWUnLFxuICAgICAgICAgICAgc3M6ICclZCBzYW5peWUnLFxuICAgICAgICAgICAgbTogJ2JpciBkYWtpa2EnLFxuICAgICAgICAgICAgbW06ICclZCBkYWtpa2EnLFxuICAgICAgICAgICAgaDogJ2JpciBzYWF0JyxcbiAgICAgICAgICAgIGhoOiAnJWQgc2FhdCcsXG4gICAgICAgICAgICBkOiAnYmlyIGfDvG4nLFxuICAgICAgICAgICAgZGQ6ICclZCBnw7xuJyxcbiAgICAgICAgICAgIHc6ICdiaXIgaGFmdGEnLFxuICAgICAgICAgICAgd3c6ICclZCBoYWZ0YScsXG4gICAgICAgICAgICBNOiAnYmlyIGF5JyxcbiAgICAgICAgICAgIE1NOiAnJWQgYXknLFxuICAgICAgICAgICAgeTogJ2JpciB5xLFsJyxcbiAgICAgICAgICAgIHl5OiAnJWQgecSxbCcsXG4gICAgICAgIH0sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEbyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREQnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNwZWNpYWwgY2FzZSBmb3IgemVyb1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIFwiJ8SxbmPEsVwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgICAgICAgICBiID0gKG51bWJlciAlIDEwMCkgLSBhLFxuICAgICAgICAgICAgICAgICAgICAgICAgYyA9IG51bWJlciA+PSAxMDAgPyAxMDAgOiBudWxsO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKHN1ZmZpeGVzJDVbYV0gfHwgc3VmZml4ZXMkNVtiXSB8fCBzdWZmaXhlcyQ1W2NdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNywgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgLy8gQWZ0ZXIgdGhlIHllYXIgdGhlcmUgc2hvdWxkIGJlIGEgc2xhc2ggYW5kIHRoZSBhbW91bnQgb2YgeWVhcnMgc2luY2UgRGVjZW1iZXIgMjYsIDE5NzkgaW4gUm9tYW4gbnVtZXJhbHMuXG4gICAgLy8gVGhpcyBpcyBjdXJyZW50bHkgdG9vIGRpZmZpY3VsdCAobWF5YmUgZXZlbiBpbXBvc3NpYmxlKSB0byBhZGQuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0emwnLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcl9GZXZyYWdsaF9NYXLDp19BdnLDr3VfTWFpX0fDvG5fSnVsaWFfR3VzY2h0X1NldGVtdmFyX0xpc3RvcMOkdHNfTm9lbXZhcl9aZWNlbXZhcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKYW5fRmV2X01hcl9BdnJfTWFpX0fDvG5fSnVsX0d1c19TZXRfTGlzX05vZV9aZWMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzOiAnU8O6bGFkaV9Mw7puZcOnaV9NYWl0emlfTcOhcmN1cmlfWGjDumFkaV9WacOpbmVyw6dpX1PDoXR1cmknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTw7psX0zDum5fTWFpX03DoXJfWGjDul9WacOpX1PDoXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnU8O6X0zDul9NYV9Nw6FfWGhfVmlfU8OhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISC5tbScsXG4gICAgICAgICAgICBMVFM6ICdISC5tbS5zcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QuIE1NTU0gW2RhbGxhc10gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdELiBNTU1NIFtkYWxsYXNdIFlZWVkgSEgubW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIFtsaV0gRC4gTU1NTSBbZGFsbGFzXSBZWVlZIEhILm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL2RcXCdvfGRcXCdhL2ksXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiZCdvXCIgPT09IGlucHV0LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VycyA+IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyBcImQnb1wiIDogXCJEJ09cIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyBcImQnYVwiIDogXCJEJ0FcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbb3hoaSDDoF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tkZW3DoCDDoF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvDoF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tpZWlyaSDDoF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbc8O8ciBlbF0gZGRkZCBbbGFzdGV1IMOgXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ29zcHJlaSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnamElcycsXG4gICAgICAgICAgICBzOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDgsXG4gICAgICAgICAgICBzczogcHJvY2Vzc1JlbGF0aXZlVGltZSQ4LFxuICAgICAgICAgICAgbTogcHJvY2Vzc1JlbGF0aXZlVGltZSQ4LFxuICAgICAgICAgICAgbW06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkOCxcbiAgICAgICAgICAgIGg6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkOCxcbiAgICAgICAgICAgIGhoOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDgsXG4gICAgICAgICAgICBkOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDgsXG4gICAgICAgICAgICBkZDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ4LFxuICAgICAgICAgICAgTTogcHJvY2Vzc1JlbGF0aXZlVGltZSQ4LFxuICAgICAgICAgICAgTU06IHByb2Nlc3NSZWxhdGl2ZVRpbWUkOCxcbiAgICAgICAgICAgIHk6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkOCxcbiAgICAgICAgICAgIHl5OiBwcm9jZXNzUmVsYXRpdmVUaW1lJDgsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWw6ICclZC4nLFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA0LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lJDgobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICBzOiBbJ3ZpZW5zYXMgc2VjdW5kcycsIFwiJ2llbnNhcyBzZWN1bmRzXCJdLFxuICAgICAgICAgICAgc3M6IFtudW1iZXIgKyAnIHNlY3VuZHMnLCAnJyArIG51bWJlciArICcgc2VjdW5kcyddLFxuICAgICAgICAgICAgbTogW1wiJ24gbcOtdXRcIiwgXCInaWVucyBtw611dFwiXSxcbiAgICAgICAgICAgIG1tOiBbbnVtYmVyICsgJyBtw611dHMnLCAnJyArIG51bWJlciArICcgbcOtdXRzJ10sXG4gICAgICAgICAgICBoOiBbXCInbiDDvm9yYVwiLCBcIidpZW5zYSDDvm9yYVwiXSxcbiAgICAgICAgICAgIGhoOiBbbnVtYmVyICsgJyDDvm9yYXMnLCAnJyArIG51bWJlciArICcgw75vcmFzJ10sXG4gICAgICAgICAgICBkOiBbXCInbiB6aXVhXCIsIFwiJ2llbnNhIHppdWFcIl0sXG4gICAgICAgICAgICBkZDogW251bWJlciArICcgeml1YXMnLCAnJyArIG51bWJlciArICcgeml1YXMnXSxcbiAgICAgICAgICAgIE06IFtcIiduIG1lc1wiLCBcIidpZW5zIG1lc1wiXSxcbiAgICAgICAgICAgIE1NOiBbbnVtYmVyICsgJyBtZXNlbicsICcnICsgbnVtYmVyICsgJyBtZXNlbiddLFxuICAgICAgICAgICAgeTogW1wiJ24gYXJcIiwgXCInaWVucyBhclwiXSxcbiAgICAgICAgICAgIHl5OiBbbnVtYmVyICsgJyBhcnMnLCAnJyArIG51bWJlciArICcgYXJzJ10sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBpc0Z1dHVyZVxuICAgICAgICAgICAgPyBmb3JtYXRba2V5XVswXVxuICAgICAgICAgICAgOiB3aXRob3V0U3VmZml4XG4gICAgICAgICAgICA/IGZvcm1hdFtrZXldWzBdXG4gICAgICAgICAgICA6IGZvcm1hdFtrZXldWzFdO1xuICAgIH1cblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndHptLWxhdG4nLCB7XG4gICAgICAgIG1vbnRoczogJ2lubmF5cl9icsukYXlyy6RfbWFyy6Rzy6RfaWJyaXJfbWF5eXdfeXdueXdfeXdseXd6X8mjd8WhdF/FoXd0YW5iaXJfa3TLpHdicsukX253d2FuYmlyX2R3am5iaXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnaW5uYXlyX2Jyy6RheXLLpF9tYXLLpHPLpF9pYnJpcl9tYXl5d195d255d195d2x5d3pfyaN3xaF0X8Whd3RhbmJpcl9rdMukd2Jyy6Rfbnd3YW5iaXJfZHdqbmJpcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICdhc2FtYXNfYXluYXNfYXNpbmFzX2FrcmFzX2Frd2FzX2FzaW13YXNfYXNp4biNeWFzJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnYXNhbWFzX2F5bmFzX2FzaW5hc19ha3Jhc19ha3dhc19hc2ltd2FzX2FzaeG4jXlhcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdhc2FtYXNfYXluYXNfYXNpbmFzX2FrcmFzX2Frd2FzX2FzaW13YXNfYXNp4biNeWFzJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbYXNka2ggZ10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1thc2thIGddIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbZ10gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1thc3NhbnQgZ10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFtnXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ2RhZGtoIHMgeWFuICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICd5YW4gJXMnLFxuICAgICAgICAgICAgczogJ2ltaWsnLFxuICAgICAgICAgICAgc3M6ICclZCBpbWlrJyxcbiAgICAgICAgICAgIG06ICdtaW514biNJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbWludeG4jScsXG4gICAgICAgICAgICBoOiAnc2HJm2EnLFxuICAgICAgICAgICAgaGg6ICclZCB0YXNzYcmbaW4nLFxuICAgICAgICAgICAgZDogJ2FzcycsXG4gICAgICAgICAgICBkZDogJyVkIG9zc2FuJyxcbiAgICAgICAgICAgIE06ICdheW93cicsXG4gICAgICAgICAgICBNTTogJyVkIGl5eWlybicsXG4gICAgICAgICAgICB5OiAnYXNnYXMnLFxuICAgICAgICAgICAgeXk6ICclZCBpc2dhc24nLFxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDEyLCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxMnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0em0nLCB7XG4gICAgICAgIG1vbnRoczogJ+K1ieK1j+K1j+K0sOK1ouK1lF/itLHitZXitLDitaLitZVf4rWO4rSw4rWV4rWaX+K1ieK0seK1lOK1ieK1lF/itY7itLDitaLitaLitZNf4rWi4rWT4rWP4rWi4rWTX+K1ouK1k+K1jeK1ouK1k+K1o1/itZbitZPitZvitZxf4rWb4rWT4rWc4rSw4rWP4rSx4rWJ4rWUX+K0veK1n+K1k+K0seK1lV/itY/itZPitaHitLDitY/itLHitYnitZRf4rS34rWT4rWK4rWP4rSx4rWJ4rWUJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJ+K1ieK1j+K1j+K0sOK1ouK1lF/itLHitZXitLDitaLitZVf4rWO4rSw4rWV4rWaX+K1ieK0seK1lOK1ieK1lF/itY7itLDitaLitaLitZNf4rWi4rWT4rWP4rWi4rWTX+K1ouK1k+K1jeK1ouK1k+K1o1/itZbitZPitZvitZxf4rWb4rWT4rWc4rSw4rWP4rSx4rWJ4rWUX+K0veK1n+K1k+K0seK1lV/itY/itZPitaHitLDitY/itLHitYnitZRf4rS34rWT4rWK4rWP4rSx4rWJ4rWUJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ+K0sOK1meK0sOK1juK0sOK1mV/itLDitaLitY/itLDitZlf4rSw4rWZ4rWJ4rWP4rSw4rWZX+K0sOK0veK1lOK0sOK1mV/itLDitL3itaHitLDitZlf4rSw4rWZ4rWJ4rWO4rWh4rSw4rWZX+K0sOK1meK1ieK0ueK1ouK0sOK1mScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+K0sOK1meK0sOK1juK0sOK1mV/itLDitaLitY/itLDitZlf4rSw4rWZ4rWJ4rWP4rSw4rWZX+K0sOK0veK1lOK0sOK1mV/itLDitL3itaHitLDitZlf4rSw4rWZ4rWJ4rWO4rWh4rSw4rWZX+K0sOK1meK1ieK0ueK1ouK0sOK1mScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfitLDitZnitLDitY7itLDitZlf4rSw4rWi4rWP4rSw4rWZX+K0sOK1meK1ieK1j+K0sOK1mV/itLDitL3itZTitLDitZlf4rSw4rS94rWh4rSw4rWZX+K0sOK1meK1ieK1juK1oeK0sOK1mV/itLDitZnitYnitLnitaLitLDitZknLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vitLDitZnitLfitYUg4rS0XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW+K0sOK1meK0veK0sCDitLRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb4rS0XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW+K0sOK1muK0sOK1j+K1nCDitLRdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb4rS0XSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ+K0t+K0sOK0t+K1hSDitZkg4rWi4rSw4rWPICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICfitaLitLDitY8gJXMnLFxuICAgICAgICAgICAgczogJ+K1ieK1juK1ieK0vScsXG4gICAgICAgICAgICBzczogJyVkIOK1ieK1juK1ieK0vScsXG4gICAgICAgICAgICBtOiAn4rWO4rWJ4rWP4rWT4rS6JyxcbiAgICAgICAgICAgIG1tOiAnJWQg4rWO4rWJ4rWP4rWT4rS6JyxcbiAgICAgICAgICAgIGg6ICfitZnitLDitYTitLAnLFxuICAgICAgICAgICAgaGg6ICclZCDitZzitLDitZnitZnitLDitYTitYnitY8nLFxuICAgICAgICAgICAgZDogJ+K0sOK1meK1mScsXG4gICAgICAgICAgICBkZDogJyVkIG/itZnitZnitLDitY8nLFxuICAgICAgICAgICAgTTogJ+K0sOK1om/itZPitZQnLFxuICAgICAgICAgICAgTU06ICclZCDitYnitaLitaLitYnitZTitY8nLFxuICAgICAgICAgICAgeTogJ+K0sOK1meK0s+K0sOK1mScsXG4gICAgICAgICAgICB5eTogJyVkIOK1ieK1meK0s+K0sOK1meK1jycsXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogNiwgLy8gU2F0dXJkYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogMTIsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDEydGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3VnLWNuJywge1xuICAgICAgICBtb250aHM6ICfZitin2Ybbi9in2LFf2YHbkNuL2LHYp9mEX9mF2KfYsdiqX9im2KfZvtix25DZhF/Zhdin2Ypf2KbZidmK24fZhl/YptmJ2Yrbh9mEX9im2Kfbi9i624fYs9iqX9iz25DZhtiq25XYqNmJ2LFf2KbbhtmD2Krbldio2YnYsV/ZhtmI2YrYp9io2YnYsV/Yr9uQ2YPYp9io2YnYsScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfZitin2Ybbi9in2LFf2YHbkNuL2LHYp9mEX9mF2KfYsdiqX9im2KfZvtix25DZhF/Zhdin2Ypf2KbZidmK24fZhl/YptmJ2Yrbh9mEX9im2Kfbi9i624fYs9iqX9iz25DZhtiq25XYqNmJ2LFf2KbbhtmD2Krbldio2YnYsV/ZhtmI2YrYp9io2YnYsV/Yr9uQ2YPYp9io2YnYsScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfZituV2YPYtNuV2YbYqNuVX9iv24jYtNuV2YbYqNuVX9iz25XZiti025XZhtio25Vf2obYp9ix2LTbldmG2KjblV/ZvtuV2YrYtNuV2YbYqNuVX9is24jZhduVX9i025XZhtio25UnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfZituVX9iv24hf2LPblV/ahtinX9m+25Vf2KzbiF/YtNuVJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9mK25Vf2K/biF/Ys9uVX9qG2Kdf2b7blV/YrNuIX9i025UnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgICAgIExMOiAnWVlZWS3ZitmJ2YTZiU0t2KbYp9mK2YbZidqtRC3Zg9uI2YbZiScsXG4gICAgICAgICAgICBMTEw6ICdZWVlZLdmK2YnZhNmJTS3Yptin2YrZhtmJ2q1ELdmD24jZhtmJ2IwgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGTYjCBZWVlZLdmK2YnZhNmJTS3Yptin2YrZhtmJ2q1ELdmD24jZhtmJ2IwgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv2YrbkNix2YnZhSDZg9uQ2obblXzYs9uV2r7bldixfNqG24jYtNiq2YnZhiDYqNuH2LHbh9mGfNqG24jYtHzahtuI2LTYqtmJ2YYg2YPbkNmK2YnZhnzZg9uV2oYvLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfZituQ2LHZidmFINmD25DahtuVJyB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn2LPbldq+25XYsScgfHxcbiAgICAgICAgICAgICAgICBtZXJpZGllbSA9PT0gJ9qG24jYtNiq2YnZhiDYqNuH2LHbh9mGJ1xuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn2obbiNi02KrZidmGINmD25DZitmJ2YYnIHx8IG1lcmlkaWVtID09PSAn2YPbldqGJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIHZhciBobSA9IGhvdXIgKiAxMDAgKyBtaW51dGU7XG4gICAgICAgICAgICBpZiAoaG0gPCA2MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9mK25DYsdmJ2YUg2YPbkNqG25UnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2LPbldq+25XYsSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTEzMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2obbiNi02KrZidmGINio24fYsduH2YYnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDEyMzApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9qG24jYtCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTgwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2obbiNi02KrZidmGINmD25DZitmJ2YYnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9mD25Xahic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9io24jar9uI2YYg2LPYp9im25XYql0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vYptuV2KrblSDYs9in2KbbldiqXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1vZg9uQ2YTbldix2YPZiV0gZGRkZCBb2LPYp9im25XYql0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYqtuG2YbbiNqv24jZhl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdb2KbYp9mE2K/ZidmG2YLZiV0gZGRkZCBb2LPYp9im25XYql0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclcyDZg9uQ2YrZidmGJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDYqNuH2LHbh9mGJyxcbiAgICAgICAgICAgIHM6ICfZhtuV2obahtuVINiz25DZg9mI2YbYqicsXG4gICAgICAgICAgICBzczogJyVkINiz25DZg9mI2YbYqicsXG4gICAgICAgICAgICBtOiAn2KjZidixINmF2YnZhtuH2KonLFxuICAgICAgICAgICAgbW06ICclZCDZhdmJ2Ybbh9iqJyxcbiAgICAgICAgICAgIGg6ICfYqNmJ2LEg2LPYp9im25XYqicsXG4gICAgICAgICAgICBoaDogJyVkINiz2KfYptuV2KonLFxuICAgICAgICAgICAgZDogJ9io2YnYsSDZg9uI2YYnLFxuICAgICAgICAgICAgZGQ6ICclZCDZg9uI2YYnLFxuICAgICAgICAgICAgTTogJ9io2YnYsSDYptin2YonLFxuICAgICAgICAgICAgTU06ICclZCDYptin2YonLFxuICAgICAgICAgICAgeTogJ9io2YnYsSDZitmJ2YQnLFxuICAgICAgICAgICAgeXk6ICclZCDZitmJ2YQnLFxuICAgICAgICB9LFxuXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSgt2YPbiNmG2Yl8Ldim2KfZinwt2r7bldm+2KrblSkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct2YPbiNmG2YknO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3avtuV2b7YqtuVJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC/YjC9nLCAnLCcpO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIC8vIEdCL1QgNzQwOC0xOTk044CK5pWw5o2u5YWD5ZKM5Lqk5o2i5qC85byPwrfkv6Hmga/kuqTmjaLCt+aXpeacn+WSjOaXtumXtOihqOekuuazleOAi+S4jklTTyA4NjAxOjE5ODjnrYnmlYhcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIHBsdXJhbCQ2KHdvcmQsIG51bSkge1xuICAgICAgICB2YXIgZm9ybXMgPSB3b3JkLnNwbGl0KCdfJyk7XG4gICAgICAgIHJldHVybiBudW0gJSAxMCA9PT0gMSAmJiBudW0gJSAxMDAgIT09IDExXG4gICAgICAgICAgICA/IGZvcm1zWzBdXG4gICAgICAgICAgICA6IG51bSAlIDEwID49IDIgJiYgbnVtICUgMTAgPD0gNCAmJiAobnVtICUgMTAwIDwgMTAgfHwgbnVtICUgMTAwID49IDIwKVxuICAgICAgICAgICAgPyBmb3Jtc1sxXVxuICAgICAgICAgICAgOiBmb3Jtc1syXTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICBzczogd2l0aG91dFN1ZmZpeCA/ICfRgdC10LrRg9C90LTQsF/RgdC10LrRg9C90LTQuF/RgdC10LrRg9C90LQnIDogJ9GB0LXQutGD0L3QtNGDX9GB0LXQutGD0L3QtNC4X9GB0LXQutGD0L3QtCcsXG4gICAgICAgICAgICBtbTogd2l0aG91dFN1ZmZpeCA/ICfRhdCy0LjQu9C40L3QsF/RhdCy0LjQu9C40L3QuF/RhdCy0LjQu9C40L0nIDogJ9GF0LLQuNC70LjQvdGDX9GF0LLQuNC70LjQvdC4X9GF0LLQuNC70LjQvScsXG4gICAgICAgICAgICBoaDogd2l0aG91dFN1ZmZpeCA/ICfQs9C+0LTQuNC90LBf0LPQvtC00LjQvdC4X9Cz0L7QtNC40L0nIDogJ9Cz0L7QtNC40L3Rg1/Qs9C+0LTQuNC90Lhf0LPQvtC00LjQvScsXG4gICAgICAgICAgICBkZDogJ9C00LXQvdGMX9C00L3Rll/QtNC90ZbQsicsXG4gICAgICAgICAgICBNTTogJ9C80ZbRgdGP0YbRjF/QvNGW0YHRj9GG0ZZf0LzRltGB0Y/RhtGW0LInLFxuICAgICAgICAgICAgeXk6ICfRgNGW0Lpf0YDQvtC60Lhf0YDQvtC60ZbQsicsXG4gICAgICAgIH07XG4gICAgICAgIGlmIChrZXkgPT09ICdtJykge1xuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAn0YXQstC40LvQuNC90LAnIDogJ9GF0LLQuNC70LjQvdGDJztcbiAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09ICdoJykge1xuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAn0LPQvtC00LjQvdCwJyA6ICfQs9C+0LTQuNC90YMnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgJyArIHBsdXJhbCQ2KGZvcm1hdFtrZXldLCArbnVtYmVyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiB3ZWVrZGF5c0Nhc2VSZXBsYWNlKG0sIGZvcm1hdCkge1xuICAgICAgICB2YXIgd2Vla2RheXMgPSB7XG4gICAgICAgICAgICAgICAgbm9taW5hdGl2ZTogJ9C90LXQtNGW0LvRj1/Qv9C+0L3QtdC00ZbQu9C+0Lpf0LLRltCy0YLQvtGA0L7Qul/RgdC10YDQtdC00LBf0YfQtdGC0LLQtdGAX9C/4oCZ0Y/RgtC90LjRhtGPX9GB0YPQsdC+0YLQsCcuc3BsaXQoXG4gICAgICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYWNjdXNhdGl2ZTogJ9C90LXQtNGW0LvRjl/Qv9C+0L3QtdC00ZbQu9C+0Lpf0LLRltCy0YLQvtGA0L7Qul/RgdC10YDQtdC00YNf0YfQtdGC0LLQtdGAX9C/4oCZ0Y/RgtC90LjRhtGOX9GB0YPQsdC+0YLRgycuc3BsaXQoXG4gICAgICAgICAgICAgICAgICAgICdfJ1xuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgZ2VuaXRpdmU6ICfQvdC10LTRltC70ZZf0L/QvtC90LXQtNGW0LvQutCwX9Cy0ZbQstGC0L7RgNC60LBf0YHQtdGA0LXQtNC4X9GH0LXRgtCy0LXRgNCz0LBf0L/igJnRj9GC0L3QuNGG0ZZf0YHRg9Cx0L7RgtC4Jy5zcGxpdChcbiAgICAgICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBub3VuQ2FzZTtcblxuICAgICAgICBpZiAobSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHdlZWtkYXlzWydub21pbmF0aXZlJ11cbiAgICAgICAgICAgICAgICAuc2xpY2UoMSwgNylcbiAgICAgICAgICAgICAgICAuY29uY2F0KHdlZWtkYXlzWydub21pbmF0aXZlJ10uc2xpY2UoMCwgMSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgcmV0dXJuIHdlZWtkYXlzWydub21pbmF0aXZlJ107XG4gICAgICAgIH1cblxuICAgICAgICBub3VuQ2FzZSA9IC8oXFxbW9CS0LLQo9GDXVxcXSkgP2RkZGQvLnRlc3QoZm9ybWF0KVxuICAgICAgICAgICAgPyAnYWNjdXNhdGl2ZSdcbiAgICAgICAgICAgIDogL1xcWz8oPzrQvNC40L3Rg9C70L7Rl3zQvdCw0YHRgtGD0L/QvdC+0ZcpPyA/XFxdID9kZGRkLy50ZXN0KGZvcm1hdClcbiAgICAgICAgICAgID8gJ2dlbml0aXZlJ1xuICAgICAgICAgICAgOiAnbm9taW5hdGl2ZSc7XG4gICAgICAgIHJldHVybiB3ZWVrZGF5c1tub3VuQ2FzZV1bbS5kYXkoKV07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKHN0cikge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHN0ciArICfQvicgKyAodGhpcy5ob3VycygpID09PSAxMSA/ICfQsScgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd1aycsIHtcbiAgICAgICAgbW9udGhzOiB7XG4gICAgICAgICAgICBmb3JtYXQ6ICfRgdGW0YfQvdGPX9C70Y7RgtC+0LPQvl/QsdC10YDQtdC30L3Rj1/QutCy0ZbRgtC90Y9f0YLRgNCw0LLQvdGPX9GH0LXRgNCy0L3Rj1/Qu9C40L/QvdGPX9GB0LXRgNC/0L3Rj1/QstC10YDQtdGB0L3Rj1/QttC+0LLRgtC90Y9f0LvQuNGB0YLQvtC/0LDQtNCwX9Cz0YDRg9C00L3Rjycuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ9GB0ZbRh9C10L3RjF/Qu9GO0YLQuNC5X9Cx0LXRgNC10LfQtdC90Yxf0LrQstGW0YLQtdC90Yxf0YLRgNCw0LLQtdC90Yxf0YfQtdGA0LLQtdC90Yxf0LvQuNC/0LXQvdGMX9GB0LXRgNC/0LXQvdGMX9Cy0LXRgNC10YHQtdC90Yxf0LbQvtCy0YLQtdC90Yxf0LvQuNGB0YLQvtC/0LDQtF/Qs9GA0YPQtNC10L3RjCcuc3BsaXQoXG4gICAgICAgICAgICAgICAgJ18nXG4gICAgICAgICAgICApLFxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydDogJ9GB0ZbRh1/Qu9GO0YJf0LHQtdGAX9C60LLRltGCX9GC0YDQsNCyX9GH0LXRgNCyX9C70LjQv1/RgdC10YDQv1/QstC10YBf0LbQvtCy0YJf0LvQuNGB0YJf0LPRgNGD0LQnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzOiB3ZWVrZGF5c0Nhc2VSZXBsYWNlLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn0L3QtF/Qv9C9X9Cy0YJf0YHRgF/Rh9GCX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfQvdC0X9C/0L1f0LLRgl/RgdGAX9GH0YJf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZINGALicsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSDRgC4sIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSDRgC4sIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0KHRjNC+0LPQvtC00L3RliAnKSxcbiAgICAgICAgICAgIG5leHREYXk6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0JfQsNCy0YLRgNCwICcpLFxuICAgICAgICAgICAgbGFzdERheTogcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQktGH0L7RgNCwICcpLFxuICAgICAgICAgICAgbmV4dFdlZWs6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0KNdIGRkZGQgWycpLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0JzQuNC90YPQu9C+0ZddIGRkZGQgWycpLmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQnNC40L3Rg9C70L7Qs9C+XSBkZGRkIFsnKS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9C30LAgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzINGC0L7QvNGDJyxcbiAgICAgICAgICAgIHM6ICfQtNC10LrRltC70YzQutCwINGB0LXQutGD0L3QtCcsXG4gICAgICAgICAgICBzczogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICAgICAgbTogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICAgICAgbW06IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkNCxcbiAgICAgICAgICAgIGg6ICfQs9C+0LTQuNC90YMnLFxuICAgICAgICAgICAgaGg6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkNCxcbiAgICAgICAgICAgIGQ6ICfQtNC10L3RjCcsXG4gICAgICAgICAgICBkZDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICAgICAgTTogJ9C80ZbRgdGP0YbRjCcsXG4gICAgICAgICAgICBNTTogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICAgICAgeTogJ9GA0ZbQuicsXG4gICAgICAgICAgICB5eTogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICB9LFxuICAgICAgICAvLyBNLiBFLjogdGhvc2UgdHdvIGFyZSB2aXJ0dWFsbHkgdW51c2VkIGJ1dCBhIHVzZXIgbWlnaHQgd2FudCB0byBpbXBsZW1lbnQgdGhlbSBmb3IgaGlzL2hlciB3ZWJzaXRlIGZvciBzb21lIHJlYXNvblxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv0L3QvtGH0ZZ80YDQsNC90LrRg3zQtNC90Y980LLQtdGH0L7RgNCwLyxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gL14o0LTQvdGPfNCy0LXRh9C+0YDQsCkkLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0L3QvtGH0ZYnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9GA0LDQvdC60YMnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9C00L3Rjyc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0LLQtdGH0L7RgNCwJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjQuXzQs9C+KS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QuSc7XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdCz0L4nO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBtb250aHMkYiA9IFtcbiAgICAgICAgICAgICfYrNmG2YjYsduMJyxcbiAgICAgICAgICAgICfZgdix2YjYsduMJyxcbiAgICAgICAgICAgICfZhdin2LHahicsXG4gICAgICAgICAgICAn2KfZvtix24zZhCcsXG4gICAgICAgICAgICAn2YXYptuMJyxcbiAgICAgICAgICAgICfYrNmI2YYnLFxuICAgICAgICAgICAgJ9is2YjZhNin2KbbjCcsXG4gICAgICAgICAgICAn2Kfar9iz2KonLFxuICAgICAgICAgICAgJ9iz2KrZhdio2LEnLFxuICAgICAgICAgICAgJ9in2qnYqtmI2KjYsScsXG4gICAgICAgICAgICAn2YbZiNmF2KjYsScsXG4gICAgICAgICAgICAn2K/Ys9mF2KjYsScsXG4gICAgICAgIF0sXG4gICAgICAgIGRheXMkMiA9IFsn2KfYqtmI2KfYsScsICfZvtuM2LEnLCAn2YXZhtqv2YQnLCAn2KjYr9q+JywgJ9is2YXYudix2KfYqicsICfYrNmF2LnbgScsICfbgdmB2KrbgSddO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd1cicsIHtcbiAgICAgICAgbW9udGhzOiBtb250aHMkYixcbiAgICAgICAgbW9udGhzU2hvcnQ6IG1vbnRocyRiLFxuICAgICAgICB3ZWVrZGF5czogZGF5cyQyLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiBkYXlzJDIsXG4gICAgICAgIHdlZWtkYXlzTWluOiBkYXlzJDIsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGTYjCBEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/Ytdio2K182LTYp9mFLyxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9i02KfZhScgPT09IGlucHV0O1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2LXYqNitJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAn2LTYp9mFJztcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb2KLYrCDYqNmI2YLYql0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vaqdmEINio2YjZgtiqXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW9io2YjZgtiqXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9qv2LDYtNiq24Eg2LHZiNiyINio2YjZgtiqXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1var9iw2LTYqtuBXSBkZGRkIFvYqNmI2YLYql0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclcyDYqNi52K8nLFxuICAgICAgICAgICAgcGFzdDogJyVzINmC2KjZhCcsXG4gICAgICAgICAgICBzOiAn2obZhtivINiz24zaqdmG2ognLFxuICAgICAgICAgICAgc3M6ICclZCDYs9uM2qnZhtqIJyxcbiAgICAgICAgICAgIG06ICfYp9uM2qkg2YXZhtm5JyxcbiAgICAgICAgICAgIG1tOiAnJWQg2YXZhtm5JyxcbiAgICAgICAgICAgIGg6ICfYp9uM2qkg2q/avtmG2bnbgScsXG4gICAgICAgICAgICBoaDogJyVkINqv2r7Zhtm525InLFxuICAgICAgICAgICAgZDogJ9in24zaqSDYr9mGJyxcbiAgICAgICAgICAgIGRkOiAnJWQg2K/ZhicsXG4gICAgICAgICAgICBNOiAn2KfbjNqpINmF2KfbgScsXG4gICAgICAgICAgICBNTTogJyVkINmF2KfbgScsXG4gICAgICAgICAgICB5OiAn2KfbjNqpINiz2KfZhCcsXG4gICAgICAgICAgICB5eTogJyVkINiz2KfZhCcsXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd1ei1sYXRuJywge1xuICAgICAgICBtb250aHM6ICdZYW52YXJfRmV2cmFsX01hcnRfQXByZWxfTWF5X0l5dW5fSXl1bF9Bdmd1c3RfU2VudGFicl9Pa3RhYnJfTm95YWJyX0Rla2Ficicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdZYW5fRmV2X01hcl9BcHJfTWF5X0l5dW5fSXl1bF9BdmdfU2VuX09rdF9Ob3lfRGVrJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ1lha3NoYW5iYV9EdXNoYW5iYV9TZXNoYW5iYV9DaG9yc2hhbmJhX1BheXNoYW5iYV9KdW1hX1NoYW5iYScuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ1lha19EdXNoX1Nlc2hfQ2hvcl9QYXlfSnVtX1NoYW4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnWWFfRHVfU2VfQ2hvX1BhX0p1X1NoYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnRCBNTU1NIFlZWVksIGRkZGQgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tCdWd1biBzb2F0XSBMVCBbZGFdJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbRXJ0YWdhXSBMVCBbZGFdJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBba3VuaSBzb2F0XSBMVCBbZGFdJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbS2VjaGEgc29hdF0gTFQgW2RhXScsXG4gICAgICAgICAgICBsYXN0V2VlazogXCJbTyd0Z2FuXSBkZGRkIFtrdW5pIHNvYXRdIExUIFtkYV1cIixcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnWWFxaW4gJXMgaWNoaWRhJyxcbiAgICAgICAgICAgIHBhc3Q6ICdCaXIgbmVjaGEgJXMgb2xkaW4nLFxuICAgICAgICAgICAgczogJ3Nvbml5YScsXG4gICAgICAgICAgICBzczogJyVkIHNvbml5YScsXG4gICAgICAgICAgICBtOiAnYmlyIGRhcWlxYScsXG4gICAgICAgICAgICBtbTogJyVkIGRhcWlxYScsXG4gICAgICAgICAgICBoOiAnYmlyIHNvYXQnLFxuICAgICAgICAgICAgaGg6ICclZCBzb2F0JyxcbiAgICAgICAgICAgIGQ6ICdiaXIga3VuJyxcbiAgICAgICAgICAgIGRkOiAnJWQga3VuJyxcbiAgICAgICAgICAgIE06ICdiaXIgb3knLFxuICAgICAgICAgICAgTU06ICclZCBveScsXG4gICAgICAgICAgICB5OiAnYmlyIHlpbCcsXG4gICAgICAgICAgICB5eTogJyVkIHlpbCcsXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDcsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndXonLCB7XG4gICAgICAgIG1vbnRoczogJ9GP0L3QstCw0YBf0YTQtdCy0YDQsNC7X9C80LDRgNGCX9Cw0L/RgNC10Ltf0LzQsNC5X9C40Y7QvV/QuNGO0Ltf0LDQstCz0YPRgdGCX9GB0LXQvdGC0Y/QsdGAX9C+0LrRgtGP0LHRgF/QvdC+0Y/QsdGAX9C00LXQutCw0LHRgCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfRj9C90LJf0YTQtdCyX9C80LDRgF/QsNC/0YBf0LzQsNC5X9C40Y7QvV/QuNGO0Ltf0LDQstCzX9GB0LXQvV/QvtC60YJf0L3QvtGPX9C00LXQuicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXM6ICfQr9C60YjQsNC90LHQsF/QlNGD0YjQsNC90LHQsF/QodC10YjQsNC90LHQsF/Qp9C+0YDRiNCw0L3QsdCwX9Cf0LDQudGI0LDQvdCx0LBf0JbRg9C80LBf0KjQsNC90LHQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9Cv0LrRiF/QlNGD0Yhf0KHQtdGIX9Cn0L7RgF/Qn9Cw0Llf0JbRg9C8X9Co0LDQvScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfQr9C6X9CU0YNf0KHQtV/Qp9C+X9Cf0LBf0JbRg1/QqNCwJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdEIE1NTU0gWVlZWSwgZGRkZCBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9CR0YPQs9GD0L0g0YHQvtCw0YJdIExUIFvQtNCwXScsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9Ct0YDRgtCw0LPQsF0gTFQgW9C00LBdJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb0LrRg9C90Lgg0YHQvtCw0YJdIExUIFvQtNCwXScsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9Ca0LXRh9CwINGB0L7QsNGCXSBMVCBb0LTQsF0nLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdb0KPRgtCz0LDQvV0gZGRkZCBb0LrRg9C90Lgg0YHQvtCw0YJdIExUIFvQtNCwXScsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJ9Cv0LrQuNC9ICVzINC40YfQuNC00LAnLFxuICAgICAgICAgICAgcGFzdDogJ9CR0LjRgCDQvdC10YfQsCAlcyDQvtC70LTQuNC9JyxcbiAgICAgICAgICAgIHM6ICfRhNGD0YDRgdCw0YInLFxuICAgICAgICAgICAgc3M6ICclZCDRhNGD0YDRgdCw0YInLFxuICAgICAgICAgICAgbTogJ9Cx0LjRgCDQtNCw0LrQuNC60LAnLFxuICAgICAgICAgICAgbW06ICclZCDQtNCw0LrQuNC60LAnLFxuICAgICAgICAgICAgaDogJ9Cx0LjRgCDRgdC+0LDRgicsXG4gICAgICAgICAgICBoaDogJyVkINGB0L7QsNGCJyxcbiAgICAgICAgICAgIGQ6ICfQsdC40YAg0LrRg9C9JyxcbiAgICAgICAgICAgIGRkOiAnJWQg0LrRg9C9JyxcbiAgICAgICAgICAgIE06ICfQsdC40YAg0L7QuScsXG4gICAgICAgICAgICBNTTogJyVkINC+0LknLFxuICAgICAgICAgICAgeTogJ9Cx0LjRgCDQudC40LsnLFxuICAgICAgICAgICAgeXk6ICclZCDQudC40LsnLFxuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA3LCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3ZpJywge1xuICAgICAgICBtb250aHM6ICd0aMOhbmcgMV90aMOhbmcgMl90aMOhbmcgM190aMOhbmcgNF90aMOhbmcgNV90aMOhbmcgNl90aMOhbmcgN190aMOhbmcgOF90aMOhbmcgOV90aMOhbmcgMTBfdGjDoW5nIDExX3Row6FuZyAxMicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdUaGcgMDFfVGhnIDAyX1RoZyAwM19UaGcgMDRfVGhnIDA1X1RoZyAwNl9UaGcgMDdfVGhnIDA4X1RoZyAwOV9UaGcgMTBfVGhnIDExX1RoZyAxMicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXM6ICdjaOG7pyBuaOG6rXRfdGjhu6kgaGFpX3Ro4bupIGJhX3Ro4bupIHTGsF90aOG7qSBuxINtX3Ro4bupIHPDoXVfdGjhu6kgYuG6o3knLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdDTl9UMl9UM19UNF9UNV9UNl9UNycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdDTl9UMl9UM19UNF9UNV9UNl9UNycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAvc2F8Y2gvaSxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gL15jaCQvaS50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXJzIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdzYScgOiAnU0EnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdjaCcgOiAnQ0gnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBbbsSDbV0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gW27Eg21dIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBbbsSDbV0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBsOiAnREQvTS9ZWVlZJyxcbiAgICAgICAgICAgIGxsOiAnRCBNTU0gWVlZWScsXG4gICAgICAgICAgICBsbGw6ICdEIE1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGw6ICdkZGQsIEQgTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tIw7RtIG5heSBsw7pjXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW05nw6B5IG1haSBsw7pjXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3R14bqnbiB04bubaSBsw7pjXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0jDtG0gcXVhIGzDumNdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbdHXhuqduIHRyxrDhu5tjIGzDumNdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMgdOG7m2knLFxuICAgICAgICAgICAgcGFzdDogJyVzIHRyxrDhu5tjJyxcbiAgICAgICAgICAgIHM6ICd2w6BpIGdpw6J5JyxcbiAgICAgICAgICAgIHNzOiAnJWQgZ2nDonknLFxuICAgICAgICAgICAgbTogJ23hu5l0IHBow7p0JyxcbiAgICAgICAgICAgIG1tOiAnJWQgcGjDunQnLFxuICAgICAgICAgICAgaDogJ23hu5l0IGdp4budJyxcbiAgICAgICAgICAgIGhoOiAnJWQgZ2nhu50nLFxuICAgICAgICAgICAgZDogJ23hu5l0IG5nw6B5JyxcbiAgICAgICAgICAgIGRkOiAnJWQgbmfDoHknLFxuICAgICAgICAgICAgdzogJ23hu5l0IHR14bqnbicsXG4gICAgICAgICAgICB3dzogJyVkIHR14bqnbicsXG4gICAgICAgICAgICBNOiAnbeG7mXQgdGjDoW5nJyxcbiAgICAgICAgICAgIE1NOiAnJWQgdGjDoW5nJyxcbiAgICAgICAgICAgIHk6ICdt4buZdCBuxINtJyxcbiAgICAgICAgICAgIHl5OiAnJWQgbsSDbScsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgneC1wc2V1ZG8nLCB7XG4gICAgICAgIG1vbnRoczogJ0p+w6HDscO6w6F+csO9X0Z+w6licsO6fsOhcsO9X35Nw6FyY35oX8OBcH5yw61sX35Nw6HDvV9+SsO6w7HDqX5fSsO6bH7DvV/DgcO6fmfDunN0fl9Tw6lwfnTDqW1ifsOpcl/Dk35jdMOzYn7DqXJfw5F+w7N2w6ltfmLDqXJffkTDqWPDqX5tYsOpcicuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdKfsOhw7FffkbDqWJffk3DoXJffsOBcHJffk3DocO9X35Kw7rDsV9+SsO6bF9+w4HDumdfflPDqXBffsOTY3RffsORw7N2X35Ew6ljJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ1N+w7rDsWTDoX7DvV9Nw7N+w7Fkw6HDvX5fVMO6w6l+c2TDocO9fl9Xw6lkfsOxw6lzZH7DocO9X1R+aMO6cnN+ZMOhw71ffkZyw61kfsOhw71fU37DoXTDunJ+ZMOhw70nLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTfsO6w7Fffk3Ds8OxX35Uw7rDqV9+V8OpZF9+VGjDul9+RnLDrV9+U8OhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdTfsO6X03Ds35fVMO6X35Xw6lfVH5oX0Zyfl9Tw6EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tUfsOzZMOhfsO9IMOhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tUfsOzbcOzfnJyw7N+dyDDoXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbw6F0XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW8OdfsOpc3R+w6lyZMOhfsO9IMOhdF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbTH7DoXN0XSBkZGRkIFvDoXRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnw61+w7EgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIMOhfmfDsycsXG4gICAgICAgICAgICBzOiAnw6EgfmbDqXcgfnPDqWPDs37DsWRzJyxcbiAgICAgICAgICAgIHNzOiAnJWQgc37DqWPDs8OxfmRzJyxcbiAgICAgICAgICAgIG06ICfDoSB+bcOtw7F+w7p0w6knLFxuICAgICAgICAgICAgbW06ICclZCBtfsOtw7HDun50w6lzJyxcbiAgICAgICAgICAgIGg6ICfDoX7DsSBow7N+w7pyJyxcbiAgICAgICAgICAgIGhoOiAnJWQgaH7Ds8O6cnMnLFxuICAgICAgICAgICAgZDogJ8OhIH5kw6HDvScsXG4gICAgICAgICAgICBkZDogJyVkIGR+w6HDvXMnLFxuICAgICAgICAgICAgTTogJ8OhIH5tw7PDsX50aCcsXG4gICAgICAgICAgICBNTTogJyVkIG1+w7PDsXR+aHMnLFxuICAgICAgICAgICAgeTogJ8OhIH7DvcOpw6FyJyxcbiAgICAgICAgICAgIHl5OiAnJWQgw71+w6nDoXJzJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHRofHN0fG5kfHJkKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID1cbiAgICAgICAgICAgICAgICAgICAgfn4oKG51bWJlciAlIDEwMCkgLyAxMCkgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3RoJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdzdCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gMlxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnbmQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDNcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ3JkJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiAndGgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCwgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd5bycsIHtcbiAgICAgICAgbW9udGhzOiAnU+G6ucyBcuG6ucyBX0XMgHJlzIBsZcyAX+G6uHLhurnMgG5hzIBfScyAZ2JlzIFfRcyAYmliaV9PzIBrdcyAZHVfQWfhurltb19PzIBndcyBbl9Pd2V3ZV/hu4zMgHdhzIByYcyAX0JlzIFsdcyBX+G7jMyAcOG6ucyAzIAnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnU+G6ucyBcl9FzIBybF/hurhybl9JzIBnYl9FzIBiaV9PzIBrdcyAX0Fn4bq5X0/MgGd1zIFfT3dlX+G7jMyAd2HMgF9CZcyBbF/hu4zMgHDhurnMgMyAJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ0HMgGnMgGt1zIFfQWplzIFfScyAc+G6ucyBZ3VuX+G7jGrhu43MgXJ1zIFf4buMauG7jcyBYuG7jV/hurh0acyAX0HMgGJhzIFt4bq5zIF0YScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ0HMgGnMgGtfQWplzIFfScyAc+G6ucyBX+G7jGpyX+G7jGpiX+G6uHRpzIBfQcyAYmHMgScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdBzIBpzIBfQWpfScyAc1/hu4xyX+G7jGJf4bq4dF9BzIBiJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdoOm1tIEEnLFxuICAgICAgICAgICAgTFRTOiAnaDptbTpzcyBBJyxcbiAgICAgICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnLFxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tPzIBuacyAIG5pXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW+G7jMyAbGEgbmldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiBcImRkZGQgW+G7jHPhurnMgCB0b8yBbidi4buNXSBbbmldIExUXCIsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0HMgG5hIG5pXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW+G7jHPhurnMgCB0b8yBbOG7jcyBXSBbbmldIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnbmnMgSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMga+G7jWphzIEnLFxuICAgICAgICAgICAgczogJ2nMgHPhurlqdcyBIGFheWHMgSBkaWUnLFxuICAgICAgICAgICAgc3M6ICdhYXlhzIEgJWQnLFxuICAgICAgICAgICAgbTogJ2nMgHPhurlqdcyBIGthbicsXG4gICAgICAgICAgICBtbTogJ2nMgHPhurlqdcyBICVkJyxcbiAgICAgICAgICAgIGg6ICd3YcyBa2F0aSBrYW4nLFxuICAgICAgICAgICAgaGg6ICd3YcyBa2F0aSAlZCcsXG4gICAgICAgICAgICBkOiAn4buNauG7jcyBIGthbicsXG4gICAgICAgICAgICBkZDogJ+G7jWrhu43MgSAlZCcsXG4gICAgICAgICAgICBNOiAnb3N1zIAga2FuJyxcbiAgICAgICAgICAgIE1NOiAnb3N1zIAgJWQnLFxuICAgICAgICAgICAgeTogJ+G7jWR1zIFuIGthbicsXG4gICAgICAgICAgICB5eTogJ+G7jWR1zIFuICVkJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL+G7jWrhu43MgVxcc1xcZHsxLDJ9LyxcbiAgICAgICAgb3JkaW5hbDogJ+G7jWrhu43MgSAlZCcsXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnemgtY24nLCB7XG4gICAgICAgIG1vbnRoczogJ+S4gOaciF/kuozmnIhf5LiJ5pyIX+Wbm+aciF/kupTmnIhf5YWt5pyIX+S4g+aciF/lhavmnIhf5Lmd5pyIX+WNgeaciF/ljYHkuIDmnIhf5Y2B5LqM5pyIJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ+aYn+acn+aXpV/mmJ/mnJ/kuIBf5pif5pyf5LqMX+aYn+acn+S4iV/mmJ/mnJ/lm5tf5pif5pyf5LqUX+aYn+acn+WFrScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+WRqOaXpV/lkajkuIBf5ZGo5LqMX+WRqOS4iV/lkajlm5tf5ZGo5LqUX+WRqOWFrScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfml6Vf5LiAX+S6jF/kuIlf5ZubX+S6lF/lha0nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdZWVlZL01NL0REJyxcbiAgICAgICAgICAgIExMOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgICAgIExMTDogJ1lZWVnlubRN5pyIROaXpUFo54K5bW3liIYnLFxuICAgICAgICAgICAgTExMTDogJ1lZWVnlubRN5pyIROaXpWRkZGRBaOeCuW1t5YiGJyxcbiAgICAgICAgICAgIGw6ICdZWVlZL00vRCcsXG4gICAgICAgICAgICBsbDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgICAgICBsbGw6ICdZWVlZ5bm0TeaciETml6UgSEg6bW0nLFxuICAgICAgICAgICAgbGxsbDogJ1lZWVnlubRN5pyIROaXpWRkZGQgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv5YeM5pmofOaXqeS4inzkuIrljYh85Lit5Y2IfOS4i+WNiHzmmZrkuIovLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICflh4zmmagnIHx8IG1lcmlkaWVtID09PSAn5pep5LiKJyB8fCBtZXJpZGllbSA9PT0gJ+S4iuWNiCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfkuIvljYgnIHx8IG1lcmlkaWVtID09PSAn5pma5LiKJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICfkuK3ljYgnXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgdmFyIGhtID0gaG91ciAqIDEwMCArIG1pbnV0ZTtcbiAgICAgICAgICAgIGlmIChobSA8IDYwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5YeM5pmoJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCA5MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+aXqeS4iic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTEzMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5LiK5Y2IJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCAxMjMwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfkuK3ljYgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDE4MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+S4i+WNiCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5pma5LiKJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb5LuK5aSpXUxUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb5piO5aSpXUxUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAobm93KSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vdy53ZWVrKCkgIT09IHRoaXMud2VlaygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW+S4i11kZGRMVCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb5pysXWRkZExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogJ1vmmKjlpKldTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uIChub3cpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53ZWVrKCkgIT09IG5vdy53ZWVrKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb5LiKXWRkZExUJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vmnKxdZGRkTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0o5pelfOaciHzlkagpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5pelJztcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfmnIgnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+WRqCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclc+WQjicsXG4gICAgICAgICAgICBwYXN0OiAnJXPliY0nLFxuICAgICAgICAgICAgczogJ+WHoOenkicsXG4gICAgICAgICAgICBzczogJyVkIOenkicsXG4gICAgICAgICAgICBtOiAnMSDliIbpkp8nLFxuICAgICAgICAgICAgbW06ICclZCDliIbpkp8nLFxuICAgICAgICAgICAgaDogJzEg5bCP5pe2JyxcbiAgICAgICAgICAgIGhoOiAnJWQg5bCP5pe2JyxcbiAgICAgICAgICAgIGQ6ICcxIOWkqScsXG4gICAgICAgICAgICBkZDogJyVkIOWkqScsXG4gICAgICAgICAgICB3OiAnMSDlkagnLFxuICAgICAgICAgICAgd3c6ICclZCDlkagnLFxuICAgICAgICAgICAgTTogJzEg5Liq5pyIJyxcbiAgICAgICAgICAgIE1NOiAnJWQg5Liq5pyIJyxcbiAgICAgICAgICAgIHk6ICcxIOW5tCcsXG4gICAgICAgICAgICB5eTogJyVkIOW5tCcsXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIC8vIEdCL1QgNzQwOC0xOTk044CK5pWw5o2u5YWD5ZKM5Lqk5o2i5qC85byPwrfkv6Hmga/kuqTmjaLCt+aXpeacn+WSjOaXtumXtOihqOekuuazleOAi+S4jklTTyA4NjAxOjE5ODjnrYnmlYhcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnemgtaGsnLCB7XG4gICAgICAgIG1vbnRoczogJ+S4gOaciF/kuozmnIhf5LiJ5pyIX+Wbm+aciF/kupTmnIhf5YWt5pyIX+S4g+aciF/lhavmnIhf5Lmd5pyIX+WNgeaciF/ljYHkuIDmnIhf5Y2B5LqM5pyIJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICBtb250aHNTaG9ydDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5czogJ+aYn+acn+aXpV/mmJ/mnJ/kuIBf5pif5pyf5LqMX+aYn+acn+S4iV/mmJ/mnJ/lm5tf5pif5pyf5LqUX+aYn+acn+WFrScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+mAseaXpV/pgLHkuIBf6YCx5LqMX+mAseS4iV/pgLHlm5tf6YCx5LqUX+mAseWFrScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfml6Vf5LiAX+S6jF/kuIlf5ZubX+S6lF/lha0nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdZWVlZL01NL0REJyxcbiAgICAgICAgICAgIExMOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgICAgIExMTDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbScsXG4gICAgICAgICAgICBsOiAnWVlZWS9NL0QnLFxuICAgICAgICAgICAgbGw6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICAgICAgbGxsOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGw6ICdZWVlZ5bm0TeaciETml6VkZGRkIEhIOm1tJyxcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+WHjOaZqHzml6nkuIp85LiK5Y2IfOS4reWNiHzkuIvljYh85pma5LiKLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn5YeM5pmoJyB8fCBtZXJpZGllbSA9PT0gJ+aXqeS4iicgfHwgbWVyaWRpZW0gPT09ICfkuIrljYgnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn5Lit5Y2IJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfkuIvljYgnIHx8IG1lcmlkaWVtID09PSAn5pma5LiKJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICB2YXIgaG0gPSBob3VyICogMTAwICsgbWludXRlO1xuICAgICAgICAgICAgaWYgKGhtIDwgNjAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICflh4zmmagnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5pep5LiKJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCAxMjAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfkuIrljYgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA9PT0gMTIwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5Lit5Y2IJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCAxODAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfkuIvljYgnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+aZmuS4iic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+S7iuWkqV1MVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW+aYjuWkqV1MVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1vkuItdZGRkZExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb5pio5aSpXUxUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+S4il1kZGRkTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KOaXpXzmnIh86YCxKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aXpSc7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5pyIJztcbiAgICAgICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfpgLEnO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXPlvownLFxuICAgICAgICAgICAgcGFzdDogJyVz5YmNJyxcbiAgICAgICAgICAgIHM6ICflub7np5InLFxuICAgICAgICAgICAgc3M6ICclZCDnp5InLFxuICAgICAgICAgICAgbTogJzEg5YiG6ZCYJyxcbiAgICAgICAgICAgIG1tOiAnJWQg5YiG6ZCYJyxcbiAgICAgICAgICAgIGg6ICcxIOWwj+aZgicsXG4gICAgICAgICAgICBoaDogJyVkIOWwj+aZgicsXG4gICAgICAgICAgICBkOiAnMSDlpKknLFxuICAgICAgICAgICAgZGQ6ICclZCDlpKknLFxuICAgICAgICAgICAgTTogJzEg5YCL5pyIJyxcbiAgICAgICAgICAgIE1NOiAnJWQg5YCL5pyIJyxcbiAgICAgICAgICAgIHk6ICcxIOW5tCcsXG4gICAgICAgICAgICB5eTogJyVkIOW5tCcsXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3poLW1vJywge1xuICAgICAgICBtb250aHM6ICfkuIDmnIhf5LqM5pyIX+S4ieaciF/lm5vmnIhf5LqU5pyIX+WFreaciF/kuIPmnIhf5YWr5pyIX+S5neaciF/ljYHmnIhf5Y2B5LiA5pyIX+WNgeS6jOaciCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICcx5pyIXzLmnIhfM+aciF805pyIXzXmnIhfNuaciF835pyIXzjmnIhfOeaciF8xMOaciF8xMeaciF8xMuaciCcuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgd2Vla2RheXM6ICfmmJ/mnJ/ml6Vf5pif5pyf5LiAX+aYn+acn+S6jF/mmJ/mnJ/kuIlf5pif5pyf5ZubX+aYn+acn+S6lF/mmJ/mnJ/lha0nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICfpgLHml6Vf6YCx5LiAX+mAseS6jF/pgLHkuIlf6YCx5ZubX+mAseS6lF/pgLHlha0nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAn5pelX+S4gF/kuoxf5LiJX+Wbm1/kupRf5YWtJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgICAgICBMTEw6ICdZWVlZ5bm0TeaciETml6UgSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ1lZWVnlubRN5pyIROaXpWRkZGQgSEg6bW0nLFxuICAgICAgICAgICAgbDogJ0QvTS9ZWVlZJyxcbiAgICAgICAgICAgIGxsOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgICAgIGxsbDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgICAgICBsbGxsOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbScsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/lh4zmmah85pep5LiKfOS4iuWNiHzkuK3ljYh85LiL5Y2IfOaZmuS4ii8sXG4gICAgICAgIG1lcmlkaWVtSG91cjogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+WHjOaZqCcgfHwgbWVyaWRpZW0gPT09ICfml6nkuIonIHx8IG1lcmlkaWVtID09PSAn5LiK5Y2IJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+S4reWNiCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn5LiL5Y2IJyB8fCBtZXJpZGllbSA9PT0gJ+aZmuS4iicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgdmFyIGhtID0gaG91ciAqIDEwMCArIG1pbnV0ZTtcbiAgICAgICAgICAgIGlmIChobSA8IDYwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5YeM5pmoJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCA5MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+aXqeS4iic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTEzMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5LiK5Y2IJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCAxMjMwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfkuK3ljYgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDE4MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+S4i+WNiCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5pma5LiKJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb5LuK5aSpXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW+aYjuWkqV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdb5LiLXWRkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vmmKjlpKldIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+S4il1kZGRkIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSjml6V85pyIfOmAsSkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfml6UnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aciCc7XG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn6YCxJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJyVz5YWnJyxcbiAgICAgICAgICAgIHBhc3Q6ICclc+WJjScsXG4gICAgICAgICAgICBzOiAn5bm+56eSJyxcbiAgICAgICAgICAgIHNzOiAnJWQg56eSJyxcbiAgICAgICAgICAgIG06ICcxIOWIhumQmCcsXG4gICAgICAgICAgICBtbTogJyVkIOWIhumQmCcsXG4gICAgICAgICAgICBoOiAnMSDlsI/mmYInLFxuICAgICAgICAgICAgaGg6ICclZCDlsI/mmYInLFxuICAgICAgICAgICAgZDogJzEg5aSpJyxcbiAgICAgICAgICAgIGRkOiAnJWQg5aSpJyxcbiAgICAgICAgICAgIE06ICcxIOWAi+aciCcsXG4gICAgICAgICAgICBNTTogJyVkIOWAi+aciCcsXG4gICAgICAgICAgICB5OiAnMSDlubQnLFxuICAgICAgICAgICAgeXk6ICclZCDlubQnLFxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd6aC10dycsIHtcbiAgICAgICAgbW9udGhzOiAn5LiA5pyIX+S6jOaciF/kuInmnIhf5Zub5pyIX+S6lOaciF/lha3mnIhf5LiD5pyIX+WFq+aciF/kuZ3mnIhf5Y2B5pyIX+WNgeS4gOaciF/ljYHkuozmnIgnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnMeaciF8y5pyIXzPmnIhfNOaciF815pyIXzbmnIhfN+aciF845pyIXznmnIhfMTDmnIhfMTHmnIhfMTLmnIgnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzOiAn5pif5pyf5pelX+aYn+acn+S4gF/mmJ/mnJ/kuoxf5pif5pyf5LiJX+aYn+acn+Wbm1/mmJ/mnJ/kupRf5pif5pyf5YWtJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn6YCx5pelX+mAseS4gF/pgLHkuoxf6YCx5LiJX+mAseWbm1/pgLHkupRf6YCx5YWtJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ+aXpV/kuIBf5LqMX+S4iV/lm5tf5LqUX+WFrScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ1lZWVkvTU0vREQnLFxuICAgICAgICAgICAgTEw6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICAgICAgTExMOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdZWVlZ5bm0TeaciETml6VkZGRkIEhIOm1tJyxcbiAgICAgICAgICAgIGw6ICdZWVlZL00vRCcsXG4gICAgICAgICAgICBsbDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgICAgICBsbGw6ICdZWVlZ5bm0TeaciETml6UgSEg6bW0nLFxuICAgICAgICAgICAgbGxsbDogJ1lZWVnlubRN5pyIROaXpWRkZGQgSEg6bW0nLFxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv5YeM5pmofOaXqeS4inzkuIrljYh85Lit5Y2IfOS4i+WNiHzmmZrkuIovLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICflh4zmmagnIHx8IG1lcmlkaWVtID09PSAn5pep5LiKJyB8fCBtZXJpZGllbSA9PT0gJ+S4iuWNiCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfkuK3ljYgnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+S4i+WNiCcgfHwgbWVyaWRpZW0gPT09ICfmmZrkuIonKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIHZhciBobSA9IGhvdXIgKiAxMDAgKyBtaW51dGU7XG4gICAgICAgICAgICBpZiAoaG0gPCA2MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+WHjOaZqCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgOTAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfml6nkuIonO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDExMzApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+S4iuWNiCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTIzMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5Lit5Y2IJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCAxODAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfkuIvljYgnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+aZmuS4iic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+S7iuWkqV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vmmI7lpKldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW+S4i11kZGRkIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb5pio5aSpXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vkuIpdZGRkZCBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0o5pelfOaciHzpgLEpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5pelJztcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfmnIgnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+mAsSc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclc+W+jCcsXG4gICAgICAgICAgICBwYXN0OiAnJXPliY0nLFxuICAgICAgICAgICAgczogJ+W5vuenkicsXG4gICAgICAgICAgICBzczogJyVkIOenkicsXG4gICAgICAgICAgICBtOiAnMSDliIbpkJgnLFxuICAgICAgICAgICAgbW06ICclZCDliIbpkJgnLFxuICAgICAgICAgICAgaDogJzEg5bCP5pmCJyxcbiAgICAgICAgICAgIGhoOiAnJWQg5bCP5pmCJyxcbiAgICAgICAgICAgIGQ6ICcxIOWkqScsXG4gICAgICAgICAgICBkZDogJyVkIOWkqScsXG4gICAgICAgICAgICBNOiAnMSDlgIvmnIgnLFxuICAgICAgICAgICAgTU06ICclZCDlgIvmnIgnLFxuICAgICAgICAgICAgeTogJzEg5bm0JyxcbiAgICAgICAgICAgIHl5OiAnJWQg5bm0JyxcbiAgICAgICAgfSxcbiAgICB9KTtcblxuICAgIGhvb2tzLmxvY2FsZSgnZW4nKTtcblxuICAgIHJldHVybiBob29rcztcblxufSkpKTtcbiIsIiFmdW5jdGlvbih0LGUpe1widXNlIHN0cmljdFwiO1wib2JqZWN0XCI9PXR5cGVvZiBtb2R1bGUmJm1vZHVsZS5leHBvcnRzP21vZHVsZS5leHBvcnRzPWUocmVxdWlyZShcIm1vbWVudFwiKSk6XCJmdW5jdGlvblwiPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShbXCJtb21lbnRcIl0sZSk6ZSh0Lm1vbWVudCl9KHRoaXMsZnVuY3Rpb24ocyl7XCJ1c2Ugc3RyaWN0XCI7dm9pZCAwPT09cy52ZXJzaW9uJiZzLmRlZmF1bHQmJihzPXMuZGVmYXVsdCk7dmFyIGUsaT17fSxmPXt9LHU9e30sYT17fSxjPXt9O3MmJlwic3RyaW5nXCI9PXR5cGVvZiBzLnZlcnNpb258fEQoXCJNb21lbnQgVGltZXpvbmUgcmVxdWlyZXMgTW9tZW50LmpzLiBTZWUgaHR0cHM6Ly9tb21lbnRqcy5jb20vdGltZXpvbmUvZG9jcy8jL3VzZS1pdC9icm93c2VyL1wiKTt2YXIgdD1zLnZlcnNpb24uc3BsaXQoXCIuXCIpLG49K3RbMF0sbz0rdFsxXTtmdW5jdGlvbiBsKHQpe3JldHVybiA5Njx0P3QtODc6NjQ8dD90LTI5OnQtNDh9ZnVuY3Rpb24gcih0KXt2YXIgZT0wLG49dC5zcGxpdChcIi5cIiksbz1uWzBdLHI9blsxXXx8XCJcIixzPTEsaT0wLGY9MTtmb3IoNDU9PT10LmNoYXJDb2RlQXQoMCkmJihmPS0oZT0xKSk7ZTxvLmxlbmd0aDtlKyspaT02MCppK2woby5jaGFyQ29kZUF0KGUpKTtmb3IoZT0wO2U8ci5sZW5ndGg7ZSsrKXMvPTYwLGkrPWwoci5jaGFyQ29kZUF0KGUpKSpzO3JldHVybiBpKmZ9ZnVuY3Rpb24gaCh0KXtmb3IodmFyIGU9MDtlPHQubGVuZ3RoO2UrKyl0W2VdPXIodFtlXSl9ZnVuY3Rpb24gcCh0LGUpe2Zvcih2YXIgbj1bXSxvPTA7bzxlLmxlbmd0aDtvKyspbltvXT10W2Vbb11dO3JldHVybiBufWZ1bmN0aW9uIG0odCl7dmFyIGU9dC5zcGxpdChcInxcIiksbj1lWzJdLnNwbGl0KFwiIFwiKSxvPWVbM10uc3BsaXQoXCJcIikscj1lWzRdLnNwbGl0KFwiIFwiKTtyZXR1cm4gaChuKSxoKG8pLGgociksZnVuY3Rpb24odCxlKXtmb3IodmFyIG49MDtuPGU7bisrKXRbbl09TWF0aC5yb3VuZCgodFtuLTFdfHwwKSs2ZTQqdFtuXSk7dFtlLTFdPTEvMH0ocixvLmxlbmd0aCkse25hbWU6ZVswXSxhYmJyczpwKGVbMV0uc3BsaXQoXCIgXCIpLG8pLG9mZnNldHM6cChuLG8pLHVudGlsczpyLHBvcHVsYXRpb246MHxlWzVdfX1mdW5jdGlvbiBkKHQpe3QmJnRoaXMuX3NldChtKHQpKX1mdW5jdGlvbiB6KHQsZSl7dGhpcy5uYW1lPXQsdGhpcy56b25lcz1lfWZ1bmN0aW9uIHYodCl7dmFyIGU9dC50b1RpbWVTdHJpbmcoKSxuPWUubWF0Y2goL1xcKFthLXogXStcXCkvaSk7XCJHTVRcIj09PShuPW4mJm5bMF0/KG49blswXS5tYXRjaCgvW0EtWl0vZykpP24uam9pbihcIlwiKTp2b2lkIDA6KG49ZS5tYXRjaCgvW0EtWl17Myw1fS9nKSk/blswXTp2b2lkIDApJiYobj12b2lkIDApLHRoaXMuYXQ9K3QsdGhpcy5hYmJyPW4sdGhpcy5vZmZzZXQ9dC5nZXRUaW1lem9uZU9mZnNldCgpfWZ1bmN0aW9uIGIodCl7dGhpcy56b25lPXQsdGhpcy5vZmZzZXRTY29yZT0wLHRoaXMuYWJiclNjb3JlPTB9ZnVuY3Rpb24gZygpe2Zvcih2YXIgdCxlLG49KG5ldyBEYXRlKS5nZXRGdWxsWWVhcigpLTIsbz1uZXcgdihuZXcgRGF0ZShuLDAsMSkpLHI9W29dLHM9MTtzPDQ4O3MrKykoZT1uZXcgdihuZXcgRGF0ZShuLHMsMSkpKS5vZmZzZXQhPT1vLm9mZnNldCYmKHQ9ZnVuY3Rpb24odCxlKXtmb3IodmFyIG4sbztvPTZlNCooKGUuYXQtdC5hdCkvMTJlNHwwKTspKG49bmV3IHYobmV3IERhdGUodC5hdCtvKSkpLm9mZnNldD09PXQub2Zmc2V0P3Q9bjplPW47cmV0dXJuIHR9KG8sZSksci5wdXNoKHQpLHIucHVzaChuZXcgdihuZXcgRGF0ZSh0LmF0KzZlNCkpKSksbz1lO2ZvcihzPTA7czw0O3MrKylyLnB1c2gobmV3IHYobmV3IERhdGUobitzLDAsMSkpKSxyLnB1c2gobmV3IHYobmV3IERhdGUobitzLDYsMSkpKTtyZXR1cm4gcn1mdW5jdGlvbiBfKHQsZSl7cmV0dXJuIHQub2Zmc2V0U2NvcmUhPT1lLm9mZnNldFNjb3JlP3Qub2Zmc2V0U2NvcmUtZS5vZmZzZXRTY29yZTp0LmFiYnJTY29yZSE9PWUuYWJiclNjb3JlP3QuYWJiclNjb3JlLWUuYWJiclNjb3JlOnQuem9uZS5wb3B1bGF0aW9uIT09ZS56b25lLnBvcHVsYXRpb24/ZS56b25lLnBvcHVsYXRpb24tdC56b25lLnBvcHVsYXRpb246ZS56b25lLm5hbWUubG9jYWxlQ29tcGFyZSh0LnpvbmUubmFtZSl9ZnVuY3Rpb24gdygpe3RyeXt2YXIgdD1JbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7aWYodCYmMzx0Lmxlbmd0aCl7dmFyIGU9YVt5KHQpXTtpZihlKXJldHVybiBlO0QoXCJNb21lbnQgVGltZXpvbmUgZm91bmQgXCIrdCtcIiBmcm9tIHRoZSBJbnRsIGFwaSwgYnV0IGRpZCBub3QgaGF2ZSB0aGF0IGRhdGEgbG9hZGVkLlwiKX19Y2F0Y2godCl7fWZvcih2YXIgbixvLHI9ZygpLHM9ci5sZW5ndGgsaT1mdW5jdGlvbih0KXtmb3IodmFyIGUsbixvPXQubGVuZ3RoLHI9e30scz1bXSxpPTA7aTxvO2krKylmb3IoZSBpbiBuPWNbdFtpXS5vZmZzZXRdfHx7fSluLmhhc093blByb3BlcnR5KGUpJiYocltlXT0hMCk7Zm9yKGkgaW4gcilyLmhhc093blByb3BlcnR5KGkpJiZzLnB1c2goYVtpXSk7cmV0dXJuIHN9KHIpLGY9W10sdT0wO3U8aS5sZW5ndGg7dSsrKXtmb3Iobj1uZXcgYihTKGlbdV0pKSxvPTA7bzxzO28rKyluLnNjb3JlT2Zmc2V0QXQocltvXSk7Zi5wdXNoKG4pfXJldHVybiBmLnNvcnQoXyksMDxmLmxlbmd0aD9mWzBdLnpvbmUubmFtZTp2b2lkIDB9ZnVuY3Rpb24geSh0KXtyZXR1cm4odHx8XCJcIikudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9cXC8vZyxcIl9cIil9ZnVuY3Rpb24gTyh0KXt2YXIgZSxuLG8scjtmb3IoXCJzdHJpbmdcIj09dHlwZW9mIHQmJih0PVt0XSksZT0wO2U8dC5sZW5ndGg7ZSsrKXI9eShuPShvPXRbZV0uc3BsaXQoXCJ8XCIpKVswXSksaVtyXT10W2VdLGFbcl09bixmdW5jdGlvbih0LGUpe3ZhciBuLG87Zm9yKGgoZSksbj0wO248ZS5sZW5ndGg7bisrKW89ZVtuXSxjW29dPWNbb118fHt9LGNbb11bdF09ITB9KHIsb1syXS5zcGxpdChcIiBcIikpfWZ1bmN0aW9uIFModCxlKXt0PXkodCk7dmFyIG4sbz1pW3RdO3JldHVybiBvIGluc3RhbmNlb2YgZD9vOlwic3RyaW5nXCI9PXR5cGVvZiBvPyhvPW5ldyBkKG8pLGlbdF09byk6Zlt0XSYmZSE9PVMmJihuPVMoZlt0XSxTKSk/KChvPWlbdF09bmV3IGQpLl9zZXQobiksby5uYW1lPWFbdF0sbyk6bnVsbH1mdW5jdGlvbiBNKHQpe3ZhciBlLG4sbyxyO2ZvcihcInN0cmluZ1wiPT10eXBlb2YgdCYmKHQ9W3RdKSxlPTA7ZTx0Lmxlbmd0aDtlKyspbz15KChuPXRbZV0uc3BsaXQoXCJ8XCIpKVswXSkscj15KG5bMV0pLGZbb109cixhW29dPW5bMF0sZltyXT1vLGFbcl09blsxXX1mdW5jdGlvbiBqKHQpe3JldHVybiBqLmRpZFNob3dFcnJvcnx8KGouZGlkU2hvd0Vycm9yPSEwLEQoXCJtb21lbnQudHouem9uZUV4aXN0cygnXCIrdCtcIicpIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgIW1vbWVudC50ei56b25lKCdcIit0K1wiJylcIikpLCEhUyh0KX1mdW5jdGlvbiBBKHQpe3ZhciBlPVwiWFwiPT09dC5fZnx8XCJ4XCI9PT10Ll9mO3JldHVybiEoIXQuX2F8fHZvaWQgMCE9PXQuX3R6bXx8ZSl9ZnVuY3Rpb24gRCh0KXtcInVuZGVmaW5lZFwiIT10eXBlb2YgY29uc29sZSYmXCJmdW5jdGlvblwiPT10eXBlb2YgY29uc29sZS5lcnJvciYmY29uc29sZS5lcnJvcih0KX1mdW5jdGlvbiBUKHQpe3ZhciBlPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywwLC0xKSxuPWFyZ3VtZW50c1thcmd1bWVudHMubGVuZ3RoLTFdLG89UyhuKSxyPXMudXRjLmFwcGx5KG51bGwsZSk7cmV0dXJuIG8mJiFzLmlzTW9tZW50KHQpJiZBKHIpJiZyLmFkZChvLnBhcnNlKHIpLFwibWludXRlc1wiKSxyLnR6KG4pLHJ9KG48Mnx8Mj09biYmbzw2KSYmRChcIk1vbWVudCBUaW1lem9uZSByZXF1aXJlcyBNb21lbnQuanMgPj0gMi42LjAuIFlvdSBhcmUgdXNpbmcgTW9tZW50LmpzIFwiK3MudmVyc2lvbitcIi4gU2VlIG1vbWVudGpzLmNvbVwiKSxkLnByb3RvdHlwZT17X3NldDpmdW5jdGlvbih0KXt0aGlzLm5hbWU9dC5uYW1lLHRoaXMuYWJicnM9dC5hYmJycyx0aGlzLnVudGlscz10LnVudGlscyx0aGlzLm9mZnNldHM9dC5vZmZzZXRzLHRoaXMucG9wdWxhdGlvbj10LnBvcHVsYXRpb259LF9pbmRleDpmdW5jdGlvbih0KXtmb3IodmFyIGU9K3Qsbj10aGlzLnVudGlscyxvPTA7bzxuLmxlbmd0aDtvKyspaWYoZTxuW29dKXJldHVybiBvfSxjb3VudHJpZXM6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLm5hbWU7cmV0dXJuIE9iamVjdC5rZXlzKHUpLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm4tMSE9PXVbdF0uem9uZXMuaW5kZXhPZihlKX0pfSxwYXJzZTpmdW5jdGlvbih0KXtmb3IodmFyIGUsbixvLHI9K3Qscz10aGlzLm9mZnNldHMsaT10aGlzLnVudGlscyxmPWkubGVuZ3RoLTEsdT0wO3U8Zjt1KyspaWYoZT1zW3VdLG49c1t1KzFdLG89c1t1P3UtMTp1XSxlPG4mJlQubW92ZUFtYmlndW91c0ZvcndhcmQ/ZT1uOm88ZSYmVC5tb3ZlSW52YWxpZEZvcndhcmQmJihlPW8pLHI8aVt1XS02ZTQqZSlyZXR1cm4gc1t1XTtyZXR1cm4gc1tmXX0sYWJicjpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5hYmJyc1t0aGlzLl9pbmRleCh0KV19LG9mZnNldDpmdW5jdGlvbih0KXtyZXR1cm4gRChcInpvbmUub2Zmc2V0IGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2Ygem9uZS51dGNPZmZzZXRcIiksdGhpcy5vZmZzZXRzW3RoaXMuX2luZGV4KHQpXX0sdXRjT2Zmc2V0OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLm9mZnNldHNbdGhpcy5faW5kZXgodCldfX0sYi5wcm90b3R5cGUuc2NvcmVPZmZzZXRBdD1mdW5jdGlvbih0KXt0aGlzLm9mZnNldFNjb3JlKz1NYXRoLmFicyh0aGlzLnpvbmUudXRjT2Zmc2V0KHQuYXQpLXQub2Zmc2V0KSx0aGlzLnpvbmUuYWJicih0LmF0KS5yZXBsYWNlKC9bXkEtWl0vZyxcIlwiKSE9PXQuYWJiciYmdGhpcy5hYmJyU2NvcmUrK30sVC52ZXJzaW9uPVwiMC41LjMyXCIsVC5kYXRhVmVyc2lvbj1cIlwiLFQuX3pvbmVzPWksVC5fbGlua3M9ZixULl9uYW1lcz1hLFQuX2NvdW50cmllcz11LFQuYWRkPU8sVC5saW5rPU0sVC5sb2FkPWZ1bmN0aW9uKHQpe08odC56b25lcyksTSh0LmxpbmtzKSxmdW5jdGlvbih0KXt2YXIgZSxuLG8scjtpZih0JiZ0Lmxlbmd0aClmb3IoZT0wO2U8dC5sZW5ndGg7ZSsrKW49KHI9dFtlXS5zcGxpdChcInxcIikpWzBdLnRvVXBwZXJDYXNlKCksbz1yWzFdLnNwbGl0KFwiIFwiKSx1W25dPW5ldyB6KG4sbyl9KHQuY291bnRyaWVzKSxULmRhdGFWZXJzaW9uPXQudmVyc2lvbn0sVC56b25lPVMsVC56b25lRXhpc3RzPWosVC5ndWVzcz1mdW5jdGlvbih0KXtyZXR1cm4gZSYmIXR8fChlPXcoKSksZX0sVC5uYW1lcz1mdW5jdGlvbigpe3ZhciB0LGU9W107Zm9yKHQgaW4gYSlhLmhhc093blByb3BlcnR5KHQpJiYoaVt0XXx8aVtmW3RdXSkmJmFbdF0mJmUucHVzaChhW3RdKTtyZXR1cm4gZS5zb3J0KCl9LFQuWm9uZT1kLFQudW5wYWNrPW0sVC51bnBhY2tCYXNlNjA9cixULm5lZWRzT2Zmc2V0PUEsVC5tb3ZlSW52YWxpZEZvcndhcmQ9ITAsVC5tb3ZlQW1iaWd1b3VzRm9yd2FyZD0hMSxULmNvdW50cmllcz1mdW5jdGlvbigpe3JldHVybiBPYmplY3Qua2V5cyh1KX0sVC56b25lc0ZvckNvdW50cnk9ZnVuY3Rpb24odCxlKXt2YXIgbjtpZihuPShuPXQpLnRvVXBwZXJDYXNlKCksISh0PXVbbl18fG51bGwpKXJldHVybiBudWxsO3ZhciBvPXQuem9uZXMuc29ydCgpO3JldHVybiBlP28ubWFwKGZ1bmN0aW9uKHQpe3JldHVybntuYW1lOnQsb2Zmc2V0OlModCkudXRjT2Zmc2V0KG5ldyBEYXRlKX19KTpvfTt2YXIgeCxDPXMuZm47ZnVuY3Rpb24gWih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fej90aGlzLl96LmFiYnIodGhpcyk6dC5jYWxsKHRoaXMpfX1mdW5jdGlvbiBrKHQpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0aGlzLl96PW51bGwsdC5hcHBseSh0aGlzLGFyZ3VtZW50cyl9fXMudHo9VCxzLmRlZmF1bHRab25lPW51bGwscy51cGRhdGVPZmZzZXQ9ZnVuY3Rpb24odCxlKXt2YXIgbixvLHI9cy5kZWZhdWx0Wm9uZTt2b2lkIDA9PT10Ll96JiYociYmQSh0KSYmIXQuX2lzVVRDJiYodC5fZD1zLnV0Yyh0Ll9hKS5fZCx0LnV0YygpLmFkZChyLnBhcnNlKHQpLFwibWludXRlc1wiKSksdC5fej1yKSx0Ll96JiYobz10Ll96LnV0Y09mZnNldCh0KSxNYXRoLmFicyhvKTwxNiYmKG8vPTYwKSx2b2lkIDAhPT10LnV0Y09mZnNldD8obj10Ll96LHQudXRjT2Zmc2V0KC1vLGUpLHQuX3o9bik6dC56b25lKG8sZSkpfSxDLnR6PWZ1bmN0aW9uKHQsZSl7aWYodCl7aWYoXCJzdHJpbmdcIiE9dHlwZW9mIHQpdGhyb3cgbmV3IEVycm9yKFwiVGltZSB6b25lIG5hbWUgbXVzdCBiZSBhIHN0cmluZywgZ290IFwiK3QrXCIgW1wiK3R5cGVvZiB0K1wiXVwiKTtyZXR1cm4gdGhpcy5fej1TKHQpLHRoaXMuX3o/cy51cGRhdGVPZmZzZXQodGhpcyxlKTpEKFwiTW9tZW50IFRpbWV6b25lIGhhcyBubyBkYXRhIGZvciBcIit0K1wiLiBTZWUgaHR0cDovL21vbWVudGpzLmNvbS90aW1lem9uZS9kb2NzLyMvZGF0YS1sb2FkaW5nLy5cIiksdGhpc31pZih0aGlzLl96KXJldHVybiB0aGlzLl96Lm5hbWV9LEMuem9uZU5hbWU9WihDLnpvbmVOYW1lKSxDLnpvbmVBYmJyPVooQy56b25lQWJiciksQy51dGM9ayhDLnV0YyksQy5sb2NhbD1rKEMubG9jYWwpLEMudXRjT2Zmc2V0PSh4PUMudXRjT2Zmc2V0LGZ1bmN0aW9uKCl7cmV0dXJuIDA8YXJndW1lbnRzLmxlbmd0aCYmKHRoaXMuX3o9bnVsbCkseC5hcHBseSh0aGlzLGFyZ3VtZW50cyl9KSxzLnR6LnNldERlZmF1bHQ9ZnVuY3Rpb24odCl7cmV0dXJuKG48Mnx8Mj09biYmbzw5KSYmRChcIk1vbWVudCBUaW1lem9uZSBzZXREZWZhdWx0KCkgcmVxdWlyZXMgTW9tZW50LmpzID49IDIuOS4wLiBZb3UgYXJlIHVzaW5nIE1vbWVudC5qcyBcIitzLnZlcnNpb24rXCIuXCIpLHMuZGVmYXVsdFpvbmU9dD9TKHQpOm51bGwsc307dmFyIEY9cy5tb21lbnRQcm9wZXJ0aWVzO3JldHVyblwiW29iamVjdCBBcnJheV1cIj09PU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChGKT8oRi5wdXNoKFwiX3pcIiksRi5wdXNoKFwiX2FcIikpOkYmJihGLl96PW51bGwpLHN9KTsiLCJ2YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG4vLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIEluY29uc2lzdGVudE5hbWluZ1xudmFyIERhdGVUaW1lUGlja2VyID0gZnVuY3Rpb24gKCQsIG1vbWVudCkge1xuICAgIGZ1bmN0aW9uIGVzY2FwZVJlZ0V4cCh0ZXh0KSB7XG4gICAgICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoL1stW1xcXXt9KCkqKz8uLFxcXFxeJHwjXFxzXS9nLCAnXFxcXCQmJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNWYWxpZERhdGUoZGF0ZSkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGUpID09PSAnW29iamVjdCBEYXRlXScgJiYgIWlzTmFOKGRhdGUuZ2V0VGltZSgpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkRGF0ZVRpbWVTdHIoc3RyKSB7XG4gICAgICAgIHJldHVybiBpc1ZhbGlkRGF0ZShuZXcgRGF0ZShzdHIpKTtcbiAgICB9XG5cbiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBJbmNvbnNpc3RlbnROYW1pbmdcbiAgICB2YXIgdHJpbSA9IGZ1bmN0aW9uIHRyaW0oc3RyKSB7XG4gICAgICAgIHJldHVybiBzdHIucmVwbGFjZSgvKF5cXHMrKXwoXFxzKyQpL2csICcnKTtcbiAgICB9LFxuICAgICAgICBOQU1FID0gJ2RhdGV0aW1lcGlja2VyJyxcbiAgICAgICAgREFUQV9LRVkgPSAnJyArIE5BTUUsXG4gICAgICAgIEVWRU5UX0tFWSA9ICcuJyArIERBVEFfS0VZLFxuICAgICAgICBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJyxcbiAgICAgICAgU2VsZWN0b3IgPSB7XG4gICAgICAgIERBVEFfVE9HR0xFOiAnW2RhdGEtdG9nZ2xlPVwiJyArIERBVEFfS0VZICsgJ1wiXSdcbiAgICB9LFxuICAgICAgICBDbGFzc05hbWUgPSB7XG4gICAgICAgIElOUFVUOiBOQU1FICsgJy1pbnB1dCdcbiAgICB9LFxuICAgICAgICBFdmVudCA9IHtcbiAgICAgICAgQ0hBTkdFOiAnY2hhbmdlJyArIEVWRU5UX0tFWSxcbiAgICAgICAgQkxVUjogJ2JsdXInICsgRVZFTlRfS0VZLFxuICAgICAgICBLRVlVUDogJ2tleXVwJyArIEVWRU5UX0tFWSxcbiAgICAgICAgS0VZRE9XTjogJ2tleWRvd24nICsgRVZFTlRfS0VZLFxuICAgICAgICBGT0NVUzogJ2ZvY3VzJyArIEVWRU5UX0tFWSxcbiAgICAgICAgQ0xJQ0tfREFUQV9BUEk6ICdjbGljaycgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVksXG4gICAgICAgIC8vZW1pdHRlZFxuICAgICAgICBVUERBVEU6ICd1cGRhdGUnICsgRVZFTlRfS0VZLFxuICAgICAgICBFUlJPUjogJ2Vycm9yJyArIEVWRU5UX0tFWSxcbiAgICAgICAgSElERTogJ2hpZGUnICsgRVZFTlRfS0VZLFxuICAgICAgICBTSE9XOiAnc2hvdycgKyBFVkVOVF9LRVlcbiAgICB9LFxuICAgICAgICBEYXRlUGlja2VyTW9kZXMgPSBbe1xuICAgICAgICBDTEFTU19OQU1FOiAnZGF5cycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ00nLFxuICAgICAgICBOQVZfU1RFUDogMVxuICAgIH0sIHtcbiAgICAgICAgQ0xBU1NfTkFNRTogJ21vbnRocycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ3knLFxuICAgICAgICBOQVZfU1RFUDogMVxuICAgIH0sIHtcbiAgICAgICAgQ0xBU1NfTkFNRTogJ3llYXJzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAneScsXG4gICAgICAgIE5BVl9TVEVQOiAxMFxuICAgIH0sIHtcbiAgICAgICAgQ0xBU1NfTkFNRTogJ2RlY2FkZXMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICAgICAgTkFWX1NURVA6IDEwMFxuICAgIH1dLFxuICAgICAgICBLZXlNYXAgPSB7XG4gICAgICAgICd1cCc6IDM4LFxuICAgICAgICAzODogJ3VwJyxcbiAgICAgICAgJ2Rvd24nOiA0MCxcbiAgICAgICAgNDA6ICdkb3duJyxcbiAgICAgICAgJ2xlZnQnOiAzNyxcbiAgICAgICAgMzc6ICdsZWZ0JyxcbiAgICAgICAgJ3JpZ2h0JzogMzksXG4gICAgICAgIDM5OiAncmlnaHQnLFxuICAgICAgICAndGFiJzogOSxcbiAgICAgICAgOTogJ3RhYicsXG4gICAgICAgICdlc2NhcGUnOiAyNyxcbiAgICAgICAgMjc6ICdlc2NhcGUnLFxuICAgICAgICAnZW50ZXInOiAxMyxcbiAgICAgICAgMTM6ICdlbnRlcicsXG4gICAgICAgICdwYWdlVXAnOiAzMyxcbiAgICAgICAgMzM6ICdwYWdlVXAnLFxuICAgICAgICAncGFnZURvd24nOiAzNCxcbiAgICAgICAgMzQ6ICdwYWdlRG93bicsXG4gICAgICAgICdzaGlmdCc6IDE2LFxuICAgICAgICAxNjogJ3NoaWZ0JyxcbiAgICAgICAgJ2NvbnRyb2wnOiAxNyxcbiAgICAgICAgMTc6ICdjb250cm9sJyxcbiAgICAgICAgJ3NwYWNlJzogMzIsXG4gICAgICAgIDMyOiAnc3BhY2UnLFxuICAgICAgICAndCc6IDg0LFxuICAgICAgICA4NDogJ3QnLFxuICAgICAgICAnZGVsZXRlJzogNDYsXG4gICAgICAgIDQ2OiAnZGVsZXRlJ1xuICAgIH0sXG4gICAgICAgIFZpZXdNb2RlcyA9IFsndGltZXMnLCAnZGF5cycsICdtb250aHMnLCAneWVhcnMnLCAnZGVjYWRlcyddLFxuICAgICAgICBrZXlTdGF0ZSA9IHt9LFxuICAgICAgICBrZXlQcmVzc0hhbmRsZWQgPSB7fSxcbiAgICAgICAgb3B0aW9uc1NvcnRNYXAgPSB7XG4gICAgICAgIHRpbWVab25lOiAtMzksXG4gICAgICAgIGZvcm1hdDogLTM4LFxuICAgICAgICBkYXlWaWV3SGVhZGVyRm9ybWF0OiAtMzcsXG4gICAgICAgIGV4dHJhRm9ybWF0czogLTM2LFxuICAgICAgICBzdGVwcGluZzogLTM1LFxuICAgICAgICBtaW5EYXRlOiAtMzQsXG4gICAgICAgIG1heERhdGU6IC0zMyxcbiAgICAgICAgdXNlQ3VycmVudDogLTMyLFxuICAgICAgICBjb2xsYXBzZTogLTMxLFxuICAgICAgICBsb2NhbGU6IC0zMCxcbiAgICAgICAgZGVmYXVsdERhdGU6IC0yOSxcbiAgICAgICAgZGlzYWJsZWREYXRlczogLTI4LFxuICAgICAgICBlbmFibGVkRGF0ZXM6IC0yNyxcbiAgICAgICAgaWNvbnM6IC0yNixcbiAgICAgICAgdG9vbHRpcHM6IC0yNSxcbiAgICAgICAgdXNlU3RyaWN0OiAtMjQsXG4gICAgICAgIHNpZGVCeVNpZGU6IC0yMyxcbiAgICAgICAgZGF5c09mV2Vla0Rpc2FibGVkOiAtMjIsXG4gICAgICAgIGNhbGVuZGFyV2Vla3M6IC0yMSxcbiAgICAgICAgdmlld01vZGU6IC0yMCxcbiAgICAgICAgdG9vbGJhclBsYWNlbWVudDogLTE5LFxuICAgICAgICBidXR0b25zOiAtMTgsXG4gICAgICAgIHdpZGdldFBvc2l0aW9uaW5nOiAtMTcsXG4gICAgICAgIHdpZGdldFBhcmVudDogLTE2LFxuICAgICAgICBpZ25vcmVSZWFkb25seTogLTE1LFxuICAgICAgICBrZWVwT3BlbjogLTE0LFxuICAgICAgICBmb2N1c09uU2hvdzogLTEzLFxuICAgICAgICBpbmxpbmU6IC0xMixcbiAgICAgICAga2VlcEludmFsaWQ6IC0xMSxcbiAgICAgICAga2V5QmluZHM6IC0xMCxcbiAgICAgICAgZGVidWc6IC05LFxuICAgICAgICBhbGxvd0lucHV0VG9nZ2xlOiAtOCxcbiAgICAgICAgZGlzYWJsZWRUaW1lSW50ZXJ2YWxzOiAtNyxcbiAgICAgICAgZGlzYWJsZWRIb3VyczogLTYsXG4gICAgICAgIGVuYWJsZWRIb3VyczogLTUsXG4gICAgICAgIHZpZXdEYXRlOiAtNCxcbiAgICAgICAgYWxsb3dNdWx0aWRhdGU6IC0zLFxuICAgICAgICBtdWx0aWRhdGVTZXBhcmF0b3I6IC0yLFxuICAgICAgICB1cGRhdGVPbmx5VGhyb3VnaERhdGVPcHRpb246IC0xLFxuICAgICAgICBkYXRlOiAxXG4gICAgfSxcbiAgICAgICAgZGVmYXVsdEZlYXRoZXJJY29ucyA9IHtcbiAgICAgICAgdGltZTogJ2Nsb2NrJyxcbiAgICAgICAgZGF0ZTogJ2NhbGVuZGFyJyxcbiAgICAgICAgdXA6ICdhcnJvdy11cCcsXG4gICAgICAgIGRvd246ICdhcnJvdy1kb3duJyxcbiAgICAgICAgcHJldmlvdXM6ICdhcnJvdy1sZWZ0JyxcbiAgICAgICAgbmV4dDogJ2Fycm93LXJpZ2h0JyxcbiAgICAgICAgdG9kYXk6ICdhcnJvdy1kb3duLWNpcmNsZScsXG4gICAgICAgIGNsZWFyOiAndHJhc2gtMicsXG4gICAgICAgIGNsb3NlOiAneCdcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gb3B0aW9uc1NvcnRGbihvcHRpb25LZXlBLCBvcHRpb25LZXlCKSB7XG4gICAgICAgIGlmIChvcHRpb25zU29ydE1hcFtvcHRpb25LZXlBXSAmJiBvcHRpb25zU29ydE1hcFtvcHRpb25LZXlCXSkge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnNTb3J0TWFwW29wdGlvbktleUFdIDwgMCAmJiBvcHRpb25zU29ydE1hcFtvcHRpb25LZXlCXSA8IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTWF0aC5hYnMob3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5Ql0pIC0gTWF0aC5hYnMob3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5QV0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zU29ydE1hcFtvcHRpb25LZXlBXSA8IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnNTb3J0TWFwW29wdGlvbktleUJdIDwgMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnNTb3J0TWFwW29wdGlvbktleUFdIC0gb3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5Ql07XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5QV0pIHtcbiAgICAgICAgICAgIHJldHVybiBvcHRpb25zU29ydE1hcFtvcHRpb25LZXlBXTtcbiAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zU29ydE1hcFtvcHRpb25LZXlCXSkge1xuICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnNTb3J0TWFwW29wdGlvbktleUJdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIHZhciBEZWZhdWx0ID0ge1xuICAgICAgICB0aW1lWm9uZTogJycsXG4gICAgICAgIGZvcm1hdDogZmFsc2UsXG4gICAgICAgIGRheVZpZXdIZWFkZXJGb3JtYXQ6ICdNTU1NIFlZWVknLFxuICAgICAgICBleHRyYUZvcm1hdHM6IGZhbHNlLFxuICAgICAgICBzdGVwcGluZzogMSxcbiAgICAgICAgbWluRGF0ZTogZmFsc2UsXG4gICAgICAgIG1heERhdGU6IGZhbHNlLFxuICAgICAgICB1c2VDdXJyZW50OiB0cnVlLFxuICAgICAgICBjb2xsYXBzZTogdHJ1ZSxcbiAgICAgICAgbG9jYWxlOiBtb21lbnQubG9jYWxlKCksXG4gICAgICAgIGRlZmF1bHREYXRlOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWREYXRlczogZmFsc2UsXG4gICAgICAgIGVuYWJsZWREYXRlczogZmFsc2UsXG4gICAgICAgIGljb25zOiB7XG4gICAgICAgICAgICB0eXBlOiAnY2xhc3MnLFxuICAgICAgICAgICAgdGltZTogJ2ZhIGZhLWNsb2NrLW8nLFxuICAgICAgICAgICAgZGF0ZTogJ2ZhIGZhLWNhbGVuZGFyJyxcbiAgICAgICAgICAgIHVwOiAnZmEgZmEtYXJyb3ctdXAnLFxuICAgICAgICAgICAgZG93bjogJ2ZhIGZhLWFycm93LWRvd24nLFxuICAgICAgICAgICAgcHJldmlvdXM6ICdmYSBmYS1jaGV2cm9uLWxlZnQnLFxuICAgICAgICAgICAgbmV4dDogJ2ZhIGZhLWNoZXZyb24tcmlnaHQnLFxuICAgICAgICAgICAgdG9kYXk6ICdmYSBmYS1jYWxlbmRhci1jaGVjay1vJyxcbiAgICAgICAgICAgIGNsZWFyOiAnZmEgZmEtdHJhc2gnLFxuICAgICAgICAgICAgY2xvc2U6ICdmYSBmYS10aW1lcydcbiAgICAgICAgfSxcbiAgICAgICAgdG9vbHRpcHM6IHtcbiAgICAgICAgICAgIHRvZGF5OiAnR28gdG8gdG9kYXknLFxuICAgICAgICAgICAgY2xlYXI6ICdDbGVhciBzZWxlY3Rpb24nLFxuICAgICAgICAgICAgY2xvc2U6ICdDbG9zZSB0aGUgcGlja2VyJyxcbiAgICAgICAgICAgIHNlbGVjdE1vbnRoOiAnU2VsZWN0IE1vbnRoJyxcbiAgICAgICAgICAgIHByZXZNb250aDogJ1ByZXZpb3VzIE1vbnRoJyxcbiAgICAgICAgICAgIG5leHRNb250aDogJ05leHQgTW9udGgnLFxuICAgICAgICAgICAgc2VsZWN0WWVhcjogJ1NlbGVjdCBZZWFyJyxcbiAgICAgICAgICAgIHByZXZZZWFyOiAnUHJldmlvdXMgWWVhcicsXG4gICAgICAgICAgICBuZXh0WWVhcjogJ05leHQgWWVhcicsXG4gICAgICAgICAgICBzZWxlY3REZWNhZGU6ICdTZWxlY3QgRGVjYWRlJyxcbiAgICAgICAgICAgIHByZXZEZWNhZGU6ICdQcmV2aW91cyBEZWNhZGUnLFxuICAgICAgICAgICAgbmV4dERlY2FkZTogJ05leHQgRGVjYWRlJyxcbiAgICAgICAgICAgIHByZXZDZW50dXJ5OiAnUHJldmlvdXMgQ2VudHVyeScsXG4gICAgICAgICAgICBuZXh0Q2VudHVyeTogJ05leHQgQ2VudHVyeScsXG4gICAgICAgICAgICBwaWNrSG91cjogJ1BpY2sgSG91cicsXG4gICAgICAgICAgICBpbmNyZW1lbnRIb3VyOiAnSW5jcmVtZW50IEhvdXInLFxuICAgICAgICAgICAgZGVjcmVtZW50SG91cjogJ0RlY3JlbWVudCBIb3VyJyxcbiAgICAgICAgICAgIHBpY2tNaW51dGU6ICdQaWNrIE1pbnV0ZScsXG4gICAgICAgICAgICBpbmNyZW1lbnRNaW51dGU6ICdJbmNyZW1lbnQgTWludXRlJyxcbiAgICAgICAgICAgIGRlY3JlbWVudE1pbnV0ZTogJ0RlY3JlbWVudCBNaW51dGUnLFxuICAgICAgICAgICAgcGlja1NlY29uZDogJ1BpY2sgU2Vjb25kJyxcbiAgICAgICAgICAgIGluY3JlbWVudFNlY29uZDogJ0luY3JlbWVudCBTZWNvbmQnLFxuICAgICAgICAgICAgZGVjcmVtZW50U2Vjb25kOiAnRGVjcmVtZW50IFNlY29uZCcsXG4gICAgICAgICAgICB0b2dnbGVQZXJpb2Q6ICdUb2dnbGUgUGVyaW9kJyxcbiAgICAgICAgICAgIHNlbGVjdFRpbWU6ICdTZWxlY3QgVGltZScsXG4gICAgICAgICAgICBzZWxlY3REYXRlOiAnU2VsZWN0IERhdGUnXG4gICAgICAgIH0sXG4gICAgICAgIHVzZVN0cmljdDogZmFsc2UsXG4gICAgICAgIHNpZGVCeVNpZGU6IGZhbHNlLFxuICAgICAgICBkYXlzT2ZXZWVrRGlzYWJsZWQ6IGZhbHNlLFxuICAgICAgICBjYWxlbmRhcldlZWtzOiBmYWxzZSxcbiAgICAgICAgdmlld01vZGU6ICdkYXlzJyxcbiAgICAgICAgdG9vbGJhclBsYWNlbWVudDogJ2RlZmF1bHQnLFxuICAgICAgICBidXR0b25zOiB7XG4gICAgICAgICAgICBzaG93VG9kYXk6IGZhbHNlLFxuICAgICAgICAgICAgc2hvd0NsZWFyOiBmYWxzZSxcbiAgICAgICAgICAgIHNob3dDbG9zZTogZmFsc2VcbiAgICAgICAgfSxcbiAgICAgICAgd2lkZ2V0UG9zaXRpb25pbmc6IHtcbiAgICAgICAgICAgIGhvcml6b250YWw6ICdhdXRvJyxcbiAgICAgICAgICAgIHZlcnRpY2FsOiAnYXV0bydcbiAgICAgICAgfSxcbiAgICAgICAgd2lkZ2V0UGFyZW50OiBudWxsLFxuICAgICAgICByZWFkb25seTogZmFsc2UsXG4gICAgICAgIGlnbm9yZVJlYWRvbmx5OiBmYWxzZSxcbiAgICAgICAga2VlcE9wZW46IGZhbHNlLFxuICAgICAgICBmb2N1c09uU2hvdzogdHJ1ZSxcbiAgICAgICAgaW5saW5lOiBmYWxzZSxcbiAgICAgICAga2VlcEludmFsaWQ6IGZhbHNlLFxuICAgICAgICBrZXlCaW5kczoge1xuICAgICAgICAgICAgdXA6IGZ1bmN0aW9uIHVwKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCg3LCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCh0aGlzLnN0ZXBwaW5nKCksICdtJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkb3duOiBmdW5jdGlvbiBkb3duKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDcsICdkJykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QodGhpcy5zdGVwcGluZygpLCAnbScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2NvbnRyb2wgdXAnOiBmdW5jdGlvbiBjb250cm9sVXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICd5JykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICdoJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnY29udHJvbCBkb3duJzogZnVuY3Rpb24gY29udHJvbERvd24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAneScpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdoJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsZWZ0OiBmdW5jdGlvbiBsZWZ0KCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmlnaHQ6IGZ1bmN0aW9uIHJpZ2h0KCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhZ2VVcDogZnVuY3Rpb24gcGFnZVVwKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnTScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFnZURvd246IGZ1bmN0aW9uIHBhZ2VEb3duKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ00nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudGVyOiBmdW5jdGlvbiBlbnRlcigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXNjYXBlOiBmdW5jdGlvbiBlc2NhcGUoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdjb250cm9sIHNwYWNlJzogZnVuY3Rpb24gY29udHJvbFNwYWNlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcuYnRuW2RhdGEtYWN0aW9uPVwidG9nZ2xlUGVyaW9kXCJdJykuY2xpY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdDogZnVuY3Rpb24gdCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlKHRoaXMuZ2V0TW9tZW50KCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdkZWxldGUnOiBmdW5jdGlvbiBfZGVsZXRlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICAgICAgYWxsb3dJbnB1dFRvZ2dsZTogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkVGltZUludGVydmFsczogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkSG91cnM6IGZhbHNlLFxuICAgICAgICBlbmFibGVkSG91cnM6IGZhbHNlLFxuICAgICAgICB2aWV3RGF0ZTogZmFsc2UsXG4gICAgICAgIGFsbG93TXVsdGlkYXRlOiBmYWxzZSxcbiAgICAgICAgbXVsdGlkYXRlU2VwYXJhdG9yOiAnLCAnLFxuICAgICAgICB1cGRhdGVPbmx5VGhyb3VnaERhdGVPcHRpb246IGZhbHNlLFxuICAgICAgICBwcm9tcHRUaW1lT25EYXRlQ2hhbmdlOiBmYWxzZSxcbiAgICAgICAgcHJvbXB0VGltZU9uRGF0ZUNoYW5nZVRyYW5zaXRpb25EZWxheTogMjAwXG4gICAgfTtcblxuICAgIC8vIFJlU2hhcnBlciByZXN0b3JlIEluY29uc2lzdGVudE5hbWluZ1xuXG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBEZWNsYXJhdGlvbkhpZGVzXG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBJbmNvbnNpc3RlbnROYW1pbmdcblxuICAgIHZhciBEYXRlVGltZVBpY2tlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLyoqIEBuYW1lc3BhY2UgZURhdGEuZGF0ZU9wdGlvbnMgKi9cbiAgICAgICAgLyoqIEBuYW1lc3BhY2UgbW9tZW50LnR6ICovXG5cbiAgICAgICAgZnVuY3Rpb24gRGF0ZVRpbWVQaWNrZXIoZWxlbWVudCwgb3B0aW9ucykge1xuICAgICAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIERhdGVUaW1lUGlja2VyKTtcblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucyA9IHRoaXMuX2dldE9wdGlvbnMob3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZCA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy51bnNldCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMudXNlMjRIb3VycyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmFjdHVhbEZvcm1hdCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnBhcnNlRm9ybWF0cyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRWaWV3TW9kZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLk1pblZpZXdNb2RlTnVtYmVyID0gMDtcbiAgICAgICAgICAgIHRoaXMuaXNJbml0Rm9ybWF0dGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5pc0luaXQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5oYXNJbml0RGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5pbml0RGF0ZSA9IHZvaWQgMDtcbiAgICAgICAgICAgIHRoaXMuX25vdGlmeUNoYW5nZUV2ZW50Q29udGV4dCA9IHZvaWQgMDtcbiAgICAgICAgICAgIHRoaXMuX2N1cnJlbnRQcm9tcHRUaW1lVGltZW91dCA9IG51bGw7XG5cbiAgICAgICAgICAgIHRoaXMuX2ludCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAqL1xuXG5cbiAgICAgICAgLy9wcml2YXRlXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbnQgPSBmdW5jdGlvbiBfaW50KCkge1xuICAgICAgICAgICAgdGhpcy5pc0luaXQgPSB0cnVlO1xuICAgICAgICAgICAgdmFyIHRhcmdldElucHV0ID0gdGhpcy5fZWxlbWVudC5kYXRhKCd0YXJnZXQtaW5wdXQnKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9lbGVtZW50LmlzKCdpbnB1dCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dCA9IHRoaXMuX2VsZW1lbnQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldElucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0SW5wdXQgPT09ICduZWFyZXN0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0ID0gdGhpcy5fZWxlbWVudC5maW5kKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQgPSAkKHRhcmdldElucHV0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICAgICAgICB0aGlzLl9kYXRlc1swXSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCkuY2xvbmUoKTtcblxuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgdGhpcy5fb3B0aW9ucywgdGhpcy5fZGF0YVRvT3B0aW9ucygpKTtcblxuICAgICAgICAgICAgdGhpcy5oYXNJbml0RGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5pbml0RGF0ZSA9IHZvaWQgMDtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucyh0aGlzLl9vcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5pc0luaXRGb3JtYXR0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7XG4gICAgICAgICAgICB0aGlzLmlzSW5pdEZvcm1hdHRpbmcgPSBmYWxzZTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LmlzKCdpbnB1dCcpICYmIHRoaXMuaW5wdXQudmFsKCkudHJpbSgpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX3BhcnNlSW5wdXREYXRlKHRoaXMuaW5wdXQudmFsKCkudHJpbSgpKSwgMCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgJiYgdGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQuYXR0cigncGxhY2Vob2xkZXInKSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNJbml0RGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZSh0aGlzLmluaXREYXRlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmlzSW5pdCA9IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fdXBkYXRlID0gZnVuY3Rpb24gX3VwZGF0ZSgpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fZmlsbFRpbWUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3NldFZhbHVlID0gZnVuY3Rpb24gX3NldFZhbHVlKHRhcmdldE1vbWVudCwgaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBub0luZGV4ID0gdHlwZW9mIGluZGV4ID09PSAndW5kZWZpbmVkJyxcbiAgICAgICAgICAgICAgICBpc0NsZWFyID0gIXRhcmdldE1vbWVudCAmJiBub0luZGV4LFxuICAgICAgICAgICAgICAgIGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGUgPSB0aGlzLmlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGUsXG4gICAgICAgICAgICAgICAgaXNOb3RBbGxvd2VkUHJvZ3JhbW1hdGljVXBkYXRlID0gIXRoaXMuaXNJbml0ICYmIHRoaXMuX29wdGlvbnMudXBkYXRlT25seVRocm91Z2hEYXRlT3B0aW9uICYmICFpc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlO1xuICAgICAgICAgICAgdmFyIG91dHBWYWx1ZSA9ICcnLFxuICAgICAgICAgICAgICAgIGlzSW52YWxpZCA9IGZhbHNlLFxuICAgICAgICAgICAgICAgIG9sZERhdGUgPSB0aGlzLnVuc2V0ID8gbnVsbCA6IHRoaXMuX2RhdGVzW2luZGV4XTtcbiAgICAgICAgICAgIGlmICghb2xkRGF0ZSAmJiAhdGhpcy51bnNldCAmJiBub0luZGV4ICYmIGlzQ2xlYXIpIHtcbiAgICAgICAgICAgICAgICBvbGREYXRlID0gdGhpcy5fZGF0ZXNbdGhpcy5fZGF0ZXMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGNhc2Ugb2YgY2FsbGluZyBzZXRWYWx1ZShudWxsIG9yIGZhbHNlKVxuICAgICAgICAgICAgaWYgKCF0YXJnZXRNb21lbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNOb3RBbGxvd2VkUHJvZ3JhbW1hdGljVXBkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IHRhcmdldE1vbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NsZWFyOiBpc0NsZWFyLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbnZhbGlkOiBpc0ludmFsaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlOiBpc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbml0OiB0aGlzLmlzSW5pdFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgfHwgdGhpcy5fZGF0ZXMubGVuZ3RoID09PSAxIHx8IGlzQ2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51bnNldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkID0gW107XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gJycgKyB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnKSArIHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yO1xuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSBvbGREYXRlICYmIG91dHBWYWx1ZS5yZXBsYWNlKCcnICsgb2xkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpICsgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3IsICcnKS5yZXBsYWNlKCcnICsgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3IgKyB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciwgJycpLnJlcGxhY2UobmV3IFJlZ0V4cChlc2NhcGVSZWdFeHAodGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3IpICsgJ1xcXFxzKiQnKSwgJycpIHx8ICcnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSB0cmltKG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnZhbChvdXRwVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnRyaWdnZXIoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQuZGF0YSgnZGF0ZScsIG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgICAgICAgICAgIGRhdGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlLFxuICAgICAgICAgICAgICAgICAgICBpc0NsZWFyOiBpc0NsZWFyLFxuICAgICAgICAgICAgICAgICAgICBpc0ludmFsaWQ6IGlzSW52YWxpZCxcbiAgICAgICAgICAgICAgICAgICAgaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZTogaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZSxcbiAgICAgICAgICAgICAgICAgICAgaXNJbml0OiB0aGlzLmlzSW5pdFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGFyZ2V0TW9tZW50ID0gdGFyZ2V0TW9tZW50LmNsb25lKCkubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRNb21lbnQudHoodGhpcy5fb3B0aW9ucy50aW1lWm9uZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0TW9tZW50Lm1pbnV0ZXMoTWF0aC5yb3VuZCh0YXJnZXRNb21lbnQubWludXRlcygpIC8gdGhpcy5fb3B0aW9ucy5zdGVwcGluZykgKiB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nKS5zZWNvbmRzKDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZCh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzTm90QWxsb3dlZFByb2dyYW1tYXRpY1VwZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQuY2xvbmUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NsZWFyOiBpc0NsZWFyLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbnZhbGlkOiBpc0ludmFsaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlOiBpc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbml0OiB0aGlzLmlzSW5pdFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpbmRleF0gPSB0YXJnZXRNb21lbnQ7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWRbaW5kZXhdID0gdGFyZ2V0TW9tZW50LmZvcm1hdCgnWVlZWS1NTS1ERCcpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gdGFyZ2V0TW9tZW50LmNsb25lKCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgJiYgdGhpcy5fZGF0ZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgKz0gJycgKyB0aGlzLl9kYXRlc1tpXS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpICsgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gb3V0cFZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cCh0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciArICdcXFxccyokJyksICcnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSB0aGlzLl9kYXRlc1tpbmRleF0uZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gdHJpbShvdXRwVmFsdWUpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwob3V0cFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC50cmlnZ2VyKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnLCBvdXRwVmFsdWUpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy51bnNldCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLFxuICAgICAgICAgICAgICAgICAgICBkYXRlOiB0aGlzLl9kYXRlc1tpbmRleF0uY2xvbmUoKSxcbiAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgaXNDbGVhcjogaXNDbGVhcixcbiAgICAgICAgICAgICAgICAgICAgaXNJbnZhbGlkOiBpc0ludmFsaWQsXG4gICAgICAgICAgICAgICAgICAgIGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGU6IGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGUsXG4gICAgICAgICAgICAgICAgICAgIGlzSW5pdDogdGhpcy5pc0luaXRcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaXNJbnZhbGlkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwoJycgKyAodGhpcy51bnNldCA/ICcnIDogdGhpcy5fZGF0ZXNbaW5kZXhdLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IHRhcmdldE1vbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NsZWFyOiBpc0NsZWFyLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbnZhbGlkOiBpc0ludmFsaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlOiBpc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbml0OiB0aGlzLmlzSW5pdFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5FUlJPUixcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogdGFyZ2V0TW9tZW50LFxuICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9jaGFuZ2UgPSBmdW5jdGlvbiBfY2hhbmdlKGUpIHtcbiAgICAgICAgICAgIHZhciB2YWwgPSAkKGUudGFyZ2V0KS52YWwoKS50cmltKCksXG4gICAgICAgICAgICAgICAgcGFyc2VkRGF0ZSA9IHZhbCA/IHRoaXMuX3BhcnNlSW5wdXREYXRlKHZhbCkgOiBudWxsO1xuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUocGFyc2VkRGF0ZSwgMCk7XG4gICAgICAgICAgICBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTTWV0aG9kQ2FuQmVTdGF0aWNcblxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uIF9nZXRPcHRpb25zKG9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgRGVmYXVsdCwgb3B0aW9ucyAmJiBvcHRpb25zLmljb25zICYmIG9wdGlvbnMuaWNvbnMudHlwZSA9PT0gJ2ZlYXRoZXInID8ge1xuICAgICAgICAgICAgICAgIGljb25zOiBkZWZhdWx0RmVhdGhlckljb25zXG4gICAgICAgICAgICB9IDoge30sIG9wdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNUaW1lWm9uZSA9IGZ1bmN0aW9uIF9oYXNUaW1lWm9uZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBtb21lbnQudHogIT09IHVuZGVmaW5lZCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gbnVsbCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSAnJztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzRW5hYmxlZCA9IGZ1bmN0aW9uIF9pc0VuYWJsZWQoZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZ3JhbnVsYXJpdHkgIT09ICdzdHJpbmcnIHx8IGdyYW51bGFyaXR5Lmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpc0VuYWJsZWQgZXhwZWN0cyBhIHNpbmdsZSBjaGFyYWN0ZXIgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3dpdGNoIChncmFudWxhcml0eSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZignWScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ00nKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2QnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnSCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2gnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC5pbmRleE9mKCdtJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZigncycpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdhJzpcbiAgICAgICAgICAgICAgICBjYXNlICdBJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignYScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNUaW1lID0gZnVuY3Rpb24gX2hhc1RpbWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNFbmFibGVkKCdoJykgfHwgdGhpcy5faXNFbmFibGVkKCdtJykgfHwgdGhpcy5faXNFbmFibGVkKCdzJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNEYXRlID0gZnVuY3Rpb24gX2hhc0RhdGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNFbmFibGVkKCd5JykgfHwgdGhpcy5faXNFbmFibGVkKCdNJykgfHwgdGhpcy5faXNFbmFibGVkKCdkJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9kYXRhVG9PcHRpb25zID0gZnVuY3Rpb24gX2RhdGFUb09wdGlvbnMoKSB7XG4gICAgICAgICAgICB2YXIgZURhdGEgPSB0aGlzLl9lbGVtZW50LmRhdGEoKTtcbiAgICAgICAgICAgIHZhciBkYXRhT3B0aW9ucyA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoZURhdGEuZGF0ZU9wdGlvbnMgJiYgZURhdGEuZGF0ZU9wdGlvbnMgaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgICAgICAgICBkYXRhT3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIGRhdGFPcHRpb25zLCBlRGF0YS5kYXRlT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQuZWFjaCh0aGlzLl9vcHRpb25zLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGF0dHJpYnV0ZU5hbWUgPSAnZGF0ZScgKyBrZXkuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBrZXkuc2xpY2UoMSk7IC8vdG9kbyBkYXRhIGFwaSBrZXlcbiAgICAgICAgICAgICAgICBpZiAoZURhdGFbYXR0cmlidXRlTmFtZV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhT3B0aW9uc1trZXldID0gZURhdGFbYXR0cmlidXRlTmFtZV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGRhdGFPcHRpb25zW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gZGF0YU9wdGlvbnM7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9mb3JtYXQgPSBmdW5jdGlvbiBfZm9ybWF0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZm9ybWF0IHx8ICdZWVlZLU1NLUREIEhIOm1tJztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2FyZVNhbWVEYXRlcyA9IGZ1bmN0aW9uIF9hcmVTYW1lRGF0ZXMoYSwgYikge1xuICAgICAgICAgICAgdmFyIGZvcm1hdCA9IHRoaXMuX2Zvcm1hdCgpO1xuICAgICAgICAgICAgcmV0dXJuIGEgJiYgYiAmJiAoYS5pc1NhbWUoYikgfHwgbW9tZW50KGEuZm9ybWF0KGZvcm1hdCksIGZvcm1hdCkuaXNTYW1lKG1vbWVudChiLmZvcm1hdChmb3JtYXQpLCBmb3JtYXQpKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9ub3RpZnlFdmVudCA9IGZ1bmN0aW9uIF9ub3RpZnlFdmVudChlKSB7XG4gICAgICAgICAgICBpZiAoZS50eXBlID09PSBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlDaGFuZ2VFdmVudENvbnRleHQgPSB0aGlzLl9ub3RpZnlDaGFuZ2VFdmVudENvbnRleHQgfHwgMDtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlDaGFuZ2VFdmVudENvbnRleHQrKztcbiAgICAgICAgICAgICAgICBpZiAoZS5kYXRlICYmIHRoaXMuX2FyZVNhbWVEYXRlcyhlLmRhdGUsIGUub2xkRGF0ZSkgfHwgIWUuaXNDbGVhciAmJiAhZS5kYXRlICYmICFlLm9sZERhdGUgfHwgdGhpcy5fbm90aWZ5Q2hhbmdlRXZlbnRDb250ZXh0ID4gMSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlDaGFuZ2VFdmVudENvbnRleHQgPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5faGFuZGxlUHJvbXB0VGltZUlmTmVlZGVkKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fZWxlbWVudC50cmlnZ2VyKGUpO1xuICAgICAgICAgICAgdGhpcy5fbm90aWZ5Q2hhbmdlRXZlbnRDb250ZXh0ID0gdm9pZCAwO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFuZGxlUHJvbXB0VGltZUlmTmVlZGVkID0gZnVuY3Rpb24gX2hhbmRsZVByb21wdFRpbWVJZk5lZWRlZChlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5wcm9tcHRUaW1lT25EYXRlQ2hhbmdlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFlLm9sZERhdGUgJiYgdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcnN0IHRpbWUgZXZlci4gSWYgdXNlQ3VycmVudCBvcHRpb24gaXMgc2V0IHRvIHRydWUgKGRlZmF1bHQpLCBkbyBub3RoaW5nXG4gICAgICAgICAgICAgICAgICAgIC8vIGJlY2F1c2UgdGhlIGZpcnN0IGRhdGUgaXMgc2VsZWN0ZWQgYXV0b21hdGljYWxseS5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5vbGREYXRlICYmIGUuZGF0ZSAmJiAoZS5vbGREYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpID09PSBlLmRhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykgfHwgZS5vbGREYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpICE9PSBlLmRhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykgJiYgZS5vbGREYXRlLmZvcm1hdCgnSEg6bW06c3MnKSAhPT0gZS5kYXRlLmZvcm1hdCgnSEg6bW06c3MnKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRGF0ZSBkaWRuJ3QgY2hhbmdlICh0aW1lIGRpZCkgb3IgZGF0ZSBjaGFuZ2VkIGJlY2F1c2UgdGltZSBkaWQuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX2N1cnJlbnRQcm9tcHRUaW1lVGltZW91dCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fY3VycmVudFByb21wdFRpbWVUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGF0LndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC53aWRnZXQuZmluZCgnW2RhdGEtYWN0aW9uPVwidG9nZ2xlUGlja2VyXCJdJykuY2xpY2soKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIHRoaXMuX29wdGlvbnMucHJvbXB0VGltZU9uRGF0ZUNoYW5nZVRyYW5zaXRpb25EZWxheSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl92aWV3VXBkYXRlID0gZnVuY3Rpb24gX3ZpZXdVcGRhdGUoZSkge1xuICAgICAgICAgICAgaWYgKGUgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgIGUgPSAnWVlZWSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuVVBEQVRFLFxuICAgICAgICAgICAgICAgIGNoYW5nZTogZSxcbiAgICAgICAgICAgICAgICB2aWV3RGF0ZTogdGhpcy5fdmlld0RhdGUuY2xvbmUoKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9zaG93TW9kZSA9IGZ1bmN0aW9uIF9zaG93TW9kZShkaXIpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGlyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heCh0aGlzLk1pblZpZXdNb2RlTnVtYmVyLCBNYXRoLm1pbigzLCB0aGlzLmN1cnJlbnRWaWV3TW9kZSArIGRpcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXIgPiBkaXYnKS5oaWRlKCkuZmlsdGVyKCcuZGF0ZXBpY2tlci0nICsgRGF0ZVBpY2tlck1vZGVzW3RoaXMuY3VycmVudFZpZXdNb2RlXS5DTEFTU19OQU1FKS5zaG93KCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRGlzYWJsZWREYXRlcyA9IGZ1bmN0aW9uIF9pc0luRGlzYWJsZWREYXRlcyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlc1t0ZXN0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRW5hYmxlZERhdGVzID0gZnVuY3Rpb24gX2lzSW5FbmFibGVkRGF0ZXModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlc1t0ZXN0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRGlzYWJsZWRIb3VycyA9IGZ1bmN0aW9uIF9pc0luRGlzYWJsZWRIb3Vycyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3Vyc1t0ZXN0RGF0ZS5mb3JtYXQoJ0gnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRW5hYmxlZEhvdXJzID0gZnVuY3Rpb24gX2lzSW5FbmFibGVkSG91cnModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3Vyc1t0ZXN0RGF0ZS5mb3JtYXQoJ0gnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc1ZhbGlkID0gZnVuY3Rpb24gX2lzVmFsaWQodGFyZ2V0TW9tZW50LCBncmFudWxhcml0eSkge1xuICAgICAgICAgICAgaWYgKCF0YXJnZXRNb21lbnQgfHwgIXRhcmdldE1vbWVudC5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgdGhpcy5faXNJbkRpc2FibGVkRGF0ZXModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmICF0aGlzLl9pc0luRW5hYmxlZERhdGVzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHRhcmdldE1vbWVudC5pc0JlZm9yZSh0aGlzLl9vcHRpb25zLm1pbkRhdGUsIGdyYW51bGFyaXR5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgdGFyZ2V0TW9tZW50LmlzQWZ0ZXIodGhpcy5fb3B0aW9ucy5tYXhEYXRlLCBncmFudWxhcml0eSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZC5pbmRleE9mKHRhcmdldE1vbWVudC5kYXkoKSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpICYmIHRoaXMuX2lzSW5EaXNhYmxlZEhvdXJzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSAmJiAhdGhpcy5faXNJbkVuYWJsZWRIb3Vycyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykpIHtcbiAgICAgICAgICAgICAgICB2YXIgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRhcmdldE1vbWVudC5pc0JldHdlZW4odGhpc1swXSwgdGhpc1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChmb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9wYXJzZUlucHV0RGF0ZSA9IGZ1bmN0aW9uIF9wYXJzZUlucHV0RGF0ZShpbnB1dERhdGUpIHtcbiAgICAgICAgICAgIHZhciBfcmVmID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fSxcbiAgICAgICAgICAgICAgICBfcmVmJGlzUGlja2VyU2hvdyA9IF9yZWYuaXNQaWNrZXJTaG93LFxuICAgICAgICAgICAgICAgIGlzUGlja2VyU2hvdyA9IF9yZWYkaXNQaWNrZXJTaG93ID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IF9yZWYkaXNQaWNrZXJTaG93O1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZSA9PT0gdW5kZWZpbmVkIHx8IGlzUGlja2VyU2hvdykge1xuICAgICAgICAgICAgICAgIGlmICghbW9tZW50LmlzTW9tZW50KGlucHV0RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXREYXRlID0gdGhpcy5nZXRNb21lbnQoaW5wdXREYXRlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlucHV0RGF0ZSA9IHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUoaW5wdXREYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vaW5wdXREYXRlLmxvY2FsZSh0aGlzLm9wdGlvbnMubG9jYWxlKTtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dERhdGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9rZXlkb3duID0gZnVuY3Rpb24gX2tleWRvd24oZSkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZXIgPSBudWxsLFxuICAgICAgICAgICAgICAgIGluZGV4ID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGluZGV4MiA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBrZXlCaW5kS2V5cyA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIHByZXNzZWRLZXlzID0gW10sXG4gICAgICAgICAgICAgICAgcHJlc3NlZE1vZGlmaWVycyA9IHt9LFxuICAgICAgICAgICAgICAgIGN1cnJlbnRLZXkgPSBlLndoaWNoLFxuICAgICAgICAgICAgICAgIHByZXNzZWQgPSAncCc7XG5cbiAgICAgICAgICAgIGtleVN0YXRlW2N1cnJlbnRLZXldID0gcHJlc3NlZDtcblxuICAgICAgICAgICAgZm9yIChpbmRleCBpbiBrZXlTdGF0ZSkge1xuICAgICAgICAgICAgICAgIGlmIChrZXlTdGF0ZS5oYXNPd25Qcm9wZXJ0eShpbmRleCkgJiYga2V5U3RhdGVbaW5kZXhdID09PSBwcmVzc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXNzZWRLZXlzLnB1c2goaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGFyc2VJbnQoaW5kZXgsIDEwKSAhPT0gY3VycmVudEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJlc3NlZE1vZGlmaWVyc1tpbmRleF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKGluZGV4IGluIHRoaXMuX29wdGlvbnMua2V5QmluZHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5rZXlCaW5kcy5oYXNPd25Qcm9wZXJ0eShpbmRleCkgJiYgdHlwZW9mIHRoaXMuX29wdGlvbnMua2V5QmluZHNbaW5kZXhdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleUJpbmRLZXlzID0gaW5kZXguc3BsaXQoJyAnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleUJpbmRLZXlzLmxlbmd0aCA9PT0gcHJlc3NlZEtleXMubGVuZ3RoICYmIEtleU1hcFtjdXJyZW50S2V5XSA9PT0ga2V5QmluZEtleXNba2V5QmluZEtleXMubGVuZ3RoIC0gMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbE1vZGlmaWVyc1ByZXNzZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpbmRleDIgPSBrZXlCaW5kS2V5cy5sZW5ndGggLSAyOyBpbmRleDIgPj0gMDsgaW5kZXgyLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShLZXlNYXBba2V5QmluZEtleXNbaW5kZXgyXV0gaW4gcHJlc3NlZE1vZGlmaWVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWxsTW9kaWZpZXJzUHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZXIgPSB0aGlzLl9vcHRpb25zLmtleUJpbmRzW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlci5jYWxsKHRoaXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNNZXRob2RDYW5CZVN0YXRpYyxTcGVsbENoZWNraW5nSW5zcGVjdGlvblxuXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9rZXl1cCA9IGZ1bmN0aW9uIF9rZXl1cChlKSB7XG4gICAgICAgICAgICBrZXlTdGF0ZVtlLndoaWNoXSA9ICdyJztcbiAgICAgICAgICAgIGlmIChrZXlQcmVzc0hhbmRsZWRbZS53aGljaF0pIHtcbiAgICAgICAgICAgICAgICBrZXlQcmVzc0hhbmRsZWRbZS53aGljaF0gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2luZGV4R2l2ZW5EYXRlcyA9IGZ1bmN0aW9uIF9pbmRleEdpdmVuRGF0ZXMoZ2l2ZW5EYXRlc0FycmF5KSB7XG4gICAgICAgICAgICAvLyBTdG9yZSBnaXZlbiBlbmFibGVkRGF0ZXMgYW5kIGRpc2FibGVkRGF0ZXMgYXMga2V5cy5cbiAgICAgICAgICAgIC8vIFRoaXMgd2F5IHdlIGNhbiBjaGVjayB0aGVpciBleGlzdGVuY2UgaW4gTygxKSB0aW1lIGluc3RlYWQgb2YgbG9vcGluZyB0aHJvdWdoIHdob2xlIGFycmF5LlxuICAgICAgICAgICAgLy8gKGZvciBleGFtcGxlOiBvcHRpb25zLmVuYWJsZWREYXRlc1snMjAxNC0wMi0yNyddID09PSB0cnVlKVxuICAgICAgICAgICAgdmFyIGdpdmVuRGF0ZXNJbmRleGVkID0ge30sXG4gICAgICAgICAgICAgICAgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICAkLmVhY2goZ2l2ZW5EYXRlc0FycmF5LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGREYXRlID0gc2VsZi5fcGFyc2VJbnB1dERhdGUodGhpcyk7XG4gICAgICAgICAgICAgICAgaWYgKGREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgICAgICBnaXZlbkRhdGVzSW5kZXhlZFtkRGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGdpdmVuRGF0ZXNJbmRleGVkKS5sZW5ndGggPyBnaXZlbkRhdGVzSW5kZXhlZCA6IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW5kZXhHaXZlbkhvdXJzID0gZnVuY3Rpb24gX2luZGV4R2l2ZW5Ib3VycyhnaXZlbkhvdXJzQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIFN0b3JlIGdpdmVuIGVuYWJsZWRIb3VycyBhbmQgZGlzYWJsZWRIb3VycyBhcyBrZXlzLlxuICAgICAgICAgICAgLy8gVGhpcyB3YXkgd2UgY2FuIGNoZWNrIHRoZWlyIGV4aXN0ZW5jZSBpbiBPKDEpIHRpbWUgaW5zdGVhZCBvZiBsb29waW5nIHRocm91Z2ggd2hvbGUgYXJyYXkuXG4gICAgICAgICAgICAvLyAoZm9yIGV4YW1wbGU6IG9wdGlvbnMuZW5hYmxlZEhvdXJzWycyMDE0LTAyLTI3J10gPT09IHRydWUpXG4gICAgICAgICAgICB2YXIgZ2l2ZW5Ib3Vyc0luZGV4ZWQgPSB7fTtcbiAgICAgICAgICAgICQuZWFjaChnaXZlbkhvdXJzQXJyYXksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBnaXZlbkhvdXJzSW5kZXhlZFt0aGlzXSA9IHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhnaXZlbkhvdXJzSW5kZXhlZCkubGVuZ3RoID8gZ2l2ZW5Ib3Vyc0luZGV4ZWQgOiBmYWxzZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2luaXRGb3JtYXR0aW5nID0gZnVuY3Rpb24gX2luaXRGb3JtYXR0aW5nKCkge1xuICAgICAgICAgICAgdmFyIGZvcm1hdCA9IHRoaXMuX29wdGlvbnMuZm9ybWF0IHx8ICdMIExUJyxcbiAgICAgICAgICAgICAgICBzZWxmID0gdGhpcztcblxuICAgICAgICAgICAgdGhpcy5hY3R1YWxGb3JtYXQgPSBmb3JtYXQucmVwbGFjZSgvKFxcW1teXFxbXSpdKXwoXFxcXCk/KExUU3xMVHxMTD9MP0w/fGx7MSw0fSkvZywgZnVuY3Rpb24gKGZvcm1hdElucHV0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChzZWxmLmlzSW5pdEZvcm1hdHRpbmcgJiYgc2VsZi5fb3B0aW9ucy5kYXRlID09PSBudWxsID8gc2VsZi5nZXRNb21lbnQoKSA6IHNlbGYuX2RhdGVzWzBdKS5sb2NhbGVEYXRhKCkubG9uZ0RhdGVGb3JtYXQoZm9ybWF0SW5wdXQpIHx8IGZvcm1hdElucHV0OyAvL3RvZG8gdGFraW5nIHRoZSBmaXJzdCBkYXRlIHNob3VsZCBiZSBva1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMucGFyc2VGb3JtYXRzID0gdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMgPyB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cy5zbGljZSgpIDogW107XG4gICAgICAgICAgICBpZiAodGhpcy5wYXJzZUZvcm1hdHMuaW5kZXhPZihmb3JtYXQpIDwgMCAmJiB0aGlzLnBhcnNlRm9ybWF0cy5pbmRleE9mKHRoaXMuYWN0dWFsRm9ybWF0KSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlRm9ybWF0cy5wdXNoKHRoaXMuYWN0dWFsRm9ybWF0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy51c2UyNEhvdXJzID0gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdhJykgPCAxICYmIHRoaXMuYWN0dWFsRm9ybWF0LnJlcGxhY2UoL1xcWy4qP10vZywgJycpLmluZGV4T2YoJ2gnKSA8IDE7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ3knKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuTWluVmlld01vZGVOdW1iZXIgPSAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnTScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdkJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLk1pblZpZXdNb2RlTnVtYmVyID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heCh0aGlzLk1pblZpZXdNb2RlTnVtYmVyLCB0aGlzLmN1cnJlbnRWaWV3TW9kZSk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy51bnNldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzWzBdLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2dldExhc3RQaWNrZWREYXRlID0gZnVuY3Rpb24gX2dldExhc3RQaWNrZWREYXRlKCkge1xuICAgICAgICAgICAgdmFyIGxhc3RQaWNrZWREYXRlID0gdGhpcy5fZGF0ZXNbdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpXTtcbiAgICAgICAgICAgIGlmICghbGFzdFBpY2tlZERhdGUgJiYgdGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgICAgIGxhc3RQaWNrZWREYXRlID0gbW9tZW50KG5ldyBEYXRlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGxhc3RQaWNrZWREYXRlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCA9IGZ1bmN0aW9uIF9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzLmxlbmd0aCAtIDE7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9wdWJsaWNcblxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5nZXRNb21lbnQgPSBmdW5jdGlvbiBnZXRNb21lbnQoZCkge1xuICAgICAgICAgICAgdmFyIHJldHVybk1vbWVudCA9IHZvaWQgMDtcblxuICAgICAgICAgICAgaWYgKGQgPT09IHVuZGVmaW5lZCB8fCBkID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogU2hvdWxkIHRoaXMgdXNlIGZvcm1hdD9cbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQgPSBtb21lbnQoKS5jbG9uZSgpLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGVyZSBpcyBhIHN0cmluZyB0byBwYXJzZSBhbmQgYSBkZWZhdWx0IHRpbWUgem9uZVxuICAgICAgICAgICAgICAgIC8vIHBhcnNlIHdpdGggdGhlIHR6IGZ1bmN0aW9uIHdoaWNoIHRha2VzIGEgZGVmYXVsdCB0aW1lIHpvbmUgaWYgaXQgaXMgbm90IGluIHRoZSBmb3JtYXQgc3RyaW5nXG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50LnR6KGQsIHRoaXMucGFyc2VGb3JtYXRzLCB0aGlzLl9vcHRpb25zLmxvY2FsZSwgdGhpcy5fb3B0aW9ucy51c2VTdHJpY3QsIHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQgPSBtb21lbnQoZCwgdGhpcy5wYXJzZUZvcm1hdHMsIHRoaXMuX29wdGlvbnMubG9jYWxlLCB0aGlzLl9vcHRpb25zLnVzZVN0cmljdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50LnR6KHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmV0dXJuTW9tZW50O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS50b2dnbGUgPSBmdW5jdGlvbiB0b2dnbGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWRnZXQgPyB0aGlzLmhpZGUoKSA6IHRoaXMuc2hvdygpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5yZWFkb25seSA9IGZ1bmN0aW9uIHJlYWRvbmx5KF9yZWFkb25seSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5yZWFkb25seTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3JlYWRvbmx5ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWFkb25seSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5yZWFkb25seSA9IF9yZWFkb25seTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnByb3AoJ3JlYWRvbmx5JywgdGhpcy5fb3B0aW9ucy5yZWFkb25seSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuaWdub3JlUmVhZG9ubHkgPSBmdW5jdGlvbiBpZ25vcmVSZWFkb25seShfaWdub3JlUmVhZG9ubHkpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuaWdub3JlUmVhZG9ubHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIF9pZ25vcmVSZWFkb25seSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaWdub3JlUmVhZG9ubHkoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuaWdub3JlUmVhZG9ubHkgPSBfaWdub3JlUmVhZG9ubHk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm9wdGlvbnMgPSBmdW5jdGlvbiBvcHRpb25zKG5ld09wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHRydWUsIHt9LCB0aGlzLl9vcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEobmV3T3B0aW9ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb25zKCkgdGhpcy5vcHRpb25zIHBhcmFtZXRlciBzaG91bGQgYmUgYW4gb2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCB0aGlzLl9vcHRpb25zLCBuZXdPcHRpb25zKTtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcyxcbiAgICAgICAgICAgICAgICBvcHRpb25zS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuX29wdGlvbnMpLnNvcnQob3B0aW9uc1NvcnRGbik7XG4gICAgICAgICAgICAkLmVhY2gob3B0aW9uc0tleXMsIGZ1bmN0aW9uIChpLCBrZXkpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBzZWxmLl9vcHRpb25zW2tleV07XG4gICAgICAgICAgICAgICAgaWYgKHNlbGZba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmlzSW5pdCAmJiBrZXkgPT09ICdkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5oYXNJbml0RGF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXREYXRlID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZltrZXldKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGF0ZSA9IGZ1bmN0aW9uIGRhdGUobmV3RGF0ZSwgaW5kZXgpIHtcbiAgICAgICAgICAgIGluZGV4ID0gaW5kZXggfHwgMDtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlcy5qb2luKHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXNbaW5kZXhdLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobmV3RGF0ZSAhPT0gbnVsbCAmJiB0eXBlb2YgbmV3RGF0ZSAhPT0gJ3N0cmluZycgJiYgIW1vbWVudC5pc01vbWVudChuZXdEYXRlKSAmJiAhKG5ld0RhdGUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgW251bGwsIHN0cmluZywgbW9tZW50IG9yIERhdGVdJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3RGF0ZSA9PT0gJ3N0cmluZycgJiYgaXNWYWxpZERhdGVUaW1lU3RyKG5ld0RhdGUpKSB7XG4gICAgICAgICAgICAgICAgbmV3RGF0ZSA9IG5ldyBEYXRlKG5ld0RhdGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShuZXdEYXRlID09PSBudWxsID8gbnVsbCA6IHRoaXMuX3BhcnNlSW5wdXREYXRlKG5ld0RhdGUpLCBpbmRleCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnVwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbiA9IGZ1bmN0aW9uIHVwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbihfdXBkYXRlT25seVRocm91Z2hEYXRlT3B0aW9uKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIF91cGRhdGVPbmx5VGhyb3VnaERhdGVPcHRpb24gIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbigpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnVwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbiA9IF91cGRhdGVPbmx5VGhyb3VnaERhdGVPcHRpb247XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmZvcm1hdCA9IGZ1bmN0aW9uIGZvcm1hdChuZXdGb3JtYXQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZm9ybWF0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ3N0cmluZycgJiYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdib29sZWFuJyB8fCBuZXdGb3JtYXQgIT09IGZhbHNlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Zvcm1hdCgpIGV4cGVjdHMgYSBzdHJpbmcgb3IgYm9vbGVhbjpmYWxzZSBwYXJhbWV0ZXIgJyArIG5ld0Zvcm1hdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZm9ybWF0ID0gbmV3Rm9ybWF0O1xuICAgICAgICAgICAgaWYgKHRoaXMuYWN0dWFsRm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0aWFsaXplIGZvcm1hdHRpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudGltZVpvbmUgPSBmdW5jdGlvbiB0aW1lWm9uZShuZXdab25lKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnRpbWVab25lO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld1pvbmUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbmV3Wm9uZSgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudGltZVpvbmUgPSBuZXdab25lO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXlWaWV3SGVhZGVyRm9ybWF0ID0gZnVuY3Rpb24gZGF5Vmlld0hlYWRlckZvcm1hdChuZXdGb3JtYXQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGF5Vmlld0hlYWRlckZvcm1hdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF5Vmlld0hlYWRlckZvcm1hdCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF5Vmlld0hlYWRlckZvcm1hdCA9IG5ld0Zvcm1hdDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZXh0cmFGb3JtYXRzID0gZnVuY3Rpb24gZXh0cmFGb3JtYXRzKGZvcm1hdHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZm9ybWF0cyAhPT0gZmFsc2UgJiYgIShmb3JtYXRzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZXh0cmFGb3JtYXRzKCkgZXhwZWN0cyBhbiBhcnJheSBvciBmYWxzZSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMgPSBmb3JtYXRzO1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VGb3JtYXRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0IGZvcm1hdHRpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWREYXRlcyA9IGZ1bmN0aW9uIGRpc2FibGVkRGF0ZXMoZGF0ZXMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMpIDogdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWRhdGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShkYXRlcyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkRGF0ZXMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gdGhpcy5faW5kZXhHaXZlbkRhdGVzKGRhdGVzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZW5hYmxlZERhdGVzID0gZnVuY3Rpb24gZW5hYmxlZERhdGVzKGRhdGVzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcykgOiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFkYXRlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShkYXRlcyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuYWJsZWREYXRlcygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IHRoaXMuX2luZGV4R2l2ZW5EYXRlcyhkYXRlcyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBmdW5jdGlvbiBkYXlzT2ZXZWVrRGlzYWJsZWQoX2RheXNPZldlZWtEaXNhYmxlZCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQuc3BsaWNlKDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9kYXlzT2ZXZWVrRGlzYWJsZWQgPT09ICdib29sZWFuJyAmJiAhX2RheXNPZldlZWtEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF9kYXlzT2ZXZWVrRGlzYWJsZWQgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXlzT2ZXZWVrRGlzYWJsZWQoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBfZGF5c09mV2Vla0Rpc2FibGVkLnJlZHVjZShmdW5jdGlvbiAocHJldmlvdXNWYWx1ZSwgY3VycmVudFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFZhbHVlID0gcGFyc2VJbnQoY3VycmVudFZhbHVlLCAxMCk7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA+IDYgfHwgY3VycmVudFZhbHVlIDwgMCB8fCBpc05hTihjdXJyZW50VmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZS5pbmRleE9mKGN1cnJlbnRWYWx1ZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUucHVzaChjdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcbiAgICAgICAgICAgIH0sIFtdKS5zb3J0KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAzMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAzMSB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubWF4RGF0ZSA9IGZ1bmN0aW9uIG1heERhdGUoX21heERhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubWF4RGF0ZSA/IHRoaXMuX29wdGlvbnMubWF4RGF0ZS5jbG9uZSgpIDogdGhpcy5fb3B0aW9ucy5tYXhEYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9tYXhEYXRlID09PSAnYm9vbGVhbicgJiYgX21heERhdGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5tYXhEYXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21heERhdGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9tYXhEYXRlID09PSAnbm93JyB8fCBfbWF4RGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICAgICAgICAgICAgX21heERhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfbWF4RGF0ZSk7XG5cbiAgICAgICAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXhEYXRlKCkgQ291bGQgbm90IHBhcnNlIGRhdGUgcGFyYW1ldGVyOiAnICsgX21heERhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiBwYXJzZWREYXRlLmlzQmVmb3JlKHRoaXMuX29wdGlvbnMubWluRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXhEYXRlKCkgZGF0ZSBwYXJhbWV0ZXIgaXMgYmVmb3JlIHRoaXMub3B0aW9ucy5taW5EYXRlOiAnICsgcGFyc2VkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWF4RGF0ZSA9IHBhcnNlZERhdGU7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCAmJiB0aGlzLl9kYXRlc1tpXS5pc0FmdGVyKF9tYXhEYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLm1heERhdGUsIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl92aWV3RGF0ZS5pc0FmdGVyKHBhcnNlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSBwYXJzZWREYXRlLmNsb25lKCkuc3VidHJhY3QodGhpcy5fb3B0aW9ucy5zdGVwcGluZywgJ20nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5taW5EYXRlID0gZnVuY3Rpb24gbWluRGF0ZShfbWluRGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5taW5EYXRlID8gdGhpcy5fb3B0aW9ucy5taW5EYXRlLmNsb25lKCkgOiB0aGlzLl9vcHRpb25zLm1pbkRhdGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21pbkRhdGUgPT09ICdib29sZWFuJyAmJiBfbWluRGF0ZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWluRGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoX21pbkRhdGUgPT09ICdub3cnIHx8IF9taW5EYXRlID09PSAnbW9tZW50Jykge1xuICAgICAgICAgICAgICAgICAgICBfbWluRGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKF9taW5EYXRlKTtcblxuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21pbkRhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBfbWluRGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHBhcnNlZERhdGUuaXNBZnRlcih0aGlzLl9vcHRpb25zLm1heERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWluRGF0ZSgpIGRhdGUgcGFyYW1ldGVyIGlzIGFmdGVyIHRoaXMub3B0aW9ucy5tYXhEYXRlOiAnICsgcGFyc2VkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWluRGF0ZSA9IHBhcnNlZERhdGU7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCAmJiB0aGlzLl9kYXRlc1tpXS5pc0JlZm9yZShfbWluRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5taW5EYXRlLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fdmlld0RhdGUuaXNCZWZvcmUocGFyc2VkRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHBhcnNlZERhdGUuY2xvbmUoKS5hZGQodGhpcy5fb3B0aW9ucy5zdGVwcGluZywgJ20nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kZWZhdWx0RGF0ZSA9IGZ1bmN0aW9uIGRlZmF1bHREYXRlKF9kZWZhdWx0RGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA/IHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIV9kZWZhdWx0RGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGVmYXVsdERhdGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9kZWZhdWx0RGF0ZSA9PT0gJ25vdycgfHwgX2RlZmF1bHREYXRlID09PSAnbW9tZW50Jykge1xuICAgICAgICAgICAgICAgICAgICBfZGVmYXVsdERhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF9kZWZhdWx0RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KF9kZWZhdWx0RGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKF9kZWZhdWx0RGF0ZSk7XG4gICAgICAgICAgICBpZiAoIXBhcnNlZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVmYXVsdERhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBfZGVmYXVsdERhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHBhcnNlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVmYXVsdERhdGUoKSBkYXRlIHBhc3NlZCBpcyBpbnZhbGlkIGFjY29yZGluZyB0byBjb21wb25lbnQgc2V0dXAgdmFsaWRhdGlvbnMnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA9IHBhcnNlZERhdGU7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlICYmIHRoaXMuX29wdGlvbnMuaW5saW5lIHx8IHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubG9jYWxlID0gZnVuY3Rpb24gbG9jYWxlKF9sb2NhbGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubG9jYWxlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIW1vbWVudC5sb2NhbGVEYXRhKF9sb2NhbGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbG9jYWxlKCkgbG9jYWxlICcgKyBfbG9jYWxlICsgJyBpcyBub3QgbG9hZGVkIGZyb20gbW9tZW50IGxvY2FsZXMhJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubG9jYWxlID0gX2xvY2FsZTtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5sb2NhbGUodGhpcy5fb3B0aW9ucy5sb2NhbGUpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5hY3R1YWxGb3JtYXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXRpYWxpemUgZm9ybWF0dGluZ1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnN0ZXBwaW5nID0gZnVuY3Rpb24gc3RlcHBpbmcoX3N0ZXBwaW5nKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBfc3RlcHBpbmcgPSBwYXJzZUludChfc3RlcHBpbmcsIDEwKTtcbiAgICAgICAgICAgIGlmIChpc05hTihfc3RlcHBpbmcpIHx8IF9zdGVwcGluZyA8IDEpIHtcbiAgICAgICAgICAgICAgICBfc3RlcHBpbmcgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5zdGVwcGluZyA9IF9zdGVwcGluZztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudXNlQ3VycmVudCA9IGZ1bmN0aW9uIHVzZUN1cnJlbnQoX3VzZUN1cnJlbnQpIHtcbiAgICAgICAgICAgIHZhciB1c2VDdXJyZW50T3B0aW9ucyA9IFsneWVhcicsICdtb250aCcsICdkYXknLCAnaG91cicsICdtaW51dGUnXTtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfdXNlQ3VycmVudCAhPT0gJ2Jvb2xlYW4nICYmIHR5cGVvZiBfdXNlQ3VycmVudCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1c2VDdXJyZW50KCkgZXhwZWN0cyBhIGJvb2xlYW4gb3Igc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfdXNlQ3VycmVudCA9PT0gJ3N0cmluZycgJiYgdXNlQ3VycmVudE9wdGlvbnMuaW5kZXhPZihfdXNlQ3VycmVudC50b0xvd2VyQ2FzZSgpKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1c2VDdXJyZW50KCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXIgb2YgJyArIHVzZUN1cnJlbnRPcHRpb25zLmpvaW4oJywgJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ID0gX3VzZUN1cnJlbnQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmNvbGxhcHNlID0gZnVuY3Rpb24gY29sbGFwc2UoX2NvbGxhcHNlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmNvbGxhcHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9jb2xsYXBzZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignY29sbGFwc2UoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmNvbGxhcHNlID09PSBfY29sbGFwc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuY29sbGFwc2UgPSBfY29sbGFwc2U7XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuaWNvbnMgPSBmdW5jdGlvbiBpY29ucyhfaWNvbnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmljb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX2ljb25zIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2ljb25zKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYW4gT2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQuZXh0ZW5kKHRoaXMuX29wdGlvbnMuaWNvbnMsIF9pY29ucyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS50b29sdGlwcyA9IGZ1bmN0aW9uIHRvb2x0aXBzKF90b29sdGlwcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMudG9vbHRpcHMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfdG9vbHRpcHMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndG9vbHRpcHMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZXh0ZW5kKHRoaXMuX29wdGlvbnMudG9vbHRpcHMsIF90b29sdGlwcyk7XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudXNlU3RyaWN0ID0gZnVuY3Rpb24gdXNlU3RyaWN0KF91c2VTdHJpY3QpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF91c2VTdHJpY3QgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VzZVN0cmljdCgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy51c2VTdHJpY3QgPSBfdXNlU3RyaWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5zaWRlQnlTaWRlID0gZnVuY3Rpb24gc2lkZUJ5U2lkZShfc2lkZUJ5U2lkZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5zaWRlQnlTaWRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9zaWRlQnlTaWRlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzaWRlQnlTaWRlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnNpZGVCeVNpZGUgPSBfc2lkZUJ5U2lkZTtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS52aWV3TW9kZSA9IGZ1bmN0aW9uIHZpZXdNb2RlKF92aWV3TW9kZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy52aWV3TW9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfdmlld01vZGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmlld01vZGUoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoRGF0ZVRpbWVQaWNrZXIuVmlld01vZGVzLmluZGV4T2YoX3ZpZXdNb2RlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3TW9kZSgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiAoJyArIERhdGVUaW1lUGlja2VyLlZpZXdNb2Rlcy5qb2luKCcsICcpICsgJykgdmFsdWUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy52aWV3TW9kZSA9IF92aWV3TW9kZTtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgoRGF0ZVRpbWVQaWNrZXIuVmlld01vZGVzLmluZGV4T2YoX3ZpZXdNb2RlKSAtIDEsIHRoaXMuTWluVmlld01vZGVOdW1iZXIpO1xuXG4gICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5jYWxlbmRhcldlZWtzID0gZnVuY3Rpb24gY2FsZW5kYXJXZWVrcyhfY2FsZW5kYXJXZWVrcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9jYWxlbmRhcldlZWtzICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjYWxlbmRhcldlZWtzKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYSBib29sZWFuIHZhbHVlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcyA9IF9jYWxlbmRhcldlZWtzO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmJ1dHRvbnMgPSBmdW5jdGlvbiBidXR0b25zKF9idXR0b25zKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5idXR0b25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX2J1dHRvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkLmV4dGVuZCh0aGlzLl9vcHRpb25zLmJ1dHRvbnMsIF9idXR0b25zKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd1RvZGF5ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zLnNob3dUb2RheSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbGVhciAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucy5zaG93Q2xlYXIgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93Q2xvc2UgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMuc2hvd0Nsb3NlIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUua2VlcE9wZW4gPSBmdW5jdGlvbiBrZWVwT3Blbihfa2VlcE9wZW4pIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMua2VlcE9wZW47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2tlZXBPcGVuICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdrZWVwT3BlbigpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtlZXBPcGVuID0gX2tlZXBPcGVuO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5mb2N1c09uU2hvdyA9IGZ1bmN0aW9uIGZvY3VzT25TaG93KF9mb2N1c09uU2hvdykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5mb2N1c09uU2hvdztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZm9jdXNPblNob3cgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2ZvY3VzT25TaG93KCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZm9jdXNPblNob3cgPSBfZm9jdXNPblNob3c7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmlubGluZSA9IGZ1bmN0aW9uIGlubGluZShfaW5saW5lKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmlubGluZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfaW5saW5lICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpbmxpbmUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5pbmxpbmUgPSBfaW5saW5lO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobnVsbCk7IC8vdG9kb1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZXlCaW5kcyA9IGZ1bmN0aW9uIGtleUJpbmRzKF9rZXlCaW5kcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZXlCaW5kcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5rZXlCaW5kcyA9IF9rZXlCaW5kcztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGVidWcgPSBmdW5jdGlvbiBkZWJ1ZyhfZGVidWcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RlYnVnICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWJ1ZygpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRlYnVnID0gX2RlYnVnO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5hbGxvd0lucHV0VG9nZ2xlID0gZnVuY3Rpb24gYWxsb3dJbnB1dFRvZ2dsZShfYWxsb3dJbnB1dFRvZ2dsZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9hbGxvd0lucHV0VG9nZ2xlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdhbGxvd0lucHV0VG9nZ2xlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuYWxsb3dJbnB1dFRvZ2dsZSA9IF9hbGxvd0lucHV0VG9nZ2xlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZWVwSW52YWxpZCA9IGZ1bmN0aW9uIGtlZXBJbnZhbGlkKF9rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfa2VlcEludmFsaWQgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2tlZXBJbnZhbGlkKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkID0gX2tlZXBJbnZhbGlkO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXRlcGlja2VySW5wdXQgPSBmdW5jdGlvbiBkYXRlcGlja2VySW5wdXQoX2RhdGVwaWNrZXJJbnB1dCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXRlcGlja2VySW5wdXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RhdGVwaWNrZXJJbnB1dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRlcGlja2VySW5wdXQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRhdGVwaWNrZXJJbnB1dCA9IF9kYXRlcGlja2VySW5wdXQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnBhcnNlSW5wdXREYXRlID0gZnVuY3Rpb24gcGFyc2VJbnB1dERhdGUoX3BhcnNlSW5wdXREYXRlMikge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfcGFyc2VJbnB1dERhdGUyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncGFyc2VJbnB1dERhdGUoKSBzaG91bGQgYmUgYXMgZnVuY3Rpb24nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZSA9IF9wYXJzZUlucHV0RGF0ZTI7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRpc2FibGVkVGltZUludGVydmFscyA9IGZ1bmN0aW9uIGRpc2FibGVkVGltZUludGVydmFscyhfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKF9kaXNhYmxlZFRpbWVJbnRlcnZhbHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZFRpbWVJbnRlcnZhbHMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRpc2FibGVkSG91cnMgPSBmdW5jdGlvbiBkaXNhYmxlZEhvdXJzKGhvdXJzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzKSA6IHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFob3Vycykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoaG91cnMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZEhvdXJzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA9IHRoaXMuX2luZGV4R2l2ZW5Ib3Vycyhob3Vycyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX2RhdGVzW2ldLCAnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpXS5hZGQoMSwgJ2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmllcyA9PT0gMjQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAnVHJpZWQgMjQgdGltZXMgdG8gZmluZCBhIHZhbGlkIGRhdGUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdHJpZXMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1tpXSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmVuYWJsZWRIb3VycyA9IGZ1bmN0aW9uIGVuYWJsZWRIb3Vycyhob3Vycykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMpIDogdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaG91cnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoaG91cnMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmFibGVkSG91cnMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPSB0aGlzLl9pbmRleEdpdmVuSG91cnMoaG91cnMpO1xuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAyNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAyNCB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudmlld0RhdGUgPSBmdW5jdGlvbiB2aWV3RGF0ZShuZXdEYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIW5ld0RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9ICh0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpKS5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0RhdGUgIT09ICdzdHJpbmcnICYmICFtb21lbnQuaXNNb21lbnQobmV3RGF0ZSkgJiYgIShuZXdEYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3RGF0ZSgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiBbc3RyaW5nLCBtb21lbnQgb3IgRGF0ZV0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShuZXdEYXRlKTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZShEYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdICYmIERhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uTkFWX0ZVTkNUSU9OKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2ZpbGxEYXRlID0gZnVuY3Rpb24gX2ZpbGxEYXRlKCkge307XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl91c2VGZWF0aGVySWNvbnMgPSBmdW5jdGlvbiBfdXNlRmVhdGhlckljb25zKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuaWNvbnMudHlwZSA9PT0gJ2ZlYXRoZXInO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5hbGxvd011bHRpZGF0ZSA9IGZ1bmN0aW9uIGFsbG93TXVsdGlkYXRlKF9hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBfYWxsb3dNdWx0aWRhdGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93TXVsdGlkYXRlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgPSBfYWxsb3dNdWx0aWRhdGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm11bHRpZGF0ZVNlcGFyYXRvciA9IGZ1bmN0aW9uIG11bHRpZGF0ZVNlcGFyYXRvcihfbXVsdGlkYXRlU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbXVsdGlkYXRlU2VwYXJhdG9yICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ211bHRpZGF0ZVNlcGFyYXRvciBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciA9IF9tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgIH07XG5cbiAgICAgICAgX2NyZWF0ZUNsYXNzKERhdGVUaW1lUGlja2VyLCBudWxsLCBbe1xuICAgICAgICAgICAga2V5OiAnTkFNRScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTkFNRTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERBVEFfS0VZO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdFVkVOVF9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVWRU5UX0tFWTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9BUElfS0VZJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEQVRBX0FQSV9LRVk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RhdGVQaWNrZXJNb2RlcycsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGF0ZVBpY2tlck1vZGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdWaWV3TW9kZXMnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFZpZXdNb2RlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnRXZlbnQnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdTZWxlY3RvcicsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU2VsZWN0b3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RlZmF1bHQnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBEZWZhdWx0ID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0NsYXNzTmFtZScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gQ2xhc3NOYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XSk7XG5cbiAgICAgICAgcmV0dXJuIERhdGVUaW1lUGlja2VyO1xuICAgIH0oKTtcblxuICAgIHJldHVybiBEYXRlVGltZVBpY2tlcjtcbn0oalF1ZXJ5LCBtb21lbnQpO1xuIiwiLyohQHByZXNlcnZlXHJcbiAqIFRlbXB1cyBEb21pbnVzIEJvb3RzdHJhcDQgdjUuMzkuMCAoaHR0cHM6Ly90ZW1wdXNkb21pbnVzLmdpdGh1Yi5pby9ib290c3RyYXAtNC8pXHJcbiAqIENvcHlyaWdodCAyMDE2LTIwMjAgSm9uYXRoYW4gUGV0ZXJzb24gYW5kIGNvbnRyaWJ1dG9yc1xyXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90ZW1wdXNkb21pbnVzL2Jvb3RzdHJhcC0zL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXHJcbiAqL1xyXG5cclxuaWYgKHR5cGVvZiBqUXVlcnkgPT09ICd1bmRlZmluZWQnKSB7XHJcbiAgdGhyb3cgbmV3IEVycm9yKCdUZW1wdXMgRG9taW51cyBCb290c3RyYXA0XFwncyByZXF1aXJlcyBqUXVlcnkuIGpRdWVyeSBtdXN0IGJlIGluY2x1ZGVkIGJlZm9yZSBUZW1wdXMgRG9taW51cyBCb290c3RyYXA0XFwncyBKYXZhU2NyaXB0LicpO1xyXG59XHJcblxyXG4rZnVuY3Rpb24gKCQpIHtcclxuICB2YXIgdmVyc2lvbiA9ICQuZm4uanF1ZXJ5LnNwbGl0KCcgJylbMF0uc3BsaXQoJy4nKTtcclxuICBpZiAoKHZlcnNpb25bMF0gPCAyICYmIHZlcnNpb25bMV0gPCA5KSB8fCAodmVyc2lvblswXSA9PT0gMSAmJiB2ZXJzaW9uWzFdID09PSA5ICYmIHZlcnNpb25bMl0gPCAxKSB8fCAodmVyc2lvblswXSA+PSA0KSkge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKCdUZW1wdXMgRG9taW51cyBCb290c3RyYXA0XFwncyByZXF1aXJlcyBhdCBsZWFzdCBqUXVlcnkgdjMuMC4wIGJ1dCBsZXNzIHRoYW4gdjQuMC4wJyk7XHJcbiAgfVxyXG59KGpRdWVyeSk7XHJcblxyXG5cclxuaWYgKHR5cGVvZiBtb21lbnQgPT09ICd1bmRlZmluZWQnKSB7XHJcbiAgdGhyb3cgbmV3IEVycm9yKCdUZW1wdXMgRG9taW51cyBCb290c3RyYXA0XFwncyByZXF1aXJlcyBtb21lbnQuanMuIE1vbWVudC5qcyBtdXN0IGJlIGluY2x1ZGVkIGJlZm9yZSBUZW1wdXMgRG9taW51cyBCb290c3RyYXA0XFwncyBKYXZhU2NyaXB0LicpO1xyXG59XHJcblxyXG52YXIgdmVyc2lvbiA9IG1vbWVudC52ZXJzaW9uLnNwbGl0KCcuJylcclxuaWYgKCh2ZXJzaW9uWzBdIDw9IDIgJiYgdmVyc2lvblsxXSA8IDE3KSB8fCAodmVyc2lvblswXSA+PSAzKSkge1xyXG4gIHRocm93IG5ldyBFcnJvcignVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgcmVxdWlyZXMgYXQgbGVhc3QgbW9tZW50LmpzIHYyLjE3LjAgYnV0IGxlc3MgdGhhbiB2My4wLjAnKTtcclxufVxyXG5cclxuK2Z1bmN0aW9uICgpIHtcclxuXHJcbmZ1bmN0aW9uIF9pbmhlcml0c0xvb3NlKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG5mdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9XG5cbmZ1bmN0aW9uIF9jcmVhdGVDbGFzcyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9XG5cbi8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG52YXIgRGF0ZVRpbWVQaWNrZXIgPSBmdW5jdGlvbiAoJCwgbW9tZW50KSB7XG4gIGZ1bmN0aW9uIGVzY2FwZVJlZ0V4cCh0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csICdcXFxcJCYnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzVmFsaWREYXRlKGRhdGUpIHtcbiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGUpID09PSAnW29iamVjdCBEYXRlXScgJiYgIWlzTmFOKGRhdGUuZ2V0VGltZSgpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzVmFsaWREYXRlVGltZVN0cihzdHIpIHtcbiAgICByZXR1cm4gaXNWYWxpZERhdGUobmV3IERhdGUoc3RyKSk7XG4gIH0gLy8gUmVTaGFycGVyIGRpc2FibGUgSW5jb25zaXN0ZW50TmFtaW5nXG5cblxuICB2YXIgdHJpbSA9IGZ1bmN0aW9uIHRyaW0oc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8oXlxccyspfChcXHMrJCkvZywgJycpO1xuICB9LFxuICAgICAgTkFNRSA9ICdkYXRldGltZXBpY2tlcicsXG4gICAgICBEQVRBX0tFWSA9IFwiXCIgKyBOQU1FLFxuICAgICAgRVZFTlRfS0VZID0gXCIuXCIgKyBEQVRBX0tFWSxcbiAgICAgIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknLFxuICAgICAgU2VsZWN0b3IgPSB7XG4gICAgREFUQV9UT0dHTEU6IFwiW2RhdGEtdG9nZ2xlPVxcXCJcIiArIERBVEFfS0VZICsgXCJcXFwiXVwiXG4gIH0sXG4gICAgICBDbGFzc05hbWUgPSB7XG4gICAgSU5QVVQ6IE5BTUUgKyBcIi1pbnB1dFwiXG4gIH0sXG4gICAgICBFdmVudCA9IHtcbiAgICBDSEFOR0U6IFwiY2hhbmdlXCIgKyBFVkVOVF9LRVksXG4gICAgQkxVUjogXCJibHVyXCIgKyBFVkVOVF9LRVksXG4gICAgS0VZVVA6IFwia2V5dXBcIiArIEVWRU5UX0tFWSxcbiAgICBLRVlET1dOOiBcImtleWRvd25cIiArIEVWRU5UX0tFWSxcbiAgICBGT0NVUzogXCJmb2N1c1wiICsgRVZFTlRfS0VZLFxuICAgIENMSUNLX0RBVEFfQVBJOiBcImNsaWNrXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVksXG4gICAgLy9lbWl0dGVkXG4gICAgVVBEQVRFOiBcInVwZGF0ZVwiICsgRVZFTlRfS0VZLFxuICAgIEVSUk9SOiBcImVycm9yXCIgKyBFVkVOVF9LRVksXG4gICAgSElERTogXCJoaWRlXCIgKyBFVkVOVF9LRVksXG4gICAgU0hPVzogXCJzaG93XCIgKyBFVkVOVF9LRVlcbiAgfSxcbiAgICAgIERhdGVQaWNrZXJNb2RlcyA9IFt7XG4gICAgQ0xBU1NfTkFNRTogJ2RheXMnLFxuICAgIE5BVl9GVU5DVElPTjogJ00nLFxuICAgIE5BVl9TVEVQOiAxXG4gIH0sIHtcbiAgICBDTEFTU19OQU1FOiAnbW9udGhzJyxcbiAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICBOQVZfU1RFUDogMVxuICB9LCB7XG4gICAgQ0xBU1NfTkFNRTogJ3llYXJzJyxcbiAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICBOQVZfU1RFUDogMTBcbiAgfSwge1xuICAgIENMQVNTX05BTUU6ICdkZWNhZGVzJyxcbiAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICBOQVZfU1RFUDogMTAwXG4gIH1dLFxuICAgICAgS2V5TWFwID0ge1xuICAgICd1cCc6IDM4LFxuICAgIDM4OiAndXAnLFxuICAgICdkb3duJzogNDAsXG4gICAgNDA6ICdkb3duJyxcbiAgICAnbGVmdCc6IDM3LFxuICAgIDM3OiAnbGVmdCcsXG4gICAgJ3JpZ2h0JzogMzksXG4gICAgMzk6ICdyaWdodCcsXG4gICAgJ3RhYic6IDksXG4gICAgOTogJ3RhYicsXG4gICAgJ2VzY2FwZSc6IDI3LFxuICAgIDI3OiAnZXNjYXBlJyxcbiAgICAnZW50ZXInOiAxMyxcbiAgICAxMzogJ2VudGVyJyxcbiAgICAncGFnZVVwJzogMzMsXG4gICAgMzM6ICdwYWdlVXAnLFxuICAgICdwYWdlRG93bic6IDM0LFxuICAgIDM0OiAncGFnZURvd24nLFxuICAgICdzaGlmdCc6IDE2LFxuICAgIDE2OiAnc2hpZnQnLFxuICAgICdjb250cm9sJzogMTcsXG4gICAgMTc6ICdjb250cm9sJyxcbiAgICAnc3BhY2UnOiAzMixcbiAgICAzMjogJ3NwYWNlJyxcbiAgICAndCc6IDg0LFxuICAgIDg0OiAndCcsXG4gICAgJ2RlbGV0ZSc6IDQ2LFxuICAgIDQ2OiAnZGVsZXRlJ1xuICB9LFxuICAgICAgVmlld01vZGVzID0gWyd0aW1lcycsICdkYXlzJywgJ21vbnRocycsICd5ZWFycycsICdkZWNhZGVzJ10sXG4gICAgICBrZXlTdGF0ZSA9IHt9LFxuICAgICAga2V5UHJlc3NIYW5kbGVkID0ge30sXG4gICAgICBvcHRpb25zU29ydE1hcCA9IHtcbiAgICB0aW1lWm9uZTogLTM5LFxuICAgIGZvcm1hdDogLTM4LFxuICAgIGRheVZpZXdIZWFkZXJGb3JtYXQ6IC0zNyxcbiAgICBleHRyYUZvcm1hdHM6IC0zNixcbiAgICBzdGVwcGluZzogLTM1LFxuICAgIG1pbkRhdGU6IC0zNCxcbiAgICBtYXhEYXRlOiAtMzMsXG4gICAgdXNlQ3VycmVudDogLTMyLFxuICAgIGNvbGxhcHNlOiAtMzEsXG4gICAgbG9jYWxlOiAtMzAsXG4gICAgZGVmYXVsdERhdGU6IC0yOSxcbiAgICBkaXNhYmxlZERhdGVzOiAtMjgsXG4gICAgZW5hYmxlZERhdGVzOiAtMjcsXG4gICAgaWNvbnM6IC0yNixcbiAgICB0b29sdGlwczogLTI1LFxuICAgIHVzZVN0cmljdDogLTI0LFxuICAgIHNpZGVCeVNpZGU6IC0yMyxcbiAgICBkYXlzT2ZXZWVrRGlzYWJsZWQ6IC0yMixcbiAgICBjYWxlbmRhcldlZWtzOiAtMjEsXG4gICAgdmlld01vZGU6IC0yMCxcbiAgICB0b29sYmFyUGxhY2VtZW50OiAtMTksXG4gICAgYnV0dG9uczogLTE4LFxuICAgIHdpZGdldFBvc2l0aW9uaW5nOiAtMTcsXG4gICAgd2lkZ2V0UGFyZW50OiAtMTYsXG4gICAgaWdub3JlUmVhZG9ubHk6IC0xNSxcbiAgICBrZWVwT3BlbjogLTE0LFxuICAgIGZvY3VzT25TaG93OiAtMTMsXG4gICAgaW5saW5lOiAtMTIsXG4gICAga2VlcEludmFsaWQ6IC0xMSxcbiAgICBrZXlCaW5kczogLTEwLFxuICAgIGRlYnVnOiAtOSxcbiAgICBhbGxvd0lucHV0VG9nZ2xlOiAtOCxcbiAgICBkaXNhYmxlZFRpbWVJbnRlcnZhbHM6IC03LFxuICAgIGRpc2FibGVkSG91cnM6IC02LFxuICAgIGVuYWJsZWRIb3VyczogLTUsXG4gICAgdmlld0RhdGU6IC00LFxuICAgIGFsbG93TXVsdGlkYXRlOiAtMyxcbiAgICBtdWx0aWRhdGVTZXBhcmF0b3I6IC0yLFxuICAgIHVwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbjogLTEsXG4gICAgZGF0ZTogMVxuICB9LFxuICAgICAgZGVmYXVsdEZlYXRoZXJJY29ucyA9IHtcbiAgICB0aW1lOiAnY2xvY2snLFxuICAgIGRhdGU6ICdjYWxlbmRhcicsXG4gICAgdXA6ICdhcnJvdy11cCcsXG4gICAgZG93bjogJ2Fycm93LWRvd24nLFxuICAgIHByZXZpb3VzOiAnYXJyb3ctbGVmdCcsXG4gICAgbmV4dDogJ2Fycm93LXJpZ2h0JyxcbiAgICB0b2RheTogJ2Fycm93LWRvd24tY2lyY2xlJyxcbiAgICBjbGVhcjogJ3RyYXNoLTInLFxuICAgIGNsb3NlOiAneCdcbiAgfTtcblxuICBmdW5jdGlvbiBvcHRpb25zU29ydEZuKG9wdGlvbktleUEsIG9wdGlvbktleUIpIHtcbiAgICBpZiAob3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5QV0gJiYgb3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5Ql0pIHtcbiAgICAgIGlmIChvcHRpb25zU29ydE1hcFtvcHRpb25LZXlBXSA8IDAgJiYgb3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5Ql0gPCAwKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmFicyhvcHRpb25zU29ydE1hcFtvcHRpb25LZXlCXSkgLSBNYXRoLmFicyhvcHRpb25zU29ydE1hcFtvcHRpb25LZXlBXSk7XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnNTb3J0TWFwW29wdGlvbktleUFdIDwgMCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnNTb3J0TWFwW29wdGlvbktleUJdIDwgMCkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9wdGlvbnNTb3J0TWFwW29wdGlvbktleUFdIC0gb3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5Ql07XG4gICAgfSBlbHNlIGlmIChvcHRpb25zU29ydE1hcFtvcHRpb25LZXlBXSkge1xuICAgICAgcmV0dXJuIG9wdGlvbnNTb3J0TWFwW29wdGlvbktleUFdO1xuICAgIH0gZWxzZSBpZiAob3B0aW9uc1NvcnRNYXBbb3B0aW9uS2V5Ql0pIHtcbiAgICAgIHJldHVybiBvcHRpb25zU29ydE1hcFtvcHRpb25LZXlCXTtcbiAgICB9XG5cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIHZhciBEZWZhdWx0ID0ge1xuICAgIHRpbWVab25lOiAnJyxcbiAgICBmb3JtYXQ6IGZhbHNlLFxuICAgIGRheVZpZXdIZWFkZXJGb3JtYXQ6ICdNTU1NIFlZWVknLFxuICAgIGV4dHJhRm9ybWF0czogZmFsc2UsXG4gICAgc3RlcHBpbmc6IDEsXG4gICAgbWluRGF0ZTogZmFsc2UsXG4gICAgbWF4RGF0ZTogZmFsc2UsXG4gICAgdXNlQ3VycmVudDogdHJ1ZSxcbiAgICBjb2xsYXBzZTogdHJ1ZSxcbiAgICBsb2NhbGU6IG1vbWVudC5sb2NhbGUoKSxcbiAgICBkZWZhdWx0RGF0ZTogZmFsc2UsXG4gICAgZGlzYWJsZWREYXRlczogZmFsc2UsXG4gICAgZW5hYmxlZERhdGVzOiBmYWxzZSxcbiAgICBpY29uczoge1xuICAgICAgdHlwZTogJ2NsYXNzJyxcbiAgICAgIHRpbWU6ICdmYSBmYS1jbG9jay1vJyxcbiAgICAgIGRhdGU6ICdmYSBmYS1jYWxlbmRhcicsXG4gICAgICB1cDogJ2ZhIGZhLWFycm93LXVwJyxcbiAgICAgIGRvd246ICdmYSBmYS1hcnJvdy1kb3duJyxcbiAgICAgIHByZXZpb3VzOiAnZmEgZmEtY2hldnJvbi1sZWZ0JyxcbiAgICAgIG5leHQ6ICdmYSBmYS1jaGV2cm9uLXJpZ2h0JyxcbiAgICAgIHRvZGF5OiAnZmEgZmEtY2FsZW5kYXItY2hlY2stbycsXG4gICAgICBjbGVhcjogJ2ZhIGZhLXRyYXNoJyxcbiAgICAgIGNsb3NlOiAnZmEgZmEtdGltZXMnXG4gICAgfSxcbiAgICB0b29sdGlwczoge1xuICAgICAgdG9kYXk6ICdHbyB0byB0b2RheScsXG4gICAgICBjbGVhcjogJ0NsZWFyIHNlbGVjdGlvbicsXG4gICAgICBjbG9zZTogJ0Nsb3NlIHRoZSBwaWNrZXInLFxuICAgICAgc2VsZWN0TW9udGg6ICdTZWxlY3QgTW9udGgnLFxuICAgICAgcHJldk1vbnRoOiAnUHJldmlvdXMgTW9udGgnLFxuICAgICAgbmV4dE1vbnRoOiAnTmV4dCBNb250aCcsXG4gICAgICBzZWxlY3RZZWFyOiAnU2VsZWN0IFllYXInLFxuICAgICAgcHJldlllYXI6ICdQcmV2aW91cyBZZWFyJyxcbiAgICAgIG5leHRZZWFyOiAnTmV4dCBZZWFyJyxcbiAgICAgIHNlbGVjdERlY2FkZTogJ1NlbGVjdCBEZWNhZGUnLFxuICAgICAgcHJldkRlY2FkZTogJ1ByZXZpb3VzIERlY2FkZScsXG4gICAgICBuZXh0RGVjYWRlOiAnTmV4dCBEZWNhZGUnLFxuICAgICAgcHJldkNlbnR1cnk6ICdQcmV2aW91cyBDZW50dXJ5JyxcbiAgICAgIG5leHRDZW50dXJ5OiAnTmV4dCBDZW50dXJ5JyxcbiAgICAgIHBpY2tIb3VyOiAnUGljayBIb3VyJyxcbiAgICAgIGluY3JlbWVudEhvdXI6ICdJbmNyZW1lbnQgSG91cicsXG4gICAgICBkZWNyZW1lbnRIb3VyOiAnRGVjcmVtZW50IEhvdXInLFxuICAgICAgcGlja01pbnV0ZTogJ1BpY2sgTWludXRlJyxcbiAgICAgIGluY3JlbWVudE1pbnV0ZTogJ0luY3JlbWVudCBNaW51dGUnLFxuICAgICAgZGVjcmVtZW50TWludXRlOiAnRGVjcmVtZW50IE1pbnV0ZScsXG4gICAgICBwaWNrU2Vjb25kOiAnUGljayBTZWNvbmQnLFxuICAgICAgaW5jcmVtZW50U2Vjb25kOiAnSW5jcmVtZW50IFNlY29uZCcsXG4gICAgICBkZWNyZW1lbnRTZWNvbmQ6ICdEZWNyZW1lbnQgU2Vjb25kJyxcbiAgICAgIHRvZ2dsZVBlcmlvZDogJ1RvZ2dsZSBQZXJpb2QnLFxuICAgICAgc2VsZWN0VGltZTogJ1NlbGVjdCBUaW1lJyxcbiAgICAgIHNlbGVjdERhdGU6ICdTZWxlY3QgRGF0ZSdcbiAgICB9LFxuICAgIHVzZVN0cmljdDogZmFsc2UsXG4gICAgc2lkZUJ5U2lkZTogZmFsc2UsXG4gICAgZGF5c09mV2Vla0Rpc2FibGVkOiBmYWxzZSxcbiAgICBjYWxlbmRhcldlZWtzOiBmYWxzZSxcbiAgICB2aWV3TW9kZTogJ2RheXMnLFxuICAgIHRvb2xiYXJQbGFjZW1lbnQ6ICdkZWZhdWx0JyxcbiAgICBidXR0b25zOiB7XG4gICAgICBzaG93VG9kYXk6IGZhbHNlLFxuICAgICAgc2hvd0NsZWFyOiBmYWxzZSxcbiAgICAgIHNob3dDbG9zZTogZmFsc2VcbiAgICB9LFxuICAgIHdpZGdldFBvc2l0aW9uaW5nOiB7XG4gICAgICBob3Jpem9udGFsOiAnYXV0bycsXG4gICAgICB2ZXJ0aWNhbDogJ2F1dG8nXG4gICAgfSxcbiAgICB3aWRnZXRQYXJlbnQ6IG51bGwsXG4gICAgcmVhZG9ubHk6IGZhbHNlLFxuICAgIGlnbm9yZVJlYWRvbmx5OiBmYWxzZSxcbiAgICBrZWVwT3BlbjogZmFsc2UsXG4gICAgZm9jdXNPblNob3c6IHRydWUsXG4gICAgaW5saW5lOiBmYWxzZSxcbiAgICBrZWVwSW52YWxpZDogZmFsc2UsXG4gICAga2V5QmluZHM6IHtcbiAgICAgIHVwOiBmdW5jdGlvbiB1cCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcblxuICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoNywgJ2QnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQodGhpcy5zdGVwcGluZygpLCAnbScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgIGRvd246IGZ1bmN0aW9uIGRvd24oKSB7XG4gICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG5cbiAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCg3LCAnZCcpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuc3RlcHBpbmcoKSwgJ20nKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgICAnY29udHJvbCB1cCc6IGZ1bmN0aW9uIGNvbnRyb2xVcCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcblxuICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ3knKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ2gnKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgICAnY29udHJvbCBkb3duJzogZnVuY3Rpb24gY29udHJvbERvd24oKSB7XG4gICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG5cbiAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAneScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdoJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9LFxuICAgICAgbGVmdDogZnVuY3Rpb24gbGVmdCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcblxuICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ2QnKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgICByaWdodDogZnVuY3Rpb24gcmlnaHQoKSB7XG4gICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG5cbiAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnZCcpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgIHBhZ2VVcDogZnVuY3Rpb24gcGFnZVVwKCkge1xuICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuXG4gICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnTScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgIHBhZ2VEb3duOiBmdW5jdGlvbiBwYWdlRG93bigpIHtcbiAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcblxuICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICdNJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9LFxuICAgICAgZW50ZXI6IGZ1bmN0aW9uIGVudGVyKCkge1xuICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgIGVzY2FwZTogZnVuY3Rpb24gZXNjYXBlKCkge1xuICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgICdjb250cm9sIHNwYWNlJzogZnVuY3Rpb24gY29udHJvbFNwYWNlKCkge1xuICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcuYnRuW2RhdGEtYWN0aW9uPVwidG9nZ2xlUGVyaW9kXCJdJykuY2xpY2soKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgIHQ6IGZ1bmN0aW9uIHQoKSB7XG4gICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmRhdGUodGhpcy5nZXRNb21lbnQoKSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgICdkZWxldGUnOiBmdW5jdGlvbiBfZGVsZXRlKCkge1xuICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGRlYnVnOiBmYWxzZSxcbiAgICBhbGxvd0lucHV0VG9nZ2xlOiBmYWxzZSxcbiAgICBkaXNhYmxlZFRpbWVJbnRlcnZhbHM6IGZhbHNlLFxuICAgIGRpc2FibGVkSG91cnM6IGZhbHNlLFxuICAgIGVuYWJsZWRIb3VyczogZmFsc2UsXG4gICAgdmlld0RhdGU6IGZhbHNlLFxuICAgIGFsbG93TXVsdGlkYXRlOiBmYWxzZSxcbiAgICBtdWx0aWRhdGVTZXBhcmF0b3I6ICcsICcsXG4gICAgdXBkYXRlT25seVRocm91Z2hEYXRlT3B0aW9uOiBmYWxzZSxcbiAgICBwcm9tcHRUaW1lT25EYXRlQ2hhbmdlOiBmYWxzZSxcbiAgICBwcm9tcHRUaW1lT25EYXRlQ2hhbmdlVHJhbnNpdGlvbkRlbGF5OiAyMDBcbiAgfTsgLy8gUmVTaGFycGVyIHJlc3RvcmUgSW5jb25zaXN0ZW50TmFtaW5nXG4gIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgRGVjbGFyYXRpb25IaWRlc1xuICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIEluY29uc2lzdGVudE5hbWluZ1xuXG4gIHZhciBEYXRlVGltZVBpY2tlciA9IC8qI19fUFVSRV9fKi9mdW5jdGlvbiAoKSB7XG4gICAgLyoqIEBuYW1lc3BhY2UgZURhdGEuZGF0ZU9wdGlvbnMgKi9cblxuICAgIC8qKiBAbmFtZXNwYWNlIG1vbWVudC50eiAqL1xuICAgIGZ1bmN0aW9uIERhdGVUaW1lUGlja2VyKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAgIHRoaXMuX29wdGlvbnMgPSB0aGlzLl9nZXRPcHRpb25zKG9wdGlvbnMpO1xuICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICB0aGlzLl9kYXRlcyA9IFtdO1xuICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWQgPSBbXTtcbiAgICAgIHRoaXMuX3ZpZXdEYXRlID0gbnVsbDtcbiAgICAgIHRoaXMudW5zZXQgPSB0cnVlO1xuICAgICAgdGhpcy5jb21wb25lbnQgPSBmYWxzZTtcbiAgICAgIHRoaXMud2lkZ2V0ID0gZmFsc2U7XG4gICAgICB0aGlzLnVzZTI0SG91cnMgPSBudWxsO1xuICAgICAgdGhpcy5hY3R1YWxGb3JtYXQgPSBudWxsO1xuICAgICAgdGhpcy5wYXJzZUZvcm1hdHMgPSBudWxsO1xuICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBudWxsO1xuICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDA7XG4gICAgICB0aGlzLmlzSW5pdEZvcm1hdHRpbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMuaXNJbml0ID0gZmFsc2U7XG4gICAgICB0aGlzLmlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGUgPSBmYWxzZTtcbiAgICAgIHRoaXMuaGFzSW5pdERhdGUgPSBmYWxzZTtcbiAgICAgIHRoaXMuaW5pdERhdGUgPSB2b2lkIDA7XG4gICAgICB0aGlzLl9ub3RpZnlDaGFuZ2VFdmVudENvbnRleHQgPSB2b2lkIDA7XG4gICAgICB0aGlzLl9jdXJyZW50UHJvbXB0VGltZVRpbWVvdXQgPSBudWxsO1xuXG4gICAgICB0aGlzLl9pbnQoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHJldHVybiB7c3RyaW5nfVxuICAgICAqL1xuXG5cbiAgICB2YXIgX3Byb3RvID0gRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlO1xuXG4gICAgLy9wcml2YXRlXG4gICAgX3Byb3RvLl9pbnQgPSBmdW5jdGlvbiBfaW50KCkge1xuICAgICAgdGhpcy5pc0luaXQgPSB0cnVlO1xuXG4gICAgICB2YXIgdGFyZ2V0SW5wdXQgPSB0aGlzLl9lbGVtZW50LmRhdGEoJ3RhcmdldC1pbnB1dCcpO1xuXG4gICAgICBpZiAodGhpcy5fZWxlbWVudC5pcygnaW5wdXQnKSkge1xuICAgICAgICB0aGlzLmlucHV0ID0gdGhpcy5fZWxlbWVudDtcbiAgICAgIH0gZWxzZSBpZiAodGFyZ2V0SW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAodGFyZ2V0SW5wdXQgPT09ICduZWFyZXN0Jykge1xuICAgICAgICAgIHRoaXMuaW5wdXQgPSB0aGlzLl9lbGVtZW50LmZpbmQoJ2lucHV0Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5pbnB1dCA9ICQodGFyZ2V0SW5wdXQpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICB0aGlzLl9kYXRlc1swXSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCkuY2xvbmUoKTtcbiAgICAgICQuZXh0ZW5kKHRydWUsIHRoaXMuX29wdGlvbnMsIHRoaXMuX2RhdGFUb09wdGlvbnMoKSk7XG4gICAgICB0aGlzLmhhc0luaXREYXRlID0gZmFsc2U7XG4gICAgICB0aGlzLmluaXREYXRlID0gdm9pZCAwO1xuICAgICAgdGhpcy5vcHRpb25zKHRoaXMuX29wdGlvbnMpO1xuICAgICAgdGhpcy5pc0luaXRGb3JtYXR0aW5nID0gdHJ1ZTtcblxuICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTtcblxuICAgICAgdGhpcy5pc0luaXRGb3JtYXR0aW5nID0gZmFsc2U7XG5cbiAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC5pcygnaW5wdXQnKSAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fcGFyc2VJbnB1dERhdGUodGhpcy5pbnB1dC52YWwoKS50cmltKCkpLCAwKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiB0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC5hdHRyKCdwbGFjZWhvbGRlcicpID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSwgMCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmhhc0luaXREYXRlKSB7XG4gICAgICAgIHRoaXMuZGF0ZSh0aGlzLmluaXREYXRlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmlzSW5pdCA9IGZhbHNlO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX3VwZGF0ZSA9IGZ1bmN0aW9uIF91cGRhdGUoKSB7XG4gICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fZmlsbERhdGUoKTtcblxuICAgICAgdGhpcy5fZmlsbFRpbWUoKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9zZXRWYWx1ZSA9IGZ1bmN0aW9uIF9zZXRWYWx1ZSh0YXJnZXRNb21lbnQsIGluZGV4KSB7XG4gICAgICB2YXIgbm9JbmRleCA9IHR5cGVvZiBpbmRleCA9PT0gJ3VuZGVmaW5lZCcsXG4gICAgICAgICAgaXNDbGVhciA9ICF0YXJnZXRNb21lbnQgJiYgbm9JbmRleCxcbiAgICAgICAgICBpc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlID0gdGhpcy5pc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlLFxuICAgICAgICAgIGlzTm90QWxsb3dlZFByb2dyYW1tYXRpY1VwZGF0ZSA9ICF0aGlzLmlzSW5pdCAmJiB0aGlzLl9vcHRpb25zLnVwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbiAmJiAhaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZTtcbiAgICAgIHZhciBvdXRwVmFsdWUgPSAnJyxcbiAgICAgICAgICBpc0ludmFsaWQgPSBmYWxzZSxcbiAgICAgICAgICBvbGREYXRlID0gdGhpcy51bnNldCA/IG51bGwgOiB0aGlzLl9kYXRlc1tpbmRleF07XG5cbiAgICAgIGlmICghb2xkRGF0ZSAmJiAhdGhpcy51bnNldCAmJiBub0luZGV4ICYmIGlzQ2xlYXIpIHtcbiAgICAgICAgb2xkRGF0ZSA9IHRoaXMuX2RhdGVzW3RoaXMuX2RhdGVzLmxlbmd0aCAtIDFdO1xuICAgICAgfSAvLyBjYXNlIG9mIGNhbGxpbmcgc2V0VmFsdWUobnVsbCBvciBmYWxzZSlcblxuXG4gICAgICBpZiAoIXRhcmdldE1vbWVudCkge1xuICAgICAgICBpZiAoaXNOb3RBbGxvd2VkUHJvZ3JhbW1hdGljVXBkYXRlKSB7XG4gICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLFxuICAgICAgICAgICAgZGF0ZTogdGFyZ2V0TW9tZW50LFxuICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZSxcbiAgICAgICAgICAgIGlzQ2xlYXI6IGlzQ2xlYXIsXG4gICAgICAgICAgICBpc0ludmFsaWQ6IGlzSW52YWxpZCxcbiAgICAgICAgICAgIGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGU6IGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGUsXG4gICAgICAgICAgICBpc0luaXQ6IHRoaXMuaXNJbml0XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgfHwgdGhpcy5fZGF0ZXMubGVuZ3RoID09PSAxIHx8IGlzQ2xlYXIpIHtcbiAgICAgICAgICB0aGlzLnVuc2V0ID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLl9kYXRlcyA9IFtdO1xuICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3V0cFZhbHVlID0gXCJcIiArIHRoaXMuX2VsZW1lbnQuZGF0YSgnZGF0ZScpICsgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgICAgb3V0cFZhbHVlID0gb2xkRGF0ZSAmJiBvdXRwVmFsdWUucmVwbGFjZShcIlwiICsgb2xkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpICsgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3IsICcnKS5yZXBsYWNlKFwiXCIgKyB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciArIHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yLCAnJykucmVwbGFjZShuZXcgUmVnRXhwKGVzY2FwZVJlZ0V4cCh0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcikgKyBcIlxcXFxzKiRcIiksICcnKSB8fCAnJztcblxuICAgICAgICAgIHRoaXMuX2RhdGVzLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgb3V0cFZhbHVlID0gdHJpbShvdXRwVmFsdWUpO1xuXG4gICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aGlzLmlucHV0LnZhbChvdXRwVmFsdWUpO1xuICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuZGF0YSgnZGF0ZScsIG91dHBWYWx1ZSk7XG5cbiAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICBkYXRlOiBmYWxzZSxcbiAgICAgICAgICBvbGREYXRlOiBvbGREYXRlLFxuICAgICAgICAgIGlzQ2xlYXI6IGlzQ2xlYXIsXG4gICAgICAgICAgaXNJbnZhbGlkOiBpc0ludmFsaWQsXG4gICAgICAgICAgaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZTogaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZSxcbiAgICAgICAgICBpc0luaXQ6IHRoaXMuaXNJbml0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGFyZ2V0TW9tZW50ID0gdGFyZ2V0TW9tZW50LmNsb25lKCkubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcblxuICAgICAgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgdGFyZ2V0TW9tZW50LnR6KHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5zdGVwcGluZyAhPT0gMSkge1xuICAgICAgICB0YXJnZXRNb21lbnQubWludXRlcyhNYXRoLnJvdW5kKHRhcmdldE1vbWVudC5taW51dGVzKCkgLyB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nKSAqIHRoaXMuX29wdGlvbnMuc3RlcHBpbmcpLnNlY29uZHMoMCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgaWYgKGlzTm90QWxsb3dlZFByb2dyYW1tYXRpY1VwZGF0ZSkge1xuICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgIGRhdGU6IHRhcmdldE1vbWVudC5jbG9uZSgpLFxuICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZSxcbiAgICAgICAgICAgIGlzQ2xlYXI6IGlzQ2xlYXIsXG4gICAgICAgICAgICBpc0ludmFsaWQ6IGlzSW52YWxpZCxcbiAgICAgICAgICAgIGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGU6IGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGUsXG4gICAgICAgICAgICBpc0luaXQ6IHRoaXMuaXNJbml0XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9kYXRlc1tpbmRleF0gPSB0YXJnZXRNb21lbnQ7XG4gICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkW2luZGV4XSA9IHRhcmdldE1vbWVudC5mb3JtYXQoJ1lZWVktTU0tREQnKTtcbiAgICAgICAgdGhpcy5fdmlld0RhdGUgPSB0YXJnZXRNb21lbnQuY2xvbmUoKTtcblxuICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSAmJiB0aGlzLl9kYXRlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3V0cFZhbHVlICs9IFwiXCIgKyB0aGlzLl9kYXRlc1tpXS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpICsgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgb3V0cFZhbHVlID0gb3V0cFZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cCh0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciArIFwiXFxcXHMqJFwiKSwgJycpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG91dHBWYWx1ZSA9IHRoaXMuX2RhdGVzW2luZGV4XS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgb3V0cFZhbHVlID0gdHJpbShvdXRwVmFsdWUpO1xuXG4gICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aGlzLmlucHV0LnZhbChvdXRwVmFsdWUpO1xuICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuZGF0YSgnZGF0ZScsIG91dHBWYWx1ZSk7XG5cbiAgICAgICAgdGhpcy51bnNldCA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuXG4gICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgZGF0ZTogdGhpcy5fZGF0ZXNbaW5kZXhdLmNsb25lKCksXG4gICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZSxcbiAgICAgICAgICBpc0NsZWFyOiBpc0NsZWFyLFxuICAgICAgICAgIGlzSW52YWxpZDogaXNJbnZhbGlkLFxuICAgICAgICAgIGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGU6IGlzRGF0ZVVwZGF0ZVRocm91Z2hEYXRlT3B0aW9uRnJvbUNsaWVudENvZGUsXG4gICAgICAgICAgaXNJbml0OiB0aGlzLmlzSW5pdFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlzSW52YWxpZCA9IHRydWU7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwoXCJcIiArICh0aGlzLnVuc2V0ID8gJycgOiB0aGlzLl9kYXRlc1tpbmRleF0uZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSkpO1xuICAgICAgICAgICAgdGhpcy5pbnB1dC50cmlnZ2VyKCdpbnB1dCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQsXG4gICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlLFxuICAgICAgICAgICAgaXNDbGVhcjogaXNDbGVhcixcbiAgICAgICAgICAgIGlzSW52YWxpZDogaXNJbnZhbGlkLFxuICAgICAgICAgICAgaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZTogaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZSxcbiAgICAgICAgICAgIGlzSW5pdDogdGhpcy5pc0luaXRcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5FUlJPUixcbiAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQsXG4gICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9jaGFuZ2UgPSBmdW5jdGlvbiBfY2hhbmdlKGUpIHtcbiAgICAgIHZhciB2YWwgPSAkKGUudGFyZ2V0KS52YWwoKS50cmltKCksXG4gICAgICAgICAgcGFyc2VkRGF0ZSA9IHZhbCA/IHRoaXMuX3BhcnNlSW5wdXREYXRlKHZhbCkgOiBudWxsO1xuXG4gICAgICB0aGlzLl9zZXRWYWx1ZShwYXJzZWREYXRlLCAwKTtcblxuICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IC8vbm9pbnNwZWN0aW9uIEpTTWV0aG9kQ2FuQmVTdGF0aWNcbiAgICA7XG5cbiAgICBfcHJvdG8uX2dldE9wdGlvbnMgPSBmdW5jdGlvbiBfZ2V0T3B0aW9ucyhvcHRpb25zKSB7XG4gICAgICBvcHRpb25zID0gJC5leHRlbmQodHJ1ZSwge30sIERlZmF1bHQsIG9wdGlvbnMgJiYgb3B0aW9ucy5pY29ucyAmJiBvcHRpb25zLmljb25zLnR5cGUgPT09ICdmZWF0aGVyJyA/IHtcbiAgICAgICAgaWNvbnM6IGRlZmF1bHRGZWF0aGVySWNvbnNcbiAgICAgIH0gOiB7fSwgb3B0aW9ucyk7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9oYXNUaW1lWm9uZSA9IGZ1bmN0aW9uIF9oYXNUaW1lWm9uZSgpIHtcbiAgICAgIHJldHVybiBtb21lbnQudHogIT09IHVuZGVmaW5lZCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gbnVsbCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSAnJztcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9pc0VuYWJsZWQgPSBmdW5jdGlvbiBfaXNFbmFibGVkKGdyYW51bGFyaXR5KSB7XG4gICAgICBpZiAodHlwZW9mIGdyYW51bGFyaXR5ICE9PSAnc3RyaW5nJyB8fCBncmFudWxhcml0eS5sZW5ndGggPiAxKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lzRW5hYmxlZCBleHBlY3RzIGEgc2luZ2xlIGNoYXJhY3RlciBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICB9XG5cbiAgICAgIHN3aXRjaCAoZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgY2FzZSAneSc6XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ1knKSAhPT0gLTE7XG5cbiAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ00nKSAhPT0gLTE7XG5cbiAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZCcpICE9PSAtMTtcblxuICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgY2FzZSAnSCc6XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignaCcpICE9PSAtMTtcblxuICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZignbScpICE9PSAtMTtcblxuICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZigncycpICE9PSAtMTtcblxuICAgICAgICBjYXNlICdhJzpcbiAgICAgICAgY2FzZSAnQSc6XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignYScpICE9PSAtMTtcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9oYXNUaW1lID0gZnVuY3Rpb24gX2hhc1RpbWUoKSB7XG4gICAgICByZXR1cm4gdGhpcy5faXNFbmFibGVkKCdoJykgfHwgdGhpcy5faXNFbmFibGVkKCdtJykgfHwgdGhpcy5faXNFbmFibGVkKCdzJyk7XG4gICAgfTtcblxuICAgIF9wcm90by5faGFzRGF0ZSA9IGZ1bmN0aW9uIF9oYXNEYXRlKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2lzRW5hYmxlZCgneScpIHx8IHRoaXMuX2lzRW5hYmxlZCgnTScpIHx8IHRoaXMuX2lzRW5hYmxlZCgnZCcpO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2RhdGFUb09wdGlvbnMgPSBmdW5jdGlvbiBfZGF0YVRvT3B0aW9ucygpIHtcbiAgICAgIHZhciBlRGF0YSA9IHRoaXMuX2VsZW1lbnQuZGF0YSgpO1xuXG4gICAgICB2YXIgZGF0YU9wdGlvbnMgPSB7fTtcblxuICAgICAgaWYgKGVEYXRhLmRhdGVPcHRpb25zICYmIGVEYXRhLmRhdGVPcHRpb25zIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgIGRhdGFPcHRpb25zID0gJC5leHRlbmQodHJ1ZSwgZGF0YU9wdGlvbnMsIGVEYXRhLmRhdGVPcHRpb25zKTtcbiAgICAgIH1cblxuICAgICAgJC5lYWNoKHRoaXMuX29wdGlvbnMsIGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgdmFyIGF0dHJpYnV0ZU5hbWUgPSBcImRhdGVcIiArIGtleS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGtleS5zbGljZSgxKTsgLy90b2RvIGRhdGEgYXBpIGtleVxuXG4gICAgICAgIGlmIChlRGF0YVthdHRyaWJ1dGVOYW1lXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgZGF0YU9wdGlvbnNba2V5XSA9IGVEYXRhW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBkYXRhT3B0aW9uc1trZXldO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBkYXRhT3B0aW9ucztcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9mb3JtYXQgPSBmdW5jdGlvbiBfZm9ybWF0KCkge1xuICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZm9ybWF0IHx8ICdZWVlZLU1NLUREIEhIOm1tJztcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9hcmVTYW1lRGF0ZXMgPSBmdW5jdGlvbiBfYXJlU2FtZURhdGVzKGEsIGIpIHtcbiAgICAgIHZhciBmb3JtYXQgPSB0aGlzLl9mb3JtYXQoKTtcblxuICAgICAgcmV0dXJuIGEgJiYgYiAmJiAoYS5pc1NhbWUoYikgfHwgbW9tZW50KGEuZm9ybWF0KGZvcm1hdCksIGZvcm1hdCkuaXNTYW1lKG1vbWVudChiLmZvcm1hdChmb3JtYXQpLCBmb3JtYXQpKSk7XG4gICAgfTtcblxuICAgIF9wcm90by5fbm90aWZ5RXZlbnQgPSBmdW5jdGlvbiBfbm90aWZ5RXZlbnQoZSkge1xuICAgICAgaWYgKGUudHlwZSA9PT0gRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFKSB7XG4gICAgICAgIHRoaXMuX25vdGlmeUNoYW5nZUV2ZW50Q29udGV4dCA9IHRoaXMuX25vdGlmeUNoYW5nZUV2ZW50Q29udGV4dCB8fCAwO1xuICAgICAgICB0aGlzLl9ub3RpZnlDaGFuZ2VFdmVudENvbnRleHQrKztcblxuICAgICAgICBpZiAoZS5kYXRlICYmIHRoaXMuX2FyZVNhbWVEYXRlcyhlLmRhdGUsIGUub2xkRGF0ZSkgfHwgIWUuaXNDbGVhciAmJiAhZS5kYXRlICYmICFlLm9sZERhdGUgfHwgdGhpcy5fbm90aWZ5Q2hhbmdlRXZlbnRDb250ZXh0ID4gMSkge1xuICAgICAgICAgIHRoaXMuX25vdGlmeUNoYW5nZUV2ZW50Q29udGV4dCA9IHZvaWQgMDtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9oYW5kbGVQcm9tcHRUaW1lSWZOZWVkZWQoZSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQudHJpZ2dlcihlKTtcblxuICAgICAgdGhpcy5fbm90aWZ5Q2hhbmdlRXZlbnRDb250ZXh0ID0gdm9pZCAwO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2hhbmRsZVByb21wdFRpbWVJZk5lZWRlZCA9IGZ1bmN0aW9uIF9oYW5kbGVQcm9tcHRUaW1lSWZOZWVkZWQoZSkge1xuICAgICAgaWYgKHRoaXMuX29wdGlvbnMucHJvbXB0VGltZU9uRGF0ZUNoYW5nZSkge1xuICAgICAgICBpZiAoIWUub2xkRGF0ZSAmJiB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQpIHtcbiAgICAgICAgICAvLyBGaXJzdCB0aW1lIGV2ZXIuIElmIHVzZUN1cnJlbnQgb3B0aW9uIGlzIHNldCB0byB0cnVlIChkZWZhdWx0KSwgZG8gbm90aGluZ1xuICAgICAgICAgIC8vIGJlY2F1c2UgdGhlIGZpcnN0IGRhdGUgaXMgc2VsZWN0ZWQgYXV0b21hdGljYWxseS5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoZS5vbGREYXRlICYmIGUuZGF0ZSAmJiAoZS5vbGREYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpID09PSBlLmRhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykgfHwgZS5vbGREYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpICE9PSBlLmRhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykgJiYgZS5vbGREYXRlLmZvcm1hdCgnSEg6bW06c3MnKSAhPT0gZS5kYXRlLmZvcm1hdCgnSEg6bW06c3MnKSkpIHtcbiAgICAgICAgICAvLyBEYXRlIGRpZG4ndCBjaGFuZ2UgKHRpbWUgZGlkKSBvciBkYXRlIGNoYW5nZWQgYmVjYXVzZSB0aW1lIGRpZC5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9jdXJyZW50UHJvbXB0VGltZVRpbWVvdXQpO1xuICAgICAgICB0aGlzLl9jdXJyZW50UHJvbXB0VGltZVRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAodGhhdC53aWRnZXQpIHtcbiAgICAgICAgICAgIHRoYXQud2lkZ2V0LmZpbmQoJ1tkYXRhLWFjdGlvbj1cInRvZ2dsZVBpY2tlclwiXScpLmNsaWNrKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCB0aGlzLl9vcHRpb25zLnByb21wdFRpbWVPbkRhdGVDaGFuZ2VUcmFuc2l0aW9uRGVsYXkpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8uX3ZpZXdVcGRhdGUgPSBmdW5jdGlvbiBfdmlld1VwZGF0ZShlKSB7XG4gICAgICBpZiAoZSA9PT0gJ3knKSB7XG4gICAgICAgIGUgPSAnWVlZWSc7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuVVBEQVRFLFxuICAgICAgICBjaGFuZ2U6IGUsXG4gICAgICAgIHZpZXdEYXRlOiB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9zaG93TW9kZSA9IGZ1bmN0aW9uIF9zaG93TW9kZShkaXIpIHtcbiAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZGlyKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgodGhpcy5NaW5WaWV3TW9kZU51bWJlciwgTWF0aC5taW4oMywgdGhpcy5jdXJyZW50Vmlld01vZGUgKyBkaXIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXIgPiBkaXYnKS5oaWRlKCkuZmlsdGVyKFwiLmRhdGVwaWNrZXItXCIgKyBEYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLkNMQVNTX05BTUUpLnNob3coKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9pc0luRGlzYWJsZWREYXRlcyA9IGZ1bmN0aW9uIF9pc0luRGlzYWJsZWREYXRlcyh0ZXN0RGF0ZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlc1t0ZXN0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPT09IHRydWU7XG4gICAgfTtcblxuICAgIF9wcm90by5faXNJbkVuYWJsZWREYXRlcyA9IGZ1bmN0aW9uIF9pc0luRW5hYmxlZERhdGVzKHRlc3REYXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXNbdGVzdERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID09PSB0cnVlO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2lzSW5EaXNhYmxlZEhvdXJzID0gZnVuY3Rpb24gX2lzSW5EaXNhYmxlZEhvdXJzKHRlc3REYXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzW3Rlc3REYXRlLmZvcm1hdCgnSCcpXSA9PT0gdHJ1ZTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9pc0luRW5hYmxlZEhvdXJzID0gZnVuY3Rpb24gX2lzSW5FbmFibGVkSG91cnModGVzdERhdGUpIHtcbiAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3Vyc1t0ZXN0RGF0ZS5mb3JtYXQoJ0gnKV0gPT09IHRydWU7XG4gICAgfTtcblxuICAgIF9wcm90by5faXNWYWxpZCA9IGZ1bmN0aW9uIF9pc1ZhbGlkKHRhcmdldE1vbWVudCwgZ3JhbnVsYXJpdHkpIHtcbiAgICAgIGlmICghdGFyZ2V0TW9tZW50IHx8ICF0YXJnZXRNb21lbnQuaXNWYWxpZCgpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmIHRoaXMuX2lzSW5EaXNhYmxlZERhdGVzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiAhdGhpcy5faXNJbkVuYWJsZWREYXRlcyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiB0YXJnZXRNb21lbnQuaXNCZWZvcmUodGhpcy5fb3B0aW9ucy5taW5EYXRlLCBncmFudWxhcml0eSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHRhcmdldE1vbWVudC5pc0FmdGVyKHRoaXMuX29wdGlvbnMubWF4RGF0ZSwgZ3JhbnVsYXJpdHkpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQuaW5kZXhPZih0YXJnZXRNb21lbnQuZGF5KCkpICE9PSAtMSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSAmJiB0aGlzLl9pc0luRGlzYWJsZWRIb3Vycyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykgJiYgIXRoaXMuX2lzSW5FbmFibGVkSG91cnModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpKSB7XG4gICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAodGFyZ2V0TW9tZW50LmlzQmV0d2Vlbih0aGlzWzBdLCB0aGlzWzFdKSkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX3BhcnNlSW5wdXREYXRlID0gZnVuY3Rpb24gX3BhcnNlSW5wdXREYXRlKGlucHV0RGF0ZSwgX3RlbXApIHtcbiAgICAgIHZhciBfcmVmID0gX3RlbXAgPT09IHZvaWQgMCA/IHt9IDogX3RlbXAsXG4gICAgICAgICAgX3JlZiRpc1BpY2tlclNob3cgPSBfcmVmLmlzUGlja2VyU2hvdyxcbiAgICAgICAgICBpc1BpY2tlclNob3cgPSBfcmVmJGlzUGlja2VyU2hvdyA9PT0gdm9pZCAwID8gZmFsc2UgOiBfcmVmJGlzUGlja2VyU2hvdztcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUgPT09IHVuZGVmaW5lZCB8fCBpc1BpY2tlclNob3cpIHtcbiAgICAgICAgaWYgKCFtb21lbnQuaXNNb21lbnQoaW5wdXREYXRlKSkge1xuICAgICAgICAgIGlucHV0RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KGlucHV0RGF0ZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlucHV0RGF0ZSA9IHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUoaW5wdXREYXRlKTtcbiAgICAgIH0gLy9pbnB1dERhdGUubG9jYWxlKHRoaXMub3B0aW9ucy5sb2NhbGUpO1xuXG5cbiAgICAgIHJldHVybiBpbnB1dERhdGU7XG4gICAgfTtcblxuICAgIF9wcm90by5fa2V5ZG93biA9IGZ1bmN0aW9uIF9rZXlkb3duKGUpIHtcbiAgICAgIHZhciBoYW5kbGVyID0gbnVsbCxcbiAgICAgICAgICBpbmRleCxcbiAgICAgICAgICBpbmRleDIsXG4gICAgICAgICAga2V5QmluZEtleXMsXG4gICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZDtcbiAgICAgIHZhciBwcmVzc2VkS2V5cyA9IFtdLFxuICAgICAgICAgIHByZXNzZWRNb2RpZmllcnMgPSB7fSxcbiAgICAgICAgICBjdXJyZW50S2V5ID0gZS53aGljaCxcbiAgICAgICAgICBwcmVzc2VkID0gJ3AnO1xuICAgICAga2V5U3RhdGVbY3VycmVudEtleV0gPSBwcmVzc2VkO1xuXG4gICAgICBmb3IgKGluZGV4IGluIGtleVN0YXRlKSB7XG4gICAgICAgIGlmIChrZXlTdGF0ZS5oYXNPd25Qcm9wZXJ0eShpbmRleCkgJiYga2V5U3RhdGVbaW5kZXhdID09PSBwcmVzc2VkKSB7XG4gICAgICAgICAgcHJlc3NlZEtleXMucHVzaChpbmRleCk7XG5cbiAgICAgICAgICBpZiAocGFyc2VJbnQoaW5kZXgsIDEwKSAhPT0gY3VycmVudEtleSkge1xuICAgICAgICAgICAgcHJlc3NlZE1vZGlmaWVyc1tpbmRleF0gPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGluZGV4IGluIHRoaXMuX29wdGlvbnMua2V5QmluZHMpIHtcbiAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMua2V5QmluZHMuaGFzT3duUHJvcGVydHkoaW5kZXgpICYmIHR5cGVvZiB0aGlzLl9vcHRpb25zLmtleUJpbmRzW2luZGV4XSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIGtleUJpbmRLZXlzID0gaW5kZXguc3BsaXQoJyAnKTtcblxuICAgICAgICAgIGlmIChrZXlCaW5kS2V5cy5sZW5ndGggPT09IHByZXNzZWRLZXlzLmxlbmd0aCAmJiBLZXlNYXBbY3VycmVudEtleV0gPT09IGtleUJpbmRLZXlzW2tleUJpbmRLZXlzLmxlbmd0aCAtIDFdKSB7XG4gICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gdHJ1ZTtcblxuICAgICAgICAgICAgZm9yIChpbmRleDIgPSBrZXlCaW5kS2V5cy5sZW5ndGggLSAyOyBpbmRleDIgPj0gMDsgaW5kZXgyLS0pIHtcbiAgICAgICAgICAgICAgaWYgKCEoS2V5TWFwW2tleUJpbmRLZXlzW2luZGV4Ml1dIGluIHByZXNzZWRNb2RpZmllcnMpKSB7XG4gICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChhbGxNb2RpZmllcnNQcmVzc2VkKSB7XG4gICAgICAgICAgICAgIGhhbmRsZXIgPSB0aGlzLl9vcHRpb25zLmtleUJpbmRzW2luZGV4XTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgIGlmIChoYW5kbGVyLmNhbGwodGhpcykpIHtcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gLy9ub2luc3BlY3Rpb24gSlNNZXRob2RDYW5CZVN0YXRpYyxTcGVsbENoZWNraW5nSW5zcGVjdGlvblxuICAgIDtcblxuICAgIF9wcm90by5fa2V5dXAgPSBmdW5jdGlvbiBfa2V5dXAoZSkge1xuICAgICAga2V5U3RhdGVbZS53aGljaF0gPSAncic7XG5cbiAgICAgIGlmIChrZXlQcmVzc0hhbmRsZWRbZS53aGljaF0pIHtcbiAgICAgICAga2V5UHJlc3NIYW5kbGVkW2Uud2hpY2hdID0gZmFsc2U7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9pbmRleEdpdmVuRGF0ZXMgPSBmdW5jdGlvbiBfaW5kZXhHaXZlbkRhdGVzKGdpdmVuRGF0ZXNBcnJheSkge1xuICAgICAgLy8gU3RvcmUgZ2l2ZW4gZW5hYmxlZERhdGVzIGFuZCBkaXNhYmxlZERhdGVzIGFzIGtleXMuXG4gICAgICAvLyBUaGlzIHdheSB3ZSBjYW4gY2hlY2sgdGhlaXIgZXhpc3RlbmNlIGluIE8oMSkgdGltZSBpbnN0ZWFkIG9mIGxvb3BpbmcgdGhyb3VnaCB3aG9sZSBhcnJheS5cbiAgICAgIC8vIChmb3IgZXhhbXBsZTogb3B0aW9ucy5lbmFibGVkRGF0ZXNbJzIwMTQtMDItMjcnXSA9PT0gdHJ1ZSlcbiAgICAgIHZhciBnaXZlbkRhdGVzSW5kZXhlZCA9IHt9LFxuICAgICAgICAgIHNlbGYgPSB0aGlzO1xuICAgICAgJC5lYWNoKGdpdmVuRGF0ZXNBcnJheSwgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZERhdGUgPSBzZWxmLl9wYXJzZUlucHV0RGF0ZSh0aGlzKTtcblxuICAgICAgICBpZiAoZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgZ2l2ZW5EYXRlc0luZGV4ZWRbZERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gT2JqZWN0LmtleXMoZ2l2ZW5EYXRlc0luZGV4ZWQpLmxlbmd0aCA/IGdpdmVuRGF0ZXNJbmRleGVkIDogZmFsc2U7XG4gICAgfTtcblxuICAgIF9wcm90by5faW5kZXhHaXZlbkhvdXJzID0gZnVuY3Rpb24gX2luZGV4R2l2ZW5Ib3VycyhnaXZlbkhvdXJzQXJyYXkpIHtcbiAgICAgIC8vIFN0b3JlIGdpdmVuIGVuYWJsZWRIb3VycyBhbmQgZGlzYWJsZWRIb3VycyBhcyBrZXlzLlxuICAgICAgLy8gVGhpcyB3YXkgd2UgY2FuIGNoZWNrIHRoZWlyIGV4aXN0ZW5jZSBpbiBPKDEpIHRpbWUgaW5zdGVhZCBvZiBsb29waW5nIHRocm91Z2ggd2hvbGUgYXJyYXkuXG4gICAgICAvLyAoZm9yIGV4YW1wbGU6IG9wdGlvbnMuZW5hYmxlZEhvdXJzWycyMDE0LTAyLTI3J10gPT09IHRydWUpXG4gICAgICB2YXIgZ2l2ZW5Ib3Vyc0luZGV4ZWQgPSB7fTtcbiAgICAgICQuZWFjaChnaXZlbkhvdXJzQXJyYXksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2l2ZW5Ib3Vyc0luZGV4ZWRbdGhpc10gPSB0cnVlO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gT2JqZWN0LmtleXMoZ2l2ZW5Ib3Vyc0luZGV4ZWQpLmxlbmd0aCA/IGdpdmVuSG91cnNJbmRleGVkIDogZmFsc2U7XG4gICAgfTtcblxuICAgIF9wcm90by5faW5pdEZvcm1hdHRpbmcgPSBmdW5jdGlvbiBfaW5pdEZvcm1hdHRpbmcoKSB7XG4gICAgICB2YXIgZm9ybWF0ID0gdGhpcy5fb3B0aW9ucy5mb3JtYXQgfHwgJ0wgTFQnLFxuICAgICAgICAgIHNlbGYgPSB0aGlzO1xuICAgICAgdGhpcy5hY3R1YWxGb3JtYXQgPSBmb3JtYXQucmVwbGFjZSgvKFxcW1teXFxbXSpdKXwoXFxcXCk/KExUU3xMVHxMTD9MP0w/fGx7MSw0fSkvZywgZnVuY3Rpb24gKGZvcm1hdElucHV0KSB7XG4gICAgICAgIHJldHVybiAoc2VsZi5pc0luaXRGb3JtYXR0aW5nICYmIHNlbGYuX29wdGlvbnMuZGF0ZSA9PT0gbnVsbCA/IHNlbGYuZ2V0TW9tZW50KCkgOiBzZWxmLl9kYXRlc1swXSkubG9jYWxlRGF0YSgpLmxvbmdEYXRlRm9ybWF0KGZvcm1hdElucHV0KSB8fCBmb3JtYXRJbnB1dDsgLy90b2RvIHRha2luZyB0aGUgZmlyc3QgZGF0ZSBzaG91bGQgYmUgb2tcbiAgICAgIH0pO1xuICAgICAgdGhpcy5wYXJzZUZvcm1hdHMgPSB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cyA/IHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzLnNsaWNlKCkgOiBbXTtcblxuICAgICAgaWYgKHRoaXMucGFyc2VGb3JtYXRzLmluZGV4T2YoZm9ybWF0KSA8IDAgJiYgdGhpcy5wYXJzZUZvcm1hdHMuaW5kZXhPZih0aGlzLmFjdHVhbEZvcm1hdCkgPCAwKSB7XG4gICAgICAgIHRoaXMucGFyc2VGb3JtYXRzLnB1c2godGhpcy5hY3R1YWxGb3JtYXQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnVzZTI0SG91cnMgPSB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2EnKSA8IDEgJiYgdGhpcy5hY3R1YWxGb3JtYXQucmVwbGFjZSgvXFxbLio/XS9nLCAnJykuaW5kZXhPZignaCcpIDwgMTtcblxuICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgneScpKSB7XG4gICAgICAgIHRoaXMuTWluVmlld01vZGVOdW1iZXIgPSAyO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdNJykpIHtcbiAgICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDE7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ2QnKSkge1xuICAgICAgICB0aGlzLk1pblZpZXdNb2RlTnVtYmVyID0gMDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heCh0aGlzLk1pblZpZXdNb2RlTnVtYmVyLCB0aGlzLmN1cnJlbnRWaWV3TW9kZSk7XG5cbiAgICAgIGlmICghdGhpcy51bnNldCkge1xuICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1swXSwgMCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by5fZ2V0TGFzdFBpY2tlZERhdGUgPSBmdW5jdGlvbiBfZ2V0TGFzdFBpY2tlZERhdGUoKSB7XG4gICAgICB2YXIgbGFzdFBpY2tlZERhdGUgPSB0aGlzLl9kYXRlc1t0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCldO1xuXG4gICAgICBpZiAoIWxhc3RQaWNrZWREYXRlICYmIHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgbGFzdFBpY2tlZERhdGUgPSBtb21lbnQobmV3IERhdGUoKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBsYXN0UGlja2VkRGF0ZTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4ID0gZnVuY3Rpb24gX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZGF0ZXMubGVuZ3RoIC0gMTtcbiAgICB9IC8vcHVibGljXG4gICAgO1xuXG4gICAgX3Byb3RvLmdldE1vbWVudCA9IGZ1bmN0aW9uIGdldE1vbWVudChkKSB7XG4gICAgICB2YXIgcmV0dXJuTW9tZW50O1xuXG4gICAgICBpZiAoZCA9PT0gdW5kZWZpbmVkIHx8IGQgPT09IG51bGwpIHtcbiAgICAgICAgLy8gVE9ETzogU2hvdWxkIHRoaXMgdXNlIGZvcm1hdD9cbiAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50KCkuY2xvbmUoKS5sb2NhbGUodGhpcy5fb3B0aW9ucy5sb2NhbGUpO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgIC8vIFRoZXJlIGlzIGEgc3RyaW5nIHRvIHBhcnNlIGFuZCBhIGRlZmF1bHQgdGltZSB6b25lXG4gICAgICAgIC8vIHBhcnNlIHdpdGggdGhlIHR6IGZ1bmN0aW9uIHdoaWNoIHRha2VzIGEgZGVmYXVsdCB0aW1lIHpvbmUgaWYgaXQgaXMgbm90IGluIHRoZSBmb3JtYXQgc3RyaW5nXG4gICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudC50eihkLCB0aGlzLnBhcnNlRm9ybWF0cywgdGhpcy5fb3B0aW9ucy5sb2NhbGUsIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0LCB0aGlzLl9vcHRpb25zLnRpbWVab25lKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudChkLCB0aGlzLnBhcnNlRm9ybWF0cywgdGhpcy5fb3B0aW9ucy5sb2NhbGUsIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgcmV0dXJuTW9tZW50LnR6KHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmV0dXJuTW9tZW50O1xuICAgIH07XG5cbiAgICBfcHJvdG8udG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKCkge1xuICAgICAgcmV0dXJuIHRoaXMud2lkZ2V0ID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3coKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLnJlYWRvbmx5ID0gZnVuY3Rpb24gcmVhZG9ubHkoX3JlYWRvbmx5KSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5yZWFkb25seTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfcmVhZG9ubHkgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWFkb25seSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLnJlYWRvbmx5ID0gX3JlYWRvbmx5O1xuXG4gICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuaW5wdXQucHJvcCgncmVhZG9ubHknLCB0aGlzLl9vcHRpb25zLnJlYWRvbmx5KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLmlnbm9yZVJlYWRvbmx5ID0gZnVuY3Rpb24gaWdub3JlUmVhZG9ubHkoX2lnbm9yZVJlYWRvbmx5KSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5pZ25vcmVSZWFkb25seTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfaWdub3JlUmVhZG9ubHkgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpZ25vcmVSZWFkb25seSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmlnbm9yZVJlYWRvbmx5ID0gX2lnbm9yZVJlYWRvbmx5O1xuICAgIH07XG5cbiAgICBfcHJvdG8ub3B0aW9ucyA9IGZ1bmN0aW9uIG9wdGlvbnMobmV3T3B0aW9ucykge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHRydWUsIHt9LCB0aGlzLl9vcHRpb25zKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCEobmV3T3B0aW9ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb3B0aW9ucygpIHRoaXMub3B0aW9ucyBwYXJhbWV0ZXIgc2hvdWxkIGJlIGFuIG9iamVjdCcpO1xuICAgICAgfVxuXG4gICAgICAkLmV4dGVuZCh0cnVlLCB0aGlzLl9vcHRpb25zLCBuZXdPcHRpb25zKTtcbiAgICAgIHZhciBzZWxmID0gdGhpcyxcbiAgICAgICAgICBvcHRpb25zS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuX29wdGlvbnMpLnNvcnQob3B0aW9uc1NvcnRGbik7XG4gICAgICAkLmVhY2gob3B0aW9uc0tleXMsIGZ1bmN0aW9uIChpLCBrZXkpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gc2VsZi5fb3B0aW9uc1trZXldO1xuXG4gICAgICAgIGlmIChzZWxmW2tleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGlmIChzZWxmLmlzSW5pdCAmJiBrZXkgPT09ICdkYXRlJykge1xuICAgICAgICAgICAgc2VsZi5oYXNJbml0RGF0ZSA9IHRydWU7XG4gICAgICAgICAgICBzZWxmLmluaXREYXRlID0gdmFsdWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc2VsZltrZXldKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIF9wcm90by5kYXRlID0gZnVuY3Rpb24gZGF0ZShuZXdEYXRlLCBpbmRleCkge1xuICAgICAgaW5kZXggPSBpbmRleCB8fCAwO1xuXG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBpZiAodGhpcy51bnNldCkge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXMuam9pbih0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzW2luZGV4XS5jbG9uZSgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChuZXdEYXRlICE9PSBudWxsICYmIHR5cGVvZiBuZXdEYXRlICE9PSAnc3RyaW5nJyAmJiAhbW9tZW50LmlzTW9tZW50KG5ld0RhdGUpICYmICEobmV3RGF0ZSBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgW251bGwsIHN0cmluZywgbW9tZW50IG9yIERhdGVdJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgbmV3RGF0ZSA9PT0gJ3N0cmluZycgJiYgaXNWYWxpZERhdGVUaW1lU3RyKG5ld0RhdGUpKSB7XG4gICAgICAgIG5ld0RhdGUgPSBuZXcgRGF0ZShuZXdEYXRlKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc2V0VmFsdWUobmV3RGF0ZSA9PT0gbnVsbCA/IG51bGwgOiB0aGlzLl9wYXJzZUlucHV0RGF0ZShuZXdEYXRlKSwgaW5kZXgpO1xuICAgIH07XG5cbiAgICBfcHJvdG8udXBkYXRlT25seVRocm91Z2hEYXRlT3B0aW9uID0gZnVuY3Rpb24gdXBkYXRlT25seVRocm91Z2hEYXRlT3B0aW9uKF91cGRhdGVPbmx5VGhyb3VnaERhdGVPcHRpb24pIHtcbiAgICAgIGlmICh0eXBlb2YgX3VwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbiAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbigpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLnVwZGF0ZU9ubHlUaHJvdWdoRGF0ZU9wdGlvbiA9IF91cGRhdGVPbmx5VGhyb3VnaERhdGVPcHRpb247XG4gICAgfTtcblxuICAgIF9wcm90by5mb3JtYXQgPSBmdW5jdGlvbiBmb3JtYXQobmV3Rm9ybWF0KSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5mb3JtYXQ7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgbmV3Rm9ybWF0ICE9PSAnc3RyaW5nJyAmJiAodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ2Jvb2xlYW4nIHx8IG5ld0Zvcm1hdCAhPT0gZmFsc2UpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJmb3JtYXQoKSBleHBlY3RzIGEgc3RyaW5nIG9yIGJvb2xlYW46ZmFsc2UgcGFyYW1ldGVyIFwiICsgbmV3Rm9ybWF0KTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5mb3JtYXQgPSBuZXdGb3JtYXQ7XG5cbiAgICAgIGlmICh0aGlzLmFjdHVhbEZvcm1hdCkge1xuICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXRpYWxpemUgZm9ybWF0dGluZ1xuXG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by50aW1lWm9uZSA9IGZ1bmN0aW9uIHRpbWVab25lKG5ld1pvbmUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnRpbWVab25lO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIG5ld1pvbmUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ25ld1pvbmUoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLnRpbWVab25lID0gbmV3Wm9uZTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmRheVZpZXdIZWFkZXJGb3JtYXQgPSBmdW5jdGlvbiBkYXlWaWV3SGVhZGVyRm9ybWF0KG5ld0Zvcm1hdCkge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGF5Vmlld0hlYWRlckZvcm1hdDtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RheVZpZXdIZWFkZXJGb3JtYXQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQgPSBuZXdGb3JtYXQ7XG4gICAgfTtcblxuICAgIF9wcm90by5leHRyYUZvcm1hdHMgPSBmdW5jdGlvbiBleHRyYUZvcm1hdHMoZm9ybWF0cykge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0cyAhPT0gZmFsc2UgJiYgIShmb3JtYXRzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2V4dHJhRm9ybWF0cygpIGV4cGVjdHMgYW4gYXJyYXkgb3IgZmFsc2UgcGFyYW1ldGVyJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzID0gZm9ybWF0cztcblxuICAgICAgaWYgKHRoaXMucGFyc2VGb3JtYXRzKSB7XG4gICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7IC8vIHJlaW5pdCBmb3JtYXR0aW5nXG5cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLmRpc2FibGVkRGF0ZXMgPSBmdW5jdGlvbiBkaXNhYmxlZERhdGVzKGRhdGVzKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXM7XG4gICAgICB9XG5cbiAgICAgIGlmICghZGF0ZXMpIHtcbiAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghKGRhdGVzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkRGF0ZXMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSB0aGlzLl9pbmRleEdpdmVuRGF0ZXMoZGF0ZXMpO1xuICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSBmYWxzZTtcblxuICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgfTtcblxuICAgIF9wcm90by5lbmFibGVkRGF0ZXMgPSBmdW5jdGlvbiBlbmFibGVkRGF0ZXMoZGF0ZXMpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcykgOiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcztcbiAgICAgIH1cblxuICAgICAgaWYgKCFkYXRlcykge1xuICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIShkYXRlcyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmFibGVkRGF0ZXMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IHRoaXMuX2luZGV4R2l2ZW5EYXRlcyhkYXRlcyk7XG4gICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSBmYWxzZTtcblxuICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgfTtcblxuICAgIF9wcm90by5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBmdW5jdGlvbiBkYXlzT2ZXZWVrRGlzYWJsZWQoX2RheXNPZldlZWtEaXNhYmxlZCkge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkLnNwbGljZSgwKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfZGF5c09mV2Vla0Rpc2FibGVkID09PSAnYm9vbGVhbicgJiYgIV9kYXlzT2ZXZWVrRGlzYWJsZWQpIHtcbiAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLl91cGRhdGUoKTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCEoX2RheXNPZldlZWtEaXNhYmxlZCBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXlzT2ZXZWVrRGlzYWJsZWQoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCA9IF9kYXlzT2ZXZWVrRGlzYWJsZWQucmVkdWNlKGZ1bmN0aW9uIChwcmV2aW91c1ZhbHVlLCBjdXJyZW50VmFsdWUpIHtcbiAgICAgICAgY3VycmVudFZhbHVlID0gcGFyc2VJbnQoY3VycmVudFZhbHVlLCAxMCk7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA+IDYgfHwgY3VycmVudFZhbHVlIDwgMCB8fCBpc05hTihjdXJyZW50VmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJldmlvdXNWYWx1ZS5pbmRleE9mKGN1cnJlbnRWYWx1ZSkgPT09IC0xKSB7XG4gICAgICAgICAgcHJldmlvdXNWYWx1ZS5wdXNoKGN1cnJlbnRWYWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcbiAgICAgIH0sIFtdKS5zb3J0KCk7XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciB0cmllcyA9IDA7XG5cbiAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdkJykpIHtcbiAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnZCcpO1xuXG4gICAgICAgICAgICBpZiAodHJpZXMgPT09IDMxKSB7XG4gICAgICAgICAgICAgIHRocm93ICdUcmllZCAzMSB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRyaWVzKys7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbaV0sIGkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgIH07XG5cbiAgICBfcHJvdG8ubWF4RGF0ZSA9IGZ1bmN0aW9uIG1heERhdGUoX21heERhdGUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm1heERhdGUgPyB0aGlzLl9vcHRpb25zLm1heERhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMubWF4RGF0ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfbWF4RGF0ZSA9PT0gJ2Jvb2xlYW4nICYmIF9tYXhEYXRlID09PSBmYWxzZSkge1xuICAgICAgICB0aGlzLl9vcHRpb25zLm1heERhdGUgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLl91cGRhdGUoKTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfbWF4RGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKF9tYXhEYXRlID09PSAnbm93JyB8fCBfbWF4RGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICBfbWF4RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfbWF4RGF0ZSk7XG5cbiAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm1heERhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6IFwiICsgX21heERhdGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHBhcnNlZERhdGUuaXNCZWZvcmUodGhpcy5fb3B0aW9ucy5taW5EYXRlKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwibWF4RGF0ZSgpIGRhdGUgcGFyYW1ldGVyIGlzIGJlZm9yZSB0aGlzLm9wdGlvbnMubWluRGF0ZTogXCIgKyBwYXJzZWREYXRlLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLm1heERhdGUgPSBwYXJzZWREYXRlO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQgJiYgdGhpcy5fZGF0ZXNbaV0uaXNBZnRlcihfbWF4RGF0ZSkpIHtcbiAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLm1heERhdGUsIGkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl92aWV3RGF0ZS5pc0FmdGVyKHBhcnNlZERhdGUpKSB7XG4gICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gcGFyc2VkRGF0ZS5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX29wdGlvbnMuc3RlcHBpbmcsICdtJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgIH07XG5cbiAgICBfcHJvdG8ubWluRGF0ZSA9IGZ1bmN0aW9uIG1pbkRhdGUoX21pbkRhdGUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPyB0aGlzLl9vcHRpb25zLm1pbkRhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMubWluRGF0ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfbWluRGF0ZSA9PT0gJ2Jvb2xlYW4nICYmIF9taW5EYXRlID09PSBmYWxzZSkge1xuICAgICAgICB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLl91cGRhdGUoKTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfbWluRGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKF9taW5EYXRlID09PSAnbm93JyB8fCBfbWluRGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICBfbWluRGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfbWluRGF0ZSk7XG5cbiAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm1pbkRhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6IFwiICsgX21pbkRhdGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHBhcnNlZERhdGUuaXNBZnRlcih0aGlzLl9vcHRpb25zLm1heERhdGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJtaW5EYXRlKCkgZGF0ZSBwYXJhbWV0ZXIgaXMgYWZ0ZXIgdGhpcy5vcHRpb25zLm1heERhdGU6IFwiICsgcGFyc2VkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5taW5EYXRlID0gcGFyc2VkRGF0ZTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkICYmIHRoaXMuX2RhdGVzW2ldLmlzQmVmb3JlKF9taW5EYXRlKSkge1xuICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMubWluRGF0ZSwgaSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX3ZpZXdEYXRlLmlzQmVmb3JlKHBhcnNlZERhdGUpKSB7XG4gICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gcGFyc2VkRGF0ZS5jbG9uZSgpLmFkZCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmRlZmF1bHREYXRlID0gZnVuY3Rpb24gZGVmYXVsdERhdGUoX2RlZmF1bHREYXRlKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA/IHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGU7XG4gICAgICB9XG5cbiAgICAgIGlmICghX2RlZmF1bHREYXRlKSB7XG4gICAgICAgIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgX2RlZmF1bHREYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICBpZiAoX2RlZmF1bHREYXRlID09PSAnbm93JyB8fCBfZGVmYXVsdERhdGUgPT09ICdtb21lbnQnKSB7XG4gICAgICAgICAgX2RlZmF1bHREYXRlID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBfZGVmYXVsdERhdGUgPSB0aGlzLmdldE1vbWVudChfZGVmYXVsdERhdGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBwYXJzZWREYXRlID0gdGhpcy5fcGFyc2VJbnB1dERhdGUoX2RlZmF1bHREYXRlKTtcblxuICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiZGVmYXVsdERhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6IFwiICsgX2RlZmF1bHREYXRlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHBhcnNlZERhdGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlZmF1bHREYXRlKCkgZGF0ZSBwYXNzZWQgaXMgaW52YWxpZCBhY2NvcmRpbmcgdG8gY29tcG9uZW50IHNldHVwIHZhbGlkYXRpb25zJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPSBwYXJzZWREYXRlO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiB0aGlzLl9vcHRpb25zLmlubGluZSB8fCB0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC52YWwoKS50cmltKCkgPT09ICcnKSB7XG4gICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUsIDApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8ubG9jYWxlID0gZnVuY3Rpb24gbG9jYWxlKF9sb2NhbGUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmxvY2FsZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFtb21lbnQubG9jYWxlRGF0YShfbG9jYWxlKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwibG9jYWxlKCkgbG9jYWxlIFwiICsgX2xvY2FsZSArIFwiIGlzIG5vdCBsb2FkZWQgZnJvbSBtb21lbnQgbG9jYWxlcyFcIik7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29wdGlvbnMubG9jYWxlID0gX2xvY2FsZTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLl9kYXRlc1tpXS5sb2NhbGUodGhpcy5fb3B0aW9ucy5sb2NhbGUpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl92aWV3RGF0ZS5sb2NhbGUodGhpcy5fb3B0aW9ucy5sb2NhbGUpO1xuXG4gICAgICBpZiAodGhpcy5hY3R1YWxGb3JtYXQpIHtcbiAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0aWFsaXplIGZvcm1hdHRpbmdcblxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8uc3RlcHBpbmcgPSBmdW5jdGlvbiBzdGVwcGluZyhfc3RlcHBpbmcpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nO1xuICAgICAgfVxuXG4gICAgICBfc3RlcHBpbmcgPSBwYXJzZUludChfc3RlcHBpbmcsIDEwKTtcblxuICAgICAgaWYgKGlzTmFOKF9zdGVwcGluZykgfHwgX3N0ZXBwaW5nIDwgMSkge1xuICAgICAgICBfc3RlcHBpbmcgPSAxO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nID0gX3N0ZXBwaW5nO1xuICAgIH07XG5cbiAgICBfcHJvdG8udXNlQ3VycmVudCA9IGZ1bmN0aW9uIHVzZUN1cnJlbnQoX3VzZUN1cnJlbnQpIHtcbiAgICAgIHZhciB1c2VDdXJyZW50T3B0aW9ucyA9IFsneWVhcicsICdtb250aCcsICdkYXknLCAnaG91cicsICdtaW51dGUnXTtcblxuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudDtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfdXNlQ3VycmVudCAhPT0gJ2Jvb2xlYW4nICYmIHR5cGVvZiBfdXNlQ3VycmVudCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlQ3VycmVudCgpIGV4cGVjdHMgYSBib29sZWFuIG9yIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfdXNlQ3VycmVudCA9PT0gJ3N0cmluZycgJiYgdXNlQ3VycmVudE9wdGlvbnMuaW5kZXhPZihfdXNlQ3VycmVudC50b0xvd2VyQ2FzZSgpKSA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcInVzZUN1cnJlbnQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlciBvZiBcIiArIHVzZUN1cnJlbnRPcHRpb25zLmpvaW4oJywgJykpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgPSBfdXNlQ3VycmVudDtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmNvbGxhcHNlID0gZnVuY3Rpb24gY29sbGFwc2UoX2NvbGxhcHNlKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5jb2xsYXBzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfY29sbGFwc2UgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjb2xsYXBzZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5jb2xsYXBzZSA9PT0gX2NvbGxhcHNlKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmNvbGxhcHNlID0gX2NvbGxhcHNlO1xuXG4gICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8uaWNvbnMgPSBmdW5jdGlvbiBpY29ucyhfaWNvbnMpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5pY29ucyk7XG4gICAgICB9XG5cbiAgICAgIGlmICghKF9pY29ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaWNvbnMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcbiAgICAgIH1cblxuICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy5pY29ucywgX2ljb25zKTtcblxuICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLnRvb2x0aXBzID0gZnVuY3Rpb24gdG9vbHRpcHMoX3Rvb2x0aXBzKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMudG9vbHRpcHMpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIShfdG9vbHRpcHMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Rvb2x0aXBzKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYW4gT2JqZWN0Jyk7XG4gICAgICB9XG5cbiAgICAgICQuZXh0ZW5kKHRoaXMuX29wdGlvbnMudG9vbHRpcHMsIF90b29sdGlwcyk7XG5cbiAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by51c2VTdHJpY3QgPSBmdW5jdGlvbiB1c2VTdHJpY3QoX3VzZVN0cmljdCkge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0O1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIF91c2VTdHJpY3QgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1c2VTdHJpY3QoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy51c2VTdHJpY3QgPSBfdXNlU3RyaWN0O1xuICAgIH07XG5cbiAgICBfcHJvdG8uc2lkZUJ5U2lkZSA9IGZ1bmN0aW9uIHNpZGVCeVNpZGUoX3NpZGVCeVNpZGUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnNpZGVCeVNpZGU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgX3NpZGVCeVNpZGUgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzaWRlQnlTaWRlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZSA9IF9zaWRlQnlTaWRlO1xuXG4gICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8udmlld01vZGUgPSBmdW5jdGlvbiB2aWV3TW9kZShfdmlld01vZGUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnZpZXdNb2RlO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIF92aWV3TW9kZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmlld01vZGUoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICBpZiAoRGF0ZVRpbWVQaWNrZXIuVmlld01vZGVzLmluZGV4T2YoX3ZpZXdNb2RlKSA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcInZpZXdNb2RlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mIChcIiArIERhdGVUaW1lUGlja2VyLlZpZXdNb2Rlcy5qb2luKCcsICcpICsgXCIpIHZhbHVlXCIpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLnZpZXdNb2RlID0gX3ZpZXdNb2RlO1xuICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heChEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuaW5kZXhPZihfdmlld01vZGUpIC0gMSwgdGhpcy5NaW5WaWV3TW9kZU51bWJlcik7XG5cbiAgICAgIHRoaXMuX3Nob3dNb2RlKCk7XG4gICAgfTtcblxuICAgIF9wcm90by5jYWxlbmRhcldlZWtzID0gZnVuY3Rpb24gY2FsZW5kYXJXZWVrcyhfY2FsZW5kYXJXZWVrcykge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcztcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfY2FsZW5kYXJXZWVrcyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2NhbGVuZGFyV2Vla3MoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhIGJvb2xlYW4gdmFsdWUnKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzID0gX2NhbGVuZGFyV2Vla3M7XG5cbiAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgIH07XG5cbiAgICBfcHJvdG8uYnV0dG9ucyA9IGZ1bmN0aW9uIGJ1dHRvbnMoX2J1dHRvbnMpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5idXR0b25zKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCEoX2J1dHRvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcbiAgICAgIH1cblxuICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy5idXR0b25zLCBfYnV0dG9ucyk7XG5cbiAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dUb2RheSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMuc2hvd1RvZGF5IGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93Q2xlYXIgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zLnNob3dDbGVhciBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd0Nsb3NlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucy5zaG93Q2xvc2UgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by5rZWVwT3BlbiA9IGZ1bmN0aW9uIGtlZXBPcGVuKF9rZWVwT3Blbikge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMua2VlcE9wZW47XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgX2tlZXBPcGVuICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigna2VlcE9wZW4oKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiA9IF9rZWVwT3BlbjtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmZvY3VzT25TaG93ID0gZnVuY3Rpb24gZm9jdXNPblNob3coX2ZvY3VzT25TaG93KSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5mb2N1c09uU2hvdztcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfZm9jdXNPblNob3cgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdmb2N1c09uU2hvdygpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmZvY3VzT25TaG93ID0gX2ZvY3VzT25TaG93O1xuICAgIH07XG5cbiAgICBfcHJvdG8uaW5saW5lID0gZnVuY3Rpb24gaW5saW5lKF9pbmxpbmUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmlubGluZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfaW5saW5lICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaW5saW5lKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29wdGlvbnMuaW5saW5lID0gX2lubGluZTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICB0aGlzLl9zZXRWYWx1ZShudWxsKTsgLy90b2RvXG5cbiAgICB9O1xuXG4gICAgX3Byb3RvLmtleUJpbmRzID0gZnVuY3Rpb24ga2V5QmluZHMoX2tleUJpbmRzKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZXlCaW5kcztcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5rZXlCaW5kcyA9IF9rZXlCaW5kcztcbiAgICB9O1xuXG4gICAgX3Byb3RvLmRlYnVnID0gZnVuY3Rpb24gZGVidWcoX2RlYnVnKSB7XG4gICAgICBpZiAodHlwZW9mIF9kZWJ1ZyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlYnVnKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29wdGlvbnMuZGVidWcgPSBfZGVidWc7XG4gICAgfTtcblxuICAgIF9wcm90by5hbGxvd0lucHV0VG9nZ2xlID0gZnVuY3Rpb24gYWxsb3dJbnB1dFRvZ2dsZShfYWxsb3dJbnB1dFRvZ2dsZSkge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuYWxsb3dJbnB1dFRvZ2dsZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfYWxsb3dJbnB1dFRvZ2dsZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93SW5wdXRUb2dnbGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlID0gX2FsbG93SW5wdXRUb2dnbGU7XG4gICAgfTtcblxuICAgIF9wcm90by5rZWVwSW52YWxpZCA9IGZ1bmN0aW9uIGtlZXBJbnZhbGlkKF9rZWVwSW52YWxpZCkge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMua2VlcEludmFsaWQ7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgX2tlZXBJbnZhbGlkICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigna2VlcEludmFsaWQoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCA9IF9rZWVwSW52YWxpZDtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmRhdGVwaWNrZXJJbnB1dCA9IGZ1bmN0aW9uIGRhdGVwaWNrZXJJbnB1dChfZGF0ZXBpY2tlcklucHV0KSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXRlcGlja2VySW5wdXQ7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgX2RhdGVwaWNrZXJJbnB1dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF0ZXBpY2tlcklucHV0KCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5kYXRlcGlja2VySW5wdXQgPSBfZGF0ZXBpY2tlcklucHV0O1xuICAgIH07XG5cbiAgICBfcHJvdG8ucGFyc2VJbnB1dERhdGUgPSBmdW5jdGlvbiBwYXJzZUlucHV0RGF0ZShfcGFyc2VJbnB1dERhdGUyKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfcGFyc2VJbnB1dERhdGUyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3BhcnNlSW5wdXREYXRlKCkgc2hvdWxkIGJlIGFzIGZ1bmN0aW9uJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUgPSBfcGFyc2VJbnB1dERhdGUyO1xuICAgIH07XG5cbiAgICBfcHJvdG8uZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gZnVuY3Rpb24gZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKF9kaXNhYmxlZFRpbWVJbnRlcnZhbHMpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscztcbiAgICAgIH1cblxuICAgICAgaWYgKCFfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSB7XG4gICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghKF9kaXNhYmxlZFRpbWVJbnRlcnZhbHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzO1xuXG4gICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmRpc2FibGVkSG91cnMgPSBmdW5jdGlvbiBkaXNhYmxlZEhvdXJzKGhvdXJzKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnM7XG4gICAgICB9XG5cbiAgICAgIGlmICghaG91cnMpIHtcbiAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghKGhvdXJzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkSG91cnMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPSB0aGlzLl9pbmRleEdpdmVuSG91cnMoaG91cnMpO1xuICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPSBmYWxzZTtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHRyaWVzID0gMDtcblxuICAgICAgICAgIHdoaWxlICghdGhpcy5faXNWYWxpZCh0aGlzLl9kYXRlc1tpXSwgJ2gnKSkge1xuICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0uYWRkKDEsICdoJyk7XG5cbiAgICAgICAgICAgIGlmICh0cmllcyA9PT0gMjQpIHtcbiAgICAgICAgICAgICAgdGhyb3cgJ1RyaWVkIDI0IHRpbWVzIHRvIGZpbmQgYSB2YWxpZCBkYXRlJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJpZXMrKztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1tpXSwgaSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgfTtcblxuICAgIF9wcm90by5lbmFibGVkSG91cnMgPSBmdW5jdGlvbiBlbmFibGVkSG91cnMoaG91cnMpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycykgOiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycztcbiAgICAgIH1cblxuICAgICAgaWYgKCFob3Vycykge1xuICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIShob3VycyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmFibGVkSG91cnMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IHRoaXMuX2luZGV4R2l2ZW5Ib3Vycyhob3Vycyk7XG4gICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPSBmYWxzZTtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHRyaWVzID0gMDtcblxuICAgICAgICAgIHdoaWxlICghdGhpcy5faXNWYWxpZCh0aGlzLl9kYXRlc1tpXSwgJ2gnKSkge1xuICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0uYWRkKDEsICdoJyk7XG5cbiAgICAgICAgICAgIGlmICh0cmllcyA9PT0gMjQpIHtcbiAgICAgICAgICAgICAgdGhyb3cgJ1RyaWVkIDI0IHRpbWVzIHRvIGZpbmQgYSB2YWxpZCBkYXRlJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJpZXMrKztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1tpXSwgaSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgfTtcblxuICAgIF9wcm90by52aWV3RGF0ZSA9IGZ1bmN0aW9uIHZpZXdEYXRlKG5ld0RhdGUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIW5ld0RhdGUpIHtcbiAgICAgICAgdGhpcy5fdmlld0RhdGUgPSAodGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKSkuY2xvbmUoKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgbmV3RGF0ZSAhPT0gJ3N0cmluZycgJiYgIW1vbWVudC5pc01vbWVudChuZXdEYXRlKSAmJiAhKG5ld0RhdGUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3RGF0ZSgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiBbc3RyaW5nLCBtb21lbnQgb3IgRGF0ZV0nKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fdmlld0RhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShuZXdEYXRlKTtcblxuICAgICAgdGhpcy5fdXBkYXRlKCk7XG5cbiAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoRGF0ZVBpY2tlck1vZGVzW3RoaXMuY3VycmVudFZpZXdNb2RlXSAmJiBEYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLk5BVl9GVU5DVElPTik7XG4gICAgfTtcblxuICAgIF9wcm90by5fZmlsbERhdGUgPSBmdW5jdGlvbiBfZmlsbERhdGUoKSB7fTtcblxuICAgIF9wcm90by5fdXNlRmVhdGhlckljb25zID0gZnVuY3Rpb24gX3VzZUZlYXRoZXJJY29ucygpIHtcbiAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmljb25zLnR5cGUgPT09ICdmZWF0aGVyJztcbiAgICB9O1xuXG4gICAgX3Byb3RvLmFsbG93TXVsdGlkYXRlID0gZnVuY3Rpb24gYWxsb3dNdWx0aWRhdGUoX2FsbG93TXVsdGlkYXRlKSB7XG4gICAgICBpZiAodHlwZW9mIF9hbGxvd011bHRpZGF0ZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93TXVsdGlkYXRlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgPSBfYWxsb3dNdWx0aWRhdGU7XG4gICAgfTtcblxuICAgIF9wcm90by5tdWx0aWRhdGVTZXBhcmF0b3IgPSBmdW5jdGlvbiBtdWx0aWRhdGVTZXBhcmF0b3IoX211bHRpZGF0ZVNlcGFyYXRvcikge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIF9tdWx0aWRhdGVTZXBhcmF0b3IgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ211bHRpZGF0ZVNlcGFyYXRvciBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciA9IF9tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgfTtcblxuICAgIF9jcmVhdGVDbGFzcyhEYXRlVGltZVBpY2tlciwgbnVsbCwgW3tcbiAgICAgIGtleTogXCJOQU1FXCIsXG4gICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIE5BTUU7XG4gICAgICB9XG4gICAgICAvKipcbiAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICAgICAqL1xuXG4gICAgfSwge1xuICAgICAga2V5OiBcIkRBVEFfS0VZXCIsXG4gICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIERBVEFfS0VZO1xuICAgICAgfVxuICAgICAgLyoqXG4gICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgIGtleTogXCJFVkVOVF9LRVlcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gRVZFTlRfS0VZO1xuICAgICAgfVxuICAgICAgLyoqXG4gICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgIGtleTogXCJEQVRBX0FQSV9LRVlcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gREFUQV9BUElfS0VZO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJEYXRlUGlja2VyTW9kZXNcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gRGF0ZVBpY2tlck1vZGVzO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJWaWV3TW9kZXNcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gVmlld01vZGVzO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJFdmVudFwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBFdmVudDtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiU2VsZWN0b3JcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gU2VsZWN0b3I7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgIH0sXG4gICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkge1xuICAgICAgICBEZWZhdWx0ID0gdmFsdWU7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIkNsYXNzTmFtZVwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBDbGFzc05hbWU7XG4gICAgICB9XG4gICAgfV0pO1xuXG4gICAgcmV0dXJuIERhdGVUaW1lUGlja2VyO1xuICB9KCk7XG5cbiAgcmV0dXJuIERhdGVUaW1lUGlja2VyO1xufShqUXVlcnksIG1vbWVudCk7IC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkR2xvYmFsU3ltYm9sc1xuXG4vKiBnbG9iYWwgRGF0ZVRpbWVQaWNrZXIgKi9cblxuLyogZ2xvYmFsIGZlYXRoZXIgKi9cblxuXG52YXIgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQgPSBmdW5jdGlvbiAoJCkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG4gIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkLmZuW0RhdGVUaW1lUGlja2VyLk5BTUVdLFxuICAgICAgdmVydGljYWxNb2RlcyA9IFsndG9wJywgJ2JvdHRvbScsICdhdXRvJ10sXG4gICAgICBob3Jpem9udGFsTW9kZXMgPSBbJ2xlZnQnLCAncmlnaHQnLCAnYXV0byddLFxuICAgICAgdG9vbGJhclBsYWNlbWVudHMgPSBbJ2RlZmF1bHQnLCAndG9wJywgJ2JvdHRvbSddLFxuICAgICAgZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCA9IGZ1bmN0aW9uIGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJGVsZW1lbnQpIHtcbiAgICB2YXIgc2VsZWN0b3IgPSAkZWxlbWVudC5kYXRhKCd0YXJnZXQnKSxcbiAgICAgICAgJHNlbGVjdG9yO1xuXG4gICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgc2VsZWN0b3IgPSAkZWxlbWVudC5hdHRyKCdocmVmJykgfHwgJyc7XG4gICAgICBzZWxlY3RvciA9IC9eI1thLXpdL2kudGVzdChzZWxlY3RvcikgPyBzZWxlY3RvciA6IG51bGw7XG4gICAgfVxuXG4gICAgJHNlbGVjdG9yID0gJChzZWxlY3Rvcik7XG5cbiAgICBpZiAoJHNlbGVjdG9yLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuICRlbGVtZW50O1xuICAgIH1cblxuICAgIGlmICghJHNlbGVjdG9yLmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpKSB7XG4gICAgICAkLmV4dGVuZCh7fSwgJHNlbGVjdG9yLmRhdGEoKSwgJCh0aGlzKS5kYXRhKCkpO1xuICAgIH1cblxuICAgIHJldHVybiAkc2VsZWN0b3I7XG4gIH07IC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG5cblxuICB2YXIgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQgPSAvKiNfX1BVUkVfXyovZnVuY3Rpb24gKF9EYXRlVGltZVBpY2tlcikge1xuICAgIF9pbmhlcml0c0xvb3NlKFRlbXB1c0RvbWludXNCb290c3RyYXA0LCBfRGF0ZVRpbWVQaWNrZXIpO1xuXG4gICAgZnVuY3Rpb24gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQoZWxlbWVudCwgb3B0aW9ucykge1xuICAgICAgdmFyIF90aGlzO1xuXG4gICAgICBfdGhpcyA9IF9EYXRlVGltZVBpY2tlci5jYWxsKHRoaXMsIGVsZW1lbnQsIG9wdGlvbnMpIHx8IHRoaXM7XG5cbiAgICAgIF90aGlzLl9pbml0KCk7XG5cbiAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG5cbiAgICB2YXIgX3Byb3RvMiA9IFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZTtcblxuICAgIF9wcm90bzIuX2luaXQgPSBmdW5jdGlvbiBfaW5pdCgpIHtcbiAgICAgIGlmICh0aGlzLl9lbGVtZW50Lmhhc0NsYXNzKCdpbnB1dC1ncm91cCcpKSB7XG4gICAgICAgIHZhciBkYXRlcGlja2VyQnV0dG9uID0gdGhpcy5fZWxlbWVudC5maW5kKCcuZGF0ZXBpY2tlcmJ1dHRvbicpO1xuXG4gICAgICAgIGlmIChkYXRlcGlja2VyQnV0dG9uLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuY29tcG9uZW50ID0gdGhpcy5fZWxlbWVudC5maW5kKCdbZGF0YS10b2dnbGU9XCJkYXRldGltZXBpY2tlclwiXScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuY29tcG9uZW50ID0gZGF0ZXBpY2tlckJ1dHRvbjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8yLl9pY29uVGFnID0gZnVuY3Rpb24gX2ljb25UYWcoaWNvbk5hbWUpIHtcbiAgICAgIGlmICh0eXBlb2YgZmVhdGhlciAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5fdXNlRmVhdGhlckljb25zKCkgJiYgZmVhdGhlci5pY29uc1tpY29uTmFtZV0pIHtcbiAgICAgICAgcmV0dXJuICQoJzxzcGFuPicpLmh0bWwoZmVhdGhlci5pY29uc1tpY29uTmFtZV0udG9TdmcoKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gJCgnPHNwYW4+JykuYWRkQ2xhc3MoaWNvbk5hbWUpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8yLl9nZXREYXRlUGlja2VyVGVtcGxhdGUgPSBmdW5jdGlvbiBfZ2V0RGF0ZVBpY2tlclRlbXBsYXRlKCkge1xuICAgICAgdmFyIGhlYWRUZW1wbGF0ZSA9ICQoJzx0aGVhZD4nKS5hcHBlbmQoJCgnPHRyPicpLmFwcGVuZCgkKCc8dGg+JykuYWRkQ2xhc3MoJ3ByZXYnKS5hdHRyKCdkYXRhLWFjdGlvbicsICdwcmV2aW91cycpLmFwcGVuZCh0aGlzLl9pY29uVGFnKHRoaXMuX29wdGlvbnMuaWNvbnMucHJldmlvdXMpKSkuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygncGlja2VyLXN3aXRjaCcpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3BpY2tlclN3aXRjaCcpLmF0dHIoJ2NvbHNwYW4nLCBcIlwiICsgKHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcyA/ICc2JyA6ICc1JykpKS5hcHBlbmQoJCgnPHRoPicpLmFkZENsYXNzKCduZXh0JykuYXR0cignZGF0YS1hY3Rpb24nLCAnbmV4dCcpLmFwcGVuZCh0aGlzLl9pY29uVGFnKHRoaXMuX29wdGlvbnMuaWNvbnMubmV4dCkpKSksXG4gICAgICAgICAgY29udFRlbXBsYXRlID0gJCgnPHRib2R5PicpLmFwcGVuZCgkKCc8dHI+JykuYXBwZW5kKCQoJzx0ZD4nKS5hdHRyKCdjb2xzcGFuJywgXCJcIiArICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MgPyAnOCcgOiAnNycpKSkpO1xuICAgICAgcmV0dXJuIFskKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyLWRheXMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZSB0YWJsZS1zbScpLmFwcGVuZChoZWFkVGVtcGxhdGUpLmFwcGVuZCgkKCc8dGJvZHk+JykpKSwgJCgnPGRpdj4nKS5hZGRDbGFzcygnZGF0ZXBpY2tlci1tb250aHMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKS5hcHBlbmQoaGVhZFRlbXBsYXRlLmNsb25lKCkpLmFwcGVuZChjb250VGVtcGxhdGUuY2xvbmUoKSkpLCAkKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyLXllYXJzJykuYXBwZW5kKCQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJykuYXBwZW5kKGhlYWRUZW1wbGF0ZS5jbG9uZSgpKS5hcHBlbmQoY29udFRlbXBsYXRlLmNsb25lKCkpKSwgJCgnPGRpdj4nKS5hZGRDbGFzcygnZGF0ZXBpY2tlci1kZWNhZGVzJykuYXBwZW5kKCQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJykuYXBwZW5kKGhlYWRUZW1wbGF0ZS5jbG9uZSgpKS5hcHBlbmQoY29udFRlbXBsYXRlLmNsb25lKCkpKV07XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2dldFRpbWVQaWNrZXJNYWluVGVtcGxhdGUgPSBmdW5jdGlvbiBfZ2V0VGltZVBpY2tlck1haW5UZW1wbGF0ZSgpIHtcbiAgICAgIHZhciB0b3BSb3cgPSAkKCc8dHI+JyksXG4gICAgICAgICAgbWlkZGxlUm93ID0gJCgnPHRyPicpLFxuICAgICAgICAgIGJvdHRvbVJvdyA9ICQoJzx0cj4nKTtcblxuICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnaCcpKSB7XG4gICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5pbmNyZW1lbnRIb3VyXG4gICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdpbmNyZW1lbnRIb3VycycpLmFwcGVuZCh0aGlzLl9pY29uVGFnKHRoaXMuX29wdGlvbnMuaWNvbnMudXApKSkpO1xuICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItaG91cicpLmF0dHIoe1xuICAgICAgICAgICdkYXRhLXRpbWUtY29tcG9uZW50JzogJ2hvdXJzJyxcbiAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnBpY2tIb3VyXG4gICAgICAgIH0pLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3Nob3dIb3VycycpKSk7XG4gICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5kZWNyZW1lbnRIb3VyXG4gICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdkZWNyZW1lbnRIb3VycycpLmFwcGVuZCh0aGlzLl9pY29uVGFnKHRoaXMuX29wdGlvbnMuaWNvbnMuZG93bikpKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ20nKSkge1xuICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdoJykpIHtcbiAgICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xuICAgICAgICAgIG1pZGRsZVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKS5odG1sKCc6JykpO1xuICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuaW5jcmVtZW50TWludXRlXG4gICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdpbmNyZW1lbnRNaW51dGVzJykuYXBwZW5kKHRoaXMuX2ljb25UYWcodGhpcy5fb3B0aW9ucy5pY29ucy51cCkpKSk7XG4gICAgICAgIG1pZGRsZVJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcygndGltZXBpY2tlci1taW51dGUnKS5hdHRyKHtcbiAgICAgICAgICAnZGF0YS10aW1lLWNvbXBvbmVudCc6ICdtaW51dGVzJyxcbiAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnBpY2tNaW51dGVcbiAgICAgICAgfSkuYXR0cignZGF0YS1hY3Rpb24nLCAnc2hvd01pbnV0ZXMnKSkpO1xuICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuZGVjcmVtZW50TWludXRlXG4gICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdkZWNyZW1lbnRNaW51dGVzJykuYXBwZW5kKHRoaXMuX2ljb25UYWcodGhpcy5fb3B0aW9ucy5pY29ucy5kb3duKSkpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgncycpKSB7XG4gICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ20nKSkge1xuICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpLmh0bWwoJzonKSk7XG4gICAgICAgICAgYm90dG9tUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5pbmNyZW1lbnRTZWNvbmRcbiAgICAgICAgfSkuYWRkQ2xhc3MoJ2J0bicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ2luY3JlbWVudFNlY29uZHMnKS5hcHBlbmQodGhpcy5faWNvblRhZyh0aGlzLl9vcHRpb25zLmljb25zLnVwKSkpKTtcbiAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLXNlY29uZCcpLmF0dHIoe1xuICAgICAgICAgICdkYXRhLXRpbWUtY29tcG9uZW50JzogJ3NlY29uZHMnLFxuICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMucGlja1NlY29uZFxuICAgICAgICB9KS5hdHRyKCdkYXRhLWFjdGlvbicsICdzaG93U2Vjb25kcycpKSk7XG4gICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5kZWNyZW1lbnRTZWNvbmRcbiAgICAgICAgfSkuYWRkQ2xhc3MoJ2J0bicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ2RlY3JlbWVudFNlY29uZHMnKS5hcHBlbmQodGhpcy5faWNvblRhZyh0aGlzLl9vcHRpb25zLmljb25zLmRvd24pKSkpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xuICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGJ1dHRvbj4nKS5hZGRDbGFzcygnYnRuIGJ0bi1wcmltYXJ5JykuYXR0cih7XG4gICAgICAgICAgJ2RhdGEtYWN0aW9uJzogJ3RvZ2dsZVBlcmlvZCcsXG4gICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy50b2dnbGVQZXJpb2RcbiAgICAgICAgfSkpKTtcbiAgICAgICAgYm90dG9tUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItcGlja2VyJykuYXBwZW5kKCQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJykuYXBwZW5kKFt0b3BSb3csIG1pZGRsZVJvdywgYm90dG9tUm93XSkpO1xuICAgIH07XG5cbiAgICBfcHJvdG8yLl9nZXRUaW1lUGlja2VyVGVtcGxhdGUgPSBmdW5jdGlvbiBfZ2V0VGltZVBpY2tlclRlbXBsYXRlKCkge1xuICAgICAgdmFyIGhvdXJzVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItaG91cnMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgbWludXRlc1ZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyLW1pbnV0ZXMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgc2Vjb25kc1ZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyLXNlY29uZHMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgcmV0ID0gW3RoaXMuX2dldFRpbWVQaWNrZXJNYWluVGVtcGxhdGUoKV07XG5cbiAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ2gnKSkge1xuICAgICAgICByZXQucHVzaChob3Vyc1ZpZXcpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdtJykpIHtcbiAgICAgICAgcmV0LnB1c2gobWludXRlc1ZpZXcpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdzJykpIHtcbiAgICAgICAgcmV0LnB1c2goc2Vjb25kc1ZpZXcpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmV0O1xuICAgIH07XG5cbiAgICBfcHJvdG8yLl9nZXRUb29sYmFyID0gZnVuY3Rpb24gX2dldFRvb2xiYXIoKSB7XG4gICAgICB2YXIgcm93ID0gW107XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd1RvZGF5KSB7XG4gICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICdkYXRhLWFjdGlvbic6ICd0b2RheScsXG4gICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy50b2RheVxuICAgICAgICB9KS5hcHBlbmQodGhpcy5faWNvblRhZyh0aGlzLl9vcHRpb25zLmljb25zLnRvZGF5KSkpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLnNpZGVCeVNpZGUgJiYgdGhpcy5fb3B0aW9ucy5jb2xsYXBzZSAmJiB0aGlzLl9oYXNEYXRlKCkgJiYgdGhpcy5faGFzVGltZSgpKSB7XG4gICAgICAgIHZhciB0aXRsZSwgaWNvbjtcblxuICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy52aWV3TW9kZSA9PT0gJ3RpbWVzJykge1xuICAgICAgICAgIHRpdGxlID0gdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3REYXRlO1xuICAgICAgICAgIGljb24gPSB0aGlzLl9vcHRpb25zLmljb25zLmRhdGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGl0bGUgPSB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnNlbGVjdFRpbWU7XG4gICAgICAgICAgaWNvbiA9IHRoaXMuX29wdGlvbnMuaWNvbnMudGltZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICdkYXRhLWFjdGlvbic6ICd0b2dnbGVQaWNrZXInLFxuICAgICAgICAgICd0aXRsZSc6IHRpdGxlXG4gICAgICAgIH0pLmFwcGVuZCh0aGlzLl9pY29uVGFnKGljb24pKSkpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbGVhcikge1xuICAgICAgICByb3cucHVzaCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoe1xuICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAnZGF0YS1hY3Rpb24nOiAnY2xlYXInLFxuICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuY2xlYXJcbiAgICAgICAgfSkuYXBwZW5kKHRoaXMuX2ljb25UYWcodGhpcy5fb3B0aW9ucy5pY29ucy5jbGVhcikpKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd0Nsb3NlKSB7XG4gICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICdkYXRhLWFjdGlvbic6ICdjbG9zZScsXG4gICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5jbG9zZVxuICAgICAgICB9KS5hcHBlbmQodGhpcy5faWNvblRhZyh0aGlzLl9vcHRpb25zLmljb25zLmNsb3NlKSkpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJvdy5sZW5ndGggPT09IDAgPyAnJyA6ICQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJykuYXBwZW5kKCQoJzx0Ym9keT4nKS5hcHBlbmQoJCgnPHRyPicpLmFwcGVuZChyb3cpKSk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2dldFRlbXBsYXRlID0gZnVuY3Rpb24gX2dldFRlbXBsYXRlKCkge1xuICAgICAgdmFyIHRlbXBsYXRlID0gJCgnPGRpdj4nKS5hZGRDbGFzcygoXCJib290c3RyYXAtZGF0ZXRpbWVwaWNrZXItd2lkZ2V0IGRyb3Bkb3duLW1lbnUgXCIgKyAodGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzID8gJ3RlbXB1c2RvbWludXMtYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyLXdpZGdldC13aXRoLWNhbGVuZGFyLXdlZWtzJyA6ICcnKSArIFwiIFwiICsgKCh0aGlzLl91c2VGZWF0aGVySWNvbnMoKSA/ICd0ZW1wdXNkb21pbnVzLWJvb3RzdHJhcC1kYXRldGltZXBpY2tlci13aWRnZXQtd2l0aC1mZWF0aGVyLWljb25zJyA6ICcnKSArIFwiIFwiKSkudHJpbSgpKSxcbiAgICAgICAgICBkYXRlVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXInKS5hcHBlbmQodGhpcy5fZ2V0RGF0ZVBpY2tlclRlbXBsYXRlKCkpLFxuICAgICAgICAgIHRpbWVWaWV3ID0gJCgnPGRpdj4nKS5hZGRDbGFzcygndGltZXBpY2tlcicpLmFwcGVuZCh0aGlzLl9nZXRUaW1lUGlja2VyVGVtcGxhdGUoKSksXG4gICAgICAgICAgY29udGVudCA9ICQoJzx1bD4nKS5hZGRDbGFzcygnbGlzdC11bnN0eWxlZCcpLFxuICAgICAgICAgIHRvb2xiYXIgPSAkKCc8bGk+JykuYWRkQ2xhc3MoKFwicGlja2VyLXN3aXRjaFwiICsgKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgPyAnIGFjY29yZGlvbi10b2dnbGUnIDogJycpICsgXCIgXCIgKyAoXCJcIiArICh0aGlzLl91c2VGZWF0aGVySWNvbnMoKSA/ICdwaWNrZXItc3dpdGNoLXdpdGgtZmVhdGhlcnMtaWNvbnMnIDogJycpKSkudHJpbSgpKS5hcHBlbmQodGhpcy5fZ2V0VG9vbGJhcigpKTtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgIHRlbXBsYXRlLnJlbW92ZUNsYXNzKCdkcm9wZG93bi1tZW51Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnVzZTI0SG91cnMpIHtcbiAgICAgICAgdGVtcGxhdGUuYWRkQ2xhc3MoJ3VzZXR3ZW50eWZvdXInKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LnByb3AoJ3JlYWRvbmx5JykgfHwgdGhpcy5fb3B0aW9ucy5yZWFkb25seSkge1xuICAgICAgICB0ZW1wbGF0ZS5hZGRDbGFzcygnYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyLXdpZGdldC1yZWFkb25seScpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdzJykgJiYgIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICB0ZW1wbGF0ZS5hZGRDbGFzcygnd2lkZXInKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZSAmJiB0aGlzLl9oYXNEYXRlKCkgJiYgdGhpcy5faGFzVGltZSgpKSB7XG4gICAgICAgIHRlbXBsYXRlLmFkZENsYXNzKCd0aW1lcGlja2VyLXNicycpO1xuXG4gICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICd0b3AnKSB7XG4gICAgICAgICAgdGVtcGxhdGUuYXBwZW5kKHRvb2xiYXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGVtcGxhdGUuYXBwZW5kKCQoJzxkaXY+JykuYWRkQ2xhc3MoJ3JvdycpLmFwcGVuZChkYXRlVmlldy5hZGRDbGFzcygnY29sLW1kLTYnKSkuYXBwZW5kKHRpbWVWaWV3LmFkZENsYXNzKCdjb2wtbWQtNicpKSk7XG5cbiAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9PT0gJ2JvdHRvbScgfHwgdGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAnZGVmYXVsdCcpIHtcbiAgICAgICAgICB0ZW1wbGF0ZS5hcHBlbmQodG9vbGJhcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGVtcGxhdGU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICd0b3AnKSB7XG4gICAgICAgIGNvbnRlbnQuYXBwZW5kKHRvb2xiYXIpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faGFzRGF0ZSgpKSB7XG4gICAgICAgIGNvbnRlbnQuYXBwZW5kKCQoJzxsaT4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmNvbGxhcHNlICYmIHRoaXMuX2hhc1RpbWUoKSA/ICdjb2xsYXBzZScgOiAnJykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5jb2xsYXBzZSAmJiB0aGlzLl9oYXNUaW1lKCkgJiYgdGhpcy5fb3B0aW9ucy52aWV3TW9kZSA9PT0gJ3RpbWVzJyA/ICcnIDogJ3Nob3cnKS5hcHBlbmQoZGF0ZVZpZXcpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9PT0gJ2RlZmF1bHQnKSB7XG4gICAgICAgIGNvbnRlbnQuYXBwZW5kKHRvb2xiYXIpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faGFzVGltZSgpKSB7XG4gICAgICAgIGNvbnRlbnQuYXBwZW5kKCQoJzxsaT4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmNvbGxhcHNlICYmIHRoaXMuX2hhc0RhdGUoKSA/ICdjb2xsYXBzZScgOiAnJykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5jb2xsYXBzZSAmJiB0aGlzLl9oYXNEYXRlKCkgJiYgdGhpcy5fb3B0aW9ucy52aWV3TW9kZSA9PT0gJ3RpbWVzJyA/ICdzaG93JyA6ICcnKS5hcHBlbmQodGltZVZpZXcpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgY29udGVudC5hcHBlbmQodG9vbGJhcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0ZW1wbGF0ZS5hcHBlbmQoY29udGVudCk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX3BsYWNlID0gZnVuY3Rpb24gX3BsYWNlKGUpIHtcbiAgICAgIHZhciBzZWxmID0gZSAmJiBlLmRhdGEgJiYgZS5kYXRhLnBpY2tlciB8fCB0aGlzLFxuICAgICAgICAgIHZlcnRpY2FsID0gc2VsZi5fb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCxcbiAgICAgICAgICBob3Jpem9udGFsID0gc2VsZi5fb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsLFxuICAgICAgICAgIHBhcmVudDtcbiAgICAgIHZhciBwb3NpdGlvbiA9IChzZWxmLmNvbXBvbmVudCAmJiBzZWxmLmNvbXBvbmVudC5sZW5ndGggPyBzZWxmLmNvbXBvbmVudCA6IHNlbGYuX2VsZW1lbnQpLnBvc2l0aW9uKCksXG4gICAgICAgICAgb2Zmc2V0ID0gKHNlbGYuY29tcG9uZW50ICYmIHNlbGYuY29tcG9uZW50Lmxlbmd0aCA/IHNlbGYuY29tcG9uZW50IDogc2VsZi5fZWxlbWVudCkub2Zmc2V0KCk7XG5cbiAgICAgIGlmIChzZWxmLl9vcHRpb25zLndpZGdldFBhcmVudCkge1xuICAgICAgICBwYXJlbnQgPSBzZWxmLl9vcHRpb25zLndpZGdldFBhcmVudC5hcHBlbmQoc2VsZi53aWRnZXQpO1xuICAgICAgfSBlbHNlIGlmIChzZWxmLl9lbGVtZW50LmlzKCdpbnB1dCcpKSB7XG4gICAgICAgIHBhcmVudCA9IHNlbGYuX2VsZW1lbnQuYWZ0ZXIoc2VsZi53aWRnZXQpLnBhcmVudCgpO1xuICAgICAgfSBlbHNlIGlmIChzZWxmLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICBwYXJlbnQgPSBzZWxmLl9lbGVtZW50LmFwcGVuZChzZWxmLndpZGdldCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcmVudCA9IHNlbGYuX2VsZW1lbnQ7XG5cbiAgICAgICAgc2VsZi5fZWxlbWVudC5jaGlsZHJlbigpLmZpcnN0KCkuYWZ0ZXIoc2VsZi53aWRnZXQpO1xuICAgICAgfSAvLyBUb3AgYW5kIGJvdHRvbSBsb2dpY1xuXG5cbiAgICAgIGlmICh2ZXJ0aWNhbCA9PT0gJ2F1dG8nKSB7XG4gICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVmFsaWRhdGVUeXBlc1xuICAgICAgICBpZiAob2Zmc2V0LnRvcCArIHNlbGYud2lkZ2V0LmhlaWdodCgpICogMS41ID49ICQod2luZG93KS5oZWlnaHQoKSArICQod2luZG93KS5zY3JvbGxUb3AoKSAmJiBzZWxmLndpZGdldC5oZWlnaHQoKSArIHNlbGYuX2VsZW1lbnQub3V0ZXJIZWlnaHQoKSA8IG9mZnNldC50b3ApIHtcbiAgICAgICAgICB2ZXJ0aWNhbCA9ICd0b3AnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZlcnRpY2FsID0gJ2JvdHRvbSc7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gTGVmdCBhbmQgcmlnaHQgbG9naWNcblxuXG4gICAgICBpZiAoaG9yaXpvbnRhbCA9PT0gJ2F1dG8nKSB7XG4gICAgICAgIGlmIChwYXJlbnQud2lkdGgoKSA8IG9mZnNldC5sZWZ0ICsgc2VsZi53aWRnZXQub3V0ZXJXaWR0aCgpIC8gMiAmJiBvZmZzZXQubGVmdCArIHNlbGYud2lkZ2V0Lm91dGVyV2lkdGgoKSA+ICQod2luZG93KS53aWR0aCgpKSB7XG4gICAgICAgICAgaG9yaXpvbnRhbCA9ICdyaWdodCc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaG9yaXpvbnRhbCA9ICdsZWZ0JztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodmVydGljYWwgPT09ICd0b3AnKSB7XG4gICAgICAgIHNlbGYud2lkZ2V0LmFkZENsYXNzKCd0b3AnKS5yZW1vdmVDbGFzcygnYm90dG9tJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWxmLndpZGdldC5hZGRDbGFzcygnYm90dG9tJykucmVtb3ZlQ2xhc3MoJ3RvcCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaG9yaXpvbnRhbCA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICBzZWxmLndpZGdldC5hZGRDbGFzcygnZmxvYXQtcmlnaHQnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlbGYud2lkZ2V0LnJlbW92ZUNsYXNzKCdmbG9hdC1yaWdodCcpO1xuICAgICAgfSAvLyBmaW5kIHRoZSBmaXJzdCBwYXJlbnQgZWxlbWVudCB0aGF0IGhhcyBhIHJlbGF0aXZlIGNzcyBwb3NpdGlvbmluZ1xuXG5cbiAgICAgIGlmIChwYXJlbnQuY3NzKCdwb3NpdGlvbicpICE9PSAncmVsYXRpdmUnKSB7XG4gICAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnRzKCkuZmlsdGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gJCh0aGlzKS5jc3MoJ3Bvc2l0aW9uJykgPT09ICdyZWxhdGl2ZSc7XG4gICAgICAgIH0pLmZpcnN0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZGF0ZXRpbWVwaWNrZXIgY29tcG9uZW50IHNob3VsZCBiZSBwbGFjZWQgd2l0aGluIGEgcmVsYXRpdmUgcG9zaXRpb25lZCBjb250YWluZXInKTtcbiAgICAgIH1cblxuICAgICAgc2VsZi53aWRnZXQuY3NzKHtcbiAgICAgICAgdG9wOiB2ZXJ0aWNhbCA9PT0gJ3RvcCcgPyAnYXV0bycgOiBwb3NpdGlvbi50b3AgKyBzZWxmLl9lbGVtZW50Lm91dGVySGVpZ2h0KCkgKyAncHgnLFxuICAgICAgICBib3R0b206IHZlcnRpY2FsID09PSAndG9wJyA/IHBhcmVudC5vdXRlckhlaWdodCgpIC0gKHBhcmVudCA9PT0gc2VsZi5fZWxlbWVudCA/IDAgOiBwb3NpdGlvbi50b3ApICsgJ3B4JyA6ICdhdXRvJyxcbiAgICAgICAgbGVmdDogaG9yaXpvbnRhbCA9PT0gJ2xlZnQnID8gKHBhcmVudCA9PT0gc2VsZi5fZWxlbWVudCA/IDAgOiBwb3NpdGlvbi5sZWZ0KSArICdweCcgOiAnYXV0bycsXG4gICAgICAgIHJpZ2h0OiBob3Jpem9udGFsID09PSAnbGVmdCcgPyAnYXV0bycgOiBwYXJlbnQub3V0ZXJXaWR0aCgpIC0gc2VsZi5fZWxlbWVudC5vdXRlcldpZHRoKCkgLSAocGFyZW50ID09PSBzZWxmLl9lbGVtZW50ID8gMCA6IHBvc2l0aW9uLmxlZnQpICsgJ3B4J1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2ZpbGxEb3cgPSBmdW5jdGlvbiBfZmlsbERvdygpIHtcbiAgICAgIHZhciByb3cgPSAkKCc8dHI+JyksXG4gICAgICAgICAgY3VycmVudERhdGUgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ3cnKS5zdGFydE9mKCdkJyk7XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MgPT09IHRydWUpIHtcbiAgICAgICAgcm93LmFwcGVuZCgkKCc8dGg+JykuYWRkQ2xhc3MoJ2N3JykudGV4dCgnIycpKTtcbiAgICAgIH1cblxuICAgICAgd2hpbGUgKGN1cnJlbnREYXRlLmlzQmVmb3JlKHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuZW5kT2YoJ3cnKSkpIHtcbiAgICAgICAgcm93LmFwcGVuZCgkKCc8dGg+JykuYWRkQ2xhc3MoJ2RvdycpLnRleHQoY3VycmVudERhdGUuZm9ybWF0KCdkZCcpKSk7XG4gICAgICAgIGN1cnJlbnREYXRlLmFkZCgxLCAnZCcpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci1kYXlzIHRoZWFkJykuYXBwZW5kKHJvdyk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2ZpbGxNb250aHMgPSBmdW5jdGlvbiBfZmlsbE1vbnRocygpIHtcbiAgICAgIHZhciBzcGFucyA9IFtdLFxuICAgICAgICAgIG1vbnRoc1Nob3J0ID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCd5Jykuc3RhcnRPZignZCcpO1xuXG4gICAgICB3aGlsZSAobW9udGhzU2hvcnQuaXNTYW1lKHRoaXMuX3ZpZXdEYXRlLCAneScpKSB7XG4gICAgICAgIHNwYW5zLnB1c2goJCgnPHNwYW4+JykuYXR0cignZGF0YS1hY3Rpb24nLCAnc2VsZWN0TW9udGgnKS5hZGRDbGFzcygnbW9udGgnKS50ZXh0KG1vbnRoc1Nob3J0LmZvcm1hdCgnTU1NJykpKTtcbiAgICAgICAgbW9udGhzU2hvcnQuYWRkKDEsICdNJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyLW1vbnRocyB0ZCcpLmVtcHR5KCkuYXBwZW5kKHNwYW5zKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvMi5fdXBkYXRlTW9udGhzID0gZnVuY3Rpb24gX3VwZGF0ZU1vbnRocygpIHtcbiAgICAgIHZhciBtb250aHNWaWV3ID0gdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItbW9udGhzJyksXG4gICAgICAgICAgbW9udGhzVmlld0hlYWRlciA9IG1vbnRoc1ZpZXcuZmluZCgndGgnKSxcbiAgICAgICAgICBtb250aHMgPSBtb250aHNWaWV3LmZpbmQoJ3Rib2R5JykuZmluZCgnc3BhbicpLFxuICAgICAgICAgIHNlbGYgPSB0aGlzLFxuICAgICAgICAgIGxhc3RQaWNrZWREYXRlID0gdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKTtcblxuICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgwKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnByZXZZZWFyKTtcbiAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMSkuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnNlbGVjdFllYXIpO1xuICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHRZZWFyKTtcbiAgICAgIG1vbnRoc1ZpZXcuZmluZCgnLmRpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cbiAgICAgIGlmICghdGhpcy5faXNWYWxpZCh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN1YnRyYWN0KDEsICd5JyksICd5JykpIHtcbiAgICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgIH1cblxuICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgxKS50ZXh0KHRoaXMuX3ZpZXdEYXRlLnllYXIoKSk7XG5cbiAgICAgIGlmICghdGhpcy5faXNWYWxpZCh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLmFkZCgxLCAneScpLCAneScpKSB7XG4gICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICB9XG5cbiAgICAgIG1vbnRocy5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cbiAgICAgIGlmIChsYXN0UGlja2VkRGF0ZSAmJiBsYXN0UGlja2VkRGF0ZS5pc1NhbWUodGhpcy5fdmlld0RhdGUsICd5JykgJiYgIXRoaXMudW5zZXQpIHtcbiAgICAgICAgbW9udGhzLmVxKGxhc3RQaWNrZWREYXRlLm1vbnRoKCkpLmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICAgIH1cblxuICAgICAgbW9udGhzLmVhY2goZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgIGlmICghc2VsZi5faXNWYWxpZChzZWxmLl92aWV3RGF0ZS5jbG9uZSgpLm1vbnRoKGluZGV4KSwgJ00nKSkge1xuICAgICAgICAgICQodGhpcykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfcHJvdG8yLl9nZXRTdGFydEVuZFllYXIgPSBmdW5jdGlvbiBfZ2V0U3RhcnRFbmRZZWFyKGZhY3RvciwgeWVhcikge1xuICAgICAgdmFyIHN0ZXAgPSBmYWN0b3IgLyAxMCxcbiAgICAgICAgICBzdGFydFllYXIgPSBNYXRoLmZsb29yKHllYXIgLyBmYWN0b3IpICogZmFjdG9yLFxuICAgICAgICAgIGVuZFllYXIgPSBzdGFydFllYXIgKyBzdGVwICogOSxcbiAgICAgICAgICBmb2N1c1ZhbHVlID0gTWF0aC5mbG9vcih5ZWFyIC8gc3RlcCkgKiBzdGVwO1xuICAgICAgcmV0dXJuIFtzdGFydFllYXIsIGVuZFllYXIsIGZvY3VzVmFsdWVdO1xuICAgIH07XG5cbiAgICBfcHJvdG8yLl91cGRhdGVZZWFycyA9IGZ1bmN0aW9uIF91cGRhdGVZZWFycygpIHtcbiAgICAgIHZhciB5ZWFyc1ZpZXcgPSB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci15ZWFycycpLFxuICAgICAgICAgIHllYXJzVmlld0hlYWRlciA9IHllYXJzVmlldy5maW5kKCd0aCcpLFxuICAgICAgICAgIHllYXJDYXBzID0gdGhpcy5fZ2V0U3RhcnRFbmRZZWFyKDEwLCB0aGlzLl92aWV3RGF0ZS55ZWFyKCkpLFxuICAgICAgICAgIHN0YXJ0WWVhciA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkueWVhcih5ZWFyQ2Fwc1swXSksXG4gICAgICAgICAgZW5kWWVhciA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkueWVhcih5ZWFyQ2Fwc1sxXSk7XG5cbiAgICAgIHZhciBodG1sID0gJyc7XG4gICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMCkuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5wcmV2RGVjYWRlKTtcbiAgICAgIHllYXJzVmlld0hlYWRlci5lcSgxKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0RGVjYWRlKTtcbiAgICAgIHllYXJzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHREZWNhZGUpO1xuICAgICAgeWVhcnNWaWV3LmZpbmQoJy5kaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHRoaXMuX29wdGlvbnMubWluRGF0ZS5pc0FmdGVyKHN0YXJ0WWVhciwgJ3knKSkge1xuICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMCkuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICB9XG5cbiAgICAgIHllYXJzVmlld0hlYWRlci5lcSgxKS50ZXh0KHN0YXJ0WWVhci55ZWFyKCkgKyBcIi1cIiArIGVuZFllYXIueWVhcigpKTtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWF4RGF0ZSAmJiB0aGlzLl9vcHRpb25zLm1heERhdGUuaXNCZWZvcmUoZW5kWWVhciwgJ3knKSkge1xuICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICB9XG5cbiAgICAgIGh0bWwgKz0gXCI8c3BhbiBkYXRhLWFjdGlvbj1cXFwic2VsZWN0WWVhclxcXCIgY2xhc3M9XFxcInllYXIgb2xkXCIgKyAoIXRoaXMuX2lzVmFsaWQoc3RhcnRZZWFyLCAneScpID8gJyBkaXNhYmxlZCcgOiAnJykgKyBcIlxcXCI+XCIgKyAoc3RhcnRZZWFyLnllYXIoKSAtIDEpICsgXCI8L3NwYW4+XCI7XG5cbiAgICAgIHdoaWxlICghc3RhcnRZZWFyLmlzQWZ0ZXIoZW5kWWVhciwgJ3knKSkge1xuICAgICAgICBodG1sICs9IFwiPHNwYW4gZGF0YS1hY3Rpb249XFxcInNlbGVjdFllYXJcXFwiIGNsYXNzPVxcXCJ5ZWFyXCIgKyAoc3RhcnRZZWFyLmlzU2FtZSh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLCAneScpICYmICF0aGlzLnVuc2V0ID8gJyBhY3RpdmUnIDogJycpICsgKCF0aGlzLl9pc1ZhbGlkKHN0YXJ0WWVhciwgJ3knKSA/ICcgZGlzYWJsZWQnIDogJycpICsgXCJcXFwiPlwiICsgc3RhcnRZZWFyLnllYXIoKSArIFwiPC9zcGFuPlwiO1xuICAgICAgICBzdGFydFllYXIuYWRkKDEsICd5Jyk7XG4gICAgICB9XG5cbiAgICAgIGh0bWwgKz0gXCI8c3BhbiBkYXRhLWFjdGlvbj1cXFwic2VsZWN0WWVhclxcXCIgY2xhc3M9XFxcInllYXIgb2xkXCIgKyAoIXRoaXMuX2lzVmFsaWQoc3RhcnRZZWFyLCAneScpID8gJyBkaXNhYmxlZCcgOiAnJykgKyBcIlxcXCI+XCIgKyBzdGFydFllYXIueWVhcigpICsgXCI8L3NwYW4+XCI7XG4gICAgICB5ZWFyc1ZpZXcuZmluZCgndGQnKS5odG1sKGh0bWwpO1xuICAgIH07XG5cbiAgICBfcHJvdG8yLl91cGRhdGVEZWNhZGVzID0gZnVuY3Rpb24gX3VwZGF0ZURlY2FkZXMoKSB7XG4gICAgICB2YXIgZGVjYWRlc1ZpZXcgPSB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci1kZWNhZGVzJyksXG4gICAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIgPSBkZWNhZGVzVmlldy5maW5kKCd0aCcpLFxuICAgICAgICAgIHllYXJDYXBzID0gdGhpcy5fZ2V0U3RhcnRFbmRZZWFyKDEwMCwgdGhpcy5fdmlld0RhdGUueWVhcigpKSxcbiAgICAgICAgICBzdGFydERlY2FkZSA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkueWVhcih5ZWFyQ2Fwc1swXSksXG4gICAgICAgICAgZW5kRGVjYWRlID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS55ZWFyKHllYXJDYXBzWzFdKSxcbiAgICAgICAgICBsYXN0UGlja2VkRGF0ZSA9IHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCk7XG5cbiAgICAgIHZhciBtaW5EYXRlRGVjYWRlID0gZmFsc2UsXG4gICAgICAgICAgbWF4RGF0ZURlY2FkZSA9IGZhbHNlLFxuICAgICAgICAgIGVuZERlY2FkZVllYXIsXG4gICAgICAgICAgaHRtbCA9ICcnO1xuICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMCkuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5wcmV2Q2VudHVyeSk7XG4gICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHRDZW50dXJ5KTtcbiAgICAgIGRlY2FkZXNWaWV3LmZpbmQoJy5kaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXG4gICAgICBpZiAoc3RhcnREZWNhZGUueWVhcigpID09PSAwIHx8IHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiB0aGlzLl9vcHRpb25zLm1pbkRhdGUuaXNBZnRlcihzdGFydERlY2FkZSwgJ3knKSkge1xuICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgIH1cblxuICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMSkudGV4dChzdGFydERlY2FkZS55ZWFyKCkgKyBcIi1cIiArIGVuZERlY2FkZS55ZWFyKCkpO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHRoaXMuX29wdGlvbnMubWF4RGF0ZS5pc0JlZm9yZShlbmREZWNhZGUsICd5JykpIHtcbiAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGFydERlY2FkZS55ZWFyKCkgLSAxMCA8IDApIHtcbiAgICAgICAgaHRtbCArPSAnPHNwYW4+Jm5ic3A7PC9zcGFuPic7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBodG1sICs9IFwiPHNwYW4gZGF0YS1hY3Rpb249XFxcInNlbGVjdERlY2FkZVxcXCIgY2xhc3M9XFxcImRlY2FkZSBvbGRcXFwiIGRhdGEtc2VsZWN0aW9uPVxcXCJcIiArIChzdGFydERlY2FkZS55ZWFyKCkgKyA2KSArIFwiXFxcIj5cIiArIChzdGFydERlY2FkZS55ZWFyKCkgLSAxMCkgKyBcIjwvc3Bhbj5cIjtcbiAgICAgIH1cblxuICAgICAgd2hpbGUgKCFzdGFydERlY2FkZS5pc0FmdGVyKGVuZERlY2FkZSwgJ3knKSkge1xuICAgICAgICBlbmREZWNhZGVZZWFyID0gc3RhcnREZWNhZGUueWVhcigpICsgMTE7XG4gICAgICAgIG1pbkRhdGVEZWNhZGUgPSB0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgdGhpcy5fb3B0aW9ucy5taW5EYXRlLmlzQWZ0ZXIoc3RhcnREZWNhZGUsICd5JykgJiYgdGhpcy5fb3B0aW9ucy5taW5EYXRlLnllYXIoKSA8PSBlbmREZWNhZGVZZWFyO1xuICAgICAgICBtYXhEYXRlRGVjYWRlID0gdGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHRoaXMuX29wdGlvbnMubWF4RGF0ZS5pc0FmdGVyKHN0YXJ0RGVjYWRlLCAneScpICYmIHRoaXMuX29wdGlvbnMubWF4RGF0ZS55ZWFyKCkgPD0gZW5kRGVjYWRlWWVhcjtcbiAgICAgICAgaHRtbCArPSBcIjxzcGFuIGRhdGEtYWN0aW9uPVxcXCJzZWxlY3REZWNhZGVcXFwiIGNsYXNzPVxcXCJkZWNhZGVcIiArIChsYXN0UGlja2VkRGF0ZSAmJiBsYXN0UGlja2VkRGF0ZS5pc0FmdGVyKHN0YXJ0RGVjYWRlKSAmJiBsYXN0UGlja2VkRGF0ZS55ZWFyKCkgPD0gZW5kRGVjYWRlWWVhciA/ICcgYWN0aXZlJyA6ICcnKSArICghdGhpcy5faXNWYWxpZChzdGFydERlY2FkZSwgJ3knKSAmJiAhbWluRGF0ZURlY2FkZSAmJiAhbWF4RGF0ZURlY2FkZSA/ICcgZGlzYWJsZWQnIDogJycpICsgXCJcXFwiIGRhdGEtc2VsZWN0aW9uPVxcXCJcIiArIChzdGFydERlY2FkZS55ZWFyKCkgKyA2KSArIFwiXFxcIj5cIiArIHN0YXJ0RGVjYWRlLnllYXIoKSArIFwiPC9zcGFuPlwiO1xuICAgICAgICBzdGFydERlY2FkZS5hZGQoMTAsICd5Jyk7XG4gICAgICB9XG5cbiAgICAgIGh0bWwgKz0gXCI8c3BhbiBkYXRhLWFjdGlvbj1cXFwic2VsZWN0RGVjYWRlXFxcIiBjbGFzcz1cXFwiZGVjYWRlIG9sZFxcXCIgZGF0YS1zZWxlY3Rpb249XFxcIlwiICsgKHN0YXJ0RGVjYWRlLnllYXIoKSArIDYpICsgXCJcXFwiPlwiICsgc3RhcnREZWNhZGUueWVhcigpICsgXCI8L3NwYW4+XCI7XG4gICAgICBkZWNhZGVzVmlldy5maW5kKCd0ZCcpLmh0bWwoaHRtbCk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2ZpbGxEYXRlID0gZnVuY3Rpb24gX2ZpbGxEYXRlKCkge1xuICAgICAgX0RhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZmlsbERhdGUuY2FsbCh0aGlzKTtcblxuICAgICAgdmFyIGRheXNWaWV3ID0gdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItZGF5cycpLFxuICAgICAgICAgIGRheXNWaWV3SGVhZGVyID0gZGF5c1ZpZXcuZmluZCgndGgnKSxcbiAgICAgICAgICBodG1sID0gW107XG4gICAgICB2YXIgY3VycmVudERhdGUsIHJvdywgY2xzTmFtZSwgaTtcblxuICAgICAgaWYgKCF0aGlzLl9oYXNEYXRlKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBkYXlzVmlld0hlYWRlci5lcSgwKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnByZXZNb250aCk7XG4gICAgICBkYXlzVmlld0hlYWRlci5lcSgxKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0TW9udGgpO1xuICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMikuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5uZXh0TW9udGgpO1xuICAgICAgZGF5c1ZpZXcuZmluZCgnLmRpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICBkYXlzVmlld0hlYWRlci5lcSgxKS50ZXh0KHRoaXMuX3ZpZXdEYXRlLmZvcm1hdCh0aGlzLl9vcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQpKTtcblxuICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuc3VidHJhY3QoMSwgJ00nKSwgJ00nKSkge1xuICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuYWRkKDEsICdNJyksICdNJykpIHtcbiAgICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICB9XG5cbiAgICAgIGN1cnJlbnREYXRlID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdNJykuc3RhcnRPZigndycpLnN0YXJ0T2YoJ2QnKTtcblxuICAgICAgZm9yIChpID0gMDsgaSA8IDQyOyBpKyspIHtcbiAgICAgICAgLy9hbHdheXMgZGlzcGxheSA0MiBkYXlzIChzaG91bGQgc2hvdyA2IHdlZWtzKVxuICAgICAgICBpZiAoY3VycmVudERhdGUud2Vla2RheSgpID09PSAwKSB7XG4gICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xuXG4gICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcykge1xuICAgICAgICAgICAgcm93LmFwcGVuZChcIjx0ZCBjbGFzcz1cXFwiY3dcXFwiPlwiICsgY3VycmVudERhdGUud2VlaygpICsgXCI8L3RkPlwiKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBodG1sLnB1c2gocm93KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNsc05hbWUgPSAnJztcblxuICAgICAgICBpZiAoY3VycmVudERhdGUuaXNCZWZvcmUodGhpcy5fdmlld0RhdGUsICdNJykpIHtcbiAgICAgICAgICBjbHNOYW1lICs9ICcgb2xkJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc0FmdGVyKHRoaXMuX3ZpZXdEYXRlLCAnTScpKSB7XG4gICAgICAgICAgY2xzTmFtZSArPSAnIG5ldyc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgIHZhciBpbmRleCA9IHRoaXMuX2RhdGVzRm9ybWF0dGVkLmluZGV4T2YoY3VycmVudERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykpO1xuXG4gICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmlzU2FtZSh0aGlzLl9kYXRlc0Zvcm1hdHRlZFtpbmRleF0sICdkJykgJiYgIXRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgY2xzTmFtZSArPSAnIGFjdGl2ZSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc1NhbWUodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKSwgJ2QnKSAmJiAhdGhpcy51bnNldCkge1xuICAgICAgICAgICAgY2xzTmFtZSArPSAnIGFjdGl2ZSc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKGN1cnJlbnREYXRlLCAnZCcpKSB7XG4gICAgICAgICAgY2xzTmFtZSArPSAnIGRpc2FibGVkJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc1NhbWUodGhpcy5nZXRNb21lbnQoKSwgJ2QnKSkge1xuICAgICAgICAgIGNsc05hbWUgKz0gJyB0b2RheSc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY3VycmVudERhdGUuZGF5KCkgPT09IDAgfHwgY3VycmVudERhdGUuZGF5KCkgPT09IDYpIHtcbiAgICAgICAgICBjbHNOYW1lICs9ICcgd2Vla2VuZCc7XG4gICAgICAgIH1cblxuICAgICAgICByb3cuYXBwZW5kKFwiPHRkIGRhdGEtYWN0aW9uPVxcXCJzZWxlY3REYXlcXFwiIGRhdGEtZGF5PVxcXCJcIiArIGN1cnJlbnREYXRlLmZvcm1hdCgnTCcpICsgXCJcXFwiIGNsYXNzPVxcXCJkYXlcIiArIGNsc05hbWUgKyBcIlxcXCI+XCIgKyBjdXJyZW50RGF0ZS5kYXRlKCkgKyBcIjwvdGQ+XCIpO1xuICAgICAgICBjdXJyZW50RGF0ZS5hZGQoMSwgJ2QnKTtcbiAgICAgIH1cblxuICAgICAgJCgnYm9keScpLmFkZENsYXNzKCd0ZW1wdXNkb21pbnVzLWJvb3RzdHJhcC1kYXRldGltZXBpY2tlci13aWRnZXQtZGF5LWNsaWNrJyk7XG4gICAgICAkKCdib2R5JykuYXBwZW5kKCc8ZGl2IGNsYXNzPVwidGVtcHVzZG9taW51cy1ib290c3RyYXAtZGF0ZXRpbWVwaWNrZXItd2lkZ2V0LWRheS1jbGljay1nbGFzcy1wYW5lbFwiPjwvZGl2PicpO1xuICAgICAgZGF5c1ZpZXcuZmluZCgndGJvZHknKS5lbXB0eSgpLmFwcGVuZChodG1sKTtcbiAgICAgICQoJ2JvZHknKS5maW5kKCcudGVtcHVzZG9taW51cy1ib290c3RyYXAtZGF0ZXRpbWVwaWNrZXItd2lkZ2V0LWRheS1jbGljay1nbGFzcy1wYW5lbCcpLnJlbW92ZSgpO1xuICAgICAgJCgnYm9keScpLnJlbW92ZUNsYXNzKCd0ZW1wdXNkb21pbnVzLWJvb3RzdHJhcC1kYXRldGltZXBpY2tlci13aWRnZXQtZGF5LWNsaWNrJyk7XG5cbiAgICAgIHRoaXMuX3VwZGF0ZU1vbnRocygpO1xuXG4gICAgICB0aGlzLl91cGRhdGVZZWFycygpO1xuXG4gICAgICB0aGlzLl91cGRhdGVEZWNhZGVzKCk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2ZpbGxIb3VycyA9IGZ1bmN0aW9uIF9maWxsSG91cnMoKSB7XG4gICAgICB2YXIgdGFibGUgPSB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlci1ob3VycyB0YWJsZScpLFxuICAgICAgICAgIGN1cnJlbnRIb3VyID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdkJyksXG4gICAgICAgICAgaHRtbCA9IFtdO1xuXG4gICAgICB2YXIgcm93ID0gJCgnPHRyPicpO1xuXG4gICAgICBpZiAodGhpcy5fdmlld0RhdGUuaG91cigpID4gMTEgJiYgIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICBjdXJyZW50SG91ci5ob3VyKDEyKTtcbiAgICAgIH1cblxuICAgICAgd2hpbGUgKGN1cnJlbnRIb3VyLmlzU2FtZSh0aGlzLl92aWV3RGF0ZSwgJ2QnKSAmJiAodGhpcy51c2UyNEhvdXJzIHx8IHRoaXMuX3ZpZXdEYXRlLmhvdXIoKSA8IDEyICYmIGN1cnJlbnRIb3VyLmhvdXIoKSA8IDEyIHx8IHRoaXMuX3ZpZXdEYXRlLmhvdXIoKSA+IDExKSkge1xuICAgICAgICBpZiAoY3VycmVudEhvdXIuaG91cigpICUgNCA9PT0gMCkge1xuICAgICAgICAgIHJvdyA9ICQoJzx0cj4nKTtcbiAgICAgICAgICBodG1sLnB1c2gocm93KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJvdy5hcHBlbmQoXCI8dGQgZGF0YS1hY3Rpb249XFxcInNlbGVjdEhvdXJcXFwiIGNsYXNzPVxcXCJob3VyXCIgKyAoIXRoaXMuX2lzVmFsaWQoY3VycmVudEhvdXIsICdoJykgPyAnIGRpc2FibGVkJyA6ICcnKSArIFwiXFxcIj5cIiArIGN1cnJlbnRIb3VyLmZvcm1hdCh0aGlzLnVzZTI0SG91cnMgPyAnSEgnIDogJ2hoJykgKyBcIjwvdGQ+XCIpO1xuICAgICAgICBjdXJyZW50SG91ci5hZGQoMSwgJ2gnKTtcbiAgICAgIH1cblxuICAgICAgdGFibGUuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2ZpbGxNaW51dGVzID0gZnVuY3Rpb24gX2ZpbGxNaW51dGVzKCkge1xuICAgICAgdmFyIHRhYmxlID0gdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItbWludXRlcyB0YWJsZScpLFxuICAgICAgICAgIGN1cnJlbnRNaW51dGUgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ2gnKSxcbiAgICAgICAgICBodG1sID0gW10sXG4gICAgICAgICAgc3RlcCA9IHRoaXMuX29wdGlvbnMuc3RlcHBpbmcgPT09IDEgPyA1IDogdGhpcy5fb3B0aW9ucy5zdGVwcGluZztcblxuICAgICAgdmFyIHJvdyA9ICQoJzx0cj4nKTtcblxuICAgICAgd2hpbGUgKHRoaXMuX3ZpZXdEYXRlLmlzU2FtZShjdXJyZW50TWludXRlLCAnaCcpKSB7XG4gICAgICAgIGlmIChjdXJyZW50TWludXRlLm1pbnV0ZSgpICUgKHN0ZXAgKiA0KSA9PT0gMCkge1xuICAgICAgICAgIHJvdyA9ICQoJzx0cj4nKTtcbiAgICAgICAgICBodG1sLnB1c2gocm93KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJvdy5hcHBlbmQoXCI8dGQgZGF0YS1hY3Rpb249XFxcInNlbGVjdE1pbnV0ZVxcXCIgY2xhc3M9XFxcIm1pbnV0ZVwiICsgKCF0aGlzLl9pc1ZhbGlkKGN1cnJlbnRNaW51dGUsICdtJykgPyAnIGRpc2FibGVkJyA6ICcnKSArIFwiXFxcIj5cIiArIGN1cnJlbnRNaW51dGUuZm9ybWF0KCdtbScpICsgXCI8L3RkPlwiKTtcbiAgICAgICAgY3VycmVudE1pbnV0ZS5hZGQoc3RlcCwgJ20nKTtcbiAgICAgIH1cblxuICAgICAgdGFibGUuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2ZpbGxTZWNvbmRzID0gZnVuY3Rpb24gX2ZpbGxTZWNvbmRzKCkge1xuICAgICAgdmFyIHRhYmxlID0gdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItc2Vjb25kcyB0YWJsZScpLFxuICAgICAgICAgIGN1cnJlbnRTZWNvbmQgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ20nKSxcbiAgICAgICAgICBodG1sID0gW107XG5cbiAgICAgIHZhciByb3cgPSAkKCc8dHI+Jyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLl92aWV3RGF0ZS5pc1NhbWUoY3VycmVudFNlY29uZCwgJ20nKSkge1xuICAgICAgICBpZiAoY3VycmVudFNlY29uZC5zZWNvbmQoKSAlIDIwID09PSAwKSB7XG4gICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xuICAgICAgICAgIGh0bWwucHVzaChyb3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgcm93LmFwcGVuZChcIjx0ZCBkYXRhLWFjdGlvbj1cXFwic2VsZWN0U2Vjb25kXFxcIiBjbGFzcz1cXFwic2Vjb25kXCIgKyAoIXRoaXMuX2lzVmFsaWQoY3VycmVudFNlY29uZCwgJ3MnKSA/ICcgZGlzYWJsZWQnIDogJycpICsgXCJcXFwiPlwiICsgY3VycmVudFNlY29uZC5mb3JtYXQoJ3NzJykgKyBcIjwvdGQ+XCIpO1xuICAgICAgICBjdXJyZW50U2Vjb25kLmFkZCg1LCAncycpO1xuICAgICAgfVxuXG4gICAgICB0YWJsZS5lbXB0eSgpLmFwcGVuZChodG1sKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvMi5fZmlsbFRpbWUgPSBmdW5jdGlvbiBfZmlsbFRpbWUoKSB7XG4gICAgICB2YXIgdG9nZ2xlLCBuZXdEYXRlO1xuXG4gICAgICB2YXIgdGltZUNvbXBvbmVudHMgPSB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciBzcGFuW2RhdGEtdGltZS1jb21wb25lbnRdJyksXG4gICAgICAgICAgbGFzdFBpY2tlZERhdGUgPSB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpO1xuXG4gICAgICBpZiAoIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICB0b2dnbGUgPSB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciBbZGF0YS1hY3Rpb249dG9nZ2xlUGVyaW9kXScpO1xuICAgICAgICBuZXdEYXRlID0gbGFzdFBpY2tlZERhdGUgPyBsYXN0UGlja2VkRGF0ZS5jbG9uZSgpLmFkZChsYXN0UGlja2VkRGF0ZS5ob3VycygpID49IDEyID8gLTEyIDogMTIsICdoJykgOiB2b2lkIDA7XG4gICAgICAgIGxhc3RQaWNrZWREYXRlICYmIHRvZ2dsZS50ZXh0KGxhc3RQaWNrZWREYXRlLmZvcm1hdCgnQScpKTtcblxuICAgICAgICBpZiAodGhpcy5faXNWYWxpZChuZXdEYXRlLCAnaCcpKSB7XG4gICAgICAgICAgdG9nZ2xlLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRvZ2dsZS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsYXN0UGlja2VkRGF0ZSAmJiB0aW1lQ29tcG9uZW50cy5maWx0ZXIoJ1tkYXRhLXRpbWUtY29tcG9uZW50PWhvdXJzXScpLnRleHQobGFzdFBpY2tlZERhdGUuZm9ybWF0KFwiXCIgKyAodGhpcy51c2UyNEhvdXJzID8gJ0hIJyA6ICdoaCcpKSk7XG4gICAgICBsYXN0UGlja2VkRGF0ZSAmJiB0aW1lQ29tcG9uZW50cy5maWx0ZXIoJ1tkYXRhLXRpbWUtY29tcG9uZW50PW1pbnV0ZXNdJykudGV4dChsYXN0UGlja2VkRGF0ZS5mb3JtYXQoJ21tJykpO1xuICAgICAgbGFzdFBpY2tlZERhdGUgJiYgdGltZUNvbXBvbmVudHMuZmlsdGVyKCdbZGF0YS10aW1lLWNvbXBvbmVudD1zZWNvbmRzXScpLnRleHQobGFzdFBpY2tlZERhdGUuZm9ybWF0KCdzcycpKTtcblxuICAgICAgdGhpcy5fZmlsbEhvdXJzKCk7XG5cbiAgICAgIHRoaXMuX2ZpbGxNaW51dGVzKCk7XG5cbiAgICAgIHRoaXMuX2ZpbGxTZWNvbmRzKCk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuX2RvQWN0aW9uID0gZnVuY3Rpb24gX2RvQWN0aW9uKGUsIGFjdGlvbikge1xuICAgICAgdmFyIGxhc3RQaWNrZWQgPSB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpO1xuXG4gICAgICBpZiAoJChlLmN1cnJlbnRUYXJnZXQpLmlzKCcuZGlzYWJsZWQnKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGFjdGlvbiA9IGFjdGlvbiB8fCAkKGUuY3VycmVudFRhcmdldCkuZGF0YSgnYWN0aW9uJyk7XG5cbiAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgIGNhc2UgJ25leHQnOlxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBuYXZGbmMgPSBEYXRlVGltZVBpY2tlci5EYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLk5BVl9GVU5DVElPTjtcblxuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUuYWRkKERhdGVUaW1lUGlja2VyLkRhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uTkFWX1NURVAsIG5hdkZuYyk7XG5cbiAgICAgICAgICAgIHRoaXMuX2ZpbGxEYXRlKCk7XG5cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUobmF2Rm5jKTtcblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ3ByZXZpb3VzJzpcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgX25hdkZuYyA9IERhdGVUaW1lUGlja2VyLkRhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uTkFWX0ZVTkNUSU9OO1xuXG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5zdWJ0cmFjdChEYXRlVGltZVBpY2tlci5EYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLk5BVl9TVEVQLCBfbmF2Rm5jKTtcblxuICAgICAgICAgICAgdGhpcy5fZmlsbERhdGUoKTtcblxuICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZShfbmF2Rm5jKTtcblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ3BpY2tlclN3aXRjaCc6XG4gICAgICAgICAgdGhpcy5fc2hvd01vZGUoMSk7XG5cbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdzZWxlY3RNb250aCc6XG4gICAgICAgICAge1xuICAgICAgICAgICAgdmFyIG1vbnRoID0gJChlLnRhcmdldCkuY2xvc2VzdCgndGJvZHknKS5maW5kKCdzcGFuJykuaW5kZXgoJChlLnRhcmdldCkpO1xuXG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5tb250aChtb250aCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRWaWV3TW9kZSA9PT0gdGhpcy5NaW5WaWV3TW9kZU51bWJlcikge1xuICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkueWVhcih0aGlzLl92aWV3RGF0ZS55ZWFyKCkpLm1vbnRoKHRoaXMuX3ZpZXdEYXRlLm1vbnRoKCkpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuXG4gICAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhpcy5fc2hvd01vZGUoLTEpO1xuXG4gICAgICAgICAgICAgIHRoaXMuX2ZpbGxEYXRlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoJ00nKTtcblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ3NlbGVjdFllYXInOlxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciB5ZWFyID0gcGFyc2VJbnQoJChlLnRhcmdldCkudGV4dCgpLCAxMCkgfHwgMDtcblxuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUueWVhcih5ZWFyKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudFZpZXdNb2RlID09PSB0aGlzLk1pblZpZXdNb2RlTnVtYmVyKSB7XG4gICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS55ZWFyKHRoaXMuX3ZpZXdEYXRlLnllYXIoKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG5cbiAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgtMSk7XG5cbiAgICAgICAgICAgICAgdGhpcy5fZmlsbERhdGUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZSgnWVlZWScpO1xuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAnc2VsZWN0RGVjYWRlJzpcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgX3llYXIgPSBwYXJzZUludCgkKGUudGFyZ2V0KS5kYXRhKCdzZWxlY3Rpb24nKSwgMTApIHx8IDA7XG5cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlLnllYXIoX3llYXIpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50Vmlld01vZGUgPT09IHRoaXMuTWluVmlld01vZGVOdW1iZXIpIHtcbiAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobGFzdFBpY2tlZC5jbG9uZSgpLnllYXIodGhpcy5fdmlld0RhdGUueWVhcigpKSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcblxuICAgICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKC0xKTtcblxuICAgICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl92aWV3VXBkYXRlKCdZWVlZJyk7XG5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICBjYXNlICdzZWxlY3REYXknOlxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBkYXkgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpO1xuXG4gICAgICAgICAgICBpZiAoJChlLnRhcmdldCkuaXMoJy5vbGQnKSkge1xuICAgICAgICAgICAgICBkYXkuc3VidHJhY3QoMSwgJ00nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCQoZS50YXJnZXQpLmlzKCcubmV3JykpIHtcbiAgICAgICAgICAgICAgZGF5LmFkZCgxLCAnTScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgc2VsZWN0RGF0ZSA9IGRheS5kYXRlKHBhcnNlSW50KCQoZS50YXJnZXQpLnRleHQoKSwgMTApKSxcbiAgICAgICAgICAgICAgICBpbmRleCA9IDA7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlKSB7XG4gICAgICAgICAgICAgIGluZGV4ID0gdGhpcy5fZGF0ZXNGb3JtYXR0ZWQuaW5kZXhPZihzZWxlY3REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpKTtcblxuICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobnVsbCwgaW5kZXgpOyAvL2Rlc2VsZWN0IG11bHRpZGF0ZVxuXG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoc2VsZWN0RGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpICsgMSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHNlbGVjdERhdGUsIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5faGFzVGltZSgpICYmICF0aGlzLl9vcHRpb25zLmtlZXBPcGVuICYmICF0aGlzLl9vcHRpb25zLmlubGluZSAmJiAhdGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ2luY3JlbWVudEhvdXJzJzpcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZiAoIWxhc3RQaWNrZWQpIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBuZXdEYXRlID0gbGFzdFBpY2tlZC5jbG9uZSgpLmFkZCgxLCAnaCcpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZChuZXdEYXRlLCAnaCcpKSB7XG4gICAgICAgICAgICAgIGlmICh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlKG5ld0RhdGUpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobmV3RGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ2luY3JlbWVudE1pbnV0ZXMnOlxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGlmICghbGFzdFBpY2tlZCkge1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIF9uZXdEYXRlID0gbGFzdFBpY2tlZC5jbG9uZSgpLmFkZCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZChfbmV3RGF0ZSwgJ20nKSkge1xuICAgICAgICAgICAgICBpZiAodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpIDwgMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShfbmV3RGF0ZSk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShfbmV3RGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ2luY3JlbWVudFNlY29uZHMnOlxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGlmICghbGFzdFBpY2tlZCkge1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIF9uZXdEYXRlMiA9IGxhc3RQaWNrZWQuY2xvbmUoKS5hZGQoMSwgJ3MnKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGUyLCAncycpKSB7XG4gICAgICAgICAgICAgIGlmICh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlKF9uZXdEYXRlMik7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShfbmV3RGF0ZTIsIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICBjYXNlICdkZWNyZW1lbnRIb3Vycyc6XG4gICAgICAgICAge1xuICAgICAgICAgICAgaWYgKCFsYXN0UGlja2VkKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgX25ld0RhdGUzID0gbGFzdFBpY2tlZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdoJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKF9uZXdEYXRlMywgJ2gnKSkge1xuICAgICAgICAgICAgICBpZiAodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpIDwgMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShfbmV3RGF0ZTMpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGUzLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAnZGVjcmVtZW50TWludXRlcyc6XG4gICAgICAgICAge1xuICAgICAgICAgICAgaWYgKCFsYXN0UGlja2VkKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgX25ld0RhdGU0ID0gbGFzdFBpY2tlZC5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX29wdGlvbnMuc3RlcHBpbmcsICdtJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKF9uZXdEYXRlNCwgJ20nKSkge1xuICAgICAgICAgICAgICBpZiAodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpIDwgMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShfbmV3RGF0ZTQpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGU0LCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAnZGVjcmVtZW50U2Vjb25kcyc6XG4gICAgICAgICAge1xuICAgICAgICAgICAgaWYgKCFsYXN0UGlja2VkKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgX25ld0RhdGU1ID0gbGFzdFBpY2tlZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdzJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKF9uZXdEYXRlNSwgJ3MnKSkge1xuICAgICAgICAgICAgICBpZiAodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpIDwgMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShfbmV3RGF0ZTUpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGU1LCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAndG9nZ2xlUGVyaW9kJzpcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkuYWRkKGxhc3RQaWNrZWQuaG91cnMoKSA+PSAxMiA/IC0xMiA6IDEyLCAnaCcpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAndG9nZ2xlUGlja2VyJzpcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgJHRoaXMgPSAkKGUudGFyZ2V0KSxcbiAgICAgICAgICAgICAgICAkbGluayA9ICR0aGlzLmNsb3Nlc3QoJ2EnKSxcbiAgICAgICAgICAgICAgICAkcGFyZW50ID0gJHRoaXMuY2xvc2VzdCgndWwnKSxcbiAgICAgICAgICAgICAgICBleHBhbmRlZCA9ICRwYXJlbnQuZmluZCgnLnNob3cnKSxcbiAgICAgICAgICAgICAgICBjbG9zZWQgPSAkcGFyZW50LmZpbmQoJy5jb2xsYXBzZTpub3QoLnNob3cpJyksXG4gICAgICAgICAgICAgICAgJHNwYW4gPSAkdGhpcy5pcygnc3BhbicpID8gJHRoaXMgOiAkdGhpcy5maW5kKCdzcGFuJyk7XG4gICAgICAgICAgICB2YXIgY29sbGFwc2VEYXRhLCBpbmFjdGl2ZUljb24sIGljb25UZXN0O1xuXG4gICAgICAgICAgICBpZiAoZXhwYW5kZWQgJiYgZXhwYW5kZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIGNvbGxhcHNlRGF0YSA9IGV4cGFuZGVkLmRhdGEoJ2NvbGxhcHNlJyk7XG5cbiAgICAgICAgICAgICAgaWYgKGNvbGxhcHNlRGF0YSAmJiBjb2xsYXBzZURhdGEudHJhbnNpdGlvbmluZykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKGV4cGFuZGVkLmNvbGxhcHNlKSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgY29sbGFwc2UgcGx1Z2luIGlzIGF2YWlsYWJsZSB0aHJvdWdoIGJvb3RzdHJhcC5qcyB0aGVuIHVzZSBpdFxuICAgICAgICAgICAgICAgIGV4cGFuZGVkLmNvbGxhcHNlKCdoaWRlJyk7XG4gICAgICAgICAgICAgICAgY2xvc2VkLmNvbGxhcHNlKCdzaG93Jyk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGp1c3QgdG9nZ2xlIGluIGNsYXNzIG9uIHRoZSB0d28gdmlld3NcbiAgICAgICAgICAgICAgICBleHBhbmRlZC5yZW1vdmVDbGFzcygnc2hvdycpO1xuICAgICAgICAgICAgICAgIGNsb3NlZC5hZGRDbGFzcygnc2hvdycpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHRoaXMuX3VzZUZlYXRoZXJJY29ucygpKSB7XG4gICAgICAgICAgICAgICAgJGxpbmsudG9nZ2xlQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy50aW1lICsgJyAnICsgdGhpcy5fb3B0aW9ucy5pY29ucy5kYXRlKTtcbiAgICAgICAgICAgICAgICBpbmFjdGl2ZUljb24gPSAkbGluay5oYXNDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLnRpbWUpID8gdGhpcy5fb3B0aW9ucy5pY29ucy5kYXRlIDogdGhpcy5fb3B0aW9ucy5pY29ucy50aW1lO1xuICAgICAgICAgICAgICAgICRsaW5rLmh0bWwodGhpcy5faWNvblRhZyhpbmFjdGl2ZUljb24pKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkc3Bhbi50b2dnbGVDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLnRpbWUgKyAnICcgKyB0aGlzLl9vcHRpb25zLmljb25zLmRhdGUpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHRoaXMuX3VzZUZlYXRoZXJJY29ucygpKSB7XG4gICAgICAgICAgICAgICAgaWNvblRlc3QgPSAkbGluay5oYXNDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRhdGUpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGljb25UZXN0ID0gJHNwYW4uaGFzQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy5kYXRlKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmIChpY29uVGVzdCkge1xuICAgICAgICAgICAgICAgICRsaW5rLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3REYXRlKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkbGluay5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0VGltZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnc2hvd1BpY2tlcic6XG4gICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgPiBkaXY6bm90KC50aW1lcGlja2VyLXBpY2tlciknKS5oaWRlKCk7XG4gICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuc2hvdygpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3Nob3dIb3Vycyc6XG4gICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuaGlkZSgpO1xuICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLWhvdXJzJykuc2hvdygpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3Nob3dNaW51dGVzJzpcbiAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1waWNrZXInKS5oaWRlKCk7XG4gICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItbWludXRlcycpLnNob3coKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdzaG93U2Vjb25kcyc6XG4gICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuaGlkZSgpO1xuICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLXNlY29uZHMnKS5zaG93KCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnc2VsZWN0SG91cic6XG4gICAgICAgICAge1xuICAgICAgICAgICAgdmFyIGhvdXIgPSBwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnVzZTI0SG91cnMpIHtcbiAgICAgICAgICAgICAgaWYgKGxhc3RQaWNrZWQuaG91cnMoKSA+PSAxMikge1xuICAgICAgICAgICAgICAgIGlmIChob3VyICE9PSAxMikge1xuICAgICAgICAgICAgICAgICAgaG91ciArPSAxMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobGFzdFBpY2tlZC5jbG9uZSgpLmhvdXJzKGhvdXIpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzRW5hYmxlZCgnYScpICYmICF0aGlzLl9pc0VuYWJsZWQoJ20nKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLl9kb0FjdGlvbihlLCAnc2hvd1BpY2tlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAnc2VsZWN0TWludXRlJzpcbiAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkubWludXRlcyhwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG5cbiAgICAgICAgICBpZiAoIXRoaXMuX2lzRW5hYmxlZCgnYScpICYmICF0aGlzLl9pc0VuYWJsZWQoJ3MnKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9kb0FjdGlvbihlLCAnc2hvd1BpY2tlcicpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3NlbGVjdFNlY29uZCc6XG4gICAgICAgICAgdGhpcy5fc2V0VmFsdWUobGFzdFBpY2tlZC5jbG9uZSgpLnNlY29uZHMocGFyc2VJbnQoJChlLnRhcmdldCkudGV4dCgpLCAxMCkpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuXG4gICAgICAgICAgaWYgKCF0aGlzLl9pc0VuYWJsZWQoJ2EnKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9kb0FjdGlvbihlLCAnc2hvd1BpY2tlcicpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ2NsZWFyJzpcbiAgICAgICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnY2xvc2UnOlxuICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3RvZGF5JzpcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgdG9kYXlzRGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKHRvZGF5c0RhdGUsICdkJykpIHtcbiAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodG9kYXlzRGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSAvL3B1YmxpY1xuICAgIDtcblxuICAgIF9wcm90bzIuaGlkZSA9IGZ1bmN0aW9uIGhpZGUoKSB7XG4gICAgICB2YXIgdHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuXG4gICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gSWdub3JlIGV2ZW50IGlmIGluIHRoZSBtaWRkbGUgb2YgYSBwaWNrZXIgdHJhbnNpdGlvblxuXG5cbiAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5jb2xsYXBzZScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sbGFwc2VEYXRhID0gJCh0aGlzKS5kYXRhKCdjb2xsYXBzZScpO1xuXG4gICAgICAgIGlmIChjb2xsYXBzZURhdGEgJiYgY29sbGFwc2VEYXRhLnRyYW5zaXRpb25pbmcpIHtcbiAgICAgICAgICB0cmFuc2l0aW9uaW5nID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAodHJhbnNpdGlvbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgdGhpcy5jb21wb25lbnQudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLndpZGdldC5oaWRlKCk7XG4gICAgICAkKHdpbmRvdykub2ZmKCdyZXNpemUnLCB0aGlzLl9wbGFjZSk7XG4gICAgICB0aGlzLndpZGdldC5vZmYoJ2NsaWNrJywgJ1tkYXRhLWFjdGlvbl0nKTtcbiAgICAgIHRoaXMud2lkZ2V0Lm9mZignbW91c2Vkb3duJywgZmFsc2UpO1xuICAgICAgdGhpcy53aWRnZXQucmVtb3ZlKCk7XG4gICAgICB0aGlzLndpZGdldCA9IGZhbHNlO1xuXG4gICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQudmFsKCkgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fcGFyc2VJbnB1dERhdGUodGhpcy5pbnB1dC52YWwoKS50cmltKCksIHtcbiAgICAgICAgICBpc1BpY2tlclNob3c6IGZhbHNlXG4gICAgICAgIH0pLCAwKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGxhc3RQaWNrZWREYXRlID0gdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKTtcblxuICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5ISURFLFxuICAgICAgICBkYXRlOiB0aGlzLnVuc2V0ID8gbnVsbCA6IGxhc3RQaWNrZWREYXRlID8gbGFzdFBpY2tlZERhdGUuY2xvbmUoKSA6IHZvaWQgMFxuICAgICAgfSk7XG5cbiAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5pbnB1dC5ibHVyKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3ZpZXdEYXRlID0gbGFzdFBpY2tlZERhdGUgPyBsYXN0UGlja2VkRGF0ZS5jbG9uZSgpIDogdGhpcy5nZXRNb21lbnQoKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvMi5zaG93ID0gZnVuY3Rpb24gc2hvdygpIHtcbiAgICAgIHZhciBjdXJyZW50TW9tZW50LFxuICAgICAgICAgIHNob3VsZFVzZUN1cnJlbnRJZlVuc2V0ID0gZmFsc2U7XG4gICAgICB2YXIgdXNlQ3VycmVudEdyYW51bGFyaXR5ID0ge1xuICAgICAgICAneWVhcic6IGZ1bmN0aW9uIHllYXIobSkge1xuICAgICAgICAgIHJldHVybiBtLm1vbnRoKDApLmRhdGUoMSkuaG91cnMoMCkuc2Vjb25kcygwKS5taW51dGVzKDApO1xuICAgICAgICB9LFxuICAgICAgICAnbW9udGgnOiBmdW5jdGlvbiBtb250aChtKSB7XG4gICAgICAgICAgcmV0dXJuIG0uZGF0ZSgxKS5ob3VycygwKS5zZWNvbmRzKDApLm1pbnV0ZXMoMCk7XG4gICAgICAgIH0sXG4gICAgICAgICdkYXknOiBmdW5jdGlvbiBkYXkobSkge1xuICAgICAgICAgIHJldHVybiBtLmhvdXJzKDApLnNlY29uZHMoMCkubWludXRlcygwKTtcbiAgICAgICAgfSxcbiAgICAgICAgJ2hvdXInOiBmdW5jdGlvbiBob3VyKG0pIHtcbiAgICAgICAgICByZXR1cm4gbS5zZWNvbmRzKDApLm1pbnV0ZXMoMCk7XG4gICAgICAgIH0sXG4gICAgICAgICdtaW51dGUnOiBmdW5jdGlvbiBtaW51dGUobSkge1xuICAgICAgICAgIHJldHVybiBtLnNlY29uZHMoMCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHRoaXMuaW5wdXQucHJvcCgnZGlzYWJsZWQnKSB8fCAhdGhpcy5fb3B0aW9ucy5pZ25vcmVSZWFkb25seSAmJiB0aGlzLmlucHV0LnByb3AoJ3JlYWRvbmx5JykgfHwgdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pbnB1dC52YWwoKSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQudmFsKCkudHJpbSgpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX3BhcnNlSW5wdXREYXRlKHRoaXMuaW5wdXQudmFsKCkudHJpbSgpLCB7XG4gICAgICAgICAgICBpc1BpY2tlclNob3c6IHRydWVcbiAgICAgICAgICB9KSwgMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2hvdWxkVXNlQ3VycmVudElmVW5zZXQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaG91bGRVc2VDdXJyZW50SWZVbnNldCA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChzaG91bGRVc2VDdXJyZW50SWZVbnNldCAmJiB0aGlzLnVuc2V0ICYmIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCkge1xuICAgICAgICBjdXJyZW50TW9tZW50ID0gdGhpcy5nZXRNb21lbnQoKTtcblxuICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjdXJyZW50TW9tZW50ID0gdXNlQ3VycmVudEdyYW51bGFyaXR5W3RoaXMuX29wdGlvbnMudXNlQ3VycmVudF0oY3VycmVudE1vbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zZXRWYWx1ZShjdXJyZW50TW9tZW50LCAwKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy53aWRnZXQgPSB0aGlzLl9nZXRUZW1wbGF0ZSgpO1xuXG4gICAgICB0aGlzLl9maWxsRG93KCk7XG5cbiAgICAgIHRoaXMuX2ZpbGxNb250aHMoKTtcblxuICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItaG91cnMnKS5oaWRlKCk7XG4gICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlci1taW51dGVzJykuaGlkZSgpO1xuICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItc2Vjb25kcycpLmhpZGUoKTtcblxuICAgICAgdGhpcy5fdXBkYXRlKCk7XG5cbiAgICAgIHRoaXMuX3Nob3dNb2RlKCk7XG5cbiAgICAgICQod2luZG93KS5vbigncmVzaXplJywge1xuICAgICAgICBwaWNrZXI6IHRoaXNcbiAgICAgIH0sIHRoaXMuX3BsYWNlKTtcbiAgICAgIHRoaXMud2lkZ2V0Lm9uKCdjbGljaycsICdbZGF0YS1hY3Rpb25dJywgJC5wcm94eSh0aGlzLl9kb0FjdGlvbiwgdGhpcykpOyAvLyB0aGlzIGhhbmRsZXMgY2xpY2tzIG9uIHRoZSB3aWRnZXRcblxuICAgICAgdGhpcy53aWRnZXQub24oJ21vdXNlZG93bicsIGZhbHNlKTtcblxuICAgICAgaWYgKHRoaXMuY29tcG9uZW50ICYmIHRoaXMuY29tcG9uZW50Lmhhc0NsYXNzKCdidG4nKSkge1xuICAgICAgICB0aGlzLmNvbXBvbmVudC50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3BsYWNlKCk7XG5cbiAgICAgIHRoaXMud2lkZ2V0LnNob3coKTtcblxuICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLl9vcHRpb25zLmZvY3VzT25TaG93ICYmICF0aGlzLmlucHV0LmlzKCc6Zm9jdXMnKSkge1xuICAgICAgICB0aGlzLmlucHV0LmZvY3VzKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuU0hPV1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIF9wcm90bzIuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICB0aGlzLmhpZGUoKTsgLy90b2RvIGRvYyBvZmY/XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQucmVtb3ZlRGF0YShEYXRlVGltZVBpY2tlci5EQVRBX0tFWSk7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQucmVtb3ZlRGF0YSgnZGF0ZScpO1xuICAgIH07XG5cbiAgICBfcHJvdG8yLmRpc2FibGUgPSBmdW5jdGlvbiBkaXNhYmxlKCkge1xuICAgICAgdGhpcy5oaWRlKCk7XG5cbiAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgdGhpcy5jb21wb25lbnQuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5pbnB1dC5wcm9wKCdkaXNhYmxlZCcsIHRydWUpOyAvL3RvZG8gZGlzYWJsZSB0aGlzL2NvbXAgaWYgaW5wdXQgaXMgbnVsbFxuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8yLmVuYWJsZSA9IGZ1bmN0aW9uIGVuYWJsZSgpIHtcbiAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgdGhpcy5jb21wb25lbnQucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5pbnB1dC5wcm9wKCdkaXNhYmxlZCcsIGZhbHNlKTsgLy90b2RvIGVuYWJsZSBjb21wL3RoaXMgaWYgaW5wdXQgaXMgbnVsbFxuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8yLnRvb2xiYXJQbGFjZW1lbnQgPSBmdW5jdGlvbiB0b29sYmFyUGxhY2VtZW50KF90b29sYmFyUGxhY2VtZW50KSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50O1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIF90b29sYmFyUGxhY2VtZW50ICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0b29sYmFyUGxhY2VtZW50KCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRvb2xiYXJQbGFjZW1lbnRzLmluZGV4T2YoX3Rvb2xiYXJQbGFjZW1lbnQpID09PSAtMSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwidG9vbGJhclBsYWNlbWVudCgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiAoXCIgKyB0b29sYmFyUGxhY2VtZW50cy5qb2luKCcsICcpICsgXCIpIHZhbHVlXCIpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPSBfdG9vbGJhclBsYWNlbWVudDtcblxuICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvMi53aWRnZXRQb3NpdGlvbmluZyA9IGZ1bmN0aW9uIHdpZGdldFBvc2l0aW9uaW5nKF93aWRnZXRQb3NpdGlvbmluZykge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHt9LnRvU3RyaW5nLmNhbGwoX3dpZGdldFBvc2l0aW9uaW5nKSAhPT0gJ1tvYmplY3QgT2JqZWN0XScpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSBleHBlY3RzIGFuIG9iamVjdCB2YXJpYWJsZScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd3aWRnZXRQb3NpdGlvbmluZygpIGhvcml6b250YWwgdmFyaWFibGUgbXVzdCBiZSBhIHN0cmluZycpO1xuICAgICAgICB9XG5cbiAgICAgICAgX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwgPSBfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgIGlmIChob3Jpem9udGFsTW9kZXMuaW5kZXhPZihfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbCkgPT09IC0xKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIndpZGdldFBvc2l0aW9uaW5nKCkgZXhwZWN0cyBob3Jpem9udGFsIHBhcmFtZXRlciB0byBiZSBvbmUgb2YgKFwiICsgaG9yaXpvbnRhbE1vZGVzLmpvaW4oJywgJykgKyBcIilcIik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwgPSBfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbDtcbiAgICAgIH1cblxuICAgICAgaWYgKF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCkge1xuICAgICAgICBpZiAodHlwZW9mIF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd3aWRnZXRQb3NpdGlvbmluZygpIHZlcnRpY2FsIHZhcmlhYmxlIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCA9IF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgIGlmICh2ZXJ0aWNhbE1vZGVzLmluZGV4T2YoX3dpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsKSA9PT0gLTEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwid2lkZ2V0UG9zaXRpb25pbmcoKSBleHBlY3RzIHZlcnRpY2FsIHBhcmFtZXRlciB0byBiZSBvbmUgb2YgKFwiICsgdmVydGljYWxNb2Rlcy5qb2luKCcsICcpICsgXCIpXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCA9IF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgfTtcblxuICAgIF9wcm90bzIud2lkZ2V0UGFyZW50ID0gZnVuY3Rpb24gd2lkZ2V0UGFyZW50KF93aWRnZXRQYXJlbnQpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLndpZGdldFBhcmVudDtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBfd2lkZ2V0UGFyZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICBfd2lkZ2V0UGFyZW50ID0gJChfd2lkZ2V0UGFyZW50KTtcbiAgICAgIH1cblxuICAgICAgaWYgKF93aWRnZXRQYXJlbnQgIT09IG51bGwgJiYgdHlwZW9mIF93aWRnZXRQYXJlbnQgIT09ICdzdHJpbmcnICYmICEoX3dpZGdldFBhcmVudCBpbnN0YW5jZW9mICQpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBhcmVudCgpIGV4cGVjdHMgYSBzdHJpbmcgb3IgYSBqUXVlcnkgb2JqZWN0IHBhcmFtZXRlcicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcHRpb25zLndpZGdldFBhcmVudCA9IF93aWRnZXRQYXJlbnQ7XG5cbiAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90bzIuc2V0TXVsdGlEYXRlID0gZnVuY3Rpb24gc2V0TXVsdGlEYXRlKG11bHRpRGF0ZUFycmF5KSB7XG4gICAgICB2YXIgZGF0ZUZvcm1hdCA9IHRoaXMuX29wdGlvbnMuZm9ybWF0O1xuICAgICAgdGhpcy5jbGVhcigpO1xuXG4gICAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbXVsdGlEYXRlQXJyYXkubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgIHZhciBkYXRlID0gbW9tZW50KG11bHRpRGF0ZUFycmF5W2luZGV4XSwgZGF0ZUZvcm1hdCk7XG5cbiAgICAgICAgdGhpcy5fc2V0VmFsdWUoZGF0ZSwgaW5kZXgpO1xuICAgICAgfVxuICAgIH0gLy9zdGF0aWNcbiAgICA7XG5cbiAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SGFuZGxlVGhpcyA9IGZ1bmN0aW9uIF9qUXVlcnlIYW5kbGVUaGlzKG1lLCBvcHRpb24sIGFyZ3VtZW50KSB7XG4gICAgICB2YXIgZGF0YSA9ICQobWUpLmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpO1xuXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgJC5leHRlbmQoe30sIERhdGVUaW1lUGlja2VyLkRlZmF1bHQsIG9wdGlvbik7XG4gICAgICB9XG5cbiAgICAgIGlmICghZGF0YSkge1xuICAgICAgICBkYXRhID0gbmV3IFRlbXB1c0RvbWludXNCb290c3RyYXA0KCQobWUpLCBvcHRpb24pO1xuICAgICAgICAkKG1lKS5kYXRhKERhdGVUaW1lUGlja2VyLkRBVEFfS0VZLCBkYXRhKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGlmIChkYXRhW29wdGlvbl0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBvcHRpb24gKyBcIlxcXCJcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYXJndW1lbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJldHVybiBkYXRhW29wdGlvbl0oKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAob3B0aW9uID09PSAnZGF0ZScpIHtcbiAgICAgICAgICAgIGRhdGEuaXNEYXRlVXBkYXRlVGhyb3VnaERhdGVPcHRpb25Gcm9tQ2xpZW50Q29kZSA9IHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHJldCA9IGRhdGFbb3B0aW9uXShhcmd1bWVudCk7XG4gICAgICAgICAgZGF0YS5pc0RhdGVVcGRhdGVUaHJvdWdoRGF0ZU9wdGlvbkZyb21DbGllbnRDb2RlID0gZmFsc2U7XG4gICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShvcHRpb24sIGFyZ3VtZW50KSB7XG4gICAgICBpZiAodGhpcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlIYW5kbGVUaGlzKHRoaXNbMF0sIG9wdGlvbiwgYXJndW1lbnQpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUhhbmRsZVRoaXModGhpcywgb3B0aW9uLCBhcmd1bWVudCk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFRlbXB1c0RvbWludXNCb290c3RyYXA0O1xuICB9KERhdGVUaW1lUGlja2VyKTtcbiAgLyoqXHJcbiAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAqIGpRdWVyeVxyXG4gICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgKi9cblxuXG4gICQoZG9jdW1lbnQpLm9uKERhdGVUaW1lUGlja2VyLkV2ZW50LkNMSUNLX0RBVEFfQVBJLCBEYXRlVGltZVBpY2tlci5TZWxlY3Rvci5EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKCkge1xuICAgIHZhciAkb3JpZ2luYWxUYXJnZXQgPSAkKHRoaXMpLFxuICAgICAgICAkdGFyZ2V0ID0gZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCgkb3JpZ2luYWxUYXJnZXQpLFxuICAgICAgICBjb25maWcgPSAkdGFyZ2V0LmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpO1xuXG4gICAgaWYgKCR0YXJnZXQubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNvbmZpZy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlICYmICRvcmlnaW5hbFRhcmdldC5pcygnaW5wdXRbZGF0YS10b2dnbGU9XCJkYXRldGltZXBpY2tlclwiXScpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZS5jYWxsKCR0YXJnZXQsICd0b2dnbGUnKTtcbiAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLCBcIi5cIiArIERhdGVUaW1lUGlja2VyLkNsYXNzTmFtZS5JTlBVVCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpO1xuXG4gICAgaWYgKCR0YXJnZXQubGVuZ3RoID09PSAwIHx8IGV2ZW50LmlzSW5pdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkdGFyZ2V0LCAnX2NoYW5nZScsIGV2ZW50KTtcbiAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQkxVUiwgXCIuXCIgKyBEYXRlVGltZVBpY2tlci5DbGFzc05hbWUuSU5QVVQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciAkdGFyZ2V0ID0gZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCgkKHRoaXMpKSxcbiAgICAgICAgY29uZmlnID0gJHRhcmdldC5kYXRhKERhdGVUaW1lUGlja2VyLkRBVEFfS0VZKTtcblxuICAgIGlmICgkdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjb25maWcuX29wdGlvbnMuZGVidWcgfHwgd2luZG93LmRlYnVnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZS5jYWxsKCR0YXJnZXQsICdoaWRlJywgZXZlbnQpO1xuICB9KS5vbihEYXRlVGltZVBpY2tlci5FdmVudC5LRVlET1dOLCBcIi5cIiArIERhdGVUaW1lUGlja2VyLkNsYXNzTmFtZS5JTlBVVCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpO1xuXG4gICAgaWYgKCR0YXJnZXQubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZS5jYWxsKCR0YXJnZXQsICdfa2V5ZG93bicsIGV2ZW50KTtcbiAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuS0VZVVAsIFwiLlwiICsgRGF0ZVRpbWVQaWNrZXIuQ2xhc3NOYW1lLklOUFVULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSk7XG5cbiAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ19rZXl1cCcsIGV2ZW50KTtcbiAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuRk9DVVMsIFwiLlwiICsgRGF0ZVRpbWVQaWNrZXIuQ2xhc3NOYW1lLklOUFVULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSksXG4gICAgICAgIGNvbmZpZyA9ICR0YXJnZXQuZGF0YShEYXRlVGltZVBpY2tlci5EQVRBX0tFWSk7XG5cbiAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWNvbmZpZy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZS5jYWxsKCR0YXJnZXQsICdzaG93JywgZXZlbnQpO1xuICB9KTtcbiAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXSA9IFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2U7XG4gICQuZm5bRGF0ZVRpbWVQaWNrZXIuTkFNRV0uQ29uc3RydWN0b3IgPSBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNDtcblxuICAkLmZuW0RhdGVUaW1lUGlja2VyLk5BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICByZXR1cm4gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZTtcbiAgfTtcblxuICByZXR1cm4gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQ7XG59KGpRdWVyeSk7XHJcblxyXG59KCk7XHJcbiIsIi8qIVxuICogZGlzdC9qcXVlcnkuaW5wdXRtYXNrXG4gKiBodHRwczovL2dpdGh1Yi5jb20vUm9iaW5IZXJib3RzL0lucHV0bWFza1xuICogQ29weXJpZ2h0IChjKSAyMDEwIC0gMjAyMCBSb2JpbiBIZXJib3RzXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2VcbiAqIFZlcnNpb246IDUuMC41LWJldGEuMFxuICovXG4hZnVuY3Rpb24gd2VicGFja1VuaXZlcnNhbE1vZHVsZURlZmluaXRpb24ocm9vdCwgZmFjdG9yeSkge1xuICAgIGlmIChcIm9iamVjdFwiID09IHR5cGVvZiBleHBvcnRzICYmIFwib2JqZWN0XCIgPT0gdHlwZW9mIG1vZHVsZSkgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoXCJqcXVlcnlcIikpOyBlbHNlIGlmIChcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIGRlZmluZSAmJiBkZWZpbmUuYW1kKSBkZWZpbmUoWyBcImpxdWVyeVwiIF0sIGZhY3RvcnkpOyBlbHNlIHtcbiAgICAgICAgdmFyIGEgPSBcIm9iamVjdFwiID09IHR5cGVvZiBleHBvcnRzID8gZmFjdG9yeShyZXF1aXJlKFwianF1ZXJ5XCIpKSA6IGZhY3Rvcnkocm9vdC5qUXVlcnkpO1xuICAgICAgICBmb3IgKHZhciBpIGluIGEpIChcIm9iamVjdFwiID09IHR5cGVvZiBleHBvcnRzID8gZXhwb3J0cyA6IHJvb3QpW2ldID0gYVtpXTtcbiAgICB9XG59KHdpbmRvdywgZnVuY3Rpb24oX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV9fOF9fKSB7XG4gICAgcmV0dXJuIG1vZHVsZXMgPSBbIGZ1bmN0aW9uKG1vZHVsZSkge1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEpTT04ucGFyc2UoJ3tcIkJBQ0tTUEFDRVwiOjgsXCJCQUNLU1BBQ0VfU0FGQVJJXCI6MTI3LFwiREVMRVRFXCI6NDYsXCJET1dOXCI6NDAsXCJFTkRcIjozNSxcIkVOVEVSXCI6MTMsXCJFU0NBUEVcIjoyNyxcIkhPTUVcIjozNixcIklOU0VSVFwiOjQ1LFwiTEVGVFwiOjM3LFwiUEFHRV9ET1dOXCI6MzQsXCJQQUdFX1VQXCI6MzMsXCJSSUdIVFwiOjM5LFwiU1BBQ0VcIjozMixcIlRBQlwiOjksXCJVUFwiOjM4LFwiWFwiOjg4LFwiQ09OVFJPTFwiOjE3LFwiS0VZXzIyOVwiOjIyOX0nKTtcbiAgICB9LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICAgICAgICAgICAgdmFsdWU6ICEwXG4gICAgICAgIH0pLCBleHBvcnRzLmRlZmF1bHQgPSB2b2lkIDAsIF9fd2VicGFja19yZXF1aXJlX18oOSk7XG4gICAgICAgIHZhciBfbWFzayA9IF9fd2VicGFja19yZXF1aXJlX18oMTApLCBfaW5wdXRtYXNrID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDEyKSksIF93aW5kb3cgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMTMpKSwgX21hc2tMZXhlciA9IF9fd2VicGFja19yZXF1aXJlX18oMTcpLCBfdmFsaWRhdGlvblRlc3RzID0gX193ZWJwYWNrX3JlcXVpcmVfXygzKSwgX3Bvc2l0aW9uaW5nID0gX193ZWJwYWNrX3JlcXVpcmVfXygyKSwgX3ZhbGlkYXRpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQpLCBfaW5wdXRIYW5kbGluZyA9IF9fd2VicGFja19yZXF1aXJlX18oNSksIF9ldmVudHJ1bGVyID0gX193ZWJwYWNrX3JlcXVpcmVfXygxMSksIF9kZWZpbml0aW9ucyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygxOCkpLCBfZGVmYXVsdHMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMTkpKTtcbiAgICAgICAgZnVuY3Rpb24gX3R5cGVvZihvYmopIHtcbiAgICAgICAgICAgIHJldHVybiBfdHlwZW9mID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgXCJzeW1ib2xcIiA9PSB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID8gZnVuY3Rpb24gX3R5cGVvZihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIG9iajtcbiAgICAgICAgICAgIH0gOiBmdW5jdGlvbiBfdHlwZW9mKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmogJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7XG4gICAgICAgICAgICB9LCBfdHlwZW9mKG9iaik7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHtcbiAgICAgICAgICAgIHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDogb2JqXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBkb2N1bWVudCA9IF93aW5kb3cuZGVmYXVsdC5kb2N1bWVudCwgZGF0YUtleSA9IFwiX2lucHV0bWFza19vcHRzXCI7XG4gICAgICAgIGZ1bmN0aW9uIElucHV0bWFzayhhbGlhcywgb3B0aW9ucywgaW50ZXJuYWwpIHtcbiAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBJbnB1dG1hc2spKSByZXR1cm4gbmV3IElucHV0bWFzayhhbGlhcywgb3B0aW9ucywgaW50ZXJuYWwpO1xuICAgICAgICAgICAgdGhpcy5kZXBlbmRlbmN5TGliID0gX2lucHV0bWFzay5kZWZhdWx0LCB0aGlzLmVsID0gdm9pZCAwLCB0aGlzLmV2ZW50cyA9IHt9LCB0aGlzLm1hc2tzZXQgPSB2b2lkIDAsIFxuICAgICAgICAgICAgITAgIT09IGludGVybmFsICYmIChcIltvYmplY3QgT2JqZWN0XVwiID09PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYWxpYXMpID8gb3B0aW9ucyA9IGFsaWFzIDogKG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LCBcbiAgICAgICAgICAgIGFsaWFzICYmIChvcHRpb25zLmFsaWFzID0gYWxpYXMpKSwgdGhpcy5vcHRzID0gX2lucHV0bWFzay5kZWZhdWx0LmV4dGVuZCghMCwge30sIHRoaXMuZGVmYXVsdHMsIG9wdGlvbnMpLCBcbiAgICAgICAgICAgIHRoaXMubm9NYXNrc0NhY2hlID0gb3B0aW9ucyAmJiB2b2lkIDAgIT09IG9wdGlvbnMuZGVmaW5pdGlvbnMsIHRoaXMudXNlck9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LCBcbiAgICAgICAgICAgIHJlc29sdmVBbGlhcyh0aGlzLm9wdHMuYWxpYXMsIG9wdGlvbnMsIHRoaXMub3B0cykpLCB0aGlzLnJlZnJlc2hWYWx1ZSA9ICExLCB0aGlzLnVuZG9WYWx1ZSA9IHZvaWQgMCwgXG4gICAgICAgICAgICB0aGlzLiRlbCA9IHZvaWQgMCwgdGhpcy5za2lwS2V5UHJlc3NFdmVudCA9ICExLCB0aGlzLnNraXBJbnB1dEV2ZW50ID0gITEsIHRoaXMudmFsaWRhdGlvbkV2ZW50ID0gITEsIFxuICAgICAgICAgICAgdGhpcy5pZ25vcmFibGUgPSAhMSwgdGhpcy5tYXhMZW5ndGgsIHRoaXMubW91c2VFbnRlciA9ICExLCB0aGlzLm9yaWdpbmFsUGxhY2Vob2xkZXIgPSB2b2lkIDAsIFxuICAgICAgICAgICAgdGhpcy5pc0NvbXBvc2luZyA9ICExO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHJlc29sdmVBbGlhcyhhbGlhc1N0ciwgb3B0aW9ucywgb3B0cykge1xuICAgICAgICAgICAgdmFyIGFsaWFzRGVmaW5pdGlvbiA9IElucHV0bWFzay5wcm90b3R5cGUuYWxpYXNlc1thbGlhc1N0cl07XG4gICAgICAgICAgICByZXR1cm4gYWxpYXNEZWZpbml0aW9uID8gKGFsaWFzRGVmaW5pdGlvbi5hbGlhcyAmJiByZXNvbHZlQWxpYXMoYWxpYXNEZWZpbml0aW9uLmFsaWFzLCB2b2lkIDAsIG9wdHMpLCBcbiAgICAgICAgICAgIF9pbnB1dG1hc2suZGVmYXVsdC5leHRlbmQoITAsIG9wdHMsIGFsaWFzRGVmaW5pdGlvbiksIF9pbnB1dG1hc2suZGVmYXVsdC5leHRlbmQoITAsIG9wdHMsIG9wdGlvbnMpLCBcbiAgICAgICAgICAgICEwKSA6IChudWxsID09PSBvcHRzLm1hc2sgJiYgKG9wdHMubWFzayA9IGFsaWFzU3RyKSwgITEpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGltcG9ydEF0dHJpYnV0ZU9wdGlvbnMobnB0LCBvcHRzLCB1c2VyT3B0aW9ucywgZGF0YUF0dHJpYnV0ZSkge1xuICAgICAgICAgICAgZnVuY3Rpb24gaW1wb3J0T3B0aW9uKG9wdGlvbiwgb3B0aW9uRGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBhdHRyT3B0aW9uID0gXCJcIiA9PT0gZGF0YUF0dHJpYnV0ZSA/IG9wdGlvbiA6IGRhdGFBdHRyaWJ1dGUgKyBcIi1cIiArIG9wdGlvbjtcbiAgICAgICAgICAgICAgICBvcHRpb25EYXRhID0gdm9pZCAwICE9PSBvcHRpb25EYXRhID8gb3B0aW9uRGF0YSA6IG5wdC5nZXRBdHRyaWJ1dGUoYXR0ck9wdGlvbiksIFxuICAgICAgICAgICAgICAgIG51bGwgIT09IG9wdGlvbkRhdGEgJiYgKFwic3RyaW5nXCIgPT0gdHlwZW9mIG9wdGlvbkRhdGEgJiYgKDAgPT09IG9wdGlvbi5pbmRleE9mKFwib25cIikgPyBvcHRpb25EYXRhID0gX3dpbmRvdy5kZWZhdWx0W29wdGlvbkRhdGFdIDogXCJmYWxzZVwiID09PSBvcHRpb25EYXRhID8gb3B0aW9uRGF0YSA9ICExIDogXCJ0cnVlXCIgPT09IG9wdGlvbkRhdGEgJiYgKG9wdGlvbkRhdGEgPSAhMCkpLCBcbiAgICAgICAgICAgICAgICB1c2VyT3B0aW9uc1tvcHRpb25dID0gb3B0aW9uRGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoITAgPT09IG9wdHMuaW1wb3J0RGF0YUF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXR0ck9wdGlvbnMgPSBucHQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGUpLCBvcHRpb24sIGRhdGFvcHRpb25zLCBvcHRpb25EYXRhLCBwO1xuICAgICAgICAgICAgICAgIGlmIChhdHRyT3B0aW9ucyAmJiBcIlwiICE9PSBhdHRyT3B0aW9ucyAmJiAoYXR0ck9wdGlvbnMgPSBhdHRyT3B0aW9ucy5yZXBsYWNlKC8nL2csICdcIicpLCBcbiAgICAgICAgICAgICAgICBkYXRhb3B0aW9ucyA9IEpTT04ucGFyc2UoXCJ7XCIgKyBhdHRyT3B0aW9ucyArIFwifVwiKSksIGRhdGFvcHRpb25zKSBmb3IgKHAgaW4gb3B0aW9uRGF0YSA9IHZvaWQgMCwgXG4gICAgICAgICAgICAgICAgZGF0YW9wdGlvbnMpIGlmIChcImFsaWFzXCIgPT09IHAudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICBvcHRpb25EYXRhID0gZGF0YW9wdGlvbnNbcF07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKG9wdGlvbiBpbiBpbXBvcnRPcHRpb24oXCJhbGlhc1wiLCBvcHRpb25EYXRhKSwgdXNlck9wdGlvbnMuYWxpYXMgJiYgcmVzb2x2ZUFsaWFzKHVzZXJPcHRpb25zLmFsaWFzLCB1c2VyT3B0aW9ucywgb3B0cyksIFxuICAgICAgICAgICAgICAgIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFvcHRpb25zKSBmb3IgKHAgaW4gb3B0aW9uRGF0YSA9IHZvaWQgMCwgZGF0YW9wdGlvbnMpIGlmIChwLnRvTG93ZXJDYXNlKCkgPT09IG9wdGlvbi50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25EYXRhID0gZGF0YW9wdGlvbnNbcF07XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRPcHRpb24ob3B0aW9uLCBvcHRpb25EYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gX2lucHV0bWFzay5kZWZhdWx0LmV4dGVuZCghMCwgb3B0cywgdXNlck9wdGlvbnMpLCBcInJ0bFwiICE9PSBucHQuZGlyICYmICFvcHRzLnJpZ2h0QWxpZ24gfHwgKG5wdC5zdHlsZS50ZXh0QWxpZ24gPSBcInJpZ2h0XCIpLCBcbiAgICAgICAgICAgIFwicnRsXCIgIT09IG5wdC5kaXIgJiYgIW9wdHMubnVtZXJpY0lucHV0IHx8IChucHQuZGlyID0gXCJsdHJcIiwgbnB0LnJlbW92ZUF0dHJpYnV0ZShcImRpclwiKSwgXG4gICAgICAgICAgICBvcHRzLmlzUlRMID0gITApLCBPYmplY3Qua2V5cyh1c2VyT3B0aW9ucykubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIElucHV0bWFzay5wcm90b3R5cGUgPSB7XG4gICAgICAgICAgICBkYXRhQXR0cmlidXRlOiBcImRhdGEtaW5wdXRtYXNrXCIsXG4gICAgICAgICAgICBkZWZhdWx0czogX2RlZmF1bHRzLmRlZmF1bHQsXG4gICAgICAgICAgICBkZWZpbml0aW9uczogX2RlZmluaXRpb25zLmRlZmF1bHQsXG4gICAgICAgICAgICBhbGlhc2VzOiB7fSxcbiAgICAgICAgICAgIG1hc2tzQ2FjaGU6IHt9LFxuICAgICAgICAgICAgZ2V0IGlzUlRMKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wdHMuaXNSVEwgfHwgdGhpcy5vcHRzLm51bWVyaWNJbnB1dDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtYXNrOiBmdW5jdGlvbiBtYXNrKGVsZW1zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgIHJldHVybiBcInN0cmluZ1wiID09IHR5cGVvZiBlbGVtcyAmJiAoZWxlbXMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtcykgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChlbGVtcykpLCBcbiAgICAgICAgICAgICAgICBlbGVtcyA9IGVsZW1zLm5vZGVOYW1lID8gWyBlbGVtcyBdIDogZWxlbXMsIGVsZW1zLmZvckVhY2goZnVuY3Rpb24oZWwsIG5keCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2NvcGVkT3B0cyA9IF9pbnB1dG1hc2suZGVmYXVsdC5leHRlbmQoITAsIHt9LCB0aGF0Lm9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW1wb3J0QXR0cmlidXRlT3B0aW9ucyhlbCwgc2NvcGVkT3B0cywgX2lucHV0bWFzay5kZWZhdWx0LmV4dGVuZCghMCwge30sIHRoYXQudXNlck9wdGlvbnMpLCB0aGF0LmRhdGFBdHRyaWJ1dGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWFza3NldCA9ICgwLCBfbWFza0xleGVyLmdlbmVyYXRlTWFza1NldCkoc2NvcGVkT3B0cywgdGhhdC5ub01hc2tzQ2FjaGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCAwICE9PSBtYXNrc2V0ICYmICh2b2lkIDAgIT09IGVsLmlucHV0bWFzayAmJiAoZWwuaW5wdXRtYXNrLm9wdHMuYXV0b1VubWFzayA9ICEwLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5yZW1vdmUoKSksIGVsLmlucHV0bWFzayA9IG5ldyBJbnB1dG1hc2sodm9pZCAwLCB2b2lkIDAsICEwKSwgZWwuaW5wdXRtYXNrLm9wdHMgPSBzY29wZWRPcHRzLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5ub01hc2tzQ2FjaGUgPSB0aGF0Lm5vTWFza3NDYWNoZSwgZWwuaW5wdXRtYXNrLnVzZXJPcHRpb25zID0gX2lucHV0bWFzay5kZWZhdWx0LmV4dGVuZCghMCwge30sIHRoYXQudXNlck9wdGlvbnMpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5lbCA9IGVsLCBlbC5pbnB1dG1hc2suJGVsID0gKDAsIF9pbnB1dG1hc2suZGVmYXVsdCkoZWwpLCBlbC5pbnB1dG1hc2subWFza3NldCA9IG1hc2tzZXQsIFxuICAgICAgICAgICAgICAgICAgICAgICAgX2lucHV0bWFzay5kZWZhdWx0LmRhdGEoZWwsIGRhdGFLZXksIHRoYXQudXNlck9wdGlvbnMpLCBfbWFzay5tYXNrLmNhbGwoZWwuaW5wdXRtYXNrKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSwgZWxlbXMgJiYgZWxlbXNbMF0gJiYgZWxlbXNbMF0uaW5wdXRtYXNrIHx8IHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9uOiBmdW5jdGlvbiBvcHRpb24ob3B0aW9ucywgbm9yZW1hc2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJzdHJpbmdcIiA9PSB0eXBlb2Ygb3B0aW9ucyA/IHRoaXMub3B0c1tvcHRpb25zXSA6IFwib2JqZWN0XCIgPT09IF90eXBlb2Yob3B0aW9ucykgPyAoX2lucHV0bWFzay5kZWZhdWx0LmV4dGVuZCh0aGlzLnVzZXJPcHRpb25zLCBvcHRpb25zKSwgXG4gICAgICAgICAgICAgICAgdGhpcy5lbCAmJiAhMCAhPT0gbm9yZW1hc2sgJiYgdGhpcy5tYXNrKHRoaXMuZWwpLCB0aGlzKSA6IHZvaWQgMDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1bm1hc2tlZHZhbHVlOiBmdW5jdGlvbiB1bm1hc2tlZHZhbHVlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCAoMCwgX21hc2tMZXhlci5nZW5lcmF0ZU1hc2tTZXQpKHRoaXMub3B0cywgdGhpcy5ub01hc2tzQ2FjaGUpLCBcbiAgICAgICAgICAgICAgICB2b2lkIDAgPT09IHRoaXMuZWwgfHwgdm9pZCAwICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVCdWZmZXIgPSAoXCJmdW5jdGlvblwiID09IHR5cGVvZiB0aGlzLm9wdHMub25CZWZvcmVNYXNrICYmIHRoaXMub3B0cy5vbkJlZm9yZU1hc2suY2FsbCh0aGlzLCB2YWx1ZSwgdGhpcy5vcHRzKSB8fCB2YWx1ZSkuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIF9pbnB1dEhhbmRsaW5nLmNoZWNrVmFsLmNhbGwodGhpcywgdm9pZCAwLCAhMSwgITEsIHZhbHVlQnVmZmVyKSwgXCJmdW5jdGlvblwiID09IHR5cGVvZiB0aGlzLm9wdHMub25CZWZvcmVXcml0ZSAmJiB0aGlzLm9wdHMub25CZWZvcmVXcml0ZS5jYWxsKHRoaXMsIHZvaWQgMCwgX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKHRoaXMpLCAwLCB0aGlzLm9wdHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gX2lucHV0SGFuZGxpbmcudW5tYXNrZWR2YWx1ZS5jYWxsKHRoaXMsIHRoaXMuZWwpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlbW92ZTogZnVuY3Rpb24gcmVtb3ZlKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIF9pbnB1dG1hc2suZGVmYXVsdC5kYXRhKHRoaXMuZWwsIGRhdGFLZXksIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY3YgPSB0aGlzLm9wdHMuYXV0b1VubWFzayA/ICgwLCBfaW5wdXRIYW5kbGluZy51bm1hc2tlZHZhbHVlKSh0aGlzLmVsKSA6IHRoaXMuX3ZhbHVlR2V0KHRoaXMub3B0cy5hdXRvVW5tYXNrKSwgdmFsdWVQcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgY3YgIT09IF9wb3NpdGlvbmluZy5nZXRCdWZmZXJUZW1wbGF0ZS5jYWxsKHRoaXMpLmpvaW4oXCJcIikgPyB0aGlzLl92YWx1ZVNldChjdiwgdGhpcy5vcHRzLmF1dG9Vbm1hc2spIDogdGhpcy5fdmFsdWVTZXQoXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICBfZXZlbnRydWxlci5FdmVudFJ1bGVyLm9mZih0aGlzLmVsKSwgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvciAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YgPyAodmFsdWVQcm9wZXJ0eSA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMuZWwpLCBcInZhbHVlXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVQcm9wZXJ0eSAmJiB0aGlzLl9fdmFsdWVHZXQgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuZWwsIFwidmFsdWVcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0OiB0aGlzLl9fdmFsdWVHZXQsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXQ6IHRoaXMuX192YWx1ZVNldCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogITBcbiAgICAgICAgICAgICAgICAgICAgfSkpIDogZG9jdW1lbnQuX19sb29rdXBHZXR0ZXJfXyAmJiB0aGlzLmVsLl9fbG9va3VwR2V0dGVyX18oXCJ2YWx1ZVwiKSAmJiB0aGlzLl9fdmFsdWVHZXQgJiYgKHRoaXMuZWwuX19kZWZpbmVHZXR0ZXJfXyhcInZhbHVlXCIsIHRoaXMuX192YWx1ZUdldCksIFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVsLl9fZGVmaW5lU2V0dGVyX18oXCJ2YWx1ZVwiLCB0aGlzLl9fdmFsdWVTZXQpKSwgdGhpcy5lbC5pbnB1dG1hc2sgPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVsO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldGVtcHR5bWFzazogZnVuY3Rpb24gZ2V0ZW1wdHltYXNrKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1hc2tzZXQgPSB0aGlzLm1hc2tzZXQgfHwgKDAsIF9tYXNrTGV4ZXIuZ2VuZXJhdGVNYXNrU2V0KSh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKSwgXG4gICAgICAgICAgICAgICAgX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlclRlbXBsYXRlLmNhbGwodGhpcykuam9pbihcIlwiKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoYXNNYXNrZWRWYWx1ZTogZnVuY3Rpb24gaGFzTWFza2VkVmFsdWUoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLm9wdHMuYXV0b1VubWFzaztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiBmdW5jdGlvbiBpc0NvbXBsZXRlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1hc2tzZXQgPSB0aGlzLm1hc2tzZXQgfHwgKDAsIF9tYXNrTGV4ZXIuZ2VuZXJhdGVNYXNrU2V0KSh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKSwgXG4gICAgICAgICAgICAgICAgX3ZhbGlkYXRpb24uaXNDb21wbGV0ZS5jYWxsKHRoaXMsIF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbCh0aGlzKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0bWV0YWRhdGE6IGZ1bmN0aW9uIGdldG1ldGFkYXRhKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1hc2tzZXQgPSB0aGlzLm1hc2tzZXQgfHwgKDAsIF9tYXNrTGV4ZXIuZ2VuZXJhdGVNYXNrU2V0KSh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKSwgXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheSh0aGlzLm1hc2tzZXQubWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXNrVGFyZ2V0ID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRNYXNrVGVtcGxhdGUuY2FsbCh0aGlzLCAhMCwgMCwgITEpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1hc2tzZXQubWV0YWRhdGEuZm9yRWFjaChmdW5jdGlvbihtdGR0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbXRkdC5tYXNrICE9PSBtYXNrVGFyZ2V0IHx8IChtYXNrVGFyZ2V0ID0gbXRkdCwgITEpO1xuICAgICAgICAgICAgICAgICAgICB9KSwgbWFza1RhcmdldDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWFza3NldC5tZXRhZGF0YTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc1ZhbGlkOiBmdW5jdGlvbiBpc1ZhbGlkKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCAoMCwgX21hc2tMZXhlci5nZW5lcmF0ZU1hc2tTZXQpKHRoaXMub3B0cywgdGhpcy5ub01hc2tzQ2FjaGUpLCBcbiAgICAgICAgICAgICAgICB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVCdWZmZXIgPSAoXCJmdW5jdGlvblwiID09IHR5cGVvZiB0aGlzLm9wdHMub25CZWZvcmVNYXNrICYmIHRoaXMub3B0cy5vbkJlZm9yZU1hc2suY2FsbCh0aGlzLCB2YWx1ZSwgdGhpcy5vcHRzKSB8fCB2YWx1ZSkuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIF9pbnB1dEhhbmRsaW5nLmNoZWNrVmFsLmNhbGwodGhpcywgdm9pZCAwLCAhMCwgITEsIHZhbHVlQnVmZmVyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgdmFsdWUgPSB0aGlzLmlzUlRMID8gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKHRoaXMpLnNsaWNlKCkucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwodGhpcykuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBidWZmZXIgPSBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwodGhpcyksIHJsID0gX3Bvc2l0aW9uaW5nLmRldGVybWluZUxhc3RSZXF1aXJlZFBvc2l0aW9uLmNhbGwodGhpcyksIGxtaWIgPSBidWZmZXIubGVuZ3RoIC0gMTsgcmwgPCBsbWliICYmICFfcG9zaXRpb25pbmcuaXNNYXNrLmNhbGwodGhpcywgbG1pYik7IGxtaWItLSkgO1xuICAgICAgICAgICAgICAgIHJldHVybiBidWZmZXIuc3BsaWNlKHJsLCBsbWliICsgMSAtIHJsKSwgX3ZhbGlkYXRpb24uaXNDb21wbGV0ZS5jYWxsKHRoaXMsIGJ1ZmZlcikgJiYgdmFsdWUgPT09ICh0aGlzLmlzUlRMID8gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKHRoaXMpLnNsaWNlKCkucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwodGhpcykuam9pbihcIlwiKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9ybWF0OiBmdW5jdGlvbiBmb3JtYXQodmFsdWUsIG1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tYXNrc2V0ID0gdGhpcy5tYXNrc2V0IHx8ICgwLCBfbWFza0xleGVyLmdlbmVyYXRlTWFza1NldCkodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSk7XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlQnVmZmVyID0gKFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgdGhpcy5vcHRzLm9uQmVmb3JlTWFzayAmJiB0aGlzLm9wdHMub25CZWZvcmVNYXNrLmNhbGwodGhpcywgdmFsdWUsIHRoaXMub3B0cykgfHwgdmFsdWUpLnNwbGl0KFwiXCIpO1xuICAgICAgICAgICAgICAgIF9pbnB1dEhhbmRsaW5nLmNoZWNrVmFsLmNhbGwodGhpcywgdm9pZCAwLCAhMCwgITEsIHZhbHVlQnVmZmVyKTtcbiAgICAgICAgICAgICAgICB2YXIgZm9ybWF0dGVkVmFsdWUgPSB0aGlzLmlzUlRMID8gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKHRoaXMpLnNsaWNlKCkucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwodGhpcykuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWV0YWRhdGEgPyB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiBmb3JtYXR0ZWRWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IHRoaXMuZ2V0bWV0YWRhdGEoKVxuICAgICAgICAgICAgICAgIH0gOiBmb3JtYXR0ZWRWYWx1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXRWYWx1ZTogZnVuY3Rpb24gc2V0VmFsdWUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVsICYmICgwLCBfaW5wdXRtYXNrLmRlZmF1bHQpKHRoaXMuZWwpLnRyaWdnZXIoXCJzZXR2YWx1ZVwiLCBbIHZhbHVlIF0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGFuYWx5c2VNYXNrOiBfbWFza0xleGVyLmFuYWx5c2VNYXNrXG4gICAgICAgIH0sIElucHV0bWFzay5leHRlbmREZWZhdWx0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgICAgIF9pbnB1dG1hc2suZGVmYXVsdC5leHRlbmQoITAsIElucHV0bWFzay5wcm90b3R5cGUuZGVmYXVsdHMsIG9wdGlvbnMpO1xuICAgICAgICB9LCBJbnB1dG1hc2suZXh0ZW5kRGVmaW5pdGlvbnMgPSBmdW5jdGlvbihkZWZpbml0aW9uKSB7XG4gICAgICAgICAgICBfaW5wdXRtYXNrLmRlZmF1bHQuZXh0ZW5kKCEwLCBJbnB1dG1hc2sucHJvdG90eXBlLmRlZmluaXRpb25zLCBkZWZpbml0aW9uKTtcbiAgICAgICAgfSwgSW5wdXRtYXNrLmV4dGVuZEFsaWFzZXMgPSBmdW5jdGlvbihhbGlhcykge1xuICAgICAgICAgICAgX2lucHV0bWFzay5kZWZhdWx0LmV4dGVuZCghMCwgSW5wdXRtYXNrLnByb3RvdHlwZS5hbGlhc2VzLCBhbGlhcyk7XG4gICAgICAgIH0sIElucHV0bWFzay5mb3JtYXQgPSBmdW5jdGlvbih2YWx1ZSwgb3B0aW9ucywgbWV0YWRhdGEpIHtcbiAgICAgICAgICAgIHJldHVybiBJbnB1dG1hc2sob3B0aW9ucykuZm9ybWF0KHZhbHVlLCBtZXRhZGF0YSk7XG4gICAgICAgIH0sIElucHV0bWFzay51bm1hc2sgPSBmdW5jdGlvbih2YWx1ZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuIElucHV0bWFzayhvcHRpb25zKS51bm1hc2tlZHZhbHVlKHZhbHVlKTtcbiAgICAgICAgfSwgSW5wdXRtYXNrLmlzVmFsaWQgPSBmdW5jdGlvbih2YWx1ZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuIElucHV0bWFzayhvcHRpb25zKS5pc1ZhbGlkKHZhbHVlKTtcbiAgICAgICAgfSwgSW5wdXRtYXNrLnJlbW92ZSA9IGZ1bmN0aW9uKGVsZW1zKSB7XG4gICAgICAgICAgICBcInN0cmluZ1wiID09IHR5cGVvZiBlbGVtcyAmJiAoZWxlbXMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtcykgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChlbGVtcykpLCBcbiAgICAgICAgICAgIGVsZW1zID0gZWxlbXMubm9kZU5hbWUgPyBbIGVsZW1zIF0gOiBlbGVtcywgZWxlbXMuZm9yRWFjaChmdW5jdGlvbihlbCkge1xuICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzayAmJiBlbC5pbnB1dG1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgSW5wdXRtYXNrLnNldFZhbHVlID0gZnVuY3Rpb24oZWxlbXMsIHZhbHVlKSB7XG4gICAgICAgICAgICBcInN0cmluZ1wiID09IHR5cGVvZiBlbGVtcyAmJiAoZWxlbXMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtcykgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChlbGVtcykpLCBcbiAgICAgICAgICAgIGVsZW1zID0gZWxlbXMubm9kZU5hbWUgPyBbIGVsZW1zIF0gOiBlbGVtcywgZWxlbXMuZm9yRWFjaChmdW5jdGlvbihlbCkge1xuICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzayA/IGVsLmlucHV0bWFzay5zZXRWYWx1ZSh2YWx1ZSkgOiAoMCwgX2lucHV0bWFzay5kZWZhdWx0KShlbCkudHJpZ2dlcihcInNldHZhbHVlXCIsIFsgdmFsdWUgXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgSW5wdXRtYXNrLmRlcGVuZGVuY3lMaWIgPSBfaW5wdXRtYXNrLmRlZmF1bHQsIF93aW5kb3cuZGVmYXVsdC5JbnB1dG1hc2sgPSBJbnB1dG1hc2s7XG4gICAgICAgIHZhciBfZGVmYXVsdCA9IElucHV0bWFzaztcbiAgICAgICAgZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgICAgICAgICAgIHZhbHVlOiAhMFxuICAgICAgICB9KSwgZXhwb3J0cy5jYXJldCA9IGNhcmV0LCBleHBvcnRzLmRldGVybWluZUxhc3RSZXF1aXJlZFBvc2l0aW9uID0gZGV0ZXJtaW5lTGFzdFJlcXVpcmVkUG9zaXRpb24sIFxuICAgICAgICBleHBvcnRzLmRldGVybWluZU5ld0NhcmV0UG9zaXRpb24gPSBkZXRlcm1pbmVOZXdDYXJldFBvc2l0aW9uLCBleHBvcnRzLmdldEJ1ZmZlciA9IGdldEJ1ZmZlciwgXG4gICAgICAgIGV4cG9ydHMuZ2V0QnVmZmVyVGVtcGxhdGUgPSBnZXRCdWZmZXJUZW1wbGF0ZSwgZXhwb3J0cy5nZXRMYXN0VmFsaWRQb3NpdGlvbiA9IGdldExhc3RWYWxpZFBvc2l0aW9uLCBcbiAgICAgICAgZXhwb3J0cy5pc01hc2sgPSBpc01hc2ssIGV4cG9ydHMucmVzZXRNYXNrU2V0ID0gcmVzZXRNYXNrU2V0LCBleHBvcnRzLnNlZWtOZXh0ID0gc2Vla05leHQsIFxuICAgICAgICBleHBvcnRzLnNlZWtQcmV2aW91cyA9IHNlZWtQcmV2aW91cywgZXhwb3J0cy50cmFuc2xhdGVQb3NpdGlvbiA9IHRyYW5zbGF0ZVBvc2l0aW9uO1xuICAgICAgICB2YXIgX3ZhbGlkYXRpb25UZXN0cyA9IF9fd2VicGFja19yZXF1aXJlX18oMyksIF92YWxpZGF0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0KSwgX21hc2sgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDEwKTtcbiAgICAgICAgZnVuY3Rpb24gY2FyZXQoaW5wdXQsIGJlZ2luLCBlbmQsIG5vdHJhbnNsYXRlLCBpc0RlbGV0ZSkge1xuICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMsIG9wdHMgPSB0aGlzLm9wdHMsIHJhbmdlO1xuICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gYmVnaW4pIHJldHVybiBcInNlbGVjdGlvblN0YXJ0XCIgaW4gaW5wdXQgJiYgXCJzZWxlY3Rpb25FbmRcIiBpbiBpbnB1dCA/IChiZWdpbiA9IGlucHV0LnNlbGVjdGlvblN0YXJ0LCBcbiAgICAgICAgICAgIGVuZCA9IGlucHV0LnNlbGVjdGlvbkVuZCkgOiB3aW5kb3cuZ2V0U2VsZWN0aW9uID8gKHJhbmdlID0gd2luZG93LmdldFNlbGVjdGlvbigpLmdldFJhbmdlQXQoMCksIFxuICAgICAgICAgICAgcmFuZ2UuY29tbW9uQW5jZXN0b3JDb250YWluZXIucGFyZW50Tm9kZSAhPT0gaW5wdXQgJiYgcmFuZ2UuY29tbW9uQW5jZXN0b3JDb250YWluZXIgIT09IGlucHV0IHx8IChiZWdpbiA9IHJhbmdlLnN0YXJ0T2Zmc2V0LCBcbiAgICAgICAgICAgIGVuZCA9IHJhbmdlLmVuZE9mZnNldCkpIDogZG9jdW1lbnQuc2VsZWN0aW9uICYmIGRvY3VtZW50LnNlbGVjdGlvbi5jcmVhdGVSYW5nZSAmJiAocmFuZ2UgPSBkb2N1bWVudC5zZWxlY3Rpb24uY3JlYXRlUmFuZ2UoKSwgXG4gICAgICAgICAgICBiZWdpbiA9IDAgLSByYW5nZS5kdXBsaWNhdGUoKS5tb3ZlU3RhcnQoXCJjaGFyYWN0ZXJcIiwgLWlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKS5sZW5ndGgpLCBcbiAgICAgICAgICAgIGVuZCA9IGJlZ2luICsgcmFuZ2UudGV4dC5sZW5ndGgpLCB7XG4gICAgICAgICAgICAgICAgYmVnaW46IG5vdHJhbnNsYXRlID8gYmVnaW4gOiB0cmFuc2xhdGVQb3NpdGlvbi5jYWxsKHRoaXMsIGJlZ2luKSxcbiAgICAgICAgICAgICAgICBlbmQ6IG5vdHJhbnNsYXRlID8gZW5kIDogdHJhbnNsYXRlUG9zaXRpb24uY2FsbCh0aGlzLCBlbmQpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYmVnaW4pICYmIChlbmQgPSB0aGlzLmlzUlRMID8gYmVnaW5bMF0gOiBiZWdpblsxXSwgYmVnaW4gPSB0aGlzLmlzUlRMID8gYmVnaW5bMV0gOiBiZWdpblswXSksIFxuICAgICAgICAgICAgdm9pZCAwICE9PSBiZWdpbi5iZWdpbiAmJiAoZW5kID0gdGhpcy5pc1JUTCA/IGJlZ2luLmJlZ2luIDogYmVnaW4uZW5kLCBiZWdpbiA9IHRoaXMuaXNSVEwgPyBiZWdpbi5lbmQgOiBiZWdpbi5iZWdpbiksIFxuICAgICAgICAgICAgXCJudW1iZXJcIiA9PSB0eXBlb2YgYmVnaW4pIHtcbiAgICAgICAgICAgICAgICBiZWdpbiA9IG5vdHJhbnNsYXRlID8gYmVnaW4gOiB0cmFuc2xhdGVQb3NpdGlvbi5jYWxsKHRoaXMsIGJlZ2luKSwgZW5kID0gbm90cmFuc2xhdGUgPyBlbmQgOiB0cmFuc2xhdGVQb3NpdGlvbi5jYWxsKHRoaXMsIGVuZCksIFxuICAgICAgICAgICAgICAgIGVuZCA9IFwibnVtYmVyXCIgPT0gdHlwZW9mIGVuZCA/IGVuZCA6IGJlZ2luO1xuICAgICAgICAgICAgICAgIHZhciBzY3JvbGxDYWxjID0gcGFyc2VJbnQoKChpbnB1dC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3IHx8IHdpbmRvdykuZ2V0Q29tcHV0ZWRTdHlsZSA/IChpbnB1dC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3IHx8IHdpbmRvdykuZ2V0Q29tcHV0ZWRTdHlsZShpbnB1dCwgbnVsbCkgOiBpbnB1dC5jdXJyZW50U3R5bGUpLmZvbnRTaXplKSAqIGVuZDtcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQuc2Nyb2xsTGVmdCA9IHNjcm9sbENhbGMgPiBpbnB1dC5zY3JvbGxXaWR0aCA/IHNjcm9sbENhbGMgOiAwLCBpbnB1dC5pbnB1dG1hc2suY2FyZXRQb3MgPSB7XG4gICAgICAgICAgICAgICAgICAgIGJlZ2luOiBiZWdpbixcbiAgICAgICAgICAgICAgICAgICAgZW5kOiBlbmRcbiAgICAgICAgICAgICAgICB9LCBvcHRzLmluc2VydE1vZGVWaXN1YWwgJiYgITEgPT09IG9wdHMuaW5zZXJ0TW9kZSAmJiBiZWdpbiA9PT0gZW5kICYmIChpc0RlbGV0ZSB8fCBlbmQrKyksIFxuICAgICAgICAgICAgICAgIGlucHV0ID09PSAoaW5wdXQuaW5wdXRtYXNrLnNoYWRvd1Jvb3QgfHwgZG9jdW1lbnQpLmFjdGl2ZUVsZW1lbnQpIGlmIChcInNldFNlbGVjdGlvblJhbmdlXCIgaW4gaW5wdXQpIGlucHV0LnNldFNlbGVjdGlvblJhbmdlKGJlZ2luLCBlbmQpOyBlbHNlIGlmICh3aW5kb3cuZ2V0U2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyYW5nZSA9IGRvY3VtZW50LmNyZWF0ZVJhbmdlKCksIHZvaWQgMCA9PT0gaW5wdXQuZmlyc3RDaGlsZCB8fCBudWxsID09PSBpbnB1dC5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGV4dE5vZGUgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LmFwcGVuZENoaWxkKHRleHROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByYW5nZS5zZXRTdGFydChpbnB1dC5maXJzdENoaWxkLCBiZWdpbiA8IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKS5sZW5ndGggPyBiZWdpbiA6IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKS5sZW5ndGgpLCBcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2Uuc2V0RW5kKGlucHV0LmZpcnN0Q2hpbGQsIGVuZCA8IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKS5sZW5ndGggPyBlbmQgOiBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkubGVuZ3RoKSwgXG4gICAgICAgICAgICAgICAgICAgIHJhbmdlLmNvbGxhcHNlKCEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlbCA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpLCBzZWwuYWRkUmFuZ2UocmFuZ2UpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpbnB1dC5jcmVhdGVUZXh0UmFuZ2UgJiYgKHJhbmdlID0gaW5wdXQuY3JlYXRlVGV4dFJhbmdlKCksIHJhbmdlLmNvbGxhcHNlKCEwKSwgXG4gICAgICAgICAgICAgICAgcmFuZ2UubW92ZUVuZChcImNoYXJhY3RlclwiLCBlbmQpLCByYW5nZS5tb3ZlU3RhcnQoXCJjaGFyYWN0ZXJcIiwgYmVnaW4pLCByYW5nZS5zZWxlY3QoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZGV0ZXJtaW5lTGFzdFJlcXVpcmVkUG9zaXRpb24ocmV0dXJuRGVmaW5pdGlvbikge1xuICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMsIG1hc2tzZXQgPSB0aGlzLm1hc2tzZXQsICQgPSB0aGlzLmRlcGVuZGVuY3lMaWIsIGJ1ZmZlciA9IF92YWxpZGF0aW9uVGVzdHMuZ2V0TWFza1RlbXBsYXRlLmNhbGwodGhpcywgITAsIGdldExhc3RWYWxpZFBvc2l0aW9uLmNhbGwodGhpcyksICEwLCAhMCksIGJsID0gYnVmZmVyLmxlbmd0aCwgcG9zLCBsdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbi5jYWxsKHRoaXMpLCBwb3NpdGlvbnMgPSB7fSwgbHZUZXN0ID0gbWFza3NldC52YWxpZFBvc2l0aW9uc1tsdnBdLCBuZHhJbnRsenIgPSB2b2lkIDAgIT09IGx2VGVzdCA/IGx2VGVzdC5sb2NhdG9yLnNsaWNlKCkgOiB2b2lkIDAsIHRlc3RQb3M7XG4gICAgICAgICAgICBmb3IgKHBvcyA9IGx2cCArIDE7IHBvcyA8IGJ1ZmZlci5sZW5ndGg7IHBvcysrKSB0ZXN0UG9zID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0VGVtcGxhdGUuY2FsbCh0aGlzLCBwb3MsIG5keEludGx6ciwgcG9zIC0gMSksIFxuICAgICAgICAgICAgbmR4SW50bHpyID0gdGVzdFBvcy5sb2NhdG9yLnNsaWNlKCksIHBvc2l0aW9uc1twb3NdID0gJC5leHRlbmQoITAsIHt9LCB0ZXN0UG9zKTtcbiAgICAgICAgICAgIHZhciBsdlRlc3RBbHQgPSBsdlRlc3QgJiYgdm9pZCAwICE9PSBsdlRlc3QuYWx0ZXJuYXRpb24gPyBsdlRlc3QubG9jYXRvcltsdlRlc3QuYWx0ZXJuYXRpb25dIDogdm9pZCAwO1xuICAgICAgICAgICAgZm9yIChwb3MgPSBibCAtIDE7IGx2cCA8IHBvcyAmJiAodGVzdFBvcyA9IHBvc2l0aW9uc1twb3NdLCAodGVzdFBvcy5tYXRjaC5vcHRpb25hbGl0eSB8fCB0ZXN0UG9zLm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciAmJiB0ZXN0UG9zLm1hdGNoLm5ld0Jsb2NrTWFya2VyIHx8IGx2VGVzdEFsdCAmJiAobHZUZXN0QWx0ICE9PSBwb3NpdGlvbnNbcG9zXS5sb2NhdG9yW2x2VGVzdC5hbHRlcm5hdGlvbl0gJiYgMSAhPSB0ZXN0UG9zLm1hdGNoLnN0YXRpYyB8fCAhMCA9PT0gdGVzdFBvcy5tYXRjaC5zdGF0aWMgJiYgdGVzdFBvcy5sb2NhdG9yW2x2VGVzdC5hbHRlcm5hdGlvbl0gJiYgX3ZhbGlkYXRpb24uY2hlY2tBbHRlcm5hdGlvbk1hdGNoLmNhbGwodGhpcywgdGVzdFBvcy5sb2NhdG9yW2x2VGVzdC5hbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5zcGxpdChcIixcIiksIGx2VGVzdEFsdC50b1N0cmluZygpLnNwbGl0KFwiLFwiKSkgJiYgXCJcIiAhPT0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0cy5jYWxsKHRoaXMsIHBvcylbMF0uZGVmKSkgJiYgYnVmZmVyW3Bvc10gPT09IF92YWxpZGF0aW9uVGVzdHMuZ2V0UGxhY2Vob2xkZXIuY2FsbCh0aGlzLCBwb3MsIHRlc3RQb3MubWF0Y2gpKTsgcG9zLS0pIGJsLS07XG4gICAgICAgICAgICByZXR1cm4gcmV0dXJuRGVmaW5pdGlvbiA/IHtcbiAgICAgICAgICAgICAgICBsOiBibCxcbiAgICAgICAgICAgICAgICBkZWY6IHBvc2l0aW9uc1tibF0gPyBwb3NpdGlvbnNbYmxdLm1hdGNoIDogdm9pZCAwXG4gICAgICAgICAgICB9IDogYmw7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZGV0ZXJtaW5lTmV3Q2FyZXRQb3NpdGlvbihzZWxlY3RlZENhcmV0LCB0YWJiZWQpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCBtYXNrc2V0ID0gdGhpcy5tYXNrc2V0LCBvcHRzID0gdGhpcy5vcHRzO1xuICAgICAgICAgICAgZnVuY3Rpb24gZG9SYWRpeEZvY3VzKGNsaWNrUG9zKSB7XG4gICAgICAgICAgICAgICAgaWYgKFwiXCIgIT09IG9wdHMucmFkaXhQb2ludCAmJiAwICE9PSBvcHRzLmRpZ2l0cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdnBzID0gbWFza3NldC52YWxpZFBvc2l0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gdnBzW2NsaWNrUG9zXSB8fCB2cHNbY2xpY2tQb3NdLmlucHV0ID09PSBfdmFsaWRhdGlvblRlc3RzLmdldFBsYWNlaG9sZGVyLmNhbGwoaW5wdXRtYXNrLCBjbGlja1BvcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjbGlja1BvcyA8IHNlZWtOZXh0LmNhbGwoaW5wdXRtYXNrLCAtMSkpIHJldHVybiAhMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvcyA9IGdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykuaW5kZXhPZihvcHRzLnJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKC0xICE9PSByYWRpeFBvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHZwIGluIHZwcykgaWYgKHZwc1t2cF0gJiYgcmFkaXhQb3MgPCB2cCAmJiB2cHNbdnBdLmlucHV0ICE9PSBfdmFsaWRhdGlvblRlc3RzLmdldFBsYWNlaG9sZGVyLmNhbGwoaW5wdXRtYXNrLCB2cCkpIHJldHVybiAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuICExO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRhYmJlZCAmJiAoaW5wdXRtYXNrLmlzUlRMID8gc2VsZWN0ZWRDYXJldC5lbmQgPSBzZWxlY3RlZENhcmV0LmJlZ2luIDogc2VsZWN0ZWRDYXJldC5iZWdpbiA9IHNlbGVjdGVkQ2FyZXQuZW5kKSwgXG4gICAgICAgICAgICBzZWxlY3RlZENhcmV0LmJlZ2luID09PSBzZWxlY3RlZENhcmV0LmVuZCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAob3B0cy5wb3NpdGlvbkNhcmV0T25DbGljaykge1xuICAgICAgICAgICAgICAgICAgY2FzZSBcIm5vbmVcIjpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJzZWxlY3RcIjpcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRDYXJldCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBnZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLmxlbmd0aFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcImlnbm9yZVwiOlxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZENhcmV0LmVuZCA9IHNlbGVjdGVkQ2FyZXQuYmVnaW4gPSBzZWVrTmV4dC5jYWxsKGlucHV0bWFzaywgZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbChpbnB1dG1hc2spKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJyYWRpeEZvY3VzXCI6XG4gICAgICAgICAgICAgICAgICAgIGlmIChkb1JhZGl4Rm9jdXMoc2VsZWN0ZWRDYXJldC5iZWdpbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvcyA9IGdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykuam9pbihcIlwiKS5pbmRleE9mKG9wdHMucmFkaXhQb2ludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZENhcmV0LmVuZCA9IHNlbGVjdGVkQ2FyZXQuYmVnaW4gPSBvcHRzLm51bWVyaWNJbnB1dCA/IHNlZWtOZXh0LmNhbGwoaW5wdXRtYXNrLCByYWRpeFBvcykgOiByYWRpeFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHZhciBjbGlja1Bvc2l0aW9uID0gc2VsZWN0ZWRDYXJldC5iZWdpbiwgbHZjbGlja1Bvc2l0aW9uID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbChpbnB1dG1hc2ssIGNsaWNrUG9zaXRpb24sICEwKSwgbGFzdFBvc2l0aW9uID0gc2Vla05leHQuY2FsbChpbnB1dG1hc2ssIC0xICE9PSBsdmNsaWNrUG9zaXRpb24gfHwgaXNNYXNrLmNhbGwoaW5wdXRtYXNrLCAwKSA/IGx2Y2xpY2tQb3NpdGlvbiA6IC0xKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNsaWNrUG9zaXRpb24gPD0gbGFzdFBvc2l0aW9uKSBzZWxlY3RlZENhcmV0LmVuZCA9IHNlbGVjdGVkQ2FyZXQuYmVnaW4gPSBpc01hc2suY2FsbChpbnB1dG1hc2ssIGNsaWNrUG9zaXRpb24sICExLCAhMCkgPyBjbGlja1Bvc2l0aW9uIDogc2Vla05leHQuY2FsbChpbnB1dG1hc2ssIGNsaWNrUG9zaXRpb24pOyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsdnAgPSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW2x2Y2xpY2tQb3NpdGlvbl0sIHR0ID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0VGVtcGxhdGUuY2FsbChpbnB1dG1hc2ssIGxhc3RQb3NpdGlvbiwgbHZwID8gbHZwLm1hdGNoLmxvY2F0b3IgOiB2b2lkIDAsIGx2cCksIHBsYWNlaG9sZGVyID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRQbGFjZWhvbGRlci5jYWxsKGlucHV0bWFzaywgbGFzdFBvc2l0aW9uLCB0dC5tYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJcIiAhPT0gcGxhY2Vob2xkZXIgJiYgZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKVtsYXN0UG9zaXRpb25dICE9PSBwbGFjZWhvbGRlciAmJiAhMCAhPT0gdHQubWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyICYmICEwICE9PSB0dC5tYXRjaC5uZXdCbG9ja01hcmtlciB8fCAhaXNNYXNrLmNhbGwoaW5wdXRtYXNrLCBsYXN0UG9zaXRpb24sIG9wdHMua2VlcFN0YXRpYywgITApICYmIHR0Lm1hdGNoLmRlZiA9PT0gcGxhY2Vob2xkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3UG9zID0gc2Vla05leHQuY2FsbChpbnB1dG1hc2ssIGxhc3RQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5ld1BvcyA8PSBjbGlja1Bvc2l0aW9uIHx8IGNsaWNrUG9zaXRpb24gPT09IGxhc3RQb3NpdGlvbikgJiYgKGxhc3RQb3NpdGlvbiA9IG5ld1Bvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZENhcmV0LmVuZCA9IHNlbGVjdGVkQ2FyZXQuYmVnaW4gPSBsYXN0UG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGVjdGVkQ2FyZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2V0QnVmZmVyKG5vQ2FjaGUpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCBtYXNrc2V0ID0gdGhpcy5tYXNrc2V0O1xuICAgICAgICAgICAgcmV0dXJuIHZvaWQgMCAhPT0gbWFza3NldC5idWZmZXIgJiYgITAgIT09IG5vQ2FjaGUgfHwgKG1hc2tzZXQuYnVmZmVyID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRNYXNrVGVtcGxhdGUuY2FsbCh0aGlzLCAhMCwgZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbCh0aGlzKSwgITApLCBcbiAgICAgICAgICAgIHZvaWQgMCA9PT0gbWFza3NldC5fYnVmZmVyICYmIChtYXNrc2V0Ll9idWZmZXIgPSBtYXNrc2V0LmJ1ZmZlci5zbGljZSgpKSksIG1hc2tzZXQuYnVmZmVyO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdldEJ1ZmZlclRlbXBsYXRlKCkge1xuICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMsIG1hc2tzZXQgPSB0aGlzLm1hc2tzZXQ7XG4gICAgICAgICAgICByZXR1cm4gdm9pZCAwID09PSBtYXNrc2V0Ll9idWZmZXIgJiYgKG1hc2tzZXQuX2J1ZmZlciA9IF92YWxpZGF0aW9uVGVzdHMuZ2V0TWFza1RlbXBsYXRlLmNhbGwodGhpcywgITEsIDEpLCBcbiAgICAgICAgICAgIHZvaWQgMCA9PT0gbWFza3NldC5idWZmZXIgJiYgKG1hc2tzZXQuYnVmZmVyID0gbWFza3NldC5fYnVmZmVyLnNsaWNlKCkpKSwgbWFza3NldC5fYnVmZmVyO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdldExhc3RWYWxpZFBvc2l0aW9uKGNsb3Nlc3RUbywgc3RyaWN0LCB2YWxpZFBvc2l0aW9ucykge1xuICAgICAgICAgICAgdmFyIG1hc2tzZXQgPSB0aGlzLm1hc2tzZXQsIGJlZm9yZSA9IC0xLCBhZnRlciA9IC0xLCB2YWxpZHMgPSB2YWxpZFBvc2l0aW9ucyB8fCBtYXNrc2V0LnZhbGlkUG9zaXRpb25zO1xuICAgICAgICAgICAgZm9yICh2YXIgcG9zTmR4IGluIHZvaWQgMCA9PT0gY2xvc2VzdFRvICYmIChjbG9zZXN0VG8gPSAtMSksIHZhbGlkcykge1xuICAgICAgICAgICAgICAgIHZhciBwc05keCA9IHBhcnNlSW50KHBvc05keCk7XG4gICAgICAgICAgICAgICAgdmFsaWRzW3BzTmR4XSAmJiAoc3RyaWN0IHx8ICEwICE9PSB2YWxpZHNbcHNOZHhdLmdlbmVyYXRlZElucHV0KSAmJiAocHNOZHggPD0gY2xvc2VzdFRvICYmIChiZWZvcmUgPSBwc05keCksIFxuICAgICAgICAgICAgICAgIGNsb3Nlc3RUbyA8PSBwc05keCAmJiAoYWZ0ZXIgPSBwc05keCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIC0xID09PSBiZWZvcmUgfHwgYmVmb3JlID09IGNsb3Nlc3RUbyA/IGFmdGVyIDogLTEgPT0gYWZ0ZXIgPyBiZWZvcmUgOiBjbG9zZXN0VG8gLSBiZWZvcmUgPCBhZnRlciAtIGNsb3Nlc3RUbyA/IGJlZm9yZSA6IGFmdGVyO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGlzTWFzayhwb3MsIHN0cmljdCwgZnV6enkpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCBtYXNrc2V0ID0gdGhpcy5tYXNrc2V0LCB0ZXN0ID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0VGVtcGxhdGUuY2FsbCh0aGlzLCBwb3MpLm1hdGNoO1xuICAgICAgICAgICAgaWYgKFwiXCIgPT09IHRlc3QuZGVmICYmICh0ZXN0ID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0LmNhbGwodGhpcywgcG9zKS5tYXRjaCksIFxuICAgICAgICAgICAgITAgIT09IHRlc3Quc3RhdGljKSByZXR1cm4gdGVzdC5mbjtcbiAgICAgICAgICAgIGlmICghMCA9PT0gZnV6enkgJiYgdm9pZCAwICE9PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10gJiYgITAgIT09IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXS5nZW5lcmF0ZWRJbnB1dCkgcmV0dXJuICEwO1xuICAgICAgICAgICAgaWYgKCEwICE9PSBzdHJpY3QgJiYgLTEgPCBwb3MpIHtcbiAgICAgICAgICAgICAgICBpZiAoZnV6enkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRlc3RzID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0cy5jYWxsKHRoaXMsIHBvcyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0ZXN0cy5sZW5ndGggPiAxICsgKFwiXCIgPT09IHRlc3RzW3Rlc3RzLmxlbmd0aCAtIDFdLm1hdGNoLmRlZiA/IDEgOiAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHRlc3RUZW1wbGF0ZSA9IF92YWxpZGF0aW9uVGVzdHMuZGV0ZXJtaW5lVGVzdFRlbXBsYXRlLmNhbGwodGhpcywgcG9zLCBfdmFsaWRhdGlvblRlc3RzLmdldFRlc3RzLmNhbGwodGhpcywgcG9zKSksIHRlc3RQbGFjZUhvbGRlciA9IF92YWxpZGF0aW9uVGVzdHMuZ2V0UGxhY2Vob2xkZXIuY2FsbCh0aGlzLCBwb3MsIHRlc3RUZW1wbGF0ZS5tYXRjaCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRlc3RUZW1wbGF0ZS5tYXRjaC5kZWYgIT09IHRlc3RQbGFjZUhvbGRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAhMTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiByZXNldE1hc2tTZXQoc29mdCkge1xuICAgICAgICAgICAgdmFyIG1hc2tzZXQgPSB0aGlzLm1hc2tzZXQ7XG4gICAgICAgICAgICBtYXNrc2V0LmJ1ZmZlciA9IHZvaWQgMCwgITAgIT09IHNvZnQgJiYgKG1hc2tzZXQudmFsaWRQb3NpdGlvbnMgPSB7fSwgbWFza3NldC5wID0gMCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gc2Vla05leHQocG9zLCBuZXdCbG9jaywgZnV6enkpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzO1xuICAgICAgICAgICAgdm9pZCAwID09PSBmdXp6eSAmJiAoZnV6enkgPSAhMCk7XG4gICAgICAgICAgICBmb3IgKHZhciBwb3NpdGlvbiA9IHBvcyArIDE7IFwiXCIgIT09IF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdC5jYWxsKHRoaXMsIHBvc2l0aW9uKS5tYXRjaC5kZWYgJiYgKCEwID09PSBuZXdCbG9jayAmJiAoITAgIT09IF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdC5jYWxsKHRoaXMsIHBvc2l0aW9uKS5tYXRjaC5uZXdCbG9ja01hcmtlciB8fCAhaXNNYXNrLmNhbGwodGhpcywgcG9zaXRpb24sIHZvaWQgMCwgITApKSB8fCAhMCAhPT0gbmV3QmxvY2sgJiYgIWlzTWFzay5jYWxsKHRoaXMsIHBvc2l0aW9uLCB2b2lkIDAsIGZ1enp5KSk7ICkgcG9zaXRpb24rKztcbiAgICAgICAgICAgIHJldHVybiBwb3NpdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBzZWVrUHJldmlvdXMocG9zLCBuZXdCbG9jaykge1xuICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMsIHBvc2l0aW9uID0gcG9zIC0gMTtcbiAgICAgICAgICAgIGlmIChwb3MgPD0gMCkgcmV0dXJuIDA7XG4gICAgICAgICAgICBmb3IgKDswIDwgcG9zaXRpb24gJiYgKCEwID09PSBuZXdCbG9jayAmJiAoITAgIT09IF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdC5jYWxsKHRoaXMsIHBvc2l0aW9uKS5tYXRjaC5uZXdCbG9ja01hcmtlciB8fCAhaXNNYXNrLmNhbGwodGhpcywgcG9zaXRpb24sIHZvaWQgMCwgITApKSB8fCAhMCAhPT0gbmV3QmxvY2sgJiYgIWlzTWFzay5jYWxsKHRoaXMsIHBvc2l0aW9uLCB2b2lkIDAsICEwKSk7ICkgcG9zaXRpb24tLTtcbiAgICAgICAgICAgIHJldHVybiBwb3NpdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiB0cmFuc2xhdGVQb3NpdGlvbihwb3MpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCBvcHRzID0gdGhpcy5vcHRzLCBlbCA9IHRoaXMuZWw7XG4gICAgICAgICAgICByZXR1cm4gIXRoaXMuaXNSVEwgfHwgXCJudW1iZXJcIiAhPSB0eXBlb2YgcG9zIHx8IG9wdHMuZ3JlZWR5ICYmIFwiXCIgPT09IG9wdHMucGxhY2Vob2xkZXIgfHwgIWVsIHx8IChwb3MgPSB0aGlzLl92YWx1ZUdldCgpLmxlbmd0aCAtIHBvcyksIFxuICAgICAgICAgICAgcG9zO1xuICAgICAgICB9XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBmdW5jdGlvbiBnZXRMb2NhdG9yKHRzdCwgYWxpZ24pIHtcbiAgICAgICAgICAgIHZhciBsb2NhdG9yID0gKG51bGwgIT0gdHN0LmFsdGVybmF0aW9uID8gdHN0Lm1sb2NbZ2V0RGVjaXNpb25UYWtlcih0c3QpXSA6IHRzdC5sb2NhdG9yKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgaWYgKFwiXCIgIT09IGxvY2F0b3IpIGZvciAoO2xvY2F0b3IubGVuZ3RoIDwgYWxpZ247ICkgbG9jYXRvciArPSBcIjBcIjtcbiAgICAgICAgICAgIHJldHVybiBsb2NhdG9yO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdldERlY2lzaW9uVGFrZXIodHN0KSB7XG4gICAgICAgICAgICB2YXIgZGVjaXNpb25UYWtlciA9IHRzdC5sb2NhdG9yW3RzdC5hbHRlcm5hdGlvbl07XG4gICAgICAgICAgICByZXR1cm4gXCJzdHJpbmdcIiA9PSB0eXBlb2YgZGVjaXNpb25UYWtlciAmJiAwIDwgZGVjaXNpb25UYWtlci5sZW5ndGggJiYgKGRlY2lzaW9uVGFrZXIgPSBkZWNpc2lvblRha2VyLnNwbGl0KFwiLFwiKVswXSksIFxuICAgICAgICAgICAgdm9pZCAwICE9PSBkZWNpc2lvblRha2VyID8gZGVjaXNpb25UYWtlci50b1N0cmluZygpIDogXCJcIjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBnZXRQbGFjZWhvbGRlcihwb3MsIHRlc3QsIHJldHVyblBMKSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcywgb3B0cyA9IHRoaXMub3B0cywgbWFza3NldCA9IHRoaXMubWFza3NldDtcbiAgICAgICAgICAgIGlmICh0ZXN0ID0gdGVzdCB8fCBnZXRUZXN0LmNhbGwodGhpcywgcG9zKS5tYXRjaCwgdm9pZCAwICE9PSB0ZXN0LnBsYWNlaG9sZGVyIHx8ICEwID09PSByZXR1cm5QTCkgcmV0dXJuIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgdGVzdC5wbGFjZWhvbGRlciA/IHRlc3QucGxhY2Vob2xkZXIob3B0cykgOiB0ZXN0LnBsYWNlaG9sZGVyO1xuICAgICAgICAgICAgaWYgKCEwICE9PSB0ZXN0LnN0YXRpYykgcmV0dXJuIG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KHBvcyAlIG9wdHMucGxhY2Vob2xkZXIubGVuZ3RoKTtcbiAgICAgICAgICAgIGlmICgtMSA8IHBvcyAmJiB2b2lkIDAgPT09IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXSkge1xuICAgICAgICAgICAgICAgIHZhciB0ZXN0cyA9IGdldFRlc3RzLmNhbGwodGhpcywgcG9zKSwgc3RhdGljQWx0ZXJuYXRpb25zID0gW10sIHByZXZUZXN0O1xuICAgICAgICAgICAgICAgIGlmICh0ZXN0cy5sZW5ndGggPiAxICsgKFwiXCIgPT09IHRlc3RzW3Rlc3RzLmxlbmd0aCAtIDFdLm1hdGNoLmRlZiA/IDEgOiAwKSkgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXN0cy5sZW5ndGg7IGkrKykgaWYgKFwiXCIgIT09IHRlc3RzW2ldLm1hdGNoLmRlZiAmJiAhMCAhPT0gdGVzdHNbaV0ubWF0Y2gub3B0aW9uYWxpdHkgJiYgITAgIT09IHRlc3RzW2ldLm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciAmJiAoITAgPT09IHRlc3RzW2ldLm1hdGNoLnN0YXRpYyB8fCB2b2lkIDAgPT09IHByZXZUZXN0IHx8ICExICE9PSB0ZXN0c1tpXS5tYXRjaC5mbi50ZXN0KHByZXZUZXN0Lm1hdGNoLmRlZiwgbWFza3NldCwgcG9zLCAhMCwgb3B0cykpICYmIChzdGF0aWNBbHRlcm5hdGlvbnMucHVzaCh0ZXN0c1tpXSksIFxuICAgICAgICAgICAgICAgICEwID09PSB0ZXN0c1tpXS5tYXRjaC5zdGF0aWMgJiYgKHByZXZUZXN0ID0gdGVzdHNbaV0pLCAxIDwgc3RhdGljQWx0ZXJuYXRpb25zLmxlbmd0aCAmJiAvWzAtOWEtYkEtWl0vLnRlc3Qoc3RhdGljQWx0ZXJuYXRpb25zWzBdLm1hdGNoLmRlZikpKSByZXR1cm4gb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQocG9zICUgb3B0cy5wbGFjZWhvbGRlci5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRlc3QuZGVmO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdldE1hc2tUZW1wbGF0ZShiYXNlT25JbnB1dCwgbWluaW1hbFBvcywgaW5jbHVkZU1vZGUsIG5vSml0LCBjbGVhck9wdGlvbmFsVGFpbCkge1xuICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMsIG9wdHMgPSB0aGlzLm9wdHMsIG1hc2tzZXQgPSB0aGlzLm1hc2tzZXQsIGdyZWVkeSA9IG9wdHMuZ3JlZWR5O1xuICAgICAgICAgICAgY2xlYXJPcHRpb25hbFRhaWwgJiYgKG9wdHMuZ3JlZWR5ID0gITEpLCBtaW5pbWFsUG9zID0gbWluaW1hbFBvcyB8fCAwO1xuICAgICAgICAgICAgdmFyIG1hc2tUZW1wbGF0ZSA9IFtdLCBuZHhJbnRsenIsIHBvcyA9IDAsIHRlc3QsIHRlc3RQb3MsIGppdFJlbmRlclN0YXRpYztcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICBpZiAoITAgPT09IGJhc2VPbklucHV0ICYmIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXSkgdGVzdFBvcyA9IGNsZWFyT3B0aW9uYWxUYWlsICYmICEwID09PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10ubWF0Y2gub3B0aW9uYWxpdHkgJiYgdm9pZCAwID09PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3BvcyArIDFdICYmICghMCA9PT0gbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdLmdlbmVyYXRlZElucHV0IHx8IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXS5pbnB1dCA9PSBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIgJiYgMCA8IHBvcykgPyBkZXRlcm1pbmVUZXN0VGVtcGxhdGUuY2FsbCh0aGlzLCBwb3MsIGdldFRlc3RzLmNhbGwodGhpcywgcG9zLCBuZHhJbnRsenIsIHBvcyAtIDEpKSA6IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXSwgXG4gICAgICAgICAgICAgICAgdGVzdCA9IHRlc3RQb3MubWF0Y2gsIG5keEludGx6ciA9IHRlc3RQb3MubG9jYXRvci5zbGljZSgpLCBtYXNrVGVtcGxhdGUucHVzaCghMCA9PT0gaW5jbHVkZU1vZGUgPyB0ZXN0UG9zLmlucHV0IDogITEgPT09IGluY2x1ZGVNb2RlID8gdGVzdC5uYXRpdmVEZWYgOiBnZXRQbGFjZWhvbGRlci5jYWxsKHRoaXMsIHBvcywgdGVzdCkpOyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IGdldFRlc3RUZW1wbGF0ZS5jYWxsKHRoaXMsIHBvcywgbmR4SW50bHpyLCBwb3MgLSAxKSwgdGVzdCA9IHRlc3RQb3MubWF0Y2gsIFxuICAgICAgICAgICAgICAgICAgICBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGppdE1hc2tpbmcgPSAhMCAhPT0gbm9KaXQgJiYgKCExICE9PSBvcHRzLmppdE1hc2tpbmcgPyBvcHRzLmppdE1hc2tpbmcgOiB0ZXN0LmppdCk7XG4gICAgICAgICAgICAgICAgICAgIGppdFJlbmRlclN0YXRpYyA9IGppdFJlbmRlclN0YXRpYyAmJiB0ZXN0LnN0YXRpYyAmJiB0ZXN0LmRlZiAhPT0gb3B0cy5ncm91cFNlcGFyYXRvciAmJiBudWxsID09PSB0ZXN0LmZuIHx8IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zIC0gMV0gJiYgdGVzdC5zdGF0aWMgJiYgdGVzdC5kZWYgIT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IgJiYgbnVsbCA9PT0gdGVzdC5mbiwgXG4gICAgICAgICAgICAgICAgICAgIGppdFJlbmRlclN0YXRpYyB8fCAhMSA9PT0gaml0TWFza2luZyB8fCB2b2lkIDAgPT09IGppdE1hc2tpbmcgfHwgXCJudW1iZXJcIiA9PSB0eXBlb2Ygaml0TWFza2luZyAmJiBpc0Zpbml0ZShqaXRNYXNraW5nKSAmJiBwb3MgPCBqaXRNYXNraW5nID8gbWFza1RlbXBsYXRlLnB1c2goITEgPT09IGluY2x1ZGVNb2RlID8gdGVzdC5uYXRpdmVEZWYgOiBnZXRQbGFjZWhvbGRlci5jYWxsKHRoaXMsIHBvcywgdGVzdCkpIDogaml0UmVuZGVyU3RhdGljID0gITE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBvcysrO1xuICAgICAgICAgICAgfSB3aGlsZSAoKHZvaWQgMCA9PT0gdGhpcy5tYXhMZW5ndGggfHwgcG9zIDwgdGhpcy5tYXhMZW5ndGgpICYmICghMCAhPT0gdGVzdC5zdGF0aWMgfHwgXCJcIiAhPT0gdGVzdC5kZWYpIHx8IHBvcyA8IG1pbmltYWxQb3MpO1xuICAgICAgICAgICAgcmV0dXJuIFwiXCIgPT09IG1hc2tUZW1wbGF0ZVttYXNrVGVtcGxhdGUubGVuZ3RoIC0gMV0gJiYgbWFza1RlbXBsYXRlLnBvcCgpLCAhMSA9PT0gaW5jbHVkZU1vZGUgJiYgdm9pZCAwICE9PSBtYXNrc2V0Lm1hc2tMZW5ndGggfHwgKG1hc2tzZXQubWFza0xlbmd0aCA9IHBvcyAtIDEpLCBcbiAgICAgICAgICAgIG9wdHMuZ3JlZWR5ID0gZ3JlZWR5LCBtYXNrVGVtcGxhdGU7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2V0VGVzdFRlbXBsYXRlKHBvcywgbmR4SW50bHpyLCB0c3RQcykge1xuICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMsIG1hc2tzZXQgPSB0aGlzLm1hc2tzZXQ7XG4gICAgICAgICAgICByZXR1cm4gbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdIHx8IGRldGVybWluZVRlc3RUZW1wbGF0ZS5jYWxsKHRoaXMsIHBvcywgZ2V0VGVzdHMuY2FsbCh0aGlzLCBwb3MsIG5keEludGx6ciA/IG5keEludGx6ci5zbGljZSgpIDogbmR4SW50bHpyLCB0c3RQcykpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGRldGVybWluZVRlc3RUZW1wbGF0ZShwb3MsIHRlc3RzKSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcywgb3B0cyA9IHRoaXMub3B0cztcbiAgICAgICAgICAgIHBvcyA9IDAgPCBwb3MgPyBwb3MgLSAxIDogMDtcbiAgICAgICAgICAgIGZvciAodmFyIGFsdFRlc3QgPSBnZXRUZXN0LmNhbGwodGhpcywgcG9zKSwgdGFyZ2V0TG9jYXRvciA9IGdldExvY2F0b3IoYWx0VGVzdCksIHRzdExvY2F0b3IsIGNsb3Nlc3QsIGJlc3RNYXRjaCwgbmR4ID0gMDsgbmR4IDwgdGVzdHMubGVuZ3RoOyBuZHgrKykge1xuICAgICAgICAgICAgICAgIHZhciB0c3QgPSB0ZXN0c1tuZHhdO1xuICAgICAgICAgICAgICAgIHRzdExvY2F0b3IgPSBnZXRMb2NhdG9yKHRzdCwgdGFyZ2V0TG9jYXRvci5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIHZhciBkaXN0YW5jZSA9IE1hdGguYWJzKHRzdExvY2F0b3IgLSB0YXJnZXRMb2NhdG9yKTtcbiAgICAgICAgICAgICAgICAodm9pZCAwID09PSBjbG9zZXN0IHx8IFwiXCIgIT09IHRzdExvY2F0b3IgJiYgZGlzdGFuY2UgPCBjbG9zZXN0IHx8IGJlc3RNYXRjaCAmJiAhb3B0cy5ncmVlZHkgJiYgYmVzdE1hdGNoLm1hdGNoLm9wdGlvbmFsaXR5ICYmIFwibWFzdGVyXCIgPT09IGJlc3RNYXRjaC5tYXRjaC5uZXdCbG9ja01hcmtlciAmJiAoIXRzdC5tYXRjaC5vcHRpb25hbGl0eSB8fCAhdHN0Lm1hdGNoLm5ld0Jsb2NrTWFya2VyKSB8fCBiZXN0TWF0Y2ggJiYgYmVzdE1hdGNoLm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciAmJiAhdHN0Lm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllcikgJiYgKGNsb3Nlc3QgPSBkaXN0YW5jZSwgXG4gICAgICAgICAgICAgICAgYmVzdE1hdGNoID0gdHN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiZXN0TWF0Y2g7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2V0VGVzdChwb3MsIHRlc3RzKSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcywgbWFza3NldCA9IHRoaXMubWFza3NldDtcbiAgICAgICAgICAgIHJldHVybiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10gPyBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10gOiAodGVzdHMgfHwgZ2V0VGVzdHMuY2FsbCh0aGlzLCBwb3MpKVswXTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBnZXRUZXN0cyhwb3MsIG5keEludGx6ciwgdHN0UHMpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCAkID0gdGhpcy5kZXBlbmRlbmN5TGliLCBtYXNrc2V0ID0gdGhpcy5tYXNrc2V0LCBvcHRzID0gdGhpcy5vcHRzLCBlbCA9IHRoaXMuZWwsIG1hc2tUb2tlbnMgPSBtYXNrc2V0Lm1hc2tUb2tlbiwgdGVzdFBvcyA9IG5keEludGx6ciA/IHRzdFBzIDogMCwgbmR4SW5pdGlhbGl6ZXIgPSBuZHhJbnRsenIgPyBuZHhJbnRsenIuc2xpY2UoKSA6IFsgMCBdLCBtYXRjaGVzID0gW10sIGluc2VydFN0b3AgPSAhMSwgbGF0ZXN0TWF0Y2gsIGNhY2hlRGVwZW5kZW5jeSA9IG5keEludGx6ciA/IG5keEludGx6ci5qb2luKFwiXCIpIDogXCJcIjtcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlc29sdmVUZXN0RnJvbVRva2VuKG1hc2tUb2tlbiwgbmR4SW5pdGlhbGl6ZXIsIGxvb3BOZHgsIHF1YW50aWZpZXJSZWN1cnNlKSB7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlTWF0Y2gobWF0Y2gsIGxvb3BOZHgsIHF1YW50aWZpZXJSZWN1cnNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzRmlyc3RNYXRjaChsYXRlc3RNYXRjaCwgdG9rZW5Hcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZpcnN0TWF0Y2ggPSAwID09PSB0b2tlbkdyb3VwLm1hdGNoZXMuaW5kZXhPZihsYXRlc3RNYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmlyc3RNYXRjaCB8fCB0b2tlbkdyb3VwLm1hdGNoZXMuZXZlcnkoZnVuY3Rpb24obWF0Y2gsIG5keCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhMCA9PT0gbWF0Y2guaXNRdWFudGlmaWVyID8gZmlyc3RNYXRjaCA9IGlzRmlyc3RNYXRjaChsYXRlc3RNYXRjaCwgdG9rZW5Hcm91cC5tYXRjaGVzW25keCAtIDFdKSA6IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtYXRjaCwgXCJtYXRjaGVzXCIpICYmIChmaXJzdE1hdGNoID0gaXNGaXJzdE1hdGNoKGxhdGVzdE1hdGNoLCBtYXRjaCkpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAhZmlyc3RNYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLCBmaXJzdE1hdGNoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJlc29sdmVOZHhJbml0aWFsaXplcihwb3MsIGFsdGVybmF0ZU5keCwgdGFyZ2V0QWx0ZXJuYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBiZXN0TWF0Y2gsIGluZGV4UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChtYXNrc2V0LnRlc3RzW3Bvc10gfHwgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdKSAmJiAobWFza3NldC50ZXN0c1twb3NdIHx8IFsgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdIF0pLmV2ZXJ5KGZ1bmN0aW9uKGxtbnQsIG5keCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsbW50Lm1sb2NbYWx0ZXJuYXRlTmR4XSkgcmV0dXJuIGJlc3RNYXRjaCA9IGxtbnQsICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRlcm5hdGlvbiA9IHZvaWQgMCAhPT0gdGFyZ2V0QWx0ZXJuYXRpb24gPyB0YXJnZXRBbHRlcm5hdGlvbiA6IGxtbnQuYWx0ZXJuYXRpb24sIG5keFBvcyA9IHZvaWQgMCAhPT0gbG1udC5sb2NhdG9yW2FsdGVybmF0aW9uXSA/IGxtbnQubG9jYXRvclthbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5pbmRleE9mKGFsdGVybmF0ZU5keCkgOiAtMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKHZvaWQgMCA9PT0gaW5kZXhQb3MgfHwgbmR4UG9zIDwgaW5kZXhQb3MpICYmIC0xICE9PSBuZHhQb3MgJiYgKGJlc3RNYXRjaCA9IGxtbnQsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4UG9zID0gbmR4UG9zKSwgITA7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSwgYmVzdE1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJlc3RNYXRjaEFsdEluZGV4ID0gYmVzdE1hdGNoLmxvY2F0b3JbYmVzdE1hdGNoLmFsdGVybmF0aW9uXSwgbG9jYXRvciA9IGJlc3RNYXRjaC5tbG9jW2FsdGVybmF0ZU5keF0gfHwgYmVzdE1hdGNoLm1sb2NbYmVzdE1hdGNoQWx0SW5kZXhdIHx8IGJlc3RNYXRjaC5sb2NhdG9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBsb2NhdG9yLnNsaWNlKCh2b2lkIDAgIT09IHRhcmdldEFsdGVybmF0aW9uID8gdGFyZ2V0QWx0ZXJuYXRpb24gOiBiZXN0TWF0Y2guYWx0ZXJuYXRpb24pICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm9pZCAwICE9PSB0YXJnZXRBbHRlcm5hdGlvbiA/IHJlc29sdmVOZHhJbml0aWFsaXplcihwb3MsIGFsdGVybmF0ZU5keCkgOiB2b2lkIDA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNTdWJzZXRPZihzb3VyY2UsIHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gZXhwYW5kKHBhdHRlcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBleHBhbmRlZCA9IFtdLCBzdGFydCA9IC0xLCBlbmQsIGkgPSAwLCBsID0gcGF0dGVybi5sZW5ndGg7IGkgPCBsOyBpKyspIGlmIChcIi1cIiA9PT0gcGF0dGVybi5jaGFyQXQoaSkpIGZvciAoZW5kID0gcGF0dGVybi5jaGFyQ29kZUF0KGkgKyAxKTsgKytzdGFydCA8IGVuZDsgKSBleHBhbmRlZC5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoc3RhcnQpKTsgZWxzZSBzdGFydCA9IHBhdHRlcm4uY2hhckNvZGVBdChpKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWQucHVzaChwYXR0ZXJuLmNoYXJBdChpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGFuZGVkLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc291cmNlLm1hdGNoLmRlZiA9PT0gdGFyZ2V0Lm1hdGNoLm5hdGl2ZURlZiB8fCAhKCEob3B0cy5yZWdleCB8fCBzb3VyY2UubWF0Y2guZm4gaW5zdGFuY2VvZiBSZWdFeHAgJiYgdGFyZ2V0Lm1hdGNoLmZuIGluc3RhbmNlb2YgUmVnRXhwKSB8fCAhMCA9PT0gc291cmNlLm1hdGNoLnN0YXRpYyB8fCAhMCA9PT0gdGFyZ2V0Lm1hdGNoLnN0YXRpYykgJiYgLTEgIT09IGV4cGFuZCh0YXJnZXQubWF0Y2guZm4udG9TdHJpbmcoKS5yZXBsYWNlKC9bW1xcXS9dL2csIFwiXCIpKS5pbmRleE9mKGV4cGFuZChzb3VyY2UubWF0Y2guZm4udG9TdHJpbmcoKS5yZXBsYWNlKC9bW1xcXS9dL2csIFwiXCIpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gc3RhdGljQ2FuTWF0Y2hEZWZpbml0aW9uKHNvdXJjZSwgdGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gITAgPT09IHNvdXJjZS5tYXRjaC5zdGF0aWMgJiYgITAgIT09IHRhcmdldC5tYXRjaC5zdGF0aWMgJiYgdGFyZ2V0Lm1hdGNoLmZuLnRlc3Qoc291cmNlLm1hdGNoLmRlZiwgbWFza3NldCwgcG9zLCAhMSwgb3B0cywgITEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHNldE1lcmdlTG9jYXRvcnModGFyZ2V0TWF0Y2gsIGFsdE1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWx0ZXJuYXRpb25OZHggPSB0YXJnZXRNYXRjaC5hbHRlcm5hdGlvbiwgc2hvdWxkTWVyZ2UgPSB2b2lkIDAgPT09IGFsdE1hdGNoIHx8IGFsdGVybmF0aW9uTmR4ID09PSBhbHRNYXRjaC5hbHRlcm5hdGlvbiAmJiAtMSA9PT0gdGFyZ2V0TWF0Y2gubG9jYXRvclthbHRlcm5hdGlvbk5keF0udG9TdHJpbmcoKS5pbmRleE9mKGFsdE1hdGNoLmxvY2F0b3JbYWx0ZXJuYXRpb25OZHhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2hvdWxkTWVyZ2UgJiYgYWx0ZXJuYXRpb25OZHggPiBhbHRNYXRjaC5hbHRlcm5hdGlvbikgZm9yICh2YXIgaSA9IGFsdE1hdGNoLmFsdGVybmF0aW9uOyBpIDwgYWx0ZXJuYXRpb25OZHg7IGkrKykgaWYgKHRhcmdldE1hdGNoLmxvY2F0b3JbaV0gIT09IGFsdE1hdGNoLmxvY2F0b3JbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdGlvbk5keCA9IGksIHNob3VsZE1lcmdlID0gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkTWVyZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRNYXRjaC5tbG9jID0gdGFyZ2V0TWF0Y2gubWxvYyB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbG9jTmR4ID0gdGFyZ2V0TWF0Y2gubG9jYXRvclthbHRlcm5hdGlvbk5keF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZvaWQgMCAhPT0gbG9jTmR4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcInN0cmluZ1wiID09IHR5cGVvZiBsb2NOZHggJiYgKGxvY05keCA9IGxvY05keC5zcGxpdChcIixcIilbMF0pLCB2b2lkIDAgPT09IHRhcmdldE1hdGNoLm1sb2NbbG9jTmR4XSAmJiAodGFyZ2V0TWF0Y2gubWxvY1tsb2NOZHhdID0gdGFyZ2V0TWF0Y2gubG9jYXRvci5zbGljZSgpKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZvaWQgMCAhPT0gYWx0TWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG5keCBpbiBhbHRNYXRjaC5tbG9jKSBcInN0cmluZ1wiID09IHR5cGVvZiBuZHggJiYgKG5keCA9IG5keC5zcGxpdChcIixcIilbMF0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZvaWQgMCA9PT0gdGFyZ2V0TWF0Y2gubWxvY1tuZHhdICYmICh0YXJnZXRNYXRjaC5tbG9jW25keF0gPSBhbHRNYXRjaC5tbG9jW25keF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TWF0Y2gubG9jYXRvclthbHRlcm5hdGlvbk5keF0gPSBPYmplY3Qua2V5cyh0YXJnZXRNYXRjaC5tbG9jKS5qb2luKFwiLFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldE1hdGNoLmFsdGVybmF0aW9uID0gdm9pZCAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICExO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzU2FtZUxldmVsKHRhcmdldE1hdGNoLCBhbHRNYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRhcmdldE1hdGNoLmxvY2F0b3IubGVuZ3RoICE9PSBhbHRNYXRjaC5sb2NhdG9yLmxlbmd0aCkgcmV0dXJuICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbG9jTmR4ID0gdGFyZ2V0TWF0Y2guYWx0ZXJuYXRpb24gKyAxOyBsb2NOZHggPCB0YXJnZXRNYXRjaC5sb2NhdG9yLmxlbmd0aDsgbG9jTmR4KyspIGlmICh0YXJnZXRNYXRjaC5sb2NhdG9yW2xvY05keF0gIT09IGFsdE1hdGNoLmxvY2F0b3JbbG9jTmR4XSkgcmV0dXJuICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0UG9zID4gcG9zICsgb3B0cy5fbWF4VGVzdFBvcykgdGhyb3cgXCJJbnB1dG1hc2s6IFRoZXJlIGlzIHByb2JhYmx5IGFuIGVycm9yIGluIHlvdXIgbWFzayBkZWZpbml0aW9uIG9yIGluIHRoZSBjb2RlLiBDcmVhdGUgYW4gaXNzdWUgb24gZ2l0aHViIHdpdGggYW4gZXhhbXBsZSBvZiB0aGUgbWFzayB5b3UgYXJlIHVzaW5nLiBcIiArIG1hc2tzZXQubWFzaztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RQb3MgPT09IHBvcyAmJiB2b2lkIDAgPT09IG1hdGNoLm1hdGNoZXMpIHJldHVybiBtYXRjaGVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2g6IG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbG9jYXRvcjogbG9vcE5keC5yZXZlcnNlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBjZDogY2FjaGVEZXBlbmRlbmN5LFxuICAgICAgICAgICAgICAgICAgICAgICAgbWxvYzoge31cbiAgICAgICAgICAgICAgICAgICAgfSksICEwO1xuICAgICAgICAgICAgICAgICAgICBpZiAodm9pZCAwICE9PSBtYXRjaC5tYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2guaXNHcm91cCAmJiBxdWFudGlmaWVyUmVjdXJzZSAhPT0gbWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2ggPSBoYW5kbGVNYXRjaChtYXNrVG9rZW4ubWF0Y2hlc1ttYXNrVG9rZW4ubWF0Y2hlcy5pbmRleE9mKG1hdGNoKSArIDFdLCBsb29wTmR4LCBxdWFudGlmaWVyUmVjdXJzZSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoKSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoLmlzT3B0aW9uYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3B0aW9uYWxUb2tlbiA9IG1hdGNoLCBtdGNoc05keCA9IG1hdGNoZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCA9IHJlc29sdmVUZXN0RnJvbVRva2VuKG1hdGNoLCBuZHhJbml0aWFsaXplciwgbG9vcE5keCwgcXVhbnRpZmllclJlY3Vyc2UpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hlcy5mb3JFYWNoKGZ1bmN0aW9uKG10Y2gsIG5keCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXRjaHNOZHggPD0gbmR4ICYmIChtdGNoLm1hdGNoLm9wdGlvbmFsaXR5ID0gITApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgbGF0ZXN0TWF0Y2ggPSBtYXRjaGVzW21hdGNoZXMubGVuZ3RoIC0gMV0ubWF0Y2gsIHZvaWQgMCAhPT0gcXVhbnRpZmllclJlY3Vyc2UgfHwgIWlzRmlyc3RNYXRjaChsYXRlc3RNYXRjaCwgb3B0aW9uYWxUb2tlbikpIHJldHVybiAhMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0U3RvcCA9ICEwLCB0ZXN0UG9zID0gcG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2guaXNBbHRlcm5hdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdGVybmF0ZVRva2VuID0gbWF0Y2gsIG1hbHRlcm5hdGVNYXRjaGVzID0gW10sIG1hbHRNYXRjaGVzLCBjdXJyZW50TWF0Y2hlcyA9IG1hdGNoZXMuc2xpY2UoKSwgbG9vcE5keENudCA9IGxvb3BOZHgubGVuZ3RoLCBhbHRJbmRleCA9IDAgPCBuZHhJbml0aWFsaXplci5sZW5ndGggPyBuZHhJbml0aWFsaXplci5zaGlmdCgpIDogLTE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKC0xID09PSBhbHRJbmRleCB8fCBcInN0cmluZ1wiID09IHR5cGVvZiBhbHRJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY3VycmVudFBvcyA9IHRlc3RQb3MsIG5keEluaXRpYWxpemVyQ2xvbmUgPSBuZHhJbml0aWFsaXplci5zbGljZSgpLCBhbHRJbmRleEFyciA9IFtdLCBhbW5keDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwic3RyaW5nXCIgPT0gdHlwZW9mIGFsdEluZGV4KSBhbHRJbmRleEFyciA9IGFsdEluZGV4LnNwbGl0KFwiLFwiKTsgZWxzZSBmb3IgKGFtbmR4ID0gMDsgYW1uZHggPCBhbHRlcm5hdGVUb2tlbi5tYXRjaGVzLmxlbmd0aDsgYW1uZHgrKykgYWx0SW5kZXhBcnIucHVzaChhbW5keC50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZvaWQgMCAhPT0gbWFza3NldC5leGNsdWRlc1twb3NdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhbHRJbmRleEFyckNsb25lID0gYWx0SW5kZXhBcnIuc2xpY2UoKSwgaSA9IDAsIGV4bCA9IG1hc2tzZXQuZXhjbHVkZXNbcG9zXS5sZW5ndGg7IGkgPCBleGw7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBleGNsdWRlU2V0ID0gbWFza3NldC5leGNsdWRlc1twb3NdW2ldLnRvU3RyaW5nKCkuc3BsaXQoXCI6XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvb3BOZHgubGVuZ3RoID09IGV4Y2x1ZGVTZXRbMV0gJiYgYWx0SW5kZXhBcnIuc3BsaWNlKGFsdEluZGV4QXJyLmluZGV4T2YoZXhjbHVkZVNldFswXSksIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMCA9PT0gYWx0SW5kZXhBcnIubGVuZ3RoICYmIChkZWxldGUgbWFza3NldC5leGNsdWRlc1twb3NdLCBhbHRJbmRleEFyciA9IGFsdEluZGV4QXJyQ2xvbmUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICghMCA9PT0gb3B0cy5rZWVwU3RhdGljIHx8IGlzRmluaXRlKHBhcnNlSW50KG9wdHMua2VlcFN0YXRpYykpICYmIGN1cnJlbnRQb3MgPj0gb3B0cy5rZWVwU3RhdGljKSAmJiAoYWx0SW5kZXhBcnIgPSBhbHRJbmRleEFyci5zbGljZSgwLCAxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHVuTWF0Y2hlZEFsdGVybmF0aW9uID0gITEsIG5keCA9IDA7IG5keCA8IGFsdEluZGV4QXJyLmxlbmd0aDsgbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFtbmR4ID0gcGFyc2VJbnQoYWx0SW5kZXhBcnJbbmR4XSksIG1hdGNoZXMgPSBbXSwgbmR4SW5pdGlhbGl6ZXIgPSBcInN0cmluZ1wiID09IHR5cGVvZiBhbHRJbmRleCAmJiByZXNvbHZlTmR4SW5pdGlhbGl6ZXIodGVzdFBvcywgYW1uZHgsIGxvb3BOZHhDbnQpIHx8IG5keEluaXRpYWxpemVyQ2xvbmUuc2xpY2UoKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdGVUb2tlbi5tYXRjaGVzW2FtbmR4XSAmJiBoYW5kbGVNYXRjaChhbHRlcm5hdGVUb2tlbi5tYXRjaGVzW2FtbmR4XSwgWyBhbW5keCBdLmNvbmNhdChsb29wTmR4KSwgcXVhbnRpZmllclJlY3Vyc2UpID8gbWF0Y2ggPSAhMCA6IDAgPT09IG5keCAmJiAodW5NYXRjaGVkQWx0ZXJuYXRpb24gPSAhMCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsdE1hdGNoZXMgPSBtYXRjaGVzLnNsaWNlKCksIHRlc3RQb3MgPSBjdXJyZW50UG9zLCBtYXRjaGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBuZHgxID0gMDsgbmR4MSA8IG1hbHRNYXRjaGVzLmxlbmd0aDsgbmR4MSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdE1hdGNoID0gbWFsdE1hdGNoZXNbbmR4MV0sIGRyb3BNYXRjaCA9ICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdE1hdGNoLm1hdGNoLmppdCA9IGFsdE1hdGNoLm1hdGNoLmppdCB8fCB1bk1hdGNoZWRBbHRlcm5hdGlvbiwgYWx0TWF0Y2guYWx0ZXJuYXRpb24gPSBhbHRNYXRjaC5hbHRlcm5hdGlvbiB8fCBsb29wTmR4Q250LCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRNZXJnZUxvY2F0b3JzKGFsdE1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBuZHgyID0gMDsgbmR4MiA8IG1hbHRlcm5hdGVNYXRjaGVzLmxlbmd0aDsgbmR4MisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRNYXRjaDIgPSBtYWx0ZXJuYXRlTWF0Y2hlc1tuZHgyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwic3RyaW5nXCIgIT0gdHlwZW9mIGFsdEluZGV4IHx8IHZvaWQgMCAhPT0gYWx0TWF0Y2guYWx0ZXJuYXRpb24gJiYgYWx0SW5kZXhBcnIuaW5jbHVkZXMoYWx0TWF0Y2gubG9jYXRvclthbHRNYXRjaC5hbHRlcm5hdGlvbl0udG9TdHJpbmcoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHRNYXRjaC5tYXRjaC5uYXRpdmVEZWYgPT09IGFsdE1hdGNoMi5tYXRjaC5uYXRpdmVEZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wTWF0Y2ggPSAhMCwgc2V0TWVyZ2VMb2NhdG9ycyhhbHRNYXRjaDIsIGFsdE1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1N1YnNldE9mKGFsdE1hdGNoLCBhbHRNYXRjaDIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0TWVyZ2VMb2NhdG9ycyhhbHRNYXRjaCwgYWx0TWF0Y2gyKSAmJiAoZHJvcE1hdGNoID0gITAsIG1hbHRlcm5hdGVNYXRjaGVzLnNwbGljZShtYWx0ZXJuYXRlTWF0Y2hlcy5pbmRleE9mKGFsdE1hdGNoMiksIDAsIGFsdE1hdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNTdWJzZXRPZihhbHRNYXRjaDIsIGFsdE1hdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldE1lcmdlTG9jYXRvcnMoYWx0TWF0Y2gyLCBhbHRNYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdGljQ2FuTWF0Y2hEZWZpbml0aW9uKGFsdE1hdGNoLCBhbHRNYXRjaDIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNTYW1lTGV2ZWwoYWx0TWF0Y2gsIGFsdE1hdGNoMikgfHwgdm9pZCAwICE9PSBlbC5pbnB1dG1hc2sudXNlck9wdGlvbnMua2VlcFN0YXRpYyA/IHNldE1lcmdlTG9jYXRvcnMoYWx0TWF0Y2gsIGFsdE1hdGNoMikgJiYgKGRyb3BNYXRjaCA9ICEwLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWx0ZXJuYXRlTWF0Y2hlcy5zcGxpY2UobWFsdGVybmF0ZU1hdGNoZXMuaW5kZXhPZihhbHRNYXRjaDIpLCAwLCBhbHRNYXRjaCkpIDogb3B0cy5rZWVwU3RhdGljID0gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJvcE1hdGNoIHx8IG1hbHRlcm5hdGVNYXRjaGVzLnB1c2goYWx0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMgPSBjdXJyZW50TWF0Y2hlcy5jb25jYXQobWFsdGVybmF0ZU1hdGNoZXMpLCB0ZXN0UG9zID0gcG9zLCBpbnNlcnRTdG9wID0gMCA8IG1hdGNoZXMubGVuZ3RoLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSAwIDwgbWFsdGVybmF0ZU1hdGNoZXMubGVuZ3RoLCBuZHhJbml0aWFsaXplciA9IG5keEluaXRpYWxpemVyQ2xvbmUuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgbWF0Y2ggPSBoYW5kbGVNYXRjaChhbHRlcm5hdGVUb2tlbi5tYXRjaGVzW2FsdEluZGV4XSB8fCBtYXNrVG9rZW4ubWF0Y2hlc1thbHRJbmRleF0sIFsgYWx0SW5kZXggXS5jb25jYXQobG9vcE5keCksIHF1YW50aWZpZXJSZWN1cnNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHJldHVybiAhMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2guaXNRdWFudGlmaWVyICYmIHF1YW50aWZpZXJSZWN1cnNlICE9PSBtYXNrVG9rZW4ubWF0Y2hlc1ttYXNrVG9rZW4ubWF0Y2hlcy5pbmRleE9mKG1hdGNoKSAtIDFdKSBmb3IgKHZhciBxdCA9IG1hdGNoLCBxbmR4ID0gMCA8IG5keEluaXRpYWxpemVyLmxlbmd0aCA/IG5keEluaXRpYWxpemVyLnNoaWZ0KCkgOiAwOyBxbmR4IDwgKGlzTmFOKHF0LnF1YW50aWZpZXIubWF4KSA/IHFuZHggKyAxIDogcXQucXVhbnRpZmllci5tYXgpICYmIHRlc3RQb3MgPD0gcG9zOyBxbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG9rZW5Hcm91cCA9IG1hc2tUb2tlbi5tYXRjaGVzW21hc2tUb2tlbi5tYXRjaGVzLmluZGV4T2YocXQpIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoID0gaGFuZGxlTWF0Y2godG9rZW5Hcm91cCwgWyBxbmR4IF0uY29uY2F0KGxvb3BOZHgpLCB0b2tlbkdyb3VwKSwgbWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhdGVzdE1hdGNoID0gbWF0Y2hlc1ttYXRjaGVzLmxlbmd0aCAtIDFdLm1hdGNoLCBsYXRlc3RNYXRjaC5vcHRpb25hbFF1YW50aWZpZXIgPSBxbmR4ID49IHF0LnF1YW50aWZpZXIubWluLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0ZXN0TWF0Y2guaml0ID0gKHFuZHggfHwgMSkgKiB0b2tlbkdyb3VwLm1hdGNoZXMuaW5kZXhPZihsYXRlc3RNYXRjaCkgPj0gcXQucXVhbnRpZmllci5qaXQsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRlc3RNYXRjaC5vcHRpb25hbFF1YW50aWZpZXIgJiYgaXNGaXJzdE1hdGNoKGxhdGVzdE1hdGNoLCB0b2tlbkdyb3VwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0U3RvcCA9ICEwLCB0ZXN0UG9zID0gcG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxhdGVzdE1hdGNoLmppdCAmJiAobWFza3NldC5qaXRPZmZzZXRbcG9zXSA9IHRva2VuR3JvdXAubWF0Y2hlcy5sZW5ndGggLSB0b2tlbkdyb3VwLm1hdGNoZXMuaW5kZXhPZihsYXRlc3RNYXRjaCkpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaCA9IHJlc29sdmVUZXN0RnJvbVRva2VuKG1hdGNoLCBuZHhJbml0aWFsaXplciwgbG9vcE5keCwgcXVhbnRpZmllclJlY3Vyc2UpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoKSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB0ZXN0UG9zKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAodmFyIHRuZHggPSAwIDwgbmR4SW5pdGlhbGl6ZXIubGVuZ3RoID8gbmR4SW5pdGlhbGl6ZXIuc2hpZnQoKSA6IDA7IHRuZHggPCBtYXNrVG9rZW4ubWF0Y2hlcy5sZW5ndGg7IHRuZHgrKykgaWYgKCEwICE9PSBtYXNrVG9rZW4ubWF0Y2hlc1t0bmR4XS5pc1F1YW50aWZpZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gaGFuZGxlTWF0Y2gobWFza1Rva2VuLm1hdGNoZXNbdG5keF0sIFsgdG5keCBdLmNvbmNhdChsb29wTmR4KSwgcXVhbnRpZmllclJlY3Vyc2UpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2ggJiYgdGVzdFBvcyA9PT0gcG9zKSByZXR1cm4gbWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwb3MgPCB0ZXN0UG9zKSBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBtZXJnZUxvY2F0b3JzKHBvcywgdGVzdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbG9jYXRvciA9IFtdLCBhbHRlcm5hdGlvbjtcbiAgICAgICAgICAgICAgICByZXR1cm4gQXJyYXkuaXNBcnJheSh0ZXN0cykgfHwgKHRlc3RzID0gWyB0ZXN0cyBdKSwgMCA8IHRlc3RzLmxlbmd0aCAmJiAodm9pZCAwID09PSB0ZXN0c1swXS5hbHRlcm5hdGlvbiB8fCAhMCA9PT0gb3B0cy5rZWVwU3RhdGljID8gKGxvY2F0b3IgPSBkZXRlcm1pbmVUZXN0VGVtcGxhdGUuY2FsbChpbnB1dG1hc2ssIHBvcywgdGVzdHMuc2xpY2UoKSkubG9jYXRvci5zbGljZSgpLCBcbiAgICAgICAgICAgICAgICAwID09PSBsb2NhdG9yLmxlbmd0aCAmJiAobG9jYXRvciA9IHRlc3RzWzBdLmxvY2F0b3Iuc2xpY2UoKSkpIDogdGVzdHMuZm9yRWFjaChmdW5jdGlvbih0c3QpIHtcbiAgICAgICAgICAgICAgICAgICAgXCJcIiAhPT0gdHN0LmRlZiAmJiAoMCA9PT0gbG9jYXRvci5sZW5ndGggPyAoYWx0ZXJuYXRpb24gPSB0c3QuYWx0ZXJuYXRpb24sIGxvY2F0b3IgPSB0c3QubG9jYXRvci5zbGljZSgpKSA6IHRzdC5sb2NhdG9yW2FsdGVybmF0aW9uXSAmJiAtMSA9PT0gbG9jYXRvclthbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5pbmRleE9mKHRzdC5sb2NhdG9yW2FsdGVybmF0aW9uXSkgJiYgKGxvY2F0b3JbYWx0ZXJuYXRpb25dICs9IFwiLFwiICsgdHN0LmxvY2F0b3JbYWx0ZXJuYXRpb25dKSk7XG4gICAgICAgICAgICAgICAgfSkpLCBsb2NhdG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKC0xIDwgcG9zICYmICh2b2lkIDAgPT09IGlucHV0bWFzay5tYXhMZW5ndGggfHwgcG9zIDwgaW5wdXRtYXNrLm1heExlbmd0aCkpIHtcbiAgICAgICAgICAgICAgICBpZiAodm9pZCAwID09PSBuZHhJbnRsenIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJldmlvdXNQb3MgPSBwb3MgLSAxLCB0ZXN0OyB2b2lkIDAgPT09ICh0ZXN0ID0gbWFza3NldC52YWxpZFBvc2l0aW9uc1twcmV2aW91c1Bvc10gfHwgbWFza3NldC50ZXN0c1twcmV2aW91c1Bvc10pICYmIC0xIDwgcHJldmlvdXNQb3M7ICkgcHJldmlvdXNQb3MtLTtcbiAgICAgICAgICAgICAgICAgICAgdm9pZCAwICE9PSB0ZXN0ICYmIC0xIDwgcHJldmlvdXNQb3MgJiYgKG5keEluaXRpYWxpemVyID0gbWVyZ2VMb2NhdG9ycyhwcmV2aW91c1BvcywgdGVzdCksIFxuICAgICAgICAgICAgICAgICAgICBjYWNoZURlcGVuZGVuY3kgPSBuZHhJbml0aWFsaXplci5qb2luKFwiXCIpLCB0ZXN0UG9zID0gcHJldmlvdXNQb3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWFza3NldC50ZXN0c1twb3NdICYmIG1hc2tzZXQudGVzdHNbcG9zXVswXS5jZCA9PT0gY2FjaGVEZXBlbmRlbmN5KSByZXR1cm4gbWFza3NldC50ZXN0c1twb3NdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIG10bmR4ID0gbmR4SW5pdGlhbGl6ZXIuc2hpZnQoKTsgbXRuZHggPCBtYXNrVG9rZW5zLmxlbmd0aDsgbXRuZHgrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2ggPSByZXNvbHZlVGVzdEZyb21Ub2tlbihtYXNrVG9rZW5zW210bmR4XSwgbmR4SW5pdGlhbGl6ZXIsIFsgbXRuZHggXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCAmJiB0ZXN0UG9zID09PSBwb3MgfHwgcG9zIDwgdGVzdFBvcykgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIDAgIT09IG1hdGNoZXMubGVuZ3RoICYmICFpbnNlcnRTdG9wIHx8IG1hdGNoZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgbWF0Y2g6IHtcbiAgICAgICAgICAgICAgICAgICAgZm46IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIHN0YXRpYzogITAsXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsaXR5OiAhMSxcbiAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICBkZWY6IFwiXCIsXG4gICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIlwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsb2NhdG9yOiBbXSxcbiAgICAgICAgICAgICAgICBtbG9jOiB7fSxcbiAgICAgICAgICAgICAgICBjZDogY2FjaGVEZXBlbmRlbmN5XG4gICAgICAgICAgICB9KSwgdm9pZCAwICE9PSBuZHhJbnRsenIgJiYgbWFza3NldC50ZXN0c1twb3NdID8gJC5leHRlbmQoITAsIFtdLCBtYXRjaGVzKSA6IChtYXNrc2V0LnRlc3RzW3Bvc10gPSAkLmV4dGVuZCghMCwgW10sIG1hdGNoZXMpLCBcbiAgICAgICAgICAgIG1hc2tzZXQudGVzdHNbcG9zXSk7XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gICAgICAgICAgICB2YWx1ZTogITBcbiAgICAgICAgfSksIGV4cG9ydHMuZGV0ZXJtaW5lVGVzdFRlbXBsYXRlID0gZGV0ZXJtaW5lVGVzdFRlbXBsYXRlLCBleHBvcnRzLmdldERlY2lzaW9uVGFrZXIgPSBnZXREZWNpc2lvblRha2VyLCBcbiAgICAgICAgZXhwb3J0cy5nZXRNYXNrVGVtcGxhdGUgPSBnZXRNYXNrVGVtcGxhdGUsIGV4cG9ydHMuZ2V0UGxhY2Vob2xkZXIgPSBnZXRQbGFjZWhvbGRlciwgXG4gICAgICAgIGV4cG9ydHMuZ2V0VGVzdCA9IGdldFRlc3QsIGV4cG9ydHMuZ2V0VGVzdHMgPSBnZXRUZXN0cywgZXhwb3J0cy5nZXRUZXN0VGVtcGxhdGUgPSBnZXRUZXN0VGVtcGxhdGU7XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgICAgICAgICAgIHZhbHVlOiAhMFxuICAgICAgICB9KSwgZXhwb3J0cy5hbHRlcm5hdGUgPSBhbHRlcm5hdGUsIGV4cG9ydHMuY2hlY2tBbHRlcm5hdGlvbk1hdGNoID0gY2hlY2tBbHRlcm5hdGlvbk1hdGNoLCBcbiAgICAgICAgZXhwb3J0cy5pc0NvbXBsZXRlID0gaXNDb21wbGV0ZSwgZXhwb3J0cy5pc1ZhbGlkID0gaXNWYWxpZCwgZXhwb3J0cy5yZWZyZXNoRnJvbUJ1ZmZlciA9IHJlZnJlc2hGcm9tQnVmZmVyLCBcbiAgICAgICAgZXhwb3J0cy5yZXZhbGlkYXRlTWFzayA9IHJldmFsaWRhdGVNYXNrLCBleHBvcnRzLmhhbmRsZVJlbW92ZSA9IGhhbmRsZVJlbW92ZTtcbiAgICAgICAgdmFyIF92YWxpZGF0aW9uVGVzdHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDMpLCBfa2V5Y29kZSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygwKSksIF9wb3NpdGlvbmluZyA9IF9fd2VicGFja19yZXF1aXJlX18oMiksIF9ldmVudGhhbmRsZXJzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2KTtcbiAgICAgICAgZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHtcbiAgICAgICAgICAgIHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDogb2JqXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGFsdGVybmF0ZShtYXNrUG9zLCBjLCBzdHJpY3QsIGZyb21Jc1ZhbGlkLCByQWx0UG9zLCBzZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCAkID0gdGhpcy5kZXBlbmRlbmN5TGliLCBvcHRzID0gdGhpcy5vcHRzLCBtYXNrc2V0ID0gdGhpcy5tYXNrc2V0LCB2YWxpZFBzQ2xvbmUgPSAkLmV4dGVuZCghMCwge30sIG1hc2tzZXQudmFsaWRQb3NpdGlvbnMpLCB0c3RDbG9uZSA9ICQuZXh0ZW5kKCEwLCB7fSwgbWFza3NldC50ZXN0cyksIGxhc3RBbHQsIGFsdGVybmF0aW9uLCBpc1ZhbGlkUnNsdCA9ICExLCByZXR1cm5Sc2x0ID0gITEsIGFsdFBvcywgcHJldkFsdFBvcywgaSwgdmFsaWRQb3MsIGRlY2lzaW9uUG9zLCBsQWx0UG9zID0gdm9pZCAwICE9PSByQWx0UG9zID8gckFsdFBvcyA6IF9wb3NpdGlvbmluZy5nZXRMYXN0VmFsaWRQb3NpdGlvbi5jYWxsKHRoaXMpLCBuZXh0UG9zLCBpbnB1dCwgYmVnaW4sIGVuZDtcbiAgICAgICAgICAgIGlmIChzZWxlY3Rpb24gJiYgKGJlZ2luID0gc2VsZWN0aW9uLmJlZ2luLCBlbmQgPSBzZWxlY3Rpb24uZW5kLCBzZWxlY3Rpb24uYmVnaW4gPiBzZWxlY3Rpb24uZW5kICYmIChiZWdpbiA9IHNlbGVjdGlvbi5lbmQsIFxuICAgICAgICAgICAgZW5kID0gc2VsZWN0aW9uLmJlZ2luKSksIC0xID09PSBsQWx0UG9zICYmIHZvaWQgMCA9PT0gckFsdFBvcykgbGFzdEFsdCA9IDAsIHByZXZBbHRQb3MgPSBfdmFsaWRhdGlvblRlc3RzLmdldFRlc3QuY2FsbCh0aGlzLCBsYXN0QWx0KSwgXG4gICAgICAgICAgICBhbHRlcm5hdGlvbiA9IHByZXZBbHRQb3MuYWx0ZXJuYXRpb247IGVsc2UgZm9yICg7MCA8PSBsQWx0UG9zOyBsQWx0UG9zLS0pIGlmIChhbHRQb3MgPSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW2xBbHRQb3NdLCBcbiAgICAgICAgICAgIGFsdFBvcyAmJiB2b2lkIDAgIT09IGFsdFBvcy5hbHRlcm5hdGlvbikge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2QWx0UG9zICYmIHByZXZBbHRQb3MubG9jYXRvclthbHRQb3MuYWx0ZXJuYXRpb25dICE9PSBhbHRQb3MubG9jYXRvclthbHRQb3MuYWx0ZXJuYXRpb25dKSBicmVhaztcbiAgICAgICAgICAgICAgICBsYXN0QWx0ID0gbEFsdFBvcywgYWx0ZXJuYXRpb24gPSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW2xhc3RBbHRdLmFsdGVybmF0aW9uLCBwcmV2QWx0UG9zID0gYWx0UG9zO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHZvaWQgMCAhPT0gYWx0ZXJuYXRpb24pIHtcbiAgICAgICAgICAgICAgICBkZWNpc2lvblBvcyA9IHBhcnNlSW50KGxhc3RBbHQpLCBtYXNrc2V0LmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXSA9IG1hc2tzZXQuZXhjbHVkZXNbZGVjaXNpb25Qb3NdIHx8IFtdLCBcbiAgICAgICAgICAgICAgICAhMCAhPT0gbWFza1BvcyAmJiBtYXNrc2V0LmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXS5wdXNoKCgwLCBfdmFsaWRhdGlvblRlc3RzLmdldERlY2lzaW9uVGFrZXIpKHByZXZBbHRQb3MpICsgXCI6XCIgKyBwcmV2QWx0UG9zLmFsdGVybmF0aW9uKTtcbiAgICAgICAgICAgICAgICB2YXIgdmFsaWRJbnB1dHMgPSBbXSwgcmVzdWx0UG9zID0gLTE7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gZGVjaXNpb25Qb3M7IGkgPCBfcG9zaXRpb25pbmcuZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbCh0aGlzLCB2b2lkIDAsICEwKSArIDE7IGkrKykgLTEgPT09IHJlc3VsdFBvcyAmJiBtYXNrUG9zIDw9IGkgJiYgdm9pZCAwICE9PSBjICYmICh2YWxpZElucHV0cy5wdXNoKGMpLCBcbiAgICAgICAgICAgICAgICByZXN1bHRQb3MgPSB2YWxpZElucHV0cy5sZW5ndGggLSAxKSwgdmFsaWRQb3MgPSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW2ldLCB2YWxpZFBvcyAmJiAhMCAhPT0gdmFsaWRQb3MuZ2VuZXJhdGVkSW5wdXQgJiYgKHZvaWQgMCA9PT0gc2VsZWN0aW9uIHx8IGkgPCBiZWdpbiB8fCBlbmQgPD0gaSkgJiYgdmFsaWRJbnB1dHMucHVzaCh2YWxpZFBvcy5pbnB1dCksIFxuICAgICAgICAgICAgICAgIGRlbGV0ZSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW2ldO1xuICAgICAgICAgICAgICAgIGZvciAoLTEgPT09IHJlc3VsdFBvcyAmJiB2b2lkIDAgIT09IGMgJiYgKHZhbGlkSW5wdXRzLnB1c2goYyksIHJlc3VsdFBvcyA9IHZhbGlkSW5wdXRzLmxlbmd0aCAtIDEpOyB2b2lkIDAgIT09IG1hc2tzZXQuZXhjbHVkZXNbZGVjaXNpb25Qb3NdICYmIG1hc2tzZXQuZXhjbHVkZXNbZGVjaXNpb25Qb3NdLmxlbmd0aCA8IDEwOyApIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChtYXNrc2V0LnRlc3RzID0ge30sIF9wb3NpdGlvbmluZy5yZXNldE1hc2tTZXQuY2FsbCh0aGlzLCAhMCksIGlzVmFsaWRSc2x0ID0gITAsIFxuICAgICAgICAgICAgICAgICAgICBpID0gMDsgaSA8IHZhbGlkSW5wdXRzLmxlbmd0aCAmJiAobmV4dFBvcyA9IGlzVmFsaWRSc2x0LmNhcmV0IHx8IF9wb3NpdGlvbmluZy5nZXRMYXN0VmFsaWRQb3NpdGlvbi5jYWxsKHRoaXMsIHZvaWQgMCwgITApICsgMSwgXG4gICAgICAgICAgICAgICAgICAgIGlucHV0ID0gdmFsaWRJbnB1dHNbaV0sIGlzVmFsaWRSc2x0ID0gaXNWYWxpZC5jYWxsKHRoaXMsIG5leHRQb3MsIGlucHV0LCAhMSwgZnJvbUlzVmFsaWQsICEwKSk7IGkrKykgaSA9PT0gcmVzdWx0UG9zICYmIChyZXR1cm5Sc2x0ID0gaXNWYWxpZFJzbHQpLCBcbiAgICAgICAgICAgICAgICAgICAgMSA9PSBtYXNrUG9zICYmIGlzVmFsaWRSc2x0ICYmIChyZXR1cm5Sc2x0ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3M6IGlcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkUnNsdCkgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfcG9zaXRpb25pbmcucmVzZXRNYXNrU2V0LmNhbGwodGhpcyksIHByZXZBbHRQb3MgPSBfdmFsaWRhdGlvblRlc3RzLmdldFRlc3QuY2FsbCh0aGlzLCBkZWNpc2lvblBvcyksIFxuICAgICAgICAgICAgICAgICAgICBtYXNrc2V0LnZhbGlkUG9zaXRpb25zID0gJC5leHRlbmQoITAsIHt9LCB2YWxpZFBzQ2xvbmUpLCBtYXNrc2V0LnRlc3RzID0gJC5leHRlbmQoITAsIHt9LCB0c3RDbG9uZSksIFxuICAgICAgICAgICAgICAgICAgICAhbWFza3NldC5leGNsdWRlc1tkZWNpc2lvblBvc10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVyblJzbHQgPSBhbHRlcm5hdGUuY2FsbCh0aGlzLCBtYXNrUG9zLCBjLCBzdHJpY3QsIGZyb21Jc1ZhbGlkLCBkZWNpc2lvblBvcyAtIDEsIHNlbGVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgZGVjaXNpb25UYWtlciA9ICgwLCBfdmFsaWRhdGlvblRlc3RzLmdldERlY2lzaW9uVGFrZXIpKHByZXZBbHRQb3MpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoLTEgIT09IG1hc2tzZXQuZXhjbHVkZXNbZGVjaXNpb25Qb3NdLmluZGV4T2YoZGVjaXNpb25UYWtlciArIFwiOlwiICsgcHJldkFsdFBvcy5hbHRlcm5hdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVyblJzbHQgPSBhbHRlcm5hdGUuY2FsbCh0aGlzLCBtYXNrUG9zLCBjLCBzdHJpY3QsIGZyb21Jc1ZhbGlkLCBkZWNpc2lvblBvcyAtIDEsIHNlbGVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3IgKG1hc2tzZXQuZXhjbHVkZXNbZGVjaXNpb25Qb3NdLnB1c2goZGVjaXNpb25UYWtlciArIFwiOlwiICsgcHJldkFsdFBvcy5hbHRlcm5hdGlvbiksIFxuICAgICAgICAgICAgICAgICAgICBpID0gZGVjaXNpb25Qb3M7IGkgPCBfcG9zaXRpb25pbmcuZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbCh0aGlzLCB2b2lkIDAsICEwKSArIDE7IGkrKykgZGVsZXRlIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJldHVyblJzbHQgJiYgITEgPT09IG9wdHMua2VlcFN0YXRpYyB8fCBkZWxldGUgbWFza3NldC5leGNsdWRlc1tkZWNpc2lvblBvc10sIFxuICAgICAgICAgICAgcmV0dXJuUnNsdDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBjYXNpbmcoZWxlbSwgdGVzdCwgcG9zKSB7XG4gICAgICAgICAgICB2YXIgb3B0cyA9IHRoaXMub3B0cywgbWFza3NldCA9IHRoaXMubWFza3NldDtcbiAgICAgICAgICAgIHN3aXRjaCAob3B0cy5jYXNpbmcgfHwgdGVzdC5jYXNpbmcpIHtcbiAgICAgICAgICAgICAgY2FzZSBcInVwcGVyXCI6XG4gICAgICAgICAgICAgICAgZWxlbSA9IGVsZW0udG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICBjYXNlIFwibG93ZXJcIjpcbiAgICAgICAgICAgICAgICBlbGVtID0gZWxlbS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJ0aXRsZVwiOlxuICAgICAgICAgICAgICAgIHZhciBwb3NCZWZvcmUgPSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdO1xuICAgICAgICAgICAgICAgIGVsZW0gPSAwID09PSBwb3MgfHwgcG9zQmVmb3JlICYmIHBvc0JlZm9yZS5pbnB1dCA9PT0gU3RyaW5nLmZyb21DaGFyQ29kZShfa2V5Y29kZS5kZWZhdWx0LlNQQUNFKSA/IGVsZW0udG9VcHBlckNhc2UoKSA6IGVsZW0udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGlmIChcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIG9wdHMuY2FzaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgYXJncy5wdXNoKG1hc2tzZXQudmFsaWRQb3NpdGlvbnMpLCBlbGVtID0gb3B0cy5jYXNpbmcuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gY2hlY2tBbHRlcm5hdGlvbk1hdGNoKGFsdEFycjEsIGFsdEFycjIsIG5hKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBvcHRzID0gdGhpcy5vcHRzLCBhbHRBcnJDID0gb3B0cy5ncmVlZHkgPyBhbHRBcnIyIDogYWx0QXJyMi5zbGljZSgwLCAxKSwgaXNNYXRjaCA9ICExLCBuYUFyciA9IHZvaWQgMCAhPT0gbmEgPyBuYS5zcGxpdChcIixcIikgOiBbXSwgbmFOZHgsIGkgPSAwOyBpIDwgbmFBcnIubGVuZ3RoOyBpKyspIC0xICE9PSAobmFOZHggPSBhbHRBcnIxLmluZGV4T2YobmFBcnJbaV0pKSAmJiBhbHRBcnIxLnNwbGljZShuYU5keCwgMSk7XG4gICAgICAgICAgICBmb3IgKHZhciBhbG5keCA9IDA7IGFsbmR4IDwgYWx0QXJyMS5sZW5ndGg7IGFsbmR4KyspIGlmIChhbHRBcnJDLmluY2x1ZGVzKGFsdEFycjFbYWxuZHhdKSkge1xuICAgICAgICAgICAgICAgIGlzTWF0Y2ggPSAhMDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpc01hdGNoO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGhhbmRsZVJlbW92ZShpbnB1dCwgaywgcG9zLCBzdHJpY3QsIGZyb21Jc1ZhbGlkKSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcywgbWFza3NldCA9IHRoaXMubWFza3NldCwgb3B0cyA9IHRoaXMub3B0cztcbiAgICAgICAgICAgIGlmICgob3B0cy5udW1lcmljSW5wdXQgfHwgdGhpcy5pc1JUTCkgJiYgKGsgPT09IF9rZXljb2RlLmRlZmF1bHQuQkFDS1NQQUNFID8gayA9IF9rZXljb2RlLmRlZmF1bHQuREVMRVRFIDogayA9PT0gX2tleWNvZGUuZGVmYXVsdC5ERUxFVEUgJiYgKGsgPSBfa2V5Y29kZS5kZWZhdWx0LkJBQ0tTUEFDRSksIFxuICAgICAgICAgICAgdGhpcy5pc1JUTCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGVuZCA9IHBvcy5lbmQ7XG4gICAgICAgICAgICAgICAgcG9zLmVuZCA9IHBvcy5iZWdpbiwgcG9zLmJlZ2luID0gcGVuZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBsdnAgPSBfcG9zaXRpb25pbmcuZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbCh0aGlzLCB2b2lkIDAsICEwKSwgb2Zmc2V0O1xuICAgICAgICAgICAgaWYgKHBvcy5lbmQgPj0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKHRoaXMpLmxlbmd0aCAmJiBsdnAgPj0gcG9zLmVuZCAmJiAocG9zLmVuZCA9IGx2cCArIDEpLCBcbiAgICAgICAgICAgIGsgPT09IF9rZXljb2RlLmRlZmF1bHQuQkFDS1NQQUNFID8gcG9zLmVuZCAtIHBvcy5iZWdpbiA8IDEgJiYgKHBvcy5iZWdpbiA9IF9wb3NpdGlvbmluZy5zZWVrUHJldmlvdXMuY2FsbCh0aGlzLCBwb3MuYmVnaW4pKSA6IGsgPT09IF9rZXljb2RlLmRlZmF1bHQuREVMRVRFICYmIHBvcy5iZWdpbiA9PT0gcG9zLmVuZCAmJiAocG9zLmVuZCA9IF9wb3NpdGlvbmluZy5pc01hc2suY2FsbCh0aGlzLCBwb3MuZW5kLCAhMCwgITApID8gcG9zLmVuZCArIDEgOiBfcG9zaXRpb25pbmcuc2Vla05leHQuY2FsbCh0aGlzLCBwb3MuZW5kKSArIDEpLCBcbiAgICAgICAgICAgICExICE9PSAob2Zmc2V0ID0gcmV2YWxpZGF0ZU1hc2suY2FsbCh0aGlzLCBwb3MpKSkge1xuICAgICAgICAgICAgICAgIGlmICghMCAhPT0gc3RyaWN0ICYmICExICE9PSBvcHRzLmtlZXBTdGF0aWMgfHwgbnVsbCAhPT0gb3B0cy5yZWdleCAmJiAtMSAhPT0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0LmNhbGwodGhpcywgcG9zLmJlZ2luKS5tYXRjaC5kZWYuaW5kZXhPZihcInxcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGFsdGVybmF0ZS5jYWxsKHRoaXMsICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1BvcyA9IHZvaWQgMCAhPT0gcmVzdWx0LmNhcmV0ID8gcmVzdWx0LmNhcmV0IDogcmVzdWx0LnBvcyA/IF9wb3NpdGlvbmluZy5zZWVrTmV4dC5jYWxsKHRoaXMsIHJlc3VsdC5wb3MuYmVnaW4gPyByZXN1bHQucG9zLmJlZ2luIDogcmVzdWx0LnBvcykgOiBfcG9zaXRpb25pbmcuZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbCh0aGlzLCAtMSwgITApO1xuICAgICAgICAgICAgICAgICAgICAgICAgKGsgIT09IF9rZXljb2RlLmRlZmF1bHQuREVMRVRFIHx8IHBvcy5iZWdpbiA+IG5ld1BvcykgJiYgcG9zLmJlZ2luO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICEwICE9PSBzdHJpY3QgJiYgKG1hc2tzZXQucCA9IGsgPT09IF9rZXljb2RlLmRlZmF1bHQuREVMRVRFID8gcG9zLmJlZ2luICsgb2Zmc2V0IDogcG9zLmJlZ2luKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc0NvbXBsZXRlKGJ1ZmZlcikge1xuICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMsIG9wdHMgPSB0aGlzLm9wdHMsIG1hc2tzZXQgPSB0aGlzLm1hc2tzZXQ7XG4gICAgICAgICAgICBpZiAoXCJmdW5jdGlvblwiID09IHR5cGVvZiBvcHRzLmlzQ29tcGxldGUpIHJldHVybiBvcHRzLmlzQ29tcGxldGUoYnVmZmVyLCBvcHRzKTtcbiAgICAgICAgICAgIGlmIChcIipcIiAhPT0gb3B0cy5yZXBlYXQpIHtcbiAgICAgICAgICAgICAgICB2YXIgY29tcGxldGUgPSAhMSwgbHJwID0gX3Bvc2l0aW9uaW5nLmRldGVybWluZUxhc3RSZXF1aXJlZFBvc2l0aW9uLmNhbGwodGhpcywgITApLCBhbWwgPSBfcG9zaXRpb25pbmcuc2Vla1ByZXZpb3VzLmNhbGwodGhpcywgbHJwLmwpO1xuICAgICAgICAgICAgICAgIGlmICh2b2lkIDAgPT09IGxycC5kZWYgfHwgbHJwLmRlZi5uZXdCbG9ja01hcmtlciB8fCBscnAuZGVmLm9wdGlvbmFsaXR5IHx8IGxycC5kZWYub3B0aW9uYWxRdWFudGlmaWVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlID0gITA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDw9IGFtbDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdCA9IF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdFRlbXBsYXRlLmNhbGwodGhpcywgaSkubWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoITAgIT09IHRlc3Quc3RhdGljICYmIHZvaWQgMCA9PT0gbWFza3NldC52YWxpZFBvc2l0aW9uc1tpXSAmJiAhMCAhPT0gdGVzdC5vcHRpb25hbGl0eSAmJiAhMCAhPT0gdGVzdC5vcHRpb25hbFF1YW50aWZpZXIgfHwgITAgPT09IHRlc3Quc3RhdGljICYmIGJ1ZmZlcltpXSAhPT0gX3ZhbGlkYXRpb25UZXN0cy5nZXRQbGFjZWhvbGRlci5jYWxsKHRoaXMsIGksIHRlc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGxldGUgPSAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gY29tcGxldGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gaXNWYWxpZChwb3MsIGMsIHN0cmljdCwgZnJvbUlzVmFsaWQsIGZyb21BbHRlcm5hdGUsIHZhbGlkYXRlT25seSwgZnJvbUNoZWNrdmFsKSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcywgJCA9IHRoaXMuZGVwZW5kZW5jeUxpYiwgb3B0cyA9IHRoaXMub3B0cywgZWwgPSBpbnB1dG1hc2suZWwsIG1hc2tzZXQgPSBpbnB1dG1hc2subWFza3NldDtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzU2VsZWN0aW9uKHBvc09iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dG1hc2suaXNSVEwgPyAxIDwgcG9zT2JqLmJlZ2luIC0gcG9zT2JqLmVuZCB8fCBwb3NPYmouYmVnaW4gLSBwb3NPYmouZW5kID09IDEgOiAxIDwgcG9zT2JqLmVuZCAtIHBvc09iai5iZWdpbiB8fCBwb3NPYmouZW5kIC0gcG9zT2JqLmJlZ2luID09IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdHJpY3QgPSAhMCA9PT0gc3RyaWN0O1xuICAgICAgICAgICAgdmFyIG1hc2tQb3MgPSBwb3M7XG4gICAgICAgICAgICBmdW5jdGlvbiBwcm9jZXNzQ29tbWFuZE9iamVjdChjb21tYW5kT2JqKSB7XG4gICAgICAgICAgICAgICAgaWYgKHZvaWQgMCAhPT0gY29tbWFuZE9iaikge1xuICAgICAgICAgICAgICAgICAgICBpZiAodm9pZCAwICE9PSBjb21tYW5kT2JqLnJlbW92ZSAmJiAoQXJyYXkuaXNBcnJheShjb21tYW5kT2JqLnJlbW92ZSkgfHwgKGNvbW1hbmRPYmoucmVtb3ZlID0gWyBjb21tYW5kT2JqLnJlbW92ZSBdKSwgXG4gICAgICAgICAgICAgICAgICAgIGNvbW1hbmRPYmoucmVtb3ZlLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGIucG9zIC0gYS5wb3M7XG4gICAgICAgICAgICAgICAgICAgIH0pLmZvckVhY2goZnVuY3Rpb24obG1udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV2YWxpZGF0ZU1hc2suY2FsbChpbnB1dG1hc2ssIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogbG1udCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IGxtbnQgKyAxXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSksIGNvbW1hbmRPYmoucmVtb3ZlID0gdm9pZCAwKSwgdm9pZCAwICE9PSBjb21tYW5kT2JqLmluc2VydCAmJiAoQXJyYXkuaXNBcnJheShjb21tYW5kT2JqLmluc2VydCkgfHwgKGNvbW1hbmRPYmouaW5zZXJ0ID0gWyBjb21tYW5kT2JqLmluc2VydCBdKSwgXG4gICAgICAgICAgICAgICAgICAgIGNvbW1hbmRPYmouaW5zZXJ0LnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEucG9zIC0gYi5wb3M7XG4gICAgICAgICAgICAgICAgICAgIH0pLmZvckVhY2goZnVuY3Rpb24obG1udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJcIiAhPT0gbG1udC5jICYmIGlzVmFsaWQuY2FsbChpbnB1dG1hc2ssIGxtbnQucG9zLCBsbW50LmMsIHZvaWQgMCA9PT0gbG1udC5zdHJpY3QgfHwgbG1udC5zdHJpY3QsIHZvaWQgMCAhPT0gbG1udC5mcm9tSXNWYWxpZCA/IGxtbnQuZnJvbUlzVmFsaWQgOiBmcm9tSXNWYWxpZCk7XG4gICAgICAgICAgICAgICAgICAgIH0pLCBjb21tYW5kT2JqLmluc2VydCA9IHZvaWQgMCksIGNvbW1hbmRPYmoucmVmcmVzaEZyb21CdWZmZXIgJiYgY29tbWFuZE9iai5idWZmZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZWZyZXNoID0gY29tbWFuZE9iai5yZWZyZXNoRnJvbUJ1ZmZlcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2hGcm9tQnVmZmVyLmNhbGwoaW5wdXRtYXNrLCAhMCA9PT0gcmVmcmVzaCA/IHJlZnJlc2ggOiByZWZyZXNoLnN0YXJ0LCByZWZyZXNoLmVuZCwgY29tbWFuZE9iai5idWZmZXIpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbW1hbmRPYmoucmVmcmVzaEZyb21CdWZmZXIgPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdm9pZCAwICE9PSBjb21tYW5kT2JqLnJld3JpdGVQb3NpdGlvbiAmJiAobWFza1BvcyA9IGNvbW1hbmRPYmoucmV3cml0ZVBvc2l0aW9uLCBcbiAgICAgICAgICAgICAgICAgICAgY29tbWFuZE9iaiA9ICEwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbW1hbmRPYmo7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBfaXNWYWxpZChwb3NpdGlvbiwgYywgc3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHJzbHQgPSAhMTtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0cy5jYWxsKGlucHV0bWFzaywgcG9zaXRpb24pLmV2ZXJ5KGZ1bmN0aW9uKHRzdCwgbmR4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZXN0ID0gdHN0Lm1hdGNoO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaywgITApLCByc2x0ID0gbnVsbCAhPSB0ZXN0LmZuID8gdGVzdC5mbi50ZXN0KGMsIG1hc2tzZXQsIHBvc2l0aW9uLCBzdHJpY3QsIG9wdHMsIGlzU2VsZWN0aW9uKHBvcykpIDogKGMgPT09IHRlc3QuZGVmIHx8IGMgPT09IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlcikgJiYgXCJcIiAhPT0gdGVzdC5kZWYgJiYge1xuICAgICAgICAgICAgICAgICAgICAgICAgYzogX3ZhbGlkYXRpb25UZXN0cy5nZXRQbGFjZWhvbGRlci5jYWxsKGlucHV0bWFzaywgcG9zaXRpb24sIHRlc3QsICEwKSB8fCB0ZXN0LmRlZixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zaXRpb25cbiAgICAgICAgICAgICAgICAgICAgfSwgITEgPT09IHJzbHQpIHJldHVybiAhMDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVsZW0gPSB2b2lkIDAgIT09IHJzbHQuYyA/IHJzbHQuYyA6IGMsIHZhbGlkYXRlZFBvcyA9IHBvc2l0aW9uO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZWxlbSA9IGVsZW0gPT09IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlciAmJiAhMCA9PT0gdGVzdC5zdGF0aWMgPyBfdmFsaWRhdGlvblRlc3RzLmdldFBsYWNlaG9sZGVyLmNhbGwoaW5wdXRtYXNrLCBwb3NpdGlvbiwgdGVzdCwgITApIHx8IHRlc3QuZGVmIDogZWxlbSwgXG4gICAgICAgICAgICAgICAgICAgIHJzbHQgPSBwcm9jZXNzQ29tbWFuZE9iamVjdChyc2x0KSwgITAgIT09IHJzbHQgJiYgdm9pZCAwICE9PSByc2x0LnBvcyAmJiByc2x0LnBvcyAhPT0gcG9zaXRpb24gJiYgKHZhbGlkYXRlZFBvcyA9IHJzbHQucG9zKSwgXG4gICAgICAgICAgICAgICAgICAgICEwICE9PSByc2x0ICYmIHZvaWQgMCA9PT0gcnNsdC5wb3MgJiYgdm9pZCAwID09PSByc2x0LmMgfHwgITEgPT09IHJldmFsaWRhdGVNYXNrLmNhbGwoaW5wdXRtYXNrLCBwb3MsICQuZXh0ZW5kKHt9LCB0c3QsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0OiBjYXNpbmcuY2FsbChpbnB1dG1hc2ssIGVsZW0sIHRlc3QsIHZhbGlkYXRlZFBvcylcbiAgICAgICAgICAgICAgICAgICAgfSksIGZyb21Jc1ZhbGlkLCB2YWxpZGF0ZWRQb3MpICYmIChyc2x0ID0gITEpLCAhMTtcbiAgICAgICAgICAgICAgICB9KSwgcnNsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZvaWQgMCAhPT0gcG9zLmJlZ2luICYmIChtYXNrUG9zID0gaW5wdXRtYXNrLmlzUlRMID8gcG9zLmVuZCA6IHBvcy5iZWdpbik7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gITAsIHBvc2l0aW9uc0Nsb25lID0gJC5leHRlbmQoITAsIHt9LCBtYXNrc2V0LnZhbGlkUG9zaXRpb25zKTtcbiAgICAgICAgICAgIGlmICghMSA9PT0gb3B0cy5rZWVwU3RhdGljICYmIHZvaWQgMCAhPT0gbWFza3NldC5leGNsdWRlc1ttYXNrUG9zXSAmJiAhMCAhPT0gZnJvbUFsdGVybmF0ZSAmJiAhMCAhPT0gZnJvbUlzVmFsaWQpIGZvciAodmFyIGkgPSBtYXNrUG9zOyBpIDwgKGlucHV0bWFzay5pc1JUTCA/IHBvcy5iZWdpbiA6IHBvcy5lbmQpOyBpKyspIHZvaWQgMCAhPT0gbWFza3NldC5leGNsdWRlc1tpXSAmJiAobWFza3NldC5leGNsdWRlc1tpXSA9IHZvaWQgMCwgXG4gICAgICAgICAgICBkZWxldGUgbWFza3NldC50ZXN0c1tpXSk7XG4gICAgICAgICAgICBpZiAoXCJmdW5jdGlvblwiID09IHR5cGVvZiBvcHRzLnByZVZhbGlkYXRpb24gJiYgITAgIT09IGZyb21Jc1ZhbGlkICYmICEwICE9PSB2YWxpZGF0ZU9ubHkgJiYgKHJlc3VsdCA9IG9wdHMucHJlVmFsaWRhdGlvbi5jYWxsKGVsLCBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKSwgbWFza1BvcywgYywgaXNTZWxlY3Rpb24ocG9zKSwgb3B0cywgbWFza3NldCwgcG9zLCBzdHJpY3QgfHwgZnJvbUFsdGVybmF0ZSksIFxuICAgICAgICAgICAgcmVzdWx0ID0gcHJvY2Vzc0NvbW1hbmRPYmplY3QocmVzdWx0KSksICEwID09PSByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAodm9pZCAwID09PSBpbnB1dG1hc2subWF4TGVuZ3RoIHx8IG1hc2tQb3MgPCBpbnB1dG1hc2subWF4TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPSBfaXNWYWxpZChtYXNrUG9zLCBjLCBzdHJpY3QpLCAoIXN0cmljdCB8fCAhMCA9PT0gZnJvbUlzVmFsaWQpICYmICExID09PSByZXN1bHQgJiYgITAgIT09IHZhbGlkYXRlT25seSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRQb3NWYWxpZCA9IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbbWFza1Bvc107XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWN1cnJlbnRQb3NWYWxpZCB8fCAhMCAhPT0gY3VycmVudFBvc1ZhbGlkLm1hdGNoLnN0YXRpYyB8fCBjdXJyZW50UG9zVmFsaWQubWF0Y2guZGVmICE9PSBjICYmIGMgIT09IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3Rlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmluc2VydE1vZGUgfHwgdm9pZCAwID09PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW19wb3NpdGlvbmluZy5zZWVrTmV4dC5jYWxsKGlucHV0bWFzaywgbWFza1BvcyldIHx8IHBvcy5lbmQgPiBtYXNrUG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBza2lwID0gITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrc2V0LmppdE9mZnNldFttYXNrUG9zXSAmJiB2b2lkIDAgPT09IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbX3Bvc2l0aW9uaW5nLnNlZWtOZXh0LmNhbGwoaW5wdXRtYXNrLCBtYXNrUG9zKV0gJiYgKHJlc3VsdCA9IGlzVmFsaWQuY2FsbChpbnB1dG1hc2ssIG1hc2tQb3MgKyBtYXNrc2V0LmppdE9mZnNldFttYXNrUG9zXSwgYywgITApLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgITEgIT09IHJlc3VsdCAmJiAoITAgIT09IGZyb21BbHRlcm5hdGUgJiYgKHJlc3VsdC5jYXJldCA9IG1hc2tQb3MpLCBza2lwID0gITApKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5lbmQgPiBtYXNrUG9zICYmIChtYXNrc2V0LnZhbGlkUG9zaXRpb25zW21hc2tQb3NdID0gdm9pZCAwKSwgIXNraXAgJiYgIV9wb3NpdGlvbmluZy5pc01hc2suY2FsbChpbnB1dG1hc2ssIG1hc2tQb3MsIG9wdHMua2VlcFN0YXRpYyAmJiAwID09PSBtYXNrUG9zKSkgZm9yICh2YXIgblBvcyA9IG1hc2tQb3MgKyAxLCBzblBvcyA9IF9wb3NpdGlvbmluZy5zZWVrTmV4dC5jYWxsKGlucHV0bWFzaywgbWFza1BvcywgITEsIDAgIT09IG1hc2tQb3MpOyBuUG9zIDw9IHNuUG9zOyBuUG9zKyspIGlmIChyZXN1bHQgPSBfaXNWYWxpZChuUG9zLCBjLCBzdHJpY3QpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgITEgIT09IHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJhY2tiYWNrUG9zaXRpb25zLmNhbGwoaW5wdXRtYXNrLCBtYXNrUG9zLCB2b2lkIDAgIT09IHJlc3VsdC5wb3MgPyByZXN1bHQucG9zIDogblBvcykgfHwgcmVzdWx0LCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tQb3MgPSBuUG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgcmVzdWx0ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBfcG9zaXRpb25pbmcuc2Vla05leHQuY2FsbChpbnB1dG1hc2ssIG1hc2tQb3MpXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHJlc3VsdCA9ICExO1xuICAgICAgICAgICAgICAgICExICE9PSByZXN1bHQgfHwgIW9wdHMua2VlcFN0YXRpYyB8fCAhaXNDb21wbGV0ZS5jYWxsKGlucHV0bWFzaywgX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykpICYmIDAgIT09IG1hc2tQb3MgfHwgc3RyaWN0IHx8ICEwID09PSBmcm9tQWx0ZXJuYXRlID8gaXNTZWxlY3Rpb24ocG9zKSAmJiBtYXNrc2V0LnRlc3RzW21hc2tQb3NdICYmIDEgPCBtYXNrc2V0LnRlc3RzW21hc2tQb3NdLmxlbmd0aCAmJiBvcHRzLmtlZXBTdGF0aWMgJiYgIXN0cmljdCAmJiAhMCAhPT0gZnJvbUFsdGVybmF0ZSAmJiAocmVzdWx0ID0gYWx0ZXJuYXRlLmNhbGwoaW5wdXRtYXNrLCAhMCkpIDogcmVzdWx0ID0gYWx0ZXJuYXRlLmNhbGwoaW5wdXRtYXNrLCBtYXNrUG9zLCBjLCBzdHJpY3QsIGZyb21Jc1ZhbGlkLCB2b2lkIDAsIHBvcyksIFxuICAgICAgICAgICAgICAgICEwID09PSByZXN1bHQgJiYgKHJlc3VsdCA9IHtcbiAgICAgICAgICAgICAgICAgICAgcG9zOiBtYXNrUG9zXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXCJmdW5jdGlvblwiID09IHR5cGVvZiBvcHRzLnBvc3RWYWxpZGF0aW9uICYmICEwICE9PSBmcm9tSXNWYWxpZCAmJiAhMCAhPT0gdmFsaWRhdGVPbmx5KSB7XG4gICAgICAgICAgICAgICAgdmFyIHBvc3RSZXN1bHQgPSBvcHRzLnBvc3RWYWxpZGF0aW9uLmNhbGwoZWwsIF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2ssICEwKSwgdm9pZCAwICE9PSBwb3MuYmVnaW4gPyBpbnB1dG1hc2suaXNSVEwgPyBwb3MuZW5kIDogcG9zLmJlZ2luIDogcG9zLCBjLCByZXN1bHQsIG9wdHMsIG1hc2tzZXQsIHN0cmljdCwgZnJvbUNoZWNrdmFsKTtcbiAgICAgICAgICAgICAgICB2b2lkIDAgIT09IHBvc3RSZXN1bHQgJiYgKHJlc3VsdCA9ICEwID09PSBwb3N0UmVzdWx0ID8gcmVzdWx0IDogcG9zdFJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQgJiYgdm9pZCAwID09PSByZXN1bHQucG9zICYmIChyZXN1bHQucG9zID0gbWFza1BvcyksICExID09PSByZXN1bHQgfHwgITAgPT09IHZhbGlkYXRlT25seSA/IChfcG9zaXRpb25pbmcucmVzZXRNYXNrU2V0LmNhbGwoaW5wdXRtYXNrLCAhMCksIFxuICAgICAgICAgICAgbWFza3NldC52YWxpZFBvc2l0aW9ucyA9ICQuZXh0ZW5kKCEwLCB7fSwgcG9zaXRpb25zQ2xvbmUpKSA6IHRyYWNrYmFja1Bvc2l0aW9ucy5jYWxsKGlucHV0bWFzaywgdm9pZCAwLCBtYXNrUG9zLCAhMCk7XG4gICAgICAgICAgICB2YXIgZW5kUmVzdWx0ID0gcHJvY2Vzc0NvbW1hbmRPYmplY3QocmVzdWx0KTtcbiAgICAgICAgICAgIHJldHVybiBlbmRSZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcG9zaXRpb25DYW5NYXRjaERlZmluaXRpb24ocG9zLCB0ZXN0RGVmaW5pdGlvbiwgb3B0cykge1xuICAgICAgICAgICAgZm9yICh2YXIgaW5wdXRtYXNrID0gdGhpcywgbWFza3NldCA9IHRoaXMubWFza3NldCwgdmFsaWQgPSAhMSwgdGVzdHMgPSBfdmFsaWRhdGlvblRlc3RzLmdldFRlc3RzLmNhbGwodGhpcywgcG9zKSwgdG5keCA9IDA7IHRuZHggPCB0ZXN0cy5sZW5ndGg7IHRuZHgrKykge1xuICAgICAgICAgICAgICAgIGlmICh0ZXN0c1t0bmR4XS5tYXRjaCAmJiAoISh0ZXN0c1t0bmR4XS5tYXRjaC5uYXRpdmVEZWYgIT09IHRlc3REZWZpbml0aW9uLm1hdGNoW29wdHMuc2hpZnRQb3NpdGlvbnMgPyBcImRlZlwiIDogXCJuYXRpdmVEZWZcIl0gfHwgb3B0cy5zaGlmdFBvc2l0aW9ucyAmJiB0ZXN0RGVmaW5pdGlvbi5tYXRjaC5zdGF0aWMpIHx8IHRlc3RzW3RuZHhdLm1hdGNoLm5hdGl2ZURlZiA9PT0gdGVzdERlZmluaXRpb24ubWF0Y2gubmF0aXZlRGVmKSkge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZCA9ICEwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRlc3RzW3RuZHhdLm1hdGNoICYmIHRlc3RzW3RuZHhdLm1hdGNoLmRlZiA9PT0gdGVzdERlZmluaXRpb24ubWF0Y2gubmF0aXZlRGVmKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkID0gdm9pZCAwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gITEgPT09IHZhbGlkICYmIHZvaWQgMCAhPT0gbWFza3NldC5qaXRPZmZzZXRbcG9zXSAmJiAodmFsaWQgPSBwb3NpdGlvbkNhbk1hdGNoRGVmaW5pdGlvbi5jYWxsKHRoaXMsIHBvcyArIG1hc2tzZXQuaml0T2Zmc2V0W3Bvc10sIHRlc3REZWZpbml0aW9uLCBvcHRzKSksIFxuICAgICAgICAgICAgdmFsaWQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcmVmcmVzaEZyb21CdWZmZXIoc3RhcnQsIGVuZCwgYnVmZmVyKSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcywgbWFza3NldCA9IHRoaXMubWFza3NldCwgb3B0cyA9IHRoaXMub3B0cywgJCA9IHRoaXMuZGVwZW5kZW5jeUxpYiwgZWwgPSB0aGlzLmVsLCBpLCBwLCBza2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyID0gb3B0cy5za2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyLCBiZmZyID0gdGhpcy5pc1JUTCA/IGJ1ZmZlci5zbGljZSgpLnJldmVyc2UoKSA6IGJ1ZmZlcjtcbiAgICAgICAgICAgIGlmIChvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIgPSBcIlwiLCAhMCA9PT0gc3RhcnQpIF9wb3NpdGlvbmluZy5yZXNldE1hc2tTZXQuY2FsbCh0aGlzKSwgXG4gICAgICAgICAgICBtYXNrc2V0LnRlc3RzID0ge30sIHN0YXJ0ID0gMCwgZW5kID0gYnVmZmVyLmxlbmd0aCwgcCA9IF9wb3NpdGlvbmluZy5kZXRlcm1pbmVOZXdDYXJldFBvc2l0aW9uLmNhbGwodGhpcywge1xuICAgICAgICAgICAgICAgIGJlZ2luOiAwLFxuICAgICAgICAgICAgICAgIGVuZDogMFxuICAgICAgICAgICAgfSwgITEpLmJlZ2luOyBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSBkZWxldGUgbWFza3NldC52YWxpZFBvc2l0aW9uc1tpXTtcbiAgICAgICAgICAgICAgICBwID0gc3RhcnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIga2V5cHJlc3MgPSBuZXcgJC5FdmVudChcImtleXByZXNzXCIpO1xuICAgICAgICAgICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGtleXByZXNzLndoaWNoID0gYmZmcltpXS50b1N0cmluZygpLmNoYXJDb2RlQXQoMCksIHRoaXMuaWdub3JhYmxlID0gITE7XG4gICAgICAgICAgICAgICAgdmFyIHZhbFJlc3VsdCA9IF9ldmVudGhhbmRsZXJzLkV2ZW50SGFuZGxlcnMua2V5cHJlc3NFdmVudC5jYWxsKGVsLCBrZXlwcmVzcywgITAsICExLCAhMSwgcCk7XG4gICAgICAgICAgICAgICAgITEgIT09IHZhbFJlc3VsdCAmJiAocCA9IHZhbFJlc3VsdC5mb3J3YXJkUG9zaXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3B0cy5za2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyID0gc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlcjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiB0cmFja2JhY2tQb3NpdGlvbnMob3JpZ2luYWxQb3MsIG5ld1BvcywgZmlsbE9ubHkpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCBtYXNrc2V0ID0gdGhpcy5tYXNrc2V0LCAkID0gdGhpcy5kZXBlbmRlbmN5TGliO1xuICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gb3JpZ2luYWxQb3MpIGZvciAob3JpZ2luYWxQb3MgPSBuZXdQb3MgLSAxOyAwIDwgb3JpZ2luYWxQb3MgJiYgIW1hc2tzZXQudmFsaWRQb3NpdGlvbnNbb3JpZ2luYWxQb3NdOyBvcmlnaW5hbFBvcy0tKSA7XG4gICAgICAgICAgICBmb3IgKHZhciBwcyA9IG9yaWdpbmFsUG9zOyBwcyA8IG5ld1BvczsgcHMrKykgaWYgKHZvaWQgMCA9PT0gbWFza3NldC52YWxpZFBvc2l0aW9uc1twc10gJiYgIV9wb3NpdGlvbmluZy5pc01hc2suY2FsbCh0aGlzLCBwcywgITApKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZwID0gMCA9PSBwcyA/IF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdC5jYWxsKHRoaXMsIHBzKSA6IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcHMgLSAxXTtcbiAgICAgICAgICAgICAgICBpZiAodnApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRlc3RzID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0cy5jYWxsKHRoaXMsIHBzKS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICBcIlwiID09PSB0ZXN0c1t0ZXN0cy5sZW5ndGggLSAxXS5tYXRjaC5kZWYgJiYgdGVzdHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBiZXN0TWF0Y2ggPSBfdmFsaWRhdGlvblRlc3RzLmRldGVybWluZVRlc3RUZW1wbGF0ZS5jYWxsKHRoaXMsIHBzLCB0ZXN0cyksIG5wO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYmVzdE1hdGNoICYmICghMCAhPT0gYmVzdE1hdGNoLm1hdGNoLmppdCB8fCBcIm1hc3RlclwiID09PSBiZXN0TWF0Y2gubWF0Y2gubmV3QmxvY2tNYXJrZXIgJiYgKG5wID0gbWFza3NldC52YWxpZFBvc2l0aW9uc1twcyArIDFdKSAmJiAhMCA9PT0gbnAubWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyKSAmJiAoYmVzdE1hdGNoID0gJC5leHRlbmQoe30sIGJlc3RNYXRjaCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQ6IF92YWxpZGF0aW9uVGVzdHMuZ2V0UGxhY2Vob2xkZXIuY2FsbCh0aGlzLCBwcywgYmVzdE1hdGNoLm1hdGNoLCAhMCkgfHwgYmVzdE1hdGNoLm1hdGNoLmRlZlxuICAgICAgICAgICAgICAgICAgICB9KSwgYmVzdE1hdGNoLmdlbmVyYXRlZElucHV0ID0gITAsIHJldmFsaWRhdGVNYXNrLmNhbGwodGhpcywgcHMsIGJlc3RNYXRjaCwgITApLCBcbiAgICAgICAgICAgICAgICAgICAgITAgIT09IGZpbGxPbmx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN2cElucHV0ID0gbWFza3NldC52YWxpZFBvc2l0aW9uc1tuZXdQb3NdLmlucHV0O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbbmV3UG9zXSA9IHZvaWQgMCwgaXNWYWxpZC5jYWxsKHRoaXMsIG5ld1BvcywgY3ZwSW5wdXQsICEwLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcmV2YWxpZGF0ZU1hc2socG9zLCB2YWxpZFRlc3QsIGZyb21Jc1ZhbGlkLCB2YWxpZGF0ZWRQb3MpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCBtYXNrc2V0ID0gdGhpcy5tYXNrc2V0LCBvcHRzID0gdGhpcy5vcHRzLCAkID0gdGhpcy5kZXBlbmRlbmN5TGliO1xuICAgICAgICAgICAgZnVuY3Rpb24gSXNFbmNsb3NlZFN0YXRpYyhwb3MsIHZhbGlkcywgc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBvc01hdGNoID0gdmFsaWRzW3Bvc107XG4gICAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gcG9zTWF0Y2ggfHwgITAgIT09IHBvc01hdGNoLm1hdGNoLnN0YXRpYyB8fCAhMCA9PT0gcG9zTWF0Y2gubWF0Y2gub3B0aW9uYWxpdHkgfHwgdm9pZCAwICE9PSB2YWxpZHNbMF0gJiYgdm9pZCAwICE9PSB2YWxpZHNbMF0uYWx0ZXJuYXRpb24pIHJldHVybiAhMTtcbiAgICAgICAgICAgICAgICB2YXIgcHJldk1hdGNoID0gc2VsZWN0aW9uLmJlZ2luIDw9IHBvcyAtIDEgPyB2YWxpZHNbcG9zIC0gMV0gJiYgITAgPT09IHZhbGlkc1twb3MgLSAxXS5tYXRjaC5zdGF0aWMgJiYgdmFsaWRzW3BvcyAtIDFdIDogdmFsaWRzW3BvcyAtIDFdLCBuZXh0TWF0Y2ggPSBzZWxlY3Rpb24uZW5kID4gcG9zICsgMSA/IHZhbGlkc1twb3MgKyAxXSAmJiAhMCA9PT0gdmFsaWRzW3BvcyArIDFdLm1hdGNoLnN0YXRpYyAmJiB2YWxpZHNbcG9zICsgMV0gOiB2YWxpZHNbcG9zICsgMV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXZNYXRjaCAmJiBuZXh0TWF0Y2g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgb2Zmc2V0ID0gMCwgYmVnaW4gPSB2b2lkIDAgIT09IHBvcy5iZWdpbiA/IHBvcy5iZWdpbiA6IHBvcywgZW5kID0gdm9pZCAwICE9PSBwb3MuZW5kID8gcG9zLmVuZCA6IHBvcztcbiAgICAgICAgICAgIGlmIChwb3MuYmVnaW4gPiBwb3MuZW5kICYmIChiZWdpbiA9IHBvcy5lbmQsIGVuZCA9IHBvcy5iZWdpbiksIHZhbGlkYXRlZFBvcyA9IHZvaWQgMCAhPT0gdmFsaWRhdGVkUG9zID8gdmFsaWRhdGVkUG9zIDogYmVnaW4sIFxuICAgICAgICAgICAgYmVnaW4gIT09IGVuZCB8fCBvcHRzLmluc2VydE1vZGUgJiYgdm9pZCAwICE9PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3ZhbGlkYXRlZFBvc10gJiYgdm9pZCAwID09PSBmcm9tSXNWYWxpZCB8fCB2b2lkIDAgPT09IHZhbGlkVGVzdCkge1xuICAgICAgICAgICAgICAgIHZhciBwb3NpdGlvbnNDbG9uZSA9ICQuZXh0ZW5kKCEwLCB7fSwgbWFza3NldC52YWxpZFBvc2l0aW9ucyksIGx2cCA9IF9wb3NpdGlvbmluZy5nZXRMYXN0VmFsaWRQb3NpdGlvbi5jYWxsKHRoaXMsIHZvaWQgMCwgITApLCBpO1xuICAgICAgICAgICAgICAgIGZvciAobWFza3NldC5wID0gYmVnaW4sIGkgPSBsdnA7IGJlZ2luIDw9IGk7IGktLSkgZGVsZXRlIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbaV0sIFxuICAgICAgICAgICAgICAgIHZvaWQgMCA9PT0gdmFsaWRUZXN0ICYmIGRlbGV0ZSBtYXNrc2V0LnRlc3RzW2kgKyAxXTtcbiAgICAgICAgICAgICAgICB2YXIgdmFsaWQgPSAhMCwgaiA9IHZhbGlkYXRlZFBvcywgcG9zTWF0Y2ggPSBqLCB0LCBjYW5NYXRjaDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhbGlkVGVzdCAmJiAobWFza3NldC52YWxpZFBvc2l0aW9uc1t2YWxpZGF0ZWRQb3NdID0gJC5leHRlbmQoITAsIHt9LCB2YWxpZFRlc3QpLCBcbiAgICAgICAgICAgICAgICBwb3NNYXRjaCsrLCBqKyspLCBpID0gdmFsaWRUZXN0ID8gZW5kIDogZW5kIC0gMTsgaSA8PSBsdnA7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodm9pZCAwICE9PSAodCA9IHBvc2l0aW9uc0Nsb25lW2ldKSAmJiAhMCAhPT0gdC5nZW5lcmF0ZWRJbnB1dCAmJiAoZW5kIDw9IGkgfHwgYmVnaW4gPD0gaSAmJiBJc0VuY2xvc2VkU3RhdGljKGksIHBvc2l0aW9uc0Nsb25lLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogYmVnaW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IGVuZFxuICAgICAgICAgICAgICAgICAgICB9KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoO1wiXCIgIT09IF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdC5jYWxsKHRoaXMsIHBvc01hdGNoKS5tYXRjaC5kZWY7ICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghMSAhPT0gKGNhbk1hdGNoID0gcG9zaXRpb25DYW5NYXRjaERlZmluaXRpb24uY2FsbCh0aGlzLCBwb3NNYXRjaCwgdCwgb3B0cykpIHx8IFwiK1wiID09PSB0Lm1hdGNoLmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIitcIiA9PT0gdC5tYXRjaC5kZWYgJiYgX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKHRoaXMsICEwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGlzVmFsaWQuY2FsbCh0aGlzLCBwb3NNYXRjaCwgdC5pbnB1dCwgXCIrXCIgIT09IHQubWF0Y2guZGVmLCBcIitcIiAhPT0gdC5tYXRjaC5kZWYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsaWQgPSAhMSAhPT0gcmVzdWx0LCBqID0gKHJlc3VsdC5wb3MgfHwgcG9zTWF0Y2gpICsgMSwgIXZhbGlkICYmIGNhbk1hdGNoKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgdmFsaWQgPSAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCAwID09PSB2YWxpZFRlc3QgJiYgdC5tYXRjaC5zdGF0aWMgJiYgaSA9PT0gcG9zLmJlZ2luICYmIG9mZnNldCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF2YWxpZCAmJiBwb3NNYXRjaCA+IG1hc2tzZXQubWFza0xlbmd0aCkgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zTWF0Y2grKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIFwiXCIgPT0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0LmNhbGwodGhpcywgcG9zTWF0Y2gpLm1hdGNoLmRlZiAmJiAodmFsaWQgPSAhMSksIHBvc01hdGNoID0gajtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIXZhbGlkKSBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF2YWxpZCkgcmV0dXJuIG1hc2tzZXQudmFsaWRQb3NpdGlvbnMgPSAkLmV4dGVuZCghMCwge30sIHBvc2l0aW9uc0Nsb25lKSwgX3Bvc2l0aW9uaW5nLnJlc2V0TWFza1NldC5jYWxsKHRoaXMsICEwKSwgXG4gICAgICAgICAgICAgICAgITE7XG4gICAgICAgICAgICB9IGVsc2UgdmFsaWRUZXN0ICYmIF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdC5jYWxsKHRoaXMsIHZhbGlkYXRlZFBvcykubWF0Y2guY2QgPT09IHZhbGlkVGVzdC5tYXRjaC5jZCAmJiAobWFza3NldC52YWxpZFBvc2l0aW9uc1t2YWxpZGF0ZWRQb3NdID0gJC5leHRlbmQoITAsIHt9LCB2YWxpZFRlc3QpKTtcbiAgICAgICAgICAgIHJldHVybiBfcG9zaXRpb25pbmcucmVzZXRNYXNrU2V0LmNhbGwodGhpcywgITApLCBvZmZzZXQ7XG4gICAgICAgIH1cbiAgICB9LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICAgICAgICAgICAgdmFsdWU6ICEwXG4gICAgICAgIH0pLCBleHBvcnRzLmFwcGx5SW5wdXRWYWx1ZSA9IGFwcGx5SW5wdXRWYWx1ZSwgZXhwb3J0cy5jbGVhck9wdGlvbmFsVGFpbCA9IGNsZWFyT3B0aW9uYWxUYWlsLCBcbiAgICAgICAgZXhwb3J0cy5jaGVja1ZhbCA9IGNoZWNrVmFsLCBleHBvcnRzLkhhbmRsZU5hdGl2ZVBsYWNlaG9sZGVyID0gSGFuZGxlTmF0aXZlUGxhY2Vob2xkZXIsIFxuICAgICAgICBleHBvcnRzLnVubWFza2VkdmFsdWUgPSB1bm1hc2tlZHZhbHVlLCBleHBvcnRzLndyaXRlQnVmZmVyID0gd3JpdGVCdWZmZXI7XG4gICAgICAgIHZhciBfa2V5Y29kZSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygwKSksIF92YWxpZGF0aW9uVGVzdHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDMpLCBfcG9zaXRpb25pbmcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIpLCBfdmFsaWRhdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oNCksIF9lbnZpcm9ubWVudCA9IF9fd2VicGFja19yZXF1aXJlX18oNyksIF9ldmVudGhhbmRsZXJzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2KTtcbiAgICAgICAgZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHtcbiAgICAgICAgICAgIHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDogb2JqXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGFwcGx5SW5wdXRWYWx1ZShpbnB1dCwgdmFsdWUpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSBpbnB1dCA/IGlucHV0LmlucHV0bWFzayA6IHRoaXMsIG9wdHMgPSBpbnB1dG1hc2sub3B0cztcbiAgICAgICAgICAgIGlucHV0LmlucHV0bWFzay5yZWZyZXNoVmFsdWUgPSAhMSwgXCJmdW5jdGlvblwiID09IHR5cGVvZiBvcHRzLm9uQmVmb3JlTWFzayAmJiAodmFsdWUgPSBvcHRzLm9uQmVmb3JlTWFzay5jYWxsKGlucHV0bWFzaywgdmFsdWUsIG9wdHMpIHx8IHZhbHVlKSwgXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCkuc3BsaXQoXCJcIiksIGNoZWNrVmFsKGlucHV0LCAhMCwgITEsIHZhbHVlKSwgaW5wdXRtYXNrLnVuZG9WYWx1ZSA9IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIiksIFxuICAgICAgICAgICAgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgfHwgb3B0cy5jbGVhckluY29tcGxldGUpICYmIGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKSA9PT0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlclRlbXBsYXRlLmNhbGwoaW5wdXRtYXNrKS5qb2luKFwiXCIpICYmIC0xID09PSBfcG9zaXRpb25pbmcuZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbChpbnB1dG1hc2spICYmIGlucHV0LmlucHV0bWFzay5fdmFsdWVTZXQoXCJcIik7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gY2xlYXJPcHRpb25hbFRhaWwoYnVmZmVyKSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcztcbiAgICAgICAgICAgIGJ1ZmZlci5sZW5ndGggPSAwO1xuICAgICAgICAgICAgZm9yICh2YXIgdGVtcGxhdGUgPSBfdmFsaWRhdGlvblRlc3RzLmdldE1hc2tUZW1wbGF0ZS5jYWxsKHRoaXMsICEwLCAwLCAhMCwgdm9pZCAwLCAhMCksIGxtbnQ7IHZvaWQgMCAhPT0gKGxtbnQgPSB0ZW1wbGF0ZS5zaGlmdCgpKTsgKSBidWZmZXIucHVzaChsbW50KTtcbiAgICAgICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gY2hlY2tWYWwoaW5wdXQsIHdyaXRlT3V0LCBzdHJpY3QsIG5wdHZsLCBpbml0aWF0aW5nRXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSBpbnB1dCA/IGlucHV0LmlucHV0bWFzayA6IHRoaXMsIG1hc2tzZXQgPSBpbnB1dG1hc2subWFza3NldCwgb3B0cyA9IGlucHV0bWFzay5vcHRzLCAkID0gaW5wdXRtYXNrLmRlcGVuZGVuY3lMaWIsIGlucHV0VmFsdWUgPSBucHR2bC5zbGljZSgpLCBjaGFyQ29kZXMgPSBcIlwiLCBpbml0aWFsTmR4ID0gLTEsIHJlc3VsdCA9IHZvaWQgMCwgc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlciA9IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlcjtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGVtcGxhdGVNYXRjaChuZHgsIGNoYXJDb2Rlcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHRhcmdldFRlbXBsYXRlID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRNYXNrVGVtcGxhdGUuY2FsbChpbnB1dG1hc2ssICEwLCAwKS5zbGljZShuZHgsIF9wb3NpdGlvbmluZy5zZWVrTmV4dC5jYWxsKGlucHV0bWFzaywgbmR4KSkuam9pbihcIlwiKS5yZXBsYWNlKC8nL2csIFwiXCIpLCBjaGFyQ29kZU5keCA9IHRhcmdldFRlbXBsYXRlLmluZGV4T2YoY2hhckNvZGVzKTsgMCA8IGNoYXJDb2RlTmR4ICYmIFwiIFwiID09PSB0YXJnZXRUZW1wbGF0ZVtjaGFyQ29kZU5keCAtIDFdOyApIGNoYXJDb2RlTmR4LS07XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gMCA9PT0gY2hhckNvZGVOZHggJiYgIV9wb3NpdGlvbmluZy5pc01hc2suY2FsbChpbnB1dG1hc2ssIG5keCkgJiYgKF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdC5jYWxsKGlucHV0bWFzaywgbmR4KS5tYXRjaC5uYXRpdmVEZWYgPT09IGNoYXJDb2Rlcy5jaGFyQXQoMCkgfHwgITAgPT09IF92YWxpZGF0aW9uVGVzdHMuZ2V0VGVzdC5jYWxsKGlucHV0bWFzaywgbmR4KS5tYXRjaC5zdGF0aWMgJiYgX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0LmNhbGwoaW5wdXRtYXNrLCBuZHgpLm1hdGNoLm5hdGl2ZURlZiA9PT0gXCInXCIgKyBjaGFyQ29kZXMuY2hhckF0KDApIHx8IFwiIFwiID09PSBfdmFsaWRhdGlvblRlc3RzLmdldFRlc3QuY2FsbChpbnB1dG1hc2ssIG5keCkubWF0Y2gubmF0aXZlRGVmICYmIChfdmFsaWRhdGlvblRlc3RzLmdldFRlc3QuY2FsbChpbnB1dG1hc2ssIG5keCArIDEpLm1hdGNoLm5hdGl2ZURlZiA9PT0gY2hhckNvZGVzLmNoYXJBdCgwKSB8fCAhMCA9PT0gX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0LmNhbGwoaW5wdXRtYXNrLCBuZHggKyAxKS5tYXRjaC5zdGF0aWMgJiYgX3ZhbGlkYXRpb25UZXN0cy5nZXRUZXN0LmNhbGwoaW5wdXRtYXNrLCBuZHggKyAxKS5tYXRjaC5uYXRpdmVEZWYgPT09IFwiJ1wiICsgY2hhckNvZGVzLmNoYXJBdCgwKSkpO1xuICAgICAgICAgICAgICAgIGlmICghbWF0Y2ggJiYgMCA8IGNoYXJDb2RlTmR4ICYmICFfcG9zaXRpb25pbmcuaXNNYXNrLmNhbGwoaW5wdXRtYXNrLCBuZHgsICExLCAhMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRQb3MgPSBfcG9zaXRpb25pbmcuc2Vla05leHQuY2FsbChpbnB1dG1hc2ssIG5keCk7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0bWFzay5jYXJldFBvcy5iZWdpbiA8IG5leHRQb3MgJiYgKGlucHV0bWFzay5jYXJldFBvcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiBuZXh0UG9zXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIgPSBcIlwiLCBfcG9zaXRpb25pbmcucmVzZXRNYXNrU2V0LmNhbGwoaW5wdXRtYXNrKSwgXG4gICAgICAgICAgICBtYXNrc2V0LnRlc3RzID0ge30sIGluaXRpYWxOZHggPSBvcHRzLnJhZGl4UG9pbnQgPyBfcG9zaXRpb25pbmcuZGV0ZXJtaW5lTmV3Q2FyZXRQb3NpdGlvbi5jYWxsKGlucHV0bWFzaywge1xuICAgICAgICAgICAgICAgIGJlZ2luOiAwLFxuICAgICAgICAgICAgICAgIGVuZDogMFxuICAgICAgICAgICAgfSkuYmVnaW4gOiAwLCBtYXNrc2V0LnAgPSBpbml0aWFsTmR4LCBpbnB1dG1hc2suY2FyZXRQb3MgPSB7XG4gICAgICAgICAgICAgICAgYmVnaW46IGluaXRpYWxOZHhcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgc3RhdGljTWF0Y2hlcyA9IFtdLCBwcmV2Q2FyZXRQb3MgPSBpbnB1dG1hc2suY2FyZXRQb3M7XG4gICAgICAgICAgICBpZiAoaW5wdXRWYWx1ZS5mb3JFYWNoKGZ1bmN0aW9uKGNoYXJDb2RlLCBuZHgpIHtcbiAgICAgICAgICAgICAgICBpZiAodm9pZCAwICE9PSBjaGFyQ29kZSkgaWYgKHZvaWQgMCA9PT0gbWFza3NldC52YWxpZFBvc2l0aW9uc1tuZHhdICYmIGlucHV0VmFsdWVbbmR4XSA9PT0gX3ZhbGlkYXRpb25UZXN0cy5nZXRQbGFjZWhvbGRlci5jYWxsKGlucHV0bWFzaywgbmR4KSAmJiBfcG9zaXRpb25pbmcuaXNNYXNrLmNhbGwoaW5wdXRtYXNrLCBuZHgsICEwKSAmJiAhMSA9PT0gX3ZhbGlkYXRpb24uaXNWYWxpZC5jYWxsKGlucHV0bWFzaywgbmR4LCBpbnB1dFZhbHVlW25keF0sICEwLCB2b2lkIDAsIHZvaWQgMCwgITApKSBtYXNrc2V0LnArKzsgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBrZXlwcmVzcyA9IG5ldyAkLkV2ZW50KFwiX2NoZWNrdmFsXCIpO1xuICAgICAgICAgICAgICAgICAgICBrZXlwcmVzcy53aGljaCA9IGNoYXJDb2RlLnRvU3RyaW5nKCkuY2hhckNvZGVBdCgwKSwgY2hhckNvZGVzICs9IGNoYXJDb2RlO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbHZwID0gX3Bvc2l0aW9uaW5nLmdldExhc3RWYWxpZFBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrLCB2b2lkIDAsICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaXNUZW1wbGF0ZU1hdGNoKGluaXRpYWxOZHgsIGNoYXJDb2RlcykgPyByZXN1bHQgPSBfZXZlbnRoYW5kbGVycy5FdmVudEhhbmRsZXJzLmtleXByZXNzRXZlbnQuY2FsbChpbnB1dCB8fCBpbnB1dG1hc2ssIGtleXByZXNzLCAhMCwgITEsIHN0cmljdCwgbHZwICsgMSkgOiAocmVzdWx0ID0gX2V2ZW50aGFuZGxlcnMuRXZlbnRIYW5kbGVycy5rZXlwcmVzc0V2ZW50LmNhbGwoaW5wdXQgfHwgaW5wdXRtYXNrLCBrZXlwcmVzcywgITAsICExLCBzdHJpY3QsIGlucHV0bWFzay5jYXJldFBvcy5iZWdpbiksIFxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgJiYgKGluaXRpYWxOZHggPSBpbnB1dG1hc2suY2FyZXRQb3MuYmVnaW4gKyAxLCBjaGFyQ29kZXMgPSBcIlwiKSksIHJlc3VsdCA/ICh2b2lkIDAgIT09IHJlc3VsdC5wb3MgJiYgbWFza3NldC52YWxpZFBvc2l0aW9uc1tyZXN1bHQucG9zXSAmJiAhMCA9PT0gbWFza3NldC52YWxpZFBvc2l0aW9uc1tyZXN1bHQucG9zXS5tYXRjaC5zdGF0aWMgJiYgdm9pZCAwID09PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Jlc3VsdC5wb3NdLmFsdGVybmF0aW9uICYmIChzdGF0aWNNYXRjaGVzLnB1c2gocmVzdWx0LnBvcyksIFxuICAgICAgICAgICAgICAgICAgICBpbnB1dG1hc2suaXNSVEwgfHwgKHJlc3VsdC5mb3J3YXJkUG9zaXRpb24gPSByZXN1bHQucG9zICsgMSkpLCB3cml0ZUJ1ZmZlci5jYWxsKGlucHV0bWFzaywgdm9pZCAwLCBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKSwgcmVzdWx0LmZvcndhcmRQb3NpdGlvbiwga2V5cHJlc3MsICExKSwgXG4gICAgICAgICAgICAgICAgICAgIGlucHV0bWFzay5jYXJldFBvcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiByZXN1bHQuZm9yd2FyZFBvc2l0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiByZXN1bHQuZm9yd2FyZFBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIH0sIHByZXZDYXJldFBvcyA9IGlucHV0bWFzay5jYXJldFBvcykgOiBpbnB1dG1hc2suY2FyZXRQb3MgPSBwcmV2Q2FyZXRQb3M7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSksIDAgPCBzdGF0aWNNYXRjaGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHZhciBzbmR4LCB2YWxpZFBvcywgbmV4dFZhbGlkID0gX3Bvc2l0aW9uaW5nLnNlZWtOZXh0LmNhbGwoaW5wdXRtYXNrLCAtMSwgdm9pZCAwLCAhMSk7XG4gICAgICAgICAgICAgICAgaWYgKCFfdmFsaWRhdGlvbi5pc0NvbXBsZXRlLmNhbGwoaW5wdXRtYXNrLCBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKSkgJiYgc3RhdGljTWF0Y2hlcy5sZW5ndGggPD0gbmV4dFZhbGlkIHx8IF92YWxpZGF0aW9uLmlzQ29tcGxldGUuY2FsbChpbnB1dG1hc2ssIF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spKSAmJiAwIDwgc3RhdGljTWF0Y2hlcy5sZW5ndGggJiYgc3RhdGljTWF0Y2hlcy5sZW5ndGggIT09IG5leHRWYWxpZCAmJiAwID09PSBzdGF0aWNNYXRjaGVzWzBdKSBmb3IgKHZhciBuZXh0U25keCA9IG5leHRWYWxpZDsgdm9pZCAwICE9PSAoc25keCA9IHN0YXRpY01hdGNoZXMuc2hpZnQoKSk7ICkge1xuICAgICAgICAgICAgICAgICAgICB2YXIga2V5cHJlc3MgPSBuZXcgJC5FdmVudChcIl9jaGVja3ZhbFwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbGlkUG9zID0gbWFza3NldC52YWxpZFBvc2l0aW9uc1tzbmR4XSwgdmFsaWRQb3MuZ2VuZXJhdGVkSW5wdXQgPSAhMCwga2V5cHJlc3Mud2hpY2ggPSB2YWxpZFBvcy5pbnB1dC5jaGFyQ29kZUF0KDApLCBcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gX2V2ZW50aGFuZGxlcnMuRXZlbnRIYW5kbGVycy5rZXlwcmVzc0V2ZW50LmNhbGwoaW5wdXQsIGtleXByZXNzLCAhMCwgITEsIHN0cmljdCwgbmV4dFNuZHgpLCBcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICYmIHZvaWQgMCAhPT0gcmVzdWx0LnBvcyAmJiByZXN1bHQucG9zICE9PSBzbmR4ICYmIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcmVzdWx0LnBvc10gJiYgITAgPT09IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcmVzdWx0LnBvc10ubWF0Y2guc3RhdGljKSBzdGF0aWNNYXRjaGVzLnB1c2gocmVzdWx0LnBvcyk7IGVsc2UgaWYgKCFyZXN1bHQpIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBuZXh0U25keCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdyaXRlT3V0ICYmIHdyaXRlQnVmZmVyLmNhbGwoaW5wdXRtYXNrLCBpbnB1dCwgX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzayksIHJlc3VsdCA/IHJlc3VsdC5mb3J3YXJkUG9zaXRpb24gOiBpbnB1dG1hc2suY2FyZXRQb3MuYmVnaW4sIGluaXRpYXRpbmdFdmVudCB8fCBuZXcgJC5FdmVudChcImNoZWNrdmFsXCIpLCBpbml0aWF0aW5nRXZlbnQgJiYgXCJpbnB1dFwiID09PSBpbml0aWF0aW5nRXZlbnQudHlwZSAmJiBpbnB1dG1hc2sudW5kb1ZhbHVlICE9PSBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKS5qb2luKFwiXCIpKSwgXG4gICAgICAgICAgICBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIgPSBza2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIEhhbmRsZU5hdGl2ZVBsYWNlaG9sZGVyKG5wdCwgdmFsdWUpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSBucHQgPyBucHQuaW5wdXRtYXNrIDogdGhpcztcbiAgICAgICAgICAgIGlmIChfZW52aXJvbm1lbnQuaWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobnB0LmlucHV0bWFzay5fdmFsdWVHZXQoKSAhPT0gdmFsdWUgJiYgKG5wdC5wbGFjZWhvbGRlciAhPT0gdmFsdWUgfHwgXCJcIiA9PT0gbnB0LnBsYWNlaG9sZGVyKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykuc2xpY2UoKSwgbnB0VmFsdWUgPSBucHQuaW5wdXRtYXNrLl92YWx1ZUdldCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobnB0VmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbHZwID0gX3Bvc2l0aW9uaW5nLmdldExhc3RWYWxpZFBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC0xID09PSBsdnAgJiYgbnB0VmFsdWUgPT09IF9wb3NpdGlvbmluZy5nZXRCdWZmZXJUZW1wbGF0ZS5jYWxsKGlucHV0bWFzaykuam9pbihcIlwiKSA/IGJ1ZmZlciA9IFtdIDogLTEgIT09IGx2cCAmJiBjbGVhck9wdGlvbmFsVGFpbC5jYWxsKGlucHV0bWFzaywgYnVmZmVyKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICB3cml0ZUJ1ZmZlcihucHQsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgbnB0LnBsYWNlaG9sZGVyICE9PSB2YWx1ZSAmJiAobnB0LnBsYWNlaG9sZGVyID0gdmFsdWUsIFwiXCIgPT09IG5wdC5wbGFjZWhvbGRlciAmJiBucHQucmVtb3ZlQXR0cmlidXRlKFwicGxhY2Vob2xkZXJcIikpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHVubWFza2VkdmFsdWUoaW5wdXQpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSBpbnB1dCA/IGlucHV0LmlucHV0bWFzayA6IHRoaXMsIG9wdHMgPSBpbnB1dG1hc2sub3B0cywgbWFza3NldCA9IGlucHV0bWFzay5tYXNrc2V0O1xuICAgICAgICAgICAgaWYgKGlucHV0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gaW5wdXQuaW5wdXRtYXNrKSByZXR1cm4gaW5wdXQudmFsdWU7XG4gICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrICYmIGlucHV0LmlucHV0bWFzay5yZWZyZXNoVmFsdWUgJiYgYXBwbHlJbnB1dFZhbHVlKGlucHV0LCBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCEwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgdW1WYWx1ZSA9IFtdLCB2cHMgPSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zO1xuICAgICAgICAgICAgZm9yICh2YXIgcG5keCBpbiB2cHMpIHZwc1twbmR4XSAmJiB2cHNbcG5keF0ubWF0Y2ggJiYgKDEgIT0gdnBzW3BuZHhdLm1hdGNoLnN0YXRpYyB8fCBBcnJheS5pc0FycmF5KG1hc2tzZXQubWV0YWRhdGEpICYmICEwICE9PSB2cHNbcG5keF0uZ2VuZXJhdGVkSW5wdXQpICYmIHVtVmFsdWUucHVzaCh2cHNbcG5keF0uaW5wdXQpO1xuICAgICAgICAgICAgdmFyIHVubWFza2VkVmFsdWUgPSAwID09PSB1bVZhbHVlLmxlbmd0aCA/IFwiXCIgOiAoaW5wdXRtYXNrLmlzUlRMID8gdW1WYWx1ZS5yZXZlcnNlKCkgOiB1bVZhbHVlKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgaWYgKFwiZnVuY3Rpb25cIiA9PSB0eXBlb2Ygb3B0cy5vblVuTWFzaykge1xuICAgICAgICAgICAgICAgIHZhciBidWZmZXJWYWx1ZSA9IChpbnB1dG1hc2suaXNSVEwgPyBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKS5zbGljZSgpLnJldmVyc2UoKSA6IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgIHVubWFza2VkVmFsdWUgPSBvcHRzLm9uVW5NYXNrLmNhbGwoaW5wdXRtYXNrLCBidWZmZXJWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdW5tYXNrZWRWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiB3cml0ZUJ1ZmZlcihpbnB1dCwgYnVmZmVyLCBjYXJldFBvcywgZXZlbnQsIHRyaWdnZXJFdmVudHMpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSBpbnB1dCA/IGlucHV0LmlucHV0bWFzayA6IHRoaXMsIG9wdHMgPSBpbnB1dG1hc2sub3B0cywgJCA9IGlucHV0bWFzay5kZXBlbmRlbmN5TGliO1xuICAgICAgICAgICAgaWYgKGV2ZW50ICYmIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2Ygb3B0cy5vbkJlZm9yZVdyaXRlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IG9wdHMub25CZWZvcmVXcml0ZS5jYWxsKGlucHV0bWFzaywgZXZlbnQsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpO1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5yZWZyZXNoRnJvbUJ1ZmZlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlZnJlc2ggPSByZXN1bHQucmVmcmVzaEZyb21CdWZmZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdmFsaWRhdGlvbi5yZWZyZXNoRnJvbUJ1ZmZlci5jYWxsKGlucHV0bWFzaywgITAgPT09IHJlZnJlc2ggPyByZWZyZXNoIDogcmVmcmVzaC5zdGFydCwgcmVmcmVzaC5lbmQsIHJlc3VsdC5idWZmZXIgfHwgYnVmZmVyKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBidWZmZXIgPSBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdm9pZCAwICE9PSBjYXJldFBvcyAmJiAoY2FyZXRQb3MgPSB2b2lkIDAgIT09IHJlc3VsdC5jYXJldCA/IHJlc3VsdC5jYXJldCA6IGNhcmV0UG9zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodm9pZCAwICE9PSBpbnB1dCAmJiAoaW5wdXQuaW5wdXRtYXNrLl92YWx1ZVNldChidWZmZXIuam9pbihcIlwiKSksIHZvaWQgMCA9PT0gY2FyZXRQb3MgfHwgdm9pZCAwICE9PSBldmVudCAmJiBcImJsdXJcIiA9PT0gZXZlbnQudHlwZSB8fCBfcG9zaXRpb25pbmcuY2FyZXQuY2FsbChpbnB1dG1hc2ssIGlucHV0LCBjYXJldFBvcywgdm9pZCAwLCB2b2lkIDAsIHZvaWQgMCAhPT0gZXZlbnQgJiYgXCJrZXlkb3duXCIgPT09IGV2ZW50LnR5cGUgJiYgKGV2ZW50LmtleUNvZGUgPT09IF9rZXljb2RlLmRlZmF1bHQuREVMRVRFIHx8IGV2ZW50LmtleUNvZGUgPT09IF9rZXljb2RlLmRlZmF1bHQuQkFDS1NQQUNFKSksIFxuICAgICAgICAgICAgITAgPT09IHRyaWdnZXJFdmVudHMpKSB7XG4gICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQoaW5wdXQpLCBucHRWYWwgPSBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCk7XG4gICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLnNraXBJbnB1dEV2ZW50ID0gITAsICRpbnB1dC50cmlnZ2VyKFwiaW5wdXRcIiksIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIG5wdFZhbCA9PT0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlclRlbXBsYXRlLmNhbGwoaW5wdXRtYXNrKS5qb2luKFwiXCIpID8gJGlucHV0LnRyaWdnZXIoXCJjbGVhcmVkXCIpIDogITAgPT09IF92YWxpZGF0aW9uLmlzQ29tcGxldGUuY2FsbChpbnB1dG1hc2ssIGJ1ZmZlcikgJiYgJGlucHV0LnRyaWdnZXIoXCJjb21wbGV0ZVwiKTtcbiAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gICAgICAgICAgICB2YWx1ZTogITBcbiAgICAgICAgfSksIGV4cG9ydHMuRXZlbnRIYW5kbGVycyA9IHZvaWQgMDtcbiAgICAgICAgdmFyIF9wb3NpdGlvbmluZyA9IF9fd2VicGFja19yZXF1aXJlX18oMiksIF9rZXljb2RlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDApKSwgX2Vudmlyb25tZW50ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3KSwgX3ZhbGlkYXRpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQpLCBfaW5wdXRIYW5kbGluZyA9IF9fd2VicGFja19yZXF1aXJlX18oNSksIF92YWxpZGF0aW9uVGVzdHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDMpO1xuICAgICAgICBmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiBvYmpcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIEV2ZW50SGFuZGxlcnMgPSB7XG4gICAgICAgICAgICBrZXlkb3duRXZlbnQ6IGZ1bmN0aW9uIGtleWRvd25FdmVudChlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMuaW5wdXRtYXNrLCBvcHRzID0gaW5wdXRtYXNrLm9wdHMsICQgPSBpbnB1dG1hc2suZGVwZW5kZW5jeUxpYiwgbWFza3NldCA9IGlucHV0bWFzay5tYXNrc2V0LCBpbnB1dCA9IHRoaXMsICRpbnB1dCA9ICQoaW5wdXQpLCBrID0gZS5rZXlDb2RlLCBwb3MgPSBfcG9zaXRpb25pbmcuY2FyZXQuY2FsbChpbnB1dG1hc2ssIGlucHV0KSwga2RSZXN1bHQgPSBvcHRzLm9uS2V5RG93bi5jYWxsKHRoaXMsIGUsIF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLCBwb3MsIG9wdHMpO1xuICAgICAgICAgICAgICAgIGlmICh2b2lkIDAgIT09IGtkUmVzdWx0KSByZXR1cm4ga2RSZXN1bHQ7XG4gICAgICAgICAgICAgICAgaWYgKGsgPT09IF9rZXljb2RlLmRlZmF1bHQuQkFDS1NQQUNFIHx8IGsgPT09IF9rZXljb2RlLmRlZmF1bHQuREVMRVRFIHx8IF9lbnZpcm9ubWVudC5pcGhvbmUgJiYgayA9PT0gX2tleWNvZGUuZGVmYXVsdC5CQUNLU1BBQ0VfU0FGQVJJIHx8IGUuY3RybEtleSAmJiBrID09PSBfa2V5Y29kZS5kZWZhdWx0LlggJiYgIShcIm9uY3V0XCIgaW4gaW5wdXQpKSBlLnByZXZlbnREZWZhdWx0KCksIFxuICAgICAgICAgICAgICAgIF92YWxpZGF0aW9uLmhhbmRsZVJlbW92ZS5jYWxsKGlucHV0bWFzaywgaW5wdXQsIGssIHBvcyksICgwLCBfaW5wdXRIYW5kbGluZy53cml0ZUJ1ZmZlcikoaW5wdXQsIF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2ssICEwKSwgbWFza3NldC5wLCBlLCBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgIT09IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIikpOyBlbHNlIGlmIChrID09PSBfa2V5Y29kZS5kZWZhdWx0LkVORCB8fCBrID09PSBfa2V5Y29kZS5kZWZhdWx0LlBBR0VfRE9XTikge1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjYXJldFBvcyA9IF9wb3NpdGlvbmluZy5zZWVrTmV4dC5jYWxsKGlucHV0bWFzaywgX3Bvc2l0aW9uaW5nLmdldExhc3RWYWxpZFBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrKSk7XG4gICAgICAgICAgICAgICAgICAgIF9wb3NpdGlvbmluZy5jYXJldC5jYWxsKGlucHV0bWFzaywgaW5wdXQsIGUuc2hpZnRLZXkgPyBwb3MuYmVnaW4gOiBjYXJldFBvcywgY2FyZXRQb3MsICEwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgayA9PT0gX2tleWNvZGUuZGVmYXVsdC5IT01FICYmICFlLnNoaWZ0S2V5IHx8IGsgPT09IF9rZXljb2RlLmRlZmF1bHQuUEFHRV9VUCA/IChlLnByZXZlbnREZWZhdWx0KCksIFxuICAgICAgICAgICAgICAgIF9wb3NpdGlvbmluZy5jYXJldC5jYWxsKGlucHV0bWFzaywgaW5wdXQsIDAsIGUuc2hpZnRLZXkgPyBwb3MuYmVnaW4gOiAwLCAhMCkpIDogKG9wdHMudW5kb09uRXNjYXBlICYmIGsgPT09IF9rZXljb2RlLmRlZmF1bHQuRVNDQVBFIHx8IDkwID09PSBrICYmIGUuY3RybEtleSkgJiYgITAgIT09IGUuYWx0S2V5ID8gKCgwLCBcbiAgICAgICAgICAgICAgICBfaW5wdXRIYW5kbGluZy5jaGVja1ZhbCkoaW5wdXQsICEwLCAhMSwgaW5wdXRtYXNrLnVuZG9WYWx1ZS5zcGxpdChcIlwiKSksICRpbnB1dC50cmlnZ2VyKFwiY2xpY2tcIikpIDogITAgPT09IG9wdHMudGFiVGhyb3VnaCAmJiBrID09PSBfa2V5Y29kZS5kZWZhdWx0LlRBQiA/ICEwID09PSBlLnNoaWZ0S2V5ID8gKHBvcy5lbmQgPSBfcG9zaXRpb25pbmcuc2Vla1ByZXZpb3VzLmNhbGwoaW5wdXRtYXNrLCBwb3MuZW5kLCAhMCksIFxuICAgICAgICAgICAgICAgICEwID09PSBfdmFsaWRhdGlvblRlc3RzLmdldFRlc3QuY2FsbChpbnB1dG1hc2ssIHBvcy5lbmQgLSAxKS5tYXRjaC5zdGF0aWMgJiYgcG9zLmVuZC0tLCBcbiAgICAgICAgICAgICAgICBwb3MuYmVnaW4gPSBfcG9zaXRpb25pbmcuc2Vla1ByZXZpb3VzLmNhbGwoaW5wdXRtYXNrLCBwb3MuZW5kLCAhMCksIDAgPD0gcG9zLmJlZ2luICYmIDAgPCBwb3MuZW5kICYmIChlLnByZXZlbnREZWZhdWx0KCksIFxuICAgICAgICAgICAgICAgIF9wb3NpdGlvbmluZy5jYXJldC5jYWxsKGlucHV0bWFzaywgaW5wdXQsIHBvcy5iZWdpbiwgcG9zLmVuZCkpKSA6IChwb3MuYmVnaW4gPSBfcG9zaXRpb25pbmcuc2Vla05leHQuY2FsbChpbnB1dG1hc2ssIHBvcy5iZWdpbiwgITApLCBcbiAgICAgICAgICAgICAgICBwb3MuZW5kID0gX3Bvc2l0aW9uaW5nLnNlZWtOZXh0LmNhbGwoaW5wdXRtYXNrLCBwb3MuYmVnaW4sICEwKSwgcG9zLmVuZCA8IG1hc2tzZXQubWFza0xlbmd0aCAmJiBwb3MuZW5kLS0sIFxuICAgICAgICAgICAgICAgIHBvcy5iZWdpbiA8PSBtYXNrc2V0Lm1hc2tMZW5ndGggJiYgKGUucHJldmVudERlZmF1bHQoKSwgX3Bvc2l0aW9uaW5nLmNhcmV0LmNhbGwoaW5wdXRtYXNrLCBpbnB1dCwgcG9zLmJlZ2luLCBwb3MuZW5kKSkpIDogZS5zaGlmdEtleSB8fCBvcHRzLmluc2VydE1vZGVWaXN1YWwgJiYgITEgPT09IG9wdHMuaW5zZXJ0TW9kZSAmJiAoayA9PT0gX2tleWNvZGUuZGVmYXVsdC5SSUdIVCA/IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjYXJldFBvcyA9IF9wb3NpdGlvbmluZy5jYXJldC5jYWxsKGlucHV0bWFzaywgaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICBfcG9zaXRpb25pbmcuY2FyZXQuY2FsbChpbnB1dG1hc2ssIGlucHV0LCBjYXJldFBvcy5iZWdpbik7XG4gICAgICAgICAgICAgICAgfSwgMCkgOiBrID09PSBfa2V5Y29kZS5kZWZhdWx0LkxFRlQgJiYgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNhcmV0UG9zX2JlZ2luID0gX3Bvc2l0aW9uaW5nLnRyYW5zbGF0ZVBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrLCBpbnB1dC5pbnB1dG1hc2suY2FyZXRQb3MuYmVnaW4pLCBjYXJldFBvc19lbmQgPSBfcG9zaXRpb25pbmcudHJhbnNsYXRlUG9zaXRpb24uY2FsbChpbnB1dG1hc2ssIGlucHV0LmlucHV0bWFzay5jYXJldFBvcy5lbmQpO1xuICAgICAgICAgICAgICAgICAgICBpbnB1dG1hc2suaXNSVEwgPyBfcG9zaXRpb25pbmcuY2FyZXQuY2FsbChpbnB1dG1hc2ssIGlucHV0LCBjYXJldFBvc19iZWdpbiArIChjYXJldFBvc19iZWdpbiA9PT0gbWFza3NldC5tYXNrTGVuZ3RoID8gMCA6IDEpKSA6IF9wb3NpdGlvbmluZy5jYXJldC5jYWxsKGlucHV0bWFzaywgaW5wdXQsIGNhcmV0UG9zX2JlZ2luIC0gKDAgPT09IGNhcmV0UG9zX2JlZ2luID8gMCA6IDEpKTtcbiAgICAgICAgICAgICAgICB9LCAwKSk7XG4gICAgICAgICAgICAgICAgaW5wdXRtYXNrLmlnbm9yYWJsZSA9IG9wdHMuaWdub3JhYmxlcy5pbmNsdWRlcyhrKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBrZXlwcmVzc0V2ZW50OiBmdW5jdGlvbiBrZXlwcmVzc0V2ZW50KGUsIGNoZWNrdmFsLCB3cml0ZU91dCwgc3RyaWN0LCBuZHgpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcy5pbnB1dG1hc2sgfHwgdGhpcywgb3B0cyA9IGlucHV0bWFzay5vcHRzLCAkID0gaW5wdXRtYXNrLmRlcGVuZGVuY3lMaWIsIG1hc2tzZXQgPSBpbnB1dG1hc2subWFza3NldCwgaW5wdXQgPSBpbnB1dG1hc2suZWwsICRpbnB1dCA9ICQoaW5wdXQpLCBrID0gZS53aGljaCB8fCBlLmNoYXJDb2RlIHx8IGUua2V5Q29kZTtcbiAgICAgICAgICAgICAgICBpZiAoISghMCA9PT0gY2hlY2t2YWwgfHwgZS5jdHJsS2V5ICYmIGUuYWx0S2V5KSAmJiAoZS5jdHJsS2V5IHx8IGUubWV0YUtleSB8fCBpbnB1dG1hc2suaWdub3JhYmxlKSkgcmV0dXJuIGsgPT09IF9rZXljb2RlLmRlZmF1bHQuRU5URVIgJiYgaW5wdXRtYXNrLnVuZG9WYWx1ZSAhPT0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykuam9pbihcIlwiKSAmJiAoaW5wdXRtYXNrLnVuZG9WYWx1ZSA9IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIiksIFxuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgICAgIH0sIDApKSwgaW5wdXRtYXNrLnNraXBJbnB1dEV2ZW50ID0gITAsICEwO1xuICAgICAgICAgICAgICAgIGlmIChrKSB7XG4gICAgICAgICAgICAgICAgICAgIDQ0ICE9PSBrICYmIDQ2ICE9PSBrIHx8IDMgIT09IGUubG9jYXRpb24gfHwgXCJcIiA9PT0gb3B0cy5yYWRpeFBvaW50IHx8IChrID0gb3B0cy5yYWRpeFBvaW50LmNoYXJDb2RlQXQoMCkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcG9zID0gY2hlY2t2YWwgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogbmR4LFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBuZHhcbiAgICAgICAgICAgICAgICAgICAgfSA6IF9wb3NpdGlvbmluZy5jYXJldC5jYWxsKGlucHV0bWFzaywgaW5wdXQpLCBmb3J3YXJkUG9zaXRpb24sIGMgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGspO1xuICAgICAgICAgICAgICAgICAgICBtYXNrc2V0LndyaXRlT3V0QnVmZmVyID0gITA7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWxSZXN1bHQgPSBfdmFsaWRhdGlvbi5pc1ZhbGlkLmNhbGwoaW5wdXRtYXNrLCBwb3MsIGMsIHN0cmljdCwgdm9pZCAwLCB2b2lkIDAsIHZvaWQgMCwgY2hlY2t2YWwpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoITEgIT09IHZhbFJlc3VsdCAmJiAoX3Bvc2l0aW9uaW5nLnJlc2V0TWFza1NldC5jYWxsKGlucHV0bWFzaywgITApLCBmb3J3YXJkUG9zaXRpb24gPSB2b2lkIDAgIT09IHZhbFJlc3VsdC5jYXJldCA/IHZhbFJlc3VsdC5jYXJldCA6IF9wb3NpdGlvbmluZy5zZWVrTmV4dC5jYWxsKGlucHV0bWFzaywgdmFsUmVzdWx0LnBvcy5iZWdpbiA/IHZhbFJlc3VsdC5wb3MuYmVnaW4gOiB2YWxSZXN1bHQucG9zKSwgXG4gICAgICAgICAgICAgICAgICAgIG1hc2tzZXQucCA9IGZvcndhcmRQb3NpdGlvbiksIGZvcndhcmRQb3NpdGlvbiA9IG9wdHMubnVtZXJpY0lucHV0ICYmIHZvaWQgMCA9PT0gdmFsUmVzdWx0LmNhcmV0ID8gX3Bvc2l0aW9uaW5nLnNlZWtQcmV2aW91cy5jYWxsKGlucHV0bWFzaywgZm9yd2FyZFBvc2l0aW9uKSA6IGZvcndhcmRQb3NpdGlvbiwgXG4gICAgICAgICAgICAgICAgICAgICExICE9PSB3cml0ZU91dCAmJiAoc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMub25LZXlWYWxpZGF0aW9uLmNhbGwoaW5wdXQsIGssIHZhbFJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDApLCBtYXNrc2V0LndyaXRlT3V0QnVmZmVyICYmICExICE9PSB2YWxSZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzayk7XG4gICAgICAgICAgICAgICAgICAgICAgICAoMCwgX2lucHV0SGFuZGxpbmcud3JpdGVCdWZmZXIpKGlucHV0LCBidWZmZXIsIGZvcndhcmRQb3NpdGlvbiwgZSwgITAgIT09IGNoZWNrdmFsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZS5wcmV2ZW50RGVmYXVsdCgpLCBjaGVja3ZhbCkgcmV0dXJuICExICE9PSB2YWxSZXN1bHQgJiYgKHZhbFJlc3VsdC5mb3J3YXJkUG9zaXRpb24gPSBmb3J3YXJkUG9zaXRpb24pLCBcbiAgICAgICAgICAgICAgICAgICAgdmFsUmVzdWx0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBrZXl1cEV2ZW50OiBmdW5jdGlvbiBrZXl1cEV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcy5pbnB1dG1hc2s7XG4gICAgICAgICAgICAgICAgIWlucHV0bWFzay5pc0NvbXBvc2luZyB8fCBlLmtleUNvZGUgIT09IF9rZXljb2RlLmRlZmF1bHQuS0VZXzIyOSAmJiBlLmtleUNvZGUgIT09IF9rZXljb2RlLmRlZmF1bHQuRU5URVIgfHwgaW5wdXRtYXNrLiRlbC50cmlnZ2VyKFwiaW5wdXRcIik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFzdGVFdmVudDogZnVuY3Rpb24gcGFzdGVFdmVudChlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMuaW5wdXRtYXNrLCBvcHRzID0gaW5wdXRtYXNrLm9wdHMsIGlucHV0ID0gdGhpcywgaW5wdXRWYWx1ZSA9IGlucHV0bWFzay5fdmFsdWVHZXQoITApLCBjYXJldFBvcyA9IF9wb3NpdGlvbmluZy5jYXJldC5jYWxsKGlucHV0bWFzaywgdGhpcyksIHRlbXBWYWx1ZTtcbiAgICAgICAgICAgICAgICBpbnB1dG1hc2suaXNSVEwgJiYgKHRlbXBWYWx1ZSA9IGNhcmV0UG9zLmVuZCwgY2FyZXRQb3MuZW5kID0gY2FyZXRQb3MuYmVnaW4sIGNhcmV0UG9zLmJlZ2luID0gdGVtcFZhbHVlKTtcbiAgICAgICAgICAgICAgICB2YXIgdmFsdWVCZWZvcmVDYXJldCA9IGlucHV0VmFsdWUuc3Vic3RyKDAsIGNhcmV0UG9zLmJlZ2luKSwgdmFsdWVBZnRlckNhcmV0ID0gaW5wdXRWYWx1ZS5zdWJzdHIoY2FyZXRQb3MuZW5kLCBpbnB1dFZhbHVlLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlQmVmb3JlQ2FyZXQgPT0gKGlucHV0bWFzay5pc1JUTCA/IF9wb3NpdGlvbmluZy5nZXRCdWZmZXJUZW1wbGF0ZS5jYWxsKGlucHV0bWFzaykuc2xpY2UoKS5yZXZlcnNlKCkgOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyVGVtcGxhdGUuY2FsbChpbnB1dG1hc2spKS5zbGljZSgwLCBjYXJldFBvcy5iZWdpbikuam9pbihcIlwiKSAmJiAodmFsdWVCZWZvcmVDYXJldCA9IFwiXCIpLCBcbiAgICAgICAgICAgICAgICB2YWx1ZUFmdGVyQ2FyZXQgPT0gKGlucHV0bWFzay5pc1JUTCA/IF9wb3NpdGlvbmluZy5nZXRCdWZmZXJUZW1wbGF0ZS5jYWxsKGlucHV0bWFzaykuc2xpY2UoKS5yZXZlcnNlKCkgOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyVGVtcGxhdGUuY2FsbChpbnB1dG1hc2spKS5zbGljZShjYXJldFBvcy5lbmQpLmpvaW4oXCJcIikgJiYgKHZhbHVlQWZ0ZXJDYXJldCA9IFwiXCIpLCBcbiAgICAgICAgICAgICAgICB3aW5kb3cuY2xpcGJvYXJkRGF0YSAmJiB3aW5kb3cuY2xpcGJvYXJkRGF0YS5nZXREYXRhKSBpbnB1dFZhbHVlID0gdmFsdWVCZWZvcmVDYXJldCArIHdpbmRvdy5jbGlwYm9hcmREYXRhLmdldERhdGEoXCJUZXh0XCIpICsgdmFsdWVBZnRlckNhcmV0OyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFlLmNsaXBib2FyZERhdGEgfHwgIWUuY2xpcGJvYXJkRGF0YS5nZXREYXRhKSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0VmFsdWUgPSB2YWx1ZUJlZm9yZUNhcmV0ICsgZS5jbGlwYm9hcmREYXRhLmdldERhdGEoXCJ0ZXh0L3BsYWluXCIpICsgdmFsdWVBZnRlckNhcmV0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcGFzdGVWYWx1ZSA9IGlucHV0VmFsdWU7XG4gICAgICAgICAgICAgICAgaWYgKFwiZnVuY3Rpb25cIiA9PSB0eXBlb2Ygb3B0cy5vbkJlZm9yZVBhc3RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXN0ZVZhbHVlID0gb3B0cy5vbkJlZm9yZVBhc3RlLmNhbGwoaW5wdXRtYXNrLCBpbnB1dFZhbHVlLCBvcHRzKSwgITEgPT09IHBhc3RlVmFsdWUpIHJldHVybiBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIHBhc3RlVmFsdWUgPSBwYXN0ZVZhbHVlIHx8IGlucHV0VmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiAoMCwgX2lucHV0SGFuZGxpbmcuY2hlY2tWYWwpKHRoaXMsICEwLCAhMSwgcGFzdGVWYWx1ZS50b1N0cmluZygpLnNwbGl0KFwiXCIpLCBlKSwgXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlucHV0RmFsbEJhY2tFdmVudDogZnVuY3Rpb24gaW5wdXRGYWxsQmFja0V2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcy5pbnB1dG1hc2ssIG9wdHMgPSBpbnB1dG1hc2sub3B0cywgJCA9IGlucHV0bWFzay5kZXBlbmRlbmN5TGliO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGllTW9iaWxlSGFuZGxlcihpbnB1dCwgaW5wdXRWYWx1ZSwgY2FyZXRQb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF9lbnZpcm9ubWVudC5pZW1vYmlsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0Q2hhciA9IGlucHV0VmFsdWUucmVwbGFjZShfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKS5qb2luKFwiXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgxID09PSBpbnB1dENoYXIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGl2ID0gaW5wdXRWYWx1ZS5zcGxpdChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdi5zcGxpY2UoY2FyZXRQb3MuYmVnaW4sIDAsIGlucHV0Q2hhciksIGlucHV0VmFsdWUgPSBpdi5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dFZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBhbmFseXNlQ2hhbmdlcyhpbnB1dFZhbHVlLCBidWZmZXIsIGNhcmV0UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGZyb250UGFydCA9IGlucHV0VmFsdWUuc3Vic3RyKDAsIGNhcmV0UG9zLmJlZ2luKS5zcGxpdChcIlwiKSwgYmFja1BhcnQgPSBpbnB1dFZhbHVlLnN1YnN0cihjYXJldFBvcy5iZWdpbikuc3BsaXQoXCJcIiksIGZyb250QnVmZmVyUGFydCA9IGJ1ZmZlci5zdWJzdHIoMCwgY2FyZXRQb3MuYmVnaW4pLnNwbGl0KFwiXCIpLCBiYWNrQnVmZmVyUGFydCA9IGJ1ZmZlci5zdWJzdHIoY2FyZXRQb3MuYmVnaW4pLnNwbGl0KFwiXCIpLCBmcGwgPSBmcm9udFBhcnQubGVuZ3RoID49IGZyb250QnVmZmVyUGFydC5sZW5ndGggPyBmcm9udFBhcnQubGVuZ3RoIDogZnJvbnRCdWZmZXJQYXJ0Lmxlbmd0aCwgYnBsID0gYmFja1BhcnQubGVuZ3RoID49IGJhY2tCdWZmZXJQYXJ0Lmxlbmd0aCA/IGJhY2tQYXJ0Lmxlbmd0aCA6IGJhY2tCdWZmZXJQYXJ0Lmxlbmd0aCwgYmwsIGksIGFjdGlvbiA9IFwiXCIsIGRhdGEgPSBbXSwgbWFya2VyID0gXCJ+XCIsIHBsYWNlaG9sZGVyOyBmcm9udFBhcnQubGVuZ3RoIDwgZnBsOyApIGZyb250UGFydC5wdXNoKFwiflwiKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICg7ZnJvbnRCdWZmZXJQYXJ0Lmxlbmd0aCA8IGZwbDsgKSBmcm9udEJ1ZmZlclBhcnQucHVzaChcIn5cIik7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoO2JhY2tQYXJ0Lmxlbmd0aCA8IGJwbDsgKSBiYWNrUGFydC51bnNoaWZ0KFwiflwiKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICg7YmFja0J1ZmZlclBhcnQubGVuZ3RoIDwgYnBsOyApIGJhY2tCdWZmZXJQYXJ0LnVuc2hpZnQoXCJ+XCIpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3QnVmZmVyID0gZnJvbnRQYXJ0LmNvbmNhdChiYWNrUGFydCksIG9sZEJ1ZmZlciA9IGZyb250QnVmZmVyUGFydC5jb25jYXQoYmFja0J1ZmZlclBhcnQpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBibCA9IG5ld0J1ZmZlci5sZW5ndGg7IGkgPCBibDsgaSsrKSBzd2l0Y2ggKHBsYWNlaG9sZGVyID0gX3ZhbGlkYXRpb25UZXN0cy5nZXRQbGFjZWhvbGRlci5jYWxsKGlucHV0bWFzaywgX3Bvc2l0aW9uaW5nLnRyYW5zbGF0ZVBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrLCBpKSksIFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaW5zZXJ0VGV4dFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkQnVmZmVyW2kgLSAxXSA9PT0gbmV3QnVmZmVyW2ldICYmIGNhcmV0UG9zLmJlZ2luID09IG5ld0J1ZmZlci5sZW5ndGggLSAxICYmIGRhdGEucHVzaChuZXdCdWZmZXJbaV0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGkgPSBibDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImluc2VydFJlcGxhY2VtZW50VGV4dFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgXCJ+XCIgPT09IG5ld0J1ZmZlcltpXSA/IGNhcmV0UG9zLmVuZCsrIDogaSA9IGJsO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZGVsZXRlQ29udGVudEJhY2t3YXJkXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBcIn5cIiA9PT0gbmV3QnVmZmVyW2ldID8gY2FyZXRQb3MuZW5kKysgOiBpID0gYmw7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdCdWZmZXJbaV0gIT09IG9sZEJ1ZmZlcltpXSAmJiAoXCJ+XCIgIT09IG5ld0J1ZmZlcltpICsgMV0gJiYgbmV3QnVmZmVyW2kgKyAxXSAhPT0gcGxhY2Vob2xkZXIgJiYgdm9pZCAwICE9PSBuZXdCdWZmZXJbaSArIDFdIHx8IChvbGRCdWZmZXJbaV0gIT09IHBsYWNlaG9sZGVyIHx8IFwiflwiICE9PSBvbGRCdWZmZXJbaSArIDFdKSAmJiBcIn5cIiAhPT0gb2xkQnVmZmVyW2ldID8gXCJ+XCIgPT09IG9sZEJ1ZmZlcltpICsgMV0gJiYgb2xkQnVmZmVyW2ldID09PSBuZXdCdWZmZXJbaSArIDFdID8gKGFjdGlvbiA9IFwiaW5zZXJ0VGV4dFwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucHVzaChuZXdCdWZmZXJbaV0pLCBjYXJldFBvcy5iZWdpbi0tLCBjYXJldFBvcy5lbmQtLSkgOiBuZXdCdWZmZXJbaV0gIT09IHBsYWNlaG9sZGVyICYmIFwiflwiICE9PSBuZXdCdWZmZXJbaV0gJiYgKFwiflwiID09PSBuZXdCdWZmZXJbaSArIDFdIHx8IG9sZEJ1ZmZlcltpXSAhPT0gbmV3QnVmZmVyW2ldICYmIG9sZEJ1ZmZlcltpICsgMV0gPT09IG5ld0J1ZmZlcltpICsgMV0pID8gKGFjdGlvbiA9IFwiaW5zZXJ0UmVwbGFjZW1lbnRUZXh0XCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5wdXNoKG5ld0J1ZmZlcltpXSksIGNhcmV0UG9zLmJlZ2luLS0pIDogXCJ+XCIgPT09IG5ld0J1ZmZlcltpXSA/IChhY3Rpb24gPSBcImRlbGV0ZUNvbnRlbnRCYWNrd2FyZFwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICFfcG9zaXRpb25pbmcuaXNNYXNrLmNhbGwoaW5wdXRtYXNrLCBfcG9zaXRpb25pbmcudHJhbnNsYXRlUG9zaXRpb24uY2FsbChpbnB1dG1hc2ssIGkpLCAhMCkgJiYgb2xkQnVmZmVyW2ldICE9PSBvcHRzLnJhZGl4UG9pbnQgfHwgY2FyZXRQb3MuZW5kKyspIDogaSA9IGJsIDogKGFjdGlvbiA9IFwiaW5zZXJ0VGV4dFwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucHVzaChuZXdCdWZmZXJbaV0pLCBjYXJldFBvcy5iZWdpbi0tLCBjYXJldFBvcy5lbmQtLSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbjogYWN0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBjYXJldFBvc1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLCBpbnB1dFZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCghMCksIGJ1ZmZlciA9IChpbnB1dG1hc2suaXNSVEwgPyBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKS5zbGljZSgpLnJldmVyc2UoKSA6IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spKS5qb2luKFwiXCIpLCBjYXJldFBvcyA9IF9wb3NpdGlvbmluZy5jYXJldC5jYWxsKGlucHV0bWFzaywgaW5wdXQsIHZvaWQgMCwgdm9pZCAwLCAhMCk7XG4gICAgICAgICAgICAgICAgaWYgKGJ1ZmZlciAhPT0gaW5wdXRWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlID0gaWVNb2JpbGVIYW5kbGVyKGlucHV0LCBpbnB1dFZhbHVlLCBjYXJldFBvcyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGFuZ2VzID0gYW5hbHlzZUNoYW5nZXMoaW5wdXRWYWx1ZSwgYnVmZmVyLCBjYXJldFBvcyk7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoKGlucHV0LmlucHV0bWFzay5zaGFkb3dSb290IHx8IGRvY3VtZW50KS5hY3RpdmVFbGVtZW50ICE9PSBpbnB1dCAmJiBpbnB1dC5mb2N1cygpLCBcbiAgICAgICAgICAgICAgICAgICAgKDAsIF9pbnB1dEhhbmRsaW5nLndyaXRlQnVmZmVyKShpbnB1dCwgX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykpLCBcbiAgICAgICAgICAgICAgICAgICAgX3Bvc2l0aW9uaW5nLmNhcmV0LmNhbGwoaW5wdXRtYXNrLCBpbnB1dCwgY2FyZXRQb3MuYmVnaW4sIGNhcmV0UG9zLmVuZCwgITApLCBjaGFuZ2VzLmFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJpbnNlcnRUZXh0XCI6XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImluc2VydFJlcGxhY2VtZW50VGV4dFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2hhbmdlcy5kYXRhLmZvckVhY2goZnVuY3Rpb24oZW50cnksIG5keCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrZXlwcmVzcyA9IG5ldyAkLkV2ZW50KFwia2V5cHJlc3NcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cHJlc3Mud2hpY2ggPSBlbnRyeS5jaGFyQ29kZUF0KDApLCBpbnB1dG1hc2suaWdub3JhYmxlID0gITEsIEV2ZW50SGFuZGxlcnMua2V5cHJlc3NFdmVudC5jYWxsKGlucHV0LCBrZXlwcmVzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSwgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dG1hc2suJGVsLnRyaWdnZXIoXCJrZXl1cFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZGVsZXRlQ29udGVudEJhY2t3YXJkXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5ZG93biA9IG5ldyAkLkV2ZW50KFwia2V5ZG93blwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleWRvd24ua2V5Q29kZSA9IF9rZXljb2RlLmRlZmF1bHQuQkFDS1NQQUNFLCBFdmVudEhhbmRsZXJzLmtleWRvd25FdmVudC5jYWxsKGlucHV0LCBrZXlkb3duKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfaW5wdXRIYW5kbGluZy5hcHBseUlucHV0VmFsdWUpKGlucHV0LCBpbnB1dFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29tcG9zaXRpb25lbmRFdmVudDogZnVuY3Rpb24gY29tcG9zaXRpb25lbmRFdmVudChlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMuaW5wdXRtYXNrO1xuICAgICAgICAgICAgICAgIGlucHV0bWFzay5pc0NvbXBvc2luZyA9ICExLCBpbnB1dG1hc2suJGVsLnRyaWdnZXIoXCJpbnB1dFwiKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXRWYWx1ZUV2ZW50OiBmdW5jdGlvbiBzZXRWYWx1ZUV2ZW50KGUsIGFyZ3VtZW50XzEsIGFyZ3VtZW50XzIpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcy5pbnB1dG1hc2ssIGlucHV0ID0gdGhpcywgdmFsdWUgPSBlICYmIGUuZGV0YWlsID8gZS5kZXRhaWxbMF0gOiBhcmd1bWVudF8xO1xuICAgICAgICAgICAgICAgIHZvaWQgMCA9PT0gdmFsdWUgJiYgKHZhbHVlID0gdGhpcy5pbnB1dG1hc2suX3ZhbHVlR2V0KCEwKSksICgwLCBfaW5wdXRIYW5kbGluZy5hcHBseUlucHV0VmFsdWUpKHRoaXMsIHZhbHVlKSwgXG4gICAgICAgICAgICAgICAgKGUuZGV0YWlsICYmIHZvaWQgMCAhPT0gZS5kZXRhaWxbMV0gfHwgdm9pZCAwICE9PSBhcmd1bWVudF8yKSAmJiBfcG9zaXRpb25pbmcuY2FyZXQuY2FsbChpbnB1dG1hc2ssIHRoaXMsIGUuZGV0YWlsID8gZS5kZXRhaWxbMV0gOiBhcmd1bWVudF8yKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmb2N1c0V2ZW50OiBmdW5jdGlvbiBmb2N1c0V2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcy5pbnB1dG1hc2ssIG9wdHMgPSBpbnB1dG1hc2sub3B0cywgaW5wdXQgPSB0aGlzLCBucHRWYWx1ZSA9IHRoaXMuaW5wdXRtYXNrLl92YWx1ZUdldCgpO1xuICAgICAgICAgICAgICAgIG9wdHMuc2hvd01hc2tPbkZvY3VzICYmIG5wdFZhbHVlICE9PSBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKS5qb2luKFwiXCIpICYmICgwLCBcbiAgICAgICAgICAgICAgICBfaW5wdXRIYW5kbGluZy53cml0ZUJ1ZmZlcikodGhpcywgX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzayksIF9wb3NpdGlvbmluZy5zZWVrTmV4dC5jYWxsKGlucHV0bWFzaywgX3Bvc2l0aW9uaW5nLmdldExhc3RWYWxpZFBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrKSkpLCBcbiAgICAgICAgICAgICAgICAhMCAhPT0gb3B0cy5wb3NpdGlvbkNhcmV0T25UYWIgfHwgITEgIT09IGlucHV0bWFzay5tb3VzZUVudGVyIHx8IF92YWxpZGF0aW9uLmlzQ29tcGxldGUuY2FsbChpbnB1dG1hc2ssIF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spKSAmJiAtMSAhPT0gX3Bvc2l0aW9uaW5nLmdldExhc3RWYWxpZFBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrKSB8fCBFdmVudEhhbmRsZXJzLmNsaWNrRXZlbnQuYXBwbHkodGhpcywgWyBlLCAhMCBdKSwgXG4gICAgICAgICAgICAgICAgaW5wdXRtYXNrLnVuZG9WYWx1ZSA9IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW52YWxpZEV2ZW50OiBmdW5jdGlvbiBpbnZhbGlkRXZlbnQoZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRtYXNrLnZhbGlkYXRpb25FdmVudCA9ICEwO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1vdXNlbGVhdmVFdmVudDogZnVuY3Rpb24gbW91c2VsZWF2ZUV2ZW50KCkge1xuICAgICAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLmlucHV0bWFzaywgb3B0cyA9IGlucHV0bWFzay5vcHRzLCBpbnB1dCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgaW5wdXRtYXNrLm1vdXNlRW50ZXIgPSAhMSwgb3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cyAmJiAodGhpcy5pbnB1dG1hc2suc2hhZG93Um9vdCB8fCBkb2N1bWVudCkuYWN0aXZlRWxlbWVudCAhPT0gdGhpcyAmJiAoMCwgXG4gICAgICAgICAgICAgICAgX2lucHV0SGFuZGxpbmcuSGFuZGxlTmF0aXZlUGxhY2Vob2xkZXIpKHRoaXMsIGlucHV0bWFzay5vcmlnaW5hbFBsYWNlaG9sZGVyKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbGlja0V2ZW50OiBmdW5jdGlvbiBjbGlja0V2ZW50KGUsIHRhYmJlZCkge1xuICAgICAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLmlucHV0bWFzaywgaW5wdXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgIGlmICgodGhpcy5pbnB1dG1hc2suc2hhZG93Um9vdCB8fCBkb2N1bWVudCkuYWN0aXZlRWxlbWVudCA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3Q2FyZXRQb3NpdGlvbiA9IF9wb3NpdGlvbmluZy5kZXRlcm1pbmVOZXdDYXJldFBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrLCBfcG9zaXRpb25pbmcuY2FyZXQuY2FsbChpbnB1dG1hc2ssIHRoaXMpLCB0YWJiZWQpO1xuICAgICAgICAgICAgICAgICAgICB2b2lkIDAgIT09IG5ld0NhcmV0UG9zaXRpb24gJiYgX3Bvc2l0aW9uaW5nLmNhcmV0LmNhbGwoaW5wdXRtYXNrLCB0aGlzLCBuZXdDYXJldFBvc2l0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY3V0RXZlbnQ6IGZ1bmN0aW9uIGN1dEV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcy5pbnB1dG1hc2ssIG1hc2tzZXQgPSBpbnB1dG1hc2subWFza3NldCwgaW5wdXQgPSB0aGlzLCBwb3MgPSBfcG9zaXRpb25pbmcuY2FyZXQuY2FsbChpbnB1dG1hc2ssIHRoaXMpLCBjbGlwYm9hcmREYXRhID0gd2luZG93LmNsaXBib2FyZERhdGEgfHwgZS5jbGlwYm9hcmREYXRhLCBjbGlwRGF0YSA9IGlucHV0bWFzay5pc1JUTCA/IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLnNsaWNlKHBvcy5lbmQsIHBvcy5iZWdpbikgOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKS5zbGljZShwb3MuYmVnaW4sIHBvcy5lbmQpO1xuICAgICAgICAgICAgICAgIGNsaXBib2FyZERhdGEuc2V0RGF0YShcInRleHRcIiwgaW5wdXRtYXNrLmlzUlRMID8gY2xpcERhdGEucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBjbGlwRGF0YS5qb2luKFwiXCIpKSwgXG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuZXhlY0NvbW1hbmQgJiYgZG9jdW1lbnQuZXhlY0NvbW1hbmQoXCJjb3B5XCIpLCBfdmFsaWRhdGlvbi5oYW5kbGVSZW1vdmUuY2FsbChpbnB1dG1hc2ssIHRoaXMsIF9rZXljb2RlLmRlZmF1bHQuREVMRVRFLCBwb3MpLCBcbiAgICAgICAgICAgICAgICAoMCwgX2lucHV0SGFuZGxpbmcud3JpdGVCdWZmZXIpKHRoaXMsIF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLCBtYXNrc2V0LnAsIGUsIGlucHV0bWFzay51bmRvVmFsdWUgIT09IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJsdXJFdmVudDogZnVuY3Rpb24gYmx1ckV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcy5pbnB1dG1hc2ssIG9wdHMgPSBpbnB1dG1hc2sub3B0cywgJCA9IGlucHV0bWFzay5kZXBlbmRlbmN5TGliLCAkaW5wdXQgPSAkKHRoaXMpLCBpbnB1dCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRtYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICgwLCBfaW5wdXRIYW5kbGluZy5IYW5kbGVOYXRpdmVQbGFjZWhvbGRlcikodGhpcywgaW5wdXRtYXNrLm9yaWdpbmFsUGxhY2Vob2xkZXIpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbnB0VmFsdWUgPSB0aGlzLmlucHV0bWFzay5fdmFsdWVHZXQoKSwgYnVmZmVyID0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgXCJcIiAhPT0gbnB0VmFsdWUgJiYgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgJiYgKC0xID09PSBfcG9zaXRpb25pbmcuZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbChpbnB1dG1hc2spICYmIG5wdFZhbHVlID09PSBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyVGVtcGxhdGUuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIikgPyBidWZmZXIgPSBbXSA6IF9pbnB1dEhhbmRsaW5nLmNsZWFyT3B0aW9uYWxUYWlsLmNhbGwoaW5wdXRtYXNrLCBidWZmZXIpKSwgXG4gICAgICAgICAgICAgICAgICAgICExID09PSBfdmFsaWRhdGlvbi5pc0NvbXBsZXRlLmNhbGwoaW5wdXRtYXNrLCBidWZmZXIpICYmIChzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJpbmNvbXBsZXRlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LCAwKSwgb3B0cy5jbGVhckluY29tcGxldGUgJiYgKF9wb3NpdGlvbmluZy5yZXNldE1hc2tTZXQuY2FsbChpbnB1dG1hc2spLCBidWZmZXIgPSBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzID8gW10gOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyVGVtcGxhdGUuY2FsbChpbnB1dG1hc2spLnNsaWNlKCkpKSwgXG4gICAgICAgICAgICAgICAgICAgICgwLCBfaW5wdXRIYW5kbGluZy53cml0ZUJ1ZmZlcikodGhpcywgYnVmZmVyLCB2b2lkIDAsIGUpKSwgaW5wdXRtYXNrLnVuZG9WYWx1ZSAhPT0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykuam9pbihcIlwiKSAmJiAoaW5wdXRtYXNrLnVuZG9WYWx1ZSA9IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcImNoYW5nZVwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1vdXNlZW50ZXJFdmVudDogZnVuY3Rpb24gbW91c2VlbnRlckV2ZW50KCkge1xuICAgICAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLmlucHV0bWFzaywgb3B0cyA9IGlucHV0bWFzay5vcHRzLCBpbnB1dCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgaW5wdXRtYXNrLm1vdXNlRW50ZXIgPSAhMCwgKHRoaXMuaW5wdXRtYXNrLnNoYWRvd1Jvb3QgfHwgZG9jdW1lbnQpLmFjdGl2ZUVsZW1lbnQgIT09IHRoaXMgJiYgKG51bGwgPT0gaW5wdXRtYXNrLm9yaWdpbmFsUGxhY2Vob2xkZXIgJiYgdGhpcy5wbGFjZWhvbGRlciAhPT0gaW5wdXRtYXNrLm9yaWdpbmFsUGxhY2Vob2xkZXIgJiYgKGlucHV0bWFzay5vcmlnaW5hbFBsYWNlaG9sZGVyID0gdGhpcy5wbGFjZWhvbGRlciksIFxuICAgICAgICAgICAgICAgIG9wdHMuc2hvd01hc2tPbkhvdmVyICYmICgwLCBfaW5wdXRIYW5kbGluZy5IYW5kbGVOYXRpdmVQbGFjZWhvbGRlcikodGhpcywgKGlucHV0bWFzay5pc1JUTCA/IF9wb3NpdGlvbmluZy5nZXRCdWZmZXJUZW1wbGF0ZS5jYWxsKGlucHV0bWFzaykuc2xpY2UoKS5yZXZlcnNlKCkgOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyVGVtcGxhdGUuY2FsbChpbnB1dG1hc2spKS5qb2luKFwiXCIpKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3VibWl0RXZlbnQ6IGZ1bmN0aW9uIHN1Ym1pdEV2ZW50KCkge1xuICAgICAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLmlucHV0bWFzaywgb3B0cyA9IGlucHV0bWFzay5vcHRzO1xuICAgICAgICAgICAgICAgIGlucHV0bWFzay51bmRvVmFsdWUgIT09IF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIikgJiYgaW5wdXRtYXNrLiRlbC50cmlnZ2VyKFwiY2hhbmdlXCIpLCBcbiAgICAgICAgICAgICAgICBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzICYmIC0xID09PSBfcG9zaXRpb25pbmcuZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbChpbnB1dG1hc2spICYmIGlucHV0bWFzay5fdmFsdWVHZXQgJiYgaW5wdXRtYXNrLl92YWx1ZUdldCgpID09PSBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyVGVtcGxhdGUuY2FsbChpbnB1dG1hc2spLmpvaW4oXCJcIikgJiYgaW5wdXRtYXNrLl92YWx1ZVNldChcIlwiKSwgXG4gICAgICAgICAgICAgICAgb3B0cy5jbGVhckluY29tcGxldGUgJiYgITEgPT09IF92YWxpZGF0aW9uLmlzQ29tcGxldGUuY2FsbChpbnB1dG1hc2ssIF9wb3NpdGlvbmluZy5nZXRCdWZmZXIuY2FsbChpbnB1dG1hc2spKSAmJiBpbnB1dG1hc2suX3ZhbHVlU2V0KFwiXCIpLCBcbiAgICAgICAgICAgICAgICBvcHRzLnJlbW92ZU1hc2tPblN1Ym1pdCAmJiAoaW5wdXRtYXNrLl92YWx1ZVNldChpbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpLCAhMCksIFxuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICgwLCBfaW5wdXRIYW5kbGluZy53cml0ZUJ1ZmZlcikoaW5wdXRtYXNrLmVsLCBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKSk7XG4gICAgICAgICAgICAgICAgfSwgMCkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc2V0RXZlbnQ6IGZ1bmN0aW9uIHJlc2V0RXZlbnQoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGlucHV0bWFzayA9IHRoaXMuaW5wdXRtYXNrO1xuICAgICAgICAgICAgICAgIGlucHV0bWFzay5yZWZyZXNoVmFsdWUgPSAhMCwgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgKDAsIF9pbnB1dEhhbmRsaW5nLmFwcGx5SW5wdXRWYWx1ZSkoaW5wdXRtYXNrLmVsLCBpbnB1dG1hc2suX3ZhbHVlR2V0KCEwKSk7XG4gICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGV4cG9ydHMuRXZlbnRIYW5kbGVycyA9IEV2ZW50SGFuZGxlcnM7XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgICAgICAgICAgIHZhbHVlOiAhMFxuICAgICAgICB9KSwgZXhwb3J0cy5pcGhvbmUgPSBleHBvcnRzLmllbW9iaWxlID0gZXhwb3J0cy5tb2JpbGUgPSBleHBvcnRzLmllID0gZXhwb3J0cy51YSA9IHZvaWQgMDtcbiAgICAgICAgdmFyIHVhID0gd2luZG93Lm5hdmlnYXRvciAmJiB3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudCB8fCBcIlwiLCBpZSA9IDAgPCB1YS5pbmRleE9mKFwiTVNJRSBcIikgfHwgMCA8IHVhLmluZGV4T2YoXCJUcmlkZW50L1wiKSwgbW9iaWxlID0gXCJvbnRvdWNoc3RhcnRcIiBpbiB3aW5kb3csIGllbW9iaWxlID0gL2llbW9iaWxlL2kudGVzdCh1YSksIGlwaG9uZSA9IC9pcGhvbmUvaS50ZXN0KHVhKSAmJiAhaWVtb2JpbGU7XG4gICAgICAgIGV4cG9ydHMuaXBob25lID0gaXBob25lLCBleHBvcnRzLmllbW9iaWxlID0gaWVtb2JpbGUsIGV4cG9ydHMubW9iaWxlID0gbW9iaWxlLCBleHBvcnRzLmllID0gaWUsIFxuICAgICAgICBleHBvcnRzLnVhID0gdWE7XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV9fOF9fO1xuICAgIH0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgZnVuY3Rpb24gX3R5cGVvZihvYmopIHtcbiAgICAgICAgICAgIHJldHVybiBfdHlwZW9mID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgXCJzeW1ib2xcIiA9PSB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID8gZnVuY3Rpb24gX3R5cGVvZihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIG9iajtcbiAgICAgICAgICAgIH0gOiBmdW5jdGlvbiBfdHlwZW9mKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmogJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7XG4gICAgICAgICAgICB9LCBfdHlwZW9mKG9iaik7XG4gICAgICAgIH1cbiAgICAgICAgXCJmdW5jdGlvblwiICE9IHR5cGVvZiBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiYgKE9iamVjdC5nZXRQcm90b3R5cGVPZiA9IFwib2JqZWN0XCIgPT09IF90eXBlb2YoXCJ0ZXN0XCIuX19wcm90b19fKSA/IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdC5fX3Byb3RvX187XG4gICAgICAgIH0gOiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3QuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICB9KTtcbiAgICB9LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICAgICAgICAgICAgdmFsdWU6ICEwXG4gICAgICAgIH0pLCBleHBvcnRzLm1hc2sgPSBtYXNrLCBfX3dlYnBhY2tfcmVxdWlyZV9fKDkpO1xuICAgICAgICB2YXIgX2tleWNvZGUgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMCkpLCBfcG9zaXRpb25pbmcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIpLCBfaW5wdXRIYW5kbGluZyA9IF9fd2VicGFja19yZXF1aXJlX18oNSksIF9ldmVudHJ1bGVyID0gX193ZWJwYWNrX3JlcXVpcmVfXygxMSksIF9lbnZpcm9ubWVudCA9IF9fd2VicGFja19yZXF1aXJlX18oNyksIF92YWxpZGF0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0KSwgX2V2ZW50aGFuZGxlcnMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDYpO1xuICAgICAgICBmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiBvYmpcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gbWFzaygpIHtcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCBvcHRzID0gdGhpcy5vcHRzLCBlbCA9IHRoaXMuZWwsICQgPSB0aGlzLmRlcGVuZGVuY3lMaWI7XG4gICAgICAgICAgICBmdW5jdGlvbiBpc0VsZW1lbnRUeXBlU3VwcG9ydGVkKGlucHV0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hWYWx1ZVByb3BlcnR5KG5wdCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVHZXQsIHZhbHVlU2V0O1xuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFZhbGhvb2sodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCQudmFsSG9va3MgJiYgKHZvaWQgMCA9PT0gJC52YWxIb29rc1t0eXBlXSB8fCAhMCAhPT0gJC52YWxIb29rc1t0eXBlXS5pbnB1dG1hc2twYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsaG9va0dldCA9ICQudmFsSG9va3NbdHlwZV0gJiYgJC52YWxIb29rc1t0eXBlXS5nZXQgPyAkLnZhbEhvb2tzW3R5cGVdLmdldCA6IGZ1bmN0aW9uKGVsZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW0udmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgdmFsaG9va1NldCA9ICQudmFsSG9va3NbdHlwZV0gJiYgJC52YWxIb29rc1t0eXBlXS5zZXQgPyAkLnZhbEhvb2tzW3R5cGVdLnNldCA6IGZ1bmN0aW9uKGVsZW0sIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtLnZhbHVlID0gdmFsdWUsIGVsZW07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLnZhbEhvb2tzW3R5cGVdID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldChlbGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbS5pbnB1dG1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbS5pbnB1dG1hc2sub3B0cy5hdXRvVW5tYXNrKSByZXR1cm4gZWxlbS5pbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB2YWxob29rR2V0KGVsZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAtMSAhPT0gX3Bvc2l0aW9uaW5nLmdldExhc3RWYWxpZFBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrLCB2b2lkIDAsIHZvaWQgMCwgZWxlbS5pbnB1dG1hc2subWFza3NldC52YWxpZFBvc2l0aW9ucykgfHwgITAgIT09IG9wdHMubnVsbGFibGUgPyByZXN1bHQgOiBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbGhvb2tHZXQoZWxlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gc2V0KGVsZW0sIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gdmFsaG9va1NldChlbGVtLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZWxlbS5pbnB1dG1hc2sgJiYgKDAsIF9pbnB1dEhhbmRsaW5nLmFwcGx5SW5wdXRWYWx1ZSkoZWxlbSwgdmFsdWUpLCByZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0bWFza3BhdGNoOiAhMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2V0dGVyKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRtYXNrID8gdGhpcy5pbnB1dG1hc2sub3B0cy5hdXRvVW5tYXNrID8gdGhpcy5pbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpIDogLTEgIT09IF9wb3NpdGlvbmluZy5nZXRMYXN0VmFsaWRQb3NpdGlvbi5jYWxsKGlucHV0bWFzaykgfHwgITAgIT09IG9wdHMubnVsbGFibGUgPyAodGhpcy5pbnB1dG1hc2suc2hhZG93Um9vdCB8fCBkb2N1bWVudC5hY3RpdmVFbGVtZW50KSA9PT0gdGhpcyAmJiBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzID8gKGlucHV0bWFzay5pc1JUTCA/IF9pbnB1dEhhbmRsaW5nLmNsZWFyT3B0aW9uYWxUYWlsLmNhbGwoaW5wdXRtYXNrLCBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKS5zbGljZSgpKS5yZXZlcnNlKCkgOiBfaW5wdXRIYW5kbGluZy5jbGVhck9wdGlvbmFsVGFpbC5jYWxsKGlucHV0bWFzaywgX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykuc2xpY2UoKSkpLmpvaW4oXCJcIikgOiB2YWx1ZUdldC5jYWxsKHRoaXMpIDogXCJcIiA6IHZhbHVlR2V0LmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gc2V0dGVyKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldC5jYWxsKHRoaXMsIHZhbHVlKSwgdGhpcy5pbnB1dG1hc2sgJiYgKDAsIF9pbnB1dEhhbmRsaW5nLmFwcGx5SW5wdXRWYWx1ZSkodGhpcywgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGluc3RhbGxOYXRpdmVWYWx1ZVNldEZhbGxiYWNrKG5wdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihucHQsIFwibW91c2VlbnRlclwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLCB2YWx1ZSA9IHRoaXMuaW5wdXRtYXNrLl92YWx1ZUdldCghMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgIT09IChpbnB1dG1hc2suaXNSVEwgPyBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKS5yZXZlcnNlKCkgOiBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyLmNhbGwoaW5wdXRtYXNrKSkuam9pbihcIlwiKSAmJiAoMCwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX2lucHV0SGFuZGxpbmcuYXBwbHlJbnB1dFZhbHVlKSh0aGlzLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIW5wdC5pbnB1dG1hc2suX192YWx1ZUdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEwICE9PSBvcHRzLm5vVmFsdWVQYXRjaGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZVByb3BlcnR5ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihPYmplY3QuZ2V0UHJvdG90eXBlT2YobnB0KSwgXCJ2YWx1ZVwiKSA6IHZvaWQgMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVQcm9wZXJ0eSAmJiB2YWx1ZVByb3BlcnR5LmdldCAmJiB2YWx1ZVByb3BlcnR5LnNldCA/ICh2YWx1ZUdldCA9IHZhbHVlUHJvcGVydHkuZ2V0LCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVTZXQgPSB2YWx1ZVByb3BlcnR5LnNldCwgT2JqZWN0LmRlZmluZVByb3BlcnR5KG5wdCwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGdldHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldDogc2V0dGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiAhMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSkgOiBcImlucHV0XCIgIT09IG5wdC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgJiYgKHZhbHVlR2V0ID0gZnVuY3Rpb24gdmFsdWVHZXQoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50ZXh0Q29udGVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgdmFsdWVTZXQgPSBmdW5jdGlvbiB2YWx1ZVNldCh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0Q29udGVudCA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBPYmplY3QuZGVmaW5lUHJvcGVydHkobnB0LCBcInZhbHVlXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldDogZ2V0dGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0OiBzZXR0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6ICEwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgZG9jdW1lbnQuX19sb29rdXBHZXR0ZXJfXyAmJiBucHQuX19sb29rdXBHZXR0ZXJfXyhcInZhbHVlXCIpICYmICh2YWx1ZUdldCA9IG5wdC5fX2xvb2t1cEdldHRlcl9fKFwidmFsdWVcIiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlU2V0ID0gbnB0Ll9fbG9va3VwU2V0dGVyX18oXCJ2YWx1ZVwiKSwgbnB0Ll9fZGVmaW5lR2V0dGVyX18oXCJ2YWx1ZVwiLCBnZXR0ZXIpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBucHQuX19kZWZpbmVTZXR0ZXJfXyhcInZhbHVlXCIsIHNldHRlcikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5wdC5pbnB1dG1hc2suX192YWx1ZUdldCA9IHZhbHVlR2V0LCBucHQuaW5wdXRtYXNrLl9fdmFsdWVTZXQgPSB2YWx1ZVNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5wdC5pbnB1dG1hc2suX3ZhbHVlR2V0ID0gZnVuY3Rpb24ob3ZlcnJ1bGVSVEwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5wdXRtYXNrLmlzUlRMICYmICEwICE9PSBvdmVycnVsZVJUTCA/IHZhbHVlR2V0LmNhbGwodGhpcy5lbCkuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiB2YWx1ZUdldC5jYWxsKHRoaXMuZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgbnB0LmlucHV0bWFzay5fdmFsdWVTZXQgPSBmdW5jdGlvbih2YWx1ZSwgb3ZlcnJ1bGVSVEwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldC5jYWxsKHRoaXMuZWwsIG51bGwgPT0gdmFsdWUgPyBcIlwiIDogITAgIT09IG92ZXJydWxlUlRMICYmIGlucHV0bWFzay5pc1JUTCA/IHZhbHVlLnNwbGl0KFwiXCIpLnJldmVyc2UoKS5qb2luKFwiXCIpIDogdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgdm9pZCAwID09PSB2YWx1ZUdldCAmJiAodmFsdWVHZXQgPSBmdW5jdGlvbiB2YWx1ZUdldCgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIHZhbHVlU2V0ID0gZnVuY3Rpb24gdmFsdWVTZXQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBwYXRjaFZhbGhvb2sobnB0LnR5cGUpLCBpbnN0YWxsTmF0aXZlVmFsdWVTZXRGYWxsYmFjayhucHQpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBcInRleHRhcmVhXCIgIT09IGlucHV0LnRhZ05hbWUudG9Mb3dlckNhc2UoKSAmJiBvcHRzLmlnbm9yYWJsZXMucHVzaChfa2V5Y29kZS5kZWZhdWx0LkVOVEVSKTtcbiAgICAgICAgICAgICAgICB2YXIgZWxlbWVudFR5cGUgPSBpbnB1dC5nZXRBdHRyaWJ1dGUoXCJ0eXBlXCIpLCBpc1N1cHBvcnRlZCA9IFwiaW5wdXRcIiA9PT0gaW5wdXQudGFnTmFtZS50b0xvd2VyQ2FzZSgpICYmIG9wdHMuc3VwcG9ydHNJbnB1dFR5cGUuaW5jbHVkZXMoZWxlbWVudFR5cGUpIHx8IGlucHV0LmlzQ29udGVudEVkaXRhYmxlIHx8IFwidGV4dGFyZWFcIiA9PT0gaW5wdXQudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGlmICghaXNTdXBwb3J0ZWQpIGlmIChcImlucHV0XCIgPT09IGlucHV0LnRhZ05hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIik7XG4gICAgICAgICAgICAgICAgICAgIGVsLnNldEF0dHJpYnV0ZShcInR5cGVcIiwgZWxlbWVudFR5cGUpLCBpc1N1cHBvcnRlZCA9IFwidGV4dFwiID09PSBlbC50eXBlLCBlbCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlzU3VwcG9ydGVkID0gXCJwYXJ0aWFsXCI7XG4gICAgICAgICAgICAgICAgcmV0dXJuICExICE9PSBpc1N1cHBvcnRlZCA/IHBhdGNoVmFsdWVQcm9wZXJ0eShpbnB1dCkgOiBpbnB1dC5pbnB1dG1hc2sgPSB2b2lkIDAsIFxuICAgICAgICAgICAgICAgIGlzU3VwcG9ydGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vZmYoZWwpO1xuICAgICAgICAgICAgdmFyIGlzU3VwcG9ydGVkID0gaXNFbGVtZW50VHlwZVN1cHBvcnRlZChlbCwgb3B0cyk7XG4gICAgICAgICAgICBpZiAoITEgIT09IGlzU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICAgICAgaW5wdXRtYXNrLm9yaWdpbmFsUGxhY2Vob2xkZXIgPSBlbC5wbGFjZWhvbGRlciwgaW5wdXRtYXNrLm1heExlbmd0aCA9IHZvaWQgMCAhPT0gZWwgPyBlbC5tYXhMZW5ndGggOiB2b2lkIDAsIFxuICAgICAgICAgICAgICAgIC0xID09PSBpbnB1dG1hc2subWF4TGVuZ3RoICYmIChpbnB1dG1hc2subWF4TGVuZ3RoID0gdm9pZCAwKSwgXCJpbnB1dE1vZGVcIiBpbiBlbCAmJiBudWxsID09PSBlbC5nZXRBdHRyaWJ1dGUoXCJpbnB1dG1vZGVcIikgJiYgKGVsLmlucHV0TW9kZSA9IG9wdHMuaW5wdXRtb2RlLCBcbiAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoXCJpbnB1dG1vZGVcIiwgb3B0cy5pbnB1dG1vZGUpKSwgITAgPT09IGlzU3VwcG9ydGVkICYmIChvcHRzLnNob3dNYXNrT25Gb2N1cyA9IG9wdHMuc2hvd01hc2tPbkZvY3VzICYmIC0xID09PSBbIFwiY2MtbnVtYmVyXCIsIFwiY2MtZXhwXCIgXS5pbmRleE9mKGVsLmF1dG9jb21wbGV0ZSksIFxuICAgICAgICAgICAgICAgIF9lbnZpcm9ubWVudC5pcGhvbmUgJiYgKG9wdHMuaW5zZXJ0TW9kZVZpc3VhbCA9ICExKSwgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJzdWJtaXRcIiwgX2V2ZW50aGFuZGxlcnMuRXZlbnRIYW5kbGVycy5zdWJtaXRFdmVudCksIFxuICAgICAgICAgICAgICAgIF9ldmVudHJ1bGVyLkV2ZW50UnVsZXIub24oZWwsIFwicmVzZXRcIiwgX2V2ZW50aGFuZGxlcnMuRXZlbnRIYW5kbGVycy5yZXNldEV2ZW50KSwgXG4gICAgICAgICAgICAgICAgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJibHVyXCIsIF9ldmVudGhhbmRsZXJzLkV2ZW50SGFuZGxlcnMuYmx1ckV2ZW50KSwgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJmb2N1c1wiLCBfZXZlbnRoYW5kbGVycy5FdmVudEhhbmRsZXJzLmZvY3VzRXZlbnQpLCBcbiAgICAgICAgICAgICAgICBfZXZlbnRydWxlci5FdmVudFJ1bGVyLm9uKGVsLCBcImludmFsaWRcIiwgX2V2ZW50aGFuZGxlcnMuRXZlbnRIYW5kbGVycy5pbnZhbGlkRXZlbnQpLCBcbiAgICAgICAgICAgICAgICBfZXZlbnRydWxlci5FdmVudFJ1bGVyLm9uKGVsLCBcImNsaWNrXCIsIF9ldmVudGhhbmRsZXJzLkV2ZW50SGFuZGxlcnMuY2xpY2tFdmVudCksIFxuICAgICAgICAgICAgICAgIF9ldmVudHJ1bGVyLkV2ZW50UnVsZXIub24oZWwsIFwibW91c2VsZWF2ZVwiLCBfZXZlbnRoYW5kbGVycy5FdmVudEhhbmRsZXJzLm1vdXNlbGVhdmVFdmVudCksIFxuICAgICAgICAgICAgICAgIF9ldmVudHJ1bGVyLkV2ZW50UnVsZXIub24oZWwsIFwibW91c2VlbnRlclwiLCBfZXZlbnRoYW5kbGVycy5FdmVudEhhbmRsZXJzLm1vdXNlZW50ZXJFdmVudCksIFxuICAgICAgICAgICAgICAgIF9ldmVudHJ1bGVyLkV2ZW50UnVsZXIub24oZWwsIFwicGFzdGVcIiwgX2V2ZW50aGFuZGxlcnMuRXZlbnRIYW5kbGVycy5wYXN0ZUV2ZW50KSwgXG4gICAgICAgICAgICAgICAgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJjdXRcIiwgX2V2ZW50aGFuZGxlcnMuRXZlbnRIYW5kbGVycy5jdXRFdmVudCksIF9ldmVudHJ1bGVyLkV2ZW50UnVsZXIub24oZWwsIFwiY29tcGxldGVcIiwgb3B0cy5vbmNvbXBsZXRlKSwgXG4gICAgICAgICAgICAgICAgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJpbmNvbXBsZXRlXCIsIG9wdHMub25pbmNvbXBsZXRlKSwgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJjbGVhcmVkXCIsIG9wdHMub25jbGVhcmVkKSwgXG4gICAgICAgICAgICAgICAgITAgIT09IG9wdHMuaW5wdXRFdmVudE9ubHkgJiYgKF9ldmVudHJ1bGVyLkV2ZW50UnVsZXIub24oZWwsIFwia2V5ZG93blwiLCBfZXZlbnRoYW5kbGVycy5FdmVudEhhbmRsZXJzLmtleWRvd25FdmVudCksIFxuICAgICAgICAgICAgICAgIF9ldmVudHJ1bGVyLkV2ZW50UnVsZXIub24oZWwsIFwia2V5cHJlc3NcIiwgX2V2ZW50aGFuZGxlcnMuRXZlbnRIYW5kbGVycy5rZXlwcmVzc0V2ZW50KSwgXG4gICAgICAgICAgICAgICAgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJrZXl1cFwiLCBfZXZlbnRoYW5kbGVycy5FdmVudEhhbmRsZXJzLmtleXVwRXZlbnQpKSwgXG4gICAgICAgICAgICAgICAgKF9lbnZpcm9ubWVudC5tb2JpbGUgfHwgb3B0cy5pbnB1dEV2ZW50T25seSkgJiYgZWwucmVtb3ZlQXR0cmlidXRlKFwibWF4TGVuZ3RoXCIpLCBcbiAgICAgICAgICAgICAgICBfZXZlbnRydWxlci5FdmVudFJ1bGVyLm9uKGVsLCBcImlucHV0XCIsIF9ldmVudGhhbmRsZXJzLkV2ZW50SGFuZGxlcnMuaW5wdXRGYWxsQmFja0V2ZW50KSwgXG4gICAgICAgICAgICAgICAgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJjb21wb3NpdGlvbmVuZFwiLCBfZXZlbnRoYW5kbGVycy5FdmVudEhhbmRsZXJzLmNvbXBvc2l0aW9uZW5kRXZlbnQpKSwgXG4gICAgICAgICAgICAgICAgX2V2ZW50cnVsZXIuRXZlbnRSdWxlci5vbihlbCwgXCJzZXR2YWx1ZVwiLCBfZXZlbnRoYW5kbGVycy5FdmVudEhhbmRsZXJzLnNldFZhbHVlRXZlbnQpLCBcbiAgICAgICAgICAgICAgICBpbnB1dG1hc2sudW5kb1ZhbHVlID0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlclRlbXBsYXRlLmNhbGwoaW5wdXRtYXNrKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgIHZhciBhY3RpdmVFbGVtZW50ID0gKGVsLmlucHV0bWFzay5zaGFkb3dSb290IHx8IGRvY3VtZW50KS5hY3RpdmVFbGVtZW50O1xuICAgICAgICAgICAgICAgIGlmIChcIlwiICE9PSBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0KCEwKSB8fCAhMSA9PT0gb3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cyB8fCBhY3RpdmVFbGVtZW50ID09PSBlbCkge1xuICAgICAgICAgICAgICAgICAgICAoMCwgX2lucHV0SGFuZGxpbmcuYXBwbHlJbnB1dFZhbHVlKShlbCwgZWwuaW5wdXRtYXNrLl92YWx1ZUdldCghMCksIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlci5jYWxsKGlucHV0bWFzaykuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgITEgPT09IF92YWxpZGF0aW9uLmlzQ29tcGxldGUuY2FsbChpbnB1dG1hc2ssIGJ1ZmZlcikgJiYgb3B0cy5jbGVhckluY29tcGxldGUgJiYgX3Bvc2l0aW9uaW5nLnJlc2V0TWFza1NldC5jYWxsKGlucHV0bWFzayksIFxuICAgICAgICAgICAgICAgICAgICBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzICYmIGFjdGl2ZUVsZW1lbnQgIT09IGVsICYmICgtMSA9PT0gX3Bvc2l0aW9uaW5nLmdldExhc3RWYWxpZFBvc2l0aW9uLmNhbGwoaW5wdXRtYXNrKSA/IGJ1ZmZlciA9IFtdIDogX2lucHV0SGFuZGxpbmcuY2xlYXJPcHRpb25hbFRhaWwuY2FsbChpbnB1dG1hc2ssIGJ1ZmZlcikpLCBcbiAgICAgICAgICAgICAgICAgICAgKCExID09PSBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzIHx8IG9wdHMuc2hvd01hc2tPbkZvY3VzICYmIGFjdGl2ZUVsZW1lbnQgPT09IGVsIHx8IFwiXCIgIT09IGVsLmlucHV0bWFzay5fdmFsdWVHZXQoITApKSAmJiAoMCwgXG4gICAgICAgICAgICAgICAgICAgIF9pbnB1dEhhbmRsaW5nLndyaXRlQnVmZmVyKShlbCwgYnVmZmVyKSwgYWN0aXZlRWxlbWVudCA9PT0gZWwgJiYgX3Bvc2l0aW9uaW5nLmNhcmV0LmNhbGwoaW5wdXRtYXNrLCBlbCwgX3Bvc2l0aW9uaW5nLnNlZWtOZXh0LmNhbGwoaW5wdXRtYXNrLCBfcG9zaXRpb25pbmcuZ2V0TGFzdFZhbGlkUG9zaXRpb24uY2FsbChpbnB1dG1hc2spKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgICAgICAgICAgIHZhbHVlOiAhMFxuICAgICAgICB9KSwgZXhwb3J0cy5FdmVudFJ1bGVyID0gdm9pZCAwO1xuICAgICAgICB2YXIgX2lucHV0bWFzayA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygxKSksIF9rZXljb2RlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDApKSwgX3Bvc2l0aW9uaW5nID0gX193ZWJwYWNrX3JlcXVpcmVfXygyKSwgX2lucHV0SGFuZGxpbmcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUpO1xuICAgICAgICBmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiBvYmpcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIEV2ZW50UnVsZXIgPSB7XG4gICAgICAgICAgICBvbjogZnVuY3Rpb24gb24oaW5wdXQsIGV2ZW50TmFtZSwgZXZlbnRIYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgdmFyICQgPSBpbnB1dC5pbnB1dG1hc2suZGVwZW5kZW5jeUxpYiwgZXYgPSBmdW5jdGlvbiBldihlKSB7XG4gICAgICAgICAgICAgICAgICAgIGUub3JpZ2luYWxFdmVudCAmJiAoZSA9IGUub3JpZ2luYWxFdmVudCB8fCBlLCBhcmd1bWVudHNbMF0gPSBlKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLCBhcmdzLCBpbnB1dG1hc2sgPSB0aGF0LmlucHV0bWFzaywgb3B0cyA9IGlucHV0bWFzayA/IGlucHV0bWFzay5vcHRzIDogdm9pZCAwLCAkID0gaW5wdXRtYXNrLmRlcGVuZGVuY3lMaWI7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2b2lkIDAgPT09IGlucHV0bWFzayAmJiBcIkZPUk1cIiAhPT0gdGhpcy5ub2RlTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGltT3B0cyA9ICQuZGF0YSh0aGF0LCBcIl9pbnB1dG1hc2tfb3B0c1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICQodGhhdCkub2ZmKCksIGltT3B0cyAmJiBuZXcgX2lucHV0bWFzay5kZWZhdWx0KGltT3B0cykubWFzayh0aGF0KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcInNldHZhbHVlXCIgPT09IGUudHlwZSB8fCBcIkZPUk1cIiA9PT0gdGhpcy5ub2RlTmFtZSB8fCAhKHRoYXQuZGlzYWJsZWQgfHwgdGhhdC5yZWFkT25seSAmJiAhKFwia2V5ZG93blwiID09PSBlLnR5cGUgJiYgZS5jdHJsS2V5ICYmIDY3ID09PSBlLmtleUNvZGUgfHwgITEgPT09IG9wdHMudGFiVGhyb3VnaCAmJiBlLmtleUNvZGUgPT09IF9rZXljb2RlLmRlZmF1bHQuVEFCKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGUudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImlucHV0XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghMCA9PT0gaW5wdXRtYXNrLnNraXBJbnB1dEV2ZW50IHx8IGUuaW5wdXRUeXBlICYmIFwiaW5zZXJ0Q29tcG9zaXRpb25UZXh0XCIgPT09IGUuaW5wdXRUeXBlKSByZXR1cm4gaW5wdXRtYXNrLnNraXBJbnB1dEV2ZW50ID0gITEsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwia2V5ZG93blwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dG1hc2suc2tpcEtleVByZXNzRXZlbnQgPSAhMSwgaW5wdXRtYXNrLnNraXBJbnB1dEV2ZW50ID0gaW5wdXRtYXNrLmlzQ29tcG9zaW5nID0gZS5rZXlDb2RlID09PSBfa2V5Y29kZS5kZWZhdWx0LktFWV8yMjk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwia2V5dXBcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJjb21wb3NpdGlvbmVuZFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dG1hc2suaXNDb21wb3NpbmcgJiYgKGlucHV0bWFzay5za2lwSW5wdXRFdmVudCA9ICExKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJrZXlwcmVzc1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoITAgPT09IGlucHV0bWFzay5za2lwS2V5UHJlc3NFdmVudCkgcmV0dXJuIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRtYXNrLnNraXBLZXlQcmVzc0V2ZW50ID0gITA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY2xpY2tcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJmb2N1c1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5wdXRtYXNrLnZhbGlkYXRpb25FdmVudCA/IChpbnB1dG1hc2sudmFsaWRhdGlvbkV2ZW50ID0gITEsIGlucHV0LmJsdXIoKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfaW5wdXRIYW5kbGluZy5IYW5kbGVOYXRpdmVQbGFjZWhvbGRlcikoaW5wdXQsIChpbnB1dG1hc2suaXNSVEwgPyBfcG9zaXRpb25pbmcuZ2V0QnVmZmVyVGVtcGxhdGUuY2FsbChpbnB1dG1hc2spLnNsaWNlKCkucmV2ZXJzZSgpIDogX3Bvc2l0aW9uaW5nLmdldEJ1ZmZlclRlbXBsYXRlLmNhbGwoaW5wdXRtYXNrKSkuam9pbihcIlwiKSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgM2UzKSkgOiAoYXJncyA9IGFyZ3VtZW50cywgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LmlucHV0bWFzayAmJiBldmVudEhhbmRsZXIuYXBwbHkodGhhdCwgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApKSwgITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXR1cm5WYWwgPSBldmVudEhhbmRsZXIuYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gITEgPT09IHJldHVyblZhbCAmJiAoZS5wcmV2ZW50RGVmYXVsdCgpLCBlLnN0b3BQcm9wYWdhdGlvbigpKSwgcmV0dXJuVmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50TmFtZV0gPSBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50TmFtZV0gfHwgW10sIGlucHV0LmlucHV0bWFzay5ldmVudHNbZXZlbnROYW1lXS5wdXNoKGV2KSwgXG4gICAgICAgICAgICAgICAgWyBcInN1Ym1pdFwiLCBcInJlc2V0XCIgXS5pbmNsdWRlcyhldmVudE5hbWUpID8gbnVsbCAhPT0gaW5wdXQuZm9ybSAmJiAkKGlucHV0LmZvcm0pLm9uKGV2ZW50TmFtZSwgZXYuYmluZChpbnB1dCkpIDogJChpbnB1dCkub24oZXZlbnROYW1lLCBldik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb2ZmOiBmdW5jdGlvbiBvZmYoaW5wdXQsIGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0LmlucHV0bWFzayAmJiBpbnB1dC5pbnB1dG1hc2suZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkID0gaW5wdXQuaW5wdXRtYXNrLmRlcGVuZGVuY3lMaWIsIGV2ZW50cyA9IGlucHV0LmlucHV0bWFzay5ldmVudHM7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGV2ZW50TmFtZSBpbiBldmVudCAmJiAoZXZlbnRzID0gW10sIGV2ZW50c1tldmVudF0gPSBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50XSksIFxuICAgICAgICAgICAgICAgICAgICBldmVudHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGV2QXJyID0gZXZlbnRzW2V2ZW50TmFtZV07IDAgPCBldkFyci5sZW5ndGg7ICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldiA9IGV2QXJyLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsgXCJzdWJtaXRcIiwgXCJyZXNldFwiIF0uaW5jbHVkZXMoZXZlbnROYW1lKSA/IG51bGwgIT09IGlucHV0LmZvcm0gJiYgJChpbnB1dC5mb3JtKS5vZmYoZXZlbnROYW1lLCBldikgOiAkKGlucHV0KS5vZmYoZXZlbnROYW1lLCBldik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgaW5wdXQuaW5wdXRtYXNrLmV2ZW50c1tldmVudE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBleHBvcnRzLkV2ZW50UnVsZXIgPSBFdmVudFJ1bGVyO1xuICAgIH0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gICAgICAgICAgICB2YWx1ZTogITBcbiAgICAgICAgfSksIGV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcbiAgICAgICAgdmFyIF9qcXVlcnkgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oOCkpO1xuICAgICAgICBmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiBvYmpcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZvaWQgMCA9PT0gX2pxdWVyeS5kZWZhdWx0KSB0aHJvdyBcImpRdWVyeSBub3QgbG9hZGVkIVwiO1xuICAgICAgICB2YXIgX2RlZmF1bHQgPSBfanF1ZXJ5LmRlZmF1bHQ7XG4gICAgICAgIGV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0O1xuICAgIH0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gICAgICAgICAgICB2YWx1ZTogITBcbiAgICAgICAgfSksIGV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcbiAgICAgICAgdmFyIF9kZWZhdWx0ID0gXCJ1bmRlZmluZWRcIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDogbmV3IChldmFsKFwicmVxdWlyZSgnanNkb20nKS5KU0RPTVwiKSkoXCJcIikud2luZG93O1xuICAgICAgICBleHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDtcbiAgICB9LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICAgICAgICAgICAgdmFsdWU6ICEwXG4gICAgICAgIH0pLCBleHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDtcbiAgICAgICAgdmFyIGVzY2FwZVJlZ2V4UmVnZXggPSBuZXcgUmVnRXhwKFwiKFxcXFxcIiArIFsgXCIvXCIsIFwiLlwiLCBcIipcIiwgXCIrXCIsIFwiP1wiLCBcInxcIiwgXCIoXCIsIFwiKVwiLCBcIltcIiwgXCJdXCIsIFwie1wiLCBcIn1cIiwgXCJcXFxcXCIsIFwiJFwiLCBcIl5cIiBdLmpvaW4oXCJ8XFxcXFwiKSArIFwiKVwiLCBcImdpbVwiKTtcbiAgICAgICAgZnVuY3Rpb24gX2RlZmF1bHQoc3RyKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UoZXNjYXBlUmVnZXhSZWdleCwgXCJcXFxcJDFcIik7XG4gICAgICAgIH1cbiAgICB9LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICAgICAgICAgICAgdmFsdWU6ICEwXG4gICAgICAgIH0pLCBleHBvcnRzLmRlZmF1bHQgPSB2b2lkIDAsIF9fd2VicGFja19yZXF1aXJlX18oMTYpLCBfX3dlYnBhY2tfcmVxdWlyZV9fKDIwKSwgXG4gICAgICAgIF9fd2VicGFja19yZXF1aXJlX18oMjEpLCBfX3dlYnBhY2tfcmVxdWlyZV9fKDIyKTtcbiAgICAgICAgdmFyIF9pbnB1dG1hc2syID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDEpKTtcbiAgICAgICAgZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHtcbiAgICAgICAgICAgIHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDogb2JqXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBfZGVmYXVsdCA9IF9pbnB1dG1hc2syLmRlZmF1bHQ7XG4gICAgICAgIGV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0O1xuICAgIH0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgdmFyIF9pbnB1dG1hc2sgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMSkpO1xuICAgICAgICBmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiBvYmpcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgX2lucHV0bWFzay5kZWZhdWx0LmV4dGVuZERlZmluaXRpb25zKHtcbiAgICAgICAgICAgIEE6IHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiW0EtWmEtelxcdTA0MTAtXFx1MDQ0ZlxcdTA0MDFcXHUwNDUxXFx4YzAtXFx4ZmZcXHhiNV1cIixcbiAgICAgICAgICAgICAgICBjYXNpbmc6IFwidXBwZXJcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiJlwiOiB7XG4gICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTlBLVphLXpcXHUwNDEwLVxcdTA0NGZcXHUwNDAxXFx1MDQ1MVxceGMwLVxceGZmXFx4YjVdXCIsXG4gICAgICAgICAgICAgICAgY2FzaW5nOiBcInVwcGVyXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcIiNcIjoge1xuICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbMC05QS1GYS1mXVwiLFxuICAgICAgICAgICAgICAgIGNhc2luZzogXCJ1cHBlclwiXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgaXBWYWxpZGF0b3JSZWdleCA9IG5ldyBSZWdFeHAoXCIyNVswLTVdfDJbMC00XVswLTldfFswMV1bMC05XVswLTldXCIpO1xuICAgICAgICBmdW5jdGlvbiBpcFZhbGlkYXRvcihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgcmV0dXJuIGNocnMgPSAtMSA8IHBvcyAtIDEgJiYgXCIuXCIgIT09IG1hc2tzZXQuYnVmZmVyW3BvcyAtIDFdID8gKGNocnMgPSBtYXNrc2V0LmJ1ZmZlcltwb3MgLSAxXSArIGNocnMsIFxuICAgICAgICAgICAgLTEgPCBwb3MgLSAyICYmIFwiLlwiICE9PSBtYXNrc2V0LmJ1ZmZlcltwb3MgLSAyXSA/IG1hc2tzZXQuYnVmZmVyW3BvcyAtIDJdICsgY2hycyA6IFwiMFwiICsgY2hycykgOiBcIjAwXCIgKyBjaHJzLCBcbiAgICAgICAgICAgIGlwVmFsaWRhdG9yUmVnZXgudGVzdChjaHJzKTtcbiAgICAgICAgfVxuICAgICAgICBfaW5wdXRtYXNrLmRlZmF1bHQuZXh0ZW5kQWxpYXNlcyh7XG4gICAgICAgICAgICBjc3N1bml0OiB7XG4gICAgICAgICAgICAgICAgcmVnZXg6IFwiWystXT9bMC05XStcXFxcLj8oWzAtOV0rKT8ocHh8ZW18cmVtfGV4fCV8aW58Y218bW18cHR8cGMpXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1cmw6IHtcbiAgICAgICAgICAgICAgICByZWdleDogXCIoaHR0cHM/fGZ0cCk6Ly8uKlwiLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6ICExLFxuICAgICAgICAgICAgICAgIGtlZXBTdGF0aWM6ICExLFxuICAgICAgICAgICAgICAgIHRhYlRocm91Z2g6ICEwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXA6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcImlbaVtpXV0ualtqW2pdXS5rW2tba11dLmxbbFtsXV1cIixcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBpOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGlwVmFsaWRhdG9yXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGo6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogaXBWYWxpZGF0b3JcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgazoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBpcFZhbGlkYXRvclxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBsOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGlwVmFsaWRhdG9yXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uVW5NYXNrOiBmdW5jdGlvbiBvblVuTWFzayhtYXNrZWRWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza2VkVmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwibnVtZXJpY1wiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW1haWw6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcIip7MSw2NH1bLip7MSw2NH1dWy4qezEsNjR9XVsuKnsxLDYzfV1ALXsxLDYzfS4tezEsNjN9Wy4tezEsNjN9XVsuLXsxLDYzfV1cIixcbiAgICAgICAgICAgICAgICBncmVlZHk6ICExLFxuICAgICAgICAgICAgICAgIGNhc2luZzogXCJsb3dlclwiLFxuICAgICAgICAgICAgICAgIG9uQmVmb3JlUGFzdGU6IGZ1bmN0aW9uIG9uQmVmb3JlUGFzdGUocGFzdGVkVmFsdWUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhc3RlZFZhbHVlID0gcGFzdGVkVmFsdWUudG9Mb3dlckNhc2UoKSwgcGFzdGVkVmFsdWUucmVwbGFjZShcIm1haWx0bzpcIiwgXCJcIik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBcIipcIjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTlcXHVmZjExLVxcdWZmMTlBLVphLXpcXHUwNDEwLVxcdTA0NGZcXHUwNDAxXFx1MDQ1MVxceGMwLVxceGZmXFx4YjUhIyQlJicqKy89P15fYHt8fX4tXVwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiLVwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOUEtWmEtei1dXCJcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25Vbk1hc2s6IGZ1bmN0aW9uIG9uVW5NYXNrKG1hc2tlZFZhbHVlLCB1bm1hc2tlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXNrZWRWYWx1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGlucHV0bW9kZTogXCJlbWFpbFwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWFjOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCIjIzojIzojIzojIzojIzojI1wiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmluOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJWezEzfTl7NH1cIixcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBWOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiW0EtSEotTlBSLVphLWhqLW5wci16XFxcXGRdXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IFwidXBwZXJcIlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjbGVhckluY29tcGxldGU6ICEwLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6ICEwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3NuOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCI5OTktOTktOTk5OVwiLFxuICAgICAgICAgICAgICAgIHBvc3RWYWxpZGF0aW9uOiBmdW5jdGlvbiBwb3N0VmFsaWRhdGlvbihidWZmZXIsIHBvcywgYywgY3VycmVudFJlc3VsdCwgb3B0cywgbWFza3NldCwgc3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAvXig/ITIxOS0wOS05OTk5fDA3OC0wNS0xMTIwKSg/ITY2NnwwMDB8OS57Mn0pLnszfS0oPyEwMCkuezJ9LSg/ITB7NH0pLns0fSQvLnRlc3QoYnVmZmVyLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgICAgICAgICAgIHZhbHVlOiAhMFxuICAgICAgICB9KSwgZXhwb3J0cy5nZW5lcmF0ZU1hc2tTZXQgPSBnZW5lcmF0ZU1hc2tTZXQsIGV4cG9ydHMuYW5hbHlzZU1hc2sgPSBhbmFseXNlTWFzaztcbiAgICAgICAgdmFyIF9pbnB1dG1hc2sgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMTIpKTtcbiAgICAgICAgZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHtcbiAgICAgICAgICAgIHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDogb2JqXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdlbmVyYXRlTWFza1NldChvcHRzLCBub2NhY2hlKSB7XG4gICAgICAgICAgICB2YXIgbXM7XG4gICAgICAgICAgICBmdW5jdGlvbiBnZW5lcmF0ZU1hc2sobWFzaywgbWV0YWRhdGEsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVnZXhNYXNrID0gITEsIG1hc2tzZXREZWZpbml0aW9uLCBtYXNrZGVmS2V5O1xuICAgICAgICAgICAgICAgIGlmIChudWxsICE9PSBtYXNrICYmIFwiXCIgIT09IG1hc2sgfHwgKHJlZ2V4TWFzayA9IG51bGwgIT09IG9wdHMucmVnZXgsIG1hc2sgPSByZWdleE1hc2sgPyAobWFzayA9IG9wdHMucmVnZXgsIFxuICAgICAgICAgICAgICAgIG1hc2sucmVwbGFjZSgvXihcXF4pKC4qKShcXCQpJC8sIFwiJDJcIikpIDogKHJlZ2V4TWFzayA9ICEwLCBcIi4qXCIpKSwgMSA9PT0gbWFzay5sZW5ndGggJiYgITEgPT09IG9wdHMuZ3JlZWR5ICYmIDAgIT09IG9wdHMucmVwZWF0ICYmIChvcHRzLnBsYWNlaG9sZGVyID0gXCJcIiksIFxuICAgICAgICAgICAgICAgIDAgPCBvcHRzLnJlcGVhdCB8fCBcIipcIiA9PT0gb3B0cy5yZXBlYXQgfHwgXCIrXCIgPT09IG9wdHMucmVwZWF0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXBlYXRTdGFydCA9IFwiKlwiID09PSBvcHRzLnJlcGVhdCA/IDAgOiBcIitcIiA9PT0gb3B0cy5yZXBlYXQgPyAxIDogb3B0cy5yZXBlYXQ7XG4gICAgICAgICAgICAgICAgICAgIG1hc2sgPSBvcHRzLmdyb3VwbWFya2VyWzBdICsgbWFzayArIG9wdHMuZ3JvdXBtYXJrZXJbMV0gKyBvcHRzLnF1YW50aWZpZXJtYXJrZXJbMF0gKyByZXBlYXRTdGFydCArIFwiLFwiICsgb3B0cy5yZXBlYXQgKyBvcHRzLnF1YW50aWZpZXJtYXJrZXJbMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrZGVmS2V5ID0gcmVnZXhNYXNrID8gXCJyZWdleF9cIiArIG9wdHMucmVnZXggOiBvcHRzLm51bWVyaWNJbnB1dCA/IG1hc2suc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBtYXNrLCBcbiAgICAgICAgICAgICAgICAhMSAhPT0gb3B0cy5rZWVwU3RhdGljICYmIChtYXNrZGVmS2V5ID0gXCJrc19cIiArIG1hc2tkZWZLZXkpLCB2b2lkIDAgPT09IElucHV0bWFzay5wcm90b3R5cGUubWFza3NDYWNoZVttYXNrZGVmS2V5XSB8fCAhMCA9PT0gbm9jYWNoZSA/IChtYXNrc2V0RGVmaW5pdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgbWFzazogbWFzayxcbiAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuOiBJbnB1dG1hc2sucHJvdG90eXBlLmFuYWx5c2VNYXNrKG1hc2ssIHJlZ2V4TWFzaywgb3B0cyksXG4gICAgICAgICAgICAgICAgICAgIHZhbGlkUG9zaXRpb25zOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgX2J1ZmZlcjogdm9pZCAwLFxuICAgICAgICAgICAgICAgICAgICBidWZmZXI6IHZvaWQgMCxcbiAgICAgICAgICAgICAgICAgICAgdGVzdHM6IHt9LFxuICAgICAgICAgICAgICAgICAgICBleGNsdWRlczoge30sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiBtZXRhZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgbWFza0xlbmd0aDogdm9pZCAwLFxuICAgICAgICAgICAgICAgICAgICBqaXRPZmZzZXQ6IHt9XG4gICAgICAgICAgICAgICAgfSwgITAgIT09IG5vY2FjaGUgJiYgKElucHV0bWFzay5wcm90b3R5cGUubWFza3NDYWNoZVttYXNrZGVmS2V5XSA9IG1hc2tzZXREZWZpbml0aW9uLCBcbiAgICAgICAgICAgICAgICBtYXNrc2V0RGVmaW5pdGlvbiA9IF9pbnB1dG1hc2suZGVmYXVsdC5leHRlbmQoITAsIHt9LCBJbnB1dG1hc2sucHJvdG90eXBlLm1hc2tzQ2FjaGVbbWFza2RlZktleV0pKSkgOiBtYXNrc2V0RGVmaW5pdGlvbiA9IF9pbnB1dG1hc2suZGVmYXVsdC5leHRlbmQoITAsIHt9LCBJbnB1dG1hc2sucHJvdG90eXBlLm1hc2tzQ2FjaGVbbWFza2RlZktleV0pLCBcbiAgICAgICAgICAgICAgICBtYXNrc2V0RGVmaW5pdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIG9wdHMubWFzayAmJiAob3B0cy5tYXNrID0gb3B0cy5tYXNrKG9wdHMpKSwgQXJyYXkuaXNBcnJheShvcHRzLm1hc2spKSB7XG4gICAgICAgICAgICAgICAgaWYgKDEgPCBvcHRzLm1hc2subGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIG51bGwgPT09IG9wdHMua2VlcFN0YXRpYyAmJiAob3B0cy5rZWVwU3RhdGljID0gITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYWx0TWFzayA9IG9wdHMuZ3JvdXBtYXJrZXJbMF07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAob3B0cy5pc1JUTCA/IG9wdHMubWFzay5yZXZlcnNlKCkgOiBvcHRzLm1hc2spLmZvckVhY2goZnVuY3Rpb24obXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAxIDwgYWx0TWFzay5sZW5ndGggJiYgKGFsdE1hc2sgKz0gb3B0cy5ncm91cG1hcmtlclsxXSArIG9wdHMuYWx0ZXJuYXRvcm1hcmtlciArIG9wdHMuZ3JvdXBtYXJrZXJbMF0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIHZvaWQgMCAhPT0gbXNrLm1hc2sgJiYgXCJmdW5jdGlvblwiICE9IHR5cGVvZiBtc2subWFzayA/IGFsdE1hc2sgKz0gbXNrLm1hc2sgOiBhbHRNYXNrICs9IG1zaztcbiAgICAgICAgICAgICAgICAgICAgfSksIGFsdE1hc2sgKz0gb3B0cy5ncm91cG1hcmtlclsxXSwgZ2VuZXJhdGVNYXNrKGFsdE1hc2ssIG9wdHMubWFzaywgb3B0cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG9wdHMubWFzayA9IG9wdHMubWFzay5wb3AoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsID09PSBvcHRzLmtlZXBTdGF0aWMgJiYgKG9wdHMua2VlcFN0YXRpYyA9ICExKSwgbXMgPSBvcHRzLm1hc2sgJiYgdm9pZCAwICE9PSBvcHRzLm1hc2subWFzayAmJiBcImZ1bmN0aW9uXCIgIT0gdHlwZW9mIG9wdHMubWFzay5tYXNrID8gZ2VuZXJhdGVNYXNrKG9wdHMubWFzay5tYXNrLCBvcHRzLm1hc2ssIG9wdHMpIDogZ2VuZXJhdGVNYXNrKG9wdHMubWFzaywgb3B0cy5tYXNrLCBvcHRzKSwgXG4gICAgICAgICAgICBtcztcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBhbmFseXNlTWFzayhtYXNrLCByZWdleE1hc2ssIG9wdHMpIHtcbiAgICAgICAgICAgIHZhciB0b2tlbml6ZXIgPSAvKD86Wz8qK118XFx7WzAtOSsqXSsoPzosWzAtOSsqXSopPyg/OlxcfFswLTkrKl0qKT9cXH0pfFteLj8qK14ke1tdKCl8XFxcXF0rfC4vZywgcmVnZXhUb2tlbml6ZXIgPSAvXFxbXFxeP10/KD86W15cXFxcXFxdXSt8XFxcXFtcXFNcXHNdPykqXT98XFxcXCg/OjAoPzpbMC0zXVswLTddezAsMn18WzQtN11bMC03XT8pP3xbMS05XVswLTldKnx4WzAtOUEtRmEtZl17Mn18dVswLTlBLUZhLWZdezR9fGNbQS1aYS16XXxbXFxTXFxzXT8pfFxcKCg/OlxcP1s6PSFdPyk/fCg/Ols/KitdfFxce1swLTldKyg/OixbMC05XSopP1xcfSlcXD8/fFteLj8qK14ke1soKXxcXFxcXSt8Li9nLCBlc2NhcGVkID0gITEsIGN1cnJlbnRUb2tlbiA9IG5ldyBNYXNrVG9rZW4oKSwgbWF0Y2gsIG0sIG9wZW5lbmluZ3MgPSBbXSwgbWFza1Rva2VucyA9IFtdLCBvcGVuaW5nVG9rZW4sIGN1cnJlbnRPcGVuaW5nVG9rZW4sIGFsdGVybmF0b3IsIGxhc3RNYXRjaCwgY2xvc2VSZWdleEdyb3VwID0gITE7XG4gICAgICAgICAgICBmdW5jdGlvbiBNYXNrVG9rZW4oaXNHcm91cCwgaXNPcHRpb25hbCwgaXNRdWFudGlmaWVyLCBpc0FsdGVybmF0b3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1hdGNoZXMgPSBbXSwgdGhpcy5vcGVuR3JvdXAgPSBpc0dyb3VwIHx8ICExLCB0aGlzLmFsdGVybmF0b3JHcm91cCA9ICExLCB0aGlzLmlzR3JvdXAgPSBpc0dyb3VwIHx8ICExLCBcbiAgICAgICAgICAgICAgICB0aGlzLmlzT3B0aW9uYWwgPSBpc09wdGlvbmFsIHx8ICExLCB0aGlzLmlzUXVhbnRpZmllciA9IGlzUXVhbnRpZmllciB8fCAhMSwgdGhpcy5pc0FsdGVybmF0b3IgPSBpc0FsdGVybmF0b3IgfHwgITEsIFxuICAgICAgICAgICAgICAgIHRoaXMucXVhbnRpZmllciA9IHtcbiAgICAgICAgICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgICAgICAgICBtYXg6IDFcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0VGVzdERlZmluaXRpb24obXRva2VuLCBlbGVtZW50LCBwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gdm9pZCAwICE9PSBwb3NpdGlvbiA/IHBvc2l0aW9uIDogbXRva2VuLm1hdGNoZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBwcmV2TWF0Y2ggPSBtdG9rZW4ubWF0Y2hlc1twb3NpdGlvbiAtIDFdO1xuICAgICAgICAgICAgICAgIGlmIChyZWdleE1hc2spIDAgPT09IGVsZW1lbnQuaW5kZXhPZihcIltcIikgfHwgZXNjYXBlZCAmJiAvXFxcXGR8XFxcXHN8XFxcXHddL2kudGVzdChlbGVtZW50KSB8fCBcIi5cIiA9PT0gZWxlbWVudCA/IG10b2tlbi5tYXRjaGVzLnNwbGljZShwb3NpdGlvbisrLCAwLCB7XG4gICAgICAgICAgICAgICAgICAgIGZuOiBuZXcgUmVnRXhwKGVsZW1lbnQsIG9wdHMuY2FzaW5nID8gXCJpXCIgOiBcIlwiKSxcbiAgICAgICAgICAgICAgICAgICAgc3RhdGljOiAhMSxcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxpdHk6ICExLFxuICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja01hcmtlcjogdm9pZCAwID09PSBwcmV2TWF0Y2ggPyBcIm1hc3RlclwiIDogcHJldk1hdGNoLmRlZiAhPT0gZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICBkZWY6IGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiB2b2lkIDAsXG4gICAgICAgICAgICAgICAgICAgIG5hdGl2ZURlZjogZWxlbWVudFxuICAgICAgICAgICAgICAgIH0pIDogKGVzY2FwZWQgJiYgKGVsZW1lbnQgPSBlbGVtZW50W2VsZW1lbnQubGVuZ3RoIC0gMV0pLCBlbGVtZW50LnNwbGl0KFwiXCIpLmZvckVhY2goZnVuY3Rpb24obG1udCwgbmR4KSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZNYXRjaCA9IG10b2tlbi5tYXRjaGVzW3Bvc2l0aW9uIC0gMV0sIG10b2tlbi5tYXRjaGVzLnNwbGljZShwb3NpdGlvbisrLCAwLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmbjogL1thLXpdL2kudGVzdChvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgfHwgbG1udCkgPyBuZXcgUmVnRXhwKFwiW1wiICsgKG9wdHMuc3RhdGljRGVmaW5pdGlvblN5bWJvbCB8fCBsbW50KSArIFwiXVwiLCBvcHRzLmNhc2luZyA/IFwiaVwiIDogXCJcIikgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGljOiAhMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsaXR5OiAhMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0Jsb2NrTWFya2VyOiB2b2lkIDAgPT09IHByZXZNYXRjaCA/IFwibWFzdGVyXCIgOiBwcmV2TWF0Y2guZGVmICE9PSBsbW50ICYmICEwICE9PSBwcmV2TWF0Y2guc3RhdGljLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgfHwgbG1udCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiB2b2lkIDAgIT09IG9wdHMuc3RhdGljRGVmaW5pdGlvblN5bWJvbCA/IGxtbnQgOiB2b2lkIDAsXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVEZWY6IChlc2NhcGVkID8gXCInXCIgOiBcIlwiKSArIGxtbnRcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSkpLCBlc2NhcGVkID0gITE7IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWFza2RlZiA9IG9wdHMuZGVmaW5pdGlvbnMgJiYgb3B0cy5kZWZpbml0aW9uc1tlbGVtZW50XSB8fCBvcHRzLnVzZVByb3RvdHlwZURlZmluaXRpb25zICYmIElucHV0bWFzay5wcm90b3R5cGUuZGVmaW5pdGlvbnNbZWxlbWVudF07XG4gICAgICAgICAgICAgICAgICAgIG1hc2tkZWYgJiYgIWVzY2FwZWQgPyBtdG9rZW4ubWF0Y2hlcy5zcGxpY2UocG9zaXRpb24rKywgMCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm46IG1hc2tkZWYudmFsaWRhdG9yID8gXCJzdHJpbmdcIiA9PSB0eXBlb2YgbWFza2RlZi52YWxpZGF0b3IgPyBuZXcgUmVnRXhwKG1hc2tkZWYudmFsaWRhdG9yLCBvcHRzLmNhc2luZyA/IFwiaVwiIDogXCJcIikgOiBuZXcgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXN0ID0gbWFza2RlZi52YWxpZGF0b3I7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KCkgOiBuZXcgUmVnRXhwKFwiLlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRpYzogbWFza2RlZi5zdGF0aWMgfHwgITEsXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbGl0eTogITEsXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja01hcmtlcjogdm9pZCAwID09PSBwcmV2TWF0Y2ggPyBcIm1hc3RlclwiIDogcHJldk1hdGNoLmRlZiAhPT0gKG1hc2tkZWYuZGVmaW5pdGlvblN5bWJvbCB8fCBlbGVtZW50KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogbWFza2RlZi5jYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICBkZWY6IG1hc2tkZWYuZGVmaW5pdGlvblN5bWJvbCB8fCBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IG1hc2tkZWYucGxhY2Vob2xkZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVEZWY6IGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBnZW5lcmF0ZWQ6IG1hc2tkZWYuZ2VuZXJhdGVkXG4gICAgICAgICAgICAgICAgICAgIH0pIDogKG10b2tlbi5tYXRjaGVzLnNwbGljZShwb3NpdGlvbisrLCAwLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmbjogL1thLXpdL2kudGVzdChvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgfHwgZWxlbWVudCkgPyBuZXcgUmVnRXhwKFwiW1wiICsgKG9wdHMuc3RhdGljRGVmaW5pdGlvblN5bWJvbCB8fCBlbGVtZW50KSArIFwiXVwiLCBvcHRzLmNhc2luZyA/IFwiaVwiIDogXCJcIikgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGljOiAhMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsaXR5OiAhMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0Jsb2NrTWFya2VyOiB2b2lkIDAgPT09IHByZXZNYXRjaCA/IFwibWFzdGVyXCIgOiBwcmV2TWF0Y2guZGVmICE9PSBlbGVtZW50ICYmICEwICE9PSBwcmV2TWF0Y2guc3RhdGljLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgfHwgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiB2b2lkIDAgIT09IG9wdHMuc3RhdGljRGVmaW5pdGlvblN5bWJvbCA/IGVsZW1lbnQgOiB2b2lkIDAsXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVEZWY6IChlc2NhcGVkID8gXCInXCIgOiBcIlwiKSArIGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgfSksIGVzY2FwZWQgPSAhMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gdmVyaWZ5R3JvdXBNYXJrZXIobWFza1Rva2VuKSB7XG4gICAgICAgICAgICAgICAgbWFza1Rva2VuICYmIG1hc2tUb2tlbi5tYXRjaGVzICYmIG1hc2tUb2tlbi5tYXRjaGVzLmZvckVhY2goZnVuY3Rpb24odG9rZW4sIG5keCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dFRva2VuID0gbWFza1Rva2VuLm1hdGNoZXNbbmR4ICsgMV07XG4gICAgICAgICAgICAgICAgICAgICh2b2lkIDAgPT09IG5leHRUb2tlbiB8fCB2b2lkIDAgPT09IG5leHRUb2tlbi5tYXRjaGVzIHx8ICExID09PSBuZXh0VG9rZW4uaXNRdWFudGlmaWVyKSAmJiB0b2tlbiAmJiB0b2tlbi5pc0dyb3VwICYmICh0b2tlbi5pc0dyb3VwID0gITEsIFxuICAgICAgICAgICAgICAgICAgICByZWdleE1hc2sgfHwgKGluc2VydFRlc3REZWZpbml0aW9uKHRva2VuLCBvcHRzLmdyb3VwbWFya2VyWzBdLCAwKSwgITAgIT09IHRva2VuLm9wZW5Hcm91cCAmJiBpbnNlcnRUZXN0RGVmaW5pdGlvbih0b2tlbiwgb3B0cy5ncm91cG1hcmtlclsxXSkpKSwgXG4gICAgICAgICAgICAgICAgICAgIHZlcmlmeUdyb3VwTWFya2VyKHRva2VuKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlZmF1bHRDYXNlKCkge1xuICAgICAgICAgICAgICAgIGlmICgwIDwgb3BlbmVuaW5ncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRPcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzW29wZW5lbmluZ3MubGVuZ3RoIC0gMV0sIGluc2VydFRlc3REZWZpbml0aW9uKGN1cnJlbnRPcGVuaW5nVG9rZW4sIG0pLCBcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudE9wZW5pbmdUb2tlbi5pc0FsdGVybmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IgPSBvcGVuZW5pbmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbW5keCA9IDA7IG1uZHggPCBhbHRlcm5hdG9yLm1hdGNoZXMubGVuZ3RoOyBtbmR4KyspIGFsdGVybmF0b3IubWF0Y2hlc1ttbmR4XS5pc0dyb3VwICYmIChhbHRlcm5hdG9yLm1hdGNoZXNbbW5keF0uaXNHcm91cCA9ICExKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIDAgPCBvcGVuZW5pbmdzLmxlbmd0aCA/IChjdXJyZW50T3BlbmluZ1Rva2VuID0gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRPcGVuaW5nVG9rZW4ubWF0Y2hlcy5wdXNoKGFsdGVybmF0b3IpKSA6IGN1cnJlbnRUb2tlbi5tYXRjaGVzLnB1c2goYWx0ZXJuYXRvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaW5zZXJ0VGVzdERlZmluaXRpb24oY3VycmVudFRva2VuLCBtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJldmVyc2VUb2tlbnMobWFza1Rva2VuKSB7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gcmV2ZXJzZVN0YXRpYyhzdCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3QgPT09IG9wdHMub3B0aW9uYWxtYXJrZXJbMF0gPyBzdCA9IG9wdHMub3B0aW9uYWxtYXJrZXJbMV0gOiBzdCA9PT0gb3B0cy5vcHRpb25hbG1hcmtlclsxXSA/IHN0ID0gb3B0cy5vcHRpb25hbG1hcmtlclswXSA6IHN0ID09PSBvcHRzLmdyb3VwbWFya2VyWzBdID8gc3QgPSBvcHRzLmdyb3VwbWFya2VyWzFdIDogc3QgPT09IG9wdHMuZ3JvdXBtYXJrZXJbMV0gJiYgKHN0ID0gb3B0cy5ncm91cG1hcmtlclswXSksIFxuICAgICAgICAgICAgICAgICAgICBzdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgbWF0Y2ggaW4gbWFza1Rva2VuLm1hdGNoZXMgPSBtYXNrVG9rZW4ubWF0Y2hlcy5yZXZlcnNlKCksIG1hc2tUb2tlbi5tYXRjaGVzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1hc2tUb2tlbi5tYXRjaGVzLCBtYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGludE1hdGNoID0gcGFyc2VJbnQobWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdLmlzUXVhbnRpZmllciAmJiBtYXNrVG9rZW4ubWF0Y2hlc1tpbnRNYXRjaCArIDFdICYmIG1hc2tUb2tlbi5tYXRjaGVzW2ludE1hdGNoICsgMV0uaXNHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHF0ID0gbWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuLm1hdGNoZXMuc3BsaWNlKG1hdGNoLCAxKSwgbWFza1Rva2VuLm1hdGNoZXMuc3BsaWNlKGludE1hdGNoICsgMSwgMCwgcXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZvaWQgMCAhPT0gbWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdLm1hdGNoZXMgPyBtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF0gPSByZXZlcnNlVG9rZW5zKG1hc2tUb2tlbi5tYXRjaGVzW21hdGNoXSkgOiBtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF0gPSByZXZlcnNlU3RhdGljKG1hc2tUb2tlbi5tYXRjaGVzW21hdGNoXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrVG9rZW47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBncm91cGlmeShtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdyb3VwVG9rZW4gPSBuZXcgTWFza1Rva2VuKCEwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ3JvdXBUb2tlbi5vcGVuR3JvdXAgPSAhMSwgZ3JvdXBUb2tlbi5tYXRjaGVzID0gbWF0Y2hlcywgZ3JvdXBUb2tlbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsb3NlR3JvdXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9wZW5pbmdUb2tlbiA9IG9wZW5lbmluZ3MucG9wKCksIG9wZW5pbmdUb2tlbi5vcGVuR3JvdXAgPSAhMSwgdm9pZCAwICE9PSBvcGVuaW5nVG9rZW4pIGlmICgwIDwgb3BlbmVuaW5ncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRPcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzW29wZW5lbmluZ3MubGVuZ3RoIC0gMV0sIGN1cnJlbnRPcGVuaW5nVG9rZW4ubWF0Y2hlcy5wdXNoKG9wZW5pbmdUb2tlbiksIFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuLmlzQWx0ZXJuYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRvciA9IG9wZW5lbmluZ3MucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBtbmR4ID0gMDsgbW5keCA8IGFsdGVybmF0b3IubWF0Y2hlcy5sZW5ndGg7IG1uZHgrKykgYWx0ZXJuYXRvci5tYXRjaGVzW21uZHhdLmlzR3JvdXAgPSAhMSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdG9yLm1hdGNoZXNbbW5keF0uYWx0ZXJuYXRvckdyb3VwID0gITE7XG4gICAgICAgICAgICAgICAgICAgICAgICAwIDwgb3BlbmVuaW5ncy5sZW5ndGggPyAoY3VycmVudE9wZW5pbmdUb2tlbiA9IG9wZW5lbmluZ3Nbb3BlbmVuaW5ncy5sZW5ndGggLSAxXSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuLm1hdGNoZXMucHVzaChhbHRlcm5hdG9yKSkgOiBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wdXNoKGFsdGVybmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGN1cnJlbnRUb2tlbi5tYXRjaGVzLnB1c2gob3BlbmluZ1Rva2VuKTsgZWxzZSBkZWZhdWx0Q2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZ3JvdXBRdWFudGlmaWVyKG1hdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGFzdE1hdGNoID0gbWF0Y2hlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFzdE1hdGNoLmlzUXVhbnRpZmllciAmJiAobGFzdE1hdGNoID0gZ3JvdXBpZnkoWyBtYXRjaGVzLnBvcCgpLCBsYXN0TWF0Y2ggXSkpLCBcbiAgICAgICAgICAgICAgICBsYXN0TWF0Y2g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHJlZ2V4TWFzayAmJiAob3B0cy5vcHRpb25hbG1hcmtlclswXSA9IHZvaWQgMCwgb3B0cy5vcHRpb25hbG1hcmtlclsxXSA9IHZvaWQgMCk7IG1hdGNoID0gcmVnZXhNYXNrID8gcmVnZXhUb2tlbml6ZXIuZXhlYyhtYXNrKSA6IHRva2VuaXplci5leGVjKG1hc2spOyApIHtcbiAgICAgICAgICAgICAgICBpZiAobSA9IG1hdGNoWzBdLCByZWdleE1hc2spIHN3aXRjaCAobS5jaGFyQXQoMCkpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCI/XCI6XG4gICAgICAgICAgICAgICAgICAgIG0gPSBcInswLDF9XCI7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICBjYXNlIFwiK1wiOlxuICAgICAgICAgICAgICAgICAgY2FzZSBcIipcIjpcbiAgICAgICAgICAgICAgICAgICAgbSA9IFwie1wiICsgbSArIFwifVwiO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcInxcIjpcbiAgICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IG9wZW5lbmluZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWx0UmVnZXhHcm91cCA9IGdyb3VwaWZ5KGN1cnJlbnRUb2tlbi5tYXRjaGVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsdFJlZ2V4R3JvdXAub3Blbkdyb3VwID0gITAsIG9wZW5lbmluZ3MucHVzaChhbHRSZWdleEdyb3VwKSwgY3VycmVudFRva2VuLm1hdGNoZXMgPSBbXSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9zZVJlZ2V4R3JvdXAgPSAhMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGVzY2FwZWQpIGRlZmF1bHRDYXNlKCk7IGVsc2Ugc3dpdGNoIChtLmNoYXJBdCgwKSkge1xuICAgICAgICAgICAgICAgICAgY2FzZSBcIiRcIjpcbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJeXCI6XG4gICAgICAgICAgICAgICAgICAgIHJlZ2V4TWFzayB8fCBkZWZhdWx0Q2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcIig/PVwiOlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcIig/IVwiOlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcIig/PD1cIjpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCIoPzwhXCI6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICBjYXNlIG9wdHMuZXNjYXBlQ2hhcjpcbiAgICAgICAgICAgICAgICAgICAgZXNjYXBlZCA9ICEwLCByZWdleE1hc2sgJiYgZGVmYXVsdENhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5vcHRpb25hbG1hcmtlclsxXTpcbiAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5ncm91cG1hcmtlclsxXTpcbiAgICAgICAgICAgICAgICAgICAgY2xvc2VHcm91cCgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBvcHRzLm9wdGlvbmFsbWFya2VyWzBdOlxuICAgICAgICAgICAgICAgICAgICBvcGVuZW5pbmdzLnB1c2gobmV3IE1hc2tUb2tlbighMSwgITApKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5ncm91cG1hcmtlclswXTpcbiAgICAgICAgICAgICAgICAgICAgb3BlbmVuaW5ncy5wdXNoKG5ldyBNYXNrVG9rZW4oITApKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5xdWFudGlmaWVybWFya2VyWzBdOlxuICAgICAgICAgICAgICAgICAgICB2YXIgcXVhbnRpZmllciA9IG5ldyBNYXNrVG9rZW4oITEsICExLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIG0gPSBtLnJlcGxhY2UoL1t7fV0vZywgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtcWogPSBtLnNwbGl0KFwifFwiKSwgbXEgPSBtcWpbMF0uc3BsaXQoXCIsXCIpLCBtcTAgPSBpc05hTihtcVswXSkgPyBtcVswXSA6IHBhcnNlSW50KG1xWzBdKSwgbXExID0gMSA9PT0gbXEubGVuZ3RoID8gbXEwIDogaXNOYU4obXFbMV0pID8gbXFbMV0gOiBwYXJzZUludChtcVsxXSk7XG4gICAgICAgICAgICAgICAgICAgIFwiKlwiICE9PSBtcTAgJiYgXCIrXCIgIT09IG1xMCB8fCAobXEwID0gXCIqXCIgPT09IG1xMSA/IDAgOiAxKSwgcXVhbnRpZmllci5xdWFudGlmaWVyID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluOiBtcTAsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXg6IG1xMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGppdDogbXFqWzFdXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gMCA8IG9wZW5lbmluZ3MubGVuZ3RoID8gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdLm1hdGNoZXMgOiBjdXJyZW50VG9rZW4ubWF0Y2hlcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoID0gbWF0Y2hlcy5wb3AoKSwgbWF0Y2guaXNBbHRlcm5hdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2gobWF0Y2gpLCBtYXRjaGVzID0gbWF0Y2gubWF0Y2hlcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBncm91cFRva2VuID0gbmV3IE1hc2tUb2tlbighMCksIHRtcE1hdGNoID0gbWF0Y2hlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMucHVzaChncm91cFRva2VuKSwgbWF0Y2hlcyA9IGdyb3VwVG9rZW4ubWF0Y2hlcywgbWF0Y2ggPSB0bXBNYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtYXRjaC5pc0dyb3VwIHx8IChtYXRjaCA9IGdyb3VwaWZ5KFsgbWF0Y2ggXSkpLCBtYXRjaGVzLnB1c2gobWF0Y2gpLCBtYXRjaGVzLnB1c2gocXVhbnRpZmllcik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICBjYXNlIG9wdHMuYWx0ZXJuYXRvcm1hcmtlcjpcbiAgICAgICAgICAgICAgICAgICAgaWYgKDAgPCBvcGVuZW5pbmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudE9wZW5pbmdUb2tlbiA9IG9wZW5lbmluZ3Nbb3BlbmVuaW5ncy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzdWJUb2tlbiA9IGN1cnJlbnRPcGVuaW5nVG9rZW4ubWF0Y2hlc1tjdXJyZW50T3BlbmluZ1Rva2VuLm1hdGNoZXMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TWF0Y2ggPSBjdXJyZW50T3BlbmluZ1Rva2VuLm9wZW5Hcm91cCAmJiAodm9pZCAwID09PSBzdWJUb2tlbi5tYXRjaGVzIHx8ICExID09PSBzdWJUb2tlbi5pc0dyb3VwICYmICExID09PSBzdWJUb2tlbi5pc0FsdGVybmF0b3IpID8gb3BlbmVuaW5ncy5wb3AoKSA6IGdyb3VwUXVhbnRpZmllcihjdXJyZW50T3BlbmluZ1Rva2VuLm1hdGNoZXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgbGFzdE1hdGNoID0gZ3JvdXBRdWFudGlmaWVyKGN1cnJlbnRUb2tlbi5tYXRjaGVzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RNYXRjaC5pc0FsdGVybmF0b3IpIG9wZW5lbmluZ3MucHVzaChsYXN0TWF0Y2gpOyBlbHNlIGlmIChsYXN0TWF0Y2guYWx0ZXJuYXRvckdyb3VwID8gKGFsdGVybmF0b3IgPSBvcGVuZW5pbmdzLnBvcCgpLCBcbiAgICAgICAgICAgICAgICAgICAgbGFzdE1hdGNoLmFsdGVybmF0b3JHcm91cCA9ICExKSA6IGFsdGVybmF0b3IgPSBuZXcgTWFza1Rva2VuKCExLCAhMSwgITEsICEwKSwgYWx0ZXJuYXRvci5tYXRjaGVzLnB1c2gobGFzdE1hdGNoKSwgXG4gICAgICAgICAgICAgICAgICAgIG9wZW5lbmluZ3MucHVzaChhbHRlcm5hdG9yKSwgbGFzdE1hdGNoLm9wZW5Hcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdE1hdGNoLm9wZW5Hcm91cCA9ICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdGVybmF0b3JHcm91cCA9IG5ldyBNYXNrVG9rZW4oITApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRvckdyb3VwLmFsdGVybmF0b3JHcm91cCA9ICEwLCBvcGVuZW5pbmdzLnB1c2goYWx0ZXJuYXRvckdyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdENhc2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGNsb3NlUmVnZXhHcm91cCAmJiBjbG9zZUdyb3VwKCk7IDAgPCBvcGVuZW5pbmdzLmxlbmd0aDsgKSBvcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzLnBvcCgpLCBcbiAgICAgICAgICAgIGN1cnJlbnRUb2tlbi5tYXRjaGVzLnB1c2gob3BlbmluZ1Rva2VuKTtcbiAgICAgICAgICAgIHJldHVybiAwIDwgY3VycmVudFRva2VuLm1hdGNoZXMubGVuZ3RoICYmICh2ZXJpZnlHcm91cE1hcmtlcihjdXJyZW50VG9rZW4pLCBtYXNrVG9rZW5zLnB1c2goY3VycmVudFRva2VuKSksIFxuICAgICAgICAgICAgKG9wdHMubnVtZXJpY0lucHV0IHx8IG9wdHMuaXNSVEwpICYmIHJldmVyc2VUb2tlbnMobWFza1Rva2Vuc1swXSksIG1hc2tUb2tlbnM7XG4gICAgICAgIH1cbiAgICB9LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICAgICAgICAgICAgdmFsdWU6ICEwXG4gICAgICAgIH0pLCBleHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG4gICAgICAgIHZhciBfZGVmYXVsdCA9IHtcbiAgICAgICAgICAgIDk6IHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOVxcdWZmMTAtXFx1ZmYxOV1cIixcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uU3ltYm9sOiBcIipcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGE6IHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiW0EtWmEtelxcdTA0MTAtXFx1MDQ0ZlxcdTA0MDFcXHUwNDUxXFx4YzAtXFx4ZmZcXHhiNV1cIixcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uU3ltYm9sOiBcIipcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiKlwiOiB7XG4gICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTlcXHVmZjEwLVxcdWZmMTlBLVphLXpcXHUwNDEwLVxcdTA0NGZcXHUwNDAxXFx1MDQ1MVxceGMwLVxceGZmXFx4YjVdXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgICAgICAgICAgIHZhbHVlOiAhMFxuICAgICAgICB9KSwgZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwO1xuICAgICAgICB2YXIgX2RlZmF1bHQgPSB7XG4gICAgICAgICAgICBfbWF4VGVzdFBvczogNTAwLFxuICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiX1wiLFxuICAgICAgICAgICAgb3B0aW9uYWxtYXJrZXI6IFsgXCJbXCIsIFwiXVwiIF0sXG4gICAgICAgICAgICBxdWFudGlmaWVybWFya2VyOiBbIFwie1wiLCBcIn1cIiBdLFxuICAgICAgICAgICAgZ3JvdXBtYXJrZXI6IFsgXCIoXCIsIFwiKVwiIF0sXG4gICAgICAgICAgICBhbHRlcm5hdG9ybWFya2VyOiBcInxcIixcbiAgICAgICAgICAgIGVzY2FwZUNoYXI6IFwiXFxcXFwiLFxuICAgICAgICAgICAgbWFzazogbnVsbCxcbiAgICAgICAgICAgIHJlZ2V4OiBudWxsLFxuICAgICAgICAgICAgb25jb21wbGV0ZTogZnVuY3Rpb24gb25jb21wbGV0ZSgpIHt9LFxuICAgICAgICAgICAgb25pbmNvbXBsZXRlOiBmdW5jdGlvbiBvbmluY29tcGxldGUoKSB7fSxcbiAgICAgICAgICAgIG9uY2xlYXJlZDogZnVuY3Rpb24gb25jbGVhcmVkKCkge30sXG4gICAgICAgICAgICByZXBlYXQ6IDAsXG4gICAgICAgICAgICBncmVlZHk6ICExLFxuICAgICAgICAgICAgYXV0b1VubWFzazogITEsXG4gICAgICAgICAgICByZW1vdmVNYXNrT25TdWJtaXQ6ICExLFxuICAgICAgICAgICAgY2xlYXJNYXNrT25Mb3N0Rm9jdXM6ICEwLFxuICAgICAgICAgICAgaW5zZXJ0TW9kZTogITAsXG4gICAgICAgICAgICBpbnNlcnRNb2RlVmlzdWFsOiAhMCxcbiAgICAgICAgICAgIGNsZWFySW5jb21wbGV0ZTogITEsXG4gICAgICAgICAgICBhbGlhczogbnVsbCxcbiAgICAgICAgICAgIG9uS2V5RG93bjogZnVuY3Rpb24gb25LZXlEb3duKCkge30sXG4gICAgICAgICAgICBvbkJlZm9yZU1hc2s6IG51bGwsXG4gICAgICAgICAgICBvbkJlZm9yZVBhc3RlOiBmdW5jdGlvbiBvbkJlZm9yZVBhc3RlKHBhc3RlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2Ygb3B0cy5vbkJlZm9yZU1hc2sgPyBvcHRzLm9uQmVmb3JlTWFzay5jYWxsKHRoaXMsIHBhc3RlZFZhbHVlLCBvcHRzKSA6IHBhc3RlZFZhbHVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uQmVmb3JlV3JpdGU6IG51bGwsXG4gICAgICAgICAgICBvblVuTWFzazogbnVsbCxcbiAgICAgICAgICAgIHNob3dNYXNrT25Gb2N1czogITAsXG4gICAgICAgICAgICBzaG93TWFza09uSG92ZXI6ICEwLFxuICAgICAgICAgICAgb25LZXlWYWxpZGF0aW9uOiBmdW5jdGlvbiBvbktleVZhbGlkYXRpb24oKSB7fSxcbiAgICAgICAgICAgIHNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXI6IFwiIFwiLFxuICAgICAgICAgICAgbnVtZXJpY0lucHV0OiAhMSxcbiAgICAgICAgICAgIHJpZ2h0QWxpZ246ICExLFxuICAgICAgICAgICAgdW5kb09uRXNjYXBlOiAhMCxcbiAgICAgICAgICAgIHJhZGl4UG9pbnQ6IFwiXCIsXG4gICAgICAgICAgICBfcmFkaXhEYW5jZTogITEsXG4gICAgICAgICAgICBncm91cFNlcGFyYXRvcjogXCJcIixcbiAgICAgICAgICAgIGtlZXBTdGF0aWM6IG51bGwsXG4gICAgICAgICAgICBwb3NpdGlvbkNhcmV0T25UYWI6ICEwLFxuICAgICAgICAgICAgdGFiVGhyb3VnaDogITEsXG4gICAgICAgICAgICBzdXBwb3J0c0lucHV0VHlwZTogWyBcInRleHRcIiwgXCJ0ZWxcIiwgXCJ1cmxcIiwgXCJwYXNzd29yZFwiLCBcInNlYXJjaFwiIF0sXG4gICAgICAgICAgICBpZ25vcmFibGVzOiBbIDgsIDksIDE5LCAyNywgMzMsIDM0LCAzNSwgMzYsIDM3LCAzOCwgMzksIDQwLCA0NSwgNDYsIDkzLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAwLCAyMjkgXSxcbiAgICAgICAgICAgIGlzQ29tcGxldGU6IG51bGwsXG4gICAgICAgICAgICBwcmVWYWxpZGF0aW9uOiBudWxsLFxuICAgICAgICAgICAgcG9zdFZhbGlkYXRpb246IG51bGwsXG4gICAgICAgICAgICBzdGF0aWNEZWZpbml0aW9uU3ltYm9sOiB2b2lkIDAsXG4gICAgICAgICAgICBqaXRNYXNraW5nOiAhMSxcbiAgICAgICAgICAgIG51bGxhYmxlOiAhMCxcbiAgICAgICAgICAgIGlucHV0RXZlbnRPbmx5OiAhMSxcbiAgICAgICAgICAgIG5vVmFsdWVQYXRjaGluZzogITEsXG4gICAgICAgICAgICBwb3NpdGlvbkNhcmV0T25DbGljazogXCJsdnBcIixcbiAgICAgICAgICAgIGNhc2luZzogbnVsbCxcbiAgICAgICAgICAgIGlucHV0bW9kZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICBpbXBvcnREYXRhQXR0cmlidXRlczogITAsXG4gICAgICAgICAgICBzaGlmdFBvc2l0aW9uczogITAsXG4gICAgICAgICAgICB1c2VQcm90b3R5cGVEZWZpbml0aW9uczogITBcbiAgICAgICAgfTtcbiAgICAgICAgZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICB2YXIgX2lucHV0bWFzayA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygxKSksIF9rZXljb2RlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDApKSwgX2VzY2FwZVJlZ2V4ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDE0KSk7XG4gICAgICAgIGZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gX3R5cGVvZiA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIFwic3ltYm9sXCIgPT0gdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA/IGZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgICAgICAgICB9IDogZnVuY3Rpb24gX3R5cGVvZihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqICYmIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xuICAgICAgICAgICAgfSwgX3R5cGVvZihvYmopO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDoge1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IG9ialxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgJCA9IF9pbnB1dG1hc2suZGVmYXVsdC5kZXBlbmRlbmN5TGliLCBjdXJyZW50WWVhciA9IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKSwgZm9ybWF0Q29kZSA9IHtcbiAgICAgICAgICAgIGQ6IFsgXCJbMS05XXxbMTJdWzAtOV18M1swMV1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0RGF0ZSwgXCJkYXlcIiwgRGF0ZS5wcm90b3R5cGUuZ2V0RGF0ZSBdLFxuICAgICAgICAgICAgZGQ6IFsgXCIwWzEtOV18WzEyXVswLTldfDNbMDFdXCIsIERhdGUucHJvdG90eXBlLnNldERhdGUsIFwiZGF5XCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0RGF0ZS5jYWxsKHRoaXMpLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIGRkZDogWyBcIlwiIF0sXG4gICAgICAgICAgICBkZGRkOiBbIFwiXCIgXSxcbiAgICAgICAgICAgIG06IFsgXCJbMS05XXwxWzAxMl1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0TW9udGgsIFwibW9udGhcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERhdGUucHJvdG90eXBlLmdldE1vbnRoLmNhbGwodGhpcykgKyAxO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgbW06IFsgXCIwWzEtOV18MVswMTJdXCIsIERhdGUucHJvdG90eXBlLnNldE1vbnRoLCBcIm1vbnRoXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0TW9udGguY2FsbCh0aGlzKSArIDEsIDIpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgbW1tOiBbIFwiXCIgXSxcbiAgICAgICAgICAgIG1tbW06IFsgXCJcIiBdLFxuICAgICAgICAgICAgeXk6IFsgXCJbMC05XXsyfVwiLCBEYXRlLnByb3RvdHlwZS5zZXRGdWxsWWVhciwgXCJ5ZWFyXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0RnVsbFllYXIuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICB5eXl5OiBbIFwiWzAtOV17NH1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0RnVsbFllYXIsIFwieWVhclwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldEZ1bGxZZWFyLmNhbGwodGhpcyksIDQpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgaDogWyBcIlsxLTldfDFbMC0yXVwiLCBEYXRlLnByb3RvdHlwZS5zZXRIb3VycywgXCJob3Vyc1wiLCBEYXRlLnByb3RvdHlwZS5nZXRIb3VycyBdLFxuICAgICAgICAgICAgaGg6IFsgXCIwWzEtOV18MVswLTJdXCIsIERhdGUucHJvdG90eXBlLnNldEhvdXJzLCBcImhvdXJzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0SG91cnMuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICBoeDogWyBmdW5jdGlvbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiWzAtOV17XCIuY29uY2F0KHgsIFwifVwiKTtcbiAgICAgICAgICAgIH0sIERhdGUucHJvdG90eXBlLnNldEhvdXJzLCBcImhvdXJzXCIsIGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGF0ZS5wcm90b3R5cGUuZ2V0SG91cnM7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICBIOiBbIFwiMT9bMC05XXwyWzAtM11cIiwgRGF0ZS5wcm90b3R5cGUuc2V0SG91cnMsIFwiaG91cnNcIiwgRGF0ZS5wcm90b3R5cGUuZ2V0SG91cnMgXSxcbiAgICAgICAgICAgIEhIOiBbIFwiMFswLTldfDFbMC05XXwyWzAtM11cIiwgRGF0ZS5wcm90b3R5cGUuc2V0SG91cnMsIFwiaG91cnNcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhZChEYXRlLnByb3RvdHlwZS5nZXRIb3Vycy5jYWxsKHRoaXMpLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIEh4OiBbIGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJbMC05XXtcIi5jb25jYXQoeCwgXCJ9XCIpO1xuICAgICAgICAgICAgfSwgRGF0ZS5wcm90b3R5cGUuc2V0SG91cnMsIFwiaG91cnNcIiwgZnVuY3Rpb24oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhZChEYXRlLnByb3RvdHlwZS5nZXRIb3Vycy5jYWxsKHRoaXMpLCB4KTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgTTogWyBcIlsxLTVdP1swLTldXCIsIERhdGUucHJvdG90eXBlLnNldE1pbnV0ZXMsIFwibWludXRlc1wiLCBEYXRlLnByb3RvdHlwZS5nZXRNaW51dGVzIF0sXG4gICAgICAgICAgICBNTTogWyBcIjBbMC05XXwxWzAtOV18MlswLTldfDNbMC05XXw0WzAtOV18NVswLTldXCIsIERhdGUucHJvdG90eXBlLnNldE1pbnV0ZXMsIFwibWludXRlc1wiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldE1pbnV0ZXMuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICBzOiBbIFwiWzEtNV0/WzAtOV1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0U2Vjb25kcywgXCJzZWNvbmRzXCIsIERhdGUucHJvdG90eXBlLmdldFNlY29uZHMgXSxcbiAgICAgICAgICAgIHNzOiBbIFwiMFswLTldfDFbMC05XXwyWzAtOV18M1swLTldfDRbMC05XXw1WzAtOV1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0U2Vjb25kcywgXCJzZWNvbmRzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0U2Vjb25kcy5jYWxsKHRoaXMpLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIGw6IFsgXCJbMC05XXszfVwiLCBEYXRlLnByb3RvdHlwZS5zZXRNaWxsaXNlY29uZHMsIFwibWlsbGlzZWNvbmRzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0TWlsbGlzZWNvbmRzLmNhbGwodGhpcyksIDMpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgTDogWyBcIlswLTldezJ9XCIsIERhdGUucHJvdG90eXBlLnNldE1pbGxpc2Vjb25kcywgXCJtaWxsaXNlY29uZHNcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhZChEYXRlLnByb3RvdHlwZS5nZXRNaWxsaXNlY29uZHMuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICB0OiBbIFwiW2FwXVwiIF0sXG4gICAgICAgICAgICB0dDogWyBcIlthcF1tXCIgXSxcbiAgICAgICAgICAgIFQ6IFsgXCJbQVBdXCIgXSxcbiAgICAgICAgICAgIFRUOiBbIFwiW0FQXU1cIiBdLFxuICAgICAgICAgICAgWjogWyBcIlwiIF0sXG4gICAgICAgICAgICBvOiBbIFwiXCIgXSxcbiAgICAgICAgICAgIFM6IFsgXCJcIiBdXG4gICAgICAgIH0sIGZvcm1hdEFsaWFzID0ge1xuICAgICAgICAgICAgaXNvRGF0ZTogXCJ5eXl5LW1tLWRkXCIsXG4gICAgICAgICAgICBpc29UaW1lOiBcIkhIOk1NOnNzXCIsXG4gICAgICAgICAgICBpc29EYXRlVGltZTogXCJ5eXl5LW1tLWRkJ1QnSEg6TU06c3NcIixcbiAgICAgICAgICAgIGlzb1V0Y0RhdGVUaW1lOiBcIlVUQzp5eXl5LW1tLWRkJ1QnSEg6TU06c3MnWidcIlxuICAgICAgICB9O1xuICAgICAgICBmdW5jdGlvbiBmb3JtYXRjb2RlKG1hdGNoKSB7XG4gICAgICAgICAgICB2YXIgZHluTWF0Y2hlcyA9IG5ldyBSZWdFeHAoXCJcXFxcZCskXCIpLmV4ZWMobWF0Y2hbMF0pO1xuICAgICAgICAgICAgaWYgKGR5bk1hdGNoZXMgJiYgdm9pZCAwICE9PSBkeW5NYXRjaGVzWzBdKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZjb2RlID0gZm9ybWF0Q29kZVttYXRjaFswXVswXSArIFwieFwiXS5zbGljZShcIlwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmNvZGVbMF0gPSBmY29kZVswXShkeW5NYXRjaGVzWzBdKSwgZmNvZGVbM10gPSBmY29kZVszXShkeW5NYXRjaGVzWzBdKSwgZmNvZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZm9ybWF0Q29kZVttYXRjaFswXV0pIHJldHVybiBmb3JtYXRDb2RlW21hdGNoWzBdXTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBnZXRUb2tlbml6ZXIob3B0cykge1xuICAgICAgICAgICAgaWYgKCFvcHRzLnRva2VuaXplcikge1xuICAgICAgICAgICAgICAgIHZhciB0b2tlbnMgPSBbXSwgZHludG9rZW5zID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgbmR4IGluIGZvcm1hdENvZGUpIGlmICgvXFwuKngkLy50ZXN0KG5keCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGR5blRva2VuID0gbmR4WzBdICsgXCJcXFxcZCtcIjtcbiAgICAgICAgICAgICAgICAgICAgLTEgPT09IGR5bnRva2Vucy5pbmRleE9mKGR5blRva2VuKSAmJiBkeW50b2tlbnMucHVzaChkeW5Ub2tlbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIC0xID09PSB0b2tlbnMuaW5kZXhPZihuZHhbMF0pICYmIHRva2Vucy5wdXNoKG5keFswXSk7XG4gICAgICAgICAgICAgICAgb3B0cy50b2tlbml6ZXIgPSBcIihcIiArICgwIDwgZHludG9rZW5zLmxlbmd0aCA/IGR5bnRva2Vucy5qb2luKFwifFwiKSArIFwifFwiIDogXCJcIikgKyB0b2tlbnMuam9pbihcIit8XCIpICsgXCIpKz98LlwiLCBcbiAgICAgICAgICAgICAgICBvcHRzLnRva2VuaXplciA9IG5ldyBSZWdFeHAob3B0cy50b2tlbml6ZXIsIFwiZ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvcHRzLnRva2VuaXplcjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBwcmVmaWxsWWVhcihkYXRlUGFydHMsIGN1cnJlbnRSZXN1bHQsIG9wdHMpIHtcbiAgICAgICAgICAgIGlmIChkYXRlUGFydHMueWVhciAhPT0gZGF0ZVBhcnRzLnJhd3llYXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3JybnR5ZWFyID0gY3VycmVudFllYXIudG9TdHJpbmcoKSwgZW50ZXJlZFBhcnQgPSBkYXRlUGFydHMucmF3eWVhci5yZXBsYWNlKC9bXjAtOV0vZywgXCJcIiksIGN1cnJlbnRZZWFyUGFydCA9IGNycm50eWVhci5zbGljZSgwLCBlbnRlcmVkUGFydC5sZW5ndGgpLCBjdXJyZW50WWVhck5leHRQYXJ0ID0gY3JybnR5ZWFyLnNsaWNlKGVudGVyZWRQYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgaWYgKDIgPT09IGVudGVyZWRQYXJ0Lmxlbmd0aCAmJiBlbnRlcmVkUGFydCA9PT0gY3VycmVudFllYXJQYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlbnRyeUN1cnJlbnRZZWFyID0gbmV3IERhdGUoY3VycmVudFllYXIsIGRhdGVQYXJ0cy5tb250aCAtIDEsIGRhdGVQYXJ0cy5kYXkpO1xuICAgICAgICAgICAgICAgICAgICBkYXRlUGFydHMuZGF5ID09IGVudHJ5Q3VycmVudFllYXIuZ2V0RGF0ZSgpICYmICghb3B0cy5tYXggfHwgb3B0cy5tYXguZGF0ZS5nZXRUaW1lKCkgPj0gZW50cnlDdXJyZW50WWVhci5nZXRUaW1lKCkpICYmIChkYXRlUGFydHMuZGF0ZS5zZXRGdWxsWWVhcihjdXJyZW50WWVhciksIFxuICAgICAgICAgICAgICAgICAgICBkYXRlUGFydHMueWVhciA9IGNycm50eWVhciwgY3VycmVudFJlc3VsdC5pbnNlcnQgPSBbIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvczogY3VycmVudFJlc3VsdC5wb3MgKyAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgYzogY3VycmVudFllYXJOZXh0UGFydFswXVxuICAgICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3M6IGN1cnJlbnRSZXN1bHQucG9zICsgMixcbiAgICAgICAgICAgICAgICAgICAgICAgIGM6IGN1cnJlbnRZZWFyTmV4dFBhcnRbMV1cbiAgICAgICAgICAgICAgICAgICAgfSBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudFJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc1ZhbGlkRGF0ZShkYXRlUGFydHMsIGN1cnJlbnRSZXN1bHQsIG9wdHMpIHtcbiAgICAgICAgICAgIGlmICghaXNGaW5pdGUoZGF0ZVBhcnRzLnJhd2RheSkgfHwgXCIyOVwiID09IGRhdGVQYXJ0cy5kYXkgJiYgIWlzRmluaXRlKGRhdGVQYXJ0cy5yYXd5ZWFyKSB8fCBuZXcgRGF0ZShkYXRlUGFydHMuZGF0ZS5nZXRGdWxsWWVhcigpLCBpc0Zpbml0ZShkYXRlUGFydHMucmF3bW9udGgpID8gZGF0ZVBhcnRzLm1vbnRoIDogZGF0ZVBhcnRzLmRhdGUuZ2V0TW9udGgoKSArIDEsIDApLmdldERhdGUoKSA+PSBkYXRlUGFydHMuZGF5KSByZXR1cm4gY3VycmVudFJlc3VsdDtcbiAgICAgICAgICAgIGlmIChcIjI5XCIgPT0gZGF0ZVBhcnRzLmRheSkge1xuICAgICAgICAgICAgICAgIHZhciB0b2tlbk1hdGNoID0gZ2V0VG9rZW5NYXRjaChjdXJyZW50UmVzdWx0LnBvcywgb3B0cyk7XG4gICAgICAgICAgICAgICAgaWYgKFwieXl5eVwiID09PSB0b2tlbk1hdGNoLnRhcmdldE1hdGNoWzBdICYmIGN1cnJlbnRSZXN1bHQucG9zIC0gdG9rZW5NYXRjaC50YXJnZXRNYXRjaEluZGV4ID09IDIpIHJldHVybiBjdXJyZW50UmVzdWx0LnJlbW92ZSA9IGN1cnJlbnRSZXN1bHQucG9zICsgMSwgXG4gICAgICAgICAgICAgICAgY3VycmVudFJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAhMTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc0RhdGVJblJhbmdlKGRhdGVQYXJ0cywgcmVzdWx0LCBvcHRzLCBtYXNrc2V0LCBmcm9tQ2hlY2t2YWwpIHtcbiAgICAgICAgICAgIGlmICghcmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgaWYgKG9wdHMubWluKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGVQYXJ0cy5yYXd5ZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByYXdZZWFyID0gZGF0ZVBhcnRzLnJhd3llYXIucmVwbGFjZSgvW14wLTldL2csIFwiXCIpLCBtaW5ZZWFyID0gb3B0cy5taW4ueWVhci5zdWJzdHIoMCwgcmF3WWVhci5sZW5ndGgpLCBtYXhZZWFyO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmF3WWVhciA8IG1pblllYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0b2tlbk1hdGNoID0gZ2V0VG9rZW5NYXRjaChyZXN1bHQucG9zLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYXdZZWFyID0gZGF0ZVBhcnRzLnJhd3llYXIuc3Vic3RyKDAsIHJlc3VsdC5wb3MgLSB0b2tlbk1hdGNoLnRhcmdldE1hdGNoSW5kZXggKyAxKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5ZZWFyID0gb3B0cy5taW4ueWVhci5zdWJzdHIoMCwgcmF3WWVhci5sZW5ndGgpLCBtaW5ZZWFyIDw9IHJhd1llYXIpIHJldHVybiByZXN1bHQucmVtb3ZlID0gdG9rZW5NYXRjaC50YXJnZXRNYXRjaEluZGV4ICsgcmF3WWVhci5sZW5ndGgsIFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhd1llYXIgPSBcInl5eXlcIiA9PT0gdG9rZW5NYXRjaC50YXJnZXRNYXRjaFswXSA/IGRhdGVQYXJ0cy5yYXd5ZWFyLnN1YnN0cigxLCAxKSA6IGRhdGVQYXJ0cy5yYXd5ZWFyLnN1YnN0cigwLCAxKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5ZZWFyID0gb3B0cy5taW4ueWVhci5zdWJzdHIoMiwgMSksIG1heFllYXIgPSBvcHRzLm1heCA/IG9wdHMubWF4LnllYXIuc3Vic3RyKDIsIDEpIDogcmF3WWVhciwgXG4gICAgICAgICAgICAgICAgICAgICAgICAxID09PSByYXdZZWFyLmxlbmd0aCAmJiBtaW5ZZWFyIDw9IHJhd1llYXIgPD0gbWF4WWVhciAmJiAhMCAhPT0gZnJvbUNoZWNrdmFsKSByZXR1cm4gXCJ5eXl5XCIgPT09IHRva2VuTWF0Y2gudGFyZ2V0TWF0Y2hbMF0gPyAocmVzdWx0Lmluc2VydCA9IFsge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcmVzdWx0LnBvcyArIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYzogcmF3WWVhcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpY3Q6ICEwXG4gICAgICAgICAgICAgICAgICAgICAgICB9IF0sIHJlc3VsdC5jYXJldCA9IHJlc3VsdC5wb3MgKyAyLCBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Jlc3VsdC5wb3NdLmlucHV0ID0gb3B0cy5taW4ueWVhclsxXSkgOiAocmVzdWx0Lmluc2VydCA9IFsge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcmVzdWx0LnBvcyArIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYzogb3B0cy5taW4ueWVhclsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpY3Q6ICEwXG4gICAgICAgICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiByZXN1bHQucG9zICsgMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjOiByYXdZZWFyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmljdDogITBcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gXSwgcmVzdWx0LmNhcmV0ID0gcmVzdWx0LnBvcyArIDMsIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcmVzdWx0LnBvc10uaW5wdXQgPSBvcHRzLm1pbi55ZWFyWzBdKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSAhMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHQgJiYgZGF0ZVBhcnRzLnllYXIgJiYgZGF0ZVBhcnRzLnllYXIgPT09IGRhdGVQYXJ0cy5yYXd5ZWFyICYmIG9wdHMubWluLmRhdGUuZ2V0VGltZSgpID09IG9wdHMubWluLmRhdGUuZ2V0VGltZSgpICYmIChyZXN1bHQgPSBvcHRzLm1pbi5kYXRlLmdldFRpbWUoKSA8PSBkYXRlUGFydHMuZGF0ZS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCAmJiBvcHRzLm1heCAmJiBvcHRzLm1heC5kYXRlLmdldFRpbWUoKSA9PSBvcHRzLm1heC5kYXRlLmdldFRpbWUoKSAmJiAocmVzdWx0ID0gb3B0cy5tYXguZGF0ZS5nZXRUaW1lKCkgPj0gZGF0ZVBhcnRzLmRhdGUuZ2V0VGltZSgpKSwgXG4gICAgICAgICAgICByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcGFyc2UoZm9ybWF0LCBkYXRlT2JqVmFsdWUsIG9wdHMsIHJhdykge1xuICAgICAgICAgICAgdmFyIG1hc2sgPSBcIlwiLCBtYXRjaCwgZmNvZGU7XG4gICAgICAgICAgICBmb3IgKGdldFRva2VuaXplcihvcHRzKS5sYXN0SW5kZXggPSAwOyBtYXRjaCA9IGdldFRva2VuaXplcihvcHRzKS5leGVjKGZvcm1hdCk7ICkgaWYgKHZvaWQgMCA9PT0gZGF0ZU9ialZhbHVlKSBpZiAoZmNvZGUgPSBmb3JtYXRjb2RlKG1hdGNoKSkgbWFzayArPSBcIihcIiArIGZjb2RlWzBdICsgXCIpXCI7IGVsc2Ugc3dpdGNoIChtYXRjaFswXSkge1xuICAgICAgICAgICAgICBjYXNlIFwiW1wiOlxuICAgICAgICAgICAgICAgIG1hc2sgKz0gXCIoXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgY2FzZSBcIl1cIjpcbiAgICAgICAgICAgICAgICBtYXNrICs9IFwiKT9cIjtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIG1hc2sgKz0gKDAsIF9lc2NhcGVSZWdleC5kZWZhdWx0KShtYXRjaFswXSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGZjb2RlID0gZm9ybWF0Y29kZShtYXRjaCkpIGlmICghMCAhPT0gcmF3ICYmIGZjb2RlWzNdKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdldEZuID0gZmNvZGVbM107XG4gICAgICAgICAgICAgICAgbWFzayArPSBnZXRGbi5jYWxsKGRhdGVPYmpWYWx1ZS5kYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBmY29kZVsyXSA/IG1hc2sgKz0gZGF0ZU9ialZhbHVlW1wicmF3XCIgKyBmY29kZVsyXV0gOiBtYXNrICs9IG1hdGNoWzBdOyBlbHNlIG1hc2sgKz0gbWF0Y2hbMF07XG4gICAgICAgICAgICByZXR1cm4gbWFzaztcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBwYWQodmFsLCBsZW4pIHtcbiAgICAgICAgICAgIGZvciAodmFsID0gU3RyaW5nKHZhbCksIGxlbiA9IGxlbiB8fCAyOyB2YWwubGVuZ3RoIDwgbGVuOyApIHZhbCA9IFwiMFwiICsgdmFsO1xuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBhbmFseXNlTWFzayhtYXNrU3RyaW5nLCBmb3JtYXQsIG9wdHMpIHtcbiAgICAgICAgICAgIHZhciBkYXRlT2JqID0ge1xuICAgICAgICAgICAgICAgIGRhdGU6IG5ldyBEYXRlKDEsIDAsIDEpXG4gICAgICAgICAgICB9LCB0YXJnZXRQcm9wLCBtYXNrID0gbWFza1N0cmluZywgbWF0Y2gsIGRhdGVPcGVyYXRpb247XG4gICAgICAgICAgICBmdW5jdGlvbiBzZXRWYWx1ZShkYXRlT2JqLCB2YWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIGRhdGVPYmpbdGFyZ2V0UHJvcF0gPSB2YWx1ZS5yZXBsYWNlKC9bXjAtOV0vZywgXCIwXCIpLCBkYXRlT2JqW1wicmF3XCIgKyB0YXJnZXRQcm9wXSA9IHZhbHVlLCBcbiAgICAgICAgICAgICAgICB2b2lkIDAgIT09IGRhdGVPcGVyYXRpb24gJiYgZGF0ZU9wZXJhdGlvbi5jYWxsKGRhdGVPYmouZGF0ZSwgXCJtb250aFwiID09IHRhcmdldFByb3AgPyBwYXJzZUludChkYXRlT2JqW3RhcmdldFByb3BdKSAtIDEgOiBkYXRlT2JqW3RhcmdldFByb3BdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChcInN0cmluZ1wiID09IHR5cGVvZiBtYXNrKSB7XG4gICAgICAgICAgICAgICAgZm9yIChnZXRUb2tlbml6ZXIob3B0cykubGFzdEluZGV4ID0gMDsgbWF0Y2ggPSBnZXRUb2tlbml6ZXIob3B0cykuZXhlYyhmb3JtYXQpOyApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGR5bk1hdGNoZXMgPSBuZXcgUmVnRXhwKFwiXFxcXGQrJFwiKS5leGVjKG1hdGNoWzBdKSwgZmNvZGUgPSBkeW5NYXRjaGVzID8gbWF0Y2hbMF1bMF0gKyBcInhcIiA6IG1hdGNoWzBdLCB2YWx1ZSA9IHZvaWQgMDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGR5bk1hdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsYXN0SW5kZXggPSBnZXRUb2tlbml6ZXIob3B0cykubGFzdEluZGV4LCB0b2thbk1hdGNoID0gZ2V0VG9rZW5NYXRjaChtYXRjaC5pbmRleCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRUb2tlbml6ZXIob3B0cykubGFzdEluZGV4ID0gbGFzdEluZGV4LCB2YWx1ZSA9IG1hc2suc2xpY2UoMCwgbWFzay5pbmRleE9mKHRva2FuTWF0Y2gubmV4dE1hdGNoWzBdKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB2YWx1ZSA9IG1hc2suc2xpY2UoMCwgZmNvZGUubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGZvcm1hdENvZGUsIGZjb2RlKSAmJiAodGFyZ2V0UHJvcCA9IGZvcm1hdENvZGVbZmNvZGVdWzJdLCBcbiAgICAgICAgICAgICAgICAgICAgZGF0ZU9wZXJhdGlvbiA9IGZvcm1hdENvZGVbZmNvZGVdWzFdLCBzZXRWYWx1ZShkYXRlT2JqLCB2YWx1ZSwgb3B0cykpLCBtYXNrID0gbWFzay5zbGljZSh2YWx1ZS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZU9iajtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtYXNrICYmIFwib2JqZWN0XCIgPT09IF90eXBlb2YobWFzaykgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1hc2ssIFwiZGF0ZVwiKSkgcmV0dXJuIG1hc2s7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gaW1wb3J0RGF0ZShkYXRlT2JqLCBvcHRzKSB7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2Uob3B0cy5pbnB1dEZvcm1hdCwge1xuICAgICAgICAgICAgICAgIGRhdGU6IGRhdGVPYmpcbiAgICAgICAgICAgIH0sIG9wdHMpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdldFRva2VuTWF0Y2gocG9zLCBvcHRzKSB7XG4gICAgICAgICAgICB2YXIgY2FsY1BvcyA9IDAsIHRhcmdldE1hdGNoLCBtYXRjaCwgbWF0Y2hMZW5ndGggPSAwO1xuICAgICAgICAgICAgZm9yIChnZXRUb2tlbml6ZXIob3B0cykubGFzdEluZGV4ID0gMDsgbWF0Y2ggPSBnZXRUb2tlbml6ZXIob3B0cykuZXhlYyhvcHRzLmlucHV0Rm9ybWF0KTsgKSB7XG4gICAgICAgICAgICAgICAgdmFyIGR5bk1hdGNoZXMgPSBuZXcgUmVnRXhwKFwiXFxcXGQrJFwiKS5leGVjKG1hdGNoWzBdKTtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2hMZW5ndGggPSBkeW5NYXRjaGVzID8gcGFyc2VJbnQoZHluTWF0Y2hlc1swXSkgOiBtYXRjaFswXS5sZW5ndGgsIGNhbGNQb3MgKz0gbWF0Y2hMZW5ndGgsIFxuICAgICAgICAgICAgICAgIHBvcyA8PSBjYWxjUG9zKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldE1hdGNoID0gbWF0Y2gsIG1hdGNoID0gZ2V0VG9rZW5pemVyKG9wdHMpLmV4ZWMob3B0cy5pbnB1dEZvcm1hdCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0TWF0Y2hJbmRleDogY2FsY1BvcyAtIG1hdGNoTGVuZ3RoLFxuICAgICAgICAgICAgICAgIG5leHRNYXRjaDogbWF0Y2gsXG4gICAgICAgICAgICAgICAgdGFyZ2V0TWF0Y2g6IHRhcmdldE1hdGNoXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIF9pbnB1dG1hc2suZGVmYXVsdC5leHRlbmRBbGlhc2VzKHtcbiAgICAgICAgICAgIGRhdGV0aW1lOiB7XG4gICAgICAgICAgICAgICAgbWFzazogZnVuY3Rpb24gbWFzayhvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLm51bWVyaWNJbnB1dCA9ICExLCBmb3JtYXRDb2RlLlMgPSBvcHRzLmkxOG4ub3JkaW5hbFN1ZmZpeC5qb2luKFwifFwiKSwgXG4gICAgICAgICAgICAgICAgICAgIG9wdHMuaW5wdXRGb3JtYXQgPSBmb3JtYXRBbGlhc1tvcHRzLmlucHV0Rm9ybWF0XSB8fCBvcHRzLmlucHV0Rm9ybWF0LCBvcHRzLmRpc3BsYXlGb3JtYXQgPSBmb3JtYXRBbGlhc1tvcHRzLmRpc3BsYXlGb3JtYXRdIHx8IG9wdHMuZGlzcGxheUZvcm1hdCB8fCBvcHRzLmlucHV0Rm9ybWF0LCBcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5vdXRwdXRGb3JtYXQgPSBmb3JtYXRBbGlhc1tvcHRzLm91dHB1dEZvcm1hdF0gfHwgb3B0cy5vdXRwdXRGb3JtYXQgfHwgb3B0cy5pbnB1dEZvcm1hdCwgXG4gICAgICAgICAgICAgICAgICAgIG9wdHMucGxhY2Vob2xkZXIgPSBcIlwiICE9PSBvcHRzLnBsYWNlaG9sZGVyID8gb3B0cy5wbGFjZWhvbGRlciA6IG9wdHMuaW5wdXRGb3JtYXQucmVwbGFjZSgvW1tcXF1dLywgXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICBvcHRzLnJlZ2V4ID0gcGFyc2Uob3B0cy5pbnB1dEZvcm1hdCwgdm9pZCAwLCBvcHRzKSwgb3B0cy5taW4gPSBhbmFseXNlTWFzayhvcHRzLm1pbiwgb3B0cy5pbnB1dEZvcm1hdCwgb3B0cyksIFxuICAgICAgICAgICAgICAgICAgICBvcHRzLm1heCA9IGFuYWx5c2VNYXNrKG9wdHMubWF4LCBvcHRzLmlucHV0Rm9ybWF0LCBvcHRzKSwgbnVsbDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIlwiLFxuICAgICAgICAgICAgICAgIGlucHV0Rm9ybWF0OiBcImlzb0RhdGVUaW1lXCIsXG4gICAgICAgICAgICAgICAgZGlzcGxheUZvcm1hdDogdm9pZCAwLFxuICAgICAgICAgICAgICAgIG91dHB1dEZvcm1hdDogdm9pZCAwLFxuICAgICAgICAgICAgICAgIG1pbjogbnVsbCxcbiAgICAgICAgICAgICAgICBtYXg6IG51bGwsXG4gICAgICAgICAgICAgICAgc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlcjogXCJcIixcbiAgICAgICAgICAgICAgICBpMThuOiB7XG4gICAgICAgICAgICAgICAgICAgIGRheU5hbWVzOiBbIFwiTW9uXCIsIFwiVHVlXCIsIFwiV2VkXCIsIFwiVGh1XCIsIFwiRnJpXCIsIFwiU2F0XCIsIFwiU3VuXCIsIFwiTW9uZGF5XCIsIFwiVHVlc2RheVwiLCBcIldlZG5lc2RheVwiLCBcIlRodXJzZGF5XCIsIFwiRnJpZGF5XCIsIFwiU2F0dXJkYXlcIiwgXCJTdW5kYXlcIiBdLFxuICAgICAgICAgICAgICAgICAgICBtb250aE5hbWVzOiBbIFwiSmFuXCIsIFwiRmViXCIsIFwiTWFyXCIsIFwiQXByXCIsIFwiTWF5XCIsIFwiSnVuXCIsIFwiSnVsXCIsIFwiQXVnXCIsIFwiU2VwXCIsIFwiT2N0XCIsIFwiTm92XCIsIFwiRGVjXCIsIFwiSmFudWFyeVwiLCBcIkZlYnJ1YXJ5XCIsIFwiTWFyY2hcIiwgXCJBcHJpbFwiLCBcIk1heVwiLCBcIkp1bmVcIiwgXCJKdWx5XCIsIFwiQXVndXN0XCIsIFwiU2VwdGVtYmVyXCIsIFwiT2N0b2JlclwiLCBcIk5vdmVtYmVyXCIsIFwiRGVjZW1iZXJcIiBdLFxuICAgICAgICAgICAgICAgICAgICBvcmRpbmFsU3VmZml4OiBbIFwic3RcIiwgXCJuZFwiLCBcInJkXCIsIFwidGhcIiBdXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwcmVWYWxpZGF0aW9uOiBmdW5jdGlvbiBwcmVWYWxpZGF0aW9uKGJ1ZmZlciwgcG9zLCBjLCBpc1NlbGVjdGlvbiwgb3B0cywgbWFza3NldCwgY2FyZXRQb3MsIHN0cmljdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RyaWN0KSByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc05hTihjKSAmJiBidWZmZXJbcG9zXSAhPT0gYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRva2VuTWF0Y2ggPSBnZXRUb2tlbk1hdGNoKHBvcywgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodG9rZW5NYXRjaC5uZXh0TWF0Y2ggJiYgdG9rZW5NYXRjaC5uZXh0TWF0Y2hbMF0gPT09IGMgJiYgMSA8IHRva2VuTWF0Y2gudGFyZ2V0TWF0Y2hbMF0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbGlkYXRvciA9IGZvcm1hdENvZGVbdG9rZW5NYXRjaC50YXJnZXRNYXRjaFswXV1bMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5ldyBSZWdFeHAodmFsaWRhdG9yKS50ZXN0KFwiMFwiICsgYnVmZmVyW3BvcyAtIDFdKSkgcmV0dXJuIGJ1ZmZlcltwb3NdID0gYnVmZmVyW3BvcyAtIDFdLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXJbcG9zIC0gMV0gPSBcIjBcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdXp6eTogITAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlcjogYnVmZmVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHBvcyAtIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IHBvcyArIDFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3MgKyAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gITA7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwb3N0VmFsaWRhdGlvbjogZnVuY3Rpb24gcG9zdFZhbGlkYXRpb24oYnVmZmVyLCBwb3MsIGMsIGN1cnJlbnRSZXN1bHQsIG9wdHMsIG1hc2tzZXQsIHN0cmljdCwgZnJvbUNoZWNrdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJpY3QpIHJldHVybiAhMDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRva2VuTWF0Y2gsIHZhbGlkYXRvcjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCExID09PSBjdXJyZW50UmVzdWx0KSByZXR1cm4gdG9rZW5NYXRjaCA9IGdldFRva2VuTWF0Y2gocG9zICsgMSwgb3B0cyksIHRva2VuTWF0Y2gudGFyZ2V0TWF0Y2ggJiYgdG9rZW5NYXRjaC50YXJnZXRNYXRjaEluZGV4ID09PSBwb3MgJiYgMSA8IHRva2VuTWF0Y2gudGFyZ2V0TWF0Y2hbMF0ubGVuZ3RoICYmIHZvaWQgMCAhPT0gZm9ybWF0Q29kZVt0b2tlbk1hdGNoLnRhcmdldE1hdGNoWzBdXSAmJiAodmFsaWRhdG9yID0gZm9ybWF0Q29kZVt0b2tlbk1hdGNoLnRhcmdldE1hdGNoWzBdXVswXSwgXG4gICAgICAgICAgICAgICAgICAgIG5ldyBSZWdFeHAodmFsaWRhdG9yKS50ZXN0KFwiMFwiICsgYykpID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0OiBbIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjOiBcIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zICsgMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjOiBjXG4gICAgICAgICAgICAgICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvcyArIDFcbiAgICAgICAgICAgICAgICAgICAgfSA6IGN1cnJlbnRSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50UmVzdWx0LmZ1enp5ICYmIChidWZmZXIgPSBjdXJyZW50UmVzdWx0LmJ1ZmZlciwgcG9zID0gY3VycmVudFJlc3VsdC5wb3MpLCBcbiAgICAgICAgICAgICAgICAgICAgdG9rZW5NYXRjaCA9IGdldFRva2VuTWF0Y2gocG9zLCBvcHRzKSwgdG9rZW5NYXRjaC50YXJnZXRNYXRjaCAmJiB0b2tlbk1hdGNoLnRhcmdldE1hdGNoWzBdICYmIHZvaWQgMCAhPT0gZm9ybWF0Q29kZVt0b2tlbk1hdGNoLnRhcmdldE1hdGNoWzBdXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yID0gZm9ybWF0Q29kZVt0b2tlbk1hdGNoLnRhcmdldE1hdGNoWzBdXVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwYXJ0ID0gYnVmZmVyLnNsaWNlKHRva2VuTWF0Y2gudGFyZ2V0TWF0Y2hJbmRleCwgdG9rZW5NYXRjaC50YXJnZXRNYXRjaEluZGV4ICsgdG9rZW5NYXRjaC50YXJnZXRNYXRjaFswXS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgITEgPT09IG5ldyBSZWdFeHAodmFsaWRhdG9yKS50ZXN0KHBhcnQuam9pbihcIlwiKSkgJiYgMiA9PT0gdG9rZW5NYXRjaC50YXJnZXRNYXRjaFswXS5sZW5ndGggJiYgbWFza3NldC52YWxpZFBvc2l0aW9uc1t0b2tlbk1hdGNoLnRhcmdldE1hdGNoSW5kZXhdICYmIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbdG9rZW5NYXRjaC50YXJnZXRNYXRjaEluZGV4ICsgMV0gJiYgKG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbdG9rZW5NYXRjaC50YXJnZXRNYXRjaEluZGV4ICsgMV0uaW5wdXQgPSBcIjBcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGN1cnJlbnRSZXN1bHQsIGRhdGVQYXJ0cyA9IGFuYWx5c2VNYXNrKGJ1ZmZlci5qb2luKFwiXCIpLCBvcHRzLmlucHV0Rm9ybWF0LCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCAmJiBkYXRlUGFydHMuZGF0ZS5nZXRUaW1lKCkgPT0gZGF0ZVBhcnRzLmRhdGUuZ2V0VGltZSgpICYmIChyZXN1bHQgPSBwcmVmaWxsWWVhcihkYXRlUGFydHMsIHJlc3VsdCwgb3B0cyksIFxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBpc1ZhbGlkRGF0ZShkYXRlUGFydHMsIHJlc3VsdCwgb3B0cyksIHJlc3VsdCA9IGlzRGF0ZUluUmFuZ2UoZGF0ZVBhcnRzLCByZXN1bHQsIG9wdHMsIG1hc2tzZXQsIGZyb21DaGVja3ZhbCkpLCBcbiAgICAgICAgICAgICAgICAgICAgcG9zICYmIHJlc3VsdCAmJiBjdXJyZW50UmVzdWx0LnBvcyAhPT0gcG9zID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiBwYXJzZShvcHRzLmlucHV0Rm9ybWF0LCBkYXRlUGFydHMsIG9wdHMpLnNwbGl0KFwiXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogY3VycmVudFJlc3VsdC5wb3NcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSA6IHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uS2V5RG93bjogZnVuY3Rpb24gb25LZXlEb3duKGUsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgZS5jdHJsS2V5ICYmIGUua2V5Q29kZSA9PT0gX2tleWNvZGUuZGVmYXVsdC5SSUdIVCAmJiAodGhpcy5pbnB1dG1hc2suX3ZhbHVlU2V0KGltcG9ydERhdGUobmV3IERhdGUoKSwgb3B0cykpLCBcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS50cmlnZ2VyKFwic2V0dmFsdWVcIikpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25Vbk1hc2s6IGZ1bmN0aW9uIG9uVW5NYXNrKG1hc2tlZFZhbHVlLCB1bm1hc2tlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB1bm1hc2tlZFZhbHVlID8gcGFyc2Uob3B0cy5vdXRwdXRGb3JtYXQsIGFuYWx5c2VNYXNrKG1hc2tlZFZhbHVlLCBvcHRzLmlucHV0Rm9ybWF0LCBvcHRzKSwgb3B0cywgITApIDogdW5tYXNrZWRWYWx1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNhc2luZzogZnVuY3Rpb24gY2FzaW5nKGVsZW0sIHRlc3QsIHBvcywgdmFsaWRQb3NpdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDAgPT0gdGVzdC5uYXRpdmVEZWYuaW5kZXhPZihcIlthcF1cIikgPyBlbGVtLnRvTG93ZXJDYXNlKCkgOiAwID09IHRlc3QubmF0aXZlRGVmLmluZGV4T2YoXCJbQVBdXCIpID8gZWxlbS50b1VwcGVyQ2FzZSgpIDogZWxlbTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uQmVmb3JlTWFzazogZnVuY3Rpb24gb25CZWZvcmVNYXNrKGluaXRpYWxWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJbb2JqZWN0IERhdGVdXCIgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbml0aWFsVmFsdWUpICYmIChpbml0aWFsVmFsdWUgPSBpbXBvcnREYXRlKGluaXRpYWxWYWx1ZSwgb3B0cykpLCBcbiAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogITEsXG4gICAgICAgICAgICAgICAgc2hpZnRQb3NpdGlvbnM6ICExLFxuICAgICAgICAgICAgICAgIGtlZXBTdGF0aWM6ICExLFxuICAgICAgICAgICAgICAgIGlucHV0bW9kZTogXCJudW1lcmljXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICB2YXIgX2lucHV0bWFzayA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygxKSksIF9rZXljb2RlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDApKSwgX2VzY2FwZVJlZ2V4ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfX3dlYnBhY2tfcmVxdWlyZV9fKDE0KSk7XG4gICAgICAgIGZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDoge1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IG9ialxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgJCA9IF9pbnB1dG1hc2suZGVmYXVsdC5kZXBlbmRlbmN5TGliO1xuICAgICAgICBmdW5jdGlvbiBhdXRvRXNjYXBlKHR4dCwgb3B0cykge1xuICAgICAgICAgICAgZm9yICh2YXIgZXNjYXBlZFR4dCA9IFwiXCIsIGkgPSAwOyBpIDwgdHh0Lmxlbmd0aDsgaSsrKSBfaW5wdXRtYXNrLmRlZmF1bHQucHJvdG90eXBlLmRlZmluaXRpb25zW3R4dC5jaGFyQXQoaSldIHx8IG9wdHMuZGVmaW5pdGlvbnNbdHh0LmNoYXJBdChpKV0gfHwgb3B0cy5vcHRpb25hbG1hcmtlclswXSA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLm9wdGlvbmFsbWFya2VyWzFdID09PSB0eHQuY2hhckF0KGkpIHx8IG9wdHMucXVhbnRpZmllcm1hcmtlclswXSA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLnF1YW50aWZpZXJtYXJrZXJbMV0gPT09IHR4dC5jaGFyQXQoaSkgfHwgb3B0cy5ncm91cG1hcmtlclswXSA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLmdyb3VwbWFya2VyWzFdID09PSB0eHQuY2hhckF0KGkpIHx8IG9wdHMuYWx0ZXJuYXRvcm1hcmtlciA9PT0gdHh0LmNoYXJBdChpKSA/IGVzY2FwZWRUeHQgKz0gXCJcXFxcXCIgKyB0eHQuY2hhckF0KGkpIDogZXNjYXBlZFR4dCArPSB0eHQuY2hhckF0KGkpO1xuICAgICAgICAgICAgcmV0dXJuIGVzY2FwZWRUeHQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gYWxpZ25EaWdpdHMoYnVmZmVyLCBkaWdpdHMsIG9wdHMsIGZvcmNlKSB7XG4gICAgICAgICAgICBpZiAoMCA8IGJ1ZmZlci5sZW5ndGggJiYgMCA8IGRpZ2l0cyAmJiAoIW9wdHMuZGlnaXRzT3B0aW9uYWwgfHwgZm9yY2UpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJhZGl4UG9zaXRpb24gPSBidWZmZXIuaW5kZXhPZihvcHRzLnJhZGl4UG9pbnQpLCBuZWdhdGlvbkJhY2sgPSAhMTtcbiAgICAgICAgICAgICAgICBvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2sgPT09IGJ1ZmZlcltidWZmZXIubGVuZ3RoIC0gMV0gJiYgKG5lZ2F0aW9uQmFjayA9ICEwLCBidWZmZXIubGVuZ3RoLS0pLCBcbiAgICAgICAgICAgICAgICAtMSA9PT0gcmFkaXhQb3NpdGlvbiAmJiAoYnVmZmVyLnB1c2gob3B0cy5yYWRpeFBvaW50KSwgcmFkaXhQb3NpdGlvbiA9IGJ1ZmZlci5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8PSBkaWdpdHM7IGkrKykgaXNGaW5pdGUoYnVmZmVyW3JhZGl4UG9zaXRpb24gKyBpXSkgfHwgKGJ1ZmZlcltyYWRpeFBvc2l0aW9uICsgaV0gPSBcIjBcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmVnYXRpb25CYWNrICYmIGJ1ZmZlci5wdXNoKG9wdHMubmVnYXRpb25TeW1ib2wuYmFjayksIGJ1ZmZlcjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBmaW5kVmFsaWRhdG9yKHN5bWJvbCwgbWFza3NldCkge1xuICAgICAgICAgICAgdmFyIHBvc05keCA9IDA7XG4gICAgICAgICAgICBpZiAoXCIrXCIgPT09IHN5bWJvbCkge1xuICAgICAgICAgICAgICAgIGZvciAocG9zTmR4IGluIG1hc2tzZXQudmFsaWRQb3NpdGlvbnMpIDtcbiAgICAgICAgICAgICAgICBwb3NOZHggPSBwYXJzZUludChwb3NOZHgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgdHN0TmR4IGluIG1hc2tzZXQudGVzdHMpIGlmICh0c3ROZHggPSBwYXJzZUludCh0c3ROZHgpLCBwb3NOZHggPD0gdHN0TmR4KSBmb3IgKHZhciBuZHggPSAwLCBuZHhsID0gbWFza3NldC50ZXN0c1t0c3ROZHhdLmxlbmd0aDsgbmR4IDwgbmR4bDsgbmR4KyspIGlmICgodm9pZCAwID09PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3RzdE5keF0gfHwgXCItXCIgPT09IHN5bWJvbCkgJiYgbWFza3NldC50ZXN0c1t0c3ROZHhdW25keF0ubWF0Y2guZGVmID09PSBzeW1ib2wpIHJldHVybiB0c3ROZHggKyAodm9pZCAwICE9PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3RzdE5keF0gJiYgXCItXCIgIT09IHN5bWJvbCA/IDEgOiAwKTtcbiAgICAgICAgICAgIHJldHVybiBwb3NOZHg7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZmluZFZhbGlkKHN5bWJvbCwgbWFza3NldCkge1xuICAgICAgICAgICAgdmFyIHJldCA9IC0xO1xuICAgICAgICAgICAgZm9yICh2YXIgbmR4IGluIG1hc2tzZXQudmFsaWRQb3NpdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHN0ID0gbWFza3NldC52YWxpZFBvc2l0aW9uc1tuZHhdO1xuICAgICAgICAgICAgICAgIGlmICh0c3QgJiYgdHN0Lm1hdGNoLmRlZiA9PT0gc3ltYm9sKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldCA9IHBhcnNlSW50KG5keCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcGFyc2VNaW5NYXhPcHRpb25zKG9wdHMpIHtcbiAgICAgICAgICAgIHZvaWQgMCA9PT0gb3B0cy5wYXJzZU1pbk1heE9wdGlvbnMgJiYgKG51bGwgIT09IG9wdHMubWluICYmIChvcHRzLm1pbiA9IG9wdHMubWluLnRvU3RyaW5nKCkucmVwbGFjZShuZXcgUmVnRXhwKCgwLCBcbiAgICAgICAgICAgIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLmdyb3VwU2VwYXJhdG9yKSwgXCJnXCIpLCBcIlwiKSwgXCIsXCIgPT09IG9wdHMucmFkaXhQb2ludCAmJiAob3B0cy5taW4gPSBvcHRzLm1pbi5yZXBsYWNlKG9wdHMucmFkaXhQb2ludCwgXCIuXCIpKSwgXG4gICAgICAgICAgICBvcHRzLm1pbiA9IGlzRmluaXRlKG9wdHMubWluKSA/IHBhcnNlRmxvYXQob3B0cy5taW4pIDogTmFOLCBpc05hTihvcHRzLm1pbikgJiYgKG9wdHMubWluID0gTnVtYmVyLk1JTl9WQUxVRSkpLCBcbiAgICAgICAgICAgIG51bGwgIT09IG9wdHMubWF4ICYmIChvcHRzLm1heCA9IG9wdHMubWF4LnRvU3RyaW5nKCkucmVwbGFjZShuZXcgUmVnRXhwKCgwLCBfZXNjYXBlUmVnZXguZGVmYXVsdCkob3B0cy5ncm91cFNlcGFyYXRvciksIFwiZ1wiKSwgXCJcIiksIFxuICAgICAgICAgICAgXCIsXCIgPT09IG9wdHMucmFkaXhQb2ludCAmJiAob3B0cy5tYXggPSBvcHRzLm1heC5yZXBsYWNlKG9wdHMucmFkaXhQb2ludCwgXCIuXCIpKSwgXG4gICAgICAgICAgICBvcHRzLm1heCA9IGlzRmluaXRlKG9wdHMubWF4KSA/IHBhcnNlRmxvYXQob3B0cy5tYXgpIDogTmFOLCBpc05hTihvcHRzLm1heCkgJiYgKG9wdHMubWF4ID0gTnVtYmVyLk1BWF9WQUxVRSkpLCBcbiAgICAgICAgICAgIG9wdHMucGFyc2VNaW5NYXhPcHRpb25zID0gXCJkb25lXCIpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdlbk1hc2sob3B0cykge1xuICAgICAgICAgICAgb3B0cy5yZXBlYXQgPSAwLCBvcHRzLmdyb3VwU2VwYXJhdG9yID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgb3B0cy5kaWdpdHMgJiYgXCIwXCIgIT09IG9wdHMuZGlnaXRzICYmIChcIi5cIiA9PT0gb3B0cy5yYWRpeFBvaW50ID8gb3B0cy5ncm91cFNlcGFyYXRvciA9IFwiLFwiIDogXCIsXCIgPT09IG9wdHMucmFkaXhQb2ludCA/IG9wdHMuZ3JvdXBTZXBhcmF0b3IgPSBcIi5cIiA6IG9wdHMuZ3JvdXBTZXBhcmF0b3IgPSBcIlwiKSwgXG4gICAgICAgICAgICBcIiBcIiA9PT0gb3B0cy5ncm91cFNlcGFyYXRvciAmJiAob3B0cy5za2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyID0gdm9pZCAwKSwgMSA8IG9wdHMucGxhY2Vob2xkZXIubGVuZ3RoICYmIChvcHRzLnBsYWNlaG9sZGVyID0gb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCkpLCBcbiAgICAgICAgICAgIFwicmFkaXhGb2N1c1wiID09PSBvcHRzLnBvc2l0aW9uQ2FyZXRPbkNsaWNrICYmIFwiXCIgPT09IG9wdHMucGxhY2Vob2xkZXIgJiYgKG9wdHMucG9zaXRpb25DYXJldE9uQ2xpY2sgPSBcImx2cFwiKTtcbiAgICAgICAgICAgIHZhciBkZWNpbWFsRGVmID0gXCIwXCIsIHJhZGl4UG9pbnREZWYgPSBvcHRzLnJhZGl4UG9pbnQ7XG4gICAgICAgICAgICAhMCA9PT0gb3B0cy5udW1lcmljSW5wdXQgJiYgdm9pZCAwID09PSBvcHRzLl9fZmluYW5jZUlucHV0ID8gKGRlY2ltYWxEZWYgPSBcIjFcIiwgXG4gICAgICAgICAgICBvcHRzLnBvc2l0aW9uQ2FyZXRPbkNsaWNrID0gXCJyYWRpeEZvY3VzXCIgPT09IG9wdHMucG9zaXRpb25DYXJldE9uQ2xpY2sgPyBcImx2cFwiIDogb3B0cy5wb3NpdGlvbkNhcmV0T25DbGljaywgXG4gICAgICAgICAgICBvcHRzLmRpZ2l0c09wdGlvbmFsID0gITEsIGlzTmFOKG9wdHMuZGlnaXRzKSAmJiAob3B0cy5kaWdpdHMgPSAyKSwgb3B0cy5fcmFkaXhEYW5jZSA9ICExLCBcbiAgICAgICAgICAgIHJhZGl4UG9pbnREZWYgPSBcIixcIiA9PT0gb3B0cy5yYWRpeFBvaW50ID8gXCI/XCIgOiBcIiFcIiwgXCJcIiAhPT0gb3B0cy5yYWRpeFBvaW50ICYmIHZvaWQgMCA9PT0gb3B0cy5kZWZpbml0aW9uc1tyYWRpeFBvaW50RGVmXSAmJiAob3B0cy5kZWZpbml0aW9uc1tyYWRpeFBvaW50RGVmXSA9IHt9LCBcbiAgICAgICAgICAgIG9wdHMuZGVmaW5pdGlvbnNbcmFkaXhQb2ludERlZl0udmFsaWRhdG9yID0gXCJbXCIgKyBvcHRzLnJhZGl4UG9pbnQgKyBcIl1cIiwgb3B0cy5kZWZpbml0aW9uc1tyYWRpeFBvaW50RGVmXS5wbGFjZWhvbGRlciA9IG9wdHMucmFkaXhQb2ludCwgXG4gICAgICAgICAgICBvcHRzLmRlZmluaXRpb25zW3JhZGl4UG9pbnREZWZdLnN0YXRpYyA9ICEwLCBvcHRzLmRlZmluaXRpb25zW3JhZGl4UG9pbnREZWZdLmdlbmVyYXRlZCA9ICEwKSkgOiAob3B0cy5fX2ZpbmFuY2VJbnB1dCA9ICExLCBcbiAgICAgICAgICAgIG9wdHMubnVtZXJpY0lucHV0ID0gITApO1xuICAgICAgICAgICAgdmFyIG1hc2sgPSBcIlsrXVwiLCBhbHRNYXNrO1xuICAgICAgICAgICAgaWYgKG1hc2sgKz0gYXV0b0VzY2FwZShvcHRzLnByZWZpeCwgb3B0cyksIFwiXCIgIT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IgPyAodm9pZCAwID09PSBvcHRzLmRlZmluaXRpb25zW29wdHMuZ3JvdXBTZXBhcmF0b3JdICYmIChvcHRzLmRlZmluaXRpb25zW29wdHMuZ3JvdXBTZXBhcmF0b3JdID0ge30sIFxuICAgICAgICAgICAgb3B0cy5kZWZpbml0aW9uc1tvcHRzLmdyb3VwU2VwYXJhdG9yXS52YWxpZGF0b3IgPSBcIltcIiArIG9wdHMuZ3JvdXBTZXBhcmF0b3IgKyBcIl1cIiwgXG4gICAgICAgICAgICBvcHRzLmRlZmluaXRpb25zW29wdHMuZ3JvdXBTZXBhcmF0b3JdLnBsYWNlaG9sZGVyID0gb3B0cy5ncm91cFNlcGFyYXRvciwgb3B0cy5kZWZpbml0aW9uc1tvcHRzLmdyb3VwU2VwYXJhdG9yXS5zdGF0aWMgPSAhMCwgXG4gICAgICAgICAgICBvcHRzLmRlZmluaXRpb25zW29wdHMuZ3JvdXBTZXBhcmF0b3JdLmdlbmVyYXRlZCA9ICEwKSwgbWFzayArPSBvcHRzLl9tYXNrKG9wdHMpKSA6IG1hc2sgKz0gXCI5eyt9XCIsIFxuICAgICAgICAgICAgdm9pZCAwICE9PSBvcHRzLmRpZ2l0cyAmJiAwICE9PSBvcHRzLmRpZ2l0cykge1xuICAgICAgICAgICAgICAgIHZhciBkcSA9IG9wdHMuZGlnaXRzLnRvU3RyaW5nKCkuc3BsaXQoXCIsXCIpO1xuICAgICAgICAgICAgICAgIGlzRmluaXRlKGRxWzBdKSAmJiBkcVsxXSAmJiBpc0Zpbml0ZShkcVsxXSkgPyBtYXNrICs9IHJhZGl4UG9pbnREZWYgKyBkZWNpbWFsRGVmICsgXCJ7XCIgKyBvcHRzLmRpZ2l0cyArIFwifVwiIDogKGlzTmFOKG9wdHMuZGlnaXRzKSB8fCAwIDwgcGFyc2VJbnQob3B0cy5kaWdpdHMpKSAmJiAob3B0cy5kaWdpdHNPcHRpb25hbCA/IChhbHRNYXNrID0gbWFzayArIHJhZGl4UG9pbnREZWYgKyBkZWNpbWFsRGVmICsgXCJ7MCxcIiArIG9wdHMuZGlnaXRzICsgXCJ9XCIsIFxuICAgICAgICAgICAgICAgIG9wdHMua2VlcFN0YXRpYyA9ICEwKSA6IG1hc2sgKz0gcmFkaXhQb2ludERlZiArIGRlY2ltYWxEZWYgKyBcIntcIiArIG9wdHMuZGlnaXRzICsgXCJ9XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hc2sgKz0gYXV0b0VzY2FwZShvcHRzLnN1ZmZpeCwgb3B0cyksIG1hc2sgKz0gXCJbLV1cIiwgYWx0TWFzayAmJiAobWFzayA9IFsgYWx0TWFzayArIGF1dG9Fc2NhcGUob3B0cy5zdWZmaXgsIG9wdHMpICsgXCJbLV1cIiwgbWFzayBdKSwgXG4gICAgICAgICAgICBvcHRzLmdyZWVkeSA9ICExLCBwYXJzZU1pbk1heE9wdGlvbnMob3B0cyksIG1hc2s7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gaGFubmRsZVJhZGl4RGFuY2UocG9zLCBjLCByYWRpeFBvcywgbWFza3NldCwgb3B0cykge1xuICAgICAgICAgICAgcmV0dXJuIG9wdHMuX3JhZGl4RGFuY2UgJiYgb3B0cy5udW1lcmljSW5wdXQgJiYgYyAhPT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrICYmIHBvcyA8PSByYWRpeFBvcyAmJiAoMCA8IHJhZGl4UG9zIHx8IGMgPT0gb3B0cy5yYWRpeFBvaW50KSAmJiAodm9pZCAwID09PSBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdIHx8IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zIC0gMV0uaW5wdXQgIT09IG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaykgJiYgKHBvcyAtPSAxKSwgXG4gICAgICAgICAgICBwb3M7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZGVjaW1hbFZhbGlkYXRvcihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgdmFyIHJhZGl4UG9zID0gbWFza3NldC5idWZmZXIgPyBtYXNrc2V0LmJ1ZmZlci5pbmRleE9mKG9wdHMucmFkaXhQb2ludCkgOiAtMSwgcmVzdWx0ID0gLTEgIT09IHJhZGl4UG9zICYmIG5ldyBSZWdFeHAoXCJbMC05XFx1ZmYxMS1cXHVmZjE5XVwiKS50ZXN0KGNocnMpO1xuICAgICAgICAgICAgcmV0dXJuIG9wdHMuX3JhZGl4RGFuY2UgJiYgcmVzdWx0ICYmIG51bGwgPT0gbWFza3NldC52YWxpZFBvc2l0aW9uc1tyYWRpeFBvc10gPyB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0OiB7XG4gICAgICAgICAgICAgICAgICAgIHBvczogcmFkaXhQb3MgPT09IHBvcyA/IHJhZGl4UG9zICsgMSA6IHJhZGl4UG9zLFxuICAgICAgICAgICAgICAgICAgICBjOiBvcHRzLnJhZGl4UG9pbnRcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBvczogcG9zXG4gICAgICAgICAgICB9IDogcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGNoZWNrRm9yTGVhZGluZ1plcm9lcyhidWZmZXIsIG9wdHMpIHtcbiAgICAgICAgICAgIHZhciBudW1iZXJNYXRjaGVzID0gbmV3IFJlZ0V4cChcIiheXCIgKyAoXCJcIiAhPT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCA/ICgwLCBfZXNjYXBlUmVnZXguZGVmYXVsdCkob3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkgKyBcIj9cIiA6IFwiXCIpICsgKDAsIFxuICAgICAgICAgICAgX2VzY2FwZVJlZ2V4LmRlZmF1bHQpKG9wdHMucHJlZml4KSArIFwiKSguKikoXCIgKyAoMCwgX2VzY2FwZVJlZ2V4LmRlZmF1bHQpKG9wdHMuc3VmZml4KSArIChcIlwiICE9IG9wdHMubmVnYXRpb25TeW1ib2wuYmFjayA/ICgwLCBcbiAgICAgICAgICAgIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2spICsgXCI/XCIgOiBcIlwiKSArIFwiJClcIikuZXhlYyhidWZmZXIuc2xpY2UoKS5yZXZlcnNlKCkuam9pbihcIlwiKSksIG51bWJlciA9IG51bWJlck1hdGNoZXMgPyBudW1iZXJNYXRjaGVzWzJdIDogXCJcIiwgbGVhZGluZ3plcm9lcyA9ICExO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciAmJiAobnVtYmVyID0gbnVtYmVyLnNwbGl0KG9wdHMucmFkaXhQb2ludC5jaGFyQXQoMCkpWzBdLCBsZWFkaW5nemVyb2VzID0gbmV3IFJlZ0V4cChcIl5bMFwiICsgb3B0cy5ncm91cFNlcGFyYXRvciArIFwiXSpcIikuZXhlYyhudW1iZXIpKSwgXG4gICAgICAgICAgICAhKCFsZWFkaW5nemVyb2VzIHx8ICEoMSA8IGxlYWRpbmd6ZXJvZXNbMF0ubGVuZ3RoIHx8IDAgPCBsZWFkaW5nemVyb2VzWzBdLmxlbmd0aCAmJiBsZWFkaW5nemVyb2VzWzBdLmxlbmd0aCA8IG51bWJlci5sZW5ndGgpKSAmJiBsZWFkaW5nemVyb2VzO1xuICAgICAgICB9XG4gICAgICAgIF9pbnB1dG1hc2suZGVmYXVsdC5leHRlbmRBbGlhc2VzKHtcbiAgICAgICAgICAgIG51bWVyaWM6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBnZW5NYXNrLFxuICAgICAgICAgICAgICAgIF9tYXNrOiBmdW5jdGlvbiBfbWFzayhvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIihcIiArIG9wdHMuZ3JvdXBTZXBhcmF0b3IgKyBcIjk5OSl7K3wxfVwiO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGlnaXRzOiBcIipcIixcbiAgICAgICAgICAgICAgICBkaWdpdHNPcHRpb25hbDogITAsXG4gICAgICAgICAgICAgICAgZW5mb3JjZURpZ2l0c09uQmx1cjogITEsXG4gICAgICAgICAgICAgICAgcmFkaXhQb2ludDogXCIuXCIsXG4gICAgICAgICAgICAgICAgcG9zaXRpb25DYXJldE9uQ2xpY2s6IFwicmFkaXhGb2N1c1wiLFxuICAgICAgICAgICAgICAgIF9yYWRpeERhbmNlOiAhMCxcbiAgICAgICAgICAgICAgICBncm91cFNlcGFyYXRvcjogXCJcIixcbiAgICAgICAgICAgICAgICBhbGxvd01pbnVzOiAhMCxcbiAgICAgICAgICAgICAgICBuZWdhdGlvblN5bWJvbDoge1xuICAgICAgICAgICAgICAgICAgICBmcm9udDogXCItXCIsXG4gICAgICAgICAgICAgICAgICAgIGJhY2s6IFwiXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHByZWZpeDogXCJcIixcbiAgICAgICAgICAgICAgICBzdWZmaXg6IFwiXCIsXG4gICAgICAgICAgICAgICAgbWluOiBudWxsLFxuICAgICAgICAgICAgICAgIG1heDogbnVsbCxcbiAgICAgICAgICAgICAgICBTZXRNYXhPbk92ZXJmbG93OiAhMSxcbiAgICAgICAgICAgICAgICBzdGVwOiAxLFxuICAgICAgICAgICAgICAgIGlucHV0VHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICAgICAgdW5tYXNrQXNOdW1iZXI6ICExLFxuICAgICAgICAgICAgICAgIHJvdW5kaW5nRk46IE1hdGgucm91bmQsXG4gICAgICAgICAgICAgICAgaW5wdXRtb2RlOiBcIm51bWVyaWNcIixcbiAgICAgICAgICAgICAgICBzaG9ydGN1dHM6IHtcbiAgICAgICAgICAgICAgICAgICAgazogXCIwMDBcIixcbiAgICAgICAgICAgICAgICAgICAgbTogXCIwMDAwMDBcIlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiMFwiLFxuICAgICAgICAgICAgICAgIGdyZWVkeTogITEsXG4gICAgICAgICAgICAgICAgcmlnaHRBbGlnbjogITAsXG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogITAsXG4gICAgICAgICAgICAgICAgYXV0b1VubWFzazogITEsXG4gICAgICAgICAgICAgICAgc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlcjogXCJcIixcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICAwOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGRlY2ltYWxWYWxpZGF0b3JcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgMToge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBkZWNpbWFsVmFsaWRhdG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5pdGlvblN5bWJvbDogXCI5XCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCIrXCI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogZnVuY3Rpb24gdmFsaWRhdG9yKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMuYWxsb3dNaW51cyAmJiAoXCItXCIgPT09IGNocnMgfHwgY2hycyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiLVwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLmFsbG93TWludXMgJiYgY2hycyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwcmVWYWxpZGF0aW9uOiBmdW5jdGlvbiBwcmVWYWxpZGF0aW9uKGJ1ZmZlciwgcG9zLCBjLCBpc1NlbGVjdGlvbiwgb3B0cywgbWFza3NldCwgY2FyZXRQb3MsIHN0cmljdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoITEgIT09IG9wdHMuX19maW5hbmNlSW5wdXQgJiYgYyA9PT0gb3B0cy5yYWRpeFBvaW50KSByZXR1cm4gITE7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXR0ZXJuO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGF0dGVybiA9IG9wdHMuc2hvcnRjdXRzICYmIG9wdHMuc2hvcnRjdXRzW2NdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoMSA8IHBhdHRlcm4ubGVuZ3RoKSBmb3IgKHZhciBpbnNlcnRzID0gW10sIGkgPSAwOyBpIDwgcGF0dGVybi5sZW5ndGg7IGkrKykgaW5zZXJ0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvcyArIGksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYzogcGF0dGVybltpXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpY3Q6ICExXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0OiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvcyA9IGJ1ZmZlci5pbmRleE9mKG9wdHMucmFkaXhQb2ludCksIGluaXRQb3MgPSBwb3M7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwb3MgPSBoYW5uZGxlUmFkaXhEYW5jZShwb3MsIGMsIHJhZGl4UG9zLCBtYXNrc2V0LCBvcHRzKSwgXCItXCIgPT09IGMgfHwgYyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEwICE9PSBvcHRzLmFsbG93TWludXMpIHJldHVybiAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc05lZ2F0aXZlID0gITEsIGZyb250ID0gZmluZFZhbGlkKFwiK1wiLCBtYXNrc2V0KSwgYmFjayA9IGZpbmRWYWxpZChcIi1cIiwgbWFza3NldCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTEgIT09IGZyb250ICYmIChpc05lZ2F0aXZlID0gWyBmcm9udCwgYmFjayBdKSwgITEgIT09IGlzTmVnYXRpdmUgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlOiBpc05lZ2F0aXZlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBpbml0UG9zIC0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udC5sZW5ndGhcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0OiBbIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBmaW5kVmFsaWRhdG9yKFwiK1wiLCBtYXNrc2V0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYzogb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbUlzVmFsaWQ6ICEwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IGZpbmRWYWxpZGF0b3IoXCItXCIsIG1hc2tzZXQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjOiBvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2ssXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb21Jc1ZhbGlkOiB2b2lkIDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IGluaXRQb3MgKyBvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2subGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChjID09PSBvcHRzLmdyb3VwU2VwYXJhdG9yKSByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IGluaXRQb3NcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0cmljdCkgcmV0dXJuICEwO1xuICAgICAgICAgICAgICAgICAgICBpZiAoLTEgIT09IHJhZGl4UG9zICYmICEwID09PSBvcHRzLl9yYWRpeERhbmNlICYmICExID09PSBpc1NlbGVjdGlvbiAmJiBjID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgdm9pZCAwICE9PSBvcHRzLmRpZ2l0cyAmJiAoaXNOYU4ob3B0cy5kaWdpdHMpIHx8IDAgPCBwYXJzZUludChvcHRzLmRpZ2l0cykpICYmIHJhZGl4UG9zICE9PSBwb3MpIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogb3B0cy5fcmFkaXhEYW5jZSAmJiBwb3MgPT09IHJhZGl4UG9zIC0gMSA/IHJhZGl4UG9zICsgMSA6IHJhZGl4UG9zXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlmICghMSA9PT0gb3B0cy5fX2ZpbmFuY2VJbnB1dCkgaWYgKGlzU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5kaWdpdHNPcHRpb25hbCkgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXdyaXRlUG9zaXRpb246IGNhcmV0UG9zLmVuZFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3B0cy5kaWdpdHNPcHRpb25hbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYXJldFBvcy5iZWdpbiA+IHJhZGl4UG9zICYmIGNhcmV0UG9zLmVuZCA8PSByYWRpeFBvcykgcmV0dXJuIGMgPT09IG9wdHMucmFkaXhQb2ludCA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0OiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHJhZGl4UG9zICsgMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IFwiMFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbUlzVmFsaWQ6ICEwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJld3JpdGVQb3NpdGlvbjogcmFkaXhQb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXdyaXRlUG9zaXRpb246IHJhZGl4UG9zICsgMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhcmV0UG9zLmJlZ2luIDwgcmFkaXhQb3MpIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJld3JpdGVQb3NpdGlvbjogY2FyZXRQb3MuYmVnaW4gLSAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghb3B0cy5zaG93TWFza09uSG92ZXIgJiYgIW9wdHMuc2hvd01hc2tPbkZvY3VzICYmICFvcHRzLmRpZ2l0c09wdGlvbmFsICYmIDAgPCBvcHRzLmRpZ2l0cyAmJiBcIlwiID09PSB0aGlzLmlucHV0bWFzay5fX3ZhbHVlR2V0LmNhbGwodGhpcykpIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXdyaXRlUG9zaXRpb246IHJhZGl4UG9zXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXdyaXRlUG9zaXRpb246IHBvc1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcG9zdFZhbGlkYXRpb246IGZ1bmN0aW9uIHBvc3RWYWxpZGF0aW9uKGJ1ZmZlciwgcG9zLCBjLCBjdXJyZW50UmVzdWx0LCBvcHRzLCBtYXNrc2V0LCBzdHJpY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCExID09PSBjdXJyZW50UmVzdWx0KSByZXR1cm4gY3VycmVudFJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0cmljdCkgcmV0dXJuICEwO1xuICAgICAgICAgICAgICAgICAgICBpZiAobnVsbCAhPT0gb3B0cy5taW4gfHwgbnVsbCAhPT0gb3B0cy5tYXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB1bm1hc2tlZCA9IG9wdHMub25Vbk1hc2soYnVmZmVyLnNsaWNlKCkucmV2ZXJzZSgpLmpvaW4oXCJcIiksIHZvaWQgMCwgJC5leHRlbmQoe30sIG9wdHMsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bm1hc2tBc051bWJlcjogITBcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChudWxsICE9PSBvcHRzLm1pbiAmJiB1bm1hc2tlZCA8IG9wdHMubWluICYmICh1bm1hc2tlZC50b1N0cmluZygpLmxlbmd0aCA+IG9wdHMubWluLnRvU3RyaW5nKCkubGVuZ3RoIHx8IHVubWFza2VkIDwgMCkpIHJldHVybiAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChudWxsICE9PSBvcHRzLm1heCAmJiB1bm1hc2tlZCA+IG9wdHMubWF4KSByZXR1cm4gISFvcHRzLlNldE1heE9uT3ZlcmZsb3cgJiYge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2hGcm9tQnVmZmVyOiAhMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXI6IGFsaWduRGlnaXRzKG9wdHMubWF4LnRvU3RyaW5nKCkucmVwbGFjZShcIi5cIiwgb3B0cy5yYWRpeFBvaW50KS5zcGxpdChcIlwiKSwgb3B0cy5kaWdpdHMsIG9wdHMpLnJldmVyc2UoKVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudFJlc3VsdDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uVW5NYXNrOiBmdW5jdGlvbiBvblVuTWFzayhtYXNrZWRWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJcIiA9PT0gdW5tYXNrZWRWYWx1ZSAmJiAhMCA9PT0gb3B0cy5udWxsYWJsZSkgcmV0dXJuIHVubWFza2VkVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9jZXNzVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXBsYWNlKG9wdHMucHJlZml4LCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG9wdHMuc3VmZml4LCBcIlwiKSwgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cCgoMCwgXG4gICAgICAgICAgICAgICAgICAgIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLmdyb3VwU2VwYXJhdG9yKSwgXCJnXCIpLCBcIlwiKSwgXCJcIiAhPT0gb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCkgJiYgKHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAob3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCksIFwiZ1wiKSwgXCIwXCIpKSwgXG4gICAgICAgICAgICAgICAgICAgIG9wdHMudW5tYXNrQXNOdW1iZXIgPyAoXCJcIiAhPT0gb3B0cy5yYWRpeFBvaW50ICYmIC0xICE9PSBwcm9jZXNzVmFsdWUuaW5kZXhPZihvcHRzLnJhZGl4UG9pbnQpICYmIChwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShfZXNjYXBlUmVnZXguZGVmYXVsdC5jYWxsKHRoaXMsIG9wdHMucmFkaXhQb2ludCksIFwiLlwiKSksIFxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKFwiXlwiICsgKDAsIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250KSksIFwiLVwiKSwgXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoKDAsIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2spICsgXCIkXCIpLCBcIlwiKSwgXG4gICAgICAgICAgICAgICAgICAgIE51bWJlcihwcm9jZXNzVmFsdWUpKSA6IHByb2Nlc3NWYWx1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGlzQ29tcGxldGU6IGZ1bmN0aW9uIGlzQ29tcGxldGUoYnVmZmVyLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXNrZWRWYWx1ZSA9IChvcHRzLm51bWVyaWNJbnB1dCA/IGJ1ZmZlci5zbGljZSgpLnJldmVyc2UoKSA6IGJ1ZmZlcikuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKFwiXlwiICsgKDAsIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250KSksIFwiLVwiKSwgXG4gICAgICAgICAgICAgICAgICAgIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKCgwLCBfZXNjYXBlUmVnZXguZGVmYXVsdCkob3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSArIFwiJFwiKSwgXCJcIiksIFxuICAgICAgICAgICAgICAgICAgICBtYXNrZWRWYWx1ZSA9IG1hc2tlZFZhbHVlLnJlcGxhY2Uob3B0cy5wcmVmaXgsIFwiXCIpLCBtYXNrZWRWYWx1ZSA9IG1hc2tlZFZhbHVlLnJlcGxhY2Uob3B0cy5zdWZmaXgsIFwiXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgbWFza2VkVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoKDAsIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLmdyb3VwU2VwYXJhdG9yKSArIFwiKFswLTldezN9KVwiLCBcImdcIiksIFwiJDFcIiksIFxuICAgICAgICAgICAgICAgICAgICBcIixcIiA9PT0gb3B0cy5yYWRpeFBvaW50ICYmIChtYXNrZWRWYWx1ZSA9IG1hc2tlZFZhbHVlLnJlcGxhY2UoKDAsIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLnJhZGl4UG9pbnQpLCBcIi5cIikpLCBcbiAgICAgICAgICAgICAgICAgICAgaXNGaW5pdGUobWFza2VkVmFsdWUpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25CZWZvcmVNYXNrOiBmdW5jdGlvbiBvbkJlZm9yZU1hc2soaW5pdGlhbFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvaW50ID0gb3B0cy5yYWRpeFBvaW50IHx8IFwiLFwiO1xuICAgICAgICAgICAgICAgICAgICBpc0Zpbml0ZShvcHRzLmRpZ2l0cykgJiYgKG9wdHMuZGlnaXRzID0gcGFyc2VJbnQob3B0cy5kaWdpdHMpKSwgXCJudW1iZXJcIiAhPSB0eXBlb2YgaW5pdGlhbFZhbHVlICYmIFwibnVtYmVyXCIgIT09IG9wdHMuaW5wdXRUeXBlIHx8IFwiXCIgPT09IHJhZGl4UG9pbnQgfHwgKGluaXRpYWxWYWx1ZSA9IGluaXRpYWxWYWx1ZS50b1N0cmluZygpLnJlcGxhY2UoXCIuXCIsIHJhZGl4UG9pbnQpKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlzTmFndGl2ZSA9IFwiLVwiID09PSBpbml0aWFsVmFsdWUuY2hhckF0KDApIHx8IGluaXRpYWxWYWx1ZS5jaGFyQXQoMCkgPT09IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQsIHZhbHVlUGFydHMgPSBpbml0aWFsVmFsdWUuc3BsaXQocmFkaXhQb2ludCksIGludGVnZXJQYXJ0ID0gdmFsdWVQYXJ0c1swXS5yZXBsYWNlKC9bXlxcLTAtOV0vZywgXCJcIiksIGRlY2ltYWxQYXJ0ID0gMSA8IHZhbHVlUGFydHMubGVuZ3RoID8gdmFsdWVQYXJ0c1sxXS5yZXBsYWNlKC9bXjAtOV0vZywgXCJcIikgOiBcIlwiLCBmb3JjZURpZ2l0cyA9IDEgPCB2YWx1ZVBhcnRzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gaW50ZWdlclBhcnQgKyAoXCJcIiAhPT0gZGVjaW1hbFBhcnQgPyByYWRpeFBvaW50ICsgZGVjaW1hbFBhcnQgOiBkZWNpbWFsUGFydCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkaWdpdHMgPSAwO1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJcIiAhPT0gcmFkaXhQb2ludCAmJiAoZGlnaXRzID0gb3B0cy5kaWdpdHNPcHRpb25hbCA/IG9wdHMuZGlnaXRzIDwgZGVjaW1hbFBhcnQubGVuZ3RoID8gb3B0cy5kaWdpdHMgOiBkZWNpbWFsUGFydC5sZW5ndGggOiBvcHRzLmRpZ2l0cywgXG4gICAgICAgICAgICAgICAgICAgIFwiXCIgIT09IGRlY2ltYWxQYXJ0IHx8ICFvcHRzLmRpZ2l0c09wdGlvbmFsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRpZ2l0c0ZhY3RvciA9IE1hdGgucG93KDEwLCBkaWdpdHMgfHwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUucmVwbGFjZSgoMCwgX2VzY2FwZVJlZ2V4LmRlZmF1bHQpKHJhZGl4UG9pbnQpLCBcIi5cIiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNOYU4ocGFyc2VGbG9hdChpbml0aWFsVmFsdWUpKSB8fCAoaW5pdGlhbFZhbHVlID0gKG9wdHMucm91bmRpbmdGTihwYXJzZUZsb2F0KGluaXRpYWxWYWx1ZSkgKiBkaWdpdHNGYWN0b3IpIC8gZGlnaXRzRmFjdG9yKS50b0ZpeGVkKGRpZ2l0cykpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGluaXRpYWxWYWx1ZS50b1N0cmluZygpLnJlcGxhY2UoXCIuXCIsIHJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvcHRzLmRpZ2l0cyAmJiAtMSAhPT0gaW5pdGlhbFZhbHVlLmluZGV4T2YocmFkaXhQb2ludCkgJiYgKGluaXRpYWxWYWx1ZSA9IGluaXRpYWxWYWx1ZS5zdWJzdHJpbmcoMCwgaW5pdGlhbFZhbHVlLmluZGV4T2YocmFkaXhQb2ludCkpKSwgXG4gICAgICAgICAgICAgICAgICAgIG51bGwgIT09IG9wdHMubWluIHx8IG51bGwgIT09IG9wdHMubWF4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbnVtYmVyVmFsdWUgPSBpbml0aWFsVmFsdWUudG9TdHJpbmcoKS5yZXBsYWNlKHJhZGl4UG9pbnQsIFwiLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bGwgIT09IG9wdHMubWluICYmIG51bWJlclZhbHVlIDwgb3B0cy5taW4gPyBpbml0aWFsVmFsdWUgPSBvcHRzLm1pbi50b1N0cmluZygpLnJlcGxhY2UoXCIuXCIsIHJhZGl4UG9pbnQpIDogbnVsbCAhPT0gb3B0cy5tYXggJiYgbnVtYmVyVmFsdWUgPiBvcHRzLm1heCAmJiAoaW5pdGlhbFZhbHVlID0gb3B0cy5tYXgudG9TdHJpbmcoKS5yZXBsYWNlKFwiLlwiLCByYWRpeFBvaW50KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzTmFndGl2ZSAmJiBcIi1cIiAhPT0gaW5pdGlhbFZhbHVlLmNoYXJBdCgwKSAmJiAoaW5pdGlhbFZhbHVlID0gXCItXCIgKyBpbml0aWFsVmFsdWUpLCBcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25EaWdpdHMoaW5pdGlhbFZhbHVlLnRvU3RyaW5nKCkuc3BsaXQoXCJcIiksIGRpZ2l0cywgb3B0cywgZm9yY2VEaWdpdHMpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkJlZm9yZVdyaXRlOiBmdW5jdGlvbiBvbkJlZm9yZVdyaXRlKGUsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gc3RyaXBCdWZmZXIoYnVmZmVyLCBzdHJpcFJhZGl4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoITEgIT09IG9wdHMuX19maW5hbmNlSW5wdXQgfHwgc3RyaXBSYWRpeCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwb3NpdGlvbiA9IGJ1ZmZlci5pbmRleE9mKG9wdHMucmFkaXhQb2ludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLTEgIT09IHBvc2l0aW9uICYmIGJ1ZmZlci5zcGxpY2UocG9zaXRpb24sIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwiXCIgIT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IpIGZvciAoOy0xICE9PSAocG9zaXRpb24gPSBidWZmZXIuaW5kZXhPZihvcHRzLmdyb3VwU2VwYXJhdG9yKSk7ICkgYnVmZmVyLnNwbGljZShwb3NpdGlvbiwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYnVmZmVyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQsIGxlYWRpbmd6ZXJvZXMgPSBjaGVja0ZvckxlYWRpbmdaZXJvZXMoYnVmZmVyLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlYWRpbmd6ZXJvZXMpIGZvciAodmFyIGNhcmV0TmR4ID0gYnVmZmVyLmpvaW4oXCJcIikubGFzdEluZGV4T2YobGVhZGluZ3plcm9lc1swXS5zcGxpdChcIlwiKS5yZXZlcnNlKCkuam9pbihcIlwiKSkgLSAobGVhZGluZ3plcm9lc1swXSA9PSBsZWFkaW5nemVyb2VzLmlucHV0ID8gMCA6IDEpLCBvZmZzZXQgPSBsZWFkaW5nemVyb2VzWzBdID09IGxlYWRpbmd6ZXJvZXMuaW5wdXQgPyAxIDogMCwgaSA9IGxlYWRpbmd6ZXJvZXNbMF0ubGVuZ3RoIC0gb2Zmc2V0OyAwIDwgaTsgaS0tKSBkZWxldGUgdGhpcy5tYXNrc2V0LnZhbGlkUG9zaXRpb25zW2NhcmV0TmR4ICsgaV0sIFxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgYnVmZmVyW2NhcmV0TmR4ICsgaV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChlKSBzd2l0Y2ggKGUudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJibHVyXCI6XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImNoZWNrdmFsXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobnVsbCAhPT0gb3B0cy5taW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdW5tYXNrZWQgPSBvcHRzLm9uVW5NYXNrKGJ1ZmZlci5zbGljZSgpLnJldmVyc2UoKS5qb2luKFwiXCIpLCB2b2lkIDAsICQuZXh0ZW5kKHt9LCBvcHRzLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVubWFza0FzTnVtYmVyOiAhMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobnVsbCAhPT0gb3B0cy5taW4gJiYgdW5tYXNrZWQgPCBvcHRzLm1pbikgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXI6ICEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXI6IGFsaWduRGlnaXRzKG9wdHMubWluLnRvU3RyaW5nKCkucmVwbGFjZShcIi5cIiwgb3B0cy5yYWRpeFBvaW50KS5zcGxpdChcIlwiKSwgb3B0cy5kaWdpdHMsIG9wdHMpLnJldmVyc2UoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYnVmZmVyW2J1ZmZlci5sZW5ndGggLSAxXSA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBubWJyTXRjaHMgPSBuZXcgUmVnRXhwKFwiKF5cIiArIChcIlwiICE9IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQgPyAoMCwgX2VzY2FwZVJlZ2V4LmRlZmF1bHQpKG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpICsgXCI/XCIgOiBcIlwiKSArICgwLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfZXNjYXBlUmVnZXguZGVmYXVsdCkob3B0cy5wcmVmaXgpICsgXCIpKC4qKShcIiArICgwLCBfZXNjYXBlUmVnZXguZGVmYXVsdCkob3B0cy5zdWZmaXgpICsgKFwiXCIgIT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrID8gKDAsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9lc2NhcGVSZWdleC5kZWZhdWx0KShvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2spICsgXCI/XCIgOiBcIlwiKSArIFwiJClcIikuZXhlYyhzdHJpcEJ1ZmZlcihidWZmZXIuc2xpY2UoKSwgITApLnJldmVyc2UoKS5qb2luKFwiXCIpKSwgbnVtYmVyID0gbm1ick10Y2hzID8gbm1ick10Y2hzWzJdIDogXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAwID09IG51bWJlciAmJiAocmVzdWx0ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcjogITAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlcjogWyAwIF1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBcIlwiICE9PSBvcHRzLnJhZGl4UG9pbnQgJiYgYnVmZmVyWzBdID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgKHJlc3VsdCAmJiByZXN1bHQuYnVmZmVyID8gcmVzdWx0LmJ1ZmZlci5zaGlmdCgpIDogKGJ1ZmZlci5zaGlmdCgpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcjogITAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiBzdHJpcEJ1ZmZlcihidWZmZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5lbmZvcmNlRGlnaXRzT25CbHVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0IHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBiZmZyID0gcmVzdWx0ICYmIHJlc3VsdC5idWZmZXIgfHwgYnVmZmVyLnNsaWNlKCkucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5yZWZyZXNoRnJvbUJ1ZmZlciA9ICEwLCByZXN1bHQuYnVmZmVyID0gYWxpZ25EaWdpdHMoYmZmciwgb3B0cy5kaWdpdHMsIG9wdHMsICEwKS5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uS2V5RG93bjogZnVuY3Rpb24gb25LZXlEb3duKGUsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQodGhpcyksIGJmZnI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLmN0cmxLZXkpIHN3aXRjaCAoZS5rZXlDb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBfa2V5Y29kZS5kZWZhdWx0LlVQOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRtYXNrLl9fdmFsdWVTZXQuY2FsbCh0aGlzLCBwYXJzZUZsb2F0KHRoaXMuaW5wdXRtYXNrLnVubWFza2VkdmFsdWUoKSkgKyBwYXJzZUludChvcHRzLnN0ZXApKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcInNldHZhbHVlXCIpLCAhMTtcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX2tleWNvZGUuZGVmYXVsdC5ET1dOOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRtYXNrLl9fdmFsdWVTZXQuY2FsbCh0aGlzLCBwYXJzZUZsb2F0KHRoaXMuaW5wdXRtYXNrLnVubWFza2VkdmFsdWUoKSkgLSBwYXJzZUludChvcHRzLnN0ZXApKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcInNldHZhbHVlXCIpLCAhMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWUuc2hpZnRLZXkgJiYgKGUua2V5Q29kZSA9PT0gX2tleWNvZGUuZGVmYXVsdC5ERUxFVEUgfHwgZS5rZXlDb2RlID09PSBfa2V5Y29kZS5kZWZhdWx0LkJBQ0tTUEFDRSB8fCBlLmtleUNvZGUgPT09IF9rZXljb2RlLmRlZmF1bHQuQkFDS1NQQUNFX1NBRkFSSSkgJiYgY2FyZXRQb3MuYmVnaW4gIT09IGJ1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChidWZmZXJbZS5rZXlDb2RlID09PSBfa2V5Y29kZS5kZWZhdWx0LkRFTEVURSA/IGNhcmV0UG9zLmJlZ2luIC0gMSA6IGNhcmV0UG9zLmVuZF0gPT09IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpIHJldHVybiBiZmZyID0gYnVmZmVyLnNsaWNlKCkucmV2ZXJzZSgpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiXCIgIT09IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQgJiYgYmZmci5zaGlmdCgpLCBcIlwiICE9PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2sgJiYgYmZmci5wb3AoKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcInNldHZhbHVlXCIsIFsgYmZmci5qb2luKFwiXCIpLCBjYXJldFBvcy5iZWdpbiBdKSwgITE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoITAgPT09IG9wdHMuX3JhZGl4RGFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFkaXhQb3MgPSBidWZmZXIuaW5kZXhPZihvcHRzLnJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmRpZ2l0c09wdGlvbmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgwID09PSByYWRpeFBvcykgcmV0dXJuIGJmZnIgPSBidWZmZXIuc2xpY2UoKS5yZXZlcnNlKCksIGJmZnIucG9wKCksICRpbnB1dC50cmlnZ2VyKFwic2V0dmFsdWVcIiwgWyBiZmZyLmpvaW4oXCJcIiksIGNhcmV0UG9zLmJlZ2luID49IGJmZnIubGVuZ3RoID8gYmZmci5sZW5ndGggOiBjYXJldFBvcy5iZWdpbiBdKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICExO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoLTEgIT09IHJhZGl4UG9zICYmIChjYXJldFBvcy5iZWdpbiA8IHJhZGl4UG9zIHx8IGNhcmV0UG9zLmVuZCA8IHJhZGl4UG9zIHx8IGUua2V5Q29kZSA9PT0gX2tleWNvZGUuZGVmYXVsdC5ERUxFVEUgJiYgY2FyZXRQb3MuYmVnaW4gPT09IHJhZGl4UG9zKSkgcmV0dXJuIGNhcmV0UG9zLmJlZ2luICE9PSBjYXJldFBvcy5lbmQgfHwgZS5rZXlDb2RlICE9PSBfa2V5Y29kZS5kZWZhdWx0LkJBQ0tTUEFDRSAmJiBlLmtleUNvZGUgIT09IF9rZXljb2RlLmRlZmF1bHQuQkFDS1NQQUNFX1NBRkFSSSB8fCBjYXJldFBvcy5iZWdpbisrLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZmZyID0gYnVmZmVyLnNsaWNlKCkucmV2ZXJzZSgpLCBiZmZyLnNwbGljZShiZmZyLmxlbmd0aCAtIGNhcmV0UG9zLmJlZ2luLCBjYXJldFBvcy5iZWdpbiAtIGNhcmV0UG9zLmVuZCArIDEpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZmZyID0gYWxpZ25EaWdpdHMoYmZmciwgb3B0cy5kaWdpdHMsIG9wdHMpLmpvaW4oXCJcIiksICRpbnB1dC50cmlnZ2VyKFwic2V0dmFsdWVcIiwgWyBiZmZyLCBjYXJldFBvcy5iZWdpbiA+PSBiZmZyLmxlbmd0aCA/IHJhZGl4UG9zICsgMSA6IGNhcmV0UG9zLmJlZ2luIF0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAhMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjdXJyZW5jeToge1xuICAgICAgICAgICAgICAgIHByZWZpeDogXCJcIixcbiAgICAgICAgICAgICAgICBncm91cFNlcGFyYXRvcjogXCIsXCIsXG4gICAgICAgICAgICAgICAgYWxpYXM6IFwibnVtZXJpY1wiLFxuICAgICAgICAgICAgICAgIGRpZ2l0czogMixcbiAgICAgICAgICAgICAgICBkaWdpdHNPcHRpb25hbDogITFcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWNpbWFsOiB7XG4gICAgICAgICAgICAgICAgYWxpYXM6IFwibnVtZXJpY1wiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW50ZWdlcjoge1xuICAgICAgICAgICAgICAgIGFsaWFzOiBcIm51bWVyaWNcIixcbiAgICAgICAgICAgICAgICBkaWdpdHM6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwZXJjZW50YWdlOiB7XG4gICAgICAgICAgICAgICAgYWxpYXM6IFwibnVtZXJpY1wiLFxuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBtYXg6IDEwMCxcbiAgICAgICAgICAgICAgICBzdWZmaXg6IFwiICVcIixcbiAgICAgICAgICAgICAgICBkaWdpdHM6IDAsXG4gICAgICAgICAgICAgICAgYWxsb3dNaW51czogITFcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbmRpYW5uczoge1xuICAgICAgICAgICAgICAgIGFsaWFzOiBcIm51bWVyaWNcIixcbiAgICAgICAgICAgICAgICBfbWFzazogZnVuY3Rpb24gX21hc2sob3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCIoXCIgKyBvcHRzLmdyb3VwU2VwYXJhdG9yICsgXCI5OSl7KnwxfShcIiArIG9wdHMuZ3JvdXBTZXBhcmF0b3IgKyBcIjk5OSl7MXwxfVwiO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZ3JvdXBTZXBhcmF0b3I6IFwiLFwiLFxuICAgICAgICAgICAgICAgIHJhZGl4UG9pbnQ6IFwiLlwiLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIjBcIixcbiAgICAgICAgICAgICAgICBkaWdpdHM6IDIsXG4gICAgICAgICAgICAgICAgZGlnaXRzT3B0aW9uYWw6ICExXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgdmFyIF93aW5kb3cgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMTMpKSwgX2lucHV0bWFzayA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygxKSk7XG4gICAgICAgIGZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gX3R5cGVvZiA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIFwic3ltYm9sXCIgPT0gdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA/IGZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgICAgICAgICB9IDogZnVuY3Rpb24gX3R5cGVvZihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqICYmIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xuICAgICAgICAgICAgfSwgX3R5cGVvZihvYmopO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgIGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykge1xuICAgICAgICAgICAgaWYgKFwiZnVuY3Rpb25cIiAhPSB0eXBlb2Ygc3VwZXJDbGFzcyAmJiBudWxsICE9PSBzdXBlckNsYXNzKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb25cIik7XG4gICAgICAgICAgICBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogc3ViQ2xhc3MsXG4gICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiAhMCxcbiAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiAhMFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLCBzdXBlckNsYXNzICYmIF9zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX2NyZWF0ZVN1cGVyKERlcml2ZWQpIHtcbiAgICAgICAgICAgIHZhciBoYXNOYXRpdmVSZWZsZWN0Q29uc3RydWN0ID0gX2lzTmF0aXZlUmVmbGVjdENvbnN0cnVjdCgpO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIF9jcmVhdGVTdXBlckludGVybmFsKCkge1xuICAgICAgICAgICAgICAgIHZhciBTdXBlciA9IF9nZXRQcm90b3R5cGVPZihEZXJpdmVkKSwgcmVzdWx0O1xuICAgICAgICAgICAgICAgIGlmIChoYXNOYXRpdmVSZWZsZWN0Q29uc3RydWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBOZXdUYXJnZXQgPSBfZ2V0UHJvdG90eXBlT2YodGhpcykuY29uc3RydWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFJlZmxlY3QuY29uc3RydWN0KFN1cGVyLCBhcmd1bWVudHMsIE5ld1RhcmdldCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHJlc3VsdCA9IFN1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIHJlc3VsdCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHtcbiAgICAgICAgICAgIHJldHVybiAhY2FsbCB8fCBcIm9iamVjdFwiICE9PSBfdHlwZW9mKGNhbGwpICYmIFwiZnVuY3Rpb25cIiAhPSB0eXBlb2YgY2FsbCA/IF9hc3NlcnRUaGlzSW5pdGlhbGl6ZWQoc2VsZikgOiBjYWxsO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9hc3NlcnRUaGlzSW5pdGlhbGl6ZWQoc2VsZikge1xuICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gc2VsZikgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKFwidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkXCIpO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX3dyYXBOYXRpdmVTdXBlcihDbGFzcykge1xuICAgICAgICAgICAgdmFyIF9jYWNoZSA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgTWFwID8gbmV3IE1hcCgpIDogdm9pZCAwO1xuICAgICAgICAgICAgcmV0dXJuIF93cmFwTmF0aXZlU3VwZXIgPSBmdW5jdGlvbiBfd3JhcE5hdGl2ZVN1cGVyKENsYXNzKSB7XG4gICAgICAgICAgICAgICAgaWYgKG51bGwgPT09IENsYXNzIHx8ICFfaXNOYXRpdmVGdW5jdGlvbihDbGFzcykpIHJldHVybiBDbGFzcztcbiAgICAgICAgICAgICAgICBpZiAoXCJmdW5jdGlvblwiICE9IHR5cGVvZiBDbGFzcykgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uXCIpO1xuICAgICAgICAgICAgICAgIGlmIChcInVuZGVmaW5lZFwiICE9IHR5cGVvZiBfY2FjaGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF9jYWNoZS5oYXMoQ2xhc3MpKSByZXR1cm4gX2NhY2hlLmdldChDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgIF9jYWNoZS5zZXQoQ2xhc3MsIFdyYXBwZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBXcmFwcGVyKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NvbnN0cnVjdChDbGFzcywgYXJndW1lbnRzLCBfZ2V0UHJvdG90eXBlT2YodGhpcykuY29uc3RydWN0b3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gV3JhcHBlci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKENsYXNzLnByb3RvdHlwZSwge1xuICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IFdyYXBwZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiAhMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiAhMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogITBcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLCBfc2V0UHJvdG90eXBlT2YoV3JhcHBlciwgQ2xhc3MpO1xuICAgICAgICAgICAgfSwgX3dyYXBOYXRpdmVTdXBlcihDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX2NvbnN0cnVjdChQYXJlbnQsIGFyZ3MsIENsYXNzKSB7XG4gICAgICAgICAgICByZXR1cm4gX2NvbnN0cnVjdCA9IF9pc05hdGl2ZVJlZmxlY3RDb25zdHJ1Y3QoKSA/IFJlZmxlY3QuY29uc3RydWN0IDogZnVuY3Rpb24gX2NvbnN0cnVjdChQYXJlbnQsIGFyZ3MsIENsYXNzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGEgPSBbIG51bGwgXTtcbiAgICAgICAgICAgICAgICBhLnB1c2guYXBwbHkoYSwgYXJncyk7XG4gICAgICAgICAgICAgICAgdmFyIENvbnN0cnVjdG9yID0gRnVuY3Rpb24uYmluZC5hcHBseShQYXJlbnQsIGEpLCBpbnN0YW5jZSA9IG5ldyBDb25zdHJ1Y3RvcigpO1xuICAgICAgICAgICAgICAgIHJldHVybiBDbGFzcyAmJiBfc2V0UHJvdG90eXBlT2YoaW5zdGFuY2UsIENsYXNzLnByb3RvdHlwZSksIGluc3RhbmNlO1xuICAgICAgICAgICAgfSwgX2NvbnN0cnVjdC5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9pc05hdGl2ZVJlZmxlY3RDb25zdHJ1Y3QoKSB7XG4gICAgICAgICAgICBpZiAoXCJ1bmRlZmluZWRcIiA9PSB0eXBlb2YgUmVmbGVjdCB8fCAhUmVmbGVjdC5jb25zdHJ1Y3QpIHJldHVybiAhMTtcbiAgICAgICAgICAgIGlmIChSZWZsZWN0LmNvbnN0cnVjdC5zaGFtKSByZXR1cm4gITE7XG4gICAgICAgICAgICBpZiAoXCJmdW5jdGlvblwiID09IHR5cGVvZiBQcm94eSkgcmV0dXJuICEwO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGF0ZS5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChSZWZsZWN0LmNvbnN0cnVjdChEYXRlLCBbXSwgZnVuY3Rpb24oKSB7fSkpLCBcbiAgICAgICAgICAgICAgICAhMDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gITE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX2lzTmF0aXZlRnVuY3Rpb24oZm4pIHtcbiAgICAgICAgICAgIHJldHVybiAtMSAhPT0gRnVuY3Rpb24udG9TdHJpbmcuY2FsbChmbikuaW5kZXhPZihcIltuYXRpdmUgY29kZV1cIik7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX3NldFByb3RvdHlwZU9mKG8sIHApIHtcbiAgICAgICAgICAgIHJldHVybiBfc2V0UHJvdG90eXBlT2YgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwgZnVuY3Rpb24gX3NldFByb3RvdHlwZU9mKG8sIHApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gby5fX3Byb3RvX18gPSBwLCBvO1xuICAgICAgICAgICAgfSwgX3NldFByb3RvdHlwZU9mKG8sIHApO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9nZXRQcm90b3R5cGVPZihvKSB7XG4gICAgICAgICAgICByZXR1cm4gX2dldFByb3RvdHlwZU9mID0gT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LmdldFByb3RvdHlwZU9mIDogZnVuY3Rpb24gX2dldFByb3RvdHlwZU9mKG8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gby5fX3Byb3RvX18gfHwgT2JqZWN0LmdldFByb3RvdHlwZU9mKG8pO1xuICAgICAgICAgICAgfSwgX2dldFByb3RvdHlwZU9mKG8pO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDoge1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IG9ialxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZG9jdW1lbnQgPSBfd2luZG93LmRlZmF1bHQuZG9jdW1lbnQ7XG4gICAgICAgIGlmIChkb2N1bWVudCAmJiBkb2N1bWVudC5oZWFkICYmIGRvY3VtZW50LmhlYWQuYXR0YWNoU2hhZG93ICYmIF93aW5kb3cuZGVmYXVsdC5jdXN0b21FbGVtZW50cyAmJiB2b2lkIDAgPT09IF93aW5kb3cuZGVmYXVsdC5jdXN0b21FbGVtZW50cy5nZXQoXCJpbnB1dC1tYXNrXCIpKSB7XG4gICAgICAgICAgICB2YXIgSW5wdXRtYXNrRWxlbWVudCA9IGZ1bmN0aW9uKF9IVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIF9pbmhlcml0cyhJbnB1dG1hc2tFbGVtZW50LCBfSFRNTEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIHZhciBfc3VwZXIgPSBfY3JlYXRlU3VwZXIoSW5wdXRtYXNrRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5wdXRtYXNrRWxlbWVudCgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzO1xuICAgICAgICAgICAgICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgSW5wdXRtYXNrRWxlbWVudCksIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhdHRyaWJ1dGVOYW1lcyA9IF90aGlzLmdldEF0dHJpYnV0ZU5hbWVzKCksIHNoYWRvdyA9IF90aGlzLmF0dGFjaFNoYWRvdyh7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RlOiBcImNsb3NlZFwiXG4gICAgICAgICAgICAgICAgICAgIH0pLCBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ciBpbiBpbnB1dC50eXBlID0gXCJ0ZXh0XCIsIHNoYWRvdy5hcHBlbmRDaGlsZChpbnB1dCksIGF0dHJpYnV0ZU5hbWVzKSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYXR0cmlidXRlTmFtZXMsIGF0dHIpICYmIGlucHV0LnNldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lc1thdHRyXSwgX3RoaXMuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWVzW2F0dHJdKSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbSA9IG5ldyBfaW5wdXRtYXNrLmRlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGltLmRhdGFBdHRyaWJ1dGUgPSBcIlwiLCBpbS5tYXNrKGlucHV0KSwgaW5wdXQuaW5wdXRtYXNrLnNoYWRvd1Jvb3QgPSBzaGFkb3csIFxuICAgICAgICAgICAgICAgICAgICBfdGhpcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIElucHV0bWFza0VsZW1lbnQ7XG4gICAgICAgICAgICB9KF93cmFwTmF0aXZlU3VwZXIoSFRNTEVsZW1lbnQpKTtcbiAgICAgICAgICAgIF93aW5kb3cuZGVmYXVsdC5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJpbnB1dC1tYXNrXCIsIElucHV0bWFza0VsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICB2YXIgX2pxdWVyeSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXyg4KSksIF9pbnB1dG1hc2sgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMSkpO1xuICAgICAgICBmdW5jdGlvbiBfdHlwZW9mKG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIF90eXBlb2YgPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBcInN5bWJvbFwiID09IHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPyBmdW5jdGlvbiBfdHlwZW9mKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2Ygb2JqO1xuICAgICAgICAgICAgfSA6IGZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICAgICAgICAgIH0sIF90eXBlb2Yob2JqKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiBvYmpcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgdm9pZCAwID09PSBfanF1ZXJ5LmRlZmF1bHQuZm4uaW5wdXRtYXNrICYmIChfanF1ZXJ5LmRlZmF1bHQuZm4uaW5wdXRtYXNrID0gZnVuY3Rpb24oZm4sIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHZhciBucHRtYXNrLCBpbnB1dCA9IHRoaXNbMF07XG4gICAgICAgICAgICBpZiAodm9pZCAwID09PSBvcHRpb25zICYmIChvcHRpb25zID0ge30pLCBcInN0cmluZ1wiID09IHR5cGVvZiBmbikgc3dpdGNoIChmbikge1xuICAgICAgICAgICAgICBjYXNlIFwidW5tYXNrZWR2YWx1ZVwiOlxuICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dCAmJiBpbnB1dC5pbnB1dG1hc2sgPyBpbnB1dC5pbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpIDogKDAsIF9qcXVlcnkuZGVmYXVsdCkoaW5wdXQpLnZhbCgpO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJyZW1vdmVcIjpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0bWFzayAmJiB0aGlzLmlucHV0bWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBjYXNlIFwiZ2V0ZW1wdHltYXNrXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0ICYmIGlucHV0LmlucHV0bWFzayA/IGlucHV0LmlucHV0bWFzay5nZXRlbXB0eW1hc2soKSA6IFwiXCI7XG5cbiAgICAgICAgICAgICAgY2FzZSBcImhhc01hc2tlZFZhbHVlXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuICEoIWlucHV0IHx8ICFpbnB1dC5pbnB1dG1hc2spICYmIGlucHV0LmlucHV0bWFzay5oYXNNYXNrZWRWYWx1ZSgpO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJpc0NvbXBsZXRlXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuICFpbnB1dCB8fCAhaW5wdXQuaW5wdXRtYXNrIHx8IGlucHV0LmlucHV0bWFzay5pc0NvbXBsZXRlKCk7XG5cbiAgICAgICAgICAgICAgY2FzZSBcImdldG1ldGFkYXRhXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0ICYmIGlucHV0LmlucHV0bWFzayA/IGlucHV0LmlucHV0bWFzay5nZXRtZXRhZGF0YSgpIDogdm9pZCAwO1xuXG4gICAgICAgICAgICAgIGNhc2UgXCJzZXR2YWx1ZVwiOlxuICAgICAgICAgICAgICAgIF9pbnB1dG1hc2suZGVmYXVsdC5zZXRWYWx1ZShpbnB1dCwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgY2FzZSBcIm9wdGlvblwiOlxuICAgICAgICAgICAgICAgIGlmIChcInN0cmluZ1wiICE9IHR5cGVvZiBvcHRpb25zKSByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodm9pZCAwICE9PSB0aGlzLmlucHV0bWFzaykgcmV0dXJuIHRoaXMuaW5wdXRtYXNrLm9wdGlvbihvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQgJiYgdm9pZCAwICE9PSBpbnB1dC5pbnB1dG1hc2spIHJldHVybiBpbnB1dC5pbnB1dG1hc2sub3B0aW9uKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMuYWxpYXMgPSBmbiwgbnB0bWFzayA9IG5ldyBfaW5wdXRtYXNrLmRlZmF1bHQob3B0aW9ucyksIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgbnB0bWFzay5tYXNrKHRoaXMpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShmbikpIHJldHVybiBvcHRpb25zLmFsaWFzID0gZm4sIG5wdG1hc2sgPSBuZXcgX2lucHV0bWFzay5kZWZhdWx0KG9wdGlvbnMpLCBcbiAgICAgICAgICAgICAgICB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIG5wdG1hc2subWFzayh0aGlzKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoXCJvYmplY3RcIiA9PSBfdHlwZW9mKGZuKSkgcmV0dXJuIG5wdG1hc2sgPSBuZXcgX2lucHV0bWFzay5kZWZhdWx0KGZuKSwgdm9pZCAwID09PSBmbi5tYXNrICYmIHZvaWQgMCA9PT0gZm4uYWxpYXMgPyB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2b2lkIDAgIT09IHRoaXMuaW5wdXRtYXNrKSByZXR1cm4gdGhpcy5pbnB1dG1hc2sub3B0aW9uKGZuKTtcbiAgICAgICAgICAgICAgICAgICAgbnB0bWFzay5tYXNrKHRoaXMpO1xuICAgICAgICAgICAgICAgIH0pIDogdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBucHRtYXNrLm1hc2sodGhpcyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gZm4pIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIG5wdG1hc2sgPSBuZXcgX2lucHV0bWFzay5kZWZhdWx0KG9wdGlvbnMpLCBucHRtYXNrLm1hc2sodGhpcyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gICAgICAgICAgICB2YWx1ZTogITBcbiAgICAgICAgfSksIGV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcbiAgICAgICAgdmFyIF9idW5kbGUgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9fd2VicGFja19yZXF1aXJlX18oMTUpKTtcbiAgICAgICAgZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHtcbiAgICAgICAgICAgIHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDogb2JqXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIF9fd2VicGFja19yZXF1aXJlX18oMjMpO1xuICAgICAgICB2YXIgX2RlZmF1bHQgPSBfYnVuZGxlLmRlZmF1bHQ7XG4gICAgICAgIGV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0O1xuICAgIH0gXSwgaW5zdGFsbGVkTW9kdWxlcyA9IHt9LCBfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzLCBfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzLCBcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiAgICAgICAgX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpIHx8IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gICAgICAgICAgICBlbnVtZXJhYmxlOiAhMCxcbiAgICAgICAgICAgIGdldDogZ2V0dGVyXG4gICAgICAgIH0pO1xuICAgIH0sIF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiAgICAgICAgXCJ1bmRlZmluZWRcIiAhPSB0eXBlb2YgU3ltYm9sICYmIFN5bWJvbC50b1N0cmluZ1RhZyAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7XG4gICAgICAgICAgICB2YWx1ZTogXCJNb2R1bGVcIlxuICAgICAgICB9KSwgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gICAgICAgICAgICB2YWx1ZTogITBcbiAgICAgICAgfSk7XG4gICAgfSwgX193ZWJwYWNrX3JlcXVpcmVfXy50ID0gZnVuY3Rpb24odmFsdWUsIG1vZGUpIHtcbiAgICAgICAgaWYgKDEgJiBtb2RlICYmICh2YWx1ZSA9IF9fd2VicGFja19yZXF1aXJlX18odmFsdWUpKSwgOCAmIG1vZGUpIHJldHVybiB2YWx1ZTtcbiAgICAgICAgaWYgKDQgJiBtb2RlICYmIFwib2JqZWN0XCIgPT0gdHlwZW9mIHZhbHVlICYmIHZhbHVlICYmIHZhbHVlLl9fZXNNb2R1bGUpIHJldHVybiB2YWx1ZTtcbiAgICAgICAgdmFyIG5zID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgaWYgKF9fd2VicGFja19yZXF1aXJlX18ucihucyksIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShucywgXCJkZWZhdWx0XCIsIHtcbiAgICAgICAgICAgIGVudW1lcmFibGU6ICEwLFxuICAgICAgICAgICAgdmFsdWU6IHZhbHVlXG4gICAgICAgIH0pLCAyICYgbW9kZSAmJiBcInN0cmluZ1wiICE9IHR5cGVvZiB2YWx1ZSkgZm9yICh2YXIga2V5IGluIHZhbHVlKSBfX3dlYnBhY2tfcmVxdWlyZV9fLmQobnMsIGtleSwgZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWVba2V5XTtcbiAgICAgICAgfS5iaW5kKG51bGwsIGtleSkpO1xuICAgICAgICByZXR1cm4gbnM7XG4gICAgfSwgX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gICAgICAgIHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgPyBmdW5jdGlvbiBnZXREZWZhdWx0KCkge1xuICAgICAgICAgICAgcmV0dXJuIG1vZHVsZS5kZWZhdWx0O1xuICAgICAgICB9IDogZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHtcbiAgICAgICAgICAgIHJldHVybiBtb2R1bGU7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCBcImFcIiwgZ2V0dGVyKSwgZ2V0dGVyO1xuICAgIH0sIF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTtcbiAgICB9LCBfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiLCBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IDI0KTtcbiAgICBmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG4gICAgICAgIGlmIChpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkgcmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gICAgICAgIHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiAgICAgICAgICAgIGk6IG1vZHVsZUlkLFxuICAgICAgICAgICAgbDogITEsXG4gICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gbW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyksIFxuICAgICAgICBtb2R1bGUubCA9ICEwLCBtb2R1bGUuZXhwb3J0cztcbiAgICB9XG4gICAgdmFyIG1vZHVsZXMsIGluc3RhbGxlZE1vZHVsZXM7XG59KTsiLCIoIGZ1bmN0aW9uKCBmYWN0b3J5ICkge1xuXHRpZiAoIHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICkge1xuXG5cdFx0Ly8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxuXHRcdGRlZmluZSggWyBcImpxdWVyeVwiIF0sIGZhY3RvcnkgKTtcblx0fSBlbHNlIHtcblxuXHRcdC8vIEJyb3dzZXIgZ2xvYmFsc1xuXHRcdGZhY3RvcnkoIGpRdWVyeSApO1xuXHR9XG59ICggZnVuY3Rpb24oICQgKSB7XG5cbiQudWkgPSAkLnVpIHx8IHt9O1xuXG5yZXR1cm4gJC51aS52ZXJzaW9uID0gXCIxLjEyLjFcIjtcblxufSApICk7XG4iLCIvKiFcbiAqIGpRdWVyeSBVSSBQb3NpdGlvbiAxLjEyLjFcbiAqIGh0dHA6Ly9qcXVlcnl1aS5jb21cbiAqXG4gKiBDb3B5cmlnaHQgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLlxuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIGh0dHA6Ly9hcGkuanF1ZXJ5dWkuY29tL3Bvc2l0aW9uL1xuICovXG5cbi8vPj5sYWJlbDogUG9zaXRpb25cbi8vPj5ncm91cDogQ29yZVxuLy8+PmRlc2NyaXB0aW9uOiBQb3NpdGlvbnMgZWxlbWVudHMgcmVsYXRpdmUgdG8gb3RoZXIgZWxlbWVudHMuXG4vLz4+ZG9jczogaHR0cDovL2FwaS5qcXVlcnl1aS5jb20vcG9zaXRpb24vXG4vLz4+ZGVtb3M6IGh0dHA6Ly9qcXVlcnl1aS5jb20vcG9zaXRpb24vXG5cbiggZnVuY3Rpb24oIGZhY3RvcnkgKSB7XG5cdGlmICggdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQgKSB7XG5cblx0XHQvLyBBTUQuIFJlZ2lzdGVyIGFzIGFuIGFub255bW91cyBtb2R1bGUuXG5cdFx0ZGVmaW5lKCBbIFwianF1ZXJ5XCIsIFwiLi92ZXJzaW9uXCIgXSwgZmFjdG9yeSApO1xuXHR9IGVsc2Uge1xuXG5cdFx0Ly8gQnJvd3NlciBnbG9iYWxzXG5cdFx0ZmFjdG9yeSggalF1ZXJ5ICk7XG5cdH1cbn0oIGZ1bmN0aW9uKCAkICkge1xuKCBmdW5jdGlvbigpIHtcbnZhciBjYWNoZWRTY3JvbGxiYXJXaWR0aCxcblx0bWF4ID0gTWF0aC5tYXgsXG5cdGFicyA9IE1hdGguYWJzLFxuXHRyaG9yaXpvbnRhbCA9IC9sZWZ0fGNlbnRlcnxyaWdodC8sXG5cdHJ2ZXJ0aWNhbCA9IC90b3B8Y2VudGVyfGJvdHRvbS8sXG5cdHJvZmZzZXQgPSAvW1xcK1xcLV1cXGQrKFxcLltcXGRdKyk/JT8vLFxuXHRycG9zaXRpb24gPSAvXlxcdysvLFxuXHRycGVyY2VudCA9IC8lJC8sXG5cdF9wb3NpdGlvbiA9ICQuZm4ucG9zaXRpb247XG5cbmZ1bmN0aW9uIGdldE9mZnNldHMoIG9mZnNldHMsIHdpZHRoLCBoZWlnaHQgKSB7XG5cdHJldHVybiBbXG5cdFx0cGFyc2VGbG9hdCggb2Zmc2V0c1sgMCBdICkgKiAoIHJwZXJjZW50LnRlc3QoIG9mZnNldHNbIDAgXSApID8gd2lkdGggLyAxMDAgOiAxICksXG5cdFx0cGFyc2VGbG9hdCggb2Zmc2V0c1sgMSBdICkgKiAoIHJwZXJjZW50LnRlc3QoIG9mZnNldHNbIDEgXSApID8gaGVpZ2h0IC8gMTAwIDogMSApXG5cdF07XG59XG5cbmZ1bmN0aW9uIHBhcnNlQ3NzKCBlbGVtZW50LCBwcm9wZXJ0eSApIHtcblx0cmV0dXJuIHBhcnNlSW50KCAkLmNzcyggZWxlbWVudCwgcHJvcGVydHkgKSwgMTAgKSB8fCAwO1xufVxuXG5mdW5jdGlvbiBnZXREaW1lbnNpb25zKCBlbGVtICkge1xuXHR2YXIgcmF3ID0gZWxlbVsgMCBdO1xuXHRpZiAoIHJhdy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0d2lkdGg6IGVsZW0ud2lkdGgoKSxcblx0XHRcdGhlaWdodDogZWxlbS5oZWlnaHQoKSxcblx0XHRcdG9mZnNldDogeyB0b3A6IDAsIGxlZnQ6IDAgfVxuXHRcdH07XG5cdH1cblx0aWYgKCAkLmlzV2luZG93KCByYXcgKSApIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0d2lkdGg6IGVsZW0ud2lkdGgoKSxcblx0XHRcdGhlaWdodDogZWxlbS5oZWlnaHQoKSxcblx0XHRcdG9mZnNldDogeyB0b3A6IGVsZW0uc2Nyb2xsVG9wKCksIGxlZnQ6IGVsZW0uc2Nyb2xsTGVmdCgpIH1cblx0XHR9O1xuXHR9XG5cdGlmICggcmF3LnByZXZlbnREZWZhdWx0ICkge1xuXHRcdHJldHVybiB7XG5cdFx0XHR3aWR0aDogMCxcblx0XHRcdGhlaWdodDogMCxcblx0XHRcdG9mZnNldDogeyB0b3A6IHJhdy5wYWdlWSwgbGVmdDogcmF3LnBhZ2VYIH1cblx0XHR9O1xuXHR9XG5cdHJldHVybiB7XG5cdFx0d2lkdGg6IGVsZW0ub3V0ZXJXaWR0aCgpLFxuXHRcdGhlaWdodDogZWxlbS5vdXRlckhlaWdodCgpLFxuXHRcdG9mZnNldDogZWxlbS5vZmZzZXQoKVxuXHR9O1xufVxuXG4kLnBvc2l0aW9uID0ge1xuXHRzY3JvbGxiYXJXaWR0aDogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCBjYWNoZWRTY3JvbGxiYXJXaWR0aCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuIGNhY2hlZFNjcm9sbGJhcldpZHRoO1xuXHRcdH1cblx0XHR2YXIgdzEsIHcyLFxuXHRcdFx0ZGl2ID0gJCggXCI8ZGl2IFwiICtcblx0XHRcdFx0XCJzdHlsZT0nZGlzcGxheTpibG9jaztwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDo1MHB4O2hlaWdodDo1MHB4O292ZXJmbG93OmhpZGRlbjsnPlwiICtcblx0XHRcdFx0XCI8ZGl2IHN0eWxlPSdoZWlnaHQ6MTAwcHg7d2lkdGg6YXV0bzsnPjwvZGl2PjwvZGl2PlwiICksXG5cdFx0XHRpbm5lckRpdiA9IGRpdi5jaGlsZHJlbigpWyAwIF07XG5cblx0XHQkKCBcImJvZHlcIiApLmFwcGVuZCggZGl2ICk7XG5cdFx0dzEgPSBpbm5lckRpdi5vZmZzZXRXaWR0aDtcblx0XHRkaXYuY3NzKCBcIm92ZXJmbG93XCIsIFwic2Nyb2xsXCIgKTtcblxuXHRcdHcyID0gaW5uZXJEaXYub2Zmc2V0V2lkdGg7XG5cblx0XHRpZiAoIHcxID09PSB3MiApIHtcblx0XHRcdHcyID0gZGl2WyAwIF0uY2xpZW50V2lkdGg7XG5cdFx0fVxuXG5cdFx0ZGl2LnJlbW92ZSgpO1xuXG5cdFx0cmV0dXJuICggY2FjaGVkU2Nyb2xsYmFyV2lkdGggPSB3MSAtIHcyICk7XG5cdH0sXG5cdGdldFNjcm9sbEluZm86IGZ1bmN0aW9uKCB3aXRoaW4gKSB7XG5cdFx0dmFyIG92ZXJmbG93WCA9IHdpdGhpbi5pc1dpbmRvdyB8fCB3aXRoaW4uaXNEb2N1bWVudCA/IFwiXCIgOlxuXHRcdFx0XHR3aXRoaW4uZWxlbWVudC5jc3MoIFwib3ZlcmZsb3cteFwiICksXG5cdFx0XHRvdmVyZmxvd1kgPSB3aXRoaW4uaXNXaW5kb3cgfHwgd2l0aGluLmlzRG9jdW1lbnQgPyBcIlwiIDpcblx0XHRcdFx0d2l0aGluLmVsZW1lbnQuY3NzKCBcIm92ZXJmbG93LXlcIiApLFxuXHRcdFx0aGFzT3ZlcmZsb3dYID0gb3ZlcmZsb3dYID09PSBcInNjcm9sbFwiIHx8XG5cdFx0XHRcdCggb3ZlcmZsb3dYID09PSBcImF1dG9cIiAmJiB3aXRoaW4ud2lkdGggPCB3aXRoaW4uZWxlbWVudFsgMCBdLnNjcm9sbFdpZHRoICksXG5cdFx0XHRoYXNPdmVyZmxvd1kgPSBvdmVyZmxvd1kgPT09IFwic2Nyb2xsXCIgfHxcblx0XHRcdFx0KCBvdmVyZmxvd1kgPT09IFwiYXV0b1wiICYmIHdpdGhpbi5oZWlnaHQgPCB3aXRoaW4uZWxlbWVudFsgMCBdLnNjcm9sbEhlaWdodCApO1xuXHRcdHJldHVybiB7XG5cdFx0XHR3aWR0aDogaGFzT3ZlcmZsb3dZID8gJC5wb3NpdGlvbi5zY3JvbGxiYXJXaWR0aCgpIDogMCxcblx0XHRcdGhlaWdodDogaGFzT3ZlcmZsb3dYID8gJC5wb3NpdGlvbi5zY3JvbGxiYXJXaWR0aCgpIDogMFxuXHRcdH07XG5cdH0sXG5cdGdldFdpdGhpbkluZm86IGZ1bmN0aW9uKCBlbGVtZW50ICkge1xuXHRcdHZhciB3aXRoaW5FbGVtZW50ID0gJCggZWxlbWVudCB8fCB3aW5kb3cgKSxcblx0XHRcdGlzV2luZG93ID0gJC5pc1dpbmRvdyggd2l0aGluRWxlbWVudFsgMCBdICksXG5cdFx0XHRpc0RvY3VtZW50ID0gISF3aXRoaW5FbGVtZW50WyAwIF0gJiYgd2l0aGluRWxlbWVudFsgMCBdLm5vZGVUeXBlID09PSA5LFxuXHRcdFx0aGFzT2Zmc2V0ID0gIWlzV2luZG93ICYmICFpc0RvY3VtZW50O1xuXHRcdHJldHVybiB7XG5cdFx0XHRlbGVtZW50OiB3aXRoaW5FbGVtZW50LFxuXHRcdFx0aXNXaW5kb3c6IGlzV2luZG93LFxuXHRcdFx0aXNEb2N1bWVudDogaXNEb2N1bWVudCxcblx0XHRcdG9mZnNldDogaGFzT2Zmc2V0ID8gJCggZWxlbWVudCApLm9mZnNldCgpIDogeyBsZWZ0OiAwLCB0b3A6IDAgfSxcblx0XHRcdHNjcm9sbExlZnQ6IHdpdGhpbkVsZW1lbnQuc2Nyb2xsTGVmdCgpLFxuXHRcdFx0c2Nyb2xsVG9wOiB3aXRoaW5FbGVtZW50LnNjcm9sbFRvcCgpLFxuXHRcdFx0d2lkdGg6IHdpdGhpbkVsZW1lbnQub3V0ZXJXaWR0aCgpLFxuXHRcdFx0aGVpZ2h0OiB3aXRoaW5FbGVtZW50Lm91dGVySGVpZ2h0KClcblx0XHR9O1xuXHR9XG59O1xuXG4kLmZuLnBvc2l0aW9uID0gZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cdGlmICggIW9wdGlvbnMgfHwgIW9wdGlvbnMub2YgKSB7XG5cdFx0cmV0dXJuIF9wb3NpdGlvbi5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdH1cblxuXHQvLyBNYWtlIGEgY29weSwgd2UgZG9uJ3Qgd2FudCB0byBtb2RpZnkgYXJndW1lbnRzXG5cdG9wdGlvbnMgPSAkLmV4dGVuZCgge30sIG9wdGlvbnMgKTtcblxuXHR2YXIgYXRPZmZzZXQsIHRhcmdldFdpZHRoLCB0YXJnZXRIZWlnaHQsIHRhcmdldE9mZnNldCwgYmFzZVBvc2l0aW9uLCBkaW1lbnNpb25zLFxuXHRcdHRhcmdldCA9ICQoIG9wdGlvbnMub2YgKSxcblx0XHR3aXRoaW4gPSAkLnBvc2l0aW9uLmdldFdpdGhpbkluZm8oIG9wdGlvbnMud2l0aGluICksXG5cdFx0c2Nyb2xsSW5mbyA9ICQucG9zaXRpb24uZ2V0U2Nyb2xsSW5mbyggd2l0aGluICksXG5cdFx0Y29sbGlzaW9uID0gKCBvcHRpb25zLmNvbGxpc2lvbiB8fCBcImZsaXBcIiApLnNwbGl0KCBcIiBcIiApLFxuXHRcdG9mZnNldHMgPSB7fTtcblxuXHRkaW1lbnNpb25zID0gZ2V0RGltZW5zaW9ucyggdGFyZ2V0ICk7XG5cdGlmICggdGFyZ2V0WyAwIF0ucHJldmVudERlZmF1bHQgKSB7XG5cblx0XHQvLyBGb3JjZSBsZWZ0IHRvcCB0byBhbGxvdyBmbGlwcGluZ1xuXHRcdG9wdGlvbnMuYXQgPSBcImxlZnQgdG9wXCI7XG5cdH1cblx0dGFyZ2V0V2lkdGggPSBkaW1lbnNpb25zLndpZHRoO1xuXHR0YXJnZXRIZWlnaHQgPSBkaW1lbnNpb25zLmhlaWdodDtcblx0dGFyZ2V0T2Zmc2V0ID0gZGltZW5zaW9ucy5vZmZzZXQ7XG5cblx0Ly8gQ2xvbmUgdG8gcmV1c2Ugb3JpZ2luYWwgdGFyZ2V0T2Zmc2V0IGxhdGVyXG5cdGJhc2VQb3NpdGlvbiA9ICQuZXh0ZW5kKCB7fSwgdGFyZ2V0T2Zmc2V0ICk7XG5cblx0Ly8gRm9yY2UgbXkgYW5kIGF0IHRvIGhhdmUgdmFsaWQgaG9yaXpvbnRhbCBhbmQgdmVydGljYWwgcG9zaXRpb25zXG5cdC8vIGlmIGEgdmFsdWUgaXMgbWlzc2luZyBvciBpbnZhbGlkLCBpdCB3aWxsIGJlIGNvbnZlcnRlZCB0byBjZW50ZXJcblx0JC5lYWNoKCBbIFwibXlcIiwgXCJhdFwiIF0sIGZ1bmN0aW9uKCkge1xuXHRcdHZhciBwb3MgPSAoIG9wdGlvbnNbIHRoaXMgXSB8fCBcIlwiICkuc3BsaXQoIFwiIFwiICksXG5cdFx0XHRob3Jpem9udGFsT2Zmc2V0LFxuXHRcdFx0dmVydGljYWxPZmZzZXQ7XG5cblx0XHRpZiAoIHBvcy5sZW5ndGggPT09IDEgKSB7XG5cdFx0XHRwb3MgPSByaG9yaXpvbnRhbC50ZXN0KCBwb3NbIDAgXSApID9cblx0XHRcdFx0cG9zLmNvbmNhdCggWyBcImNlbnRlclwiIF0gKSA6XG5cdFx0XHRcdHJ2ZXJ0aWNhbC50ZXN0KCBwb3NbIDAgXSApID9cblx0XHRcdFx0XHRbIFwiY2VudGVyXCIgXS5jb25jYXQoIHBvcyApIDpcblx0XHRcdFx0XHRbIFwiY2VudGVyXCIsIFwiY2VudGVyXCIgXTtcblx0XHR9XG5cdFx0cG9zWyAwIF0gPSByaG9yaXpvbnRhbC50ZXN0KCBwb3NbIDAgXSApID8gcG9zWyAwIF0gOiBcImNlbnRlclwiO1xuXHRcdHBvc1sgMSBdID0gcnZlcnRpY2FsLnRlc3QoIHBvc1sgMSBdICkgPyBwb3NbIDEgXSA6IFwiY2VudGVyXCI7XG5cblx0XHQvLyBDYWxjdWxhdGUgb2Zmc2V0c1xuXHRcdGhvcml6b250YWxPZmZzZXQgPSByb2Zmc2V0LmV4ZWMoIHBvc1sgMCBdICk7XG5cdFx0dmVydGljYWxPZmZzZXQgPSByb2Zmc2V0LmV4ZWMoIHBvc1sgMSBdICk7XG5cdFx0b2Zmc2V0c1sgdGhpcyBdID0gW1xuXHRcdFx0aG9yaXpvbnRhbE9mZnNldCA/IGhvcml6b250YWxPZmZzZXRbIDAgXSA6IDAsXG5cdFx0XHR2ZXJ0aWNhbE9mZnNldCA/IHZlcnRpY2FsT2Zmc2V0WyAwIF0gOiAwXG5cdFx0XTtcblxuXHRcdC8vIFJlZHVjZSB0byBqdXN0IHRoZSBwb3NpdGlvbnMgd2l0aG91dCB0aGUgb2Zmc2V0c1xuXHRcdG9wdGlvbnNbIHRoaXMgXSA9IFtcblx0XHRcdHJwb3NpdGlvbi5leGVjKCBwb3NbIDAgXSApWyAwIF0sXG5cdFx0XHRycG9zaXRpb24uZXhlYyggcG9zWyAxIF0gKVsgMCBdXG5cdFx0XTtcblx0fSApO1xuXG5cdC8vIE5vcm1hbGl6ZSBjb2xsaXNpb24gb3B0aW9uXG5cdGlmICggY29sbGlzaW9uLmxlbmd0aCA9PT0gMSApIHtcblx0XHRjb2xsaXNpb25bIDEgXSA9IGNvbGxpc2lvblsgMCBdO1xuXHR9XG5cblx0aWYgKCBvcHRpb25zLmF0WyAwIF0gPT09IFwicmlnaHRcIiApIHtcblx0XHRiYXNlUG9zaXRpb24ubGVmdCArPSB0YXJnZXRXaWR0aDtcblx0fSBlbHNlIGlmICggb3B0aW9ucy5hdFsgMCBdID09PSBcImNlbnRlclwiICkge1xuXHRcdGJhc2VQb3NpdGlvbi5sZWZ0ICs9IHRhcmdldFdpZHRoIC8gMjtcblx0fVxuXG5cdGlmICggb3B0aW9ucy5hdFsgMSBdID09PSBcImJvdHRvbVwiICkge1xuXHRcdGJhc2VQb3NpdGlvbi50b3AgKz0gdGFyZ2V0SGVpZ2h0O1xuXHR9IGVsc2UgaWYgKCBvcHRpb25zLmF0WyAxIF0gPT09IFwiY2VudGVyXCIgKSB7XG5cdFx0YmFzZVBvc2l0aW9uLnRvcCArPSB0YXJnZXRIZWlnaHQgLyAyO1xuXHR9XG5cblx0YXRPZmZzZXQgPSBnZXRPZmZzZXRzKCBvZmZzZXRzLmF0LCB0YXJnZXRXaWR0aCwgdGFyZ2V0SGVpZ2h0ICk7XG5cdGJhc2VQb3NpdGlvbi5sZWZ0ICs9IGF0T2Zmc2V0WyAwIF07XG5cdGJhc2VQb3NpdGlvbi50b3AgKz0gYXRPZmZzZXRbIDEgXTtcblxuXHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHR2YXIgY29sbGlzaW9uUG9zaXRpb24sIHVzaW5nLFxuXHRcdFx0ZWxlbSA9ICQoIHRoaXMgKSxcblx0XHRcdGVsZW1XaWR0aCA9IGVsZW0ub3V0ZXJXaWR0aCgpLFxuXHRcdFx0ZWxlbUhlaWdodCA9IGVsZW0ub3V0ZXJIZWlnaHQoKSxcblx0XHRcdG1hcmdpbkxlZnQgPSBwYXJzZUNzcyggdGhpcywgXCJtYXJnaW5MZWZ0XCIgKSxcblx0XHRcdG1hcmdpblRvcCA9IHBhcnNlQ3NzKCB0aGlzLCBcIm1hcmdpblRvcFwiICksXG5cdFx0XHRjb2xsaXNpb25XaWR0aCA9IGVsZW1XaWR0aCArIG1hcmdpbkxlZnQgKyBwYXJzZUNzcyggdGhpcywgXCJtYXJnaW5SaWdodFwiICkgK1xuXHRcdFx0XHRzY3JvbGxJbmZvLndpZHRoLFxuXHRcdFx0Y29sbGlzaW9uSGVpZ2h0ID0gZWxlbUhlaWdodCArIG1hcmdpblRvcCArIHBhcnNlQ3NzKCB0aGlzLCBcIm1hcmdpbkJvdHRvbVwiICkgK1xuXHRcdFx0XHRzY3JvbGxJbmZvLmhlaWdodCxcblx0XHRcdHBvc2l0aW9uID0gJC5leHRlbmQoIHt9LCBiYXNlUG9zaXRpb24gKSxcblx0XHRcdG15T2Zmc2V0ID0gZ2V0T2Zmc2V0cyggb2Zmc2V0cy5teSwgZWxlbS5vdXRlcldpZHRoKCksIGVsZW0ub3V0ZXJIZWlnaHQoKSApO1xuXG5cdFx0aWYgKCBvcHRpb25zLm15WyAwIF0gPT09IFwicmlnaHRcIiApIHtcblx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gZWxlbVdpZHRoO1xuXHRcdH0gZWxzZSBpZiAoIG9wdGlvbnMubXlbIDAgXSA9PT0gXCJjZW50ZXJcIiApIHtcblx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gZWxlbVdpZHRoIC8gMjtcblx0XHR9XG5cblx0XHRpZiAoIG9wdGlvbnMubXlbIDEgXSA9PT0gXCJib3R0b21cIiApIHtcblx0XHRcdHBvc2l0aW9uLnRvcCAtPSBlbGVtSGVpZ2h0O1xuXHRcdH0gZWxzZSBpZiAoIG9wdGlvbnMubXlbIDEgXSA9PT0gXCJjZW50ZXJcIiApIHtcblx0XHRcdHBvc2l0aW9uLnRvcCAtPSBlbGVtSGVpZ2h0IC8gMjtcblx0XHR9XG5cblx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0WyAwIF07XG5cdFx0cG9zaXRpb24udG9wICs9IG15T2Zmc2V0WyAxIF07XG5cblx0XHRjb2xsaXNpb25Qb3NpdGlvbiA9IHtcblx0XHRcdG1hcmdpbkxlZnQ6IG1hcmdpbkxlZnQsXG5cdFx0XHRtYXJnaW5Ub3A6IG1hcmdpblRvcFxuXHRcdH07XG5cblx0XHQkLmVhY2goIFsgXCJsZWZ0XCIsIFwidG9wXCIgXSwgZnVuY3Rpb24oIGksIGRpciApIHtcblx0XHRcdGlmICggJC51aS5wb3NpdGlvblsgY29sbGlzaW9uWyBpIF0gXSApIHtcblx0XHRcdFx0JC51aS5wb3NpdGlvblsgY29sbGlzaW9uWyBpIF0gXVsgZGlyIF0oIHBvc2l0aW9uLCB7XG5cdFx0XHRcdFx0dGFyZ2V0V2lkdGg6IHRhcmdldFdpZHRoLFxuXHRcdFx0XHRcdHRhcmdldEhlaWdodDogdGFyZ2V0SGVpZ2h0LFxuXHRcdFx0XHRcdGVsZW1XaWR0aDogZWxlbVdpZHRoLFxuXHRcdFx0XHRcdGVsZW1IZWlnaHQ6IGVsZW1IZWlnaHQsXG5cdFx0XHRcdFx0Y29sbGlzaW9uUG9zaXRpb246IGNvbGxpc2lvblBvc2l0aW9uLFxuXHRcdFx0XHRcdGNvbGxpc2lvbldpZHRoOiBjb2xsaXNpb25XaWR0aCxcblx0XHRcdFx0XHRjb2xsaXNpb25IZWlnaHQ6IGNvbGxpc2lvbkhlaWdodCxcblx0XHRcdFx0XHRvZmZzZXQ6IFsgYXRPZmZzZXRbIDAgXSArIG15T2Zmc2V0WyAwIF0sIGF0T2Zmc2V0IFsgMSBdICsgbXlPZmZzZXRbIDEgXSBdLFxuXHRcdFx0XHRcdG15OiBvcHRpb25zLm15LFxuXHRcdFx0XHRcdGF0OiBvcHRpb25zLmF0LFxuXHRcdFx0XHRcdHdpdGhpbjogd2l0aGluLFxuXHRcdFx0XHRcdGVsZW06IGVsZW1cblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblxuXHRcdGlmICggb3B0aW9ucy51c2luZyApIHtcblxuXHRcdFx0Ly8gQWRkcyBmZWVkYmFjayBhcyBzZWNvbmQgYXJndW1lbnQgdG8gdXNpbmcgY2FsbGJhY2ssIGlmIHByZXNlbnRcblx0XHRcdHVzaW5nID0gZnVuY3Rpb24oIHByb3BzICkge1xuXHRcdFx0XHR2YXIgbGVmdCA9IHRhcmdldE9mZnNldC5sZWZ0IC0gcG9zaXRpb24ubGVmdCxcblx0XHRcdFx0XHRyaWdodCA9IGxlZnQgKyB0YXJnZXRXaWR0aCAtIGVsZW1XaWR0aCxcblx0XHRcdFx0XHR0b3AgPSB0YXJnZXRPZmZzZXQudG9wIC0gcG9zaXRpb24udG9wLFxuXHRcdFx0XHRcdGJvdHRvbSA9IHRvcCArIHRhcmdldEhlaWdodCAtIGVsZW1IZWlnaHQsXG5cdFx0XHRcdFx0ZmVlZGJhY2sgPSB7XG5cdFx0XHRcdFx0XHR0YXJnZXQ6IHtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudDogdGFyZ2V0LFxuXHRcdFx0XHRcdFx0XHRsZWZ0OiB0YXJnZXRPZmZzZXQubGVmdCxcblx0XHRcdFx0XHRcdFx0dG9wOiB0YXJnZXRPZmZzZXQudG9wLFxuXHRcdFx0XHRcdFx0XHR3aWR0aDogdGFyZ2V0V2lkdGgsXG5cdFx0XHRcdFx0XHRcdGhlaWdodDogdGFyZ2V0SGVpZ2h0XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0ZWxlbWVudDoge1xuXHRcdFx0XHRcdFx0XHRlbGVtZW50OiBlbGVtLFxuXHRcdFx0XHRcdFx0XHRsZWZ0OiBwb3NpdGlvbi5sZWZ0LFxuXHRcdFx0XHRcdFx0XHR0b3A6IHBvc2l0aW9uLnRvcCxcblx0XHRcdFx0XHRcdFx0d2lkdGg6IGVsZW1XaWR0aCxcblx0XHRcdFx0XHRcdFx0aGVpZ2h0OiBlbGVtSGVpZ2h0XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0aG9yaXpvbnRhbDogcmlnaHQgPCAwID8gXCJsZWZ0XCIgOiBsZWZ0ID4gMCA/IFwicmlnaHRcIiA6IFwiY2VudGVyXCIsXG5cdFx0XHRcdFx0XHR2ZXJ0aWNhbDogYm90dG9tIDwgMCA/IFwidG9wXCIgOiB0b3AgPiAwID8gXCJib3R0b21cIiA6IFwibWlkZGxlXCJcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRpZiAoIHRhcmdldFdpZHRoIDwgZWxlbVdpZHRoICYmIGFicyggbGVmdCArIHJpZ2h0ICkgPCB0YXJnZXRXaWR0aCApIHtcblx0XHRcdFx0XHRmZWVkYmFjay5ob3Jpem9udGFsID0gXCJjZW50ZXJcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIHRhcmdldEhlaWdodCA8IGVsZW1IZWlnaHQgJiYgYWJzKCB0b3AgKyBib3R0b20gKSA8IHRhcmdldEhlaWdodCApIHtcblx0XHRcdFx0XHRmZWVkYmFjay52ZXJ0aWNhbCA9IFwibWlkZGxlXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBtYXgoIGFicyggbGVmdCApLCBhYnMoIHJpZ2h0ICkgKSA+IG1heCggYWJzKCB0b3AgKSwgYWJzKCBib3R0b20gKSApICkge1xuXHRcdFx0XHRcdGZlZWRiYWNrLmltcG9ydGFudCA9IFwiaG9yaXpvbnRhbFwiO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGZlZWRiYWNrLmltcG9ydGFudCA9IFwidmVydGljYWxcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRvcHRpb25zLnVzaW5nLmNhbGwoIHRoaXMsIHByb3BzLCBmZWVkYmFjayApO1xuXHRcdFx0fTtcblx0XHR9XG5cblx0XHRlbGVtLm9mZnNldCggJC5leHRlbmQoIHBvc2l0aW9uLCB7IHVzaW5nOiB1c2luZyB9ICkgKTtcblx0fSApO1xufTtcblxuJC51aS5wb3NpdGlvbiA9IHtcblx0Zml0OiB7XG5cdFx0bGVmdDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsTGVmdCA6IHdpdGhpbi5vZmZzZXQubGVmdCxcblx0XHRcdFx0b3V0ZXJXaWR0aCA9IHdpdGhpbi53aWR0aCxcblx0XHRcdFx0Y29sbGlzaW9uUG9zTGVmdCA9IHBvc2l0aW9uLmxlZnQgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpbkxlZnQsXG5cdFx0XHRcdG92ZXJMZWZ0ID0gd2l0aGluT2Zmc2V0IC0gY29sbGlzaW9uUG9zTGVmdCxcblx0XHRcdFx0b3ZlclJpZ2h0ID0gY29sbGlzaW9uUG9zTGVmdCArIGRhdGEuY29sbGlzaW9uV2lkdGggLSBvdXRlcldpZHRoIC0gd2l0aGluT2Zmc2V0LFxuXHRcdFx0XHRuZXdPdmVyUmlnaHQ7XG5cblx0XHRcdC8vIEVsZW1lbnQgaXMgd2lkZXIgdGhhbiB3aXRoaW5cblx0XHRcdGlmICggZGF0YS5jb2xsaXNpb25XaWR0aCA+IG91dGVyV2lkdGggKSB7XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciB0aGUgbGVmdCBzaWRlIG9mIHdpdGhpblxuXHRcdFx0XHRpZiAoIG92ZXJMZWZ0ID4gMCAmJiBvdmVyUmlnaHQgPD0gMCApIHtcblx0XHRcdFx0XHRuZXdPdmVyUmlnaHQgPSBwb3NpdGlvbi5sZWZ0ICsgb3ZlckxlZnQgKyBkYXRhLmNvbGxpc2lvbldpZHRoIC0gb3V0ZXJXaWR0aCAtXG5cdFx0XHRcdFx0XHR3aXRoaW5PZmZzZXQ7XG5cdFx0XHRcdFx0cG9zaXRpb24ubGVmdCArPSBvdmVyTGVmdCAtIG5ld092ZXJSaWdodDtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIHJpZ2h0IHNpZGUgb2Ygd2l0aGluXG5cdFx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgJiYgb3ZlckxlZnQgPD0gMCApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ID0gd2l0aGluT2Zmc2V0O1xuXG5cdFx0XHRcdC8vIEVsZW1lbnQgaXMgaW5pdGlhbGx5IG92ZXIgYm90aCBsZWZ0IGFuZCByaWdodCBzaWRlcyBvZiB3aXRoaW5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpZiAoIG92ZXJMZWZ0ID4gb3ZlclJpZ2h0ICkge1xuXHRcdFx0XHRcdFx0cG9zaXRpb24ubGVmdCA9IHdpdGhpbk9mZnNldCArIG91dGVyV2lkdGggLSBkYXRhLmNvbGxpc2lvbldpZHRoO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ID0gd2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBUb28gZmFyIGxlZnQgLT4gYWxpZ24gd2l0aCBsZWZ0IGVkZ2Vcblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJMZWZ0ID4gMCApIHtcblx0XHRcdFx0cG9zaXRpb24ubGVmdCArPSBvdmVyTGVmdDtcblxuXHRcdFx0Ly8gVG9vIGZhciByaWdodCAtPiBhbGlnbiB3aXRoIHJpZ2h0IGVkZ2Vcblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gb3ZlclJpZ2h0O1xuXG5cdFx0XHQvLyBBZGp1c3QgYmFzZWQgb24gcG9zaXRpb24gYW5kIG1hcmdpblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cG9zaXRpb24ubGVmdCA9IG1heCggcG9zaXRpb24ubGVmdCAtIGNvbGxpc2lvblBvc0xlZnQsIHBvc2l0aW9uLmxlZnQgKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdHRvcDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsVG9wIDogd2l0aGluLm9mZnNldC50b3AsXG5cdFx0XHRcdG91dGVySGVpZ2h0ID0gZGF0YS53aXRoaW4uaGVpZ2h0LFxuXHRcdFx0XHRjb2xsaXNpb25Qb3NUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCxcblx0XHRcdFx0b3ZlclRvcCA9IHdpdGhpbk9mZnNldCAtIGNvbGxpc2lvblBvc1RvcCxcblx0XHRcdFx0b3ZlckJvdHRvbSA9IGNvbGxpc2lvblBvc1RvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLSB3aXRoaW5PZmZzZXQsXG5cdFx0XHRcdG5ld092ZXJCb3R0b207XG5cblx0XHRcdC8vIEVsZW1lbnQgaXMgdGFsbGVyIHRoYW4gd2l0aGluXG5cdFx0XHRpZiAoIGRhdGEuY29sbGlzaW9uSGVpZ2h0ID4gb3V0ZXJIZWlnaHQgKSB7XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciB0aGUgdG9wIG9mIHdpdGhpblxuXHRcdFx0XHRpZiAoIG92ZXJUb3AgPiAwICYmIG92ZXJCb3R0b20gPD0gMCApIHtcblx0XHRcdFx0XHRuZXdPdmVyQm90dG9tID0gcG9zaXRpb24udG9wICsgb3ZlclRvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLVxuXHRcdFx0XHRcdFx0d2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRcdHBvc2l0aW9uLnRvcCArPSBvdmVyVG9wIC0gbmV3T3ZlckJvdHRvbTtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIGJvdHRvbSBvZiB3aXRoaW5cblx0XHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgJiYgb3ZlclRvcCA8PSAwICkge1xuXHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldDtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIGJvdGggdG9wIGFuZCBib3R0b20gb2Ygd2l0aGluXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aWYgKCBvdmVyVG9wID4gb3ZlckJvdHRvbSApIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldCArIG91dGVySGVpZ2h0IC0gZGF0YS5jb2xsaXNpb25IZWlnaHQ7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gVG9vIGZhciB1cCAtPiBhbGlnbiB3aXRoIHRvcFxuXHRcdFx0fSBlbHNlIGlmICggb3ZlclRvcCA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLnRvcCArPSBvdmVyVG9wO1xuXG5cdFx0XHQvLyBUb28gZmFyIGRvd24gLT4gYWxpZ24gd2l0aCBib3R0b20gZWRnZVxuXHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLnRvcCAtPSBvdmVyQm90dG9tO1xuXG5cdFx0XHQvLyBBZGp1c3QgYmFzZWQgb24gcG9zaXRpb24gYW5kIG1hcmdpblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cG9zaXRpb24udG9wID0gbWF4KCBwb3NpdGlvbi50b3AgLSBjb2xsaXNpb25Qb3NUb3AsIHBvc2l0aW9uLnRvcCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0ZmxpcDoge1xuXHRcdGxlZnQ6IGZ1bmN0aW9uKCBwb3NpdGlvbiwgZGF0YSApIHtcblx0XHRcdHZhciB3aXRoaW4gPSBkYXRhLndpdGhpbixcblx0XHRcdFx0d2l0aGluT2Zmc2V0ID0gd2l0aGluLm9mZnNldC5sZWZ0ICsgd2l0aGluLnNjcm9sbExlZnQsXG5cdFx0XHRcdG91dGVyV2lkdGggPSB3aXRoaW4ud2lkdGgsXG5cdFx0XHRcdG9mZnNldExlZnQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsTGVmdCA6IHdpdGhpbi5vZmZzZXQubGVmdCxcblx0XHRcdFx0Y29sbGlzaW9uUG9zTGVmdCA9IHBvc2l0aW9uLmxlZnQgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpbkxlZnQsXG5cdFx0XHRcdG92ZXJMZWZ0ID0gY29sbGlzaW9uUG9zTGVmdCAtIG9mZnNldExlZnQsXG5cdFx0XHRcdG92ZXJSaWdodCA9IGNvbGxpc2lvblBvc0xlZnQgKyBkYXRhLmNvbGxpc2lvbldpZHRoIC0gb3V0ZXJXaWR0aCAtIG9mZnNldExlZnQsXG5cdFx0XHRcdG15T2Zmc2V0ID0gZGF0YS5teVsgMCBdID09PSBcImxlZnRcIiA/XG5cdFx0XHRcdFx0LWRhdGEuZWxlbVdpZHRoIDpcblx0XHRcdFx0XHRkYXRhLm15WyAwIF0gPT09IFwicmlnaHRcIiA/XG5cdFx0XHRcdFx0XHRkYXRhLmVsZW1XaWR0aCA6XG5cdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRhdE9mZnNldCA9IGRhdGEuYXRbIDAgXSA9PT0gXCJsZWZ0XCIgP1xuXHRcdFx0XHRcdGRhdGEudGFyZ2V0V2lkdGggOlxuXHRcdFx0XHRcdGRhdGEuYXRbIDAgXSA9PT0gXCJyaWdodFwiID9cblx0XHRcdFx0XHRcdC1kYXRhLnRhcmdldFdpZHRoIDpcblx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdG9mZnNldCA9IC0yICogZGF0YS5vZmZzZXRbIDAgXSxcblx0XHRcdFx0bmV3T3ZlclJpZ2h0LFxuXHRcdFx0XHRuZXdPdmVyTGVmdDtcblxuXHRcdFx0aWYgKCBvdmVyTGVmdCA8IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJSaWdodCA9IHBvc2l0aW9uLmxlZnQgKyBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0ICsgZGF0YS5jb2xsaXNpb25XaWR0aCAtXG5cdFx0XHRcdFx0b3V0ZXJXaWR0aCAtIHdpdGhpbk9mZnNldDtcblx0XHRcdFx0aWYgKCBuZXdPdmVyUmlnaHQgPCAwIHx8IG5ld092ZXJSaWdodCA8IGFicyggb3ZlckxlZnQgKSApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJMZWZ0ID0gcG9zaXRpb24ubGVmdCAtIGRhdGEuY29sbGlzaW9uUG9zaXRpb24ubWFyZ2luTGVmdCArIG15T2Zmc2V0ICtcblx0XHRcdFx0XHRhdE9mZnNldCArIG9mZnNldCAtIG9mZnNldExlZnQ7XG5cdFx0XHRcdGlmICggbmV3T3ZlckxlZnQgPiAwIHx8IGFicyggbmV3T3ZlckxlZnQgKSA8IG92ZXJSaWdodCApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXHRcdHRvcDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4ub2Zmc2V0LnRvcCArIHdpdGhpbi5zY3JvbGxUb3AsXG5cdFx0XHRcdG91dGVySGVpZ2h0ID0gd2l0aGluLmhlaWdodCxcblx0XHRcdFx0b2Zmc2V0VG9wID0gd2l0aGluLmlzV2luZG93ID8gd2l0aGluLnNjcm9sbFRvcCA6IHdpdGhpbi5vZmZzZXQudG9wLFxuXHRcdFx0XHRjb2xsaXNpb25Qb3NUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCxcblx0XHRcdFx0b3ZlclRvcCA9IGNvbGxpc2lvblBvc1RvcCAtIG9mZnNldFRvcCxcblx0XHRcdFx0b3ZlckJvdHRvbSA9IGNvbGxpc2lvblBvc1RvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLSBvZmZzZXRUb3AsXG5cdFx0XHRcdHRvcCA9IGRhdGEubXlbIDEgXSA9PT0gXCJ0b3BcIixcblx0XHRcdFx0bXlPZmZzZXQgPSB0b3AgP1xuXHRcdFx0XHRcdC1kYXRhLmVsZW1IZWlnaHQgOlxuXHRcdFx0XHRcdGRhdGEubXlbIDEgXSA9PT0gXCJib3R0b21cIiA/XG5cdFx0XHRcdFx0XHRkYXRhLmVsZW1IZWlnaHQgOlxuXHRcdFx0XHRcdFx0MCxcblx0XHRcdFx0YXRPZmZzZXQgPSBkYXRhLmF0WyAxIF0gPT09IFwidG9wXCIgP1xuXHRcdFx0XHRcdGRhdGEudGFyZ2V0SGVpZ2h0IDpcblx0XHRcdFx0XHRkYXRhLmF0WyAxIF0gPT09IFwiYm90dG9tXCIgP1xuXHRcdFx0XHRcdFx0LWRhdGEudGFyZ2V0SGVpZ2h0IDpcblx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdG9mZnNldCA9IC0yICogZGF0YS5vZmZzZXRbIDEgXSxcblx0XHRcdFx0bmV3T3ZlclRvcCxcblx0XHRcdFx0bmV3T3ZlckJvdHRvbTtcblx0XHRcdGlmICggb3ZlclRvcCA8IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJCb3R0b20gPSBwb3NpdGlvbi50b3AgKyBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0ICsgZGF0YS5jb2xsaXNpb25IZWlnaHQgLVxuXHRcdFx0XHRcdG91dGVySGVpZ2h0IC0gd2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRpZiAoIG5ld092ZXJCb3R0b20gPCAwIHx8IG5ld092ZXJCb3R0b20gPCBhYnMoIG92ZXJUb3AgKSApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi50b3AgKz0gbXlPZmZzZXQgKyBhdE9mZnNldCArIG9mZnNldDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCArIG15T2Zmc2V0ICsgYXRPZmZzZXQgK1xuXHRcdFx0XHRcdG9mZnNldCAtIG9mZnNldFRvcDtcblx0XHRcdFx0aWYgKCBuZXdPdmVyVG9wID4gMCB8fCBhYnMoIG5ld092ZXJUb3AgKSA8IG92ZXJCb3R0b20gKSB7XG5cdFx0XHRcdFx0cG9zaXRpb24udG9wICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdGZsaXBmaXQ6IHtcblx0XHRsZWZ0OiBmdW5jdGlvbigpIHtcblx0XHRcdCQudWkucG9zaXRpb24uZmxpcC5sZWZ0LmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdCQudWkucG9zaXRpb24uZml0LmxlZnQuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH0sXG5cdFx0dG9wOiBmdW5jdGlvbigpIHtcblx0XHRcdCQudWkucG9zaXRpb24uZmxpcC50b3AuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdFx0JC51aS5wb3NpdGlvbi5maXQudG9wLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHR9XG5cdH1cbn07XG5cbn0gKSgpO1xuXG5yZXR1cm4gJC51aS5wb3NpdGlvbjtcblxufSApICk7XG4iLCI7LyohIHNob3dkb3duIHYgMS45LjEgLSAwMi0xMS0yMDE5ICovXHJcbihmdW5jdGlvbigpe1xyXG4vKipcbiAqIENyZWF0ZWQgYnkgVGl2aWUgb24gMTMtMDctMjAxNS5cbiAqL1xuXG5mdW5jdGlvbiBnZXREZWZhdWx0T3B0cyAoc2ltcGxlKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgb21pdEV4dHJhV0xJbkNvZGVCbG9ja3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ09taXQgdGhlIGRlZmF1bHQgZXh0cmEgd2hpdGVsaW5lIGFkZGVkIHRvIGNvZGUgYmxvY2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbm9IZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgZ2VuZXJhdGVkIGhlYWRlciBpZCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHByZWZpeEhlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdBZGQgYSBwcmVmaXggdG8gdGhlIGdlbmVyYXRlZCBoZWFkZXIgaWRzLiBQYXNzaW5nIGEgc3RyaW5nIHdpbGwgcHJlZml4IHRoYXQgc3RyaW5nIHRvIHRoZSBoZWFkZXIgaWQuIFNldHRpbmcgdG8gdHJ1ZSB3aWxsIGFkZCBhIGdlbmVyaWMgXFwnc2VjdGlvbi1cXCcgcHJlZml4JyxcbiAgICAgIHR5cGU6ICdzdHJpbmcnXG4gICAgfSxcbiAgICByYXdQcmVmaXhIZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnU2V0dGluZyB0aGlzIG9wdGlvbiB0byB0cnVlIHdpbGwgcHJldmVudCBzaG93ZG93biBmcm9tIG1vZGlmeWluZyB0aGUgcHJlZml4LiBUaGlzIG1pZ2h0IHJlc3VsdCBpbiBtYWxmb3JtZWQgSURzIChpZiwgZm9yIGluc3RhbmNlLCB0aGUgXCIgY2hhciBpcyB1c2VkIGluIHRoZSBwcmVmaXgpJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZ2hDb21wYXRpYmxlSGVhZGVySWQ6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ0dlbmVyYXRlIGhlYWRlciBpZHMgY29tcGF0aWJsZSB3aXRoIGdpdGh1YiBzdHlsZSAoc3BhY2VzIGFyZSByZXBsYWNlZCB3aXRoIGRhc2hlcywgYSBidW5jaCBvZiBub24gYWxwaGFudW1lcmljIGNoYXJzIGFyZSByZW1vdmVkKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHJhd0hlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdSZW1vdmUgb25seSBzcGFjZXMsIFxcJyBhbmQgXCIgZnJvbSBnZW5lcmF0ZWQgaGVhZGVyIGlkcyAoaW5jbHVkaW5nIHByZWZpeGVzKSwgcmVwbGFjaW5nIHRoZW0gd2l0aCBkYXNoZXMgKC0pLiBXQVJOSU5HOiBUaGlzIG1pZ2h0IHJlc3VsdCBpbiBtYWxmb3JtZWQgaWRzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgaGVhZGVyTGV2ZWxTdGFydDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVGhlIGhlYWRlciBibG9ja3MgbGV2ZWwgc3RhcnQnLFxuICAgICAgdHlwZTogJ2ludGVnZXInXG4gICAgfSxcbiAgICBwYXJzZUltZ0RpbWVuc2lvbnM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1R1cm4gb24vb2ZmIGltYWdlIGRpbWVuc2lvbiBwYXJzaW5nJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc2ltcGxpZmllZEF1dG9MaW5rOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiBHRk0gYXV0b2xpbmsgc3R5bGUnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBleGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdFeGNsdWRlcyB0cmFpbGluZyBwdW5jdHVhdGlvbiBmcm9tIGxpbmtzIGdlbmVyYXRlZCB3aXRoIGF1dG9MaW5raW5nJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3Jlczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnUGFyc2UgbWlkd29yZCB1bmRlcnNjb3JlcyBhcyBsaXRlcmFsIHVuZGVyc2NvcmVzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbGl0ZXJhbE1pZFdvcmRBc3Rlcmlza3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1BhcnNlIG1pZHdvcmQgYXN0ZXJpc2tzIGFzIGxpdGVyYWwgYXN0ZXJpc2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc3RyaWtldGhyb3VnaDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgc3RyaWtldGhyb3VnaCBzdXBwb3J0JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgdGFibGVzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiB0YWJsZXMgc3VwcG9ydCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHRhYmxlc0hlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdBZGQgYW4gaWQgdG8gdGFibGUgaGVhZGVycycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoQ29kZUJsb2Nrczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiBHRk0gZmVuY2VkIGNvZGUgYmxvY2tzIHN1cHBvcnQnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICB0YXNrbGlzdHM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1R1cm4gb24vb2ZmIEdGTSB0YXNrbGlzdCBzdXBwb3J0JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc21vb3RoTGl2ZVByZXZpZXc6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1ByZXZlbnRzIHdlaXJkIGVmZmVjdHMgaW4gbGl2ZSBwcmV2aWV3cyBkdWUgdG8gaW5jb21wbGV0ZSBpbnB1dCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHNtYXJ0SW5kZW50YXRpb25GaXg6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1RyaWVzIHRvIHNtYXJ0bHkgZml4IGluZGVudGF0aW9uIGluIGVzNiBzdHJpbmdzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdEaXNhYmxlcyB0aGUgcmVxdWlyZW1lbnQgb2YgaW5kZW50aW5nIG5lc3RlZCBzdWJsaXN0cyBieSA0IHNwYWNlcycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHNpbXBsZUxpbmVCcmVha3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1BhcnNlcyBzaW1wbGUgbGluZSBicmVha3MgYXMgPGJyPiAoR0ZNIFN0eWxlKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHJlcXVpcmVTcGFjZUJlZm9yZUhlYWRpbmdUZXh0OiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdNYWtlcyBhZGRpbmcgYSBzcGFjZSBiZXR3ZWVuIGAjYCBhbmQgdGhlIGhlYWRlciB0ZXh0IG1hbmRhdG9yeSAoR0ZNIFN0eWxlKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoTWVudGlvbnM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VuYWJsZXMgZ2l0aHViIEBtZW50aW9ucycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoTWVudGlvbnNMaW5rOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6ICdodHRwczovL2dpdGh1Yi5jb20ve3V9JyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnQ2hhbmdlcyB0aGUgbGluayBnZW5lcmF0ZWQgYnkgQG1lbnRpb25zLiBPbmx5IGFwcGxpZXMgaWYgZ2hNZW50aW9ucyBvcHRpb24gaXMgZW5hYmxlZC4nLFxuICAgICAgdHlwZTogJ3N0cmluZydcbiAgICB9LFxuICAgIGVuY29kZUVtYWlsczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICAgICAgZGVzY3JpcHRpb246ICdFbmNvZGUgZS1tYWlsIGFkZHJlc3NlcyB0aHJvdWdoIHRoZSB1c2Ugb2YgQ2hhcmFjdGVyIEVudGl0aWVzLCB0cmFuc2Zvcm1pbmcgQVNDSUkgZS1tYWlsIGFkZHJlc3NlcyBpbnRvIGl0cyBlcXVpdmFsZW50IGRlY2ltYWwgZW50aXRpZXMnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBvcGVuTGlua3NJbk5ld1dpbmRvdzoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnT3BlbiBhbGwgbGlua3MgaW4gbmV3IHdpbmRvd3MnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBiYWNrc2xhc2hFc2NhcGVzSFRNTFRhZ3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1N1cHBvcnQgZm9yIEhUTUwgVGFnIGVzY2FwaW5nLiBleDogXFw8ZGl2PmZvb1xcPC9kaXY+JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZW1vamk6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VuYWJsZSBlbW9qaSBzdXBwb3J0LiBFeDogYHRoaXMgaXMgYSA6c21pbGU6IGVtb2ppYCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHVuZGVybGluZToge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW5hYmxlIHN1cHBvcnQgZm9yIHVuZGVybGluZS4gU3ludGF4IGlzIGRvdWJsZSBvciB0cmlwbGUgdW5kZXJzY29yZXM6IGBfX3VuZGVybGluZSB3b3JkX19gLiBXaXRoIHRoaXMgb3B0aW9uIGVuYWJsZWQsIHVuZGVyc2NvcmVzIG5vIGxvbmdlciBwYXJzZXMgaW50byBgPGVtPmAgYW5kIGA8c3Ryb25nPmAnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBjb21wbGV0ZUhUTUxEb2N1bWVudDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnT3V0cHV0cyBhIGNvbXBsZXRlIGh0bWwgZG9jdW1lbnQsIGluY2x1ZGluZyBgPGh0bWw+YCwgYDxoZWFkPmAgYW5kIGA8Ym9keT5gIHRhZ3MnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBtZXRhZGF0YToge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW5hYmxlIHN1cHBvcnQgZm9yIGRvY3VtZW50IG1ldGFkYXRhIChkZWZpbmVkIGF0IHRoZSB0b3Agb2YgdGhlIGRvY3VtZW50IGJldHdlZW4gYMKrwqvCq2AgYW5kIGDCu8K7wrtgIG9yIGJldHdlZW4gYC0tLWAgYW5kIGAtLS1gKS4nLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBzcGxpdEFkamFjZW50QmxvY2txdW90ZXM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1NwbGl0IGFkamFjZW50IGJsb2NrcXVvdGUgYmxvY2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH1cbiAgfTtcbiAgaWYgKHNpbXBsZSA9PT0gZmFsc2UpIHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShkZWZhdWx0T3B0aW9ucykpO1xuICB9XG4gIHZhciByZXQgPSB7fTtcbiAgZm9yICh2YXIgb3B0IGluIGRlZmF1bHRPcHRpb25zKSB7XG4gICAgaWYgKGRlZmF1bHRPcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpIHtcbiAgICAgIHJldFtvcHRdID0gZGVmYXVsdE9wdGlvbnNbb3B0XS5kZWZhdWx0VmFsdWU7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIGFsbE9wdGlvbnNPbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIG9wdGlvbnMgPSBnZXREZWZhdWx0T3B0cyh0cnVlKSxcbiAgICAgIHJldCA9IHt9O1xuICBmb3IgKHZhciBvcHQgaW4gb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpIHtcbiAgICAgIHJldFtvcHRdID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxyXG4vKipcbiAqIENyZWF0ZWQgYnkgVGl2aWUgb24gMDYtMDEtMjAxNS5cbiAqL1xuXG4vLyBQcml2YXRlIHByb3BlcnRpZXNcbnZhciBzaG93ZG93biA9IHt9LFxuICAgIHBhcnNlcnMgPSB7fSxcbiAgICBleHRlbnNpb25zID0ge30sXG4gICAgZ2xvYmFsT3B0aW9ucyA9IGdldERlZmF1bHRPcHRzKHRydWUpLFxuICAgIHNldEZsYXZvciA9ICd2YW5pbGxhJyxcbiAgICBmbGF2b3IgPSB7XG4gICAgICBnaXRodWI6IHtcbiAgICAgICAgb21pdEV4dHJhV0xJbkNvZGVCbG9ja3M6ICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBzaW1wbGlmaWVkQXV0b0xpbms6ICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGV4Y2x1ZGVUcmFpbGluZ1B1bmN0dWF0aW9uRnJvbVVSTHM6ICAgdHJ1ZSxcbiAgICAgICAgbGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3JlczogICAgICAgICAgICB0cnVlLFxuICAgICAgICBzdHJpa2V0aHJvdWdoOiAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhYmxlczogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgdGFibGVzSGVhZGVySWQ6ICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBnaENvZGVCbG9ja3M6ICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhc2tsaXN0czogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzOiB0cnVlLFxuICAgICAgICBzaW1wbGVMaW5lQnJlYWtzOiAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHJlcXVpcmVTcGFjZUJlZm9yZUhlYWRpbmdUZXh0OiAgICAgICAgdHJ1ZSxcbiAgICAgICAgZ2hDb21wYXRpYmxlSGVhZGVySWQ6ICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBnaE1lbnRpb25zOiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGJhY2tzbGFzaEVzY2FwZXNIVE1MVGFnczogICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZW1vamk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBzcGxpdEFkamFjZW50QmxvY2txdW90ZXM6ICAgICAgICAgICAgIHRydWVcbiAgICAgIH0sXG4gICAgICBvcmlnaW5hbDoge1xuICAgICAgICBub0hlYWRlcklkOiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGdoQ29kZUJsb2NrczogICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2VcbiAgICAgIH0sXG4gICAgICBnaG9zdDoge1xuICAgICAgICBvbWl0RXh0cmFXTEluQ29kZUJsb2NrczogICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHBhcnNlSW1nRGltZW5zaW9uczogICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc2ltcGxpZmllZEF1dG9MaW5rOiAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBleGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzOiAgIHRydWUsXG4gICAgICAgIGxpdGVyYWxNaWRXb3JkVW5kZXJzY29yZXM6ICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc3RyaWtldGhyb3VnaDogICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YWJsZXM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhYmxlc0hlYWRlcklkOiAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZ2hDb2RlQmxvY2tzOiAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YXNrbGlzdHM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHNtb290aExpdmVQcmV2aWV3OiAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc2ltcGxlTGluZUJyZWFrczogICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICByZXF1aXJlU3BhY2VCZWZvcmVIZWFkaW5nVGV4dDogICAgICAgIHRydWUsXG4gICAgICAgIGdoTWVudGlvbnM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgIGVuY29kZUVtYWlsczogICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgfSxcbiAgICAgIHZhbmlsbGE6IGdldERlZmF1bHRPcHRzKHRydWUpLFxuICAgICAgYWxsT246IGFsbE9wdGlvbnNPbigpXG4gICAgfTtcblxuLyoqXG4gKiBoZWxwZXIgbmFtZXNwYWNlXG4gKiBAdHlwZSB7e319XG4gKi9cbnNob3dkb3duLmhlbHBlciA9IHt9O1xuXG4vKipcbiAqIFRPRE8gTEVHQUNZIFNVUFBPUlQgQ09ERVxuICogQHR5cGUge3t9fVxuICovXG5zaG93ZG93bi5leHRlbnNpb25zID0ge307XG5cbi8qKlxuICogU2V0IGEgZ2xvYmFsIG9wdGlvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHJldHVybnMge3Nob3dkb3dufVxuICovXG5zaG93ZG93bi5zZXRPcHRpb24gPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAndXNlIHN0cmljdCc7XG4gIGdsb2JhbE9wdGlvbnNba2V5XSA9IHZhbHVlO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogR2V0IGEgZ2xvYmFsIG9wdGlvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHJldHVybnMgeyp9XG4gKi9cbnNob3dkb3duLmdldE9wdGlvbiA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gZ2xvYmFsT3B0aW9uc1trZXldO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGdsb2JhbCBvcHRpb25zXG4gKiBAc3RhdGljXG4gKiBAcmV0dXJucyB7e319XG4gKi9cbnNob3dkb3duLmdldE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIGdsb2JhbE9wdGlvbnM7XG59O1xuXG4vKipcbiAqIFJlc2V0IGdsb2JhbCBvcHRpb25zIHRvIHRoZSBkZWZhdWx0IHZhbHVlc1xuICogQHN0YXRpY1xuICovXG5zaG93ZG93bi5yZXNldE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgZ2xvYmFsT3B0aW9ucyA9IGdldERlZmF1bHRPcHRzKHRydWUpO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGZsYXZvciBzaG93ZG93biBzaG91bGQgdXNlIGFzIGRlZmF1bHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKi9cbnNob3dkb3duLnNldEZsYXZvciA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgaWYgKCFmbGF2b3IuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICB0aHJvdyBFcnJvcihuYW1lICsgJyBmbGF2b3Igd2FzIG5vdCBmb3VuZCcpO1xuICB9XG4gIHNob3dkb3duLnJlc2V0T3B0aW9ucygpO1xuICB2YXIgcHJlc2V0ID0gZmxhdm9yW25hbWVdO1xuICBzZXRGbGF2b3IgPSBuYW1lO1xuICBmb3IgKHZhciBvcHRpb24gaW4gcHJlc2V0KSB7XG4gICAgaWYgKHByZXNldC5oYXNPd25Qcm9wZXJ0eShvcHRpb24pKSB7XG4gICAgICBnbG9iYWxPcHRpb25zW29wdGlvbl0gPSBwcmVzZXRbb3B0aW9uXTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogR2V0IHRoZSBjdXJyZW50bHkgc2V0IGZsYXZvclxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uZ2V0Rmxhdm9yID0gZnVuY3Rpb24gKCkge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBzZXRGbGF2b3I7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgb3B0aW9ucyBvZiBhIHNwZWNpZmllZCBmbGF2b3IuIFJldHVybnMgdW5kZWZpbmVkIGlmIHRoZSBmbGF2b3Igd2FzIG5vdCBmb3VuZFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgZmxhdm9yXG4gKiBAcmV0dXJucyB7e318dW5kZWZpbmVkfVxuICovXG5zaG93ZG93bi5nZXRGbGF2b3JPcHRpb25zID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBpZiAoZmxhdm9yLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgcmV0dXJuIGZsYXZvcltuYW1lXTtcbiAgfVxufTtcblxuLyoqXG4gKiBHZXQgdGhlIGRlZmF1bHQgb3B0aW9uc1xuICogQHN0YXRpY1xuICogQHBhcmFtIHtib29sZWFufSBbc2ltcGxlPXRydWVdXG4gKiBAcmV0dXJucyB7e319XG4gKi9cbnNob3dkb3duLmdldERlZmF1bHRPcHRpb25zID0gZnVuY3Rpb24gKHNpbXBsZSkge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBnZXREZWZhdWx0T3B0cyhzaW1wbGUpO1xufTtcblxuLyoqXG4gKiBHZXQgb3Igc2V0IGEgc3ViUGFyc2VyXG4gKlxuICogc3ViUGFyc2VyKG5hbWUpICAgICAgIC0gR2V0IGEgcmVnaXN0ZXJlZCBzdWJQYXJzZXJcbiAqIHN1YlBhcnNlcihuYW1lLCBmdW5jKSAtIFJlZ2lzdGVyIGEgc3ViUGFyc2VyXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gW2Z1bmNdXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyID0gZnVuY3Rpb24gKG5hbWUsIGZ1bmMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG5hbWUpKSB7XG4gICAgaWYgKHR5cGVvZiBmdW5jICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcGFyc2Vyc1tuYW1lXSA9IGZ1bmM7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChwYXJzZXJzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZXJzW25hbWVdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ1N1YlBhcnNlciBuYW1lZCAnICsgbmFtZSArICcgbm90IHJlZ2lzdGVyZWQhJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEdldHMgb3IgcmVnaXN0ZXJzIGFuIGV4dGVuc2lvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7b2JqZWN0fGZ1bmN0aW9uPX0gZXh0XG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuc2hvd2Rvd24uZXh0ZW5zaW9uID0gZnVuY3Rpb24gKG5hbWUsIGV4dCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcobmFtZSkpIHtcbiAgICB0aHJvdyBFcnJvcignRXh0ZW5zaW9uIFxcJ25hbWVcXCcgbXVzdCBiZSBhIHN0cmluZycpO1xuICB9XG5cbiAgbmFtZSA9IHNob3dkb3duLmhlbHBlci5zdGRFeHROYW1lKG5hbWUpO1xuXG4gIC8vIEdldHRlclxuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dCkpIHtcbiAgICBpZiAoIWV4dGVuc2lvbnMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdFeHRlbnNpb24gbmFtZWQgJyArIG5hbWUgKyAnIGlzIG5vdCByZWdpc3RlcmVkIScpO1xuICAgIH1cbiAgICByZXR1cm4gZXh0ZW5zaW9uc1tuYW1lXTtcblxuICAgIC8vIFNldHRlclxuICB9IGVsc2Uge1xuICAgIC8vIEV4cGFuZCBleHRlbnNpb24gaWYgaXQncyB3cmFwcGVkIGluIGEgZnVuY3Rpb25cbiAgICBpZiAodHlwZW9mIGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZXh0ID0gZXh0KCk7XG4gICAgfVxuXG4gICAgLy8gRW5zdXJlIGV4dGVuc2lvbiBpcyBhbiBhcnJheVxuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0KSkge1xuICAgICAgZXh0ID0gW2V4dF07XG4gICAgfVxuXG4gICAgdmFyIHZhbGlkRXh0ZW5zaW9uID0gdmFsaWRhdGUoZXh0LCBuYW1lKTtcblxuICAgIGlmICh2YWxpZEV4dGVuc2lvbi52YWxpZCkge1xuICAgICAgZXh0ZW5zaW9uc1tuYW1lXSA9IGV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IodmFsaWRFeHRlbnNpb24uZXJyb3IpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBHZXRzIGFsbCBleHRlbnNpb25zIHJlZ2lzdGVyZWRcbiAqIEByZXR1cm5zIHt7fX1cbiAqL1xuc2hvd2Rvd24uZ2V0QWxsRXh0ZW5zaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gZXh0ZW5zaW9ucztcbn07XG5cbi8qKlxuICogUmVtb3ZlIGFuIGV4dGVuc2lvblxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqL1xuc2hvd2Rvd24ucmVtb3ZlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBkZWxldGUgZXh0ZW5zaW9uc1tuYW1lXTtcbn07XG5cbi8qKlxuICogUmVtb3ZlcyBhbGwgZXh0ZW5zaW9uc1xuICovXG5zaG93ZG93bi5yZXNldEV4dGVuc2lvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgZXh0ZW5zaW9ucyA9IHt9O1xufTtcblxuLyoqXG4gKiBWYWxpZGF0ZSBleHRlbnNpb25cbiAqIEBwYXJhbSB7YXJyYXl9IGV4dGVuc2lvblxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEByZXR1cm5zIHt7dmFsaWQ6IGJvb2xlYW4sIGVycm9yOiBzdHJpbmd9fVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZSAoZXh0ZW5zaW9uLCBuYW1lKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgZXJyTXNnID0gKG5hbWUpID8gJ0Vycm9yIGluICcgKyBuYW1lICsgJyBleHRlbnNpb24tPicgOiAnRXJyb3IgaW4gdW5uYW1lZCBleHRlbnNpb24nLFxuICAgICAgcmV0ID0ge1xuICAgICAgICB2YWxpZDogdHJ1ZSxcbiAgICAgICAgZXJyb3I6ICcnXG4gICAgICB9O1xuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0ZW5zaW9uKSkge1xuICAgIGV4dGVuc2lvbiA9IFtleHRlbnNpb25dO1xuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBleHRlbnNpb24ubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYmFzZU1zZyA9IGVyck1zZyArICcgc3ViLWV4dGVuc2lvbiAnICsgaSArICc6ICcsXG4gICAgICAgIGV4dCA9IGV4dGVuc2lvbltpXTtcbiAgICBpZiAodHlwZW9mIGV4dCAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdtdXN0IGJlIGFuIG9iamVjdCwgYnV0ICcgKyB0eXBlb2YgZXh0ICsgJyBnaXZlbic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKGV4dC50eXBlKSkge1xuICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ3Byb3BlcnR5IFwidHlwZVwiIG11c3QgYmUgYSBzdHJpbmcsIGJ1dCAnICsgdHlwZW9mIGV4dC50eXBlICsgJyBnaXZlbic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIHZhciB0eXBlID0gZXh0LnR5cGUgPSBleHQudHlwZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gbm9ybWFsaXplIGV4dGVuc2lvbiB0eXBlXG4gICAgaWYgKHR5cGUgPT09ICdsYW5ndWFnZScpIHtcbiAgICAgIHR5cGUgPSBleHQudHlwZSA9ICdsYW5nJztcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gJ2h0bWwnKSB7XG4gICAgICB0eXBlID0gZXh0LnR5cGUgPSAnb3V0cHV0JztcbiAgICB9XG5cbiAgICBpZiAodHlwZSAhPT0gJ2xhbmcnICYmIHR5cGUgIT09ICdvdXRwdXQnICYmIHR5cGUgIT09ICdsaXN0ZW5lcicpIHtcbiAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICd0eXBlICcgKyB0eXBlICsgJyBpcyBub3QgcmVjb2duaXplZC4gVmFsaWQgdmFsdWVzOiBcImxhbmcvbGFuZ3VhZ2VcIiwgXCJvdXRwdXQvaHRtbFwiIG9yIFwibGlzdGVuZXJcIic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnbGlzdGVuZXInKSB7XG4gICAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dC5saXN0ZW5lcnMpKSB7XG4gICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJy4gRXh0ZW5zaW9ucyBvZiB0eXBlIFwibGlzdGVuZXJcIiBtdXN0IGhhdmUgYSBwcm9wZXJ0eSBjYWxsZWQgXCJsaXN0ZW5lcnNcIic7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZXh0LmZpbHRlcikgJiYgc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dC5yZWdleCkpIHtcbiAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyB0eXBlICsgJyBleHRlbnNpb25zIG11c3QgZGVmaW5lIGVpdGhlciBhIFwicmVnZXhcIiBwcm9wZXJ0eSBvciBhIFwiZmlsdGVyXCIgbWV0aG9kJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZXh0Lmxpc3RlbmVycykge1xuICAgICAgaWYgKHR5cGVvZiBleHQubGlzdGVuZXJzICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdcImxpc3RlbmVyc1wiIHByb3BlcnR5IG11c3QgYmUgYW4gb2JqZWN0IGJ1dCAnICsgdHlwZW9mIGV4dC5saXN0ZW5lcnMgKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGxuIGluIGV4dC5saXN0ZW5lcnMpIHtcbiAgICAgICAgaWYgKGV4dC5saXN0ZW5lcnMuaGFzT3duUHJvcGVydHkobG4pKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBleHQubGlzdGVuZXJzW2xuXSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ1wibGlzdGVuZXJzXCIgcHJvcGVydHkgbXVzdCBiZSBhbiBoYXNoIG9mIFtldmVudCBuYW1lXTogW2NhbGxiYWNrXS4gbGlzdGVuZXJzLicgKyBsbiArXG4gICAgICAgICAgICAgICcgbXVzdCBiZSBhIGZ1bmN0aW9uIGJ1dCAnICsgdHlwZW9mIGV4dC5saXN0ZW5lcnNbbG5dICsgJyBnaXZlbic7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChleHQuZmlsdGVyKSB7XG4gICAgICBpZiAodHlwZW9mIGV4dC5maWx0ZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyAnXCJmaWx0ZXJcIiBtdXN0IGJlIGEgZnVuY3Rpb24sIGJ1dCAnICsgdHlwZW9mIGV4dC5maWx0ZXIgKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGV4dC5yZWdleCkge1xuICAgICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1N0cmluZyhleHQucmVnZXgpKSB7XG4gICAgICAgIGV4dC5yZWdleCA9IG5ldyBSZWdFeHAoZXh0LnJlZ2V4LCAnZycpO1xuICAgICAgfVxuICAgICAgaWYgKCEoZXh0LnJlZ2V4IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdcInJlZ2V4XCIgcHJvcGVydHkgbXVzdCBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgYSBSZWdFeHAgb2JqZWN0LCBidXQgJyArIHR5cGVvZiBleHQucmVnZXggKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZXh0LnJlcGxhY2UpKSB7XG4gICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ1wicmVnZXhcIiBleHRlbnNpb25zIG11c3QgaW1wbGVtZW50IGEgcmVwbGFjZSBzdHJpbmcgb3IgZnVuY3Rpb24nO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGV4dGVuc2lvblxuICogQHBhcmFtIHtvYmplY3R9IGV4dFxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnNob3dkb3duLnZhbGlkYXRlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKGV4dCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHZhbGlkYXRlRXh0ZW5zaW9uID0gdmFsaWRhdGUoZXh0LCBudWxsKTtcbiAgaWYgKCF2YWxpZGF0ZUV4dGVuc2lvbi52YWxpZCkge1xuICAgIGNvbnNvbGUud2Fybih2YWxpZGF0ZUV4dGVuc2lvbi5lcnJvcik7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufTtcblxyXG4vKipcbiAqIHNob3dkb3duanMgaGVscGVyIGZ1bmN0aW9uc1xuICovXG5cbmlmICghc2hvd2Rvd24uaGFzT3duUHJvcGVydHkoJ2hlbHBlcicpKSB7XG4gIHNob3dkb3duLmhlbHBlciA9IHt9O1xufVxuXG4vKipcbiAqIENoZWNrIGlmIHZhciBpcyBzdHJpbmdcbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7c3RyaW5nfSBhXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nID0gZnVuY3Rpb24gKGEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gKHR5cGVvZiBhID09PSAnc3RyaW5nJyB8fCBhIGluc3RhbmNlb2YgU3RyaW5nKTtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgdmFyIGlzIGEgZnVuY3Rpb25cbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7Kn0gYVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnNob3dkb3duLmhlbHBlci5pc0Z1bmN0aW9uID0gZnVuY3Rpb24gKGEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB2YXIgZ2V0VHlwZSA9IHt9O1xuICByZXR1cm4gYSAmJiBnZXRUeXBlLnRvU3RyaW5nLmNhbGwoYSkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59O1xuXG4vKipcbiAqIGlzQXJyYXkgaGVscGVyIGZ1bmN0aW9uXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0geyp9IGFcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5zaG93ZG93bi5oZWxwZXIuaXNBcnJheSA9IGZ1bmN0aW9uIChhKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYSk7XG59O1xuXG4vKipcbiAqIENoZWNrIGlmIHZhbHVlIGlzIHVuZGVmaW5lZFxuICogQHN0YXRpY1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYCwgZWxzZSBgZmFsc2VgLlxuICovXG5zaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn07XG5cbi8qKlxuICogRm9yRWFjaCBoZWxwZXIgZnVuY3Rpb25cbiAqIEl0ZXJhdGVzIG92ZXIgQXJyYXlzIGFuZCBPYmplY3RzIChvd24gcHJvcGVydGllcyBvbmx5KVxuICogQHN0YXRpY1xuICogQHBhcmFtIHsqfSBvYmpcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIEFjY2VwdHMgMyBwYXJhbXM6IDEuIHZhbHVlLCAyLiBrZXksIDMuIHRoZSBvcmlnaW5hbCBhcnJheS9vYmplY3RcbiAqL1xuc2hvd2Rvd24uaGVscGVyLmZvckVhY2ggPSBmdW5jdGlvbiAob2JqLCBjYWxsYmFjaykge1xuICAndXNlIHN0cmljdCc7XG4gIC8vIGNoZWNrIGlmIG9iaiBpcyBkZWZpbmVkXG4gIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQob2JqKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignb2JqIHBhcmFtIGlzIHJlcXVpcmVkJyk7XG4gIH1cblxuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGNhbGxiYWNrKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2FsbGJhY2sgcGFyYW0gaXMgcmVxdWlyZWQnKTtcbiAgfVxuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjYWxsYmFjayBwYXJhbSBtdXN0IGJlIGEgZnVuY3Rpb24vY2xvc3VyZScpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvYmouZm9yRWFjaCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIG9iai5mb3JFYWNoKGNhbGxiYWNrKTtcbiAgfSBlbHNlIGlmIChzaG93ZG93bi5oZWxwZXIuaXNBcnJheShvYmopKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmoubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNhbGxiYWNrKG9ialtpXSwgaSwgb2JqKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZW9mIChvYmopID09PSAnb2JqZWN0Jykge1xuICAgIGZvciAodmFyIHByb3AgaW4gb2JqKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgIGNhbGxiYWNrKG9ialtwcm9wXSwgcHJvcCwgb2JqKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdvYmogZG9lcyBub3Qgc2VlbSB0byBiZSBhbiBhcnJheSBvciBhbiBpdGVyYWJsZSBvYmplY3QnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTdGFuZGFyZGlkaXplIGV4dGVuc2lvbiBuYW1lXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0ge3N0cmluZ30gcyBleHRlbnNpb24gbmFtZVxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLnN0ZEV4dE5hbWUgPSBmdW5jdGlvbiAocykge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBzLnJlcGxhY2UoL1tfPyorXFwvXFxcXC5eLV0vZywgJycpLnJlcGxhY2UoL1xccy9nLCAnJykudG9Mb3dlckNhc2UoKTtcbn07XG5cbmZ1bmN0aW9uIGVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayAod2hvbGVNYXRjaCwgbTEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB2YXIgY2hhckNvZGVUb0VzY2FwZSA9IG0xLmNoYXJDb2RlQXQoMCk7XG4gIHJldHVybiAnwqhFJyArIGNoYXJDb2RlVG9Fc2NhcGUgKyAnRSc7XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgdXNlZCB0byBlc2NhcGUgY2hhcmFjdGVycyB3aGVuIHBhc3NpbmcgdGhyb3VnaCBTdHJpbmcucmVwbGFjZVxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IHdob2xlTWF0Y2hcbiAqIEBwYXJhbSB7c3RyaW5nfSBtMVxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayA9IGVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjaztcblxuLyoqXG4gKiBFc2NhcGUgY2hhcmFjdGVycyBpbiBhIHN0cmluZ1xuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjaGFyc1RvRXNjYXBlXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGFmdGVyQmFja3NsYXNoXG4gKiBAcmV0dXJucyB7WE1MfHN0cmluZ3x2b2lkfCp9XG4gKi9cbnNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzID0gZnVuY3Rpb24gKHRleHQsIGNoYXJzVG9Fc2NhcGUsIGFmdGVyQmFja3NsYXNoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgLy8gRmlyc3Qgd2UgaGF2ZSB0byBlc2NhcGUgdGhlIGVzY2FwZSBjaGFyYWN0ZXJzIHNvIHRoYXRcbiAgLy8gd2UgY2FuIGJ1aWxkIGEgY2hhcmFjdGVyIGNsYXNzIG91dCBvZiB0aGVtXG4gIHZhciByZWdleFN0cmluZyA9ICcoWycgKyBjaGFyc1RvRXNjYXBlLnJlcGxhY2UoLyhbXFxbXFxdXFxcXF0pL2csICdcXFxcJDEnKSArICddKSc7XG5cbiAgaWYgKGFmdGVyQmFja3NsYXNoKSB7XG4gICAgcmVnZXhTdHJpbmcgPSAnXFxcXFxcXFwnICsgcmVnZXhTdHJpbmc7XG4gIH1cblxuICB2YXIgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4U3RyaW5nLCAnZycpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlZ2V4LCBlc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gIHJldHVybiB0ZXh0O1xufTtcblxuLyoqXG4gKiBVbmVzY2FwZSBIVE1MIGVudGl0aWVzXG4gKiBAcGFyYW0gdHh0XG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5zaG93ZG93bi5oZWxwZXIudW5lc2NhcGVIVE1MRW50aXRpZXMgPSBmdW5jdGlvbiAodHh0KSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICByZXR1cm4gdHh0XG4gICAgLnJlcGxhY2UoLyZxdW90Oy9nLCAnXCInKVxuICAgIC5yZXBsYWNlKC8mbHQ7L2csICc8JylcbiAgICAucmVwbGFjZSgvJmd0Oy9nLCAnPicpXG4gICAgLnJlcGxhY2UoLyZhbXA7L2csICcmJyk7XG59O1xuXG52YXIgcmd4RmluZE1hdGNoUG9zID0gZnVuY3Rpb24gKHN0ciwgbGVmdCwgcmlnaHQsIGZsYWdzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIGYgPSBmbGFncyB8fCAnJyxcbiAgICAgIGcgPSBmLmluZGV4T2YoJ2cnKSA+IC0xLFxuICAgICAgeCA9IG5ldyBSZWdFeHAobGVmdCArICd8JyArIHJpZ2h0LCAnZycgKyBmLnJlcGxhY2UoL2cvZywgJycpKSxcbiAgICAgIGwgPSBuZXcgUmVnRXhwKGxlZnQsIGYucmVwbGFjZSgvZy9nLCAnJykpLFxuICAgICAgcG9zID0gW10sXG4gICAgICB0LCBzLCBtLCBzdGFydCwgZW5kO1xuXG4gIGRvIHtcbiAgICB0ID0gMDtcbiAgICB3aGlsZSAoKG0gPSB4LmV4ZWMoc3RyKSkpIHtcbiAgICAgIGlmIChsLnRlc3QobVswXSkpIHtcbiAgICAgICAgaWYgKCEodCsrKSkge1xuICAgICAgICAgIHMgPSB4Lmxhc3RJbmRleDtcbiAgICAgICAgICBzdGFydCA9IHMgLSBtWzBdLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0KSB7XG4gICAgICAgIGlmICghLS10KSB7XG4gICAgICAgICAgZW5kID0gbS5pbmRleCArIG1bMF0ubGVuZ3RoO1xuICAgICAgICAgIHZhciBvYmogPSB7XG4gICAgICAgICAgICBsZWZ0OiB7c3RhcnQ6IHN0YXJ0LCBlbmQ6IHN9LFxuICAgICAgICAgICAgbWF0Y2g6IHtzdGFydDogcywgZW5kOiBtLmluZGV4fSxcbiAgICAgICAgICAgIHJpZ2h0OiB7c3RhcnQ6IG0uaW5kZXgsIGVuZDogZW5kfSxcbiAgICAgICAgICAgIHdob2xlTWF0Y2g6IHtzdGFydDogc3RhcnQsIGVuZDogZW5kfVxuICAgICAgICAgIH07XG4gICAgICAgICAgcG9zLnB1c2gob2JqKTtcbiAgICAgICAgICBpZiAoIWcpIHtcbiAgICAgICAgICAgIHJldHVybiBwb3M7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IHdoaWxlICh0ICYmICh4Lmxhc3RJbmRleCA9IHMpKTtcblxuICByZXR1cm4gcG9zO1xufTtcblxuLyoqXG4gKiBtYXRjaFJlY3Vyc2l2ZVJlZ0V4cFxuICpcbiAqIChjKSAyMDA3IFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICogTUlUIExpY2Vuc2VcbiAqXG4gKiBBY2NlcHRzIGEgc3RyaW5nIHRvIHNlYXJjaCwgYSBsZWZ0IGFuZCByaWdodCBmb3JtYXQgZGVsaW1pdGVyXG4gKiBhcyByZWdleCBwYXR0ZXJucywgYW5kIG9wdGlvbmFsIHJlZ2V4IGZsYWdzLiBSZXR1cm5zIGFuIGFycmF5XG4gKiBvZiBtYXRjaGVzLCBhbGxvd2luZyBuZXN0ZWQgaW5zdGFuY2VzIG9mIGxlZnQvcmlnaHQgZGVsaW1pdGVycy5cbiAqIFVzZSB0aGUgXCJnXCIgZmxhZyB0byByZXR1cm4gYWxsIG1hdGNoZXMsIG90aGVyd2lzZSBvbmx5IHRoZVxuICogZmlyc3QgaXMgcmV0dXJuZWQuIEJlIGNhcmVmdWwgdG8gZW5zdXJlIHRoYXQgdGhlIGxlZnQgYW5kXG4gKiByaWdodCBmb3JtYXQgZGVsaW1pdGVycyBwcm9kdWNlIG11dHVhbGx5IGV4Y2x1c2l2ZSBtYXRjaGVzLlxuICogQmFja3JlZmVyZW5jZXMgYXJlIG5vdCBzdXBwb3J0ZWQgd2l0aGluIHRoZSByaWdodCBkZWxpbWl0ZXJcbiAqIGR1ZSB0byBob3cgaXQgaXMgaW50ZXJuYWxseSBjb21iaW5lZCB3aXRoIHRoZSBsZWZ0IGRlbGltaXRlci5cbiAqIFdoZW4gbWF0Y2hpbmcgc3RyaW5ncyB3aG9zZSBmb3JtYXQgZGVsaW1pdGVycyBhcmUgdW5iYWxhbmNlZFxuICogdG8gdGhlIGxlZnQgb3IgcmlnaHQsIHRoZSBvdXRwdXQgaXMgaW50ZW50aW9uYWxseSBhcyBhXG4gKiBjb252ZW50aW9uYWwgcmVnZXggbGlicmFyeSB3aXRoIHJlY3Vyc2lvbiBzdXBwb3J0IHdvdWxkXG4gKiBwcm9kdWNlLCBlLmcuIFwiPDx4PlwiIGFuZCBcIjx4Pj5cIiBib3RoIHByb2R1Y2UgW1wieFwiXSB3aGVuIHVzaW5nXG4gKiBcIjxcIiBhbmQgXCI+XCIgYXMgdGhlIGRlbGltaXRlcnMgKGJvdGggc3RyaW5ncyBjb250YWluIGEgc2luZ2xlLFxuICogYmFsYW5jZWQgaW5zdGFuY2Ugb2YgXCI8eD5cIikuXG4gKlxuICogZXhhbXBsZXM6XG4gKiBtYXRjaFJlY3Vyc2l2ZVJlZ0V4cChcInRlc3RcIiwgXCJcXFxcKFwiLCBcIlxcXFwpXCIpXG4gKiByZXR1cm5zOiBbXVxuICogbWF0Y2hSZWN1cnNpdmVSZWdFeHAoXCI8dDw8ZT4+PHM+PnQ8PlwiLCBcIjxcIiwgXCI+XCIsIFwiZ1wiKVxuICogcmV0dXJuczogW1widDw8ZT4+PHM+XCIsIFwiXCJdXG4gKiBtYXRjaFJlY3Vyc2l2ZVJlZ0V4cChcIjxkaXYgaWQ9XFxcInhcXFwiPnRlc3Q8L2Rpdj5cIiwgXCI8ZGl2XFxcXGJbXj5dKj5cIiwgXCI8L2Rpdj5cIiwgXCJnaVwiKVxuICogcmV0dXJuczogW1widGVzdFwiXVxuICovXG5zaG93ZG93bi5oZWxwZXIubWF0Y2hSZWN1cnNpdmVSZWdFeHAgPSBmdW5jdGlvbiAoc3RyLCBsZWZ0LCByaWdodCwgZmxhZ3MpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciBtYXRjaFBvcyA9IHJneEZpbmRNYXRjaFBvcyAoc3RyLCBsZWZ0LCByaWdodCwgZmxhZ3MpLFxuICAgICAgcmVzdWx0cyA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbWF0Y2hQb3MubGVuZ3RoOyArK2kpIHtcbiAgICByZXN1bHRzLnB1c2goW1xuICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLndob2xlTWF0Y2guc3RhcnQsIG1hdGNoUG9zW2ldLndob2xlTWF0Y2guZW5kKSxcbiAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS5tYXRjaC5zdGFydCwgbWF0Y2hQb3NbaV0ubWF0Y2guZW5kKSxcbiAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS5sZWZ0LnN0YXJ0LCBtYXRjaFBvc1tpXS5sZWZ0LmVuZCksXG4gICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ucmlnaHQuc3RhcnQsIG1hdGNoUG9zW2ldLnJpZ2h0LmVuZClcbiAgICBdKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0cztcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAqIEBwYXJhbSB7c3RyaW5nfGZ1bmN0aW9ufSByZXBsYWNlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IGxlZnRcbiAqIEBwYXJhbSB7c3RyaW5nfSByaWdodFxuICogQHBhcmFtIHtzdHJpbmd9IGZsYWdzXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5zaG93ZG93bi5oZWxwZXIucmVwbGFjZVJlY3Vyc2l2ZVJlZ0V4cCA9IGZ1bmN0aW9uIChzdHIsIHJlcGxhY2VtZW50LCBsZWZ0LCByaWdodCwgZmxhZ3MpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzRnVuY3Rpb24ocmVwbGFjZW1lbnQpKSB7XG4gICAgdmFyIHJlcFN0ciA9IHJlcGxhY2VtZW50O1xuICAgIHJlcGxhY2VtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHJlcFN0cjtcbiAgICB9O1xuICB9XG5cbiAgdmFyIG1hdGNoUG9zID0gcmd4RmluZE1hdGNoUG9zKHN0ciwgbGVmdCwgcmlnaHQsIGZsYWdzKSxcbiAgICAgIGZpbmFsU3RyID0gc3RyLFxuICAgICAgbG5nID0gbWF0Y2hQb3MubGVuZ3RoO1xuXG4gIGlmIChsbmcgPiAwKSB7XG4gICAgdmFyIGJpdHMgPSBbXTtcbiAgICBpZiAobWF0Y2hQb3NbMF0ud2hvbGVNYXRjaC5zdGFydCAhPT0gMCkge1xuICAgICAgYml0cy5wdXNoKHN0ci5zbGljZSgwLCBtYXRjaFBvc1swXS53aG9sZU1hdGNoLnN0YXJ0KSk7XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG5nOyArK2kpIHtcbiAgICAgIGJpdHMucHVzaChcbiAgICAgICAgcmVwbGFjZW1lbnQoXG4gICAgICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLndob2xlTWF0Y2guc3RhcnQsIG1hdGNoUG9zW2ldLndob2xlTWF0Y2guZW5kKSxcbiAgICAgICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ubWF0Y2guc3RhcnQsIG1hdGNoUG9zW2ldLm1hdGNoLmVuZCksXG4gICAgICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLmxlZnQuc3RhcnQsIG1hdGNoUG9zW2ldLmxlZnQuZW5kKSxcbiAgICAgICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ucmlnaHQuc3RhcnQsIG1hdGNoUG9zW2ldLnJpZ2h0LmVuZClcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICAgIGlmIChpIDwgbG5nIC0gMSkge1xuICAgICAgICBiaXRzLnB1c2goc3RyLnNsaWNlKG1hdGNoUG9zW2ldLndob2xlTWF0Y2guZW5kLCBtYXRjaFBvc1tpICsgMV0ud2hvbGVNYXRjaC5zdGFydCkpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAobWF0Y2hQb3NbbG5nIC0gMV0ud2hvbGVNYXRjaC5lbmQgPCBzdHIubGVuZ3RoKSB7XG4gICAgICBiaXRzLnB1c2goc3RyLnNsaWNlKG1hdGNoUG9zW2xuZyAtIDFdLndob2xlTWF0Y2guZW5kKSk7XG4gICAgfVxuICAgIGZpbmFsU3RyID0gYml0cy5qb2luKCcnKTtcbiAgfVxuICByZXR1cm4gZmluYWxTdHI7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IHdpdGhpbiB0aGUgcGFzc2VkIFN0cmluZyBvYmplY3Qgb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlIHNwZWNpZmllZCByZWdleCxcbiAqIHN0YXJ0aW5nIHRoZSBzZWFyY2ggYXQgZnJvbUluZGV4LiBSZXR1cm5zIC0xIGlmIHRoZSB2YWx1ZSBpcyBub3QgZm91bmQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0ciBzdHJpbmcgdG8gc2VhcmNoXG4gKiBAcGFyYW0ge1JlZ0V4cH0gcmVnZXggUmVndWxhciBleHByZXNzaW9uIHRvIHNlYXJjaFxuICogQHBhcmFtIHtpbnR9IFtmcm9tSW5kZXggPSAwXSBJbmRleCB0byBzdGFydCB0aGUgc2VhcmNoXG4gKiBAcmV0dXJucyB7TnVtYmVyfVxuICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFcnJvclxuICovXG5zaG93ZG93bi5oZWxwZXIucmVnZXhJbmRleE9mID0gZnVuY3Rpb24gKHN0ciwgcmVnZXgsIGZyb21JbmRleCkge1xuICAndXNlIHN0cmljdCc7XG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKHN0cikpIHtcbiAgICB0aHJvdyAnSW52YWxpZEFyZ3VtZW50RXJyb3I6IGZpcnN0IHBhcmFtZXRlciBvZiBzaG93ZG93bi5oZWxwZXIucmVnZXhJbmRleE9mIGZ1bmN0aW9uIG11c3QgYmUgYSBzdHJpbmcnO1xuICB9XG4gIGlmIChyZWdleCBpbnN0YW5jZW9mIFJlZ0V4cCA9PT0gZmFsc2UpIHtcbiAgICB0aHJvdyAnSW52YWxpZEFyZ3VtZW50RXJyb3I6IHNlY29uZCBwYXJhbWV0ZXIgb2Ygc2hvd2Rvd24uaGVscGVyLnJlZ2V4SW5kZXhPZiBmdW5jdGlvbiBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIFJlZ0V4cCc7XG4gIH1cbiAgdmFyIGluZGV4T2YgPSBzdHIuc3Vic3RyaW5nKGZyb21JbmRleCB8fCAwKS5zZWFyY2gocmVnZXgpO1xuICByZXR1cm4gKGluZGV4T2YgPj0gMCkgPyAoaW5kZXhPZiArIChmcm9tSW5kZXggfHwgMCkpIDogaW5kZXhPZjtcbn07XG5cbi8qKlxuICogU3BsaXRzIHRoZSBwYXNzZWQgc3RyaW5nIG9iamVjdCBhdCB0aGUgZGVmaW5lZCBpbmRleCwgYW5kIHJldHVybnMgYW4gYXJyYXkgY29tcG9zZWQgb2YgdGhlIHR3byBzdWJzdHJpbmdzXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIHN0cmluZyB0byBzcGxpdFxuICogQHBhcmFtIHtpbnR9IGluZGV4IGluZGV4IHRvIHNwbGl0IHN0cmluZyBhdFxuICogQHJldHVybnMge1tzdHJpbmcsc3RyaW5nXX1cbiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXJyb3JcbiAqL1xuc2hvd2Rvd24uaGVscGVyLnNwbGl0QXRJbmRleCA9IGZ1bmN0aW9uIChzdHIsIGluZGV4KSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcoc3RyKSkge1xuICAgIHRocm93ICdJbnZhbGlkQXJndW1lbnRFcnJvcjogZmlyc3QgcGFyYW1ldGVyIG9mIHNob3dkb3duLmhlbHBlci5yZWdleEluZGV4T2YgZnVuY3Rpb24gbXVzdCBiZSBhIHN0cmluZyc7XG4gIH1cbiAgcmV0dXJuIFtzdHIuc3Vic3RyaW5nKDAsIGluZGV4KSwgc3RyLnN1YnN0cmluZyhpbmRleCldO1xufTtcblxuLyoqXG4gKiBPYmZ1c2NhdGUgYW4gZS1tYWlsIGFkZHJlc3MgdGhyb3VnaCB0aGUgdXNlIG9mIENoYXJhY3RlciBFbnRpdGllcyxcbiAqIHRyYW5zZm9ybWluZyBBU0NJSSBjaGFyYWN0ZXJzIGludG8gdGhlaXIgZXF1aXZhbGVudCBkZWNpbWFsIG9yIGhleCBlbnRpdGllcy5cbiAqXG4gKiBTaW5jZSBpdCBoYXMgYSByYW5kb20gY29tcG9uZW50LCBzdWJzZXF1ZW50IGNhbGxzIHRvIHRoaXMgZnVuY3Rpb24gcHJvZHVjZSBkaWZmZXJlbnQgcmVzdWx0c1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtYWlsXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5zaG93ZG93bi5oZWxwZXIuZW5jb2RlRW1haWxBZGRyZXNzID0gZnVuY3Rpb24gKG1haWwpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB2YXIgZW5jb2RlID0gW1xuICAgIGZ1bmN0aW9uIChjaCkge1xuICAgICAgcmV0dXJuICcmIycgKyBjaC5jaGFyQ29kZUF0KDApICsgJzsnO1xuICAgIH0sXG4gICAgZnVuY3Rpb24gKGNoKSB7XG4gICAgICByZXR1cm4gJyYjeCcgKyBjaC5jaGFyQ29kZUF0KDApLnRvU3RyaW5nKDE2KSArICc7JztcbiAgICB9LFxuICAgIGZ1bmN0aW9uIChjaCkge1xuICAgICAgcmV0dXJuIGNoO1xuICAgIH1cbiAgXTtcblxuICBtYWlsID0gbWFpbC5yZXBsYWNlKC8uL2csIGZ1bmN0aW9uIChjaCkge1xuICAgIGlmIChjaCA9PT0gJ0AnKSB7XG4gICAgICAvLyB0aGlzICptdXN0KiBiZSBlbmNvZGVkLiBJIGluc2lzdC5cbiAgICAgIGNoID0gZW5jb2RlW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDIpXShjaCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciByID0gTWF0aC5yYW5kb20oKTtcbiAgICAgIC8vIHJvdWdobHkgMTAlIHJhdywgNDUlIGhleCwgNDUlIGRlY1xuICAgICAgY2ggPSAoXG4gICAgICAgIHIgPiAwLjkgPyBlbmNvZGVbMl0oY2gpIDogciA+IDAuNDUgPyBlbmNvZGVbMV0oY2gpIDogZW5jb2RlWzBdKGNoKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGNoO1xuICB9KTtcblxuICByZXR1cm4gbWFpbDtcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBzdHJcbiAqIEBwYXJhbSB0YXJnZXRMZW5ndGhcbiAqIEBwYXJhbSBwYWRTdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbnNob3dkb3duLmhlbHBlci5wYWRFbmQgPSBmdW5jdGlvbiBwYWRFbmQgKHN0ciwgdGFyZ2V0TGVuZ3RoLCBwYWRTdHJpbmcpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICAvKmpzaGludCBiaXR3aXNlOiBmYWxzZSovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzcGFjZS1pbmZpeC1vcHNcbiAgdGFyZ2V0TGVuZ3RoID0gdGFyZ2V0TGVuZ3RoPj4wOyAvL2Zsb29yIGlmIG51bWJlciBvciBjb252ZXJ0IG5vbi1udW1iZXIgdG8gMDtcbiAgLypqc2hpbnQgYml0d2lzZTogdHJ1ZSovXG4gIHBhZFN0cmluZyA9IFN0cmluZyhwYWRTdHJpbmcgfHwgJyAnKTtcbiAgaWYgKHN0ci5sZW5ndGggPiB0YXJnZXRMZW5ndGgpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cik7XG4gIH0gZWxzZSB7XG4gICAgdGFyZ2V0TGVuZ3RoID0gdGFyZ2V0TGVuZ3RoIC0gc3RyLmxlbmd0aDtcbiAgICBpZiAodGFyZ2V0TGVuZ3RoID4gcGFkU3RyaW5nLmxlbmd0aCkge1xuICAgICAgcGFkU3RyaW5nICs9IHBhZFN0cmluZy5yZXBlYXQodGFyZ2V0TGVuZ3RoIC8gcGFkU3RyaW5nLmxlbmd0aCk7IC8vYXBwZW5kIHRvIG9yaWdpbmFsIHRvIGVuc3VyZSB3ZSBhcmUgbG9uZ2VyIHRoYW4gbmVlZGVkXG4gICAgfVxuICAgIHJldHVybiBTdHJpbmcoc3RyKSArIHBhZFN0cmluZy5zbGljZSgwLHRhcmdldExlbmd0aCk7XG4gIH1cbn07XG5cbi8qKlxuICogUE9MWUZJTExTXG4gKi9cbi8vIHVzZSB0aGlzIGluc3RlYWQgb2YgYnVpbHRpbiBpcyB1bmRlZmluZWQgZm9yIElFOCBjb21wYXRpYmlsaXR5XG5pZiAodHlwZW9mIGNvbnNvbGUgPT09ICd1bmRlZmluZWQnKSB7XG4gIGNvbnNvbGUgPSB7XG4gICAgd2FybjogZnVuY3Rpb24gKG1zZykge1xuICAgICAgJ3VzZSBzdHJpY3QnO1xuICAgICAgYWxlcnQobXNnKTtcbiAgICB9LFxuICAgIGxvZzogZnVuY3Rpb24gKG1zZykge1xuICAgICAgJ3VzZSBzdHJpY3QnO1xuICAgICAgYWxlcnQobXNnKTtcbiAgICB9LFxuICAgIGVycm9yOiBmdW5jdGlvbiAobXNnKSB7XG4gICAgICAndXNlIHN0cmljdCc7XG4gICAgICB0aHJvdyBtc2c7XG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIENvbW1vbiByZWdleGVzLlxuICogV2UgZGVjbGFyZSBzb21lIGNvbW1vbiByZWdleGVzIHRvIGltcHJvdmUgcGVyZm9ybWFuY2VcbiAqL1xuc2hvd2Rvd24uaGVscGVyLnJlZ2V4ZXMgPSB7XG4gIGFzdGVyaXNrRGFzaEFuZENvbG9uOiAvKFsqXzp+XSkvZ1xufTtcblxuLyoqXG4gKiBFTU9KSVMgTElTVFxuICovXG5zaG93ZG93bi5oZWxwZXIuZW1vamlzID0ge1xuICAnKzEnOidcXHVkODNkXFx1ZGM0ZCcsXG4gICctMSc6J1xcdWQ4M2RcXHVkYzRlJyxcbiAgJzEwMCc6J1xcdWQ4M2RcXHVkY2FmJyxcbiAgJzEyMzQnOidcXHVkODNkXFx1ZGQyMicsXG4gICcxc3RfcGxhY2VfbWVkYWwnOidcXHVkODNlXFx1ZGQ0NycsXG4gICcybmRfcGxhY2VfbWVkYWwnOidcXHVkODNlXFx1ZGQ0OCcsXG4gICczcmRfcGxhY2VfbWVkYWwnOidcXHVkODNlXFx1ZGQ0OScsXG4gICc4YmFsbCc6J1xcdWQ4M2NcXHVkZmIxJyxcbiAgJ2EnOidcXHVkODNjXFx1ZGQ3MFxcdWZlMGYnLFxuICAnYWInOidcXHVkODNjXFx1ZGQ4ZScsXG4gICdhYmMnOidcXHVkODNkXFx1ZGQyNCcsXG4gICdhYmNkJzonXFx1ZDgzZFxcdWRkMjEnLFxuICAnYWNjZXB0JzonXFx1ZDgzY1xcdWRlNTEnLFxuICAnYWVyaWFsX3RyYW13YXknOidcXHVkODNkXFx1ZGVhMScsXG4gICdhaXJwbGFuZSc6J1xcdTI3MDhcXHVmZTBmJyxcbiAgJ2FsYXJtX2Nsb2NrJzonXFx1MjNmMCcsXG4gICdhbGVtYmljJzonXFx1MjY5N1xcdWZlMGYnLFxuICAnYWxpZW4nOidcXHVkODNkXFx1ZGM3ZCcsXG4gICdhbWJ1bGFuY2UnOidcXHVkODNkXFx1ZGU5MScsXG4gICdhbXBob3JhJzonXFx1ZDgzY1xcdWRmZmEnLFxuICAnYW5jaG9yJzonXFx1MjY5M1xcdWZlMGYnLFxuICAnYW5nZWwnOidcXHVkODNkXFx1ZGM3YycsXG4gICdhbmdlcic6J1xcdWQ4M2RcXHVkY2EyJyxcbiAgJ2FuZ3J5JzonXFx1ZDgzZFxcdWRlMjAnLFxuICAnYW5ndWlzaGVkJzonXFx1ZDgzZFxcdWRlMjcnLFxuICAnYW50JzonXFx1ZDgzZFxcdWRjMWMnLFxuICAnYXBwbGUnOidcXHVkODNjXFx1ZGY0ZScsXG4gICdhcXVhcml1cyc6J1xcdTI2NTJcXHVmZTBmJyxcbiAgJ2FyaWVzJzonXFx1MjY0OFxcdWZlMGYnLFxuICAnYXJyb3dfYmFja3dhcmQnOidcXHUyNWMwXFx1ZmUwZicsXG4gICdhcnJvd19kb3VibGVfZG93bic6J1xcdTIzZWMnLFxuICAnYXJyb3dfZG91YmxlX3VwJzonXFx1MjNlYicsXG4gICdhcnJvd19kb3duJzonXFx1MmIwN1xcdWZlMGYnLFxuICAnYXJyb3dfZG93bl9zbWFsbCc6J1xcdWQ4M2RcXHVkZDNkJyxcbiAgJ2Fycm93X2ZvcndhcmQnOidcXHUyNWI2XFx1ZmUwZicsXG4gICdhcnJvd19oZWFkaW5nX2Rvd24nOidcXHUyOTM1XFx1ZmUwZicsXG4gICdhcnJvd19oZWFkaW5nX3VwJzonXFx1MjkzNFxcdWZlMGYnLFxuICAnYXJyb3dfbGVmdCc6J1xcdTJiMDVcXHVmZTBmJyxcbiAgJ2Fycm93X2xvd2VyX2xlZnQnOidcXHUyMTk5XFx1ZmUwZicsXG4gICdhcnJvd19sb3dlcl9yaWdodCc6J1xcdTIxOThcXHVmZTBmJyxcbiAgJ2Fycm93X3JpZ2h0JzonXFx1MjdhMVxcdWZlMGYnLFxuICAnYXJyb3dfcmlnaHRfaG9vayc6J1xcdTIxYWFcXHVmZTBmJyxcbiAgJ2Fycm93X3VwJzonXFx1MmIwNlxcdWZlMGYnLFxuICAnYXJyb3dfdXBfZG93bic6J1xcdTIxOTVcXHVmZTBmJyxcbiAgJ2Fycm93X3VwX3NtYWxsJzonXFx1ZDgzZFxcdWRkM2MnLFxuICAnYXJyb3dfdXBwZXJfbGVmdCc6J1xcdTIxOTZcXHVmZTBmJyxcbiAgJ2Fycm93X3VwcGVyX3JpZ2h0JzonXFx1MjE5N1xcdWZlMGYnLFxuICAnYXJyb3dzX2Nsb2Nrd2lzZSc6J1xcdWQ4M2RcXHVkZDAzJyxcbiAgJ2Fycm93c19jb3VudGVyY2xvY2t3aXNlJzonXFx1ZDgzZFxcdWRkMDQnLFxuICAnYXJ0JzonXFx1ZDgzY1xcdWRmYTgnLFxuICAnYXJ0aWN1bGF0ZWRfbG9ycnknOidcXHVkODNkXFx1ZGU5YicsXG4gICdhcnRpZmljaWFsX3NhdGVsbGl0ZSc6J1xcdWQ4M2RcXHVkZWYwJyxcbiAgJ2FzdG9uaXNoZWQnOidcXHVkODNkXFx1ZGUzMicsXG4gICdhdGhsZXRpY19zaG9lJzonXFx1ZDgzZFxcdWRjNWYnLFxuICAnYXRtJzonXFx1ZDgzY1xcdWRmZTcnLFxuICAnYXRvbV9zeW1ib2wnOidcXHUyNjliXFx1ZmUwZicsXG4gICdhdm9jYWRvJzonXFx1ZDgzZVxcdWRkNTEnLFxuICAnYic6J1xcdWQ4M2NcXHVkZDcxXFx1ZmUwZicsXG4gICdiYWJ5JzonXFx1ZDgzZFxcdWRjNzYnLFxuICAnYmFieV9ib3R0bGUnOidcXHVkODNjXFx1ZGY3YycsXG4gICdiYWJ5X2NoaWNrJzonXFx1ZDgzZFxcdWRjMjQnLFxuICAnYmFieV9zeW1ib2wnOidcXHVkODNkXFx1ZGViYycsXG4gICdiYWNrJzonXFx1ZDgzZFxcdWRkMTknLFxuICAnYmFjb24nOidcXHVkODNlXFx1ZGQ1MycsXG4gICdiYWRtaW50b24nOidcXHVkODNjXFx1ZGZmOCcsXG4gICdiYWdnYWdlX2NsYWltJzonXFx1ZDgzZFxcdWRlYzQnLFxuICAnYmFndWV0dGVfYnJlYWQnOidcXHVkODNlXFx1ZGQ1NicsXG4gICdiYWxhbmNlX3NjYWxlJzonXFx1MjY5NlxcdWZlMGYnLFxuICAnYmFsbG9vbic6J1xcdWQ4M2NcXHVkZjg4JyxcbiAgJ2JhbGxvdF9ib3gnOidcXHVkODNkXFx1ZGRmMycsXG4gICdiYWxsb3RfYm94X3dpdGhfY2hlY2snOidcXHUyNjExXFx1ZmUwZicsXG4gICdiYW1ib28nOidcXHVkODNjXFx1ZGY4ZCcsXG4gICdiYW5hbmEnOidcXHVkODNjXFx1ZGY0YycsXG4gICdiYW5nYmFuZyc6J1xcdTIwM2NcXHVmZTBmJyxcbiAgJ2JhbmsnOidcXHVkODNjXFx1ZGZlNicsXG4gICdiYXJfY2hhcnQnOidcXHVkODNkXFx1ZGNjYScsXG4gICdiYXJiZXInOidcXHVkODNkXFx1ZGM4OCcsXG4gICdiYXNlYmFsbCc6J1xcdTI2YmVcXHVmZTBmJyxcbiAgJ2Jhc2tldGJhbGwnOidcXHVkODNjXFx1ZGZjMCcsXG4gICdiYXNrZXRiYWxsX21hbic6J1xcdTI2ZjlcXHVmZTBmJyxcbiAgJ2Jhc2tldGJhbGxfd29tYW4nOidcXHUyNmY5XFx1ZmUwZiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnYmF0JzonXFx1ZDgzZVxcdWRkODcnLFxuICAnYmF0aCc6J1xcdWQ4M2RcXHVkZWMwJyxcbiAgJ2JhdGh0dWInOidcXHVkODNkXFx1ZGVjMScsXG4gICdiYXR0ZXJ5JzonXFx1ZDgzZFxcdWRkMGInLFxuICAnYmVhY2hfdW1icmVsbGEnOidcXHVkODNjXFx1ZGZkNicsXG4gICdiZWFyJzonXFx1ZDgzZFxcdWRjM2InLFxuICAnYmVkJzonXFx1ZDgzZFxcdWRlY2YnLFxuICAnYmVlJzonXFx1ZDgzZFxcdWRjMWQnLFxuICAnYmVlcic6J1xcdWQ4M2NcXHVkZjdhJyxcbiAgJ2JlZXJzJzonXFx1ZDgzY1xcdWRmN2InLFxuICAnYmVldGxlJzonXFx1ZDgzZFxcdWRjMWUnLFxuICAnYmVnaW5uZXInOidcXHVkODNkXFx1ZGQzMCcsXG4gICdiZWxsJzonXFx1ZDgzZFxcdWRkMTQnLFxuICAnYmVsbGhvcF9iZWxsJzonXFx1ZDgzZFxcdWRlY2UnLFxuICAnYmVudG8nOidcXHVkODNjXFx1ZGY3MScsXG4gICdiaWtpbmdfbWFuJzonXFx1ZDgzZFxcdWRlYjQnLFxuICAnYmlrZSc6J1xcdWQ4M2RcXHVkZWIyJyxcbiAgJ2Jpa2luZ193b21hbic6J1xcdWQ4M2RcXHVkZWI0Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdiaWtpbmknOidcXHVkODNkXFx1ZGM1OScsXG4gICdiaW9oYXphcmQnOidcXHUyNjIzXFx1ZmUwZicsXG4gICdiaXJkJzonXFx1ZDgzZFxcdWRjMjYnLFxuICAnYmlydGhkYXknOidcXHVkODNjXFx1ZGY4MicsXG4gICdibGFja19jaXJjbGUnOidcXHUyNmFiXFx1ZmUwZicsXG4gICdibGFja19mbGFnJzonXFx1ZDgzY1xcdWRmZjQnLFxuICAnYmxhY2tfaGVhcnQnOidcXHVkODNkXFx1ZGRhNCcsXG4gICdibGFja19qb2tlcic6J1xcdWQ4M2NcXHVkY2NmJyxcbiAgJ2JsYWNrX2xhcmdlX3NxdWFyZSc6J1xcdTJiMWJcXHVmZTBmJyxcbiAgJ2JsYWNrX21lZGl1bV9zbWFsbF9zcXVhcmUnOidcXHUyNWZlXFx1ZmUwZicsXG4gICdibGFja19tZWRpdW1fc3F1YXJlJzonXFx1MjVmY1xcdWZlMGYnLFxuICAnYmxhY2tfbmliJzonXFx1MjcxMlxcdWZlMGYnLFxuICAnYmxhY2tfc21hbGxfc3F1YXJlJzonXFx1MjVhYVxcdWZlMGYnLFxuICAnYmxhY2tfc3F1YXJlX2J1dHRvbic6J1xcdWQ4M2RcXHVkZDMyJyxcbiAgJ2Jsb25kZV9tYW4nOidcXHVkODNkXFx1ZGM3MScsXG4gICdibG9uZGVfd29tYW4nOidcXHVkODNkXFx1ZGM3MSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnYmxvc3NvbSc6J1xcdWQ4M2NcXHVkZjNjJyxcbiAgJ2Jsb3dmaXNoJzonXFx1ZDgzZFxcdWRjMjEnLFxuICAnYmx1ZV9ib29rJzonXFx1ZDgzZFxcdWRjZDgnLFxuICAnYmx1ZV9jYXInOidcXHVkODNkXFx1ZGU5OScsXG4gICdibHVlX2hlYXJ0JzonXFx1ZDgzZFxcdWRjOTknLFxuICAnYmx1c2gnOidcXHVkODNkXFx1ZGUwYScsXG4gICdib2FyJzonXFx1ZDgzZFxcdWRjMTcnLFxuICAnYm9hdCc6J1xcdTI2ZjVcXHVmZTBmJyxcbiAgJ2JvbWInOidcXHVkODNkXFx1ZGNhMycsXG4gICdib29rJzonXFx1ZDgzZFxcdWRjZDYnLFxuICAnYm9va21hcmsnOidcXHVkODNkXFx1ZGQxNicsXG4gICdib29rbWFya190YWJzJzonXFx1ZDgzZFxcdWRjZDEnLFxuICAnYm9va3MnOidcXHVkODNkXFx1ZGNkYScsXG4gICdib29tJzonXFx1ZDgzZFxcdWRjYTUnLFxuICAnYm9vdCc6J1xcdWQ4M2RcXHVkYzYyJyxcbiAgJ2JvdXF1ZXQnOidcXHVkODNkXFx1ZGM5MCcsXG4gICdib3dpbmdfbWFuJzonXFx1ZDgzZFxcdWRlNDcnLFxuICAnYm93X2FuZF9hcnJvdyc6J1xcdWQ4M2NcXHVkZmY5JyxcbiAgJ2Jvd2luZ193b21hbic6J1xcdWQ4M2RcXHVkZTQ3Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdib3dsaW5nJzonXFx1ZDgzY1xcdWRmYjMnLFxuICAnYm94aW5nX2dsb3ZlJzonXFx1ZDgzZVxcdWRkNGEnLFxuICAnYm95JzonXFx1ZDgzZFxcdWRjNjYnLFxuICAnYnJlYWQnOidcXHVkODNjXFx1ZGY1ZScsXG4gICdicmlkZV93aXRoX3ZlaWwnOidcXHVkODNkXFx1ZGM3MCcsXG4gICdicmlkZ2VfYXRfbmlnaHQnOidcXHVkODNjXFx1ZGYwOScsXG4gICdicmllZmNhc2UnOidcXHVkODNkXFx1ZGNiYycsXG4gICdicm9rZW5faGVhcnQnOidcXHVkODNkXFx1ZGM5NCcsXG4gICdidWcnOidcXHVkODNkXFx1ZGMxYicsXG4gICdidWlsZGluZ19jb25zdHJ1Y3Rpb24nOidcXHVkODNjXFx1ZGZkNycsXG4gICdidWxiJzonXFx1ZDgzZFxcdWRjYTEnLFxuICAnYnVsbGV0dHJhaW5fZnJvbnQnOidcXHVkODNkXFx1ZGU4NScsXG4gICdidWxsZXR0cmFpbl9zaWRlJzonXFx1ZDgzZFxcdWRlODQnLFxuICAnYnVycml0byc6J1xcdWQ4M2NcXHVkZjJmJyxcbiAgJ2J1cyc6J1xcdWQ4M2RcXHVkZThjJyxcbiAgJ2J1c2luZXNzX3N1aXRfbGV2aXRhdGluZyc6J1xcdWQ4M2RcXHVkZDc0JyxcbiAgJ2J1c3N0b3AnOidcXHVkODNkXFx1ZGU4ZicsXG4gICdidXN0X2luX3NpbGhvdWV0dGUnOidcXHVkODNkXFx1ZGM2NCcsXG4gICdidXN0c19pbl9zaWxob3VldHRlJzonXFx1ZDgzZFxcdWRjNjUnLFxuICAnYnV0dGVyZmx5JzonXFx1ZDgzZVxcdWRkOGInLFxuICAnY2FjdHVzJzonXFx1ZDgzY1xcdWRmMzUnLFxuICAnY2FrZSc6J1xcdWQ4M2NcXHVkZjcwJyxcbiAgJ2NhbGVuZGFyJzonXFx1ZDgzZFxcdWRjYzYnLFxuICAnY2FsbF9tZV9oYW5kJzonXFx1ZDgzZVxcdWRkMTknLFxuICAnY2FsbGluZyc6J1xcdWQ4M2RcXHVkY2YyJyxcbiAgJ2NhbWVsJzonXFx1ZDgzZFxcdWRjMmInLFxuICAnY2FtZXJhJzonXFx1ZDgzZFxcdWRjZjcnLFxuICAnY2FtZXJhX2ZsYXNoJzonXFx1ZDgzZFxcdWRjZjgnLFxuICAnY2FtcGluZyc6J1xcdWQ4M2NcXHVkZmQ1JyxcbiAgJ2NhbmNlcic6J1xcdTI2NGJcXHVmZTBmJyxcbiAgJ2NhbmRsZSc6J1xcdWQ4M2RcXHVkZDZmJyxcbiAgJ2NhbmR5JzonXFx1ZDgzY1xcdWRmNmMnLFxuICAnY2Fub2UnOidcXHVkODNkXFx1ZGVmNicsXG4gICdjYXBpdGFsX2FiY2QnOidcXHVkODNkXFx1ZGQyMCcsXG4gICdjYXByaWNvcm4nOidcXHUyNjUxXFx1ZmUwZicsXG4gICdjYXInOidcXHVkODNkXFx1ZGU5NycsXG4gICdjYXJkX2ZpbGVfYm94JzonXFx1ZDgzZFxcdWRkYzMnLFxuICAnY2FyZF9pbmRleCc6J1xcdWQ4M2RcXHVkY2M3JyxcbiAgJ2NhcmRfaW5kZXhfZGl2aWRlcnMnOidcXHVkODNkXFx1ZGRjMicsXG4gICdjYXJvdXNlbF9ob3JzZSc6J1xcdWQ4M2NcXHVkZmEwJyxcbiAgJ2NhcnJvdCc6J1xcdWQ4M2VcXHVkZDU1JyxcbiAgJ2NhdCc6J1xcdWQ4M2RcXHVkYzMxJyxcbiAgJ2NhdDInOidcXHVkODNkXFx1ZGMwOCcsXG4gICdjZCc6J1xcdWQ4M2RcXHVkY2JmJyxcbiAgJ2NoYWlucyc6J1xcdTI2ZDMnLFxuICAnY2hhbXBhZ25lJzonXFx1ZDgzY1xcdWRmN2UnLFxuICAnY2hhcnQnOidcXHVkODNkXFx1ZGNiOScsXG4gICdjaGFydF93aXRoX2Rvd253YXJkc190cmVuZCc6J1xcdWQ4M2RcXHVkY2M5JyxcbiAgJ2NoYXJ0X3dpdGhfdXB3YXJkc190cmVuZCc6J1xcdWQ4M2RcXHVkY2M4JyxcbiAgJ2NoZWNrZXJlZF9mbGFnJzonXFx1ZDgzY1xcdWRmYzEnLFxuICAnY2hlZXNlJzonXFx1ZDgzZVxcdWRkYzAnLFxuICAnY2hlcnJpZXMnOidcXHVkODNjXFx1ZGY1MicsXG4gICdjaGVycnlfYmxvc3NvbSc6J1xcdWQ4M2NcXHVkZjM4JyxcbiAgJ2NoZXN0bnV0JzonXFx1ZDgzY1xcdWRmMzAnLFxuICAnY2hpY2tlbic6J1xcdWQ4M2RcXHVkYzE0JyxcbiAgJ2NoaWxkcmVuX2Nyb3NzaW5nJzonXFx1ZDgzZFxcdWRlYjgnLFxuICAnY2hpcG11bmsnOidcXHVkODNkXFx1ZGMzZicsXG4gICdjaG9jb2xhdGVfYmFyJzonXFx1ZDgzY1xcdWRmNmInLFxuICAnY2hyaXN0bWFzX3RyZWUnOidcXHVkODNjXFx1ZGY4NCcsXG4gICdjaHVyY2gnOidcXHUyNmVhXFx1ZmUwZicsXG4gICdjaW5lbWEnOidcXHVkODNjXFx1ZGZhNicsXG4gICdjaXJjdXNfdGVudCc6J1xcdWQ4M2NcXHVkZmFhJyxcbiAgJ2NpdHlfc3VucmlzZSc6J1xcdWQ4M2NcXHVkZjA3JyxcbiAgJ2NpdHlfc3Vuc2V0JzonXFx1ZDgzY1xcdWRmMDYnLFxuICAnY2l0eXNjYXBlJzonXFx1ZDgzY1xcdWRmZDknLFxuICAnY2wnOidcXHVkODNjXFx1ZGQ5MScsXG4gICdjbGFtcCc6J1xcdWQ4M2RcXHVkZGRjJyxcbiAgJ2NsYXAnOidcXHVkODNkXFx1ZGM0ZicsXG4gICdjbGFwcGVyJzonXFx1ZDgzY1xcdWRmYWMnLFxuICAnY2xhc3NpY2FsX2J1aWxkaW5nJzonXFx1ZDgzY1xcdWRmZGInLFxuICAnY2xpbmtpbmdfZ2xhc3Nlcyc6J1xcdWQ4M2VcXHVkZDQyJyxcbiAgJ2NsaXBib2FyZCc6J1xcdWQ4M2RcXHVkY2NiJyxcbiAgJ2Nsb2NrMSc6J1xcdWQ4M2RcXHVkZDUwJyxcbiAgJ2Nsb2NrMTAnOidcXHVkODNkXFx1ZGQ1OScsXG4gICdjbG9jazEwMzAnOidcXHVkODNkXFx1ZGQ2NScsXG4gICdjbG9jazExJzonXFx1ZDgzZFxcdWRkNWEnLFxuICAnY2xvY2sxMTMwJzonXFx1ZDgzZFxcdWRkNjYnLFxuICAnY2xvY2sxMic6J1xcdWQ4M2RcXHVkZDViJyxcbiAgJ2Nsb2NrMTIzMCc6J1xcdWQ4M2RcXHVkZDY3JyxcbiAgJ2Nsb2NrMTMwJzonXFx1ZDgzZFxcdWRkNWMnLFxuICAnY2xvY2syJzonXFx1ZDgzZFxcdWRkNTEnLFxuICAnY2xvY2syMzAnOidcXHVkODNkXFx1ZGQ1ZCcsXG4gICdjbG9jazMnOidcXHVkODNkXFx1ZGQ1MicsXG4gICdjbG9jazMzMCc6J1xcdWQ4M2RcXHVkZDVlJyxcbiAgJ2Nsb2NrNCc6J1xcdWQ4M2RcXHVkZDUzJyxcbiAgJ2Nsb2NrNDMwJzonXFx1ZDgzZFxcdWRkNWYnLFxuICAnY2xvY2s1JzonXFx1ZDgzZFxcdWRkNTQnLFxuICAnY2xvY2s1MzAnOidcXHVkODNkXFx1ZGQ2MCcsXG4gICdjbG9jazYnOidcXHVkODNkXFx1ZGQ1NScsXG4gICdjbG9jazYzMCc6J1xcdWQ4M2RcXHVkZDYxJyxcbiAgJ2Nsb2NrNyc6J1xcdWQ4M2RcXHVkZDU2JyxcbiAgJ2Nsb2NrNzMwJzonXFx1ZDgzZFxcdWRkNjInLFxuICAnY2xvY2s4JzonXFx1ZDgzZFxcdWRkNTcnLFxuICAnY2xvY2s4MzAnOidcXHVkODNkXFx1ZGQ2MycsXG4gICdjbG9jazknOidcXHVkODNkXFx1ZGQ1OCcsXG4gICdjbG9jazkzMCc6J1xcdWQ4M2RcXHVkZDY0JyxcbiAgJ2Nsb3NlZF9ib29rJzonXFx1ZDgzZFxcdWRjZDUnLFxuICAnY2xvc2VkX2xvY2tfd2l0aF9rZXknOidcXHVkODNkXFx1ZGQxMCcsXG4gICdjbG9zZWRfdW1icmVsbGEnOidcXHVkODNjXFx1ZGYwMicsXG4gICdjbG91ZCc6J1xcdTI2MDFcXHVmZTBmJyxcbiAgJ2Nsb3VkX3dpdGhfbGlnaHRuaW5nJzonXFx1ZDgzY1xcdWRmMjknLFxuICAnY2xvdWRfd2l0aF9saWdodG5pbmdfYW5kX3JhaW4nOidcXHUyNmM4JyxcbiAgJ2Nsb3VkX3dpdGhfcmFpbic6J1xcdWQ4M2NcXHVkZjI3JyxcbiAgJ2Nsb3VkX3dpdGhfc25vdyc6J1xcdWQ4M2NcXHVkZjI4JyxcbiAgJ2Nsb3duX2ZhY2UnOidcXHVkODNlXFx1ZGQyMScsXG4gICdjbHVicyc6J1xcdTI2NjNcXHVmZTBmJyxcbiAgJ2NvY2t0YWlsJzonXFx1ZDgzY1xcdWRmNzgnLFxuICAnY29mZmVlJzonXFx1MjYxNVxcdWZlMGYnLFxuICAnY29mZmluJzonXFx1MjZiMFxcdWZlMGYnLFxuICAnY29sZF9zd2VhdCc6J1xcdWQ4M2RcXHVkZTMwJyxcbiAgJ2NvbWV0JzonXFx1MjYwNFxcdWZlMGYnLFxuICAnY29tcHV0ZXInOidcXHVkODNkXFx1ZGNiYicsXG4gICdjb21wdXRlcl9tb3VzZSc6J1xcdWQ4M2RcXHVkZGIxJyxcbiAgJ2NvbmZldHRpX2JhbGwnOidcXHVkODNjXFx1ZGY4YScsXG4gICdjb25mb3VuZGVkJzonXFx1ZDgzZFxcdWRlMTYnLFxuICAnY29uZnVzZWQnOidcXHVkODNkXFx1ZGUxNScsXG4gICdjb25ncmF0dWxhdGlvbnMnOidcXHUzMjk3XFx1ZmUwZicsXG4gICdjb25zdHJ1Y3Rpb24nOidcXHVkODNkXFx1ZGVhNycsXG4gICdjb25zdHJ1Y3Rpb25fd29ya2VyX21hbic6J1xcdWQ4M2RcXHVkYzc3JyxcbiAgJ2NvbnN0cnVjdGlvbl93b3JrZXJfd29tYW4nOidcXHVkODNkXFx1ZGM3NyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnY29udHJvbF9rbm9icyc6J1xcdWQ4M2NcXHVkZjliJyxcbiAgJ2NvbnZlbmllbmNlX3N0b3JlJzonXFx1ZDgzY1xcdWRmZWEnLFxuICAnY29va2llJzonXFx1ZDgzY1xcdWRmNmEnLFxuICAnY29vbCc6J1xcdWQ4M2NcXHVkZDkyJyxcbiAgJ3BvbGljZW1hbic6J1xcdWQ4M2RcXHVkYzZlJyxcbiAgJ2NvcHlyaWdodCc6J1xcdTAwYTlcXHVmZTBmJyxcbiAgJ2Nvcm4nOidcXHVkODNjXFx1ZGYzZCcsXG4gICdjb3VjaF9hbmRfbGFtcCc6J1xcdWQ4M2RcXHVkZWNiJyxcbiAgJ2NvdXBsZSc6J1xcdWQ4M2RcXHVkYzZiJyxcbiAgJ2NvdXBsZV93aXRoX2hlYXJ0X3dvbWFuX21hbic6J1xcdWQ4M2RcXHVkYzkxJyxcbiAgJ2NvdXBsZV93aXRoX2hlYXJ0X21hbl9tYW4nOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1Mjc2NFxcdWZlMGYmendqO1xcdWQ4M2RcXHVkYzY4JyxcbiAgJ2NvdXBsZV93aXRoX2hlYXJ0X3dvbWFuX3dvbWFuJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdTI3NjRcXHVmZTBmJnp3ajtcXHVkODNkXFx1ZGM2OScsXG4gICdjb3VwbGVraXNzX21hbl9tYW4nOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1Mjc2NFxcdWZlMGYmendqO1xcdWQ4M2RcXHVkYzhiJnp3ajtcXHVkODNkXFx1ZGM2OCcsXG4gICdjb3VwbGVraXNzX21hbl93b21hbic6J1xcdWQ4M2RcXHVkYzhmJyxcbiAgJ2NvdXBsZWtpc3Nfd29tYW5fd29tYW4nOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1Mjc2NFxcdWZlMGYmendqO1xcdWQ4M2RcXHVkYzhiJnp3ajtcXHVkODNkXFx1ZGM2OScsXG4gICdjb3cnOidcXHVkODNkXFx1ZGMyZScsXG4gICdjb3cyJzonXFx1ZDgzZFxcdWRjMDQnLFxuICAnY293Ym95X2hhdF9mYWNlJzonXFx1ZDgzZVxcdWRkMjAnLFxuICAnY3JhYic6J1xcdWQ4M2VcXHVkZDgwJyxcbiAgJ2NyYXlvbic6J1xcdWQ4M2RcXHVkZDhkJyxcbiAgJ2NyZWRpdF9jYXJkJzonXFx1ZDgzZFxcdWRjYjMnLFxuICAnY3Jlc2NlbnRfbW9vbic6J1xcdWQ4M2NcXHVkZjE5JyxcbiAgJ2NyaWNrZXQnOidcXHVkODNjXFx1ZGZjZicsXG4gICdjcm9jb2RpbGUnOidcXHVkODNkXFx1ZGMwYScsXG4gICdjcm9pc3NhbnQnOidcXHVkODNlXFx1ZGQ1MCcsXG4gICdjcm9zc2VkX2ZpbmdlcnMnOidcXHVkODNlXFx1ZGQxZScsXG4gICdjcm9zc2VkX2ZsYWdzJzonXFx1ZDgzY1xcdWRmOGMnLFxuICAnY3Jvc3NlZF9zd29yZHMnOidcXHUyNjk0XFx1ZmUwZicsXG4gICdjcm93bic6J1xcdWQ4M2RcXHVkYzUxJyxcbiAgJ2NyeSc6J1xcdWQ4M2RcXHVkZTIyJyxcbiAgJ2NyeWluZ19jYXRfZmFjZSc6J1xcdWQ4M2RcXHVkZTNmJyxcbiAgJ2NyeXN0YWxfYmFsbCc6J1xcdWQ4M2RcXHVkZDJlJyxcbiAgJ2N1Y3VtYmVyJzonXFx1ZDgzZVxcdWRkNTInLFxuICAnY3VwaWQnOidcXHVkODNkXFx1ZGM5OCcsXG4gICdjdXJseV9sb29wJzonXFx1MjdiMCcsXG4gICdjdXJyZW5jeV9leGNoYW5nZSc6J1xcdWQ4M2RcXHVkY2IxJyxcbiAgJ2N1cnJ5JzonXFx1ZDgzY1xcdWRmNWInLFxuICAnY3VzdGFyZCc6J1xcdWQ4M2NcXHVkZjZlJyxcbiAgJ2N1c3RvbXMnOidcXHVkODNkXFx1ZGVjMycsXG4gICdjeWNsb25lJzonXFx1ZDgzY1xcdWRmMDAnLFxuICAnZGFnZ2VyJzonXFx1ZDgzZFxcdWRkZTEnLFxuICAnZGFuY2VyJzonXFx1ZDgzZFxcdWRjODMnLFxuICAnZGFuY2luZ193b21lbic6J1xcdWQ4M2RcXHVkYzZmJyxcbiAgJ2RhbmNpbmdfbWVuJzonXFx1ZDgzZFxcdWRjNmYmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ2RhbmdvJzonXFx1ZDgzY1xcdWRmNjEnLFxuICAnZGFya19zdW5nbGFzc2VzJzonXFx1ZDgzZFxcdWRkNzYnLFxuICAnZGFydCc6J1xcdWQ4M2NcXHVkZmFmJyxcbiAgJ2Rhc2gnOidcXHVkODNkXFx1ZGNhOCcsXG4gICdkYXRlJzonXFx1ZDgzZFxcdWRjYzUnLFxuICAnZGVjaWR1b3VzX3RyZWUnOidcXHVkODNjXFx1ZGYzMycsXG4gICdkZWVyJzonXFx1ZDgzZVxcdWRkOGMnLFxuICAnZGVwYXJ0bWVudF9zdG9yZSc6J1xcdWQ4M2NcXHVkZmVjJyxcbiAgJ2RlcmVsaWN0X2hvdXNlJzonXFx1ZDgzY1xcdWRmZGEnLFxuICAnZGVzZXJ0JzonXFx1ZDgzY1xcdWRmZGMnLFxuICAnZGVzZXJ0X2lzbGFuZCc6J1xcdWQ4M2NcXHVkZmRkJyxcbiAgJ2Rlc2t0b3BfY29tcHV0ZXInOidcXHVkODNkXFx1ZGRhNScsXG4gICdtYWxlX2RldGVjdGl2ZSc6J1xcdWQ4M2RcXHVkZDc1XFx1ZmUwZicsXG4gICdkaWFtb25kX3NoYXBlX3dpdGhfYV9kb3RfaW5zaWRlJzonXFx1ZDgzZFxcdWRjYTAnLFxuICAnZGlhbW9uZHMnOidcXHUyNjY2XFx1ZmUwZicsXG4gICdkaXNhcHBvaW50ZWQnOidcXHVkODNkXFx1ZGUxZScsXG4gICdkaXNhcHBvaW50ZWRfcmVsaWV2ZWQnOidcXHVkODNkXFx1ZGUyNScsXG4gICdkaXp6eSc6J1xcdWQ4M2RcXHVkY2FiJyxcbiAgJ2Rpenp5X2ZhY2UnOidcXHVkODNkXFx1ZGUzNScsXG4gICdkb19ub3RfbGl0dGVyJzonXFx1ZDgzZFxcdWRlYWYnLFxuICAnZG9nJzonXFx1ZDgzZFxcdWRjMzYnLFxuICAnZG9nMic6J1xcdWQ4M2RcXHVkYzE1JyxcbiAgJ2RvbGxhcic6J1xcdWQ4M2RcXHVkY2I1JyxcbiAgJ2RvbGxzJzonXFx1ZDgzY1xcdWRmOGUnLFxuICAnZG9scGhpbic6J1xcdWQ4M2RcXHVkYzJjJyxcbiAgJ2Rvb3InOidcXHVkODNkXFx1ZGVhYScsXG4gICdkb3VnaG51dCc6J1xcdWQ4M2NcXHVkZjY5JyxcbiAgJ2RvdmUnOidcXHVkODNkXFx1ZGQ0YScsXG4gICdkcmFnb24nOidcXHVkODNkXFx1ZGMwOScsXG4gICdkcmFnb25fZmFjZSc6J1xcdWQ4M2RcXHVkYzMyJyxcbiAgJ2RyZXNzJzonXFx1ZDgzZFxcdWRjNTcnLFxuICAnZHJvbWVkYXJ5X2NhbWVsJzonXFx1ZDgzZFxcdWRjMmEnLFxuICAnZHJvb2xpbmdfZmFjZSc6J1xcdWQ4M2VcXHVkZDI0JyxcbiAgJ2Ryb3BsZXQnOidcXHVkODNkXFx1ZGNhNycsXG4gICdkcnVtJzonXFx1ZDgzZVxcdWRkNDEnLFxuICAnZHVjayc6J1xcdWQ4M2VcXHVkZDg2JyxcbiAgJ2R2ZCc6J1xcdWQ4M2RcXHVkY2MwJyxcbiAgJ2UtbWFpbCc6J1xcdWQ4M2RcXHVkY2U3JyxcbiAgJ2VhZ2xlJzonXFx1ZDgzZVxcdWRkODUnLFxuICAnZWFyJzonXFx1ZDgzZFxcdWRjNDInLFxuICAnZWFyX29mX3JpY2UnOidcXHVkODNjXFx1ZGYzZScsXG4gICdlYXJ0aF9hZnJpY2EnOidcXHVkODNjXFx1ZGYwZCcsXG4gICdlYXJ0aF9hbWVyaWNhcyc6J1xcdWQ4M2NcXHVkZjBlJyxcbiAgJ2VhcnRoX2FzaWEnOidcXHVkODNjXFx1ZGYwZicsXG4gICdlZ2cnOidcXHVkODNlXFx1ZGQ1YScsXG4gICdlZ2dwbGFudCc6J1xcdWQ4M2NcXHVkZjQ2JyxcbiAgJ2VpZ2h0X3BvaW50ZWRfYmxhY2tfc3Rhcic6J1xcdTI3MzRcXHVmZTBmJyxcbiAgJ2VpZ2h0X3Nwb2tlZF9hc3Rlcmlzayc6J1xcdTI3MzNcXHVmZTBmJyxcbiAgJ2VsZWN0cmljX3BsdWcnOidcXHVkODNkXFx1ZGQwYycsXG4gICdlbGVwaGFudCc6J1xcdWQ4M2RcXHVkYzE4JyxcbiAgJ2VtYWlsJzonXFx1MjcwOVxcdWZlMGYnLFxuICAnZW5kJzonXFx1ZDgzZFxcdWRkMWEnLFxuICAnZW52ZWxvcGVfd2l0aF9hcnJvdyc6J1xcdWQ4M2RcXHVkY2U5JyxcbiAgJ2V1cm8nOidcXHVkODNkXFx1ZGNiNicsXG4gICdldXJvcGVhbl9jYXN0bGUnOidcXHVkODNjXFx1ZGZmMCcsXG4gICdldXJvcGVhbl9wb3N0X29mZmljZSc6J1xcdWQ4M2NcXHVkZmU0JyxcbiAgJ2V2ZXJncmVlbl90cmVlJzonXFx1ZDgzY1xcdWRmMzInLFxuICAnZXhjbGFtYXRpb24nOidcXHUyNzU3XFx1ZmUwZicsXG4gICdleHByZXNzaW9ubGVzcyc6J1xcdWQ4M2RcXHVkZTExJyxcbiAgJ2V5ZSc6J1xcdWQ4M2RcXHVkYzQxJyxcbiAgJ2V5ZV9zcGVlY2hfYnViYmxlJzonXFx1ZDgzZFxcdWRjNDEmendqO1xcdWQ4M2RcXHVkZGU4JyxcbiAgJ2V5ZWdsYXNzZXMnOidcXHVkODNkXFx1ZGM1MycsXG4gICdleWVzJzonXFx1ZDgzZFxcdWRjNDAnLFxuICAnZmFjZV93aXRoX2hlYWRfYmFuZGFnZSc6J1xcdWQ4M2VcXHVkZDE1JyxcbiAgJ2ZhY2Vfd2l0aF90aGVybW9tZXRlcic6J1xcdWQ4M2VcXHVkZDEyJyxcbiAgJ2Zpc3Rfb25jb21pbmcnOidcXHVkODNkXFx1ZGM0YScsXG4gICdmYWN0b3J5JzonXFx1ZDgzY1xcdWRmZWQnLFxuICAnZmFsbGVuX2xlYWYnOidcXHVkODNjXFx1ZGY0MicsXG4gICdmYW1pbHlfbWFuX3dvbWFuX2JveSc6J1xcdWQ4M2RcXHVkYzZhJyxcbiAgJ2ZhbWlseV9tYW5fYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fYm95X2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NiZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl9naXJsJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV9tYW5fZ2lybF9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fZ2lybF9naXJsJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfbWFuX21hbl9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY2Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX21hbl9naXJsJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfbWFuX21hbl9naXJsX2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV9tYW5fd29tYW5fYm95X2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjYmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fd29tYW5fZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X21hbl93b21hbl9naXJsX2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fd29tYW5fZ2lybF9naXJsJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X3dvbWFuX2JveSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfd29tYW5fYm95X2JveSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NiZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX2dpcmwnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X3dvbWFuX2dpcmxfYm95JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfd29tYW5fZ2lybF9naXJsJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfd29tYW5fd29tYW5fYm95JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfd29tYW5fd29tYW5fYm95X2JveSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjYmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV93b21hbl93b21hbl9naXJsJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfd29tYW5fd29tYW5fZ2lybF9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfd29tYW5fd29tYW5fZ2lybF9naXJsJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFzdF9mb3J3YXJkJzonXFx1MjNlOScsXG4gICdmYXgnOidcXHVkODNkXFx1ZGNlMCcsXG4gICdmZWFyZnVsJzonXFx1ZDgzZFxcdWRlMjgnLFxuICAnZmVldCc6J1xcdWQ4M2RcXHVkYzNlJyxcbiAgJ2ZlbWFsZV9kZXRlY3RpdmUnOidcXHVkODNkXFx1ZGQ3NVxcdWZlMGYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2ZlcnJpc193aGVlbCc6J1xcdWQ4M2NcXHVkZmExJyxcbiAgJ2ZlcnJ5JzonXFx1MjZmNCcsXG4gICdmaWVsZF9ob2NrZXknOidcXHVkODNjXFx1ZGZkMScsXG4gICdmaWxlX2NhYmluZXQnOidcXHVkODNkXFx1ZGRjNCcsXG4gICdmaWxlX2ZvbGRlcic6J1xcdWQ4M2RcXHVkY2MxJyxcbiAgJ2ZpbG1fcHJvamVjdG9yJzonXFx1ZDgzZFxcdWRjZmQnLFxuICAnZmlsbV9zdHJpcCc6J1xcdWQ4M2NcXHVkZjllJyxcbiAgJ2ZpcmUnOidcXHVkODNkXFx1ZGQyNScsXG4gICdmaXJlX2VuZ2luZSc6J1xcdWQ4M2RcXHVkZTkyJyxcbiAgJ2ZpcmV3b3Jrcyc6J1xcdWQ4M2NcXHVkZjg2JyxcbiAgJ2ZpcnN0X3F1YXJ0ZXJfbW9vbic6J1xcdWQ4M2NcXHVkZjEzJyxcbiAgJ2ZpcnN0X3F1YXJ0ZXJfbW9vbl93aXRoX2ZhY2UnOidcXHVkODNjXFx1ZGYxYicsXG4gICdmaXNoJzonXFx1ZDgzZFxcdWRjMWYnLFxuICAnZmlzaF9jYWtlJzonXFx1ZDgzY1xcdWRmNjUnLFxuICAnZmlzaGluZ19wb2xlX2FuZF9maXNoJzonXFx1ZDgzY1xcdWRmYTMnLFxuICAnZmlzdF9yYWlzZWQnOidcXHUyNzBhJyxcbiAgJ2Zpc3RfbGVmdCc6J1xcdWQ4M2VcXHVkZDFiJyxcbiAgJ2Zpc3RfcmlnaHQnOidcXHVkODNlXFx1ZGQxYycsXG4gICdmbGFncyc6J1xcdWQ4M2NcXHVkZjhmJyxcbiAgJ2ZsYXNobGlnaHQnOidcXHVkODNkXFx1ZGQyNicsXG4gICdmbGV1cl9kZV9saXMnOidcXHUyNjljXFx1ZmUwZicsXG4gICdmbGlnaHRfYXJyaXZhbCc6J1xcdWQ4M2RcXHVkZWVjJyxcbiAgJ2ZsaWdodF9kZXBhcnR1cmUnOidcXHVkODNkXFx1ZGVlYicsXG4gICdmbG9wcHlfZGlzayc6J1xcdWQ4M2RcXHVkY2JlJyxcbiAgJ2Zsb3dlcl9wbGF5aW5nX2NhcmRzJzonXFx1ZDgzY1xcdWRmYjQnLFxuICAnZmx1c2hlZCc6J1xcdWQ4M2RcXHVkZTMzJyxcbiAgJ2ZvZyc6J1xcdWQ4M2NcXHVkZjJiJyxcbiAgJ2ZvZ2d5JzonXFx1ZDgzY1xcdWRmMDEnLFxuICAnZm9vdGJhbGwnOidcXHVkODNjXFx1ZGZjOCcsXG4gICdmb290cHJpbnRzJzonXFx1ZDgzZFxcdWRjNjMnLFxuICAnZm9ya19hbmRfa25pZmUnOidcXHVkODNjXFx1ZGY3NCcsXG4gICdmb3VudGFpbic6J1xcdTI2ZjJcXHVmZTBmJyxcbiAgJ2ZvdW50YWluX3Blbic6J1xcdWQ4M2RcXHVkZDhiJyxcbiAgJ2ZvdXJfbGVhZl9jbG92ZXInOidcXHVkODNjXFx1ZGY0MCcsXG4gICdmb3hfZmFjZSc6J1xcdWQ4M2VcXHVkZDhhJyxcbiAgJ2ZyYW1lZF9waWN0dXJlJzonXFx1ZDgzZFxcdWRkYmMnLFxuICAnZnJlZSc6J1xcdWQ4M2NcXHVkZDkzJyxcbiAgJ2ZyaWVkX2VnZyc6J1xcdWQ4M2NcXHVkZjczJyxcbiAgJ2ZyaWVkX3NocmltcCc6J1xcdWQ4M2NcXHVkZjY0JyxcbiAgJ2ZyaWVzJzonXFx1ZDgzY1xcdWRmNWYnLFxuICAnZnJvZyc6J1xcdWQ4M2RcXHVkYzM4JyxcbiAgJ2Zyb3duaW5nJzonXFx1ZDgzZFxcdWRlMjYnLFxuICAnZnJvd25pbmdfZmFjZSc6J1xcdTI2MzlcXHVmZTBmJyxcbiAgJ2Zyb3duaW5nX21hbic6J1xcdWQ4M2RcXHVkZTRkJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdmcm93bmluZ193b21hbic6J1xcdWQ4M2RcXHVkZTRkJyxcbiAgJ21pZGRsZV9maW5nZXInOidcXHVkODNkXFx1ZGQ5NScsXG4gICdmdWVscHVtcCc6J1xcdTI2ZmRcXHVmZTBmJyxcbiAgJ2Z1bGxfbW9vbic6J1xcdWQ4M2NcXHVkZjE1JyxcbiAgJ2Z1bGxfbW9vbl93aXRoX2ZhY2UnOidcXHVkODNjXFx1ZGYxZCcsXG4gICdmdW5lcmFsX3Vybic6J1xcdTI2YjFcXHVmZTBmJyxcbiAgJ2dhbWVfZGllJzonXFx1ZDgzY1xcdWRmYjInLFxuICAnZ2Vhcic6J1xcdTI2OTlcXHVmZTBmJyxcbiAgJ2dlbSc6J1xcdWQ4M2RcXHVkYzhlJyxcbiAgJ2dlbWluaSc6J1xcdTI2NGFcXHVmZTBmJyxcbiAgJ2dob3N0JzonXFx1ZDgzZFxcdWRjN2InLFxuICAnZ2lmdCc6J1xcdWQ4M2NcXHVkZjgxJyxcbiAgJ2dpZnRfaGVhcnQnOidcXHVkODNkXFx1ZGM5ZCcsXG4gICdnaXJsJzonXFx1ZDgzZFxcdWRjNjcnLFxuICAnZ2xvYmVfd2l0aF9tZXJpZGlhbnMnOidcXHVkODNjXFx1ZGYxMCcsXG4gICdnb2FsX25ldCc6J1xcdWQ4M2VcXHVkZDQ1JyxcbiAgJ2dvYXQnOidcXHVkODNkXFx1ZGMxMCcsXG4gICdnb2xmJzonXFx1MjZmM1xcdWZlMGYnLFxuICAnZ29sZmluZ19tYW4nOidcXHVkODNjXFx1ZGZjY1xcdWZlMGYnLFxuICAnZ29sZmluZ193b21hbic6J1xcdWQ4M2NcXHVkZmNjXFx1ZmUwZiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnZ29yaWxsYSc6J1xcdWQ4M2VcXHVkZDhkJyxcbiAgJ2dyYXBlcyc6J1xcdWQ4M2NcXHVkZjQ3JyxcbiAgJ2dyZWVuX2FwcGxlJzonXFx1ZDgzY1xcdWRmNGYnLFxuICAnZ3JlZW5fYm9vayc6J1xcdWQ4M2RcXHVkY2Q3JyxcbiAgJ2dyZWVuX2hlYXJ0JzonXFx1ZDgzZFxcdWRjOWEnLFxuICAnZ3JlZW5fc2FsYWQnOidcXHVkODNlXFx1ZGQ1NycsXG4gICdncmV5X2V4Y2xhbWF0aW9uJzonXFx1Mjc1NScsXG4gICdncmV5X3F1ZXN0aW9uJzonXFx1Mjc1NCcsXG4gICdncmltYWNpbmcnOidcXHVkODNkXFx1ZGUyYycsXG4gICdncmluJzonXFx1ZDgzZFxcdWRlMDEnLFxuICAnZ3Jpbm5pbmcnOidcXHVkODNkXFx1ZGUwMCcsXG4gICdndWFyZHNtYW4nOidcXHVkODNkXFx1ZGM4MicsXG4gICdndWFyZHN3b21hbic6J1xcdWQ4M2RcXHVkYzgyJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdndWl0YXInOidcXHVkODNjXFx1ZGZiOCcsXG4gICdndW4nOidcXHVkODNkXFx1ZGQyYicsXG4gICdoYWlyY3V0X3dvbWFuJzonXFx1ZDgzZFxcdWRjODcnLFxuICAnaGFpcmN1dF9tYW4nOidcXHVkODNkXFx1ZGM4NyZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnaGFtYnVyZ2VyJzonXFx1ZDgzY1xcdWRmNTQnLFxuICAnaGFtbWVyJzonXFx1ZDgzZFxcdWRkMjgnLFxuICAnaGFtbWVyX2FuZF9waWNrJzonXFx1MjY5MicsXG4gICdoYW1tZXJfYW5kX3dyZW5jaCc6J1xcdWQ4M2RcXHVkZWUwJyxcbiAgJ2hhbXN0ZXInOidcXHVkODNkXFx1ZGMzOScsXG4gICdoYW5kJzonXFx1MjcwYicsXG4gICdoYW5kYmFnJzonXFx1ZDgzZFxcdWRjNWMnLFxuICAnaGFuZHNoYWtlJzonXFx1ZDgzZVxcdWRkMWQnLFxuICAnaGFua2V5JzonXFx1ZDgzZFxcdWRjYTknLFxuICAnaGF0Y2hlZF9jaGljayc6J1xcdWQ4M2RcXHVkYzI1JyxcbiAgJ2hhdGNoaW5nX2NoaWNrJzonXFx1ZDgzZFxcdWRjMjMnLFxuICAnaGVhZHBob25lcyc6J1xcdWQ4M2NcXHVkZmE3JyxcbiAgJ2hlYXJfbm9fZXZpbCc6J1xcdWQ4M2RcXHVkZTQ5JyxcbiAgJ2hlYXJ0JzonXFx1Mjc2NFxcdWZlMGYnLFxuICAnaGVhcnRfZGVjb3JhdGlvbic6J1xcdWQ4M2RcXHVkYzlmJyxcbiAgJ2hlYXJ0X2V5ZXMnOidcXHVkODNkXFx1ZGUwZCcsXG4gICdoZWFydF9leWVzX2NhdCc6J1xcdWQ4M2RcXHVkZTNiJyxcbiAgJ2hlYXJ0YmVhdCc6J1xcdWQ4M2RcXHVkYzkzJyxcbiAgJ2hlYXJ0cHVsc2UnOidcXHVkODNkXFx1ZGM5NycsXG4gICdoZWFydHMnOidcXHUyNjY1XFx1ZmUwZicsXG4gICdoZWF2eV9jaGVja19tYXJrJzonXFx1MjcxNFxcdWZlMGYnLFxuICAnaGVhdnlfZGl2aXNpb25fc2lnbic6J1xcdTI3OTcnLFxuICAnaGVhdnlfZG9sbGFyX3NpZ24nOidcXHVkODNkXFx1ZGNiMicsXG4gICdoZWF2eV9oZWFydF9leGNsYW1hdGlvbic6J1xcdTI3NjNcXHVmZTBmJyxcbiAgJ2hlYXZ5X21pbnVzX3NpZ24nOidcXHUyNzk2JyxcbiAgJ2hlYXZ5X211bHRpcGxpY2F0aW9uX3gnOidcXHUyNzE2XFx1ZmUwZicsXG4gICdoZWF2eV9wbHVzX3NpZ24nOidcXHUyNzk1JyxcbiAgJ2hlbGljb3B0ZXInOidcXHVkODNkXFx1ZGU4MScsXG4gICdoZXJiJzonXFx1ZDgzY1xcdWRmM2YnLFxuICAnaGliaXNjdXMnOidcXHVkODNjXFx1ZGYzYScsXG4gICdoaWdoX2JyaWdodG5lc3MnOidcXHVkODNkXFx1ZGQwNicsXG4gICdoaWdoX2hlZWwnOidcXHVkODNkXFx1ZGM2MCcsXG4gICdob2Nobyc6J1xcdWQ4M2RcXHVkZDJhJyxcbiAgJ2hvbGUnOidcXHVkODNkXFx1ZGQ3MycsXG4gICdob25leV9wb3QnOidcXHVkODNjXFx1ZGY2ZicsXG4gICdob3JzZSc6J1xcdWQ4M2RcXHVkYzM0JyxcbiAgJ2hvcnNlX3JhY2luZyc6J1xcdWQ4M2NcXHVkZmM3JyxcbiAgJ2hvc3BpdGFsJzonXFx1ZDgzY1xcdWRmZTUnLFxuICAnaG90X3BlcHBlcic6J1xcdWQ4M2NcXHVkZjM2JyxcbiAgJ2hvdGRvZyc6J1xcdWQ4M2NcXHVkZjJkJyxcbiAgJ2hvdGVsJzonXFx1ZDgzY1xcdWRmZTgnLFxuICAnaG90c3ByaW5ncyc6J1xcdTI2NjhcXHVmZTBmJyxcbiAgJ2hvdXJnbGFzcyc6J1xcdTIzMWJcXHVmZTBmJyxcbiAgJ2hvdXJnbGFzc19mbG93aW5nX3NhbmQnOidcXHUyM2YzJyxcbiAgJ2hvdXNlJzonXFx1ZDgzY1xcdWRmZTAnLFxuICAnaG91c2Vfd2l0aF9nYXJkZW4nOidcXHVkODNjXFx1ZGZlMScsXG4gICdob3VzZXMnOidcXHVkODNjXFx1ZGZkOCcsXG4gICdodWdzJzonXFx1ZDgzZVxcdWRkMTcnLFxuICAnaHVzaGVkJzonXFx1ZDgzZFxcdWRlMmYnLFxuICAnaWNlX2NyZWFtJzonXFx1ZDgzY1xcdWRmNjgnLFxuICAnaWNlX2hvY2tleSc6J1xcdWQ4M2NcXHVkZmQyJyxcbiAgJ2ljZV9za2F0ZSc6J1xcdTI2ZjgnLFxuICAnaWNlY3JlYW0nOidcXHVkODNjXFx1ZGY2NicsXG4gICdpZCc6J1xcdWQ4M2NcXHVkZDk0JyxcbiAgJ2lkZW9ncmFwaF9hZHZhbnRhZ2UnOidcXHVkODNjXFx1ZGU1MCcsXG4gICdpbXAnOidcXHVkODNkXFx1ZGM3ZicsXG4gICdpbmJveF90cmF5JzonXFx1ZDgzZFxcdWRjZTUnLFxuICAnaW5jb21pbmdfZW52ZWxvcGUnOidcXHVkODNkXFx1ZGNlOCcsXG4gICd0aXBwaW5nX2hhbmRfd29tYW4nOidcXHVkODNkXFx1ZGM4MScsXG4gICdpbmZvcm1hdGlvbl9zb3VyY2UnOidcXHUyMTM5XFx1ZmUwZicsXG4gICdpbm5vY2VudCc6J1xcdWQ4M2RcXHVkZTA3JyxcbiAgJ2ludGVycm9iYW5nJzonXFx1MjA0OVxcdWZlMGYnLFxuICAnaXBob25lJzonXFx1ZDgzZFxcdWRjZjEnLFxuICAnaXpha2F5YV9sYW50ZXJuJzonXFx1ZDgzY1xcdWRmZWUnLFxuICAnamFja19vX2xhbnRlcm4nOidcXHVkODNjXFx1ZGY4MycsXG4gICdqYXBhbic6J1xcdWQ4M2RcXHVkZGZlJyxcbiAgJ2phcGFuZXNlX2Nhc3RsZSc6J1xcdWQ4M2NcXHVkZmVmJyxcbiAgJ2phcGFuZXNlX2dvYmxpbic6J1xcdWQ4M2RcXHVkYzdhJyxcbiAgJ2phcGFuZXNlX29ncmUnOidcXHVkODNkXFx1ZGM3OScsXG4gICdqZWFucyc6J1xcdWQ4M2RcXHVkYzU2JyxcbiAgJ2pveSc6J1xcdWQ4M2RcXHVkZTAyJyxcbiAgJ2pveV9jYXQnOidcXHVkODNkXFx1ZGUzOScsXG4gICdqb3lzdGljayc6J1xcdWQ4M2RcXHVkZDc5JyxcbiAgJ2thYWJhJzonXFx1ZDgzZFxcdWRkNGInLFxuICAna2V5JzonXFx1ZDgzZFxcdWRkMTEnLFxuICAna2V5Ym9hcmQnOidcXHUyMzI4XFx1ZmUwZicsXG4gICdrZXljYXBfdGVuJzonXFx1ZDgzZFxcdWRkMWYnLFxuICAna2lja19zY29vdGVyJzonXFx1ZDgzZFxcdWRlZjQnLFxuICAna2ltb25vJzonXFx1ZDgzZFxcdWRjNTgnLFxuICAna2lzcyc6J1xcdWQ4M2RcXHVkYzhiJyxcbiAgJ2tpc3NpbmcnOidcXHVkODNkXFx1ZGUxNycsXG4gICdraXNzaW5nX2NhdCc6J1xcdWQ4M2RcXHVkZTNkJyxcbiAgJ2tpc3NpbmdfY2xvc2VkX2V5ZXMnOidcXHVkODNkXFx1ZGUxYScsXG4gICdraXNzaW5nX2hlYXJ0JzonXFx1ZDgzZFxcdWRlMTgnLFxuICAna2lzc2luZ19zbWlsaW5nX2V5ZXMnOidcXHVkODNkXFx1ZGUxOScsXG4gICdraXdpX2ZydWl0JzonXFx1ZDgzZVxcdWRkNWQnLFxuICAna29hbGEnOidcXHVkODNkXFx1ZGMyOCcsXG4gICdrb2tvJzonXFx1ZDgzY1xcdWRlMDEnLFxuICAnbGFiZWwnOidcXHVkODNjXFx1ZGZmNycsXG4gICdsYXJnZV9ibHVlX2NpcmNsZSc6J1xcdWQ4M2RcXHVkZDM1JyxcbiAgJ2xhcmdlX2JsdWVfZGlhbW9uZCc6J1xcdWQ4M2RcXHVkZDM3JyxcbiAgJ2xhcmdlX29yYW5nZV9kaWFtb25kJzonXFx1ZDgzZFxcdWRkMzYnLFxuICAnbGFzdF9xdWFydGVyX21vb24nOidcXHVkODNjXFx1ZGYxNycsXG4gICdsYXN0X3F1YXJ0ZXJfbW9vbl93aXRoX2ZhY2UnOidcXHVkODNjXFx1ZGYxYycsXG4gICdsYXRpbl9jcm9zcyc6J1xcdTI3MWRcXHVmZTBmJyxcbiAgJ2xhdWdoaW5nJzonXFx1ZDgzZFxcdWRlMDYnLFxuICAnbGVhdmVzJzonXFx1ZDgzY1xcdWRmNDMnLFxuICAnbGVkZ2VyJzonXFx1ZDgzZFxcdWRjZDInLFxuICAnbGVmdF9sdWdnYWdlJzonXFx1ZDgzZFxcdWRlYzUnLFxuICAnbGVmdF9yaWdodF9hcnJvdyc6J1xcdTIxOTRcXHVmZTBmJyxcbiAgJ2xlZnR3YXJkc19hcnJvd193aXRoX2hvb2snOidcXHUyMWE5XFx1ZmUwZicsXG4gICdsZW1vbic6J1xcdWQ4M2NcXHVkZjRiJyxcbiAgJ2xlbyc6J1xcdTI2NGNcXHVmZTBmJyxcbiAgJ2xlb3BhcmQnOidcXHVkODNkXFx1ZGMwNicsXG4gICdsZXZlbF9zbGlkZXInOidcXHVkODNjXFx1ZGY5YScsXG4gICdsaWJyYSc6J1xcdTI2NGVcXHVmZTBmJyxcbiAgJ2xpZ2h0X3JhaWwnOidcXHVkODNkXFx1ZGU4OCcsXG4gICdsaW5rJzonXFx1ZDgzZFxcdWRkMTcnLFxuICAnbGlvbic6J1xcdWQ4M2VcXHVkZDgxJyxcbiAgJ2xpcHMnOidcXHVkODNkXFx1ZGM0NCcsXG4gICdsaXBzdGljayc6J1xcdWQ4M2RcXHVkYzg0JyxcbiAgJ2xpemFyZCc6J1xcdWQ4M2VcXHVkZDhlJyxcbiAgJ2xvY2snOidcXHVkODNkXFx1ZGQxMicsXG4gICdsb2NrX3dpdGhfaW5rX3Blbic6J1xcdWQ4M2RcXHVkZDBmJyxcbiAgJ2xvbGxpcG9wJzonXFx1ZDgzY1xcdWRmNmQnLFxuICAnbG9vcCc6J1xcdTI3YmYnLFxuICAnbG91ZF9zb3VuZCc6J1xcdWQ4M2RcXHVkZDBhJyxcbiAgJ2xvdWRzcGVha2VyJzonXFx1ZDgzZFxcdWRjZTInLFxuICAnbG92ZV9ob3RlbCc6J1xcdWQ4M2NcXHVkZmU5JyxcbiAgJ2xvdmVfbGV0dGVyJzonXFx1ZDgzZFxcdWRjOGMnLFxuICAnbG93X2JyaWdodG5lc3MnOidcXHVkODNkXFx1ZGQwNScsXG4gICdseWluZ19mYWNlJzonXFx1ZDgzZVxcdWRkMjUnLFxuICAnbSc6J1xcdTI0YzJcXHVmZTBmJyxcbiAgJ21hZyc6J1xcdWQ4M2RcXHVkZDBkJyxcbiAgJ21hZ19yaWdodCc6J1xcdWQ4M2RcXHVkZDBlJyxcbiAgJ21haGpvbmcnOidcXHVkODNjXFx1ZGMwNFxcdWZlMGYnLFxuICAnbWFpbGJveCc6J1xcdWQ4M2RcXHVkY2ViJyxcbiAgJ21haWxib3hfY2xvc2VkJzonXFx1ZDgzZFxcdWRjZWEnLFxuICAnbWFpbGJveF93aXRoX21haWwnOidcXHVkODNkXFx1ZGNlYycsXG4gICdtYWlsYm94X3dpdGhfbm9fbWFpbCc6J1xcdWQ4M2RcXHVkY2VkJyxcbiAgJ21hbic6J1xcdWQ4M2RcXHVkYzY4JyxcbiAgJ21hbl9hcnRpc3QnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzY1xcdWRmYTgnLFxuICAnbWFuX2FzdHJvbmF1dCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGU4MCcsXG4gICdtYW5fY2FydHdoZWVsaW5nJzonXFx1ZDgzZVxcdWRkMzgmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21hbl9jb29rJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZjczJyxcbiAgJ21hbl9kYW5jaW5nJzonXFx1ZDgzZFxcdWRkN2EnLFxuICAnbWFuX2ZhY2VwYWxtaW5nJzonXFx1ZDgzZVxcdWRkMjYmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21hbl9mYWN0b3J5X3dvcmtlcic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGZlZCcsXG4gICdtYW5fZmFybWVyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZjNlJyxcbiAgJ21hbl9maXJlZmlnaHRlcic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGU5MicsXG4gICdtYW5faGVhbHRoX3dvcmtlcic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHUyNjk1XFx1ZmUwZicsXG4gICdtYW5faW5fdHV4ZWRvJzonXFx1ZDgzZVxcdWRkMzUnLFxuICAnbWFuX2p1ZGdlJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdTI2OTZcXHVmZTBmJyxcbiAgJ21hbl9qdWdnbGluZyc6J1xcdWQ4M2VcXHVkZDM5Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fbWVjaGFuaWMnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRkMjcnLFxuICAnbWFuX29mZmljZV93b3JrZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjYmMnLFxuICAnbWFuX3BpbG90JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdTI3MDhcXHVmZTBmJyxcbiAgJ21hbl9wbGF5aW5nX2hhbmRiYWxsJzonXFx1ZDgzZVxcdWRkM2UmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21hbl9wbGF5aW5nX3dhdGVyX3BvbG8nOidcXHVkODNlXFx1ZGQzZCZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWFuX3NjaWVudGlzdCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGQyYycsXG4gICdtYW5fc2hydWdnaW5nJzonXFx1ZDgzZVxcdWRkMzcmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21hbl9zaW5nZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzY1xcdWRmYTQnLFxuICAnbWFuX3N0dWRlbnQnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzY1xcdWRmOTMnLFxuICAnbWFuX3RlYWNoZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzY1xcdWRmZWInLFxuICAnbWFuX3RlY2hub2xvZ2lzdCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGNiYicsXG4gICdtYW5fd2l0aF9ndWFfcGlfbWFvJzonXFx1ZDgzZFxcdWRjNzInLFxuICAnbWFuX3dpdGhfdHVyYmFuJzonXFx1ZDgzZFxcdWRjNzMnLFxuICAndGFuZ2VyaW5lJzonXFx1ZDgzY1xcdWRmNGEnLFxuICAnbWFuc19zaG9lJzonXFx1ZDgzZFxcdWRjNWUnLFxuICAnbWFudGVscGllY2VfY2xvY2snOidcXHVkODNkXFx1ZGQ3MCcsXG4gICdtYXBsZV9sZWFmJzonXFx1ZDgzY1xcdWRmNDEnLFxuICAnbWFydGlhbF9hcnRzX3VuaWZvcm0nOidcXHVkODNlXFx1ZGQ0YicsXG4gICdtYXNrJzonXFx1ZDgzZFxcdWRlMzcnLFxuICAnbWFzc2FnZV93b21hbic6J1xcdWQ4M2RcXHVkYzg2JyxcbiAgJ21hc3NhZ2VfbWFuJzonXFx1ZDgzZFxcdWRjODYmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21lYXRfb25fYm9uZSc6J1xcdWQ4M2NcXHVkZjU2JyxcbiAgJ21lZGFsX21pbGl0YXJ5JzonXFx1ZDgzY1xcdWRmOTYnLFxuICAnbWVkYWxfc3BvcnRzJzonXFx1ZDgzY1xcdWRmYzUnLFxuICAnbWVnYSc6J1xcdWQ4M2RcXHVkY2UzJyxcbiAgJ21lbG9uJzonXFx1ZDgzY1xcdWRmNDgnLFxuICAnbWVtbyc6J1xcdWQ4M2RcXHVkY2RkJyxcbiAgJ21lbl93cmVzdGxpbmcnOidcXHVkODNlXFx1ZGQzYyZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWVub3JhaCc6J1xcdWQ4M2RcXHVkZDRlJyxcbiAgJ21lbnMnOidcXHVkODNkXFx1ZGViOScsXG4gICdtZXRhbCc6J1xcdWQ4M2VcXHVkZDE4JyxcbiAgJ21ldHJvJzonXFx1ZDgzZFxcdWRlODcnLFxuICAnbWljcm9waG9uZSc6J1xcdWQ4M2NcXHVkZmE0JyxcbiAgJ21pY3Jvc2NvcGUnOidcXHVkODNkXFx1ZGQyYycsXG4gICdtaWxrX2dsYXNzJzonXFx1ZDgzZVxcdWRkNWInLFxuICAnbWlsa3lfd2F5JzonXFx1ZDgzY1xcdWRmMGMnLFxuICAnbWluaWJ1cyc6J1xcdWQ4M2RcXHVkZTkwJyxcbiAgJ21pbmlkaXNjJzonXFx1ZDgzZFxcdWRjYmQnLFxuICAnbW9iaWxlX3Bob25lX29mZic6J1xcdWQ4M2RcXHVkY2Y0JyxcbiAgJ21vbmV5X21vdXRoX2ZhY2UnOidcXHVkODNlXFx1ZGQxMScsXG4gICdtb25leV93aXRoX3dpbmdzJzonXFx1ZDgzZFxcdWRjYjgnLFxuICAnbW9uZXliYWcnOidcXHVkODNkXFx1ZGNiMCcsXG4gICdtb25rZXknOidcXHVkODNkXFx1ZGMxMicsXG4gICdtb25rZXlfZmFjZSc6J1xcdWQ4M2RcXHVkYzM1JyxcbiAgJ21vbm9yYWlsJzonXFx1ZDgzZFxcdWRlOWQnLFxuICAnbW9vbic6J1xcdWQ4M2NcXHVkZjE0JyxcbiAgJ21vcnRhcl9ib2FyZCc6J1xcdWQ4M2NcXHVkZjkzJyxcbiAgJ21vc3F1ZSc6J1xcdWQ4M2RcXHVkZDRjJyxcbiAgJ21vdG9yX2JvYXQnOidcXHVkODNkXFx1ZGVlNScsXG4gICdtb3Rvcl9zY29vdGVyJzonXFx1ZDgzZFxcdWRlZjUnLFxuICAnbW90b3JjeWNsZSc6J1xcdWQ4M2NcXHVkZmNkJyxcbiAgJ21vdG9yd2F5JzonXFx1ZDgzZFxcdWRlZTMnLFxuICAnbW91bnRfZnVqaSc6J1xcdWQ4M2RcXHVkZGZiJyxcbiAgJ21vdW50YWluJzonXFx1MjZmMCcsXG4gICdtb3VudGFpbl9iaWtpbmdfbWFuJzonXFx1ZDgzZFxcdWRlYjUnLFxuICAnbW91bnRhaW5fYmlraW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlYjUmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ21vdW50YWluX2NhYmxld2F5JzonXFx1ZDgzZFxcdWRlYTAnLFxuICAnbW91bnRhaW5fcmFpbHdheSc6J1xcdWQ4M2RcXHVkZTllJyxcbiAgJ21vdW50YWluX3Nub3cnOidcXHVkODNjXFx1ZGZkNCcsXG4gICdtb3VzZSc6J1xcdWQ4M2RcXHVkYzJkJyxcbiAgJ21vdXNlMic6J1xcdWQ4M2RcXHVkYzAxJyxcbiAgJ21vdmllX2NhbWVyYSc6J1xcdWQ4M2NcXHVkZmE1JyxcbiAgJ21veWFpJzonXFx1ZDgzZFxcdWRkZmYnLFxuICAnbXJzX2NsYXVzJzonXFx1ZDgzZVxcdWRkMzYnLFxuICAnbXVzY2xlJzonXFx1ZDgzZFxcdWRjYWEnLFxuICAnbXVzaHJvb20nOidcXHVkODNjXFx1ZGY0NCcsXG4gICdtdXNpY2FsX2tleWJvYXJkJzonXFx1ZDgzY1xcdWRmYjknLFxuICAnbXVzaWNhbF9ub3RlJzonXFx1ZDgzY1xcdWRmYjUnLFxuICAnbXVzaWNhbF9zY29yZSc6J1xcdWQ4M2NcXHVkZmJjJyxcbiAgJ211dGUnOidcXHVkODNkXFx1ZGQwNycsXG4gICduYWlsX2NhcmUnOidcXHVkODNkXFx1ZGM4NScsXG4gICduYW1lX2JhZGdlJzonXFx1ZDgzZFxcdWRjZGInLFxuICAnbmF0aW9uYWxfcGFyayc6J1xcdWQ4M2NcXHVkZmRlJyxcbiAgJ25hdXNlYXRlZF9mYWNlJzonXFx1ZDgzZVxcdWRkMjInLFxuICAnbmVja3RpZSc6J1xcdWQ4M2RcXHVkYzU0JyxcbiAgJ25lZ2F0aXZlX3NxdWFyZWRfY3Jvc3NfbWFyayc6J1xcdTI3NGUnLFxuICAnbmVyZF9mYWNlJzonXFx1ZDgzZVxcdWRkMTMnLFxuICAnbmV1dHJhbF9mYWNlJzonXFx1ZDgzZFxcdWRlMTAnLFxuICAnbmV3JzonXFx1ZDgzY1xcdWRkOTUnLFxuICAnbmV3X21vb24nOidcXHVkODNjXFx1ZGYxMScsXG4gICduZXdfbW9vbl93aXRoX2ZhY2UnOidcXHVkODNjXFx1ZGYxYScsXG4gICduZXdzcGFwZXInOidcXHVkODNkXFx1ZGNmMCcsXG4gICduZXdzcGFwZXJfcm9sbCc6J1xcdWQ4M2RcXHVkZGRlJyxcbiAgJ25leHRfdHJhY2tfYnV0dG9uJzonXFx1MjNlZCcsXG4gICduZyc6J1xcdWQ4M2NcXHVkZDk2JyxcbiAgJ25vX2dvb2RfbWFuJzonXFx1ZDgzZFxcdWRlNDUmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ25vX2dvb2Rfd29tYW4nOidcXHVkODNkXFx1ZGU0NScsXG4gICduaWdodF93aXRoX3N0YXJzJzonXFx1ZDgzY1xcdWRmMDMnLFxuICAnbm9fYmVsbCc6J1xcdWQ4M2RcXHVkZDE1JyxcbiAgJ25vX2JpY3ljbGVzJzonXFx1ZDgzZFxcdWRlYjMnLFxuICAnbm9fZW50cnknOidcXHUyNmQ0XFx1ZmUwZicsXG4gICdub19lbnRyeV9zaWduJzonXFx1ZDgzZFxcdWRlYWInLFxuICAnbm9fbW9iaWxlX3Bob25lcyc6J1xcdWQ4M2RcXHVkY2Y1JyxcbiAgJ25vX21vdXRoJzonXFx1ZDgzZFxcdWRlMzYnLFxuICAnbm9fcGVkZXN0cmlhbnMnOidcXHVkODNkXFx1ZGViNycsXG4gICdub19zbW9raW5nJzonXFx1ZDgzZFxcdWRlYWQnLFxuICAnbm9uLXBvdGFibGVfd2F0ZXInOidcXHVkODNkXFx1ZGViMScsXG4gICdub3NlJzonXFx1ZDgzZFxcdWRjNDMnLFxuICAnbm90ZWJvb2snOidcXHVkODNkXFx1ZGNkMycsXG4gICdub3RlYm9va193aXRoX2RlY29yYXRpdmVfY292ZXInOidcXHVkODNkXFx1ZGNkNCcsXG4gICdub3Rlcyc6J1xcdWQ4M2NcXHVkZmI2JyxcbiAgJ251dF9hbmRfYm9sdCc6J1xcdWQ4M2RcXHVkZDI5JyxcbiAgJ28nOidcXHUyYjU1XFx1ZmUwZicsXG4gICdvMic6J1xcdWQ4M2NcXHVkZDdlXFx1ZmUwZicsXG4gICdvY2Vhbic6J1xcdWQ4M2NcXHVkZjBhJyxcbiAgJ29jdG9wdXMnOidcXHVkODNkXFx1ZGMxOScsXG4gICdvZGVuJzonXFx1ZDgzY1xcdWRmNjInLFxuICAnb2ZmaWNlJzonXFx1ZDgzY1xcdWRmZTInLFxuICAnb2lsX2RydW0nOidcXHVkODNkXFx1ZGVlMicsXG4gICdvayc6J1xcdWQ4M2NcXHVkZDk3JyxcbiAgJ29rX2hhbmQnOidcXHVkODNkXFx1ZGM0YycsXG4gICdva19tYW4nOidcXHVkODNkXFx1ZGU0NiZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnb2tfd29tYW4nOidcXHVkODNkXFx1ZGU0NicsXG4gICdvbGRfa2V5JzonXFx1ZDgzZFxcdWRkZGQnLFxuICAnb2xkZXJfbWFuJzonXFx1ZDgzZFxcdWRjNzQnLFxuICAnb2xkZXJfd29tYW4nOidcXHVkODNkXFx1ZGM3NScsXG4gICdvbSc6J1xcdWQ4M2RcXHVkZDQ5JyxcbiAgJ29uJzonXFx1ZDgzZFxcdWRkMWInLFxuICAnb25jb21pbmdfYXV0b21vYmlsZSc6J1xcdWQ4M2RcXHVkZTk4JyxcbiAgJ29uY29taW5nX2J1cyc6J1xcdWQ4M2RcXHVkZThkJyxcbiAgJ29uY29taW5nX3BvbGljZV9jYXInOidcXHVkODNkXFx1ZGU5NCcsXG4gICdvbmNvbWluZ190YXhpJzonXFx1ZDgzZFxcdWRlOTYnLFxuICAnb3Blbl9maWxlX2ZvbGRlcic6J1xcdWQ4M2RcXHVkY2MyJyxcbiAgJ29wZW5faGFuZHMnOidcXHVkODNkXFx1ZGM1MCcsXG4gICdvcGVuX21vdXRoJzonXFx1ZDgzZFxcdWRlMmUnLFxuICAnb3Blbl91bWJyZWxsYSc6J1xcdTI2MDJcXHVmZTBmJyxcbiAgJ29waGl1Y2h1cyc6J1xcdTI2Y2UnLFxuICAnb3JhbmdlX2Jvb2snOidcXHVkODNkXFx1ZGNkOScsXG4gICdvcnRob2RveF9jcm9zcyc6J1xcdTI2MjZcXHVmZTBmJyxcbiAgJ291dGJveF90cmF5JzonXFx1ZDgzZFxcdWRjZTQnLFxuICAnb3dsJzonXFx1ZDgzZVxcdWRkODknLFxuICAnb3gnOidcXHVkODNkXFx1ZGMwMicsXG4gICdwYWNrYWdlJzonXFx1ZDgzZFxcdWRjZTYnLFxuICAncGFnZV9mYWNpbmdfdXAnOidcXHVkODNkXFx1ZGNjNCcsXG4gICdwYWdlX3dpdGhfY3VybCc6J1xcdWQ4M2RcXHVkY2MzJyxcbiAgJ3BhZ2VyJzonXFx1ZDgzZFxcdWRjZGYnLFxuICAncGFpbnRicnVzaCc6J1xcdWQ4M2RcXHVkZDhjJyxcbiAgJ3BhbG1fdHJlZSc6J1xcdWQ4M2NcXHVkZjM0JyxcbiAgJ3BhbmNha2VzJzonXFx1ZDgzZVxcdWRkNWUnLFxuICAncGFuZGFfZmFjZSc6J1xcdWQ4M2RcXHVkYzNjJyxcbiAgJ3BhcGVyY2xpcCc6J1xcdWQ4M2RcXHVkY2NlJyxcbiAgJ3BhcGVyY2xpcHMnOidcXHVkODNkXFx1ZGQ4NycsXG4gICdwYXJhc29sX29uX2dyb3VuZCc6J1xcdTI2ZjEnLFxuICAncGFya2luZyc6J1xcdWQ4M2NcXHVkZDdmXFx1ZmUwZicsXG4gICdwYXJ0X2FsdGVybmF0aW9uX21hcmsnOidcXHUzMDNkXFx1ZmUwZicsXG4gICdwYXJ0bHlfc3VubnknOidcXHUyNmM1XFx1ZmUwZicsXG4gICdwYXNzZW5nZXJfc2hpcCc6J1xcdWQ4M2RcXHVkZWYzJyxcbiAgJ3Bhc3Nwb3J0X2NvbnRyb2wnOidcXHVkODNkXFx1ZGVjMicsXG4gICdwYXVzZV9idXR0b24nOidcXHUyM2Y4JyxcbiAgJ3BlYWNlX3N5bWJvbCc6J1xcdTI2MmVcXHVmZTBmJyxcbiAgJ3BlYWNoJzonXFx1ZDgzY1xcdWRmNTEnLFxuICAncGVhbnV0cyc6J1xcdWQ4M2VcXHVkZDVjJyxcbiAgJ3BlYXInOidcXHVkODNjXFx1ZGY1MCcsXG4gICdwZW4nOidcXHVkODNkXFx1ZGQ4YScsXG4gICdwZW5jaWwyJzonXFx1MjcwZlxcdWZlMGYnLFxuICAncGVuZ3Vpbic6J1xcdWQ4M2RcXHVkYzI3JyxcbiAgJ3BlbnNpdmUnOidcXHVkODNkXFx1ZGUxNCcsXG4gICdwZXJmb3JtaW5nX2FydHMnOidcXHVkODNjXFx1ZGZhZCcsXG4gICdwZXJzZXZlcmUnOidcXHVkODNkXFx1ZGUyMycsXG4gICdwZXJzb25fZmVuY2luZyc6J1xcdWQ4M2VcXHVkZDNhJyxcbiAgJ3BvdXRpbmdfd29tYW4nOidcXHVkODNkXFx1ZGU0ZScsXG4gICdwaG9uZSc6J1xcdTI2MGVcXHVmZTBmJyxcbiAgJ3BpY2snOidcXHUyNmNmJyxcbiAgJ3BpZyc6J1xcdWQ4M2RcXHVkYzM3JyxcbiAgJ3BpZzInOidcXHVkODNkXFx1ZGMxNicsXG4gICdwaWdfbm9zZSc6J1xcdWQ4M2RcXHVkYzNkJyxcbiAgJ3BpbGwnOidcXHVkODNkXFx1ZGM4YScsXG4gICdwaW5lYXBwbGUnOidcXHVkODNjXFx1ZGY0ZCcsXG4gICdwaW5nX3BvbmcnOidcXHVkODNjXFx1ZGZkMycsXG4gICdwaXNjZXMnOidcXHUyNjUzXFx1ZmUwZicsXG4gICdwaXp6YSc6J1xcdWQ4M2NcXHVkZjU1JyxcbiAgJ3BsYWNlX29mX3dvcnNoaXAnOidcXHVkODNkXFx1ZGVkMCcsXG4gICdwbGF0ZV93aXRoX2N1dGxlcnknOidcXHVkODNjXFx1ZGY3ZCcsXG4gICdwbGF5X29yX3BhdXNlX2J1dHRvbic6J1xcdTIzZWYnLFxuICAncG9pbnRfZG93bic6J1xcdWQ4M2RcXHVkYzQ3JyxcbiAgJ3BvaW50X2xlZnQnOidcXHVkODNkXFx1ZGM0OCcsXG4gICdwb2ludF9yaWdodCc6J1xcdWQ4M2RcXHVkYzQ5JyxcbiAgJ3BvaW50X3VwJzonXFx1MjYxZFxcdWZlMGYnLFxuICAncG9pbnRfdXBfMic6J1xcdWQ4M2RcXHVkYzQ2JyxcbiAgJ3BvbGljZV9jYXInOidcXHVkODNkXFx1ZGU5MycsXG4gICdwb2xpY2V3b21hbic6J1xcdWQ4M2RcXHVkYzZlJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdwb29kbGUnOidcXHVkODNkXFx1ZGMyOScsXG4gICdwb3Bjb3JuJzonXFx1ZDgzY1xcdWRmN2YnLFxuICAncG9zdF9vZmZpY2UnOidcXHVkODNjXFx1ZGZlMycsXG4gICdwb3N0YWxfaG9ybic6J1xcdWQ4M2RcXHVkY2VmJyxcbiAgJ3Bvc3Rib3gnOidcXHVkODNkXFx1ZGNlZScsXG4gICdwb3RhYmxlX3dhdGVyJzonXFx1ZDgzZFxcdWRlYjAnLFxuICAncG90YXRvJzonXFx1ZDgzZVxcdWRkNTQnLFxuICAncG91Y2gnOidcXHVkODNkXFx1ZGM1ZCcsXG4gICdwb3VsdHJ5X2xlZyc6J1xcdWQ4M2NcXHVkZjU3JyxcbiAgJ3BvdW5kJzonXFx1ZDgzZFxcdWRjYjcnLFxuICAncmFnZSc6J1xcdWQ4M2RcXHVkZTIxJyxcbiAgJ3BvdXRpbmdfY2F0JzonXFx1ZDgzZFxcdWRlM2UnLFxuICAncG91dGluZ19tYW4nOidcXHVkODNkXFx1ZGU0ZSZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAncHJheSc6J1xcdWQ4M2RcXHVkZTRmJyxcbiAgJ3ByYXllcl9iZWFkcyc6J1xcdWQ4M2RcXHVkY2ZmJyxcbiAgJ3ByZWduYW50X3dvbWFuJzonXFx1ZDgzZVxcdWRkMzAnLFxuICAncHJldmlvdXNfdHJhY2tfYnV0dG9uJzonXFx1MjNlZScsXG4gICdwcmluY2UnOidcXHVkODNlXFx1ZGQzNCcsXG4gICdwcmluY2Vzcyc6J1xcdWQ4M2RcXHVkYzc4JyxcbiAgJ3ByaW50ZXInOidcXHVkODNkXFx1ZGRhOCcsXG4gICdwdXJwbGVfaGVhcnQnOidcXHVkODNkXFx1ZGM5YycsXG4gICdwdXJzZSc6J1xcdWQ4M2RcXHVkYzViJyxcbiAgJ3B1c2hwaW4nOidcXHVkODNkXFx1ZGNjYycsXG4gICdwdXRfbGl0dGVyX2luX2l0c19wbGFjZSc6J1xcdWQ4M2RcXHVkZWFlJyxcbiAgJ3F1ZXN0aW9uJzonXFx1Mjc1MycsXG4gICdyYWJiaXQnOidcXHVkODNkXFx1ZGMzMCcsXG4gICdyYWJiaXQyJzonXFx1ZDgzZFxcdWRjMDcnLFxuICAncmFjZWhvcnNlJzonXFx1ZDgzZFxcdWRjMGUnLFxuICAncmFjaW5nX2Nhcic6J1xcdWQ4M2NcXHVkZmNlJyxcbiAgJ3JhZGlvJzonXFx1ZDgzZFxcdWRjZmInLFxuICAncmFkaW9fYnV0dG9uJzonXFx1ZDgzZFxcdWRkMTgnLFxuICAncmFkaW9hY3RpdmUnOidcXHUyNjIyXFx1ZmUwZicsXG4gICdyYWlsd2F5X2Nhcic6J1xcdWQ4M2RcXHVkZTgzJyxcbiAgJ3JhaWx3YXlfdHJhY2snOidcXHVkODNkXFx1ZGVlNCcsXG4gICdyYWluYm93JzonXFx1ZDgzY1xcdWRmMDgnLFxuICAncmFpbmJvd19mbGFnJzonXFx1ZDgzY1xcdWRmZjNcXHVmZTBmJnp3ajtcXHVkODNjXFx1ZGYwOCcsXG4gICdyYWlzZWRfYmFja19vZl9oYW5kJzonXFx1ZDgzZVxcdWRkMWEnLFxuICAncmFpc2VkX2hhbmRfd2l0aF9maW5nZXJzX3NwbGF5ZWQnOidcXHVkODNkXFx1ZGQ5MCcsXG4gICdyYWlzZWRfaGFuZHMnOidcXHVkODNkXFx1ZGU0YycsXG4gICdyYWlzaW5nX2hhbmRfd29tYW4nOidcXHVkODNkXFx1ZGU0YicsXG4gICdyYWlzaW5nX2hhbmRfbWFuJzonXFx1ZDgzZFxcdWRlNGImendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ3JhbSc6J1xcdWQ4M2RcXHVkYzBmJyxcbiAgJ3JhbWVuJzonXFx1ZDgzY1xcdWRmNWMnLFxuICAncmF0JzonXFx1ZDgzZFxcdWRjMDAnLFxuICAncmVjb3JkX2J1dHRvbic6J1xcdTIzZmEnLFxuICAncmVjeWNsZSc6J1xcdTI2N2JcXHVmZTBmJyxcbiAgJ3JlZF9jaXJjbGUnOidcXHVkODNkXFx1ZGQzNCcsXG4gICdyZWdpc3RlcmVkJzonXFx1MDBhZVxcdWZlMGYnLFxuICAncmVsYXhlZCc6J1xcdTI2M2FcXHVmZTBmJyxcbiAgJ3JlbGlldmVkJzonXFx1ZDgzZFxcdWRlMGMnLFxuICAncmVtaW5kZXJfcmliYm9uJzonXFx1ZDgzY1xcdWRmOTcnLFxuICAncmVwZWF0JzonXFx1ZDgzZFxcdWRkMDEnLFxuICAncmVwZWF0X29uZSc6J1xcdWQ4M2RcXHVkZDAyJyxcbiAgJ3Jlc2N1ZV93b3JrZXJfaGVsbWV0JzonXFx1MjZkMScsXG4gICdyZXN0cm9vbSc6J1xcdWQ4M2RcXHVkZWJiJyxcbiAgJ3Jldm9sdmluZ19oZWFydHMnOidcXHVkODNkXFx1ZGM5ZScsXG4gICdyZXdpbmQnOidcXHUyM2VhJyxcbiAgJ3JoaW5vY2Vyb3MnOidcXHVkODNlXFx1ZGQ4ZicsXG4gICdyaWJib24nOidcXHVkODNjXFx1ZGY4MCcsXG4gICdyaWNlJzonXFx1ZDgzY1xcdWRmNWEnLFxuICAncmljZV9iYWxsJzonXFx1ZDgzY1xcdWRmNTknLFxuICAncmljZV9jcmFja2VyJzonXFx1ZDgzY1xcdWRmNTgnLFxuICAncmljZV9zY2VuZSc6J1xcdWQ4M2NcXHVkZjkxJyxcbiAgJ3JpZ2h0X2FuZ2VyX2J1YmJsZSc6J1xcdWQ4M2RcXHVkZGVmJyxcbiAgJ3JpbmcnOidcXHVkODNkXFx1ZGM4ZCcsXG4gICdyb2JvdCc6J1xcdWQ4M2VcXHVkZDE2JyxcbiAgJ3JvY2tldCc6J1xcdWQ4M2RcXHVkZTgwJyxcbiAgJ3JvZmwnOidcXHVkODNlXFx1ZGQyMycsXG4gICdyb2xsX2V5ZXMnOidcXHVkODNkXFx1ZGU0NCcsXG4gICdyb2xsZXJfY29hc3Rlcic6J1xcdWQ4M2NcXHVkZmEyJyxcbiAgJ3Jvb3N0ZXInOidcXHVkODNkXFx1ZGMxMycsXG4gICdyb3NlJzonXFx1ZDgzY1xcdWRmMzknLFxuICAncm9zZXR0ZSc6J1xcdWQ4M2NcXHVkZmY1JyxcbiAgJ3JvdGF0aW5nX2xpZ2h0JzonXFx1ZDgzZFxcdWRlYTgnLFxuICAncm91bmRfcHVzaHBpbic6J1xcdWQ4M2RcXHVkY2NkJyxcbiAgJ3Jvd2luZ19tYW4nOidcXHVkODNkXFx1ZGVhMycsXG4gICdyb3dpbmdfd29tYW4nOidcXHVkODNkXFx1ZGVhMyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAncnVnYnlfZm9vdGJhbGwnOidcXHVkODNjXFx1ZGZjOScsXG4gICdydW5uaW5nX21hbic6J1xcdWQ4M2NcXHVkZmMzJyxcbiAgJ3J1bm5pbmdfc2hpcnRfd2l0aF9zYXNoJzonXFx1ZDgzY1xcdWRmYmQnLFxuICAncnVubmluZ193b21hbic6J1xcdWQ4M2NcXHVkZmMzJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdzYSc6J1xcdWQ4M2NcXHVkZTAyXFx1ZmUwZicsXG4gICdzYWdpdHRhcml1cyc6J1xcdTI2NTBcXHVmZTBmJyxcbiAgJ3Nha2UnOidcXHVkODNjXFx1ZGY3NicsXG4gICdzYW5kYWwnOidcXHVkODNkXFx1ZGM2MScsXG4gICdzYW50YSc6J1xcdWQ4M2NcXHVkZjg1JyxcbiAgJ3NhdGVsbGl0ZSc6J1xcdWQ4M2RcXHVkY2UxJyxcbiAgJ3NheG9waG9uZSc6J1xcdWQ4M2NcXHVkZmI3JyxcbiAgJ3NjaG9vbCc6J1xcdWQ4M2NcXHVkZmViJyxcbiAgJ3NjaG9vbF9zYXRjaGVsJzonXFx1ZDgzY1xcdWRmOTInLFxuICAnc2Npc3NvcnMnOidcXHUyNzAyXFx1ZmUwZicsXG4gICdzY29ycGlvbic6J1xcdWQ4M2VcXHVkZDgyJyxcbiAgJ3Njb3JwaXVzJzonXFx1MjY0ZlxcdWZlMGYnLFxuICAnc2NyZWFtJzonXFx1ZDgzZFxcdWRlMzEnLFxuICAnc2NyZWFtX2NhdCc6J1xcdWQ4M2RcXHVkZTQwJyxcbiAgJ3Njcm9sbCc6J1xcdWQ4M2RcXHVkY2RjJyxcbiAgJ3NlYXQnOidcXHVkODNkXFx1ZGNiYScsXG4gICdzZWNyZXQnOidcXHUzMjk5XFx1ZmUwZicsXG4gICdzZWVfbm9fZXZpbCc6J1xcdWQ4M2RcXHVkZTQ4JyxcbiAgJ3NlZWRsaW5nJzonXFx1ZDgzY1xcdWRmMzEnLFxuICAnc2VsZmllJzonXFx1ZDgzZVxcdWRkMzMnLFxuICAnc2hhbGxvd19wYW5fb2ZfZm9vZCc6J1xcdWQ4M2VcXHVkZDU4JyxcbiAgJ3NoYW1yb2NrJzonXFx1MjYxOFxcdWZlMGYnLFxuICAnc2hhcmsnOidcXHVkODNlXFx1ZGQ4OCcsXG4gICdzaGF2ZWRfaWNlJzonXFx1ZDgzY1xcdWRmNjcnLFxuICAnc2hlZXAnOidcXHVkODNkXFx1ZGMxMScsXG4gICdzaGVsbCc6J1xcdWQ4M2RcXHVkYzFhJyxcbiAgJ3NoaWVsZCc6J1xcdWQ4M2RcXHVkZWUxJyxcbiAgJ3NoaW50b19zaHJpbmUnOidcXHUyNmU5JyxcbiAgJ3NoaXAnOidcXHVkODNkXFx1ZGVhMicsXG4gICdzaGlydCc6J1xcdWQ4M2RcXHVkYzU1JyxcbiAgJ3Nob3BwaW5nJzonXFx1ZDgzZFxcdWRlY2QnLFxuICAnc2hvcHBpbmdfY2FydCc6J1xcdWQ4M2RcXHVkZWQyJyxcbiAgJ3Nob3dlcic6J1xcdWQ4M2RcXHVkZWJmJyxcbiAgJ3NocmltcCc6J1xcdWQ4M2VcXHVkZDkwJyxcbiAgJ3NpZ25hbF9zdHJlbmd0aCc6J1xcdWQ4M2RcXHVkY2Y2JyxcbiAgJ3NpeF9wb2ludGVkX3N0YXInOidcXHVkODNkXFx1ZGQyZicsXG4gICdza2knOidcXHVkODNjXFx1ZGZiZicsXG4gICdza2llcic6J1xcdTI2ZjcnLFxuICAnc2t1bGwnOidcXHVkODNkXFx1ZGM4MCcsXG4gICdza3VsbF9hbmRfY3Jvc3Nib25lcyc6J1xcdTI2MjBcXHVmZTBmJyxcbiAgJ3NsZWVwaW5nJzonXFx1ZDgzZFxcdWRlMzQnLFxuICAnc2xlZXBpbmdfYmVkJzonXFx1ZDgzZFxcdWRlY2MnLFxuICAnc2xlZXB5JzonXFx1ZDgzZFxcdWRlMmEnLFxuICAnc2xpZ2h0bHlfZnJvd25pbmdfZmFjZSc6J1xcdWQ4M2RcXHVkZTQxJyxcbiAgJ3NsaWdodGx5X3NtaWxpbmdfZmFjZSc6J1xcdWQ4M2RcXHVkZTQyJyxcbiAgJ3Nsb3RfbWFjaGluZSc6J1xcdWQ4M2NcXHVkZmIwJyxcbiAgJ3NtYWxsX2FpcnBsYW5lJzonXFx1ZDgzZFxcdWRlZTknLFxuICAnc21hbGxfYmx1ZV9kaWFtb25kJzonXFx1ZDgzZFxcdWRkMzknLFxuICAnc21hbGxfb3JhbmdlX2RpYW1vbmQnOidcXHVkODNkXFx1ZGQzOCcsXG4gICdzbWFsbF9yZWRfdHJpYW5nbGUnOidcXHVkODNkXFx1ZGQzYScsXG4gICdzbWFsbF9yZWRfdHJpYW5nbGVfZG93bic6J1xcdWQ4M2RcXHVkZDNiJyxcbiAgJ3NtaWxlJzonXFx1ZDgzZFxcdWRlMDQnLFxuICAnc21pbGVfY2F0JzonXFx1ZDgzZFxcdWRlMzgnLFxuICAnc21pbGV5JzonXFx1ZDgzZFxcdWRlMDMnLFxuICAnc21pbGV5X2NhdCc6J1xcdWQ4M2RcXHVkZTNhJyxcbiAgJ3NtaWxpbmdfaW1wJzonXFx1ZDgzZFxcdWRlMDgnLFxuICAnc21pcmsnOidcXHVkODNkXFx1ZGUwZicsXG4gICdzbWlya19jYXQnOidcXHVkODNkXFx1ZGUzYycsXG4gICdzbW9raW5nJzonXFx1ZDgzZFxcdWRlYWMnLFxuICAnc25haWwnOidcXHVkODNkXFx1ZGMwYycsXG4gICdzbmFrZSc6J1xcdWQ4M2RcXHVkYzBkJyxcbiAgJ3NuZWV6aW5nX2ZhY2UnOidcXHVkODNlXFx1ZGQyNycsXG4gICdzbm93Ym9hcmRlcic6J1xcdWQ4M2NcXHVkZmMyJyxcbiAgJ3Nub3dmbGFrZSc6J1xcdTI3NDRcXHVmZTBmJyxcbiAgJ3Nub3dtYW4nOidcXHUyNmM0XFx1ZmUwZicsXG4gICdzbm93bWFuX3dpdGhfc25vdyc6J1xcdTI2MDNcXHVmZTBmJyxcbiAgJ3NvYic6J1xcdWQ4M2RcXHVkZTJkJyxcbiAgJ3NvY2Nlcic6J1xcdTI2YmRcXHVmZTBmJyxcbiAgJ3Nvb24nOidcXHVkODNkXFx1ZGQxYycsXG4gICdzb3MnOidcXHVkODNjXFx1ZGQ5OCcsXG4gICdzb3VuZCc6J1xcdWQ4M2RcXHVkZDA5JyxcbiAgJ3NwYWNlX2ludmFkZXInOidcXHVkODNkXFx1ZGM3ZScsXG4gICdzcGFkZXMnOidcXHUyNjYwXFx1ZmUwZicsXG4gICdzcGFnaGV0dGknOidcXHVkODNjXFx1ZGY1ZCcsXG4gICdzcGFya2xlJzonXFx1Mjc0N1xcdWZlMGYnLFxuICAnc3BhcmtsZXInOidcXHVkODNjXFx1ZGY4NycsXG4gICdzcGFya2xlcyc6J1xcdTI3MjgnLFxuICAnc3BhcmtsaW5nX2hlYXJ0JzonXFx1ZDgzZFxcdWRjOTYnLFxuICAnc3BlYWtfbm9fZXZpbCc6J1xcdWQ4M2RcXHVkZTRhJyxcbiAgJ3NwZWFrZXInOidcXHVkODNkXFx1ZGQwOCcsXG4gICdzcGVha2luZ19oZWFkJzonXFx1ZDgzZFxcdWRkZTMnLFxuICAnc3BlZWNoX2JhbGxvb24nOidcXHVkODNkXFx1ZGNhYycsXG4gICdzcGVlZGJvYXQnOidcXHVkODNkXFx1ZGVhNCcsXG4gICdzcGlkZXInOidcXHVkODNkXFx1ZGQ3NycsXG4gICdzcGlkZXJfd2ViJzonXFx1ZDgzZFxcdWRkNzgnLFxuICAnc3BpcmFsX2NhbGVuZGFyJzonXFx1ZDgzZFxcdWRkZDMnLFxuICAnc3BpcmFsX25vdGVwYWQnOidcXHVkODNkXFx1ZGRkMicsXG4gICdzcG9vbic6J1xcdWQ4M2VcXHVkZDQ0JyxcbiAgJ3NxdWlkJzonXFx1ZDgzZVxcdWRkOTEnLFxuICAnc3RhZGl1bSc6J1xcdWQ4M2NcXHVkZmRmJyxcbiAgJ3N0YXInOidcXHUyYjUwXFx1ZmUwZicsXG4gICdzdGFyMic6J1xcdWQ4M2NcXHVkZjFmJyxcbiAgJ3N0YXJfYW5kX2NyZXNjZW50JzonXFx1MjYyYVxcdWZlMGYnLFxuICAnc3Rhcl9vZl9kYXZpZCc6J1xcdTI3MjFcXHVmZTBmJyxcbiAgJ3N0YXJzJzonXFx1ZDgzY1xcdWRmMjAnLFxuICAnc3RhdGlvbic6J1xcdWQ4M2RcXHVkZTg5JyxcbiAgJ3N0YXR1ZV9vZl9saWJlcnR5JzonXFx1ZDgzZFxcdWRkZmQnLFxuICAnc3RlYW1fbG9jb21vdGl2ZSc6J1xcdWQ4M2RcXHVkZTgyJyxcbiAgJ3N0ZXcnOidcXHVkODNjXFx1ZGY3MicsXG4gICdzdG9wX2J1dHRvbic6J1xcdTIzZjknLFxuICAnc3RvcF9zaWduJzonXFx1ZDgzZFxcdWRlZDEnLFxuICAnc3RvcHdhdGNoJzonXFx1MjNmMScsXG4gICdzdHJhaWdodF9ydWxlcic6J1xcdWQ4M2RcXHVkY2NmJyxcbiAgJ3N0cmF3YmVycnknOidcXHVkODNjXFx1ZGY1MycsXG4gICdzdHVja19vdXRfdG9uZ3VlJzonXFx1ZDgzZFxcdWRlMWInLFxuICAnc3R1Y2tfb3V0X3Rvbmd1ZV9jbG9zZWRfZXllcyc6J1xcdWQ4M2RcXHVkZTFkJyxcbiAgJ3N0dWNrX291dF90b25ndWVfd2lua2luZ19leWUnOidcXHVkODNkXFx1ZGUxYycsXG4gICdzdHVkaW9fbWljcm9waG9uZSc6J1xcdWQ4M2NcXHVkZjk5JyxcbiAgJ3N0dWZmZWRfZmxhdGJyZWFkJzonXFx1ZDgzZVxcdWRkNTknLFxuICAnc3VuX2JlaGluZF9sYXJnZV9jbG91ZCc6J1xcdWQ4M2NcXHVkZjI1JyxcbiAgJ3N1bl9iZWhpbmRfcmFpbl9jbG91ZCc6J1xcdWQ4M2NcXHVkZjI2JyxcbiAgJ3N1bl9iZWhpbmRfc21hbGxfY2xvdWQnOidcXHVkODNjXFx1ZGYyNCcsXG4gICdzdW5fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWUnLFxuICAnc3VuZmxvd2VyJzonXFx1ZDgzY1xcdWRmM2InLFxuICAnc3VuZ2xhc3Nlcyc6J1xcdWQ4M2RcXHVkZTBlJyxcbiAgJ3N1bm55JzonXFx1MjYwMFxcdWZlMGYnLFxuICAnc3VucmlzZSc6J1xcdWQ4M2NcXHVkZjA1JyxcbiAgJ3N1bnJpc2Vfb3Zlcl9tb3VudGFpbnMnOidcXHVkODNjXFx1ZGYwNCcsXG4gICdzdXJmaW5nX21hbic6J1xcdWQ4M2NcXHVkZmM0JyxcbiAgJ3N1cmZpbmdfd29tYW4nOidcXHVkODNjXFx1ZGZjNCZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnc3VzaGknOidcXHVkODNjXFx1ZGY2MycsXG4gICdzdXNwZW5zaW9uX3JhaWx3YXknOidcXHVkODNkXFx1ZGU5ZicsXG4gICdzd2VhdCc6J1xcdWQ4M2RcXHVkZTEzJyxcbiAgJ3N3ZWF0X2Ryb3BzJzonXFx1ZDgzZFxcdWRjYTYnLFxuICAnc3dlYXRfc21pbGUnOidcXHVkODNkXFx1ZGUwNScsXG4gICdzd2VldF9wb3RhdG8nOidcXHVkODNjXFx1ZGY2MCcsXG4gICdzd2ltbWluZ19tYW4nOidcXHVkODNjXFx1ZGZjYScsXG4gICdzd2ltbWluZ193b21hbic6J1xcdWQ4M2NcXHVkZmNhJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdzeW1ib2xzJzonXFx1ZDgzZFxcdWRkMjMnLFxuICAnc3luYWdvZ3VlJzonXFx1ZDgzZFxcdWRkNGQnLFxuICAnc3lyaW5nZSc6J1xcdWQ4M2RcXHVkYzg5JyxcbiAgJ3RhY28nOidcXHVkODNjXFx1ZGYyZScsXG4gICd0YWRhJzonXFx1ZDgzY1xcdWRmODknLFxuICAndGFuYWJhdGFfdHJlZSc6J1xcdWQ4M2NcXHVkZjhiJyxcbiAgJ3RhdXJ1cyc6J1xcdTI2NDlcXHVmZTBmJyxcbiAgJ3RheGknOidcXHVkODNkXFx1ZGU5NScsXG4gICd0ZWEnOidcXHVkODNjXFx1ZGY3NScsXG4gICd0ZWxlcGhvbmVfcmVjZWl2ZXInOidcXHVkODNkXFx1ZGNkZScsXG4gICd0ZWxlc2NvcGUnOidcXHVkODNkXFx1ZGQyZCcsXG4gICd0ZW5uaXMnOidcXHVkODNjXFx1ZGZiZScsXG4gICd0ZW50JzonXFx1MjZmYVxcdWZlMGYnLFxuICAndGhlcm1vbWV0ZXInOidcXHVkODNjXFx1ZGYyMScsXG4gICd0aGlua2luZyc6J1xcdWQ4M2VcXHVkZDE0JyxcbiAgJ3Rob3VnaHRfYmFsbG9vbic6J1xcdWQ4M2RcXHVkY2FkJyxcbiAgJ3RpY2tldCc6J1xcdWQ4M2NcXHVkZmFiJyxcbiAgJ3RpY2tldHMnOidcXHVkODNjXFx1ZGY5ZicsXG4gICd0aWdlcic6J1xcdWQ4M2RcXHVkYzJmJyxcbiAgJ3RpZ2VyMic6J1xcdWQ4M2RcXHVkYzA1JyxcbiAgJ3RpbWVyX2Nsb2NrJzonXFx1MjNmMicsXG4gICd0aXBwaW5nX2hhbmRfbWFuJzonXFx1ZDgzZFxcdWRjODEmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ3RpcmVkX2ZhY2UnOidcXHVkODNkXFx1ZGUyYicsXG4gICd0bSc6J1xcdTIxMjJcXHVmZTBmJyxcbiAgJ3RvaWxldCc6J1xcdWQ4M2RcXHVkZWJkJyxcbiAgJ3Rva3lvX3Rvd2VyJzonXFx1ZDgzZFxcdWRkZmMnLFxuICAndG9tYXRvJzonXFx1ZDgzY1xcdWRmNDUnLFxuICAndG9uZ3VlJzonXFx1ZDgzZFxcdWRjNDUnLFxuICAndG9wJzonXFx1ZDgzZFxcdWRkMWQnLFxuICAndG9waGF0JzonXFx1ZDgzY1xcdWRmYTknLFxuICAndG9ybmFkbyc6J1xcdWQ4M2NcXHVkZjJhJyxcbiAgJ3RyYWNrYmFsbCc6J1xcdWQ4M2RcXHVkZGIyJyxcbiAgJ3RyYWN0b3InOidcXHVkODNkXFx1ZGU5YycsXG4gICd0cmFmZmljX2xpZ2h0JzonXFx1ZDgzZFxcdWRlYTUnLFxuICAndHJhaW4nOidcXHVkODNkXFx1ZGU4YicsXG4gICd0cmFpbjInOidcXHVkODNkXFx1ZGU4NicsXG4gICd0cmFtJzonXFx1ZDgzZFxcdWRlOGEnLFxuICAndHJpYW5ndWxhcl9mbGFnX29uX3Bvc3QnOidcXHVkODNkXFx1ZGVhOScsXG4gICd0cmlhbmd1bGFyX3J1bGVyJzonXFx1ZDgzZFxcdWRjZDAnLFxuICAndHJpZGVudCc6J1xcdWQ4M2RcXHVkZDMxJyxcbiAgJ3RyaXVtcGgnOidcXHVkODNkXFx1ZGUyNCcsXG4gICd0cm9sbGV5YnVzJzonXFx1ZDgzZFxcdWRlOGUnLFxuICAndHJvcGh5JzonXFx1ZDgzY1xcdWRmYzYnLFxuICAndHJvcGljYWxfZHJpbmsnOidcXHVkODNjXFx1ZGY3OScsXG4gICd0cm9waWNhbF9maXNoJzonXFx1ZDgzZFxcdWRjMjAnLFxuICAndHJ1Y2snOidcXHVkODNkXFx1ZGU5YScsXG4gICd0cnVtcGV0JzonXFx1ZDgzY1xcdWRmYmEnLFxuICAndHVsaXAnOidcXHVkODNjXFx1ZGYzNycsXG4gICd0dW1ibGVyX2dsYXNzJzonXFx1ZDgzZVxcdWRkNDMnLFxuICAndHVya2V5JzonXFx1ZDgzZVxcdWRkODMnLFxuICAndHVydGxlJzonXFx1ZDgzZFxcdWRjMjInLFxuICAndHYnOidcXHVkODNkXFx1ZGNmYScsXG4gICd0d2lzdGVkX3JpZ2h0d2FyZHNfYXJyb3dzJzonXFx1ZDgzZFxcdWRkMDAnLFxuICAndHdvX2hlYXJ0cyc6J1xcdWQ4M2RcXHVkYzk1JyxcbiAgJ3R3b19tZW5faG9sZGluZ19oYW5kcyc6J1xcdWQ4M2RcXHVkYzZjJyxcbiAgJ3R3b193b21lbl9ob2xkaW5nX2hhbmRzJzonXFx1ZDgzZFxcdWRjNmQnLFxuICAndTUyNzInOidcXHVkODNjXFx1ZGUzOScsXG4gICd1NTQwOCc6J1xcdWQ4M2NcXHVkZTM0JyxcbiAgJ3U1NWI2JzonXFx1ZDgzY1xcdWRlM2EnLFxuICAndTYzMDcnOidcXHVkODNjXFx1ZGUyZlxcdWZlMGYnLFxuICAndTY3MDgnOidcXHVkODNjXFx1ZGUzN1xcdWZlMGYnLFxuICAndTY3MDknOidcXHVkODNjXFx1ZGUzNicsXG4gICd1NmU4MCc6J1xcdWQ4M2NcXHVkZTM1JyxcbiAgJ3U3MTIxJzonXFx1ZDgzY1xcdWRlMWFcXHVmZTBmJyxcbiAgJ3U3NTMzJzonXFx1ZDgzY1xcdWRlMzgnLFxuICAndTc5ODEnOidcXHVkODNjXFx1ZGUzMicsXG4gICd1N2E3YSc6J1xcdWQ4M2NcXHVkZTMzJyxcbiAgJ3VtYnJlbGxhJzonXFx1MjYxNFxcdWZlMGYnLFxuICAndW5hbXVzZWQnOidcXHVkODNkXFx1ZGUxMicsXG4gICd1bmRlcmFnZSc6J1xcdWQ4M2RcXHVkZDFlJyxcbiAgJ3VuaWNvcm4nOidcXHVkODNlXFx1ZGQ4NCcsXG4gICd1bmxvY2snOidcXHVkODNkXFx1ZGQxMycsXG4gICd1cCc6J1xcdWQ4M2NcXHVkZDk5JyxcbiAgJ3Vwc2lkZV9kb3duX2ZhY2UnOidcXHVkODNkXFx1ZGU0MycsXG4gICd2JzonXFx1MjcwY1xcdWZlMGYnLFxuICAndmVydGljYWxfdHJhZmZpY19saWdodCc6J1xcdWQ4M2RcXHVkZWE2JyxcbiAgJ3Zocyc6J1xcdWQ4M2RcXHVkY2ZjJyxcbiAgJ3ZpYnJhdGlvbl9tb2RlJzonXFx1ZDgzZFxcdWRjZjMnLFxuICAndmlkZW9fY2FtZXJhJzonXFx1ZDgzZFxcdWRjZjknLFxuICAndmlkZW9fZ2FtZSc6J1xcdWQ4M2NcXHVkZmFlJyxcbiAgJ3Zpb2xpbic6J1xcdWQ4M2NcXHVkZmJiJyxcbiAgJ3ZpcmdvJzonXFx1MjY0ZFxcdWZlMGYnLFxuICAndm9sY2Fubyc6J1xcdWQ4M2NcXHVkZjBiJyxcbiAgJ3ZvbGxleWJhbGwnOidcXHVkODNjXFx1ZGZkMCcsXG4gICd2cyc6J1xcdWQ4M2NcXHVkZDlhJyxcbiAgJ3Z1bGNhbl9zYWx1dGUnOidcXHVkODNkXFx1ZGQ5NicsXG4gICd3YWxraW5nX21hbic6J1xcdWQ4M2RcXHVkZWI2JyxcbiAgJ3dhbGtpbmdfd29tYW4nOidcXHVkODNkXFx1ZGViNiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd2FuaW5nX2NyZXNjZW50X21vb24nOidcXHVkODNjXFx1ZGYxOCcsXG4gICd3YW5pbmdfZ2liYm91c19tb29uJzonXFx1ZDgzY1xcdWRmMTYnLFxuICAnd2FybmluZyc6J1xcdTI2YTBcXHVmZTBmJyxcbiAgJ3dhc3RlYmFza2V0JzonXFx1ZDgzZFxcdWRkZDEnLFxuICAnd2F0Y2gnOidcXHUyMzFhXFx1ZmUwZicsXG4gICd3YXRlcl9idWZmYWxvJzonXFx1ZDgzZFxcdWRjMDMnLFxuICAnd2F0ZXJtZWxvbic6J1xcdWQ4M2NcXHVkZjQ5JyxcbiAgJ3dhdmUnOidcXHVkODNkXFx1ZGM0YicsXG4gICd3YXZ5X2Rhc2gnOidcXHUzMDMwXFx1ZmUwZicsXG4gICd3YXhpbmdfY3Jlc2NlbnRfbW9vbic6J1xcdWQ4M2NcXHVkZjEyJyxcbiAgJ3djJzonXFx1ZDgzZFxcdWRlYmUnLFxuICAnd2VhcnknOidcXHVkODNkXFx1ZGUyOScsXG4gICd3ZWRkaW5nJzonXFx1ZDgzZFxcdWRjOTInLFxuICAnd2VpZ2h0X2xpZnRpbmdfbWFuJzonXFx1ZDgzY1xcdWRmY2JcXHVmZTBmJyxcbiAgJ3dlaWdodF9saWZ0aW5nX3dvbWFuJzonXFx1ZDgzY1xcdWRmY2JcXHVmZTBmJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3aGFsZSc6J1xcdWQ4M2RcXHVkYzMzJyxcbiAgJ3doYWxlMic6J1xcdWQ4M2RcXHVkYzBiJyxcbiAgJ3doZWVsX29mX2RoYXJtYSc6J1xcdTI2MzhcXHVmZTBmJyxcbiAgJ3doZWVsY2hhaXInOidcXHUyNjdmXFx1ZmUwZicsXG4gICd3aGl0ZV9jaGVja19tYXJrJzonXFx1MjcwNScsXG4gICd3aGl0ZV9jaXJjbGUnOidcXHUyNmFhXFx1ZmUwZicsXG4gICd3aGl0ZV9mbGFnJzonXFx1ZDgzY1xcdWRmZjNcXHVmZTBmJyxcbiAgJ3doaXRlX2Zsb3dlcic6J1xcdWQ4M2RcXHVkY2FlJyxcbiAgJ3doaXRlX2xhcmdlX3NxdWFyZSc6J1xcdTJiMWNcXHVmZTBmJyxcbiAgJ3doaXRlX21lZGl1bV9zbWFsbF9zcXVhcmUnOidcXHUyNWZkXFx1ZmUwZicsXG4gICd3aGl0ZV9tZWRpdW1fc3F1YXJlJzonXFx1MjVmYlxcdWZlMGYnLFxuICAnd2hpdGVfc21hbGxfc3F1YXJlJzonXFx1MjVhYlxcdWZlMGYnLFxuICAnd2hpdGVfc3F1YXJlX2J1dHRvbic6J1xcdWQ4M2RcXHVkZDMzJyxcbiAgJ3dpbHRlZF9mbG93ZXInOidcXHVkODNlXFx1ZGQ0MCcsXG4gICd3aW5kX2NoaW1lJzonXFx1ZDgzY1xcdWRmOTAnLFxuICAnd2luZF9mYWNlJzonXFx1ZDgzY1xcdWRmMmMnLFxuICAnd2luZV9nbGFzcyc6J1xcdWQ4M2NcXHVkZjc3JyxcbiAgJ3dpbmsnOidcXHVkODNkXFx1ZGUwOScsXG4gICd3b2xmJzonXFx1ZDgzZFxcdWRjM2EnLFxuICAnd29tYW4nOidcXHVkODNkXFx1ZGM2OScsXG4gICd3b21hbl9hcnRpc3QnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmYTgnLFxuICAnd29tYW5fYXN0cm9uYXV0JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkZTgwJyxcbiAgJ3dvbWFuX2NhcnR3aGVlbGluZyc6J1xcdWQ4M2VcXHVkZDM4Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbl9jb29rJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZjczJyxcbiAgJ3dvbWFuX2ZhY2VwYWxtaW5nJzonXFx1ZDgzZVxcdWRkMjYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWFuX2ZhY3Rvcnlfd29ya2VyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZmVkJyxcbiAgJ3dvbWFuX2Zhcm1lcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGYzZScsXG4gICd3b21hbl9maXJlZmlnaHRlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGU5MicsXG4gICd3b21hbl9oZWFsdGhfd29ya2VyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdTI2OTVcXHVmZTBmJyxcbiAgJ3dvbWFuX2p1ZGdlJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdTI2OTZcXHVmZTBmJyxcbiAgJ3dvbWFuX2p1Z2dsaW5nJzonXFx1ZDgzZVxcdWRkMzkmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWFuX21lY2hhbmljJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkZDI3JyxcbiAgJ3dvbWFuX29mZmljZV93b3JrZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjYmMnLFxuICAnd29tYW5fcGlsb3QnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1MjcwOFxcdWZlMGYnLFxuICAnd29tYW5fcGxheWluZ19oYW5kYmFsbCc6J1xcdWQ4M2VcXHVkZDNlJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbl9wbGF5aW5nX3dhdGVyX3BvbG8nOidcXHVkODNlXFx1ZGQzZCZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fc2NpZW50aXN0JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkZDJjJyxcbiAgJ3dvbWFuX3NocnVnZ2luZyc6J1xcdWQ4M2VcXHVkZDM3Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbl9zaW5nZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmYTQnLFxuICAnd29tYW5fc3R1ZGVudCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGY5MycsXG4gICd3b21hbl90ZWFjaGVyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZmViJyxcbiAgJ3dvbWFuX3RlY2hub2xvZ2lzdCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGNiYicsXG4gICd3b21hbl93aXRoX3R1cmJhbic6J1xcdWQ4M2RcXHVkYzczJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbnNfY2xvdGhlcyc6J1xcdWQ4M2RcXHVkYzVhJyxcbiAgJ3dvbWFuc19oYXQnOidcXHVkODNkXFx1ZGM1MicsXG4gICd3b21lbl93cmVzdGxpbmcnOidcXHVkODNlXFx1ZGQzYyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tZW5zJzonXFx1ZDgzZFxcdWRlYmEnLFxuICAnd29ybGRfbWFwJzonXFx1ZDgzZFxcdWRkZmEnLFxuICAnd29ycmllZCc6J1xcdWQ4M2RcXHVkZTFmJyxcbiAgJ3dyZW5jaCc6J1xcdWQ4M2RcXHVkZDI3JyxcbiAgJ3dyaXRpbmdfaGFuZCc6J1xcdTI3MGRcXHVmZTBmJyxcbiAgJ3gnOidcXHUyNzRjJyxcbiAgJ3llbGxvd19oZWFydCc6J1xcdWQ4M2RcXHVkYzliJyxcbiAgJ3llbic6J1xcdWQ4M2RcXHVkY2I0JyxcbiAgJ3lpbl95YW5nJzonXFx1MjYyZlxcdWZlMGYnLFxuICAneXVtJzonXFx1ZDgzZFxcdWRlMGInLFxuICAnemFwJzonXFx1MjZhMVxcdWZlMGYnLFxuICAnemlwcGVyX21vdXRoX2ZhY2UnOidcXHVkODNlXFx1ZGQxMCcsXG4gICd6enonOidcXHVkODNkXFx1ZGNhNCcsXG5cbiAgLyogc3BlY2lhbCBlbW9qaXMgOlAgKi9cbiAgJ29jdG9jYXQnOiAgJzxpbWcgYWx0PVwiOm9jdG9jYXQ6XCIgaGVpZ2h0PVwiMjBcIiB3aWR0aD1cIjIwXCIgYWxpZ249XCJhYnNtaWRkbGVcIiBzcmM9XCJodHRwczovL2Fzc2V0cy1jZG4uZ2l0aHViLmNvbS9pbWFnZXMvaWNvbnMvZW1vamkvb2N0b2NhdC5wbmdcIj4nLFxuICAnc2hvd2Rvd24nOiAnPHNwYW4gc3R5bGU9XCJmb250LWZhbWlseTogXFwnQW5vbnltb3VzIFByb1xcJywgbW9ub3NwYWNlOyB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTsgdGV4dC1kZWNvcmF0aW9uLXN0eWxlOiBkYXNoZWQ7IHRleHQtZGVjb3JhdGlvbi1jb2xvcjogIzNlOGI4YTt0ZXh0LXVuZGVybGluZS1wb3NpdGlvbjogdW5kZXI7XCI+Uzwvc3Bhbj4nXG59O1xuXHJcbi8qKlxuICogQ3JlYXRlZCBieSBFc3RldmFvIG9uIDMxLTA1LTIwMTUuXG4gKi9cblxuLyoqXG4gKiBTaG93ZG93biBDb252ZXJ0ZXIgY2xhc3NcbiAqIEBjbGFzc1xuICogQHBhcmFtIHtvYmplY3R9IFtjb252ZXJ0ZXJPcHRpb25zXVxuICogQHJldHVybnMge0NvbnZlcnRlcn1cbiAqL1xuc2hvd2Rvd24uQ29udmVydGVyID0gZnVuY3Rpb24gKGNvbnZlcnRlck9wdGlvbnMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhclxuICAgICAgLyoqXG4gICAgICAgKiBPcHRpb25zIHVzZWQgYnkgdGhpcyBjb252ZXJ0ZXJcbiAgICAgICAqIEBwcml2YXRlXG4gICAgICAgKiBAdHlwZSB7e319XG4gICAgICAgKi9cbiAgICAgIG9wdGlvbnMgPSB7fSxcblxuICAgICAgLyoqXG4gICAgICAgKiBMYW5ndWFnZSBleHRlbnNpb25zIHVzZWQgYnkgdGhpcyBjb252ZXJ0ZXJcbiAgICAgICAqIEBwcml2YXRlXG4gICAgICAgKiBAdHlwZSB7QXJyYXl9XG4gICAgICAgKi9cbiAgICAgIGxhbmdFeHRlbnNpb25zID0gW10sXG5cbiAgICAgIC8qKlxuICAgICAgICogT3V0cHV0IG1vZGlmaWVycyBleHRlbnNpb25zIHVzZWQgYnkgdGhpcyBjb252ZXJ0ZXJcbiAgICAgICAqIEBwcml2YXRlXG4gICAgICAgKiBAdHlwZSB7QXJyYXl9XG4gICAgICAgKi9cbiAgICAgIG91dHB1dE1vZGlmaWVycyA9IFtdLFxuXG4gICAgICAvKipcbiAgICAgICAqIEV2ZW50IGxpc3RlbmVyc1xuICAgICAgICogQHByaXZhdGVcbiAgICAgICAqIEB0eXBlIHt7fX1cbiAgICAgICAqL1xuICAgICAgbGlzdGVuZXJzID0ge30sXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZsYXZvciBzZXQgaW4gdGhpcyBjb252ZXJ0ZXJcbiAgICAgICAqL1xuICAgICAgc2V0Q29udkZsYXZvciA9IHNldEZsYXZvcixcblxuICAgICAgLyoqXG4gICAgICAgKiBNZXRhZGF0YSBvZiB0aGUgZG9jdW1lbnRcbiAgICAgICAqIEB0eXBlIHt7cGFyc2VkOiB7fSwgcmF3OiBzdHJpbmcsIGZvcm1hdDogc3RyaW5nfX1cbiAgICAgICAqL1xuICAgICAgbWV0YWRhdGEgPSB7XG4gICAgICAgIHBhcnNlZDoge30sXG4gICAgICAgIHJhdzogJycsXG4gICAgICAgIGZvcm1hdDogJydcbiAgICAgIH07XG5cbiAgX2NvbnN0cnVjdG9yKCk7XG5cbiAgLyoqXG4gICAqIENvbnZlcnRlciBjb25zdHJ1Y3RvclxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZnVuY3Rpb24gX2NvbnN0cnVjdG9yICgpIHtcbiAgICBjb252ZXJ0ZXJPcHRpb25zID0gY29udmVydGVyT3B0aW9ucyB8fCB7fTtcblxuICAgIGZvciAodmFyIGdPcHQgaW4gZ2xvYmFsT3B0aW9ucykge1xuICAgICAgaWYgKGdsb2JhbE9wdGlvbnMuaGFzT3duUHJvcGVydHkoZ09wdCkpIHtcbiAgICAgICAgb3B0aW9uc1tnT3B0XSA9IGdsb2JhbE9wdGlvbnNbZ09wdF07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gTWVyZ2Ugb3B0aW9uc1xuICAgIGlmICh0eXBlb2YgY29udmVydGVyT3B0aW9ucyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGZvciAodmFyIG9wdCBpbiBjb252ZXJ0ZXJPcHRpb25zKSB7XG4gICAgICAgIGlmIChjb252ZXJ0ZXJPcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpIHtcbiAgICAgICAgICBvcHRpb25zW29wdF0gPSBjb252ZXJ0ZXJPcHRpb25zW29wdF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IoJ0NvbnZlcnRlciBleHBlY3RzIHRoZSBwYXNzZWQgcGFyYW1ldGVyIHRvIGJlIGFuIG9iamVjdCwgYnV0ICcgKyB0eXBlb2YgY29udmVydGVyT3B0aW9ucyArXG4gICAgICAnIHdhcyBwYXNzZWQgaW5zdGVhZC4nKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5leHRlbnNpb25zKSB7XG4gICAgICBzaG93ZG93bi5oZWxwZXIuZm9yRWFjaChvcHRpb25zLmV4dGVuc2lvbnMsIF9wYXJzZUV4dGVuc2lvbik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIGV4dGVuc2lvblxuICAgKiBAcGFyYW0geyp9IGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWU9JyddXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBmdW5jdGlvbiBfcGFyc2VFeHRlbnNpb24gKGV4dCwgbmFtZSkge1xuXG4gICAgbmFtZSA9IG5hbWUgfHwgbnVsbDtcbiAgICAvLyBJZiBpdCdzIGEgc3RyaW5nLCB0aGUgZXh0ZW5zaW9uIHdhcyBwcmV2aW91c2x5IGxvYWRlZFxuICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcoZXh0KSkge1xuICAgICAgZXh0ID0gc2hvd2Rvd24uaGVscGVyLnN0ZEV4dE5hbWUoZXh0KTtcbiAgICAgIG5hbWUgPSBleHQ7XG5cbiAgICAgIC8vIExFR0FDWV9TVVBQT1JUIENPREVcbiAgICAgIGlmIChzaG93ZG93bi5leHRlbnNpb25zW2V4dF0pIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdERVBSRUNBVElPTiBXQVJOSU5HOiAnICsgZXh0ICsgJyBpcyBhbiBvbGQgZXh0ZW5zaW9uIHRoYXQgdXNlcyBhIGRlcHJlY2F0ZWQgbG9hZGluZyBtZXRob2QuJyArXG4gICAgICAgICAgJ1BsZWFzZSBpbmZvcm0gdGhlIGRldmVsb3BlciB0aGF0IHRoZSBleHRlbnNpb24gc2hvdWxkIGJlIHVwZGF0ZWQhJyk7XG4gICAgICAgIGxlZ2FjeUV4dGVuc2lvbkxvYWRpbmcoc2hvd2Rvd24uZXh0ZW5zaW9uc1tleHRdLCBleHQpO1xuICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIEVORCBMRUdBQ1kgU1VQUE9SVCBDT0RFXG5cbiAgICAgIH0gZWxzZSBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChleHRlbnNpb25zW2V4dF0pKSB7XG4gICAgICAgIGV4dCA9IGV4dGVuc2lvbnNbZXh0XTtcblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ0V4dGVuc2lvbiBcIicgKyBleHQgKyAnXCIgY291bGQgbm90IGJlIGxvYWRlZC4gSXQgd2FzIGVpdGhlciBub3QgZm91bmQgb3IgaXMgbm90IGEgdmFsaWQgZXh0ZW5zaW9uLicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlb2YgZXh0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBleHQgPSBleHQoKTtcbiAgICB9XG5cbiAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0FycmF5KGV4dCkpIHtcbiAgICAgIGV4dCA9IFtleHRdO1xuICAgIH1cblxuICAgIHZhciB2YWxpZEV4dCA9IHZhbGlkYXRlKGV4dCwgbmFtZSk7XG4gICAgaWYgKCF2YWxpZEV4dC52YWxpZCkge1xuICAgICAgdGhyb3cgRXJyb3IodmFsaWRFeHQuZXJyb3IpO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXh0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBzd2l0Y2ggKGV4dFtpXS50eXBlKSB7XG5cbiAgICAgICAgY2FzZSAnbGFuZyc6XG4gICAgICAgICAgbGFuZ0V4dGVuc2lvbnMucHVzaChleHRbaV0pO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ291dHB1dCc6XG4gICAgICAgICAgb3V0cHV0TW9kaWZpZXJzLnB1c2goZXh0W2ldKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmIChleHRbaV0uaGFzT3duUHJvcGVydHkoJ2xpc3RlbmVycycpKSB7XG4gICAgICAgIGZvciAodmFyIGxuIGluIGV4dFtpXS5saXN0ZW5lcnMpIHtcbiAgICAgICAgICBpZiAoZXh0W2ldLmxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShsbikpIHtcbiAgICAgICAgICAgIGxpc3RlbihsbiwgZXh0W2ldLmxpc3RlbmVyc1tsbl0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICB9XG5cbiAgLyoqXG4gICAqIExFR0FDWV9TVVBQT1JUXG4gICAqIEBwYXJhbSB7Kn0gZXh0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqL1xuICBmdW5jdGlvbiBsZWdhY3lFeHRlbnNpb25Mb2FkaW5nIChleHQsIG5hbWUpIHtcbiAgICBpZiAodHlwZW9mIGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZXh0ID0gZXh0KG5ldyBzaG93ZG93bi5Db252ZXJ0ZXIoKSk7XG4gICAgfVxuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0KSkge1xuICAgICAgZXh0ID0gW2V4dF07XG4gICAgfVxuICAgIHZhciB2YWxpZCA9IHZhbGlkYXRlKGV4dCwgbmFtZSk7XG5cbiAgICBpZiAoIXZhbGlkLnZhbGlkKSB7XG4gICAgICB0aHJvdyBFcnJvcih2YWxpZC5lcnJvcik7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBleHQubGVuZ3RoOyArK2kpIHtcbiAgICAgIHN3aXRjaCAoZXh0W2ldLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnbGFuZyc6XG4gICAgICAgICAgbGFuZ0V4dGVuc2lvbnMucHVzaChleHRbaV0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdvdXRwdXQnOlxuICAgICAgICAgIG91dHB1dE1vZGlmaWVycy5wdXNoKGV4dFtpXSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6Ly8gc2hvdWxkIG5ldmVyIHJlYWNoIGhlcmVcbiAgICAgICAgICB0aHJvdyBFcnJvcignRXh0ZW5zaW9uIGxvYWRlciBlcnJvcjogVHlwZSB1bnJlY29nbml6ZWQhISEnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTGlzdGVuIHRvIGFuIGV2ZW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBmdW5jdGlvbiBsaXN0ZW4gKG5hbWUsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcobmFtZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdJbnZhbGlkIGFyZ3VtZW50IGluIGNvbnZlcnRlci5saXN0ZW4oKSBtZXRob2Q6IG5hbWUgbXVzdCBiZSBhIHN0cmluZywgYnV0ICcgKyB0eXBlb2YgbmFtZSArICcgZ2l2ZW4nKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyBFcnJvcignSW52YWxpZCBhcmd1bWVudCBpbiBjb252ZXJ0ZXIubGlzdGVuKCkgbWV0aG9kOiBjYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24sIGJ1dCAnICsgdHlwZW9mIGNhbGxiYWNrICsgJyBnaXZlbicpO1xuICAgIH1cblxuICAgIGlmICghbGlzdGVuZXJzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICBsaXN0ZW5lcnNbbmFtZV0gPSBbXTtcbiAgICB9XG4gICAgbGlzdGVuZXJzW25hbWVdLnB1c2goY2FsbGJhY2spO1xuICB9XG5cbiAgZnVuY3Rpb24gclRyaW1JbnB1dFRleHQgKHRleHQpIHtcbiAgICB2YXIgcnNwID0gdGV4dC5tYXRjaCgvXlxccyovKVswXS5sZW5ndGgsXG4gICAgICAgIHJneCA9IG5ldyBSZWdFeHAoJ15cXFxcc3swLCcgKyByc3AgKyAnfScsICdnbScpO1xuICAgIHJldHVybiB0ZXh0LnJlcGxhY2Uocmd4LCAnJyk7XG4gIH1cblxuICAvKipcbiAgICogRGlzcGF0Y2ggYW4gZXZlbnRcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV2dE5hbWUgRXZlbnQgbmFtZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCBUZXh0XG4gICAqIEBwYXJhbSB7e319IG9wdGlvbnMgQ29udmVydGVyIE9wdGlvbnNcbiAgICogQHBhcmFtIHt7fX0gZ2xvYmFsc1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgdGhpcy5fZGlzcGF0Y2ggPSBmdW5jdGlvbiBkaXNwYXRjaCAoZXZ0TmFtZSwgdGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoZXZ0TmFtZSkpIHtcbiAgICAgIGZvciAodmFyIGVpID0gMDsgZWkgPCBsaXN0ZW5lcnNbZXZ0TmFtZV0ubGVuZ3RoOyArK2VpKSB7XG4gICAgICAgIHZhciBuVGV4dCA9IGxpc3RlbmVyc1tldnROYW1lXVtlaV0oZXZ0TmFtZSwgdGV4dCwgdGhpcywgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIGlmIChuVGV4dCAmJiB0eXBlb2YgblRleHQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGV4dCA9IG5UZXh0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0ZXh0O1xuICB9O1xuXG4gIC8qKlxuICAgKiBMaXN0ZW4gdG8gYW4gZXZlbnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICogQHJldHVybnMge3Nob3dkb3duLkNvbnZlcnRlcn1cbiAgICovXG4gIHRoaXMubGlzdGVuID0gZnVuY3Rpb24gKG5hbWUsIGNhbGxiYWNrKSB7XG4gICAgbGlzdGVuKG5hbWUsIGNhbGxiYWNrKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICAvKipcbiAgICogQ29udmVydHMgYSBtYXJrZG93biBzdHJpbmcgaW50byBIVE1MXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgdGhpcy5tYWtlSHRtbCA9IGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgLy9jaGVjayBpZiB0ZXh0IGlzIG5vdCBmYWxzeVxuICAgIGlmICghdGV4dCkge1xuICAgICAgcmV0dXJuIHRleHQ7XG4gICAgfVxuXG4gICAgdmFyIGdsb2JhbHMgPSB7XG4gICAgICBnSHRtbEJsb2NrczogICAgIFtdLFxuICAgICAgZ0h0bWxNZEJsb2NrczogICBbXSxcbiAgICAgIGdIdG1sU3BhbnM6ICAgICAgW10sXG4gICAgICBnVXJsczogICAgICAgICAgIHt9LFxuICAgICAgZ1RpdGxlczogICAgICAgICB7fSxcbiAgICAgIGdEaW1lbnNpb25zOiAgICAge30sXG4gICAgICBnTGlzdExldmVsOiAgICAgIDAsXG4gICAgICBoYXNoTGlua0NvdW50czogIHt9LFxuICAgICAgbGFuZ0V4dGVuc2lvbnM6ICBsYW5nRXh0ZW5zaW9ucyxcbiAgICAgIG91dHB1dE1vZGlmaWVyczogb3V0cHV0TW9kaWZpZXJzLFxuICAgICAgY29udmVydGVyOiAgICAgICB0aGlzLFxuICAgICAgZ2hDb2RlQmxvY2tzOiAgICBbXSxcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIHBhcnNlZDoge30sXG4gICAgICAgIHJhdzogJycsXG4gICAgICAgIGZvcm1hdDogJydcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLy8gVGhpcyBsZXRzIHVzIHVzZSDCqCB0cmVtYSBhcyBhbiBlc2NhcGUgY2hhciB0byBhdm9pZCBtZDUgaGFzaGVzXG4gICAgLy8gVGhlIGNob2ljZSBvZiBjaGFyYWN0ZXIgaXMgYXJiaXRyYXJ5OyBhbnl0aGluZyB0aGF0IGlzbid0XG4gICAgLy8gbWFnaWMgaW4gTWFya2Rvd24gd2lsbCB3b3JrLlxuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoL2csICfCqFQnKTtcblxuICAgIC8vIFJlcGxhY2UgJCB3aXRoIMKoRFxuICAgIC8vIFJlZ0V4cCBpbnRlcnByZXRzICQgYXMgYSBzcGVjaWFsIGNoYXJhY3RlclxuICAgIC8vIHdoZW4gaXQncyBpbiBhIHJlcGxhY2VtZW50IHN0cmluZ1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcJC9nLCAnwqhEJyk7XG5cbiAgICAvLyBTdGFuZGFyZGl6ZSBsaW5lIGVuZGluZ3NcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpOyAvLyBET1MgdG8gVW5peFxuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcci9nLCAnXFxuJyk7IC8vIE1hYyB0byBVbml4XG5cbiAgICAvLyBTdGFyZGFyZGl6ZSBsaW5lIHNwYWNlc1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcdTAwQTAvZywgJyZuYnNwOycpO1xuXG4gICAgaWYgKG9wdGlvbnMuc21hcnRJbmRlbnRhdGlvbkZpeCkge1xuICAgICAgdGV4dCA9IHJUcmltSW5wdXRUZXh0KHRleHQpO1xuICAgIH1cblxuICAgIC8vIE1ha2Ugc3VyZSB0ZXh0IGJlZ2lucyBhbmQgZW5kcyB3aXRoIGEgY291cGxlIG9mIG5ld2xpbmVzOlxuICAgIHRleHQgPSAnXFxuXFxuJyArIHRleHQgKyAnXFxuXFxuJztcblxuICAgIC8vIGRldGFiXG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZGV0YWInKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAgIC8qKlxuICAgICAqIFN0cmlwIGFueSBsaW5lcyBjb25zaXN0aW5nIG9ubHkgb2Ygc3BhY2VzIGFuZCB0YWJzLlxuICAgICAqIFRoaXMgbWFrZXMgc3Vic2VxdWVudCByZWdleHMgZWFzaWVyIHRvIHdyaXRlLCBiZWNhdXNlIHdlIGNhblxuICAgICAqIG1hdGNoIGNvbnNlY3V0aXZlIGJsYW5rIGxpbmVzIHdpdGggL1xcbisvIGluc3RlYWQgb2Ygc29tZXRoaW5nXG4gICAgICogY29udG9ydGVkIGxpa2UgL1sgXFx0XSpcXG4rL1xuICAgICAqL1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15bIFxcdF0rJC9tZywgJycpO1xuXG4gICAgLy9ydW4gbGFuZ3VhZ2VFeHRlbnNpb25zXG4gICAgc2hvd2Rvd24uaGVscGVyLmZvckVhY2gobGFuZ0V4dGVuc2lvbnMsIGZ1bmN0aW9uIChleHQpIHtcbiAgICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3J1bkV4dGVuc2lvbicpKGV4dCwgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgfSk7XG5cbiAgICAvLyBydW4gdGhlIHN1YiBwYXJzZXJzXG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWV0YWRhdGEnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoUHJlQ29kZVRhZ3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdnaXRodWJDb2RlQmxvY2tzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxCbG9ja3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQ29kZVRhZ3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzdHJpcExpbmtEZWZpbml0aW9ucycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2Jsb2NrR2FtdXQnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmhhc2hIVE1MU3BhbnMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmVzY2FwZVNwZWNpYWxDaGFycycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gICAgLy8gYXR0YWNrbGFiOiBSZXN0b3JlIGRvbGxhciBzaWduc1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoRC9nLCAnJCQnKTtcblxuICAgIC8vIGF0dGFja2xhYjogUmVzdG9yZSB0cmVtYXNcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqFQvZywgJ8KoJyk7XG5cbiAgICAvLyByZW5kZXIgYSBjb21wbGV0ZSBodG1sIGRvY3VtZW50IGluc3RlYWQgb2YgYSBwYXJ0aWFsIGlmIHRoZSBvcHRpb24gaXMgZW5hYmxlZFxuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2NvbXBsZXRlSFRNTERvY3VtZW50JykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgICAvLyBSdW4gb3V0cHV0IG1vZGlmaWVyc1xuICAgIHNob3dkb3duLmhlbHBlci5mb3JFYWNoKG91dHB1dE1vZGlmaWVycywgZnVuY3Rpb24gKGV4dCkge1xuICAgICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcigncnVuRXh0ZW5zaW9uJykoZXh0LCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB9KTtcblxuICAgIC8vIHVwZGF0ZSBtZXRhZGF0YVxuICAgIG1ldGFkYXRhID0gZ2xvYmFscy5tZXRhZGF0YTtcbiAgICByZXR1cm4gdGV4dDtcbiAgfTtcblxuICAvKipcbiAgICogQ29udmVydHMgYW4gSFRNTCBzdHJpbmcgaW50byBhIG1hcmtkb3duIHN0cmluZ1xuICAgKiBAcGFyYW0gc3JjXG4gICAqIEBwYXJhbSBbSFRNTFBhcnNlcl0gQSBXSEFUV0cgRE9NIGFuZCBIVE1MIHBhcnNlciwgc3VjaCBhcyBKU0RPTS4gSWYgbm9uZSBpcyBzdXBwbGllZCwgd2luZG93LmRvY3VtZW50IHdpbGwgYmUgdXNlZC5cbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHRoaXMubWFrZU1hcmtkb3duID0gdGhpcy5tYWtlTWQgPSBmdW5jdGlvbiAoc3JjLCBIVE1MUGFyc2VyKSB7XG5cbiAgICAvLyByZXBsYWNlIFxcclxcbiB3aXRoIFxcblxuICAgIHNyYyA9IHNyYy5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpO1xuICAgIHNyYyA9IHNyYy5yZXBsYWNlKC9cXHIvZywgJ1xcbicpOyAvLyBvbGQgbWFjc1xuXG4gICAgLy8gZHVlIHRvIGFuIGVkZ2UgY2FzZSwgd2UgbmVlZCB0byBmaW5kIHRoaXM6ID4gPFxuICAgIC8vIHRvIHByZXZlbnQgcmVtb3Zpbmcgb2Ygbm9uIHNpbGVudCB3aGl0ZSBzcGFjZXNcbiAgICAvLyBleDogPGVtPnRoaXMgaXM8L2VtPiA8c3Ryb25nPnNwYXJ0YTwvc3Ryb25nPlxuICAgIHNyYyA9IHNyYy5yZXBsYWNlKC8+WyBcXHRdKzwvLCAnPsKoTkJTUDs8Jyk7XG5cbiAgICBpZiAoIUhUTUxQYXJzZXIpIHtcbiAgICAgIGlmICh3aW5kb3cgJiYgd2luZG93LmRvY3VtZW50KSB7XG4gICAgICAgIEhUTUxQYXJzZXIgPSB3aW5kb3cuZG9jdW1lbnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0hUTUxQYXJzZXIgaXMgdW5kZWZpbmVkLiBJZiBpbiBhIHdlYndvcmtlciBvciBub2RlanMgZW52aXJvbm1lbnQsIHlvdSBuZWVkIHRvIHByb3ZpZGUgYSBXSEFUV0cgRE9NIGFuZCBIVE1MIHN1Y2ggYXMgSlNET00nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZG9jID0gSFRNTFBhcnNlci5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBkb2MuaW5uZXJIVE1MID0gc3JjO1xuXG4gICAgdmFyIGdsb2JhbHMgPSB7XG4gICAgICBwcmVMaXN0OiBzdWJzdGl0dXRlUHJlQ29kZVRhZ3MoZG9jKVxuICAgIH07XG5cbiAgICAvLyByZW1vdmUgYWxsIG5ld2xpbmVzIGFuZCBjb2xsYXBzZSBzcGFjZXNcbiAgICBjbGVhbihkb2MpO1xuXG4gICAgLy8gc29tZSBzdHVmZiwgbGlrZSBhY2NpZGVudGFsIHJlZmVyZW5jZSBsaW5rcyBtdXN0IG5vdyBiZSBlc2NhcGVkXG4gICAgLy8gVE9ET1xuICAgIC8vIGRvYy5pbm5lckhUTUwgPSBkb2MuaW5uZXJIVE1MLnJlcGxhY2UoL1xcW1tcXFNcXHQgXV0vKTtcblxuICAgIHZhciBub2RlcyA9IGRvYy5jaGlsZE5vZGVzLFxuICAgICAgICBtZERvYyA9ICcnO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgbWREb2MgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKG5vZGVzW2ldLCBnbG9iYWxzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbGVhbiAobm9kZSkge1xuICAgICAgZm9yICh2YXIgbiA9IDA7IG4gPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyArK24pIHtcbiAgICAgICAgdmFyIGNoaWxkID0gbm9kZS5jaGlsZE5vZGVzW25dO1xuICAgICAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICBpZiAoIS9cXFMvLnRlc3QoY2hpbGQubm9kZVZhbHVlKSkge1xuICAgICAgICAgICAgbm9kZS5yZW1vdmVDaGlsZChjaGlsZCk7XG4gICAgICAgICAgICAtLW47XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoaWxkLm5vZGVWYWx1ZSA9IGNoaWxkLm5vZGVWYWx1ZS5zcGxpdCgnXFxuJykuam9pbignICcpO1xuICAgICAgICAgICAgY2hpbGQubm9kZVZhbHVlID0gY2hpbGQubm9kZVZhbHVlLnJlcGxhY2UoLyhcXHMpKy9nLCAnJDEnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoY2hpbGQubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgICBjbGVhbihjaGlsZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmaW5kIGFsbCBwcmUgdGFncyBhbmQgcmVwbGFjZSBjb250ZW50cyB3aXRoIHBsYWNlaG9sZGVyXG4gICAgLy8gd2UgbmVlZCB0aGlzIHNvIHRoYXQgd2UgY2FuIHJlbW92ZSBhbGwgaW5kZW50YXRpb24gZnJvbSBodG1sXG4gICAgLy8gdG8gZWFzZSB1cCBwYXJzaW5nXG4gICAgZnVuY3Rpb24gc3Vic3RpdHV0ZVByZUNvZGVUYWdzIChkb2MpIHtcblxuICAgICAgdmFyIHByZXMgPSBkb2MucXVlcnlTZWxlY3RvckFsbCgncHJlJyksXG4gICAgICAgICAgcHJlc1BIID0gW107XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlcy5sZW5ndGg7ICsraSkge1xuXG4gICAgICAgIGlmIChwcmVzW2ldLmNoaWxkRWxlbWVudENvdW50ID09PSAxICYmIHByZXNbaV0uZmlyc3RDaGlsZC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdjb2RlJykge1xuICAgICAgICAgIHZhciBjb250ZW50ID0gcHJlc1tpXS5maXJzdENoaWxkLmlubmVySFRNTC50cmltKCksXG4gICAgICAgICAgICAgIGxhbmd1YWdlID0gcHJlc1tpXS5maXJzdENoaWxkLmdldEF0dHJpYnV0ZSgnZGF0YS1sYW5ndWFnZScpIHx8ICcnO1xuXG4gICAgICAgICAgLy8gaWYgZGF0YS1sYW5ndWFnZSBhdHRyaWJ1dGUgaXMgbm90IGRlZmluZWQsIHRoZW4gd2UgbG9vayBmb3IgY2xhc3MgbGFuZ3VhZ2UtKlxuICAgICAgICAgIGlmIChsYW5ndWFnZSA9PT0gJycpIHtcbiAgICAgICAgICAgIHZhciBjbGFzc2VzID0gcHJlc1tpXS5maXJzdENoaWxkLmNsYXNzTmFtZS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgZm9yICh2YXIgYyA9IDA7IGMgPCBjbGFzc2VzLmxlbmd0aDsgKytjKSB7XG4gICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gY2xhc3Nlc1tjXS5tYXRjaCgvXmxhbmd1YWdlLSguKykkLyk7XG4gICAgICAgICAgICAgIGlmIChtYXRjaGVzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbGFuZ3VhZ2UgPSBtYXRjaGVzWzFdO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gdW5lc2NhcGUgaHRtbCBlbnRpdGllcyBpbiBjb250ZW50XG4gICAgICAgICAgY29udGVudCA9IHNob3dkb3duLmhlbHBlci51bmVzY2FwZUhUTUxFbnRpdGllcyhjb250ZW50KTtcblxuICAgICAgICAgIHByZXNQSC5wdXNoKGNvbnRlbnQpO1xuICAgICAgICAgIHByZXNbaV0ub3V0ZXJIVE1MID0gJzxwcmVjb2RlIGxhbmd1YWdlPVwiJyArIGxhbmd1YWdlICsgJ1wiIHByZWNvZGVudW09XCInICsgaS50b1N0cmluZygpICsgJ1wiPjwvcHJlY29kZT4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHByZXNQSC5wdXNoKHByZXNbaV0uaW5uZXJIVE1MKTtcbiAgICAgICAgICBwcmVzW2ldLmlubmVySFRNTCA9ICcnO1xuICAgICAgICAgIHByZXNbaV0uc2V0QXR0cmlidXRlKCdwcmVudW0nLCBpLnRvU3RyaW5nKCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJlc1BIO1xuICAgIH1cblxuICAgIHJldHVybiBtZERvYztcbiAgfTtcblxuICAvKipcbiAgICogU2V0IGFuIG9wdGlvbiBvZiB0aGlzIENvbnZlcnRlciBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5XG4gICAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAgICovXG4gIHRoaXMuc2V0T3B0aW9uID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICBvcHRpb25zW2tleV0gPSB2YWx1ZTtcbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBvcHRpb24gb2YgdGhpcyBDb252ZXJ0ZXIgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHRoaXMuZ2V0T3B0aW9uID0gZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiBvcHRpb25zW2tleV07XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgb3B0aW9ucyBvZiB0aGlzIENvbnZlcnRlciBpbnN0YW5jZVxuICAgKiBAcmV0dXJucyB7e319XG4gICAqL1xuICB0aGlzLmdldE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFkZCBleHRlbnNpb24gdG8gVEhJUyBjb252ZXJ0ZXJcbiAgICogQHBhcmFtIHt7fX0gZXh0ZW5zaW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZT1udWxsXVxuICAgKi9cbiAgdGhpcy5hZGRFeHRlbnNpb24gPSBmdW5jdGlvbiAoZXh0ZW5zaW9uLCBuYW1lKSB7XG4gICAgbmFtZSA9IG5hbWUgfHwgbnVsbDtcbiAgICBfcGFyc2VFeHRlbnNpb24oZXh0ZW5zaW9uLCBuYW1lKTtcbiAgfTtcblxuICAvKipcbiAgICogVXNlIGEgZ2xvYmFsIHJlZ2lzdGVyZWQgZXh0ZW5zaW9uIHdpdGggVEhJUyBjb252ZXJ0ZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV4dGVuc2lvbk5hbWUgTmFtZSBvZiB0aGUgcHJldmlvdXNseSByZWdpc3RlcmVkIGV4dGVuc2lvblxuICAgKi9cbiAgdGhpcy51c2VFeHRlbnNpb24gPSBmdW5jdGlvbiAoZXh0ZW5zaW9uTmFtZSkge1xuICAgIF9wYXJzZUV4dGVuc2lvbihleHRlbnNpb25OYW1lKTtcbiAgfTtcblxuICAvKipcbiAgICogU2V0IHRoZSBmbGF2b3IgVEhJUyBjb252ZXJ0ZXIgc2hvdWxkIHVzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgKi9cbiAgdGhpcy5zZXRGbGF2b3IgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIGlmICghZmxhdm9yLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICB0aHJvdyBFcnJvcihuYW1lICsgJyBmbGF2b3Igd2FzIG5vdCBmb3VuZCcpO1xuICAgIH1cbiAgICB2YXIgcHJlc2V0ID0gZmxhdm9yW25hbWVdO1xuICAgIHNldENvbnZGbGF2b3IgPSBuYW1lO1xuICAgIGZvciAodmFyIG9wdGlvbiBpbiBwcmVzZXQpIHtcbiAgICAgIGlmIChwcmVzZXQuaGFzT3duUHJvcGVydHkob3B0aW9uKSkge1xuICAgICAgICBvcHRpb25zW29wdGlvbl0gPSBwcmVzZXRbb3B0aW9uXTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudGx5IHNldCBmbGF2b3Igb2YgdGhpcyBjb252ZXJ0ZXJcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHRoaXMuZ2V0Rmxhdm9yID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBzZXRDb252Rmxhdm9yO1xuICB9O1xuXG4gIC8qKlxuICAgKiBSZW1vdmUgYW4gZXh0ZW5zaW9uIGZyb20gVEhJUyBjb252ZXJ0ZXIuXG4gICAqIE5vdGU6IFRoaXMgaXMgYSBjb3N0bHkgb3BlcmF0aW9uLiBJdCdzIGJldHRlciB0byBpbml0aWFsaXplIGEgbmV3IGNvbnZlcnRlclxuICAgKiBhbmQgc3BlY2lmeSB0aGUgZXh0ZW5zaW9ucyB5b3Ugd2lzaCB0byB1c2VcbiAgICogQHBhcmFtIHtBcnJheX0gZXh0ZW5zaW9uXG4gICAqL1xuICB0aGlzLnJlbW92ZUV4dGVuc2lvbiA9IGZ1bmN0aW9uIChleHRlbnNpb24pIHtcbiAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0FycmF5KGV4dGVuc2lvbikpIHtcbiAgICAgIGV4dGVuc2lvbiA9IFtleHRlbnNpb25dO1xuICAgIH1cbiAgICBmb3IgKHZhciBhID0gMDsgYSA8IGV4dGVuc2lvbi5sZW5ndGg7ICsrYSkge1xuICAgICAgdmFyIGV4dCA9IGV4dGVuc2lvblthXTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFuZ0V4dGVuc2lvbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWYgKGxhbmdFeHRlbnNpb25zW2ldID09PSBleHQpIHtcbiAgICAgICAgICBsYW5nRXh0ZW5zaW9uc1tpXS5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCBvdXRwdXRNb2RpZmllcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWYgKG91dHB1dE1vZGlmaWVyc1tpaV0gPT09IGV4dCkge1xuICAgICAgICAgIG91dHB1dE1vZGlmaWVyc1tpaV0uc3BsaWNlKGksIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBHZXQgYWxsIGV4dGVuc2lvbiBvZiBUSElTIGNvbnZlcnRlclxuICAgKiBAcmV0dXJucyB7e2xhbmd1YWdlOiBBcnJheSwgb3V0cHV0OiBBcnJheX19XG4gICAqL1xuICB0aGlzLmdldEFsbEV4dGVuc2lvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhbmd1YWdlOiBsYW5nRXh0ZW5zaW9ucyxcbiAgICAgIG91dHB1dDogb3V0cHV0TW9kaWZpZXJzXG4gICAgfTtcbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBtZXRhZGF0YSBvZiB0aGUgcHJldmlvdXNseSBwYXJzZWQgZG9jdW1lbnRcbiAgICogQHBhcmFtIHJhd1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfHt9fVxuICAgKi9cbiAgdGhpcy5nZXRNZXRhZGF0YSA9IGZ1bmN0aW9uIChyYXcpIHtcbiAgICBpZiAocmF3KSB7XG4gICAgICByZXR1cm4gbWV0YWRhdGEucmF3O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbWV0YWRhdGEucGFyc2VkO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBtZXRhZGF0YSBmb3JtYXQgb2YgdGhlIHByZXZpb3VzbHkgcGFyc2VkIGRvY3VtZW50XG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICB0aGlzLmdldE1ldGFkYXRhRm9ybWF0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBtZXRhZGF0YS5mb3JtYXQ7XG4gIH07XG5cbiAgLyoqXG4gICAqIFByaXZhdGU6IHNldCBhIHNpbmdsZSBrZXksIHZhbHVlIG1ldGFkYXRhIHBhaXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICovXG4gIHRoaXMuX3NldE1ldGFkYXRhUGFpciA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgbWV0YWRhdGEucGFyc2VkW2tleV0gPSB2YWx1ZTtcbiAgfTtcblxuICAvKipcbiAgICogUHJpdmF0ZTogc2V0IG1ldGFkYXRhIGZvcm1hdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gZm9ybWF0XG4gICAqL1xuICB0aGlzLl9zZXRNZXRhZGF0YUZvcm1hdCA9IGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICBtZXRhZGF0YS5mb3JtYXQgPSBmb3JtYXQ7XG4gIH07XG5cbiAgLyoqXG4gICAqIFByaXZhdGU6IHNldCBtZXRhZGF0YSByYXcgdGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcmF3XG4gICAqL1xuICB0aGlzLl9zZXRNZXRhZGF0YVJhdyA9IGZ1bmN0aW9uIChyYXcpIHtcbiAgICBtZXRhZGF0YS5yYXcgPSByYXc7XG4gIH07XG59O1xuXHJcbi8qKlxuICogVHVybiBNYXJrZG93biBsaW5rIHNob3J0Y3V0cyBpbnRvIFhIVE1MIDxhPiB0YWdzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2FuY2hvcnMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYW5jaG9ycy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIgd3JpdGVBbmNob3JUYWcgPSBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbGlua1RleHQsIGxpbmtJZCwgdXJsLCBtNSwgbTYsIHRpdGxlKSB7XG4gICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZCh0aXRsZSkpIHtcbiAgICAgIHRpdGxlID0gJyc7XG4gICAgfVxuICAgIGxpbmtJZCA9IGxpbmtJZC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gU3BlY2lhbCBjYXNlIGZvciBleHBsaWNpdCBlbXB0eSB1cmxcbiAgICBpZiAod2hvbGVNYXRjaC5zZWFyY2goL1xcKDw/XFxzKj4/ID8oWydcIl0uKlsnXCJdKT9cXCkkL20pID4gLTEpIHtcbiAgICAgIHVybCA9ICcnO1xuICAgIH0gZWxzZSBpZiAoIXVybCkge1xuICAgICAgaWYgKCFsaW5rSWQpIHtcbiAgICAgICAgLy8gbG93ZXItY2FzZSBhbmQgdHVybiBlbWJlZGRlZCBuZXdsaW5lcyBpbnRvIHNwYWNlc1xuICAgICAgICBsaW5rSWQgPSBsaW5rVGV4dC50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoLyA/XFxuL2csICcgJyk7XG4gICAgICB9XG4gICAgICB1cmwgPSAnIycgKyBsaW5rSWQ7XG5cbiAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGdsb2JhbHMuZ1VybHNbbGlua0lkXSkpIHtcbiAgICAgICAgdXJsID0gZ2xvYmFscy5nVXJsc1tsaW5rSWRdO1xuICAgICAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChnbG9iYWxzLmdUaXRsZXNbbGlua0lkXSkpIHtcbiAgICAgICAgICB0aXRsZSA9IGdsb2JhbHMuZ1RpdGxlc1tsaW5rSWRdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gd2hvbGVNYXRjaDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvL3VybCA9IHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzKHVybCwgJypfJywgZmFsc2UpOyAvLyByZXBsYWNlZCBsaW5lIHRvIGltcHJvdmUgcGVyZm9ybWFuY2VcbiAgICB1cmwgPSB1cmwucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG5cbiAgICB2YXIgcmVzdWx0ID0gJzxhIGhyZWY9XCInICsgdXJsICsgJ1wiJztcblxuICAgIGlmICh0aXRsZSAhPT0gJycgJiYgdGl0bGUgIT09IG51bGwpIHtcbiAgICAgIHRpdGxlID0gdGl0bGUucmVwbGFjZSgvXCIvZywgJyZxdW90OycpO1xuICAgICAgLy90aXRsZSA9IHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzKHRpdGxlLCAnKl8nLCBmYWxzZSk7IC8vIHJlcGxhY2VkIGxpbmUgdG8gaW1wcm92ZSBwZXJmb3JtYW5jZVxuICAgICAgdGl0bGUgPSB0aXRsZS5yZXBsYWNlKHNob3dkb3duLmhlbHBlci5yZWdleGVzLmFzdGVyaXNrRGFzaEFuZENvbG9uLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcbiAgICAgIHJlc3VsdCArPSAnIHRpdGxlPVwiJyArIHRpdGxlICsgJ1wiJztcbiAgICB9XG5cbiAgICAvLyBvcHRpb25MaW5rc0luTmV3V2luZG93IG9ubHkgYXBwbGllc1xuICAgIC8vIHRvIGV4dGVybmFsIGxpbmtzLiBIYXNoIGxpbmtzICgjKSBvcGVuIGluIHNhbWUgcGFnZVxuICAgIGlmIChvcHRpb25zLm9wZW5MaW5rc0luTmV3V2luZG93ICYmICEvXiMvLnRlc3QodXJsKSkge1xuICAgICAgLy8gZXNjYXBlZCBfXG4gICAgICByZXN1bHQgKz0gJyByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCIgdGFyZ2V0PVwiwqhFOTVFYmxhbmtcIic7XG4gICAgfVxuXG4gICAgcmVzdWx0ICs9ICc+JyArIGxpbmtUZXh0ICsgJzwvYT4nO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBGaXJzdCwgaGFuZGxlIHJlZmVyZW5jZS1zdHlsZSBsaW5rczogW2xpbmsgdGV4dF0gW2lkXVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFsoKD86XFxbW15cXF1dKl18W15cXFtcXF1dKSopXSA/KD86XFxuICopP1xcWyguKj8pXSgpKCkoKSgpL2csIHdyaXRlQW5jaG9yVGFnKTtcblxuICAvLyBOZXh0LCBpbmxpbmUtc3R5bGUgbGlua3M6IFtsaW5rIHRleHRdKHVybCBcIm9wdGlvbmFsIHRpdGxlXCIpXG4gIC8vIGNhc2VzIHdpdGggY3JhenkgdXJscyBsaWtlIC4vaW1hZ2UvY2F0MSkucG5nXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcWygoPzpcXFtbXlxcXV0qXXxbXlxcW1xcXV0pKildKClbIFxcdF0qXFwoWyBcXHRdPzwoW14+XSopPig/OlsgXFx0XSooKFtcIiddKShbXlwiXSo/KVxcNSkpP1sgXFx0XT9cXCkvZyxcbiAgICB3cml0ZUFuY2hvclRhZyk7XG5cbiAgLy8gbm9ybWFsIGNhc2VzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcWygoPzpcXFtbXlxcXV0qXXxbXlxcW1xcXV0pKildKClbIFxcdF0qXFwoWyBcXHRdPzw/KFtcXFNdKz8oPzpcXChbXFxTXSo/XFwpW1xcU10qPyk/KT4/KD86WyBcXHRdKigoW1wiJ10pKFteXCJdKj8pXFw1KSk/WyBcXHRdP1xcKS9nLFxuICAgIHdyaXRlQW5jaG9yVGFnKTtcblxuICAvLyBoYW5kbGUgcmVmZXJlbmNlLXN0eWxlIHNob3J0Y3V0czogW2xpbmsgdGV4dF1cbiAgLy8gVGhlc2UgbXVzdCBjb21lIGxhc3QgaW4gY2FzZSB5b3UndmUgYWxzbyBnb3QgW2xpbmsgdGVzdF1bMV1cbiAgLy8gb3IgW2xpbmsgdGVzdF0oL2ZvbylcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxbKFteXFxbXFxdXSspXSgpKCkoKSgpKCkvZywgd3JpdGVBbmNob3JUYWcpO1xuXG4gIC8vIExhc3RseSBoYW5kbGUgR2l0aHViTWVudGlvbnMgaWYgb3B0aW9uIGlzIGVuYWJsZWRcbiAgaWYgKG9wdGlvbnMuZ2hNZW50aW9ucykge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhefFxccykoXFxcXCk/KEAoW2EtelxcZF0rKD86W2EtelxcZC4tXSs/W2EtelxcZF0rKSopKS9nbWksIGZ1bmN0aW9uICh3bSwgc3QsIGVzY2FwZSwgbWVudGlvbnMsIHVzZXJuYW1lKSB7XG4gICAgICBpZiAoZXNjYXBlID09PSAnXFxcXCcpIHtcbiAgICAgICAgcmV0dXJuIHN0ICsgbWVudGlvbnM7XG4gICAgICB9XG5cbiAgICAgIC8vY2hlY2sgaWYgb3B0aW9ucy5naE1lbnRpb25zTGluayBpcyBhIHN0cmluZ1xuICAgICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5naE1lbnRpb25zTGluaykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnaE1lbnRpb25zTGluayBvcHRpb24gbXVzdCBiZSBhIHN0cmluZycpO1xuICAgICAgfVxuICAgICAgdmFyIGxuayA9IG9wdGlvbnMuZ2hNZW50aW9uc0xpbmsucmVwbGFjZSgvXFx7dX0vZywgdXNlcm5hbWUpLFxuICAgICAgICAgIHRhcmdldCA9ICcnO1xuICAgICAgaWYgKG9wdGlvbnMub3BlbkxpbmtzSW5OZXdXaW5kb3cpIHtcbiAgICAgICAgdGFyZ2V0ID0gJyByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCIgdGFyZ2V0PVwiwqhFOTVFYmxhbmtcIic7XG4gICAgICB9XG4gICAgICByZXR1cm4gc3QgKyAnPGEgaHJlZj1cIicgKyBsbmsgKyAnXCInICsgdGFyZ2V0ICsgJz4nICsgbWVudGlvbnMgKyAnPC9hPic7XG4gICAgfSk7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdhbmNob3JzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLy8gdXJsIGFsbG93ZWQgY2hhcnMgW2EtelxcZF8ufjovPyNbXUAhJCYnKCkqKyw7PS1dXG5cbnZhciBzaW1wbGVVUkxSZWdleCAgPSAvKFsqfl9dK3xcXGIpKCgoaHR0cHM/fGZ0cHxkaWN0KTpcXC9cXC98d3d3XFwuKVteJ1wiPlxcc10rP1xcLlteJ1wiPlxcc10rPykoKShcXDEpPyg/PVxcc3wkKSg/IVtcIjw+XSkvZ2ksXG4gICAgc2ltcGxlVVJMUmVnZXgyID0gLyhbKn5fXSt8XFxiKSgoKGh0dHBzP3xmdHB8ZGljdCk6XFwvXFwvfHd3d1xcLilbXidcIj5cXHNdK1xcLlteJ1wiPlxcc10rPykoWy4hPywoKVxcW1xcXV0pPyhcXDEpPyg/PVxcc3wkKSg/IVtcIjw+XSkvZ2ksXG4gICAgZGVsaW1VcmxSZWdleCAgID0gLygpPCgoKGh0dHBzP3xmdHB8ZGljdCk6XFwvXFwvfHd3d1xcLilbXidcIj5cXHNdKykoKT4oKS9naSxcbiAgICBzaW1wbGVNYWlsUmVnZXggPSAvKF58XFxzKSg/Om1haWx0bzopPyhbQS1aYS16MC05ISMkJSYnKistLz0/Xl9ge3x9fi5dK0BbLWEtejAtOV0rKFxcLlstYS16MC05XSspKlxcLlthLXpdKykoPz0kfFxccykvZ21pLFxuICAgIGRlbGltTWFpbFJlZ2V4ICA9IC88KCkoPzptYWlsdG86KT8oWy0uXFx3XStAWy1hLXowLTldKyhcXC5bLWEtejAtOV0rKSpcXC5bYS16XSspPi9naSxcblxuICAgIHJlcGxhY2VMaW5rID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgIHJldHVybiBmdW5jdGlvbiAod20sIGxlYWRpbmdNYWdpY0NoYXJzLCBsaW5rLCBtMiwgbTMsIHRyYWlsaW5nUHVuY3R1YXRpb24sIHRyYWlsaW5nTWFnaWNDaGFycykge1xuICAgICAgICBsaW5rID0gbGluay5yZXBsYWNlKHNob3dkb3duLmhlbHBlci5yZWdleGVzLmFzdGVyaXNrRGFzaEFuZENvbG9uLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcbiAgICAgICAgdmFyIGxua1R4dCA9IGxpbmssXG4gICAgICAgICAgICBhcHBlbmQgPSAnJyxcbiAgICAgICAgICAgIHRhcmdldCA9ICcnLFxuICAgICAgICAgICAgbG1jICAgID0gbGVhZGluZ01hZ2ljQ2hhcnMgfHwgJycsXG4gICAgICAgICAgICB0bWMgICAgPSB0cmFpbGluZ01hZ2ljQ2hhcnMgfHwgJyc7XG4gICAgICAgIGlmICgvXnd3d1xcLi9pLnRlc3QobGluaykpIHtcbiAgICAgICAgICBsaW5rID0gbGluay5yZXBsYWNlKC9ed3d3XFwuL2ksICdodHRwOi8vd3d3LicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmV4Y2x1ZGVUcmFpbGluZ1B1bmN0dWF0aW9uRnJvbVVSTHMgJiYgdHJhaWxpbmdQdW5jdHVhdGlvbikge1xuICAgICAgICAgIGFwcGVuZCA9IHRyYWlsaW5nUHVuY3R1YXRpb247XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMub3BlbkxpbmtzSW5OZXdXaW5kb3cpIHtcbiAgICAgICAgICB0YXJnZXQgPSAnIHJlbD1cIm5vb3BlbmVyIG5vcmVmZXJyZXJcIiB0YXJnZXQ9XCLCqEU5NUVibGFua1wiJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbG1jICsgJzxhIGhyZWY9XCInICsgbGluayArICdcIicgKyB0YXJnZXQgKyAnPicgKyBsbmtUeHQgKyAnPC9hPicgKyBhcHBlbmQgKyB0bWM7XG4gICAgICB9O1xuICAgIH0sXG5cbiAgICByZXBsYWNlTWFpbCA9IGZ1bmN0aW9uIChvcHRpb25zLCBnbG9iYWxzKSB7XG4gICAgICAndXNlIHN0cmljdCc7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gKHdob2xlTWF0Y2gsIGIsIG1haWwpIHtcbiAgICAgICAgdmFyIGhyZWYgPSAnbWFpbHRvOic7XG4gICAgICAgIGIgPSBiIHx8ICcnO1xuICAgICAgICBtYWlsID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmVzY2FwZVNwZWNpYWxDaGFycycpKG1haWwsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICBpZiAob3B0aW9ucy5lbmNvZGVFbWFpbHMpIHtcbiAgICAgICAgICBocmVmID0gc2hvd2Rvd24uaGVscGVyLmVuY29kZUVtYWlsQWRkcmVzcyhocmVmICsgbWFpbCk7XG4gICAgICAgICAgbWFpbCA9IHNob3dkb3duLmhlbHBlci5lbmNvZGVFbWFpbEFkZHJlc3MobWFpbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaHJlZiA9IGhyZWYgKyBtYWlsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiICsgJzxhIGhyZWY9XCInICsgaHJlZiArICdcIj4nICsgbWFpbCArICc8L2E+JztcbiAgICAgIH07XG4gICAgfTtcblxuc2hvd2Rvd24uc3ViUGFyc2VyKCdhdXRvTGlua3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYXV0b0xpbmtzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoZGVsaW1VcmxSZWdleCwgcmVwbGFjZUxpbmsob3B0aW9ucykpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGRlbGltTWFpbFJlZ2V4LCByZXBsYWNlTWFpbChvcHRpb25zLCBnbG9iYWxzKSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYXV0b0xpbmtzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxuc2hvd2Rvd24uc3ViUGFyc2VyKCdzaW1wbGlmaWVkQXV0b0xpbmtzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghb3B0aW9ucy5zaW1wbGlmaWVkQXV0b0xpbmspIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3NpbXBsaWZpZWRBdXRvTGlua3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgaWYgKG9wdGlvbnMuZXhjbHVkZVRyYWlsaW5nUHVuY3R1YXRpb25Gcm9tVVJMcykge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2ltcGxlVVJMUmVnZXgyLCByZXBsYWNlTGluayhvcHRpb25zKSk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZShzaW1wbGVVUkxSZWdleCwgcmVwbGFjZUxpbmsob3B0aW9ucykpO1xuICB9XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2ltcGxlTWFpbFJlZ2V4LCByZXBsYWNlTWFpbChvcHRpb25zLCBnbG9iYWxzKSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc2ltcGxpZmllZEF1dG9MaW5rcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBUaGVzZSBhcmUgYWxsIHRoZSB0cmFuc2Zvcm1hdGlvbnMgdGhhdCBmb3JtIGJsb2NrLWxldmVsXG4gKiB0YWdzIGxpa2UgcGFyYWdyYXBocywgaGVhZGVycywgYW5kIGxpc3QgaXRlbXMuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignYmxvY2tHYW11dCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdibG9ja0dhbXV0LmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIHdlIHBhcnNlIGJsb2NrcXVvdGVzIGZpcnN0IHNvIHRoYXQgd2UgY2FuIGhhdmUgaGVhZGluZ3MgYW5kIGhyc1xuICAvLyBpbnNpZGUgYmxvY2txdW90ZXNcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignYmxvY2tRdW90ZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGVhZGVycycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIERvIEhvcml6b250YWwgUnVsZXM6XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hvcml6b250YWxSdWxlJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbGlzdHMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignY29kZUJsb2NrcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd0YWJsZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBXZSBhbHJlYWR5IHJhbiBfSGFzaEhUTUxCbG9ja3MoKSBiZWZvcmUsIGluIE1hcmtkb3duKCksIGJ1dCB0aGF0XG4gIC8vIHdhcyB0byBlc2NhcGUgcmF3IEhUTUwgaW4gdGhlIG9yaWdpbmFsIE1hcmtkb3duIHNvdXJjZS4gVGhpcyB0aW1lLFxuICAvLyB3ZSdyZSBlc2NhcGluZyB0aGUgbWFya3VwIHdlJ3ZlIGp1c3QgY3JlYXRlZCwgc28gdGhhdCB3ZSBkb24ndCB3cmFwXG4gIC8vIDxwPiB0YWdzIGFyb3VuZCBibG9jay1sZXZlbCB0YWdzLlxuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoSFRNTEJsb2NrcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdwYXJhZ3JhcGhzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYmxvY2tHYW11dC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdibG9ja1F1b3RlcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdibG9ja1F1b3Rlcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBhZGQgYSBjb3VwbGUgZXh0cmEgbGluZXMgYWZ0ZXIgdGhlIHRleHQgYW5kIGVuZHRleHQgbWFya1xuICB0ZXh0ID0gdGV4dCArICdcXG5cXG4nO1xuXG4gIHZhciByZ3ggPSAvKF4gezAsM30+WyBcXHRdPy4rXFxuKC4rXFxuKSpcXG4qKSsvZ207XG5cbiAgaWYgKG9wdGlvbnMuc3BsaXRBZGphY2VudEJsb2NrcXVvdGVzKSB7XG4gICAgcmd4ID0gL14gezAsM30+W1xcc1xcU10qPyg/OlxcblxcbikvZ207XG4gIH1cblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJneCwgZnVuY3Rpb24gKGJxKSB7XG4gICAgLy8gYXR0YWNrbGFiOiBoYWNrIGFyb3VuZCBLb25xdWVyb3IgMy41LjQgYnVnOlxuICAgIC8vIFwiLS0tLS0tLS0tLWJ1Z1wiLnJlcGxhY2UoL14tL2csXCJcIikgPT0gXCJidWdcIlxuICAgIGJxID0gYnEucmVwbGFjZSgvXlsgXFx0XSo+WyBcXHRdPy9nbSwgJycpOyAvLyB0cmltIG9uZSBsZXZlbCBvZiBxdW90aW5nXG5cbiAgICAvLyBhdHRhY2tsYWI6IGNsZWFuIHVwIGhhY2tcbiAgICBicSA9IGJxLnJlcGxhY2UoL8KoMC9nLCAnJyk7XG5cbiAgICBicSA9IGJxLnJlcGxhY2UoL15bIFxcdF0rJC9nbSwgJycpOyAvLyB0cmltIHdoaXRlc3BhY2Utb25seSBsaW5lc1xuICAgIGJxID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdnaXRodWJDb2RlQmxvY2tzJykoYnEsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGJxID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdibG9ja0dhbXV0JykoYnEsIG9wdGlvbnMsIGdsb2JhbHMpOyAvLyByZWN1cnNlXG5cbiAgICBicSA9IGJxLnJlcGxhY2UoLyhefFxcbikvZywgJyQxICAnKTtcbiAgICAvLyBUaGVzZSBsZWFkaW5nIHNwYWNlcyBzY3JldyB3aXRoIDxwcmU+IGNvbnRlbnQsIHNvIHdlIG5lZWQgdG8gZml4IHRoYXQ6XG4gICAgYnEgPSBicS5yZXBsYWNlKC8oXFxzKjxwcmU+W15cXHJdKz88XFwvcHJlPikvZ20sIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSkge1xuICAgICAgdmFyIHByZSA9IG0xO1xuICAgICAgLy8gYXR0YWNrbGFiOiBoYWNrIGFyb3VuZCBLb25xdWVyb3IgMy41LjQgYnVnOlxuICAgICAgcHJlID0gcHJlLnJlcGxhY2UoL14gIC9tZywgJ8KoMCcpO1xuICAgICAgcHJlID0gcHJlLnJlcGxhY2UoL8KoMC9nLCAnJyk7XG4gICAgICByZXR1cm4gcHJlO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoJzxibG9ja3F1b3RlPlxcbicgKyBicSArICdcXG48L2Jsb2NrcXVvdGU+Jywgb3B0aW9ucywgZ2xvYmFscyk7XG4gIH0pO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2Jsb2NrUXVvdGVzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBQcm9jZXNzIE1hcmtkb3duIGA8cHJlPjxjb2RlPmAgYmxvY2tzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2NvZGVCbG9ja3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnY29kZUJsb2Nrcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBzZW50aW5lbCB3b3JrYXJvdW5kcyBmb3IgbGFjayBvZiBcXEEgYW5kIFxcWiwgc2FmYXJpXFxraHRtbCBidWdcbiAgdGV4dCArPSAnwqgwJztcblxuICB2YXIgcGF0dGVybiA9IC8oPzpcXG5cXG58XikoKD86KD86WyBdezR9fFxcdCkuKlxcbispKykoXFxuKlsgXXswLDN9W14gXFx0XFxuXXwoPz3CqDApKS9nO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHBhdHRlcm4sIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSwgbTIpIHtcbiAgICB2YXIgY29kZWJsb2NrID0gbTEsXG4gICAgICAgIG5leHRDaGFyID0gbTIsXG4gICAgICAgIGVuZCA9ICdcXG4nO1xuXG4gICAgY29kZWJsb2NrID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdvdXRkZW50JykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBjb2RlYmxvY2sgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnKShjb2RlYmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGNvZGVibG9jayA9IHNob3dkb3duLnN1YlBhcnNlcignZGV0YWInKShjb2RlYmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGNvZGVibG9jayA9IGNvZGVibG9jay5yZXBsYWNlKC9eXFxuKy9nLCAnJyk7IC8vIHRyaW0gbGVhZGluZyBuZXdsaW5lc1xuICAgIGNvZGVibG9jayA9IGNvZGVibG9jay5yZXBsYWNlKC9cXG4rJC9nLCAnJyk7IC8vIHRyaW0gdHJhaWxpbmcgbmV3bGluZXNcblxuICAgIGlmIChvcHRpb25zLm9taXRFeHRyYVdMSW5Db2RlQmxvY2tzKSB7XG4gICAgICBlbmQgPSAnJztcbiAgICB9XG5cbiAgICBjb2RlYmxvY2sgPSAnPHByZT48Y29kZT4nICsgY29kZWJsb2NrICsgZW5kICsgJzwvY29kZT48L3ByZT4nO1xuXG4gICAgcmV0dXJuIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKSArIG5leHRDaGFyO1xuICB9KTtcblxuICAvLyBzdHJpcCBzZW50aW5lbFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqDAvLCAnJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnY29kZUJsb2Nrcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICpcbiAqICAgKiAgQmFja3RpY2sgcXVvdGVzIGFyZSB1c2VkIGZvciA8Y29kZT48L2NvZGU+IHNwYW5zLlxuICpcbiAqICAgKiAgWW91IGNhbiB1c2UgbXVsdGlwbGUgYmFja3RpY2tzIGFzIHRoZSBkZWxpbWl0ZXJzIGlmIHlvdSB3YW50IHRvXG4gKiAgICAgaW5jbHVkZSBsaXRlcmFsIGJhY2t0aWNrcyBpbiB0aGUgY29kZSBzcGFuLiBTbywgdGhpcyBpbnB1dDpcbiAqXG4gKiAgICAgICAgIEp1c3QgdHlwZSBgYGZvbyBgYmFyYCBiYXpgYCBhdCB0aGUgcHJvbXB0LlxuICpcbiAqICAgICAgIFdpbGwgdHJhbnNsYXRlIHRvOlxuICpcbiAqICAgICAgICAgPHA+SnVzdCB0eXBlIDxjb2RlPmZvbyBgYmFyYCBiYXo8L2NvZGU+IGF0IHRoZSBwcm9tcHQuPC9wPlxuICpcbiAqICAgIFRoZXJlJ3Mgbm8gYXJiaXRyYXJ5IGxpbWl0IHRvIHRoZSBudW1iZXIgb2YgYmFja3RpY2tzIHlvdVxuICogICAgY2FuIHVzZSBhcyBkZWxpbXRlcnMuIElmIHlvdSBuZWVkIHRocmVlIGNvbnNlY3V0aXZlIGJhY2t0aWNrc1xuICogICAgaW4geW91ciBjb2RlLCB1c2UgZm91ciBmb3IgZGVsaW1pdGVycywgZXRjLlxuICpcbiAqICAqICBZb3UgY2FuIHVzZSBzcGFjZXMgdG8gZ2V0IGxpdGVyYWwgYmFja3RpY2tzIGF0IHRoZSBlZGdlczpcbiAqXG4gKiAgICAgICAgIC4uLiB0eXBlIGBgIGBiYXJgIGBgIC4uLlxuICpcbiAqICAgICAgIFR1cm5zIHRvOlxuICpcbiAqICAgICAgICAgLi4uIHR5cGUgPGNvZGU+YGJhcmA8L2NvZGU+IC4uLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2NvZGVTcGFucycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb2RlU3BhbnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgaWYgKHR5cGVvZiB0ZXh0ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRleHQgPSAnJztcbiAgfVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oXnxbXlxcXFxdKShgKykoW15cXHJdKj9bXmBdKVxcMig/IWApL2dtLFxuICAgIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSwgbTIsIG0zKSB7XG4gICAgICB2YXIgYyA9IG0zO1xuICAgICAgYyA9IGMucmVwbGFjZSgvXihbIFxcdF0qKS9nLCAnJyk7XHQvLyBsZWFkaW5nIHdoaXRlc3BhY2VcbiAgICAgIGMgPSBjLnJlcGxhY2UoL1sgXFx0XSokL2csICcnKTtcdC8vIHRyYWlsaW5nIHdoaXRlc3BhY2VcbiAgICAgIGMgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnKShjLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgIGMgPSBtMSArICc8Y29kZT4nICsgYyArICc8L2NvZGU+JztcbiAgICAgIGMgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hIVE1MU3BhbnMnKShjLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgIHJldHVybiBjO1xuICAgIH1cbiAgKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb2RlU3BhbnMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIENyZWF0ZSBhIGZ1bGwgSFRNTCBkb2N1bWVudCBmcm9tIHRoZSBwcm9jZXNzZWQgbWFya2Rvd25cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdjb21wbGV0ZUhUTUxEb2N1bWVudCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMuY29tcGxldGVIVE1MRG9jdW1lbnQpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2NvbXBsZXRlSFRNTERvY3VtZW50LmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciBkb2N0eXBlID0gJ2h0bWwnLFxuICAgICAgZG9jdHlwZVBhcnNlZCA9ICc8IURPQ1RZUEUgSFRNTD5cXG4nLFxuICAgICAgdGl0bGUgPSAnJyxcbiAgICAgIGNoYXJzZXQgPSAnPG1ldGEgY2hhcnNldD1cInV0Zi04XCI+XFxuJyxcbiAgICAgIGxhbmcgPSAnJyxcbiAgICAgIG1ldGFkYXRhID0gJyc7XG5cbiAgaWYgKHR5cGVvZiBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZC5kb2N0eXBlICE9PSAndW5kZWZpbmVkJykge1xuICAgIGRvY3R5cGVQYXJzZWQgPSAnPCFET0NUWVBFICcgKyAgZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWQuZG9jdHlwZSArICc+XFxuJztcbiAgICBkb2N0eXBlID0gZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWQuZG9jdHlwZS50b1N0cmluZygpLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKGRvY3R5cGUgPT09ICdodG1sJyB8fCBkb2N0eXBlID09PSAnaHRtbDUnKSB7XG4gICAgICBjaGFyc2V0ID0gJzxtZXRhIGNoYXJzZXQ9XCJ1dGYtOFwiPic7XG4gICAgfVxuICB9XG5cbiAgZm9yICh2YXIgbWV0YSBpbiBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZCkge1xuICAgIGlmIChnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZC5oYXNPd25Qcm9wZXJ0eShtZXRhKSkge1xuICAgICAgc3dpdGNoIChtZXRhLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgY2FzZSAnZG9jdHlwZSc6XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAndGl0bGUnOlxuICAgICAgICAgIHRpdGxlID0gJzx0aXRsZT4nICsgIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkLnRpdGxlICsgJzwvdGl0bGU+XFxuJztcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdjaGFyc2V0JzpcbiAgICAgICAgICBpZiAoZG9jdHlwZSA9PT0gJ2h0bWwnIHx8IGRvY3R5cGUgPT09ICdodG1sNScpIHtcbiAgICAgICAgICAgIGNoYXJzZXQgPSAnPG1ldGEgY2hhcnNldD1cIicgKyBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZC5jaGFyc2V0ICsgJ1wiPlxcbic7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoYXJzZXQgPSAnPG1ldGEgbmFtZT1cImNoYXJzZXRcIiBjb250ZW50PVwiJyArIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkLmNoYXJzZXQgKyAnXCI+XFxuJztcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnbGFuZ3VhZ2UnOlxuICAgICAgICBjYXNlICdsYW5nJzpcbiAgICAgICAgICBsYW5nID0gJyBsYW5nPVwiJyArIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkW21ldGFdICsgJ1wiJztcbiAgICAgICAgICBtZXRhZGF0YSArPSAnPG1ldGEgbmFtZT1cIicgKyBtZXRhICsgJ1wiIGNvbnRlbnQ9XCInICsgZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWRbbWV0YV0gKyAnXCI+XFxuJztcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIG1ldGFkYXRhICs9ICc8bWV0YSBuYW1lPVwiJyArIG1ldGEgKyAnXCIgY29udGVudD1cIicgKyBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZFttZXRhXSArICdcIj5cXG4nO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRleHQgPSBkb2N0eXBlUGFyc2VkICsgJzxodG1sJyArIGxhbmcgKyAnPlxcbjxoZWFkPlxcbicgKyB0aXRsZSArIGNoYXJzZXQgKyBtZXRhZGF0YSArICc8L2hlYWQ+XFxuPGJvZHk+XFxuJyArIHRleHQudHJpbSgpICsgJ1xcbjwvYm9keT5cXG48L2h0bWw+JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb21wbGV0ZUhUTUxEb2N1bWVudC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogQ29udmVydCBhbGwgdGFicyB0byBzcGFjZXNcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdkZXRhYicsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZGV0YWIuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gZXhwYW5kIGZpcnN0IG4tMSB0YWJzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcdCg/PVxcdCkvZywgJyAgICAnKTsgLy8gZ190YWJfd2lkdGhcblxuICAvLyByZXBsYWNlIHRoZSBudGggd2l0aCB0d28gc2VudGluZWxzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcdC9nLCAnwqhBwqhCJyk7XG5cbiAgLy8gdXNlIHRoZSBzZW50aW5lbCB0byBhbmNob3Igb3VyIHJlZ2V4IHNvIGl0IGRvZXNuJ3QgZXhwbG9kZVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqEIoLis/KcKoQS9nLCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEpIHtcbiAgICB2YXIgbGVhZGluZ1RleHQgPSBtMSxcbiAgICAgICAgbnVtU3BhY2VzID0gNCAtIGxlYWRpbmdUZXh0Lmxlbmd0aCAlIDQ7ICAvLyBnX3RhYl93aWR0aFxuXG4gICAgLy8gdGhlcmUgKm11c3QqIGJlIGEgYmV0dGVyIHdheSB0byBkbyB0aGlzOlxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtU3BhY2VzOyBpKyspIHtcbiAgICAgIGxlYWRpbmdUZXh0ICs9ICcgJztcbiAgICB9XG5cbiAgICByZXR1cm4gbGVhZGluZ1RleHQ7XG4gIH0pO1xuXG4gIC8vIGNsZWFuIHVwIHNlbnRpbmVsc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqEEvZywgJyAgICAnKTsgIC8vIGdfdGFiX3dpZHRoXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoQi9nLCAnJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZGV0YWIuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2VsbGlwc2lzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VsbGlwc2lzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcLlxcLlxcLi9nLCAn4oCmJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZWxsaXBzaXMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogVHVybiBlbW9qaSBjb2RlcyBpbnRvIGVtb2ppc1xuICpcbiAqIExpc3Qgb2Ygc3VwcG9ydGVkIGVtb2ppczogaHR0cHM6Ly9naXRodWIuY29tL3Nob3dkb3duanMvc2hvd2Rvd24vd2lraS9FbW9qaXNcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdlbW9qaScsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMuZW1vamkpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2Vtb2ppLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciBlbW9qaVJneCA9IC86KFtcXFNdKz8pOi9nO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoZW1vamlSZ3gsIGZ1bmN0aW9uICh3bSwgZW1vamlDb2RlKSB7XG4gICAgaWYgKHNob3dkb3duLmhlbHBlci5lbW9qaXMuaGFzT3duUHJvcGVydHkoZW1vamlDb2RlKSkge1xuICAgICAgcmV0dXJuIHNob3dkb3duLmhlbHBlci5lbW9qaXNbZW1vamlDb2RlXTtcbiAgICB9XG4gICAgcmV0dXJuIHdtO1xuICB9KTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbW9qaS5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBTbWFydCBwcm9jZXNzaW5nIGZvciBhbXBlcnNhbmRzIGFuZCBhbmdsZSBicmFja2V0cyB0aGF0IG5lZWQgdG8gYmUgZW5jb2RlZC5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVBbXBzQW5kQW5nbGVzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbmNvZGVBbXBzQW5kQW5nbGVzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIEFtcGVyc2FuZC1lbmNvZGluZyBiYXNlZCBlbnRpcmVseSBvbiBOYXQgSXJvbnMncyBBbXB1dGF0b3IgTVQgcGx1Z2luOlxuICAvLyBodHRwOi8vYnVtcHBvLm5ldC9wcm9qZWN0cy9hbXB1dGF0b3IvXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyYoPyEjP1t4WF0/KD86WzAtOWEtZkEtRl0rfFxcdyspOykvZywgJyZhbXA7Jyk7XG5cbiAgLy8gRW5jb2RlIG5ha2VkIDwnc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC88KD8hW2EtelxcLz8kIV0pL2dpLCAnJmx0OycpO1xuXG4gIC8vIEVuY29kZSA8XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLzwvZywgJyZsdDsnKTtcblxuICAvLyBFbmNvZGUgPlxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8+L2csICcmZ3Q7Jyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZW5jb2RlQW1wc0FuZEFuZ2xlcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogUmV0dXJucyB0aGUgc3RyaW5nLCB3aXRoIGFmdGVyIHByb2Nlc3NpbmcgdGhlIGZvbGxvd2luZyBiYWNrc2xhc2ggZXNjYXBlIHNlcXVlbmNlcy5cbiAqXG4gKiBhdHRhY2tsYWI6IFRoZSBwb2xpdGUgd2F5IHRvIGRvIHRoaXMgaXMgd2l0aCB0aGUgbmV3IGVzY2FwZUNoYXJhY3RlcnMoKSBmdW5jdGlvbjpcbiAqXG4gKiAgICB0ZXh0ID0gZXNjYXBlQ2hhcmFjdGVycyh0ZXh0LFwiXFxcXFwiLHRydWUpO1xuICogICAgdGV4dCA9IGVzY2FwZUNoYXJhY3RlcnModGV4dCxcImAqX3t9W10oKT4jKy0uIVwiLHRydWUpO1xuICpcbiAqIC4uLmJ1dCB3ZSdyZSBzaWRlc3RlcHBpbmcgaXRzIHVzZSBvZiB0aGUgKHNsb3cpIFJlZ0V4cCBjb25zdHJ1Y3RvclxuICogYXMgYW4gb3B0aW1pemF0aW9uIGZvciBGaXJlZm94LiAgVGhpcyBmdW5jdGlvbiBnZXRzIGNhbGxlZCBhIExPVC5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVCYWNrc2xhc2hFc2NhcGVzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbmNvZGVCYWNrc2xhc2hFc2NhcGVzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcXFwoXFxcXCkvZywgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcXFwoW2AqX3t9XFxbXFxdKCk+IysuIX49fC1dKS9nLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbmNvZGVCYWNrc2xhc2hFc2NhcGVzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBFbmNvZGUvZXNjYXBlIGNlcnRhaW4gY2hhcmFjdGVycyBpbnNpZGUgTWFya2Rvd24gY29kZSBydW5zLlxuICogVGhlIHBvaW50IGlzIHRoYXQgaW4gY29kZSwgdGhlc2UgY2hhcmFjdGVycyBhcmUgbGl0ZXJhbHMsXG4gKiBhbmQgbG9zZSB0aGVpciBzcGVjaWFsIE1hcmtkb3duIG1lYW5pbmdzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZW5jb2RlQ29kZS5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBFbmNvZGUgYWxsIGFtcGVyc2FuZHM7IEhUTUwgZW50aXRpZXMgYXJlIG5vdFxuICAvLyBlbnRpdGllcyB3aXRoaW4gYSBNYXJrZG93biBjb2RlIHNwYW4uXG4gIHRleHQgPSB0ZXh0XG4gICAgLnJlcGxhY2UoLyYvZywgJyZhbXA7JylcbiAgLy8gRG8gdGhlIGFuZ2xlIGJyYWNrZXQgc29uZyBhbmQgZGFuY2U6XG4gICAgLnJlcGxhY2UoLzwvZywgJyZsdDsnKVxuICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JylcbiAgLy8gTm93LCBlc2NhcGUgY2hhcmFjdGVycyB0aGF0IGFyZSBtYWdpYyBpbiBNYXJrZG93bjpcbiAgICAucmVwbGFjZSgvKFsqX3t9XFxbXFxdXFxcXD1+LV0pL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VuY29kZUNvZGUuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFdpdGhpbiB0YWdzIC0tIG1lYW5pbmcgYmV0d2VlbiA8IGFuZCA+IC0tIGVuY29kZSBbXFwgYCAqIF8gfiA9XSBzbyB0aGV5XG4gKiBkb24ndCBjb25mbGljdCB3aXRoIHRoZWlyIHVzZSBpbiBNYXJrZG93biBmb3IgY29kZSwgaXRhbGljcyBhbmQgc3Ryb25nLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2VzY2FwZVNwZWNpYWxDaGFyc1dpdGhpblRhZ0F0dHJpYnV0ZXMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VzY2FwZVNwZWNpYWxDaGFyc1dpdGhpblRhZ0F0dHJpYnV0ZXMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gQnVpbGQgYSByZWdleCB0byBmaW5kIEhUTUwgdGFncy5cbiAgdmFyIHRhZ3MgICAgID0gLzxcXC8/W2EtelxcZF86LV0rKD86W1xcc10rW1xcc1xcU10rPyk/Pi9naSxcbiAgICAgIGNvbW1lbnRzID0gLzwhKC0tKD86KD86W14+LV18LVtePl0pKD86W14tXXwtW14tXSkqKS0tKT4vZ2k7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSh0YWdzLCBmdW5jdGlvbiAod2hvbGVNYXRjaCkge1xuICAgIHJldHVybiB3aG9sZU1hdGNoXG4gICAgICAucmVwbGFjZSgvKC4pPFxcLz9jb2RlPig/PS4pL2csICckMWAnKVxuICAgICAgLnJlcGxhY2UoLyhbXFxcXGAqX349fF0pL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuICB9KTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGNvbW1lbnRzLCBmdW5jdGlvbiAod2hvbGVNYXRjaCkge1xuICAgIHJldHVybiB3aG9sZU1hdGNoXG4gICAgICAucmVwbGFjZSgvKFtcXFxcYCpffj18XSkvZywgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gIH0pO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VzY2FwZVNwZWNpYWxDaGFyc1dpdGhpblRhZ0F0dHJpYnV0ZXMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIEhhbmRsZSBnaXRodWIgY29kZWJsb2NrcyBwcmlvciB0byBydW5uaW5nIEhhc2hIVE1MIHNvIHRoYXRcbiAqIEhUTUwgY29udGFpbmVkIHdpdGhpbiB0aGUgY29kZWJsb2NrIGdldHMgZXNjYXBlZCBwcm9wZXJseVxuICogRXhhbXBsZTpcbiAqIGBgYHJ1YnlcbiAqICAgICBkZWYgaGVsbG9fd29ybGQoeClcbiAqICAgICAgIHB1dHMgXCJIZWxsbywgI3t4fVwiXG4gKiAgICAgZW5kXG4gKiBgYGBcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdnaXRodWJDb2RlQmxvY2tzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIGVhcmx5IGV4aXQgaWYgb3B0aW9uIGlzIG5vdCBlbmFibGVkXG4gIGlmICghb3B0aW9ucy5naENvZGVCbG9ja3MpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2dpdGh1YkNvZGVCbG9ja3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCArPSAnwqgwJztcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oPzpefFxcbikoPzogezAsM30pKGBgYCt8fn5+KykoPzogKikoW15cXHNgfl0qKVxcbihbXFxzXFxTXSo/KVxcbig/OiB7MCwzfSlcXDEvZywgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIGRlbGltLCBsYW5ndWFnZSwgY29kZWJsb2NrKSB7XG4gICAgdmFyIGVuZCA9IChvcHRpb25zLm9taXRFeHRyYVdMSW5Db2RlQmxvY2tzKSA/ICcnIDogJ1xcbic7XG5cbiAgICAvLyBGaXJzdCBwYXJzZSB0aGUgZ2l0aHViIGNvZGUgYmxvY2tcbiAgICBjb2RlYmxvY2sgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnKShjb2RlYmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGNvZGVibG9jayA9IHNob3dkb3duLnN1YlBhcnNlcignZGV0YWInKShjb2RlYmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGNvZGVibG9jayA9IGNvZGVibG9jay5yZXBsYWNlKC9eXFxuKy9nLCAnJyk7IC8vIHRyaW0gbGVhZGluZyBuZXdsaW5lc1xuICAgIGNvZGVibG9jayA9IGNvZGVibG9jay5yZXBsYWNlKC9cXG4rJC9nLCAnJyk7IC8vIHRyaW0gdHJhaWxpbmcgd2hpdGVzcGFjZVxuXG4gICAgY29kZWJsb2NrID0gJzxwcmU+PGNvZGUnICsgKGxhbmd1YWdlID8gJyBjbGFzcz1cIicgKyBsYW5ndWFnZSArICcgbGFuZ3VhZ2UtJyArIGxhbmd1YWdlICsgJ1wiJyA6ICcnKSArICc+JyArIGNvZGVibG9jayArIGVuZCArICc8L2NvZGU+PC9wcmU+JztcblxuICAgIGNvZGVibG9jayA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAgIC8vIFNpbmNlIEdIQ29kZWJsb2NrcyBjYW4gYmUgZmFsc2UgcG9zaXRpdmVzLCB3ZSBuZWVkIHRvXG4gICAgLy8gc3RvcmUgdGhlIHByaW1pdGl2ZSB0ZXh0IGFuZCB0aGUgcGFyc2VkIHRleHQgaW4gYSBnbG9iYWwgdmFyLFxuICAgIC8vIGFuZCB0aGVuIHJldHVybiBhIHRva2VuXG4gICAgcmV0dXJuICdcXG5cXG7CqEcnICsgKGdsb2JhbHMuZ2hDb2RlQmxvY2tzLnB1c2goe3RleHQ6IHdob2xlTWF0Y2gsIGNvZGVibG9jazogY29kZWJsb2NrfSkgLSAxKSArICdHXFxuXFxuJztcbiAgfSk7XG5cbiAgLy8gYXR0YWNrbGFiOiBzdHJpcCBzZW50aW5lbFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqDAvLCAnJyk7XG5cbiAgcmV0dXJuIGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZ2l0aHViQ29kZUJsb2Nrcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQmxvY2snLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hCbG9jay5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKF5cXG4rfFxcbiskKS9nLCAnJyk7XG4gIHRleHQgPSAnXFxuXFxuwqhLJyArIChnbG9iYWxzLmdIdG1sQmxvY2tzLnB1c2godGV4dCkgLSAxKSArICdLXFxuXFxuJztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaEJsb2NrLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBIYXNoIGFuZCBlc2NhcGUgPGNvZGU+IGVsZW1lbnRzIHRoYXQgc2hvdWxkIG5vdCBiZSBwYXJzZWQgYXMgbWFya2Rvd25cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQ29kZVRhZ3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hDb2RlVGFncy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIgcmVwRnVuYyA9IGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtYXRjaCwgbGVmdCwgcmlnaHQpIHtcbiAgICB2YXIgY29kZWJsb2NrID0gbGVmdCArIHNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQ29kZScpKG1hdGNoLCBvcHRpb25zLCBnbG9iYWxzKSArIHJpZ2h0O1xuICAgIHJldHVybiAnwqhDJyArIChnbG9iYWxzLmdIdG1sU3BhbnMucHVzaChjb2RlYmxvY2spIC0gMSkgKyAnQyc7XG4gIH07XG5cbiAgLy8gSGFzaCBuYWtlZCA8Y29kZT5cbiAgdGV4dCA9IHNob3dkb3duLmhlbHBlci5yZXBsYWNlUmVjdXJzaXZlUmVnRXhwKHRleHQsIHJlcEZ1bmMsICc8Y29kZVxcXFxiW14+XSo+JywgJzwvY29kZT4nLCAnZ2ltJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaENvZGVUYWdzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoRWxlbWVudCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICByZXR1cm4gZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xKSB7XG4gICAgdmFyIGJsb2NrVGV4dCA9IG0xO1xuXG4gICAgLy8gVW5kbyBkb3VibGUgbGluZXNcbiAgICBibG9ja1RleHQgPSBibG9ja1RleHQucmVwbGFjZSgvXFxuXFxuL2csICdcXG4nKTtcbiAgICBibG9ja1RleHQgPSBibG9ja1RleHQucmVwbGFjZSgvXlxcbi8sICcnKTtcblxuICAgIC8vIHN0cmlwIHRyYWlsaW5nIGJsYW5rIGxpbmVzXG4gICAgYmxvY2tUZXh0ID0gYmxvY2tUZXh0LnJlcGxhY2UoL1xcbiskL2csICcnKTtcblxuICAgIC8vIFJlcGxhY2UgdGhlIGVsZW1lbnQgdGV4dCB3aXRoIGEgbWFya2VyIChcIsKoS3hLXCIgd2hlcmUgeCBpcyBpdHMga2V5KVxuICAgIGJsb2NrVGV4dCA9ICdcXG5cXG7CqEsnICsgKGdsb2JhbHMuZ0h0bWxCbG9ja3MucHVzaChibG9ja1RleHQpIC0gMSkgKyAnS1xcblxcbic7XG5cbiAgICByZXR1cm4gYmxvY2tUZXh0O1xuICB9O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoSFRNTEJsb2NrcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaEhUTUxCbG9ja3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdmFyIGJsb2NrVGFncyA9IFtcbiAgICAgICAgJ3ByZScsXG4gICAgICAgICdkaXYnLFxuICAgICAgICAnaDEnLFxuICAgICAgICAnaDInLFxuICAgICAgICAnaDMnLFxuICAgICAgICAnaDQnLFxuICAgICAgICAnaDUnLFxuICAgICAgICAnaDYnLFxuICAgICAgICAnYmxvY2txdW90ZScsXG4gICAgICAgICd0YWJsZScsXG4gICAgICAgICdkbCcsXG4gICAgICAgICdvbCcsXG4gICAgICAgICd1bCcsXG4gICAgICAgICdzY3JpcHQnLFxuICAgICAgICAnbm9zY3JpcHQnLFxuICAgICAgICAnZm9ybScsXG4gICAgICAgICdmaWVsZHNldCcsXG4gICAgICAgICdpZnJhbWUnLFxuICAgICAgICAnbWF0aCcsXG4gICAgICAgICdzdHlsZScsXG4gICAgICAgICdzZWN0aW9uJyxcbiAgICAgICAgJ2hlYWRlcicsXG4gICAgICAgICdmb290ZXInLFxuICAgICAgICAnbmF2JyxcbiAgICAgICAgJ2FydGljbGUnLFxuICAgICAgICAnYXNpZGUnLFxuICAgICAgICAnYWRkcmVzcycsXG4gICAgICAgICdhdWRpbycsXG4gICAgICAgICdjYW52YXMnLFxuICAgICAgICAnZmlndXJlJyxcbiAgICAgICAgJ2hncm91cCcsXG4gICAgICAgICdvdXRwdXQnLFxuICAgICAgICAndmlkZW8nLFxuICAgICAgICAncCdcbiAgICAgIF0sXG4gICAgICByZXBGdW5jID0gZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG1hdGNoLCBsZWZ0LCByaWdodCkge1xuICAgICAgICB2YXIgdHh0ID0gd2hvbGVNYXRjaDtcbiAgICAgICAgLy8gY2hlY2sgaWYgdGhpcyBodG1sIGVsZW1lbnQgaXMgbWFya2VkIGFzIG1hcmtkb3duXG4gICAgICAgIC8vIGlmIHNvLCBpdCdzIGNvbnRlbnRzIHNob3VsZCBiZSBwYXJzZWQgYXMgbWFya2Rvd25cbiAgICAgICAgaWYgKGxlZnQuc2VhcmNoKC9cXGJtYXJrZG93blxcYi8pICE9PSAtMSkge1xuICAgICAgICAgIHR4dCA9IGxlZnQgKyBnbG9iYWxzLmNvbnZlcnRlci5tYWtlSHRtbChtYXRjaCkgKyByaWdodDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJ1xcblxcbsKoSycgKyAoZ2xvYmFscy5nSHRtbEJsb2Nrcy5wdXNoKHR4dCkgLSAxKSArICdLXFxuXFxuJztcbiAgICAgIH07XG5cbiAgaWYgKG9wdGlvbnMuYmFja3NsYXNoRXNjYXBlc0hUTUxUYWdzKSB7XG4gICAgLy8gZW5jb2RlIGJhY2tzbGFzaCBlc2NhcGVkIEhUTUwgdGFnc1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcXFw8KFxcLz9bXj5dKz8pPi9nLCBmdW5jdGlvbiAod20sIGluc2lkZSkge1xuICAgICAgcmV0dXJuICcmbHQ7JyArIGluc2lkZSArICcmZ3Q7JztcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGhhc2ggSFRNTCBCbG9ja3NcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja1RhZ3MubGVuZ3RoOyArK2kpIHtcblxuICAgIHZhciBvcFRhZ1BvcyxcbiAgICAgICAgcmd4MSAgICAgPSBuZXcgUmVnRXhwKCdeIHswLDN9KDwnICsgYmxvY2tUYWdzW2ldICsgJ1xcXFxiW14+XSo+KScsICdpbScpLFxuICAgICAgICBwYXRMZWZ0ICA9ICc8JyArIGJsb2NrVGFnc1tpXSArICdcXFxcYltePl0qPicsXG4gICAgICAgIHBhdFJpZ2h0ID0gJzwvJyArIGJsb2NrVGFnc1tpXSArICc+JztcbiAgICAvLyAxLiBMb29rIGZvciB0aGUgZmlyc3QgcG9zaXRpb24gb2YgdGhlIGZpcnN0IG9wZW5pbmcgSFRNTCB0YWcgaW4gdGhlIHRleHRcbiAgICB3aGlsZSAoKG9wVGFnUG9zID0gc2hvd2Rvd24uaGVscGVyLnJlZ2V4SW5kZXhPZih0ZXh0LCByZ3gxKSkgIT09IC0xKSB7XG5cbiAgICAgIC8vIGlmIHRoZSBIVE1MIHRhZyBpcyBcXCBlc2NhcGVkLCB3ZSBuZWVkIHRvIGVzY2FwZSBpdCBhbmQgYnJlYWtcblxuXG4gICAgICAvLzIuIFNwbGl0IHRoZSB0ZXh0IGluIHRoYXQgcG9zaXRpb25cbiAgICAgIHZhciBzdWJUZXh0cyA9IHNob3dkb3duLmhlbHBlci5zcGxpdEF0SW5kZXgodGV4dCwgb3BUYWdQb3MpLFxuICAgICAgICAgIC8vMy4gTWF0Y2ggcmVjdXJzaXZlbHlcbiAgICAgICAgICBuZXdTdWJUZXh0MSA9IHNob3dkb3duLmhlbHBlci5yZXBsYWNlUmVjdXJzaXZlUmVnRXhwKHN1YlRleHRzWzFdLCByZXBGdW5jLCBwYXRMZWZ0LCBwYXRSaWdodCwgJ2ltJyk7XG5cbiAgICAgIC8vIHByZXZlbnQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgaWYgKG5ld1N1YlRleHQxID09PSBzdWJUZXh0c1sxXSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHRleHQgPSBzdWJUZXh0c1swXS5jb25jYXQobmV3U3ViVGV4dDEpO1xuICAgIH1cbiAgfVxuICAvLyBIUiBTUEVDSUFMIENBU0VcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKFxcbiB7MCwzfSg8KGhyKVxcYihbXjw+XSkqP1xcLz8+KVsgXFx0XSooPz1cXG57Mix9KSkvZyxcbiAgICBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hFbGVtZW50JykodGV4dCwgb3B0aW9ucywgZ2xvYmFscykpO1xuXG4gIC8vIFNwZWNpYWwgY2FzZSBmb3Igc3RhbmRhbG9uZSBIVE1MIGNvbW1lbnRzXG4gIHRleHQgPSBzaG93ZG93bi5oZWxwZXIucmVwbGFjZVJlY3Vyc2l2ZVJlZ0V4cCh0ZXh0LCBmdW5jdGlvbiAodHh0KSB7XG4gICAgcmV0dXJuICdcXG5cXG7CqEsnICsgKGdsb2JhbHMuZ0h0bWxCbG9ja3MucHVzaCh0eHQpIC0gMSkgKyAnS1xcblxcbic7XG4gIH0sICdeIHswLDN9PCEtLScsICctLT4nLCAnZ20nKTtcblxuICAvLyBQSFAgYW5kIEFTUC1zdHlsZSBwcm9jZXNzb3IgaW5zdHJ1Y3Rpb25zICg8Py4uLj8+IGFuZCA8JS4uLiU+KVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oPzpcXG5cXG4pKCB7MCwzfSg/OjwoWz8lXSlbXlxccl0qP1xcMj4pWyBcXHRdKig/PVxcbnsyLH0pKS9nLFxuICAgIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEVsZW1lbnQnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaEhUTUxCbG9ja3MuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIEhhc2ggc3BhbiBlbGVtZW50cyB0aGF0IHNob3VsZCBub3QgYmUgcGFyc2VkIGFzIG1hcmtkb3duXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxTcGFucycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaEhUTUxTcGFucy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICBmdW5jdGlvbiBoYXNoSFRNTFNwYW4gKGh0bWwpIHtcbiAgICByZXR1cm4gJ8KoQycgKyAoZ2xvYmFscy5nSHRtbFNwYW5zLnB1c2goaHRtbCkgLSAxKSArICdDJztcbiAgfVxuXG4gIC8vIEhhc2ggU2VsZiBDbG9zaW5nIHRhZ3NcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvPFtePl0rP1xcLz4vZ2ksIGZ1bmN0aW9uICh3bSkge1xuICAgIHJldHVybiBoYXNoSFRNTFNwYW4od20pO1xuICB9KTtcblxuICAvLyBIYXNoIHRhZ3Mgd2l0aG91dCBwcm9wZXJ0aWVzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLzwoW14+XSs/KT5bXFxzXFxTXSo/PFxcL1xcMT4vZywgZnVuY3Rpb24gKHdtKSB7XG4gICAgcmV0dXJuIGhhc2hIVE1MU3Bhbih3bSk7XG4gIH0pO1xuXG4gIC8vIEhhc2ggdGFncyB3aXRoIHByb3BlcnRpZXNcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvPChbXj5dKz8pXFxzW14+XSs/PltcXHNcXFNdKj88XFwvXFwxPi9nLCBmdW5jdGlvbiAod20pIHtcbiAgICByZXR1cm4gaGFzaEhUTUxTcGFuKHdtKTtcbiAgfSk7XG5cbiAgLy8gSGFzaCBzZWxmIGNsb3NpbmcgdGFncyB3aXRob3V0IC8+XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLzxbXj5dKz8+L2dpLCBmdW5jdGlvbiAod20pIHtcbiAgICByZXR1cm4gaGFzaEhUTUxTcGFuKHdtKTtcbiAgfSk7XG5cbiAgLypzaG93ZG93bi5oZWxwZXIubWF0Y2hSZWN1cnNpdmVSZWdFeHAodGV4dCwgJzxjb2RlXFxcXGJbXj5dKj4nLCAnPC9jb2RlPicsICdnaScpOyovXG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaEhUTUxTcGFucy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXG4vKipcbiAqIFVuaGFzaCBIVE1MIHNwYW5zXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcigndW5oYXNoSFRNTFNwYW5zJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmhhc2hIVE1MU3BhbnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBnbG9iYWxzLmdIdG1sU3BhbnMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcmVwVGV4dCA9IGdsb2JhbHMuZ0h0bWxTcGFuc1tpXSxcbiAgICAgICAgLy8gbGltaXRlciB0byBwcmV2ZW50IGluZmluaXRlIGxvb3AgKGFzc3VtZSAxMCBhcyBsaW1pdCBmb3IgcmVjdXJzZSlcbiAgICAgICAgbGltaXQgPSAwO1xuXG4gICAgd2hpbGUgKC/CqEMoXFxkKylDLy50ZXN0KHJlcFRleHQpKSB7XG4gICAgICB2YXIgbnVtID0gUmVnRXhwLiQxO1xuICAgICAgcmVwVGV4dCA9IHJlcFRleHQucmVwbGFjZSgnwqhDJyArIG51bSArICdDJywgZ2xvYmFscy5nSHRtbFNwYW5zW251bV0pO1xuICAgICAgaWYgKGxpbWl0ID09PSAxMCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdtYXhpbXVtIG5lc3Rpbmcgb2YgMTAgc3BhbnMgcmVhY2hlZCEhIScpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgICsrbGltaXQ7XG4gICAgfVxuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoJ8KoQycgKyBpICsgJ0MnLCByZXBUZXh0KTtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3VuaGFzaEhUTUxTcGFucy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogSGFzaCBhbmQgZXNjYXBlIDxwcmU+PGNvZGU+IGVsZW1lbnRzIHRoYXQgc2hvdWxkIG5vdCBiZSBwYXJzZWQgYXMgbWFya2Rvd25cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoUHJlQ29kZVRhZ3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hQcmVDb2RlVGFncy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIgcmVwRnVuYyA9IGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtYXRjaCwgbGVmdCwgcmlnaHQpIHtcbiAgICAvLyBlbmNvZGUgaHRtbCBlbnRpdGllc1xuICAgIHZhciBjb2RlYmxvY2sgPSBsZWZ0ICsgc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJykobWF0Y2gsIG9wdGlvbnMsIGdsb2JhbHMpICsgcmlnaHQ7XG4gICAgcmV0dXJuICdcXG5cXG7CqEcnICsgKGdsb2JhbHMuZ2hDb2RlQmxvY2tzLnB1c2goe3RleHQ6IHdob2xlTWF0Y2gsIGNvZGVibG9jazogY29kZWJsb2NrfSkgLSAxKSArICdHXFxuXFxuJztcbiAgfTtcblxuICAvLyBIYXNoIDxwcmU+PGNvZGU+XG4gIHRleHQgPSBzaG93ZG93bi5oZWxwZXIucmVwbGFjZVJlY3Vyc2l2ZVJlZ0V4cCh0ZXh0LCByZXBGdW5jLCAnXiB7MCwzfTxwcmVcXFxcYltePl0qPlxcXFxzKjxjb2RlXFxcXGJbXj5dKj4nLCAnXiB7MCwzfTwvY29kZT5cXFxccyo8L3ByZT4nLCAnZ2ltJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaFByZUNvZGVUYWdzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdoZWFkZXJzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hlYWRlcnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdmFyIGhlYWRlckxldmVsU3RhcnQgPSAoaXNOYU4ocGFyc2VJbnQob3B0aW9ucy5oZWFkZXJMZXZlbFN0YXJ0KSkpID8gMSA6IHBhcnNlSW50KG9wdGlvbnMuaGVhZGVyTGV2ZWxTdGFydCksXG5cbiAgICAgIC8vIFNldCB0ZXh0LXN0eWxlIGhlYWRlcnM6XG4gICAgICAvL1x0SGVhZGVyIDFcbiAgICAgIC8vXHQ9PT09PT09PVxuICAgICAgLy9cbiAgICAgIC8vXHRIZWFkZXIgMlxuICAgICAgLy9cdC0tLS0tLS0tXG4gICAgICAvL1xuICAgICAgc2V0ZXh0UmVnZXhIMSA9IChvcHRpb25zLnNtb290aExpdmVQcmV2aWV3KSA/IC9eKC4rKVsgXFx0XSpcXG49ezIsfVsgXFx0XSpcXG4rL2dtIDogL14oLispWyBcXHRdKlxcbj0rWyBcXHRdKlxcbisvZ20sXG4gICAgICBzZXRleHRSZWdleEgyID0gKG9wdGlvbnMuc21vb3RoTGl2ZVByZXZpZXcpID8gL14oLispWyBcXHRdKlxcbi17Mix9WyBcXHRdKlxcbisvZ20gOiAvXiguKylbIFxcdF0qXFxuLStbIFxcdF0qXFxuKy9nbTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHNldGV4dFJlZ2V4SDEsIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSkge1xuXG4gICAgdmFyIHNwYW5HYW11dCA9IHNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0JykobTEsIG9wdGlvbnMsIGdsb2JhbHMpLFxuICAgICAgICBoSUQgPSAob3B0aW9ucy5ub0hlYWRlcklkKSA/ICcnIDogJyBpZD1cIicgKyBoZWFkZXJJZChtMSkgKyAnXCInLFxuICAgICAgICBoTGV2ZWwgPSBoZWFkZXJMZXZlbFN0YXJ0LFxuICAgICAgICBoYXNoQmxvY2sgPSAnPGgnICsgaExldmVsICsgaElEICsgJz4nICsgc3BhbkdhbXV0ICsgJzwvaCcgKyBoTGV2ZWwgKyAnPic7XG4gICAgcmV0dXJuIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoaGFzaEJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgfSk7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZShzZXRleHRSZWdleEgyLCBmdW5jdGlvbiAobWF0Y2hGb3VuZCwgbTEpIHtcbiAgICB2YXIgc3BhbkdhbXV0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShtMSwgb3B0aW9ucywgZ2xvYmFscyksXG4gICAgICAgIGhJRCA9IChvcHRpb25zLm5vSGVhZGVySWQpID8gJycgOiAnIGlkPVwiJyArIGhlYWRlcklkKG0xKSArICdcIicsXG4gICAgICAgIGhMZXZlbCA9IGhlYWRlckxldmVsU3RhcnQgKyAxLFxuICAgICAgICBoYXNoQmxvY2sgPSAnPGgnICsgaExldmVsICsgaElEICsgJz4nICsgc3BhbkdhbXV0ICsgJzwvaCcgKyBoTGV2ZWwgKyAnPic7XG4gICAgcmV0dXJuIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoaGFzaEJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgfSk7XG5cbiAgLy8gYXR4LXN0eWxlIGhlYWRlcnM6XG4gIC8vICAjIEhlYWRlciAxXG4gIC8vICAjIyBIZWFkZXIgMlxuICAvLyAgIyMgSGVhZGVyIDIgd2l0aCBjbG9zaW5nIGhhc2hlcyAjI1xuICAvLyAgLi4uXG4gIC8vICAjIyMjIyMgSGVhZGVyIDZcbiAgLy9cbiAgdmFyIGF0eFN0eWxlID0gKG9wdGlvbnMucmVxdWlyZVNwYWNlQmVmb3JlSGVhZGluZ1RleHQpID8gL14oI3sxLDZ9KVsgXFx0XSsoLis/KVsgXFx0XSojKlxcbisvZ20gOiAvXigjezEsNn0pWyBcXHRdKiguKz8pWyBcXHRdKiMqXFxuKy9nbTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGF0eFN0eWxlLCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEsIG0yKSB7XG4gICAgdmFyIGhUZXh0ID0gbTI7XG4gICAgaWYgKG9wdGlvbnMuY3VzdG9taXplZEhlYWRlcklkKSB7XG4gICAgICBoVGV4dCA9IG0yLnJlcGxhY2UoL1xccz9cXHsoW157XSs/KX1cXHMqJC8sICcnKTtcbiAgICB9XG5cbiAgICB2YXIgc3BhbiA9IHNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0JykoaFRleHQsIG9wdGlvbnMsIGdsb2JhbHMpLFxuICAgICAgICBoSUQgPSAob3B0aW9ucy5ub0hlYWRlcklkKSA/ICcnIDogJyBpZD1cIicgKyBoZWFkZXJJZChtMikgKyAnXCInLFxuICAgICAgICBoTGV2ZWwgPSBoZWFkZXJMZXZlbFN0YXJ0IC0gMSArIG0xLmxlbmd0aCxcbiAgICAgICAgaGVhZGVyID0gJzxoJyArIGhMZXZlbCArIGhJRCArICc+JyArIHNwYW4gKyAnPC9oJyArIGhMZXZlbCArICc+JztcblxuICAgIHJldHVybiBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hCbG9jaycpKGhlYWRlciwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGhlYWRlcklkIChtKSB7XG4gICAgdmFyIHRpdGxlLFxuICAgICAgICBwcmVmaXg7XG5cbiAgICAvLyBJdCBpcyBzZXBhcmF0ZSBmcm9tIG90aGVyIG9wdGlvbnMgdG8gYWxsb3cgY29tYmluaW5nIHByZWZpeCBhbmQgY3VzdG9taXplZFxuICAgIGlmIChvcHRpb25zLmN1c3RvbWl6ZWRIZWFkZXJJZCkge1xuICAgICAgdmFyIG1hdGNoID0gbS5tYXRjaCgvXFx7KFtee10rPyl9XFxzKiQvKTtcbiAgICAgIGlmIChtYXRjaCAmJiBtYXRjaFsxXSkge1xuICAgICAgICBtID0gbWF0Y2hbMV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGl0bGUgPSBtO1xuXG4gICAgLy8gUHJlZml4IGlkIHRvIHByZXZlbnQgY2F1c2luZyBpbmFkdmVydGVudCBwcmUtZXhpc3Rpbmcgc3R5bGUgbWF0Y2hlcy5cbiAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG9wdGlvbnMucHJlZml4SGVhZGVySWQpKSB7XG4gICAgICBwcmVmaXggPSBvcHRpb25zLnByZWZpeEhlYWRlcklkO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5wcmVmaXhIZWFkZXJJZCA9PT0gdHJ1ZSkge1xuICAgICAgcHJlZml4ID0gJ3NlY3Rpb24tJztcbiAgICB9IGVsc2Uge1xuICAgICAgcHJlZml4ID0gJyc7XG4gICAgfVxuXG4gICAgaWYgKCFvcHRpb25zLnJhd1ByZWZpeEhlYWRlcklkKSB7XG4gICAgICB0aXRsZSA9IHByZWZpeCArIHRpdGxlO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmdoQ29tcGF0aWJsZUhlYWRlcklkKSB7XG4gICAgICB0aXRsZSA9IHRpdGxlXG4gICAgICAgIC5yZXBsYWNlKC8gL2csICctJylcbiAgICAgICAgLy8gcmVwbGFjZSBwcmV2aW91c2x5IGVzY2FwZWQgY2hhcnMgKCYsIMKoIGFuZCAkKVxuICAgICAgICAucmVwbGFjZSgvJmFtcDsvZywgJycpXG4gICAgICAgIC5yZXBsYWNlKC/CqFQvZywgJycpXG4gICAgICAgIC5yZXBsYWNlKC/CqEQvZywgJycpXG4gICAgICAgIC8vIHJlcGxhY2UgcmVzdCBvZiB0aGUgY2hhcnMgKCZ+JCBhcmUgcmVwZWF0ZWQgYXMgdGhleSBtaWdodCBoYXZlIGJlZW4gZXNjYXBlZClcbiAgICAgICAgLy8gYm9ycm93ZWQgZnJvbSBnaXRodWIncyByZWRjYXJwZXQgKHNvbWUgdGhleSBzaG91bGQgcHJvZHVjZSBzaW1pbGFyIHJlc3VsdHMpXG4gICAgICAgIC5yZXBsYWNlKC9bJiskLFxcLzo7PT9AXCIje318XsKoflxcW1xcXWBcXFxcKikoJS4hJzw+XS9nLCAnJylcbiAgICAgICAgLnRvTG93ZXJDYXNlKCk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnJhd0hlYWRlcklkKSB7XG4gICAgICB0aXRsZSA9IHRpdGxlXG4gICAgICAgIC5yZXBsYWNlKC8gL2csICctJylcbiAgICAgICAgLy8gcmVwbGFjZSBwcmV2aW91c2x5IGVzY2FwZWQgY2hhcnMgKCYsIMKoIGFuZCAkKVxuICAgICAgICAucmVwbGFjZSgvJmFtcDsvZywgJyYnKVxuICAgICAgICAucmVwbGFjZSgvwqhUL2csICfCqCcpXG4gICAgICAgIC5yZXBsYWNlKC/CqEQvZywgJyQnKVxuICAgICAgICAvLyByZXBsYWNlIFwiIGFuZCAnXG4gICAgICAgIC5yZXBsYWNlKC9bXCInXS9nLCAnLScpXG4gICAgICAgIC50b0xvd2VyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aXRsZSA9IHRpdGxlXG4gICAgICAgIC5yZXBsYWNlKC9bXlxcd10vZywgJycpXG4gICAgICAgIC50b0xvd2VyQ2FzZSgpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLnJhd1ByZWZpeEhlYWRlcklkKSB7XG4gICAgICB0aXRsZSA9IHByZWZpeCArIHRpdGxlO1xuICAgIH1cblxuICAgIGlmIChnbG9iYWxzLmhhc2hMaW5rQ291bnRzW3RpdGxlXSkge1xuICAgICAgdGl0bGUgPSB0aXRsZSArICctJyArIChnbG9iYWxzLmhhc2hMaW5rQ291bnRzW3RpdGxlXSsrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZ2xvYmFscy5oYXNoTGlua0NvdW50c1t0aXRsZV0gPSAxO1xuICAgIH1cbiAgICByZXR1cm4gdGl0bGU7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdoZWFkZXJzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBUdXJuIE1hcmtkb3duIGxpbmsgc2hvcnRjdXRzIGludG8gWEhUTUwgPGE+IHRhZ3MuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignaG9yaXpvbnRhbFJ1bGUnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hvcml6b250YWxSdWxlLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciBrZXkgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hCbG9jaycpKCc8aHIgLz4nLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXiB7MCwyfSggPy0pezMsfVsgXFx0XSokL2dtLCBrZXkpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eIHswLDJ9KCA/XFwqKXszLH1bIFxcdF0qJC9nbSwga2V5KTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXiB7MCwyfSggP18pezMsfVsgXFx0XSokL2dtLCBrZXkpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hvcml6b250YWxSdWxlLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBUdXJuIE1hcmtkb3duIGltYWdlIHNob3J0Y3V0cyBpbnRvIDxpbWc+IHRhZ3MuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignaW1hZ2VzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2ltYWdlcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIgaW5saW5lUmVnRXhwICAgICAgPSAvIVxcWyhbXlxcXV0qPyldWyBcXHRdKigpXFwoWyBcXHRdPzw/KFtcXFNdKz8oPzpcXChbXFxTXSo/XFwpW1xcU10qPyk/KT4/KD86ID0oWypcXGRdK1tBLVphLXolXXswLDR9KXgoWypcXGRdK1tBLVphLXolXXswLDR9KSk/WyBcXHRdKig/OihbXCInXSkoW15cIl0qPylcXDYpP1sgXFx0XT9cXCkvZyxcbiAgICAgIGNyYXp5UmVnRXhwICAgICAgID0gLyFcXFsoW15cXF1dKj8pXVsgXFx0XSooKVxcKFsgXFx0XT88KFtePl0qKT4oPzogPShbKlxcZF0rW0EtWmEteiVdezAsNH0peChbKlxcZF0rW0EtWmEteiVdezAsNH0pKT9bIFxcdF0qKD86KD86KFtcIiddKShbXlwiXSo/KVxcNikpP1sgXFx0XT9cXCkvZyxcbiAgICAgIGJhc2U2NFJlZ0V4cCAgICAgID0gLyFcXFsoW15cXF1dKj8pXVsgXFx0XSooKVxcKFsgXFx0XT88PyhkYXRhOi4rP1xcLy4rPztiYXNlNjQsW0EtWmEtejAtOSsvPVxcbl0rPyk+Pyg/OiA9KFsqXFxkXStbQS1aYS16JV17MCw0fSl4KFsqXFxkXStbQS1aYS16JV17MCw0fSkpP1sgXFx0XSooPzooW1wiJ10pKFteXCJdKj8pXFw2KT9bIFxcdF0/XFwpL2csXG4gICAgICByZWZlcmVuY2VSZWdFeHAgICA9IC8hXFxbKFteXFxdXSo/KV0gPyg/OlxcbiAqKT9cXFsoW1xcc1xcU10qPyldKCkoKSgpKCkoKS9nLFxuICAgICAgcmVmU2hvcnRjdXRSZWdFeHAgPSAvIVxcWyhbXlxcW1xcXV0rKV0oKSgpKCkoKSgpL2c7XG5cbiAgZnVuY3Rpb24gd3JpdGVJbWFnZVRhZ0Jhc2U2NCAod2hvbGVNYXRjaCwgYWx0VGV4dCwgbGlua0lkLCB1cmwsIHdpZHRoLCBoZWlnaHQsIG01LCB0aXRsZSkge1xuICAgIHVybCA9IHVybC5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgIHJldHVybiB3cml0ZUltYWdlVGFnICh3aG9sZU1hdGNoLCBhbHRUZXh0LCBsaW5rSWQsIHVybCwgd2lkdGgsIGhlaWdodCwgbTUsIHRpdGxlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHdyaXRlSW1hZ2VUYWcgKHdob2xlTWF0Y2gsIGFsdFRleHQsIGxpbmtJZCwgdXJsLCB3aWR0aCwgaGVpZ2h0LCBtNSwgdGl0bGUpIHtcblxuICAgIHZhciBnVXJscyAgID0gZ2xvYmFscy5nVXJscyxcbiAgICAgICAgZ1RpdGxlcyA9IGdsb2JhbHMuZ1RpdGxlcyxcbiAgICAgICAgZ0RpbXMgICA9IGdsb2JhbHMuZ0RpbWVuc2lvbnM7XG5cbiAgICBsaW5rSWQgPSBsaW5rSWQudG9Mb3dlckNhc2UoKTtcblxuICAgIGlmICghdGl0bGUpIHtcbiAgICAgIHRpdGxlID0gJyc7XG4gICAgfVxuICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgZXhwbGljaXQgZW1wdHkgdXJsXG4gICAgaWYgKHdob2xlTWF0Y2guc2VhcmNoKC9cXCg8P1xccyo+PyA/KFsnXCJdLipbJ1wiXSk/XFwpJC9tKSA+IC0xKSB7XG4gICAgICB1cmwgPSAnJztcblxuICAgIH0gZWxzZSBpZiAodXJsID09PSAnJyB8fCB1cmwgPT09IG51bGwpIHtcbiAgICAgIGlmIChsaW5rSWQgPT09ICcnIHx8IGxpbmtJZCA9PT0gbnVsbCkge1xuICAgICAgICAvLyBsb3dlci1jYXNlIGFuZCB0dXJuIGVtYmVkZGVkIG5ld2xpbmVzIGludG8gc3BhY2VzXG4gICAgICAgIGxpbmtJZCA9IGFsdFRleHQudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC8gP1xcbi9nLCAnICcpO1xuICAgICAgfVxuICAgICAgdXJsID0gJyMnICsgbGlua0lkO1xuXG4gICAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChnVXJsc1tsaW5rSWRdKSkge1xuICAgICAgICB1cmwgPSBnVXJsc1tsaW5rSWRdO1xuICAgICAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChnVGl0bGVzW2xpbmtJZF0pKSB7XG4gICAgICAgICAgdGl0bGUgPSBnVGl0bGVzW2xpbmtJZF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZ0RpbXNbbGlua0lkXSkpIHtcbiAgICAgICAgICB3aWR0aCA9IGdEaW1zW2xpbmtJZF0ud2lkdGg7XG4gICAgICAgICAgaGVpZ2h0ID0gZ0RpbXNbbGlua0lkXS5oZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB3aG9sZU1hdGNoO1xuICAgICAgfVxuICAgIH1cblxuICAgIGFsdFRleHQgPSBhbHRUZXh0XG4gICAgICAucmVwbGFjZSgvXCIvZywgJyZxdW90OycpXG4gICAgLy9hbHRUZXh0ID0gc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnMoYWx0VGV4dCwgJypfJywgZmFsc2UpO1xuICAgICAgLnJlcGxhY2Uoc2hvd2Rvd24uaGVscGVyLnJlZ2V4ZXMuYXN0ZXJpc2tEYXNoQW5kQ29sb24sIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuICAgIC8vdXJsID0gc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnModXJsLCAnKl8nLCBmYWxzZSk7XG4gICAgdXJsID0gdXJsLnJlcGxhY2Uoc2hvd2Rvd24uaGVscGVyLnJlZ2V4ZXMuYXN0ZXJpc2tEYXNoQW5kQ29sb24sIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuICAgIHZhciByZXN1bHQgPSAnPGltZyBzcmM9XCInICsgdXJsICsgJ1wiIGFsdD1cIicgKyBhbHRUZXh0ICsgJ1wiJztcblxuICAgIGlmICh0aXRsZSAmJiBzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcodGl0bGUpKSB7XG4gICAgICB0aXRsZSA9IHRpdGxlXG4gICAgICAgIC5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JylcbiAgICAgIC8vdGl0bGUgPSBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyh0aXRsZSwgJypfJywgZmFsc2UpO1xuICAgICAgICAucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgICByZXN1bHQgKz0gJyB0aXRsZT1cIicgKyB0aXRsZSArICdcIic7XG4gICAgfVxuXG4gICAgaWYgKHdpZHRoICYmIGhlaWdodCkge1xuICAgICAgd2lkdGggID0gKHdpZHRoID09PSAnKicpID8gJ2F1dG8nIDogd2lkdGg7XG4gICAgICBoZWlnaHQgPSAoaGVpZ2h0ID09PSAnKicpID8gJ2F1dG8nIDogaGVpZ2h0O1xuXG4gICAgICByZXN1bHQgKz0gJyB3aWR0aD1cIicgKyB3aWR0aCArICdcIic7XG4gICAgICByZXN1bHQgKz0gJyBoZWlnaHQ9XCInICsgaGVpZ2h0ICsgJ1wiJztcbiAgICB9XG5cbiAgICByZXN1bHQgKz0gJyAvPic7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gRmlyc3QsIGhhbmRsZSByZWZlcmVuY2Utc3R5bGUgbGFiZWxlZCBpbWFnZXM6ICFbYWx0IHRleHRdW2lkXVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlZmVyZW5jZVJlZ0V4cCwgd3JpdGVJbWFnZVRhZyk7XG5cbiAgLy8gTmV4dCwgaGFuZGxlIGlubGluZSBpbWFnZXM6ICAhW2FsdCB0ZXh0XSh1cmwgPTx3aWR0aD54PGhlaWdodD4gXCJvcHRpb25hbCB0aXRsZVwiKVxuXG4gIC8vIGJhc2U2NCBlbmNvZGVkIGltYWdlc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGJhc2U2NFJlZ0V4cCwgd3JpdGVJbWFnZVRhZ0Jhc2U2NCk7XG5cbiAgLy8gY2FzZXMgd2l0aCBjcmF6eSB1cmxzIGxpa2UgLi9pbWFnZS9jYXQxKS5wbmdcbiAgdGV4dCA9IHRleHQucmVwbGFjZShjcmF6eVJlZ0V4cCwgd3JpdGVJbWFnZVRhZyk7XG5cbiAgLy8gbm9ybWFsIGNhc2VzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoaW5saW5lUmVnRXhwLCB3cml0ZUltYWdlVGFnKTtcblxuICAvLyBoYW5kbGUgcmVmZXJlbmNlLXN0eWxlIHNob3J0Y3V0czogIVtpbWcgdGV4dF1cbiAgdGV4dCA9IHRleHQucmVwbGFjZShyZWZTaG9ydGN1dFJlZ0V4cCwgd3JpdGVJbWFnZVRhZyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaW1hZ2VzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdpdGFsaWNzQW5kQm9sZCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdpdGFsaWNzQW5kQm9sZC5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBpdCdzIGZhc3RlciB0byBoYXZlIDMgc2VwYXJhdGUgcmVnZXhlcyBmb3IgZWFjaCBjYXNlIHRoYW4gaGF2ZSBqdXN0IG9uZVxuICAvLyBiZWNhdXNlIG9mIGJhY2t0cmFjaW5nLCBpbiBzb21lIGNhc2VzLCBpdCBjb3VsZCBsZWFkIHRvIGFuIGV4cG9uZW50aWFsIGVmZmVjdFxuICAvLyBjYWxsZWQgXCJjYXRhc3Ryb3BoaWMgYmFja3RyYWNlXCIuIE9taW5vdXMhXG5cbiAgZnVuY3Rpb24gcGFyc2VJbnNpZGUgKHR4dCwgbGVmdCwgcmlnaHQpIHtcbiAgICAvKlxuICAgIGlmIChvcHRpb25zLnNpbXBsaWZpZWRBdXRvTGluaykge1xuICAgICAgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzaW1wbGlmaWVkQXV0b0xpbmtzJykodHh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB9XG4gICAgKi9cbiAgICByZXR1cm4gbGVmdCArIHR4dCArIHJpZ2h0O1xuICB9XG5cbiAgLy8gUGFyc2UgdW5kZXJzY29yZXNcbiAgaWYgKG9wdGlvbnMubGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3Jlcykge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcYl9fXyhcXFNbXFxzXFxTXSo/KV9fX1xcYi9nLCBmdW5jdGlvbiAod20sIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsICc8c3Ryb25nPjxlbT4nLCAnPC9lbT48L3N0cm9uZz4nKTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXGJfXyhcXFNbXFxzXFxTXSo/KV9fXFxiL2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnNpZGUgKHR4dCwgJzxzdHJvbmc+JywgJzwvc3Ryb25nPicpO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcYl8oXFxTW1xcc1xcU10qPylfXFxiL2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnNpZGUgKHR4dCwgJzxlbT4nLCAnPC9lbT4nKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9fX18oXFxTW1xcc1xcU10qPylfX18vZywgZnVuY3Rpb24gKHdtLCBtKSB7XG4gICAgICByZXR1cm4gKC9cXFMkLy50ZXN0KG0pKSA/IHBhcnNlSW5zaWRlIChtLCAnPHN0cm9uZz48ZW0+JywgJzwvZW0+PC9zdHJvbmc+JykgOiB3bTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9fXyhcXFNbXFxzXFxTXSo/KV9fL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxzdHJvbmc+JywgJzwvc3Ryb25nPicpIDogd207XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXyhbXlxcc19dW1xcc1xcU10qPylfL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgLy8gIS9eX1teX10vLnRlc3QobSkgLSB0ZXN0IGlmIGl0IGRvZXNuJ3Qgc3RhcnQgd2l0aCBfXyAoc2luY2UgaXQgc2VlbXMgcmVkdW5kYW50LCB3ZSByZW1vdmVkIGl0KVxuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxlbT4nLCAnPC9lbT4nKSA6IHdtO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gTm93IHBhcnNlIGFzdGVyaXNrc1xuICBpZiAob3B0aW9ucy5saXRlcmFsTWlkV29yZEFzdGVyaXNrcykge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhbXipdfF4pXFxCXFwqXFwqXFwqKFxcU1tcXHNcXFNdKj8pXFwqXFwqXFwqXFxCKD8hXFwqKS9nLCBmdW5jdGlvbiAod20sIGxlYWQsIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsIGxlYWQgKyAnPHN0cm9uZz48ZW0+JywgJzwvZW0+PC9zdHJvbmc+Jyk7XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvKFteKl18XilcXEJcXCpcXCooXFxTW1xcc1xcU10qPylcXCpcXCpcXEIoPyFcXCopL2csIGZ1bmN0aW9uICh3bSwgbGVhZCwgdHh0KSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnNpZGUgKHR4dCwgbGVhZCArICc8c3Ryb25nPicsICc8L3N0cm9uZz4nKTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oW14qXXxeKVxcQlxcKihcXFNbXFxzXFxTXSo/KVxcKlxcQig/IVxcKikvZywgZnVuY3Rpb24gKHdtLCBsZWFkLCB0eHQpIHtcbiAgICAgIHJldHVybiBwYXJzZUluc2lkZSAodHh0LCBsZWFkICsgJzxlbT4nLCAnPC9lbT4nKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXCpcXCpcXCooXFxTW1xcc1xcU10qPylcXCpcXCpcXCovZywgZnVuY3Rpb24gKHdtLCBtKSB7XG4gICAgICByZXR1cm4gKC9cXFMkLy50ZXN0KG0pKSA/IHBhcnNlSW5zaWRlIChtLCAnPHN0cm9uZz48ZW0+JywgJzwvZW0+PC9zdHJvbmc+JykgOiB3bTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXCpcXCooXFxTW1xcc1xcU10qPylcXCpcXCovZywgZnVuY3Rpb24gKHdtLCBtKSB7XG4gICAgICByZXR1cm4gKC9cXFMkLy50ZXN0KG0pKSA/IHBhcnNlSW5zaWRlIChtLCAnPHN0cm9uZz4nLCAnPC9zdHJvbmc+JykgOiB3bTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXCooW15cXHMqXVtcXHNcXFNdKj8pXFwqL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgLy8gIS9eXFwqW14qXS8udGVzdChtKSAtIHRlc3QgaWYgaXQgZG9lc24ndCBzdGFydCB3aXRoICoqIChzaW5jZSBpdCBzZWVtcyByZWR1bmRhbnQsIHdlIHJlbW92ZWQgaXQpXG4gICAgICByZXR1cm4gKC9cXFMkLy50ZXN0KG0pKSA/IHBhcnNlSW5zaWRlIChtLCAnPGVtPicsICc8L2VtPicpIDogd207XG4gICAgfSk7XG4gIH1cblxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2l0YWxpY3NBbmRCb2xkLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBGb3JtIEhUTUwgb3JkZXJlZCAobnVtYmVyZWQpIGFuZCB1bm9yZGVyZWQgKGJ1bGxldGVkKSBsaXN0cy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdsaXN0cycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKipcbiAgICogUHJvY2VzcyB0aGUgY29udGVudHMgb2YgYSBzaW5nbGUgb3JkZXJlZCBvciB1bm9yZGVyZWQgbGlzdCwgc3BsaXR0aW5nIGl0XG4gICAqIGludG8gaW5kaXZpZHVhbCBsaXN0IGl0ZW1zLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGlzdFN0clxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHRyaW1UcmFpbGluZ1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgZnVuY3Rpb24gcHJvY2Vzc0xpc3RJdGVtcyAobGlzdFN0ciwgdHJpbVRyYWlsaW5nKSB7XG4gICAgLy8gVGhlICRnX2xpc3RfbGV2ZWwgZ2xvYmFsIGtlZXBzIHRyYWNrIG9mIHdoZW4gd2UncmUgaW5zaWRlIGEgbGlzdC5cbiAgICAvLyBFYWNoIHRpbWUgd2UgZW50ZXIgYSBsaXN0LCB3ZSBpbmNyZW1lbnQgaXQ7IHdoZW4gd2UgbGVhdmUgYSBsaXN0LFxuICAgIC8vIHdlIGRlY3JlbWVudC4gSWYgaXQncyB6ZXJvLCB3ZSdyZSBub3QgaW4gYSBsaXN0IGFueW1vcmUuXG4gICAgLy9cbiAgICAvLyBXZSBkbyB0aGlzIGJlY2F1c2Ugd2hlbiB3ZSdyZSBub3QgaW5zaWRlIGEgbGlzdCwgd2Ugd2FudCB0byB0cmVhdFxuICAgIC8vIHNvbWV0aGluZyBsaWtlIHRoaXM6XG4gICAgLy9cbiAgICAvLyAgICBJIHJlY29tbWVuZCB1cGdyYWRpbmcgdG8gdmVyc2lvblxuICAgIC8vICAgIDguIE9vcHMsIG5vdyB0aGlzIGxpbmUgaXMgdHJlYXRlZFxuICAgIC8vICAgIGFzIGEgc3ViLWxpc3QuXG4gICAgLy9cbiAgICAvLyBBcyBhIHNpbmdsZSBwYXJhZ3JhcGgsIGRlc3BpdGUgdGhlIGZhY3QgdGhhdCB0aGUgc2Vjb25kIGxpbmUgc3RhcnRzXG4gICAgLy8gd2l0aCBhIGRpZ2l0LXBlcmlvZC1zcGFjZSBzZXF1ZW5jZS5cbiAgICAvL1xuICAgIC8vIFdoZXJlYXMgd2hlbiB3ZSdyZSBpbnNpZGUgYSBsaXN0IChvciBzdWItbGlzdCksIHRoYXQgbGluZSB3aWxsIGJlXG4gICAgLy8gdHJlYXRlZCBhcyB0aGUgc3RhcnQgb2YgYSBzdWItbGlzdC4gV2hhdCBhIGtsdWRnZSwgaHVoPyBUaGlzIGlzXG4gICAgLy8gYW4gYXNwZWN0IG9mIE1hcmtkb3duJ3Mgc3ludGF4IHRoYXQncyBoYXJkIHRvIHBhcnNlIHBlcmZlY3RseVxuICAgIC8vIHdpdGhvdXQgcmVzb3J0aW5nIHRvIG1pbmQtcmVhZGluZy4gUGVyaGFwcyB0aGUgc29sdXRpb24gaXMgdG9cbiAgICAvLyBjaGFuZ2UgdGhlIHN5bnRheCBydWxlcyBzdWNoIHRoYXQgc3ViLWxpc3RzIG11c3Qgc3RhcnQgd2l0aCBhXG4gICAgLy8gc3RhcnRpbmcgY2FyZGluYWwgbnVtYmVyOyBlLmcuIFwiMS5cIiBvciBcImEuXCIuXG4gICAgZ2xvYmFscy5nTGlzdExldmVsKys7XG5cbiAgICAvLyB0cmltIHRyYWlsaW5nIGJsYW5rIGxpbmVzOlxuICAgIGxpc3RTdHIgPSBsaXN0U3RyLnJlcGxhY2UoL1xcbnsyLH0kLywgJ1xcbicpO1xuXG4gICAgLy8gYXR0YWNrbGFiOiBhZGQgc2VudGluZWwgdG8gZW11bGF0ZSBcXHpcbiAgICBsaXN0U3RyICs9ICfCqDAnO1xuXG4gICAgdmFyIHJneCA9IC8oXFxuKT8oXiB7MCwzfSkoWyorLV18XFxkK1suXSlbIFxcdF0rKChcXFsoeHxYfCApP10pP1sgXFx0XSpbXlxccl0rPyhcXG57MSwyfSkpKD89XFxuKijCqDB8IHswLDN9KFsqKy1dfFxcZCtbLl0pWyBcXHRdKykpL2dtLFxuICAgICAgICBpc1BhcmFncmFwaGVkID0gKC9cXG5bIFxcdF0qXFxuKD8hwqgwKS8udGVzdChsaXN0U3RyKSk7XG5cbiAgICAvLyBTaW5jZSB2ZXJzaW9uIDEuNSwgbmVzdGluZyBzdWJsaXN0cyByZXF1aXJlcyA0IHNwYWNlcyAob3IgMSB0YWIpIGluZGVudGF0aW9uLFxuICAgIC8vIHdoaWNoIGlzIGEgc3ludGF4IGJyZWFraW5nIGNoYW5nZVxuICAgIC8vIGFjdGl2YXRpbmcgdGhpcyBvcHRpb24gcmV2ZXJ0cyB0byBvbGQgYmVoYXZpb3JcbiAgICBpZiAob3B0aW9ucy5kaXNhYmxlRm9yY2VkNFNwYWNlc0luZGVudGVkU3VibGlzdHMpIHtcbiAgICAgIHJneCA9IC8oXFxuKT8oXiB7MCwzfSkoWyorLV18XFxkK1suXSlbIFxcdF0rKChcXFsoeHxYfCApP10pP1sgXFx0XSpbXlxccl0rPyhcXG57MSwyfSkpKD89XFxuKijCqDB8XFwyKFsqKy1dfFxcZCtbLl0pWyBcXHRdKykpL2dtO1xuICAgIH1cblxuICAgIGxpc3RTdHIgPSBsaXN0U3RyLnJlcGxhY2Uocmd4LCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEsIG0yLCBtMywgbTQsIHRhc2tidG4sIGNoZWNrZWQpIHtcbiAgICAgIGNoZWNrZWQgPSAoY2hlY2tlZCAmJiBjaGVja2VkLnRyaW0oKSAhPT0gJycpO1xuXG4gICAgICB2YXIgaXRlbSA9IHNob3dkb3duLnN1YlBhcnNlcignb3V0ZGVudCcpKG00LCBvcHRpb25zLCBnbG9iYWxzKSxcbiAgICAgICAgICBidWxsZXRTdHlsZSA9ICcnO1xuXG4gICAgICAvLyBTdXBwb3J0IGZvciBnaXRodWIgdGFza2xpc3RzXG4gICAgICBpZiAodGFza2J0biAmJiBvcHRpb25zLnRhc2tsaXN0cykge1xuICAgICAgICBidWxsZXRTdHlsZSA9ICcgY2xhc3M9XCJ0YXNrLWxpc3QtaXRlbVwiIHN0eWxlPVwibGlzdC1zdHlsZS10eXBlOiBub25lO1wiJztcbiAgICAgICAgaXRlbSA9IGl0ZW0ucmVwbGFjZSgvXlsgXFx0XSpcXFsoeHxYfCApP10vbSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHZhciBvdHAgPSAnPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGRpc2FibGVkIHN0eWxlPVwibWFyZ2luOiAwcHggMC4zNWVtIDAuMjVlbSAtMS42ZW07IHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XCInO1xuICAgICAgICAgIGlmIChjaGVja2VkKSB7XG4gICAgICAgICAgICBvdHAgKz0gJyBjaGVja2VkJztcbiAgICAgICAgICB9XG4gICAgICAgICAgb3RwICs9ICc+JztcbiAgICAgICAgICByZXR1cm4gb3RwO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gSVNTVUUgIzMxMlxuICAgICAgLy8gVGhpcyBpbnB1dDogLSAtIC0gYVxuICAgICAgLy8gY2F1c2VzIHRyb3VibGUgdG8gdGhlIHBhcnNlciwgc2luY2UgaXQgaW50ZXJwcmV0cyBpdCBhczpcbiAgICAgIC8vIDx1bD48bGk+PGxpPjxsaT5hPC9saT48L2xpPjwvbGk+PC91bD5cbiAgICAgIC8vIGluc3RlYWQgb2Y6XG4gICAgICAvLyA8dWw+PGxpPi0gLSBhPC9saT48L3VsPlxuICAgICAgLy8gU28sIHRvIHByZXZlbnQgaXQsIHdlIHdpbGwgcHV0IGEgbWFya2VyICjCqEEpaW4gdGhlIGJlZ2lubmluZyBvZiB0aGUgbGluZVxuICAgICAgLy8gS2luZCBvZiBoYWNraXNoL21vbmtleSBwYXRjaGluZywgYnV0IHNlZW1zIG1vcmUgZWZmZWN0aXZlIHRoYW4gb3ZlcmNvbXBsaWNhdGluZyB0aGUgbGlzdCBwYXJzZXJcbiAgICAgIGl0ZW0gPSBpdGVtLnJlcGxhY2UoL14oWy0qK118XFxkXFwuKVsgXFx0XStbXFxTXFxuIF0qL2csIGZ1bmN0aW9uICh3bTIpIHtcbiAgICAgICAgcmV0dXJuICfCqEEnICsgd20yO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIG0xIC0gTGVhZGluZyBsaW5lIG9yXG4gICAgICAvLyBIYXMgYSBkb3VibGUgcmV0dXJuIChtdWx0aSBwYXJhZ3JhcGgpIG9yXG4gICAgICAvLyBIYXMgc3VibGlzdFxuICAgICAgaWYgKG0xIHx8IChpdGVtLnNlYXJjaCgvXFxuezIsfS8pID4gLTEpKSB7XG4gICAgICAgIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2dpdGh1YkNvZGVCbG9ja3MnKShpdGVtLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgICAgaXRlbSA9IHNob3dkb3duLnN1YlBhcnNlcignYmxvY2tHYW11dCcpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUmVjdXJzaW9uIGZvciBzdWItbGlzdHM6XG4gICAgICAgIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2xpc3RzJykoaXRlbSwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIGl0ZW0gPSBpdGVtLnJlcGxhY2UoL1xcbiQvLCAnJyk7IC8vIGNob21wKGl0ZW0pXG4gICAgICAgIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hIVE1MQmxvY2tzJykoaXRlbSwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgICAgICAgLy8gQ29sYXBzZSBkb3VibGUgbGluZWJyZWFrc1xuICAgICAgICBpdGVtID0gaXRlbS5yZXBsYWNlKC9cXG5cXG4rL2csICdcXG5cXG4nKTtcbiAgICAgICAgaWYgKGlzUGFyYWdyYXBoZWQpIHtcbiAgICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdwYXJhZ3JhcGhzJykoaXRlbSwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaXRlbSA9IHNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0JykoaXRlbSwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gbm93IHdlIG5lZWQgdG8gcmVtb3ZlIHRoZSBtYXJrZXIgKMKoQSlcbiAgICAgIGl0ZW0gPSBpdGVtLnJlcGxhY2UoJ8KoQScsICcnKTtcbiAgICAgIC8vIHdlIGNhbiBmaW5hbGx5IHdyYXAgdGhlIGxpbmUgaW4gbGlzdCBpdGVtIHRhZ3NcbiAgICAgIGl0ZW0gPSAgJzxsaScgKyBidWxsZXRTdHlsZSArICc+JyArIGl0ZW0gKyAnPC9saT5cXG4nO1xuXG4gICAgICByZXR1cm4gaXRlbTtcbiAgICB9KTtcblxuICAgIC8vIGF0dGFja2xhYjogc3RyaXAgc2VudGluZWxcbiAgICBsaXN0U3RyID0gbGlzdFN0ci5yZXBsYWNlKC/CqDAvZywgJycpO1xuXG4gICAgZ2xvYmFscy5nTGlzdExldmVsLS07XG5cbiAgICBpZiAodHJpbVRyYWlsaW5nKSB7XG4gICAgICBsaXN0U3RyID0gbGlzdFN0ci5yZXBsYWNlKC9cXHMrJC8sICcnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbGlzdFN0cjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN0eWxlU3RhcnROdW1iZXIgKGxpc3QsIGxpc3RUeXBlKSB7XG4gICAgLy8gY2hlY2sgaWYgb2wgYW5kIHN0YXJ0cyBieSBhIG51bWJlciBkaWZmZXJlbnQgdGhhbiAxXG4gICAgaWYgKGxpc3RUeXBlID09PSAnb2wnKSB7XG4gICAgICB2YXIgcmVzID0gbGlzdC5tYXRjaCgvXiAqKFxcZCspXFwuLyk7XG4gICAgICBpZiAocmVzICYmIHJlc1sxXSAhPT0gJzEnKSB7XG4gICAgICAgIHJldHVybiAnIHN0YXJ0PVwiJyArIHJlc1sxXSArICdcIic7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBhbmQgcGFyc2UgY29uc2VjdXRpdmUgbGlzdHMgKGJldHRlciBmaXggZm9yIGlzc3VlICMxNDIpXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsaXN0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsaXN0VHlwZVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHRyaW1UcmFpbGluZ1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgZnVuY3Rpb24gcGFyc2VDb25zZWN1dGl2ZUxpc3RzIChsaXN0LCBsaXN0VHlwZSwgdHJpbVRyYWlsaW5nKSB7XG4gICAgLy8gY2hlY2sgaWYgd2UgY2F1Z2h0IDIgb3IgbW9yZSBjb25zZWN1dGl2ZSBsaXN0cyBieSBtaXN0YWtlXG4gICAgLy8gd2UgdXNlIHRoZSBjb3VudGVyUmd4LCBtZWFuaW5nIGlmIGxpc3RUeXBlIGlzIFVMIHdlIGxvb2sgZm9yIE9MIGFuZCB2aWNlIHZlcnNhXG4gICAgdmFyIG9sUmd4ID0gKG9wdGlvbnMuZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzKSA/IC9eID9cXGQrXFwuWyBcXHRdL2dtIDogL14gezAsM31cXGQrXFwuWyBcXHRdL2dtLFxuICAgICAgICB1bFJneCA9IChvcHRpb25zLmRpc2FibGVGb3JjZWQ0U3BhY2VzSW5kZW50ZWRTdWJsaXN0cykgPyAvXiA/WyorLV1bIFxcdF0vZ20gOiAvXiB7MCwzfVsqKy1dWyBcXHRdL2dtLFxuICAgICAgICBjb3VudGVyUnhnID0gKGxpc3RUeXBlID09PSAndWwnKSA/IG9sUmd4IDogdWxSZ3gsXG4gICAgICAgIHJlc3VsdCA9ICcnO1xuXG4gICAgaWYgKGxpc3Quc2VhcmNoKGNvdW50ZXJSeGcpICE9PSAtMSkge1xuICAgICAgKGZ1bmN0aW9uIHBhcnNlQ0wgKHR4dCkge1xuICAgICAgICB2YXIgcG9zID0gdHh0LnNlYXJjaChjb3VudGVyUnhnKSxcbiAgICAgICAgICAgIHN0eWxlID0gc3R5bGVTdGFydE51bWJlcihsaXN0LCBsaXN0VHlwZSk7XG4gICAgICAgIGlmIChwb3MgIT09IC0xKSB7XG4gICAgICAgICAgLy8gc2xpY2VcbiAgICAgICAgICByZXN1bHQgKz0gJ1xcblxcbjwnICsgbGlzdFR5cGUgKyBzdHlsZSArICc+XFxuJyArIHByb2Nlc3NMaXN0SXRlbXModHh0LnNsaWNlKDAsIHBvcyksICEhdHJpbVRyYWlsaW5nKSArICc8LycgKyBsaXN0VHlwZSArICc+XFxuJztcblxuICAgICAgICAgIC8vIGludmVydCBjb3VudGVyVHlwZSBhbmQgbGlzdFR5cGVcbiAgICAgICAgICBsaXN0VHlwZSA9IChsaXN0VHlwZSA9PT0gJ3VsJykgPyAnb2wnIDogJ3VsJztcbiAgICAgICAgICBjb3VudGVyUnhnID0gKGxpc3RUeXBlID09PSAndWwnKSA/IG9sUmd4IDogdWxSZ3g7XG5cbiAgICAgICAgICAvL3JlY3Vyc2VcbiAgICAgICAgICBwYXJzZUNMKHR4dC5zbGljZShwb3MpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHQgKz0gJ1xcblxcbjwnICsgbGlzdFR5cGUgKyBzdHlsZSArICc+XFxuJyArIHByb2Nlc3NMaXN0SXRlbXModHh0LCAhIXRyaW1UcmFpbGluZykgKyAnPC8nICsgbGlzdFR5cGUgKyAnPlxcbic7XG4gICAgICAgIH1cbiAgICAgIH0pKGxpc3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgc3R5bGUgPSBzdHlsZVN0YXJ0TnVtYmVyKGxpc3QsIGxpc3RUeXBlKTtcbiAgICAgIHJlc3VsdCA9ICdcXG5cXG48JyArIGxpc3RUeXBlICsgc3R5bGUgKyAnPlxcbicgKyBwcm9jZXNzTGlzdEl0ZW1zKGxpc3QsICEhdHJpbVRyYWlsaW5nKSArICc8LycgKyBsaXN0VHlwZSArICc+XFxuJztcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqIFN0YXJ0IG9mIGxpc3QgcGFyc2luZyAqKi9cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnbGlzdHMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIC8vIGFkZCBzZW50aW5lbCB0byBoYWNrIGFyb3VuZCBraHRtbC9zYWZhcmkgYnVnOlxuICAvLyBodHRwOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMTIzMVxuICB0ZXh0ICs9ICfCqDAnO1xuXG4gIGlmIChnbG9iYWxzLmdMaXN0TGV2ZWwpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eKCggezAsM30oWyorLV18XFxkK1suXSlbIFxcdF0rKVteXFxyXSs/KMKoMHxcXG57Mix9KD89XFxTKSg/IVsgXFx0XSooPzpbKistXXxcXGQrWy5dKVsgXFx0XSspKSkvZ20sXG4gICAgICBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbGlzdCwgbTIpIHtcbiAgICAgICAgdmFyIGxpc3RUeXBlID0gKG0yLnNlYXJjaCgvWyorLV0vZykgPiAtMSkgPyAndWwnIDogJ29sJztcbiAgICAgICAgcmV0dXJuIHBhcnNlQ29uc2VjdXRpdmVMaXN0cyhsaXN0LCBsaXN0VHlwZSwgdHJ1ZSk7XG4gICAgICB9XG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oXFxuXFxufF5cXG4/KSgoIHswLDN9KFsqKy1dfFxcZCtbLl0pWyBcXHRdKylbXlxccl0rPyjCqDB8XFxuezIsfSg/PVxcUykoPyFbIFxcdF0qKD86WyorLV18XFxkK1suXSlbIFxcdF0rKSkpL2dtLFxuICAgICAgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xLCBsaXN0LCBtMykge1xuICAgICAgICB2YXIgbGlzdFR5cGUgPSAobTMuc2VhcmNoKC9bKistXS9nKSA+IC0xKSA/ICd1bCcgOiAnb2wnO1xuICAgICAgICByZXR1cm4gcGFyc2VDb25zZWN1dGl2ZUxpc3RzKGxpc3QsIGxpc3RUeXBlLCBmYWxzZSk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIC8vIHN0cmlwIHNlbnRpbmVsXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoMC8sICcnKTtcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnbGlzdHMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFBhcnNlIG1ldGFkYXRhIGF0IHRoZSB0b3Agb2YgdGhlIGRvY3VtZW50XG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignbWV0YWRhdGEnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFvcHRpb25zLm1ldGFkYXRhKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdtZXRhZGF0YS5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICBmdW5jdGlvbiBwYXJzZU1ldGFkYXRhQ29udGVudHMgKGNvbnRlbnQpIHtcbiAgICAvLyByYXcgaXMgcmF3IHNvIGl0J3Mgbm90IGNoYW5nZWQgaW4gYW55IHdheVxuICAgIGdsb2JhbHMubWV0YWRhdGEucmF3ID0gY29udGVudDtcblxuICAgIC8vIGVzY2FwZSBjaGFycyBmb3JiaWRkZW4gaW4gaHRtbCBhdHRyaWJ1dGVzXG4gICAgLy8gZG91YmxlIHF1b3Rlc1xuICAgIGNvbnRlbnQgPSBjb250ZW50XG4gICAgICAvLyBhbXBlcnNhbmQgZmlyc3RcbiAgICAgIC5yZXBsYWNlKC8mL2csICcmYW1wOycpXG4gICAgICAvLyBkb3VibGUgcXVvdGVzXG4gICAgICAucmVwbGFjZSgvXCIvZywgJyZxdW90OycpO1xuXG4gICAgY29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvXFxuIHs0fS9nLCAnICcpO1xuICAgIGNvbnRlbnQucmVwbGFjZSgvXihbXFxTIF0rKTogKyhbXFxzXFxTXSs/KSQvZ20sIGZ1bmN0aW9uICh3bSwga2V5LCB2YWx1ZSkge1xuICAgICAgZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWRba2V5XSA9IHZhbHVlO1xuICAgICAgcmV0dXJuICcnO1xuICAgIH0pO1xuICB9XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXlxccyrCq8KrwqsrKFxcUyo/KVxcbihbXFxzXFxTXSs/KVxcbsK7wrvCuytcXG4vLCBmdW5jdGlvbiAod2hvbGVtYXRjaCwgZm9ybWF0LCBjb250ZW50KSB7XG4gICAgcGFyc2VNZXRhZGF0YUNvbnRlbnRzKGNvbnRlbnQpO1xuICAgIHJldHVybiAnwqhNJztcbiAgfSk7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXlxccyotLS0rKFxcUyo/KVxcbihbXFxzXFxTXSs/KVxcbi0tLStcXG4vLCBmdW5jdGlvbiAod2hvbGVtYXRjaCwgZm9ybWF0LCBjb250ZW50KSB7XG4gICAgaWYgKGZvcm1hdCkge1xuICAgICAgZ2xvYmFscy5tZXRhZGF0YS5mb3JtYXQgPSBmb3JtYXQ7XG4gICAgfVxuICAgIHBhcnNlTWV0YWRhdGFDb250ZW50cyhjb250ZW50KTtcbiAgICByZXR1cm4gJ8KoTSc7XG4gIH0pO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoTS9nLCAnJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnbWV0YWRhdGEuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFJlbW92ZSBvbmUgbGV2ZWwgb2YgbGluZS1sZWFkaW5nIHRhYnMgb3Igc3BhY2VzXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignb3V0ZGVudCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnb3V0ZGVudC5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBhdHRhY2tsYWI6IGhhY2sgYXJvdW5kIEtvbnF1ZXJvciAzLjUuNCBidWc6XG4gIC8vIFwiLS0tLS0tLS0tLWJ1Z1wiLnJlcGxhY2UoL14tL2csXCJcIikgPT0gXCJidWdcIlxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eKFxcdHxbIF17MSw0fSkvZ20sICfCqDAnKTsgLy8gYXR0YWNrbGFiOiBnX3RhYl93aWR0aFxuXG4gIC8vIGF0dGFja2xhYjogY2xlYW4gdXAgaGFja1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqDAvZywgJycpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ291dGRlbnQuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcigncGFyYWdyYXBocycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdwYXJhZ3JhcGhzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAvLyBTdHJpcCBsZWFkaW5nIGFuZCB0cmFpbGluZyBsaW5lczpcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXlxcbisvZywgJycpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXG4rJC9nLCAnJyk7XG5cbiAgdmFyIGdyYWZzID0gdGV4dC5zcGxpdCgvXFxuezIsfS9nKSxcbiAgICAgIGdyYWZzT3V0ID0gW10sXG4gICAgICBlbmQgPSBncmFmcy5sZW5ndGg7IC8vIFdyYXAgPHA+IHRhZ3NcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgdmFyIHN0ciA9IGdyYWZzW2ldO1xuICAgIC8vIGlmIHRoaXMgaXMgYW4gSFRNTCBtYXJrZXIsIGNvcHkgaXRcbiAgICBpZiAoc3RyLnNlYXJjaCgvwqgoS3xHKShcXGQrKVxcMS9nKSA+PSAwKSB7XG4gICAgICBncmFmc091dC5wdXNoKHN0cik7XG5cbiAgICAvLyB0ZXN0IGZvciBwcmVzZW5jZSBvZiBjaGFyYWN0ZXJzIHRvIHByZXZlbnQgZW1wdHkgbGluZXMgYmVpbmcgcGFyc2VkXG4gICAgLy8gYXMgcGFyYWdyYXBocyAocmVzdWx0aW5nIGluIHVuZGVzaXJlZCBleHRyYSBlbXB0eSBwYXJhZ3JhcGhzKVxuICAgIH0gZWxzZSBpZiAoc3RyLnNlYXJjaCgvXFxTLykgPj0gMCkge1xuICAgICAgc3RyID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShzdHIsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgc3RyID0gc3RyLnJlcGxhY2UoL14oWyBcXHRdKikvZywgJzxwPicpO1xuICAgICAgc3RyICs9ICc8L3A+JztcbiAgICAgIGdyYWZzT3V0LnB1c2goc3RyKTtcbiAgICB9XG4gIH1cblxuICAvKiogVW5oYXNoaWZ5IEhUTUwgYmxvY2tzICovXG4gIGVuZCA9IGdyYWZzT3V0Lmxlbmd0aDtcbiAgZm9yIChpID0gMDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgdmFyIGJsb2NrVGV4dCA9ICcnLFxuICAgICAgICBncmFmc091dEl0ID0gZ3JhZnNPdXRbaV0sXG4gICAgICAgIGNvZGVGbGFnID0gZmFsc2U7XG4gICAgLy8gaWYgdGhpcyBpcyBhIG1hcmtlciBmb3IgYW4gaHRtbCBibG9jay4uLlxuICAgIC8vIHVzZSBSZWdFeHAudGVzdCBpbnN0ZWFkIG9mIHN0cmluZy5zZWFyY2ggYmVjYXVzZSBvZiBRTUwgYnVnXG4gICAgd2hpbGUgKC/CqChLfEcpKFxcZCspXFwxLy50ZXN0KGdyYWZzT3V0SXQpKSB7XG4gICAgICB2YXIgZGVsaW0gPSBSZWdFeHAuJDEsXG4gICAgICAgICAgbnVtICAgPSBSZWdFeHAuJDI7XG5cbiAgICAgIGlmIChkZWxpbSA9PT0gJ0snKSB7XG4gICAgICAgIGJsb2NrVGV4dCA9IGdsb2JhbHMuZ0h0bWxCbG9ja3NbbnVtXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHdlIG5lZWQgdG8gY2hlY2sgaWYgZ2hCbG9jayBpcyBhIGZhbHNlIHBvc2l0aXZlXG4gICAgICAgIGlmIChjb2RlRmxhZykge1xuICAgICAgICAgIC8vIHVzZSBlbmNvZGVkIHZlcnNpb24gb2YgYWxsIHRleHRcbiAgICAgICAgICBibG9ja1RleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnKShnbG9iYWxzLmdoQ29kZUJsb2Nrc1tudW1dLnRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJsb2NrVGV4dCA9IGdsb2JhbHMuZ2hDb2RlQmxvY2tzW251bV0uY29kZWJsb2NrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBibG9ja1RleHQgPSBibG9ja1RleHQucmVwbGFjZSgvXFwkL2csICckJCQkJyk7IC8vIEVzY2FwZSBhbnkgZG9sbGFyIHNpZ25zXG5cbiAgICAgIGdyYWZzT3V0SXQgPSBncmFmc091dEl0LnJlcGxhY2UoLyhcXG5cXG4pP8KoKEt8RylcXGQrXFwyKFxcblxcbik/LywgYmxvY2tUZXh0KTtcbiAgICAgIC8vIENoZWNrIGlmIGdyYWZzT3V0SXQgaXMgYSBwcmUtPmNvZGVcbiAgICAgIGlmICgvXjxwcmVcXGJbXj5dKj5cXHMqPGNvZGVcXGJbXj5dKj4vLnRlc3QoZ3JhZnNPdXRJdCkpIHtcbiAgICAgICAgY29kZUZsYWcgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBncmFmc091dFtpXSA9IGdyYWZzT3V0SXQ7XG4gIH1cbiAgdGV4dCA9IGdyYWZzT3V0LmpvaW4oJ1xcbicpO1xuICAvLyBTdHJpcCBsZWFkaW5nIGFuZCB0cmFpbGluZyBsaW5lczpcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXlxcbisvZywgJycpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXG4rJC9nLCAnJyk7XG4gIHJldHVybiBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3BhcmFncmFwaHMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbn0pO1xuXHJcbi8qKlxuICogUnVuIGV4dGVuc2lvblxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3J1bkV4dGVuc2lvbicsIGZ1bmN0aW9uIChleHQsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmIChleHQuZmlsdGVyKSB7XG4gICAgdGV4dCA9IGV4dC5maWx0ZXIodGV4dCwgZ2xvYmFscy5jb252ZXJ0ZXIsIG9wdGlvbnMpO1xuXG4gIH0gZWxzZSBpZiAoZXh0LnJlZ2V4KSB7XG4gICAgLy8gVE9ETyByZW1vdmUgdGhpcyB3aGVuIG9sZCBleHRlbnNpb24gbG9hZGluZyBtZWNoYW5pc20gaXMgZGVwcmVjYXRlZFxuICAgIHZhciByZSA9IGV4dC5yZWdleDtcbiAgICBpZiAoIShyZSBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgIHJlID0gbmV3IFJlZ0V4cChyZSwgJ2cnKTtcbiAgICB9XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZShyZSwgZXh0LnJlcGxhY2UpO1xuICB9XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFRoZXNlIGFyZSBhbGwgdGhlIHRyYW5zZm9ybWF0aW9ucyB0aGF0IG9jY3VyICp3aXRoaW4qIGJsb2NrLWxldmVsXG4gKiB0YWdzIGxpa2UgcGFyYWdyYXBocywgaGVhZGVycywgYW5kIGxpc3QgaXRlbXMuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0JywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3NwYW5HYW11dC5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignY29kZVNwYW5zJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VzY2FwZVNwZWNpYWxDaGFyc1dpdGhpblRhZ0F0dHJpYnV0ZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQmFja3NsYXNoRXNjYXBlcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIFByb2Nlc3MgYW5jaG9yIGFuZCBpbWFnZSB0YWdzLiBJbWFnZXMgbXVzdCBjb21lIGZpcnN0LFxuICAvLyBiZWNhdXNlICFbZm9vXVtmXSBsb29rcyBsaWtlIGFuIGFuY2hvci5cbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaW1hZ2VzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2FuY2hvcnMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBNYWtlIGxpbmtzIG91dCBvZiB0aGluZ3MgbGlrZSBgPGh0dHA6Ly9leGFtcGxlLmNvbS8+YFxuICAvLyBNdXN0IGNvbWUgYWZ0ZXIgYW5jaG9ycywgYmVjYXVzZSB5b3UgY2FuIHVzZSA8IGFuZCA+XG4gIC8vIGRlbGltaXRlcnMgaW4gaW5saW5lIGxpbmtzIGxpa2UgW3RoaXNdKDx1cmw+KS5cbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignYXV0b0xpbmtzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NpbXBsaWZpZWRBdXRvTGlua3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZW1vamknKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcigndW5kZXJsaW5lJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2l0YWxpY3NBbmRCb2xkJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3N0cmlrZXRocm91Z2gnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZWxsaXBzaXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyB3ZSBuZWVkIHRvIGhhc2ggSFRNTCB0YWdzIGluc2lkZSBzcGFuc1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoSFRNTFNwYW5zJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gbm93IHdlIGVuY29kZSBhbXBzIGFuZCBhbmdsZXNcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQW1wc0FuZEFuZ2xlcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIERvIGhhcmQgYnJlYWtzXG4gIGlmIChvcHRpb25zLnNpbXBsZUxpbmVCcmVha3MpIHtcbiAgICAvLyBHRk0gc3R5bGUgaGFyZCBicmVha3NcbiAgICAvLyBvbmx5IGFkZCBsaW5lIGJyZWFrcyBpZiB0aGUgdGV4dCBkb2VzIG5vdCBjb250YWluIGEgYmxvY2sgKHNwZWNpYWwgY2FzZSBmb3IgbGlzdHMpXG4gICAgaWYgKCEvXFxuXFxuwqhLLy50ZXN0KHRleHQpKSB7XG4gICAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXG4rL2csICc8YnIgLz5cXG4nKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gVmFuaWxsYSBoYXJkIGJyZWFrc1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyAgK1xcbi9nLCAnPGJyIC8+XFxuJyk7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdzcGFuR2FtdXQuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3N0cmlrZXRocm91Z2gnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgZnVuY3Rpb24gcGFyc2VJbnNpZGUgKHR4dCkge1xuICAgIGlmIChvcHRpb25zLnNpbXBsaWZpZWRBdXRvTGluaykge1xuICAgICAgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzaW1wbGlmaWVkQXV0b0xpbmtzJykodHh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB9XG4gICAgcmV0dXJuICc8ZGVsPicgKyB0eHQgKyAnPC9kZWw+JztcbiAgfVxuXG4gIGlmIChvcHRpb25zLnN0cmlrZXRocm91Z2gpIHtcbiAgICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdzdHJpa2V0aHJvdWdoLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyg/On4pezJ9KFtcXHNcXFNdKz8pKD86fil7Mn0vZywgZnVuY3Rpb24gKHdtLCB0eHQpIHsgcmV0dXJuIHBhcnNlSW5zaWRlKHR4dCk7IH0pO1xuICAgIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3N0cmlrZXRocm91Z2guYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgfVxuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBTdHJpcHMgbGluayBkZWZpbml0aW9ucyBmcm9tIHRleHQsIHN0b3JlcyB0aGUgVVJMcyBhbmQgdGl0bGVzIGluXG4gKiBoYXNoIHJlZmVyZW5jZXMuXG4gKiBMaW5rIGRlZnMgYXJlIGluIHRoZSBmb3JtOiBeW2lkXTogdXJsIFwib3B0aW9uYWwgdGl0bGVcIlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3N0cmlwTGlua0RlZmluaXRpb25zJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciByZWdleCAgICAgICA9IC9eIHswLDN9XFxbKC4rKV06WyBcXHRdKlxcbj9bIFxcdF0qPD8oW14+XFxzXSspPj8oPzogPShbKlxcZF0rW0EtWmEteiVdezAsNH0peChbKlxcZF0rW0EtWmEteiVdezAsNH0pKT9bIFxcdF0qXFxuP1sgXFx0XSooPzooXFxuKilbXCJ8JyhdKC4rPylbXCJ8JyldWyBcXHRdKik/KD86XFxuK3woPz3CqDApKS9nbSxcbiAgICAgIGJhc2U2NFJlZ2V4ID0gL14gezAsM31cXFsoLispXTpbIFxcdF0qXFxuP1sgXFx0XSo8PyhkYXRhOi4rP1xcLy4rPztiYXNlNjQsW0EtWmEtejAtOSsvPVxcbl0rPyk+Pyg/OiA9KFsqXFxkXStbQS1aYS16JV17MCw0fSl4KFsqXFxkXStbQS1aYS16JV17MCw0fSkpP1sgXFx0XSpcXG4/WyBcXHRdKig/OihcXG4qKVtcInwnKF0oLis/KVtcInwnKV1bIFxcdF0qKT8oPzpcXG5cXG58KD89wqgwKXwoPz1cXG5cXFspKS9nbTtcblxuICAvLyBhdHRhY2tsYWI6IHNlbnRpbmVsIHdvcmthcm91bmRzIGZvciBsYWNrIG9mIFxcQSBhbmQgXFxaLCBzYWZhcmlcXGtodG1sIGJ1Z1xuICB0ZXh0ICs9ICfCqDAnO1xuXG4gIHZhciByZXBsYWNlRnVuYyA9IGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBsaW5rSWQsIHVybCwgd2lkdGgsIGhlaWdodCwgYmxhbmtMaW5lcywgdGl0bGUpIHtcbiAgICBsaW5rSWQgPSBsaW5rSWQudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAodXJsLm1hdGNoKC9eZGF0YTouKz9cXC8uKz87YmFzZTY0LC8pKSB7XG4gICAgICAvLyByZW1vdmUgbmV3bGluZXNcbiAgICAgIGdsb2JhbHMuZ1VybHNbbGlua0lkXSA9IHVybC5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgIH0gZWxzZSB7XG4gICAgICBnbG9iYWxzLmdVcmxzW2xpbmtJZF0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUFtcHNBbmRBbmdsZXMnKSh1cmwsIG9wdGlvbnMsIGdsb2JhbHMpOyAgLy8gTGluayBJRHMgYXJlIGNhc2UtaW5zZW5zaXRpdmVcbiAgICB9XG5cbiAgICBpZiAoYmxhbmtMaW5lcykge1xuICAgICAgLy8gT29wcywgZm91bmQgYmxhbmsgbGluZXMsIHNvIGl0J3Mgbm90IGEgdGl0bGUuXG4gICAgICAvLyBQdXQgYmFjayB0aGUgcGFyZW50aGV0aWNhbCBzdGF0ZW1lbnQgd2Ugc3RvbGUuXG4gICAgICByZXR1cm4gYmxhbmtMaW5lcyArIHRpdGxlO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0aXRsZSkge1xuICAgICAgICBnbG9iYWxzLmdUaXRsZXNbbGlua0lkXSA9IHRpdGxlLnJlcGxhY2UoL1wifCcvZywgJyZxdW90OycpO1xuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMucGFyc2VJbWdEaW1lbnNpb25zICYmIHdpZHRoICYmIGhlaWdodCkge1xuICAgICAgICBnbG9iYWxzLmdEaW1lbnNpb25zW2xpbmtJZF0gPSB7XG4gICAgICAgICAgd2lkdGg6ICB3aWR0aCxcbiAgICAgICAgICBoZWlnaHQ6IGhlaWdodFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBDb21wbGV0ZWx5IHJlbW92ZSB0aGUgZGVmaW5pdGlvbiBmcm9tIHRoZSB0ZXh0XG4gICAgcmV0dXJuICcnO1xuICB9O1xuXG4gIC8vIGZpcnN0IHdlIHRyeSB0byBmaW5kIGJhc2U2NCBsaW5rIHJlZmVyZW5jZXNcbiAgdGV4dCA9IHRleHQucmVwbGFjZShiYXNlNjRSZWdleCwgcmVwbGFjZUZ1bmMpO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UocmVnZXgsIHJlcGxhY2VGdW5jKTtcblxuICAvLyBhdHRhY2tsYWI6IHN0cmlwIHNlbnRpbmVsXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoMC8sICcnKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcigndGFibGVzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghb3B0aW9ucy50YWJsZXMpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHZhciB0YWJsZVJneCAgICAgICA9IC9eIHswLDN9XFx8Py4rXFx8LitcXG4gezAsM31cXHw/WyBcXHRdKjo/WyBcXHRdKig/OlstPV0pezIsfVsgXFx0XSo6P1sgXFx0XSpcXHxbIFxcdF0qOj9bIFxcdF0qKD86Wy09XSl7Mix9W1xcc1xcU10rPyg/OlxcblxcbnzCqDApL2dtLFxuICAgICAgLy9zaW5nZUNvbFRibFJneCA9IC9eIHswLDN9XFx8LitcXHxcXG4gezAsM31cXHxbIFxcdF0qOj9bIFxcdF0qKD86Wy09XSl7Mix9WyBcXHRdKjo/WyBcXHRdKlxcfFsgXFx0XSpcXG4oPzogezAsM31cXHwuK1xcfFxcbikrKD86XFxuXFxufMKoMCkvZ207XG4gICAgICBzaW5nZUNvbFRibFJneCA9IC9eIHswLDN9XFx8LitcXHxbIFxcdF0qXFxuIHswLDN9XFx8WyBcXHRdKjo/WyBcXHRdKig/OlstPV0pezIsfVsgXFx0XSo6P1sgXFx0XSpcXHxbIFxcdF0qXFxuKCB7MCwzfVxcfC4rXFx8WyBcXHRdKlxcbikqKD86XFxufMKoMCkvZ207XG5cbiAgZnVuY3Rpb24gcGFyc2VTdHlsZXMgKHNMaW5lKSB7XG4gICAgaWYgKC9eOlsgXFx0XSotLSokLy50ZXN0KHNMaW5lKSkge1xuICAgICAgcmV0dXJuICcgc3R5bGU9XCJ0ZXh0LWFsaWduOmxlZnQ7XCInO1xuICAgIH0gZWxzZSBpZiAoL14tLSpbIFxcdF0qOlsgXFx0XSokLy50ZXN0KHNMaW5lKSkge1xuICAgICAgcmV0dXJuICcgc3R5bGU9XCJ0ZXh0LWFsaWduOnJpZ2h0O1wiJztcbiAgICB9IGVsc2UgaWYgKC9eOlsgXFx0XSotLSpbIFxcdF0qOiQvLnRlc3Qoc0xpbmUpKSB7XG4gICAgICByZXR1cm4gJyBzdHlsZT1cInRleHQtYWxpZ246Y2VudGVyO1wiJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlSGVhZGVycyAoaGVhZGVyLCBzdHlsZSkge1xuICAgIHZhciBpZCA9ICcnO1xuICAgIGhlYWRlciA9IGhlYWRlci50cmltKCk7XG4gICAgLy8gc3VwcG9ydCBib3RoIHRhYmxlc0hlYWRlcklkIGFuZCB0YWJsZUhlYWRlcklkIGR1ZSB0byBlcnJvciBpbiBkb2N1bWVudGF0aW9uIHNvIHdlIGRvbid0IGJyZWFrIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG4gICAgaWYgKG9wdGlvbnMudGFibGVzSGVhZGVySWQgfHwgb3B0aW9ucy50YWJsZUhlYWRlcklkKSB7XG4gICAgICBpZCA9ICcgaWQ9XCInICsgaGVhZGVyLnJlcGxhY2UoLyAvZywgJ18nKS50b0xvd2VyQ2FzZSgpICsgJ1wiJztcbiAgICB9XG4gICAgaGVhZGVyID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShoZWFkZXIsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gICAgcmV0dXJuICc8dGgnICsgaWQgKyBzdHlsZSArICc+JyArIGhlYWRlciArICc8L3RoPlxcbic7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUNlbGxzIChjZWxsLCBzdHlsZSkge1xuICAgIHZhciBzdWJUZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShjZWxsLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICByZXR1cm4gJzx0ZCcgKyBzdHlsZSArICc+JyArIHN1YlRleHQgKyAnPC90ZD5cXG4nO1xuICB9XG5cbiAgZnVuY3Rpb24gYnVpbGRUYWJsZSAoaGVhZGVycywgY2VsbHMpIHtcbiAgICB2YXIgdGIgPSAnPHRhYmxlPlxcbjx0aGVhZD5cXG48dHI+XFxuJyxcbiAgICAgICAgdGJsTGduID0gaGVhZGVycy5sZW5ndGg7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRibExnbjsgKytpKSB7XG4gICAgICB0YiArPSBoZWFkZXJzW2ldO1xuICAgIH1cbiAgICB0YiArPSAnPC90cj5cXG48L3RoZWFkPlxcbjx0Ym9keT5cXG4nO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgICB0YiArPSAnPHRyPlxcbic7XG4gICAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgdGJsTGduOyArK2lpKSB7XG4gICAgICAgIHRiICs9IGNlbGxzW2ldW2lpXTtcbiAgICAgIH1cbiAgICAgIHRiICs9ICc8L3RyPlxcbic7XG4gICAgfVxuICAgIHRiICs9ICc8L3Rib2R5PlxcbjwvdGFibGU+XFxuJztcbiAgICByZXR1cm4gdGI7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZVRhYmxlIChyYXdUYWJsZSkge1xuICAgIHZhciBpLCB0YWJsZUxpbmVzID0gcmF3VGFibGUuc3BsaXQoJ1xcbicpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IHRhYmxlTGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIC8vIHN0cmlwIHdyb25nIGZpcnN0IGFuZCBsYXN0IGNvbHVtbiBpZiB3cmFwcGVkIHRhYmxlcyBhcmUgdXNlZFxuICAgICAgaWYgKC9eIHswLDN9XFx8Ly50ZXN0KHRhYmxlTGluZXNbaV0pKSB7XG4gICAgICAgIHRhYmxlTGluZXNbaV0gPSB0YWJsZUxpbmVzW2ldLnJlcGxhY2UoL14gezAsM31cXHwvLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoL1xcfFsgXFx0XSokLy50ZXN0KHRhYmxlTGluZXNbaV0pKSB7XG4gICAgICAgIHRhYmxlTGluZXNbaV0gPSB0YWJsZUxpbmVzW2ldLnJlcGxhY2UoL1xcfFsgXFx0XSokLywgJycpO1xuICAgICAgfVxuICAgICAgLy8gcGFyc2UgY29kZSBzcGFucyBmaXJzdCwgYnV0IHdlIG9ubHkgc3VwcG9ydCBvbmUgbGluZSBjb2RlIHNwYW5zXG4gICAgICB0YWJsZUxpbmVzW2ldID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdjb2RlU3BhbnMnKSh0YWJsZUxpbmVzW2ldLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB9XG5cbiAgICB2YXIgcmF3SGVhZGVycyA9IHRhYmxlTGluZXNbMF0uc3BsaXQoJ3wnKS5tYXAoZnVuY3Rpb24gKHMpIHsgcmV0dXJuIHMudHJpbSgpO30pLFxuICAgICAgICByYXdTdHlsZXMgPSB0YWJsZUxpbmVzWzFdLnNwbGl0KCd8JykubWFwKGZ1bmN0aW9uIChzKSB7IHJldHVybiBzLnRyaW0oKTt9KSxcbiAgICAgICAgcmF3Q2VsbHMgPSBbXSxcbiAgICAgICAgaGVhZGVycyA9IFtdLFxuICAgICAgICBzdHlsZXMgPSBbXSxcbiAgICAgICAgY2VsbHMgPSBbXTtcblxuICAgIHRhYmxlTGluZXMuc2hpZnQoKTtcbiAgICB0YWJsZUxpbmVzLnNoaWZ0KCk7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgdGFibGVMaW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKHRhYmxlTGluZXNbaV0udHJpbSgpID09PSAnJykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHJhd0NlbGxzLnB1c2goXG4gICAgICAgIHRhYmxlTGluZXNbaV1cbiAgICAgICAgICAuc3BsaXQoJ3wnKVxuICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgIHJldHVybiBzLnRyaW0oKTtcbiAgICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAocmF3SGVhZGVycy5sZW5ndGggPCByYXdTdHlsZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gcmF3VGFibGU7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMDsgaSA8IHJhd1N0eWxlcy5sZW5ndGg7ICsraSkge1xuICAgICAgc3R5bGVzLnB1c2gocGFyc2VTdHlsZXMocmF3U3R5bGVzW2ldKSk7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMDsgaSA8IHJhd0hlYWRlcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoc3R5bGVzW2ldKSkge1xuICAgICAgICBzdHlsZXNbaV0gPSAnJztcbiAgICAgIH1cbiAgICAgIGhlYWRlcnMucHVzaChwYXJzZUhlYWRlcnMocmF3SGVhZGVyc1tpXSwgc3R5bGVzW2ldKSk7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMDsgaSA8IHJhd0NlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgcm93ID0gW107XG4gICAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgaGVhZGVycy5sZW5ndGg7ICsraWkpIHtcbiAgICAgICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChyYXdDZWxsc1tpXVtpaV0pKSB7XG5cbiAgICAgICAgfVxuICAgICAgICByb3cucHVzaChwYXJzZUNlbGxzKHJhd0NlbGxzW2ldW2lpXSwgc3R5bGVzW2lpXSkpO1xuICAgICAgfVxuICAgICAgY2VsbHMucHVzaChyb3cpO1xuICAgIH1cblxuICAgIHJldHVybiBidWlsZFRhYmxlKGhlYWRlcnMsIGNlbGxzKTtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3RhYmxlcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBmaW5kIGVzY2FwZWQgcGlwZSBjaGFyYWN0ZXJzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcXFwoXFx8KS9nLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICAvLyBwYXJzZSBtdWx0aSBjb2x1bW4gdGFibGVzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UodGFibGVSZ3gsIHBhcnNlVGFibGUpO1xuXG4gIC8vIHBhcnNlIG9uZSBjb2x1bW4gdGFibGVzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2luZ2VDb2xUYmxSZ3gsIHBhcnNlVGFibGUpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3RhYmxlcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmRlcmxpbmUnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFvcHRpb25zLnVuZGVybGluZSkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgndW5kZXJsaW5lLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIGlmIChvcHRpb25zLmxpdGVyYWxNaWRXb3JkVW5kZXJzY29yZXMpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXGJfX18oXFxTW1xcc1xcU10qPylfX19cXGIvZywgZnVuY3Rpb24gKHdtLCB0eHQpIHtcbiAgICAgIHJldHVybiAnPHU+JyArIHR4dCArICc8L3U+JztcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXGJfXyhcXFNbXFxzXFxTXSo/KV9fXFxiL2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7XG4gICAgICByZXR1cm4gJzx1PicgKyB0eHQgKyAnPC91Pic7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvX19fKFxcU1tcXHNcXFNdKj8pX19fL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyAnPHU+JyArIG0gKyAnPC91PicgOiB3bTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9fXyhcXFNbXFxzXFxTXSo/KV9fL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyAnPHU+JyArIG0gKyAnPC91PicgOiB3bTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGVzY2FwZSByZW1haW5pbmcgdW5kZXJzY29yZXMgdG8gcHJldmVudCB0aGVtIGJlaW5nIHBhcnNlZCBieSBpdGFsaWMgYW5kIGJvbGRcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKF8pL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3VuZGVybGluZS5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBTd2FwIGJhY2sgaW4gYWxsIHRoZSBzcGVjaWFsIGNoYXJhY3RlcnMgd2UndmUgaGlkZGVuLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3VuZXNjYXBlU3BlY2lhbENoYXJzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmVzY2FwZVNwZWNpYWxDaGFycy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqEUoXFxkKylFL2csIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSkge1xuICAgIHZhciBjaGFyQ29kZVRvUmVwbGFjZSA9IHBhcnNlSW50KG0xKTtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZVRvUmVwbGFjZSk7XG4gIH0pO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3VuZXNjYXBlU3BlY2lhbENoYXJzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uYmxvY2txdW90ZScsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBpbm5lclR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG5cbiAgICAgIGlmIChpbm5lclR4dCA9PT0gJycpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICB0eHQgKz0gaW5uZXJUeHQ7XG4gICAgfVxuICB9XG4gIC8vIGNsZWFudXBcbiAgdHh0ID0gdHh0LnRyaW0oKTtcbiAgdHh0ID0gJz4gJyArIHR4dC5zcGxpdCgnXFxuJykuam9pbignXFxuPiAnKTtcbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmNvZGVCbG9jaycsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgbGFuZyA9IG5vZGUuZ2V0QXR0cmlidXRlKCdsYW5ndWFnZScpLFxuICAgICAgbnVtICA9IG5vZGUuZ2V0QXR0cmlidXRlKCdwcmVjb2RlbnVtJyk7XG4gIHJldHVybiAnYGBgJyArIGxhbmcgKyAnXFxuJyArIGdsb2JhbHMucHJlTGlzdFtudW1dICsgJ1xcbmBgYCc7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5jb2RlU3BhbicsIGZ1bmN0aW9uIChub2RlKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICByZXR1cm4gJ2AnICsgbm9kZS5pbm5lckhUTUwgKyAnYCc7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5lbXBoYXNpcycsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHR4dCArPSAnKic7XG4gICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZE5vZGVzLFxuICAgICAgICBjaGlsZHJlbkxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ3RoOyArK2kpIHtcbiAgICAgIHR4dCArPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMpO1xuICAgIH1cbiAgICB0eHQgKz0gJyonO1xuICB9XG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5oZWFkZXInLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscywgaGVhZGVyTGV2ZWwpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciBoZWFkZXJNYXJrID0gbmV3IEFycmF5KGhlYWRlckxldmVsICsgMSkuam9pbignIycpLFxuICAgICAgdHh0ID0gJyc7XG5cbiAgaWYgKG5vZGUuaGFzQ2hpbGROb2RlcygpKSB7XG4gICAgdHh0ID0gaGVhZGVyTWFyayArICcgJztcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICAgIGNoaWxkcmVuTGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmhyJywgZnVuY3Rpb24gKCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgcmV0dXJuICctLS0nO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaW1hZ2UnLCBmdW5jdGlvbiAobm9kZSkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAobm9kZS5oYXNBdHRyaWJ1dGUoJ3NyYycpKSB7XG4gICAgdHh0ICs9ICchWycgKyBub2RlLmdldEF0dHJpYnV0ZSgnYWx0JykgKyAnXSgnO1xuICAgIHR4dCArPSAnPCcgKyBub2RlLmdldEF0dHJpYnV0ZSgnc3JjJykgKyAnPic7XG4gICAgaWYgKG5vZGUuaGFzQXR0cmlidXRlKCd3aWR0aCcpICYmIG5vZGUuaGFzQXR0cmlidXRlKCdoZWlnaHQnKSkge1xuICAgICAgdHh0ICs9ICcgPScgKyBub2RlLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSArICd4JyArIG5vZGUuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKTtcbiAgICB9XG5cbiAgICBpZiAobm9kZS5oYXNBdHRyaWJ1dGUoJ3RpdGxlJykpIHtcbiAgICAgIHR4dCArPSAnIFwiJyArIG5vZGUuZ2V0QXR0cmlidXRlKCd0aXRsZScpICsgJ1wiJztcbiAgICB9XG4gICAgdHh0ICs9ICcpJztcbiAgfVxuICByZXR1cm4gdHh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlua3MnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAobm9kZS5oYXNDaGlsZE5vZGVzKCkgJiYgbm9kZS5oYXNBdHRyaWJ1dGUoJ2hyZWYnKSkge1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgdHh0ID0gJ1snO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5ndGg7ICsraSkge1xuICAgICAgdHh0ICs9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG4gICAgfVxuICAgIHR4dCArPSAnXSgnO1xuICAgIHR4dCArPSAnPCcgKyBub2RlLmdldEF0dHJpYnV0ZSgnaHJlZicpICsgJz4nO1xuICAgIGlmIChub2RlLmhhc0F0dHJpYnV0ZSgndGl0bGUnKSkge1xuICAgICAgdHh0ICs9ICcgXCInICsgbm9kZS5nZXRBdHRyaWJ1dGUoJ3RpdGxlJykgKyAnXCInO1xuICAgIH1cbiAgICB0eHQgKz0gJyknO1xuICB9XG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5saXN0JywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMsIHR5cGUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJztcbiAgaWYgKCFub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuICB2YXIgbGlzdEl0ZW1zICAgICAgID0gbm9kZS5jaGlsZE5vZGVzLFxuICAgICAgbGlzdEl0ZW1zTGVuZ2h0ID0gbGlzdEl0ZW1zLmxlbmd0aCxcbiAgICAgIGxpc3ROdW0gPSBub2RlLmdldEF0dHJpYnV0ZSgnc3RhcnQnKSB8fCAxO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGlzdEl0ZW1zTGVuZ2h0OyArK2kpIHtcbiAgICBpZiAodHlwZW9mIGxpc3RJdGVtc1tpXS50YWdOYW1lID09PSAndW5kZWZpbmVkJyB8fCBsaXN0SXRlbXNbaV0udGFnTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnbGknKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBkZWZpbmUgdGhlIGJ1bGxldCB0byB1c2UgaW4gbGlzdFxuICAgIHZhciBidWxsZXQgPSAnJztcbiAgICBpZiAodHlwZSA9PT0gJ29sJykge1xuICAgICAgYnVsbGV0ID0gbGlzdE51bS50b1N0cmluZygpICsgJy4gJztcbiAgICB9IGVsc2Uge1xuICAgICAgYnVsbGV0ID0gJy0gJztcbiAgICB9XG5cbiAgICAvLyBwYXJzZSBsaXN0IGl0ZW1cbiAgICB0eHQgKz0gYnVsbGV0ICsgc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlzdEl0ZW0nKShsaXN0SXRlbXNbaV0sIGdsb2JhbHMpO1xuICAgICsrbGlzdE51bTtcbiAgfVxuXG4gIC8vIGFkZCBjb21tZW50IGF0IHRoZSBlbmQgdG8gcHJldmVudCBjb25zZWN1dGl2ZSBsaXN0cyB0byBiZSBwYXJzZWQgYXMgb25lXG4gIHR4dCArPSAnXFxuPCEtLSAtLT5cXG4nO1xuICByZXR1cm4gdHh0LnRyaW0oKTtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmxpc3RJdGVtJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciBsaXN0SXRlbVR4dCA9ICcnO1xuXG4gIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgIGNoaWxkcmVuTGVuZ2h0ID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5naHQ7ICsraSkge1xuICAgIGxpc3RJdGVtVHh0ICs9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG4gIH1cbiAgLy8gaWYgaXQncyBvbmx5IG9uZSBsaW5lciwgd2UgbmVlZCB0byBhZGQgYSBuZXdsaW5lIGF0IHRoZSBlbmRcbiAgaWYgKCEvXFxuJC8udGVzdChsaXN0SXRlbVR4dCkpIHtcbiAgICBsaXN0SXRlbVR4dCArPSAnXFxuJztcbiAgfSBlbHNlIHtcbiAgICAvLyBpdCdzIG11bHRpcGFyYWdyYXBoLCBzbyB3ZSBuZWVkIHRvIGluZGVudFxuICAgIGxpc3RJdGVtVHh0ID0gbGlzdEl0ZW1UeHRcbiAgICAgIC5zcGxpdCgnXFxuJylcbiAgICAgIC5qb2luKCdcXG4gICAgJylcbiAgICAgIC5yZXBsYWNlKC9eIHs0fSQvZ20sICcnKVxuICAgICAgLnJlcGxhY2UoL1xcblxcbisvZywgJ1xcblxcbicpO1xuICB9XG5cbiAgcmV0dXJuIGxpc3RJdGVtVHh0O1xufSk7XG5cclxuXG5cbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscywgc3BhbnNPbmx5KSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBzcGFuc09ubHkgPSBzcGFuc09ubHkgfHwgZmFsc2U7XG5cbiAgdmFyIHR4dCA9ICcnO1xuXG4gIC8vIGVkZ2UgY2FzZSBvZiB0ZXh0IHdpdGhvdXQgd3JhcHBlciBwYXJhZ3JhcGhcbiAgaWYgKG5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICByZXR1cm4gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24udHh0Jykobm9kZSwgZ2xvYmFscyk7XG4gIH1cblxuICAvLyBIVE1MIGNvbW1lbnRcbiAgaWYgKG5vZGUubm9kZVR5cGUgPT09IDgpIHtcbiAgICByZXR1cm4gJzwhLS0nICsgbm9kZS5kYXRhICsgJy0tPlxcblxcbic7XG4gIH1cblxuICAvLyBwcm9jZXNzIG9ubHkgbm9kZSBlbGVtZW50c1xuICBpZiAobm9kZS5ub2RlVHlwZSAhPT0gMSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIHZhciB0YWdOYW1lID0gbm9kZS50YWdOYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgc3dpdGNoICh0YWdOYW1lKSB7XG5cbiAgICAvL1xuICAgIC8vIEJMT0NLU1xuICAgIC8vXG4gICAgY2FzZSAnaDEnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgMSkgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDInOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgMikgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDMnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgMykgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDQnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgNCkgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDUnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgNSkgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDYnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgNikgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdwJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnBhcmFncmFwaCcpKG5vZGUsIGdsb2JhbHMpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnYmxvY2txdW90ZSc6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ibG9ja3F1b3RlJykobm9kZSwgZ2xvYmFscykgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdocic6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ocicpKG5vZGUsIGdsb2JhbHMpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnb2wnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlzdCcpKG5vZGUsIGdsb2JhbHMsICdvbCcpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAndWwnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlzdCcpKG5vZGUsIGdsb2JhbHMsICd1bCcpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAncHJlY29kZSc6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5jb2RlQmxvY2snKShub2RlLCBnbG9iYWxzKSArICdcXG5cXG4nOyB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3ByZSc6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5wcmUnKShub2RlLCBnbG9iYWxzKSArICdcXG5cXG4nOyB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3RhYmxlJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnRhYmxlJykobm9kZSwgZ2xvYmFscykgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG5cbiAgICAvL1xuICAgIC8vIFNQQU5TXG4gICAgLy9cbiAgICBjYXNlICdjb2RlJzpcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmNvZGVTcGFuJykobm9kZSwgZ2xvYmFscyk7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2VtJzpcbiAgICBjYXNlICdpJzpcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmVtcGhhc2lzJykobm9kZSwgZ2xvYmFscyk7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3N0cm9uZyc6XG4gICAgY2FzZSAnYic6XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5zdHJvbmcnKShub2RlLCBnbG9iYWxzKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnZGVsJzpcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnN0cmlrZXRocm91Z2gnKShub2RlLCBnbG9iYWxzKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnYSc6XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5saW5rcycpKG5vZGUsIGdsb2JhbHMpO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdpbWcnOlxuICAgICAgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaW1hZ2UnKShub2RlLCBnbG9iYWxzKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHR4dCA9IG5vZGUub3V0ZXJIVE1MICsgJ1xcblxcbic7XG4gIH1cblxuICAvLyBjb21tb24gbm9ybWFsaXphdGlvblxuICAvLyBUT0RPIGV2ZW50dWFsbHlcblxuICByZXR1cm4gdHh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ucGFyYWdyYXBoJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJztcbiAgaWYgKG5vZGUuaGFzQ2hpbGROb2RlcygpKSB7XG4gICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZE5vZGVzLFxuICAgICAgICBjaGlsZHJlbkxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ3RoOyArK2kpIHtcbiAgICAgIHR4dCArPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHNvbWUgdGV4dCBub3JtYWxpemF0aW9uXG4gIHR4dCA9IHR4dC50cmltKCk7XG5cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnByZScsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgbnVtICA9IG5vZGUuZ2V0QXR0cmlidXRlKCdwcmVudW0nKTtcbiAgcmV0dXJuICc8cHJlPicgKyBnbG9iYWxzLnByZUxpc3RbbnVtXSArICc8L3ByZT4nO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uc3RyaWtldGhyb3VnaCcsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHR4dCArPSAnfn4nO1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzKTtcbiAgICB9XG4gICAgdHh0ICs9ICd+fic7XG4gIH1cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnN0cm9uZycsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHR4dCArPSAnKionO1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzKTtcbiAgICB9XG4gICAgdHh0ICs9ICcqKic7XG4gIH1cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnRhYmxlJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJyxcbiAgICAgIHRhYmxlQXJyYXkgPSBbW10sIFtdXSxcbiAgICAgIGhlYWRpbmdzICAgPSBub2RlLnF1ZXJ5U2VsZWN0b3JBbGwoJ3RoZWFkPnRyPnRoJyksXG4gICAgICByb3dzICAgICAgID0gbm9kZS5xdWVyeVNlbGVjdG9yQWxsKCd0Ym9keT50cicpLFxuICAgICAgaSwgaWk7XG4gIGZvciAoaSA9IDA7IGkgPCBoZWFkaW5ncy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBoZWFkQ29udGVudCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnRhYmxlQ2VsbCcpKGhlYWRpbmdzW2ldLCBnbG9iYWxzKSxcbiAgICAgICAgYWxsaWduID0gJy0tLSc7XG5cbiAgICBpZiAoaGVhZGluZ3NbaV0uaGFzQXR0cmlidXRlKCdzdHlsZScpKSB7XG4gICAgICB2YXIgc3R5bGUgPSBoZWFkaW5nc1tpXS5nZXRBdHRyaWJ1dGUoJ3N0eWxlJykudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgICAgc3dpdGNoIChzdHlsZSkge1xuICAgICAgICBjYXNlICd0ZXh0LWFsaWduOmxlZnQ7JzpcbiAgICAgICAgICBhbGxpZ24gPSAnOi0tLSc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3RleHQtYWxpZ246cmlnaHQ7JzpcbiAgICAgICAgICBhbGxpZ24gPSAnLS0tOic7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3RleHQtYWxpZ246Y2VudGVyOyc6XG4gICAgICAgICAgYWxsaWduID0gJzotLS06JztcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgdGFibGVBcnJheVswXVtpXSA9IGhlYWRDb250ZW50LnRyaW0oKTtcbiAgICB0YWJsZUFycmF5WzFdW2ldID0gYWxsaWduO1xuICB9XG5cbiAgZm9yIChpID0gMDsgaSA8IHJvd3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgciA9IHRhYmxlQXJyYXkucHVzaChbXSkgLSAxLFxuICAgICAgICBjb2xzID0gcm93c1tpXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgndGQnKTtcblxuICAgIGZvciAoaWkgPSAwOyBpaSA8IGhlYWRpbmdzLmxlbmd0aDsgKytpaSkge1xuICAgICAgdmFyIGNlbGxDb250ZW50ID0gJyAnO1xuICAgICAgaWYgKHR5cGVvZiBjb2xzW2lpXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY2VsbENvbnRlbnQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi50YWJsZUNlbGwnKShjb2xzW2lpXSwgZ2xvYmFscyk7XG4gICAgICB9XG4gICAgICB0YWJsZUFycmF5W3JdLnB1c2goY2VsbENvbnRlbnQpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBjZWxsU3BhY2VzQ291bnQgPSAzO1xuICBmb3IgKGkgPSAwOyBpIDwgdGFibGVBcnJheS5sZW5ndGg7ICsraSkge1xuICAgIGZvciAoaWkgPSAwOyBpaSA8IHRhYmxlQXJyYXlbaV0ubGVuZ3RoOyArK2lpKSB7XG4gICAgICB2YXIgc3RyTGVuID0gdGFibGVBcnJheVtpXVtpaV0ubGVuZ3RoO1xuICAgICAgaWYgKHN0ckxlbiA+IGNlbGxTcGFjZXNDb3VudCkge1xuICAgICAgICBjZWxsU3BhY2VzQ291bnQgPSBzdHJMZW47XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9yIChpID0gMDsgaSA8IHRhYmxlQXJyYXkubGVuZ3RoOyArK2kpIHtcbiAgICBmb3IgKGlpID0gMDsgaWkgPCB0YWJsZUFycmF5W2ldLmxlbmd0aDsgKytpaSkge1xuICAgICAgaWYgKGkgPT09IDEpIHtcbiAgICAgICAgaWYgKHRhYmxlQXJyYXlbaV1baWldLnNsaWNlKC0xKSA9PT0gJzonKSB7XG4gICAgICAgICAgdGFibGVBcnJheVtpXVtpaV0gPSBzaG93ZG93bi5oZWxwZXIucGFkRW5kKHRhYmxlQXJyYXlbaV1baWldLnNsaWNlKC0xKSwgY2VsbFNwYWNlc0NvdW50IC0gMSwgJy0nKSArICc6JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0YWJsZUFycmF5W2ldW2lpXSA9IHNob3dkb3duLmhlbHBlci5wYWRFbmQodGFibGVBcnJheVtpXVtpaV0sIGNlbGxTcGFjZXNDb3VudCwgJy0nKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGFibGVBcnJheVtpXVtpaV0gPSBzaG93ZG93bi5oZWxwZXIucGFkRW5kKHRhYmxlQXJyYXlbaV1baWldLCBjZWxsU3BhY2VzQ291bnQpO1xuICAgICAgfVxuICAgIH1cbiAgICB0eHQgKz0gJ3wgJyArIHRhYmxlQXJyYXlbaV0uam9pbignIHwgJykgKyAnIHxcXG4nO1xuICB9XG5cbiAgcmV0dXJuIHR4dC50cmltKCk7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi50YWJsZUNlbGwnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAoIW5vZGUuaGFzQ2hpbGROb2RlcygpKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG4gIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgIGNoaWxkcmVuTGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5ndGg7ICsraSkge1xuICAgIHR4dCArPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMsIHRydWUpO1xuICB9XG4gIHJldHVybiB0eHQudHJpbSgpO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24udHh0JywgZnVuY3Rpb24gKG5vZGUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSBub2RlLm5vZGVWYWx1ZTtcblxuICAvLyBtdWx0aXBsZSBzcGFjZXMgYXJlIGNvbGxhcHNlZFxuICB0eHQgPSB0eHQucmVwbGFjZSgvICsvZywgJyAnKTtcblxuICAvLyByZXBsYWNlIHRoZSBjdXN0b20gwqhOQlNQOyB3aXRoIGEgc3BhY2VcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL8KoTkJTUDsvZywgJyAnKTtcblxuICAvLyBcIiwgPCwgPiBhbmQgJiBzaG91bGQgcmVwbGFjZSBlc2NhcGVkIGh0bWwgZW50aXRpZXNcbiAgdHh0ID0gc2hvd2Rvd24uaGVscGVyLnVuZXNjYXBlSFRNTEVudGl0aWVzKHR4dCk7XG5cbiAgLy8gZXNjYXBlIG1hcmtkb3duIG1hZ2ljIGNoYXJhY3RlcnNcbiAgLy8gZW1waGFzaXMsIHN0cm9uZyBhbmQgc3RyaWtldGhyb3VnaCAtIGNhbiBhcHBlYXIgZXZlcnl3aGVyZVxuICAvLyB3ZSBhbHNvIGVzY2FwZSBwaXBlICh8KSBiZWNhdXNlIG9mIHRhYmxlc1xuICAvLyBhbmQgZXNjYXBlIGAgYmVjYXVzZSBvZiBjb2RlIGJsb2NrcyBhbmQgc3BhbnNcbiAgdHh0ID0gdHh0LnJlcGxhY2UoLyhbKl9+fGBdKS9nLCAnXFxcXCQxJyk7XG5cbiAgLy8gZXNjYXBlID4gYmVjYXVzZSBvZiBibG9ja3F1b3Rlc1xuICB0eHQgPSB0eHQucmVwbGFjZSgvXihcXHMqKT4vZywgJ1xcXFwkMT4nKTtcblxuICAvLyBoYXNoIGNoYXJhY3Rlciwgb25seSB0cm91Ymxlc29tZSBhdCB0aGUgYmVnaW5uaW5nIG9mIGEgbGluZSBiZWNhdXNlIG9mIGhlYWRlcnNcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL14jL2dtLCAnXFxcXCMnKTtcblxuICAvLyBob3Jpem9udGFsIHJ1bGVzXG4gIHR4dCA9IHR4dC5yZXBsYWNlKC9eKFxccyopKFstPV17Myx9KShcXHMqKSQvLCAnJDFcXFxcJDIkMycpO1xuXG4gIC8vIGRvdCwgYmVjYXVzZSBvZiBvcmRlcmVkIGxpc3RzLCBvbmx5IHRyb3VibGVzb21lIGF0IHRoZSBiZWdpbm5pbmcgb2YgYSBsaW5lIHdoZW4gcHJlY2VkZWQgYnkgYW4gaW50ZWdlclxuICB0eHQgPSB0eHQucmVwbGFjZSgvXiggezAsM31cXGQrKVxcLi9nbSwgJyQxXFxcXC4nKTtcblxuICAvLyArLCAqIGFuZCAtLCBhdCB0aGUgYmVnaW5uaW5nIG9mIGEgbGluZSBiZWNvbWVzIGEgbGlzdCwgc28gd2UgbmVlZCB0byBlc2NhcGUgdGhlbSBhbHNvIChhc3RlcmlzayB3YXMgYWxyZWFkeSBlc2NhcGVkKVxuICB0eHQgPSB0eHQucmVwbGFjZSgvXiggezAsM30pKFsrLV0pL2dtLCAnJDFcXFxcJDInKTtcblxuICAvLyBpbWFnZXMgYW5kIGxpbmtzLCBdIGZvbGxvd2VkIGJ5ICggaXMgcHJvYmxlbWF0aWMsIHNvIHdlIGVzY2FwZSBpdFxuICB0eHQgPSB0eHQucmVwbGFjZSgvXShbXFxzXSopXFwoL2csICdcXFxcXSQxXFxcXCgnKTtcblxuICAvLyByZWZlcmVuY2UgVVJJcyBtdXN0IGFsc28gYmUgZXNjYXBlZFxuICB0eHQgPSB0eHQucmVwbGFjZSgvXiB7MCwzfVxcWyhbXFxTIFxcdF0qPyldOi9nbSwgJ1xcXFxbJDFdOicpO1xuXG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG52YXIgcm9vdCA9IHRoaXM7XG5cbi8vIEFNRCBMb2FkZXJcbmlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAndXNlIHN0cmljdCc7XG4gICAgcmV0dXJuIHNob3dkb3duO1xuICB9KTtcblxuLy8gQ29tbW9uSlMvbm9kZUpTIExvYWRlclxufSBlbHNlIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICBtb2R1bGUuZXhwb3J0cyA9IHNob3dkb3duO1xuXG4vLyBSZWd1bGFyIEJyb3dzZXIgbG9hZGVyXG59IGVsc2Uge1xuICByb290LnNob3dkb3duID0gc2hvd2Rvd247XG59XG59KS5jYWxsKHRoaXMpO1xyXG5cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNob3dkb3duLmpzLm1hcFxyXG4iLCIvLyBSZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZVxuLy8gQ29weXJpZ2h0IChjKSAyMDA5LTIwMTAgRG9taW5pYyBCYWdnb3R0XG4vLyBDb3B5cmlnaHQgKGMpIDIwMDktMjAxMCBBc2ggQmVybGluXG4vLyBDb3B5cmlnaHQgKGMpIDIwMTEgQ2hyaXN0b3BoIERvcm4gPGNocmlzdG9waEBjaHJpc3RvcGhkb3JuLmNvbT4gKGh0dHA6Ly93d3cuY2hyaXN0b3BoZG9ybi5jb20pXG5cbi8qanNoaW50IGJyb3dzZXI6dHJ1ZSwgZGV2ZWw6dHJ1ZSAqL1xuXG4oZnVuY3Rpb24oIGV4cG9zZSApIHtcblxuLyoqXG4gKiAgY2xhc3MgTWFya2Rvd25cbiAqXG4gKiAgTWFya2Rvd24gcHJvY2Vzc2luZyBpbiBKYXZhc2NyaXB0IGRvbmUgcmlnaHQuIFdlIGhhdmUgdmVyeSBwYXJ0aWN1bGFyIHZpZXdzXG4gKiAgb24gd2hhdCBjb25zdGl0dXRlcyAncmlnaHQnIHdoaWNoIGluY2x1ZGU6XG4gKlxuICogIC0gcHJvZHVjZXMgd2VsbC1mb3JtZWQgSFRNTCAodGhpcyBtZWFucyB0aGF0IGVtIGFuZCBzdHJvbmcgbmVzdGluZyBpc1xuICogICAgaW1wb3J0YW50KVxuICpcbiAqICAtIGhhcyBhbiBpbnRlcm1lZGlhdGUgcmVwcmVzZW50YXRpb24gdG8gYWxsb3cgcHJvY2Vzc2luZyBvZiBwYXJzZWQgZGF0YSAoV2VcbiAqICAgIGluIGZhY3QgaGF2ZSB0d28sIGJvdGggYXMgW0pzb25NTF06IGEgbWFya2Rvd24gdHJlZSBhbmQgYW4gSFRNTCB0cmVlKS5cbiAqXG4gKiAgLSBpcyBlYXNpbHkgZXh0ZW5zaWJsZSB0byBhZGQgbmV3IGRpYWxlY3RzIHdpdGhvdXQgaGF2aW5nIHRvIHJld3JpdGUgdGhlXG4gKiAgICBlbnRpcmUgcGFyc2luZyBtZWNoYW5pY3NcbiAqXG4gKiAgLSBoYXMgYSBnb29kIHRlc3Qgc3VpdGVcbiAqXG4gKiAgVGhpcyBpbXBsZW1lbnRhdGlvbiBmdWxmaWxscyBhbGwgb2YgdGhlc2UgKGV4Y2VwdCB0aGF0IHRoZSB0ZXN0IHN1aXRlIGNvdWxkXG4gKiAgZG8gd2l0aCBleHBhbmRpbmcgdG8gYXV0b21hdGljYWxseSBydW4gYWxsIHRoZSBmaXh0dXJlcyBmcm9tIG90aGVyIE1hcmtkb3duXG4gKiAgaW1wbGVtZW50YXRpb25zLilcbiAqXG4gKiAgIyMjIyMgSW50ZXJtZWRpYXRlIFJlcHJlc2VudGF0aW9uXG4gKlxuICogICpUT0RPKiBUYWxrIGFib3V0IHRoaXMgOikgSXRzIEpzb25NTCwgYnV0IGRvY3VtZW50IHRoZSBub2RlIG5hbWVzIHdlIHVzZS5cbiAqXG4gKiAgW0pzb25NTF06IGh0dHA6Ly9qc29ubWwub3JnLyBcIkpTT04gTWFya3VwIExhbmd1YWdlXCJcbiAqKi9cbnZhciBNYXJrZG93biA9IGV4cG9zZS5NYXJrZG93biA9IGZ1bmN0aW9uKGRpYWxlY3QpIHtcbiAgc3dpdGNoICh0eXBlb2YgZGlhbGVjdCkge1xuICAgIGNhc2UgXCJ1bmRlZmluZWRcIjpcbiAgICAgIHRoaXMuZGlhbGVjdCA9IE1hcmtkb3duLmRpYWxlY3RzLkdydWJlcjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgIHRoaXMuZGlhbGVjdCA9IGRpYWxlY3Q7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgaWYgKCBkaWFsZWN0IGluIE1hcmtkb3duLmRpYWxlY3RzICkge1xuICAgICAgICB0aGlzLmRpYWxlY3QgPSBNYXJrZG93bi5kaWFsZWN0c1tkaWFsZWN0XTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIE1hcmtkb3duIGRpYWxlY3QgJ1wiICsgU3RyaW5nKGRpYWxlY3QpICsgXCInXCIpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gIH1cbiAgdGhpcy5lbV9zdGF0ZSA9IFtdO1xuICB0aGlzLnN0cm9uZ19zdGF0ZSA9IFtdO1xuICB0aGlzLmRlYnVnX2luZGVudCA9IFwiXCI7XG59O1xuXG4vKipcbiAqICBwYXJzZSggbWFya2Rvd24sIFtkaWFsZWN0XSApIC0+IEpzb25NTFxuICogIC0gbWFya2Rvd24gKFN0cmluZyk6IG1hcmtkb3duIHN0cmluZyB0byBwYXJzZVxuICogIC0gZGlhbGVjdCAoU3RyaW5nIHwgRGlhbGVjdCk6IHRoZSBkaWFsZWN0IHRvIHVzZSwgZGVmYXVsdHMgdG8gZ3J1YmVyXG4gKlxuICogIFBhcnNlIGBtYXJrZG93bmAgYW5kIHJldHVybiBhIG1hcmtkb3duIGRvY3VtZW50IGFzIGEgTWFya2Rvd24uSnNvbk1MIHRyZWUuXG4gKiovXG5leHBvc2UucGFyc2UgPSBmdW5jdGlvbiggc291cmNlLCBkaWFsZWN0ICkge1xuICAvLyBkaWFsZWN0IHdpbGwgZGVmYXVsdCBpZiB1bmRlZmluZWRcbiAgdmFyIG1kID0gbmV3IE1hcmtkb3duKCBkaWFsZWN0ICk7XG4gIHJldHVybiBtZC50b1RyZWUoIHNvdXJjZSApO1xufTtcblxuLyoqXG4gKiAgdG9IVE1MKCBtYXJrZG93biwgW2RpYWxlY3RdICApIC0+IFN0cmluZ1xuICogIHRvSFRNTCggbWRfdHJlZSApIC0+IFN0cmluZ1xuICogIC0gbWFya2Rvd24gKFN0cmluZyk6IG1hcmtkb3duIHN0cmluZyB0byBwYXJzZVxuICogIC0gbWRfdHJlZSAoTWFya2Rvd24uSnNvbk1MKTogcGFyc2VkIG1hcmtkb3duIHRyZWVcbiAqXG4gKiAgVGFrZSBtYXJrZG93biAoZWl0aGVyIGFzIGEgc3RyaW5nIG9yIGFzIGEgSnNvbk1MIHRyZWUpIGFuZCBydW4gaXQgdGhyb3VnaFxuICogIFtbdG9IVE1MVHJlZV1dIHRoZW4gdHVybiBpdCBpbnRvIGEgd2VsbC1mb3JtYXRlZCBIVE1MIGZyYWdtZW50LlxuICoqL1xuZXhwb3NlLnRvSFRNTCA9IGZ1bmN0aW9uIHRvSFRNTCggc291cmNlICwgZGlhbGVjdCAsIG9wdGlvbnMgKSB7XG4gIHZhciBpbnB1dCA9IGV4cG9zZS50b0hUTUxUcmVlKCBzb3VyY2UgLCBkaWFsZWN0ICwgb3B0aW9ucyApO1xuXG4gIHJldHVybiBleHBvc2UucmVuZGVySnNvbk1MKCBpbnB1dCApO1xufTtcblxuLyoqXG4gKiAgdG9IVE1MVHJlZSggbWFya2Rvd24sIFtkaWFsZWN0XSApIC0+IEpzb25NTFxuICogIHRvSFRNTFRyZWUoIG1kX3RyZWUgKSAtPiBKc29uTUxcbiAqICAtIG1hcmtkb3duIChTdHJpbmcpOiBtYXJrZG93biBzdHJpbmcgdG8gcGFyc2VcbiAqICAtIGRpYWxlY3QgKFN0cmluZyB8IERpYWxlY3QpOiB0aGUgZGlhbGVjdCB0byB1c2UsIGRlZmF1bHRzIHRvIGdydWJlclxuICogIC0gbWRfdHJlZSAoTWFya2Rvd24uSnNvbk1MKTogcGFyc2VkIG1hcmtkb3duIHRyZWVcbiAqXG4gKiAgVHVybiBtYXJrZG93biBpbnRvIEhUTUwsIHJlcHJlc2VudGVkIGFzIGEgSnNvbk1MIHRyZWUuIElmIGEgc3RyaW5nIGlzIGdpdmVuXG4gKiAgdG8gdGhpcyBmdW5jdGlvbiwgaXQgaXMgZmlyc3QgcGFyc2VkIGludG8gYSBtYXJrZG93biB0cmVlIGJ5IGNhbGxpbmdcbiAqICBbW3BhcnNlXV0uXG4gKiovXG5leHBvc2UudG9IVE1MVHJlZSA9IGZ1bmN0aW9uIHRvSFRNTFRyZWUoIGlucHV0LCBkaWFsZWN0ICwgb3B0aW9ucyApIHtcbiAgLy8gY29udmVydCBzdHJpbmcgaW5wdXQgdG8gYW4gTUQgdHJlZVxuICBpZiAoIHR5cGVvZiBpbnB1dCA9PT1cInN0cmluZ1wiICkgaW5wdXQgPSB0aGlzLnBhcnNlKCBpbnB1dCwgZGlhbGVjdCApO1xuXG4gIC8vIE5vdyBjb252ZXJ0IHRoZSBNRCB0cmVlIHRvIGFuIEhUTUwgdHJlZVxuXG4gIC8vIHJlbW92ZSByZWZlcmVuY2VzIGZyb20gdGhlIHRyZWVcbiAgdmFyIGF0dHJzID0gZXh0cmFjdF9hdHRyKCBpbnB1dCApLFxuICAgICAgcmVmcyA9IHt9O1xuXG4gIGlmICggYXR0cnMgJiYgYXR0cnMucmVmZXJlbmNlcyApIHtcbiAgICByZWZzID0gYXR0cnMucmVmZXJlbmNlcztcbiAgfVxuXG4gIHZhciBodG1sID0gY29udmVydF90cmVlX3RvX2h0bWwoIGlucHV0LCByZWZzICwgb3B0aW9ucyApO1xuICBtZXJnZV90ZXh0X25vZGVzKCBodG1sICk7XG4gIHJldHVybiBodG1sO1xufTtcblxuLy8gRm9yIFNwaWRlcm1vbmtleSBiYXNlZCBlbmdpbmVzXG5mdW5jdGlvbiBta19ibG9ja190b1NvdXJjZSgpIHtcbiAgcmV0dXJuIFwiTWFya2Rvd24ubWtfYmxvY2soIFwiICtcbiAgICAgICAgICB1bmV2YWwodGhpcy50b1N0cmluZygpKSArXG4gICAgICAgICAgXCIsIFwiICtcbiAgICAgICAgICB1bmV2YWwodGhpcy50cmFpbGluZykgK1xuICAgICAgICAgIFwiLCBcIiArXG4gICAgICAgICAgdW5ldmFsKHRoaXMubGluZU51bWJlcikgK1xuICAgICAgICAgIFwiIClcIjtcbn1cblxuLy8gbm9kZVxuZnVuY3Rpb24gbWtfYmxvY2tfaW5zcGVjdCgpIHtcbiAgdmFyIHV0aWwgPSByZXF1aXJlKFwidXRpbFwiKTtcbiAgcmV0dXJuIFwiTWFya2Rvd24ubWtfYmxvY2soIFwiICtcbiAgICAgICAgICB1dGlsLmluc3BlY3QodGhpcy50b1N0cmluZygpKSArXG4gICAgICAgICAgXCIsIFwiICtcbiAgICAgICAgICB1dGlsLmluc3BlY3QodGhpcy50cmFpbGluZykgK1xuICAgICAgICAgIFwiLCBcIiArXG4gICAgICAgICAgdXRpbC5pbnNwZWN0KHRoaXMubGluZU51bWJlcikgK1xuICAgICAgICAgIFwiIClcIjtcblxufVxuXG52YXIgbWtfYmxvY2sgPSBNYXJrZG93bi5ta19ibG9jayA9IGZ1bmN0aW9uKGJsb2NrLCB0cmFpbCwgbGluZSkge1xuICAvLyBCZSBoZWxwZnVsIGZvciBkZWZhdWx0IGNhc2UgaW4gdGVzdHMuXG4gIGlmICggYXJndW1lbnRzLmxlbmd0aCA9PSAxICkgdHJhaWwgPSBcIlxcblxcblwiO1xuXG4gIHZhciBzID0gbmV3IFN0cmluZyhibG9jayk7XG4gIHMudHJhaWxpbmcgPSB0cmFpbDtcbiAgLy8gVG8gbWFrZSBpdCBjbGVhciBpdHMgbm90IGp1c3QgYSBzdHJpbmdcbiAgcy5pbnNwZWN0ID0gbWtfYmxvY2tfaW5zcGVjdDtcbiAgcy50b1NvdXJjZSA9IG1rX2Jsb2NrX3RvU291cmNlO1xuXG4gIGlmICggbGluZSAhPSB1bmRlZmluZWQgKVxuICAgIHMubGluZU51bWJlciA9IGxpbmU7XG5cbiAgcmV0dXJuIHM7XG59O1xuXG5mdW5jdGlvbiBjb3VudF9saW5lcyggc3RyICkge1xuICB2YXIgbiA9IDAsIGkgPSAtMTtcbiAgd2hpbGUgKCAoIGkgPSBzdHIuaW5kZXhPZihcIlxcblwiLCBpICsgMSkgKSAhPT0gLTEgKSBuKys7XG4gIHJldHVybiBuO1xufVxuXG4vLyBJbnRlcm5hbCAtIHNwbGl0IHNvdXJjZSBpbnRvIHJvdWdoIGJsb2Nrc1xuTWFya2Rvd24ucHJvdG90eXBlLnNwbGl0X2Jsb2NrcyA9IGZ1bmN0aW9uIHNwbGl0QmxvY2tzKCBpbnB1dCwgc3RhcnRMaW5lICkge1xuICBpbnB1dCA9IGlucHV0LnJlcGxhY2UoLyhcXHJcXG58XFxufFxccikvZywgXCJcXG5cIik7XG4gIC8vIFtcXHNcXFNdIG1hdGNoZXMgX2FueXRoaW5nXyAobmV3bGluZSBvciBzcGFjZSlcbiAgLy8gW15dIGlzIGVxdWl2YWxlbnQgYnV0IGRvZXNuJ3Qgd29yayBpbiBJRXMuXG4gIHZhciByZSA9IC8oW1xcc1xcU10rPykoJHxcXG4jfFxcbig/OlxccypcXG58JCkrKS9nLFxuICAgICAgYmxvY2tzID0gW10sXG4gICAgICBtO1xuXG4gIHZhciBsaW5lX25vID0gMTtcblxuICBpZiAoICggbSA9IC9eKFxccypcXG4pLy5leGVjKGlucHV0KSApICE9IG51bGwgKSB7XG4gICAgLy8gc2tpcCAoYnV0IGNvdW50KSBsZWFkaW5nIGJsYW5rIGxpbmVzXG4gICAgbGluZV9ubyArPSBjb3VudF9saW5lcyggbVswXSApO1xuICAgIHJlLmxhc3RJbmRleCA9IG1bMF0ubGVuZ3RoO1xuICB9XG5cbiAgd2hpbGUgKCAoIG0gPSByZS5leGVjKGlucHV0KSApICE9PSBudWxsICkge1xuICAgIGlmIChtWzJdID09IFwiXFxuI1wiKSB7XG4gICAgICBtWzJdID0gXCJcXG5cIjtcbiAgICAgIHJlLmxhc3RJbmRleC0tO1xuICAgIH1cbiAgICBibG9ja3MucHVzaCggbWtfYmxvY2soIG1bMV0sIG1bMl0sIGxpbmVfbm8gKSApO1xuICAgIGxpbmVfbm8gKz0gY291bnRfbGluZXMoIG1bMF0gKTtcbiAgfVxuXG4gIHJldHVybiBibG9ja3M7XG59O1xuXG4vKipcbiAqICBNYXJrZG93biNwcm9jZXNzQmxvY2soIGJsb2NrLCBuZXh0ICkgLT4gdW5kZWZpbmVkIHwgWyBKc29uTUwsIC4uLiBdXG4gKiAgLSBibG9jayAoU3RyaW5nKTogdGhlIGJsb2NrIHRvIHByb2Nlc3NcbiAqICAtIG5leHQgKEFycmF5KTogdGhlIGZvbGxvd2luZyBibG9ja3NcbiAqXG4gKiBQcm9jZXNzIGBibG9ja2AgYW5kIHJldHVybiBhbiBhcnJheSBvZiBKc29uTUwgbm9kZXMgcmVwcmVzZW50aW5nIGBibG9ja2AuXG4gKlxuICogSXQgZG9lcyB0aGlzIGJ5IGFza2luZyBlYWNoIGJsb2NrIGxldmVsIGZ1bmN0aW9uIGluIHRoZSBkaWFsZWN0IHRvIHByb2Nlc3NcbiAqIHRoZSBibG9jayB1bnRpbCBvbmUgY2FuLiBTdWNjZXNmdWwgaGFuZGxpbmcgaXMgaW5kaWNhdGVkIGJ5IHJldHVybmluZyBhblxuICogYXJyYXkgKHdpdGggemVybyBvciBtb3JlIEpzb25NTCBub2RlcyksIGZhaWx1cmUgYnkgYSBmYWxzZSB2YWx1ZS5cbiAqXG4gKiBCbG9ja3MgaGFuZGxlcnMgYXJlIHJlc3BvbnNpYmxlIGZvciBjYWxsaW5nIFtbTWFya2Rvd24jcHJvY2Vzc0lubGluZV1dXG4gKiB0aGVtc2VsdmVzIGFzIGFwcHJvcHJpYXRlLlxuICpcbiAqIElmIHRoZSBibG9ja3Mgd2VyZSBzcGxpdCBpbmNvcnJlY3RseSBvciBhZGphY2VudCBibG9ja3MgbmVlZCBjb2xsYXBzaW5nIHlvdVxuICogY2FuIGFkanVzdCBgbmV4dGAgaW4gcGxhY2UgdXNpbmcgc2hpZnQvc3BsaWNlIGV0Yy5cbiAqXG4gKiBJZiBhbnkgb2YgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBpcyBub3QgcmlnaHQgZm9yIHRoZSBkaWFsZWN0LCB5b3UgY2FuXG4gKiBkZWZpbmUgYSBgX19jYWxsX19gIG1ldGhvZCBvbiB0aGUgZGlhbGVjdCB0aGF0IHdpbGwgZ2V0IGludm9rZWQgdG8gaGFuZGxlXG4gKiB0aGUgYmxvY2sgcHJvY2Vzc2luZy5cbiAqL1xuTWFya2Rvd24ucHJvdG90eXBlLnByb2Nlc3NCbG9jayA9IGZ1bmN0aW9uIHByb2Nlc3NCbG9jayggYmxvY2ssIG5leHQgKSB7XG4gIHZhciBjYnMgPSB0aGlzLmRpYWxlY3QuYmxvY2ssXG4gICAgICBvcmQgPSBjYnMuX19vcmRlcl9fO1xuXG4gIGlmICggXCJfX2NhbGxfX1wiIGluIGNicyApIHtcbiAgICByZXR1cm4gY2JzLl9fY2FsbF9fLmNhbGwodGhpcywgYmxvY2ssIG5leHQpO1xuICB9XG5cbiAgZm9yICggdmFyIGkgPSAwOyBpIDwgb3JkLmxlbmd0aDsgaSsrICkge1xuICAgIC8vRDp0aGlzLmRlYnVnKCBcIlRlc3RpbmdcIiwgb3JkW2ldICk7XG4gICAgdmFyIHJlcyA9IGNic1sgb3JkW2ldIF0uY2FsbCggdGhpcywgYmxvY2ssIG5leHQgKTtcbiAgICBpZiAoIHJlcyApIHtcbiAgICAgIC8vRDp0aGlzLmRlYnVnKFwiICBtYXRjaGVkXCIpO1xuICAgICAgaWYgKCAhaXNBcnJheShyZXMpIHx8ICggcmVzLmxlbmd0aCA+IDAgJiYgISggaXNBcnJheShyZXNbMF0pICkgKSApXG4gICAgICAgIHRoaXMuZGVidWcob3JkW2ldLCBcImRpZG4ndCByZXR1cm4gYSBwcm9wZXIgYXJyYXlcIik7XG4gICAgICAvL0Q6dGhpcy5kZWJ1ZyggXCJcIiApO1xuICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gIH1cblxuICAvLyBVaG9oISBubyBtYXRjaCEgU2hvdWxkIHdlIHRocm93IGFuIGVycm9yP1xuICByZXR1cm4gW107XG59O1xuXG5NYXJrZG93bi5wcm90b3R5cGUucHJvY2Vzc0lubGluZSA9IGZ1bmN0aW9uIHByb2Nlc3NJbmxpbmUoIGJsb2NrICkge1xuICByZXR1cm4gdGhpcy5kaWFsZWN0LmlubGluZS5fX2NhbGxfXy5jYWxsKCB0aGlzLCBTdHJpbmcoIGJsb2NrICkgKTtcbn07XG5cbi8qKlxuICogIE1hcmtkb3duI3RvVHJlZSggc291cmNlICkgLT4gSnNvbk1MXG4gKiAgLSBzb3VyY2UgKFN0cmluZyk6IG1hcmtkb3duIHNvdXJjZSB0byBwYXJzZVxuICpcbiAqICBQYXJzZSBgc291cmNlYCBpbnRvIGEgSnNvbk1MIHRyZWUgcmVwcmVzZW50aW5nIHRoZSBtYXJrZG93biBkb2N1bWVudC5cbiAqKi9cbi8vIGN1c3RvbV90cmVlIG1lYW5zIHNldCB0aGlzLnRyZWUgdG8gYGN1c3RvbV90cmVlYCBhbmQgcmVzdG9yZSBvbGQgdmFsdWUgb24gcmV0dXJuXG5NYXJrZG93bi5wcm90b3R5cGUudG9UcmVlID0gZnVuY3Rpb24gdG9UcmVlKCBzb3VyY2UsIGN1c3RvbV9yb290ICkge1xuICB2YXIgYmxvY2tzID0gc291cmNlIGluc3RhbmNlb2YgQXJyYXkgPyBzb3VyY2UgOiB0aGlzLnNwbGl0X2Jsb2Nrcyggc291cmNlICk7XG5cbiAgLy8gTWFrZSB0cmVlIGEgbWVtYmVyIHZhcmlhYmxlIHNvIGl0cyBlYXNpZXIgdG8gbWVzcyB3aXRoIGluIGV4dGVuc2lvbnNcbiAgdmFyIG9sZF90cmVlID0gdGhpcy50cmVlO1xuICB0cnkge1xuICAgIHRoaXMudHJlZSA9IGN1c3RvbV9yb290IHx8IHRoaXMudHJlZSB8fCBbIFwibWFya2Rvd25cIiBdO1xuXG4gICAgYmxvY2tzOlxuICAgIHdoaWxlICggYmxvY2tzLmxlbmd0aCApIHtcbiAgICAgIHZhciBiID0gdGhpcy5wcm9jZXNzQmxvY2soIGJsb2Nrcy5zaGlmdCgpLCBibG9ja3MgKTtcblxuICAgICAgLy8gUmVmZXJlbmNlIGJsb2NrcyBhbmQgdGhlIGxpa2Ugd29uJ3QgcmV0dXJuIGFueSBjb250ZW50XG4gICAgICBpZiAoICFiLmxlbmd0aCApIGNvbnRpbnVlIGJsb2NrcztcblxuICAgICAgdGhpcy50cmVlLnB1c2guYXBwbHkoIHRoaXMudHJlZSwgYiApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50cmVlO1xuICB9XG4gIGZpbmFsbHkge1xuICAgIGlmICggY3VzdG9tX3Jvb3QgKSB7XG4gICAgICB0aGlzLnRyZWUgPSBvbGRfdHJlZTtcbiAgICB9XG4gIH1cbn07XG5cbi8vIE5vb3AgYnkgZGVmYXVsdFxuTWFya2Rvd24ucHJvdG90eXBlLmRlYnVnID0gZnVuY3Rpb24gKCkge1xuICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKCBhcmd1bWVudHMpO1xuICBhcmdzLnVuc2hpZnQodGhpcy5kZWJ1Z19pbmRlbnQpO1xuICBpZiAoIHR5cGVvZiBwcmludCAhPT0gXCJ1bmRlZmluZWRcIiApXG4gICAgICBwcmludC5hcHBseSggcHJpbnQsIGFyZ3MgKTtcbiAgaWYgKCB0eXBlb2YgY29uc29sZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgY29uc29sZS5sb2cgIT09IFwidW5kZWZpbmVkXCIgKVxuICAgICAgY29uc29sZS5sb2cuYXBwbHkoIG51bGwsIGFyZ3MgKTtcbn1cblxuTWFya2Rvd24ucHJvdG90eXBlLmxvb3BfcmVfb3Zlcl9ibG9jayA9IGZ1bmN0aW9uKCByZSwgYmxvY2ssIGNiICkge1xuICAvLyBEb250IHVzZSAvZyByZWdleHBzIHdpdGggdGhpc1xuICB2YXIgbSxcbiAgICAgIGIgPSBibG9jay52YWx1ZU9mKCk7XG5cbiAgd2hpbGUgKCBiLmxlbmd0aCAmJiAobSA9IHJlLmV4ZWMoYikgKSAhPSBudWxsICkge1xuICAgIGIgPSBiLnN1YnN0ciggbVswXS5sZW5ndGggKTtcbiAgICBjYi5jYWxsKHRoaXMsIG0pO1xuICB9XG4gIHJldHVybiBiO1xufTtcblxuLyoqXG4gKiBNYXJrZG93bi5kaWFsZWN0c1xuICpcbiAqIE5hbWVzcGFjZSBvZiBidWlsdC1pbiBkaWFsZWN0cy5cbiAqKi9cbk1hcmtkb3duLmRpYWxlY3RzID0ge307XG5cbi8qKlxuICogTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyXG4gKlxuICogVGhlIGRlZmF1bHQgZGlhbGVjdCB0aGF0IGZvbGxvd3MgdGhlIHJ1bGVzIHNldCBvdXQgYnkgSm9obiBHcnViZXInc1xuICogbWFya2Rvd24ucGwgYXMgY2xvc2VseSBhcyBwb3NzaWJsZS4gV2VsbCBhY3R1YWxseSB3ZSBmb2xsb3cgdGhlIGJlaGF2aW91ciBvZlxuICogdGhhdCBzY3JpcHQgd2hpY2ggaW4gc29tZSBwbGFjZXMgaXMgbm90IGV4YWN0bHkgd2hhdCB0aGUgc3ludGF4IHdlYiBwYWdlXG4gKiBzYXlzLlxuICoqL1xuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyID0ge1xuICBibG9jazoge1xuICAgIGF0eEhlYWRlcjogZnVuY3Rpb24gYXR4SGVhZGVyKCBibG9jaywgbmV4dCApIHtcbiAgICAgIHZhciBtID0gYmxvY2subWF0Y2goIC9eKCN7MSw2fSlcXHMqKC4qPylcXHMqIypcXHMqKD86XFxufCQpLyApO1xuXG4gICAgICBpZiAoICFtICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgdmFyIGhlYWRlciA9IFsgXCJoZWFkZXJcIiwgeyBsZXZlbDogbVsgMSBdLmxlbmd0aCB9IF07XG4gICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShoZWFkZXIsIHRoaXMucHJvY2Vzc0lubGluZShtWyAyIF0pKTtcblxuICAgICAgaWYgKCBtWzBdLmxlbmd0aCA8IGJsb2NrLmxlbmd0aCApXG4gICAgICAgIG5leHQudW5zaGlmdCggbWtfYmxvY2soIGJsb2NrLnN1YnN0ciggbVswXS5sZW5ndGggKSwgYmxvY2sudHJhaWxpbmcsIGJsb2NrLmxpbmVOdW1iZXIgKyAyICkgKTtcblxuICAgICAgcmV0dXJuIFsgaGVhZGVyIF07XG4gICAgfSxcblxuICAgIHNldGV4dEhlYWRlcjogZnVuY3Rpb24gc2V0ZXh0SGVhZGVyKCBibG9jaywgbmV4dCApIHtcbiAgICAgIHZhciBtID0gYmxvY2subWF0Y2goIC9eKC4qKVxcbihbLT1dKVxcMlxcMisoPzpcXG58JCkvICk7XG5cbiAgICAgIGlmICggIW0gKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICB2YXIgbGV2ZWwgPSAoIG1bIDIgXSA9PT0gXCI9XCIgKSA/IDEgOiAyO1xuICAgICAgdmFyIGhlYWRlciA9IFsgXCJoZWFkZXJcIiwgeyBsZXZlbCA6IGxldmVsIH0sIG1bIDEgXSBdO1xuXG4gICAgICBpZiAoIG1bMF0ubGVuZ3RoIDwgYmxvY2subGVuZ3RoIClcbiAgICAgICAgbmV4dC51bnNoaWZ0KCBta19ibG9jayggYmxvY2suc3Vic3RyKCBtWzBdLmxlbmd0aCApLCBibG9jay50cmFpbGluZywgYmxvY2subGluZU51bWJlciArIDIgKSApO1xuXG4gICAgICByZXR1cm4gWyBoZWFkZXIgXTtcbiAgICB9LFxuXG4gICAgY29kZTogZnVuY3Rpb24gY29kZSggYmxvY2ssIG5leHQgKSB7XG4gICAgICAvLyB8ICAgIEZvb1xuICAgICAgLy8gfGJhclxuICAgICAgLy8gc2hvdWxkIGJlIGEgY29kZSBibG9jayBmb2xsb3dlZCBieSBhIHBhcmFncmFwaC4gRnVuXG4gICAgICAvL1xuICAgICAgLy8gVGhlcmUgbWlnaHQgYWxzbyBiZSBhZGphY2VudCBjb2RlIGJsb2NrIHRvIG1lcmdlLlxuXG4gICAgICB2YXIgcmV0ID0gW10sXG4gICAgICAgICAgcmUgPSAvXig/OiB7MCwzfVxcdHwgezR9KSguKilcXG4/LyxcbiAgICAgICAgICBsaW5lcztcblxuICAgICAgLy8gNCBzcGFjZXMgKyBjb250ZW50XG4gICAgICBpZiAoICFibG9jay5tYXRjaCggcmUgKSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIGJsb2NrX3NlYXJjaDpcbiAgICAgIGRvIHtcbiAgICAgICAgLy8gTm93IHB1bGwgb3V0IHRoZSByZXN0IG9mIHRoZSBsaW5lc1xuICAgICAgICB2YXIgYiA9IHRoaXMubG9vcF9yZV9vdmVyX2Jsb2NrKFxuICAgICAgICAgICAgICAgICAgcmUsIGJsb2NrLnZhbHVlT2YoKSwgZnVuY3Rpb24oIG0gKSB7IHJldC5wdXNoKCBtWzFdICk7IH0gKTtcblxuICAgICAgICBpZiAoIGIubGVuZ3RoICkge1xuICAgICAgICAgIC8vIENhc2UgYWxsdWRlZCB0byBpbiBmaXJzdCBjb21tZW50LiBwdXNoIGl0IGJhY2sgb24gYXMgYSBuZXcgYmxvY2tcbiAgICAgICAgICBuZXh0LnVuc2hpZnQoIG1rX2Jsb2NrKGIsIGJsb2NrLnRyYWlsaW5nKSApO1xuICAgICAgICAgIGJyZWFrIGJsb2NrX3NlYXJjaDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICggbmV4dC5sZW5ndGggKSB7XG4gICAgICAgICAgLy8gQ2hlY2sgdGhlIG5leHQgYmxvY2sgLSBpdCBtaWdodCBiZSBjb2RlIHRvb1xuICAgICAgICAgIGlmICggIW5leHRbMF0ubWF0Y2goIHJlICkgKSBicmVhayBibG9ja19zZWFyY2g7XG5cbiAgICAgICAgICAvLyBQdWxsIGhvdyBob3cgbWFueSBibGFua3MgbGluZXMgZm9sbG93IC0gbWludXMgdHdvIHRvIGFjY291bnQgZm9yIC5qb2luXG4gICAgICAgICAgcmV0LnB1c2ggKCBibG9jay50cmFpbGluZy5yZXBsYWNlKC9bXlxcbl0vZywgXCJcIikuc3Vic3RyaW5nKDIpICk7XG5cbiAgICAgICAgICBibG9jayA9IG5leHQuc2hpZnQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBicmVhayBibG9ja19zZWFyY2g7XG4gICAgICAgIH1cbiAgICAgIH0gd2hpbGUgKCB0cnVlICk7XG5cbiAgICAgIHJldHVybiBbIFsgXCJjb2RlX2Jsb2NrXCIsIHJldC5qb2luKFwiXFxuXCIpIF0gXTtcbiAgICB9LFxuXG4gICAgaG9yaXpSdWxlOiBmdW5jdGlvbiBob3JpelJ1bGUoIGJsb2NrLCBuZXh0ICkge1xuICAgICAgLy8gdGhpcyBuZWVkcyB0byBmaW5kIGFueSBociBpbiB0aGUgYmxvY2sgdG8gaGFuZGxlIGFidXR0aW5nIGJsb2Nrc1xuICAgICAgdmFyIG0gPSBibG9jay5tYXRjaCggL14oPzooW1xcc1xcU10qPylcXG4pP1sgXFx0XSooWy1fKl0pKD86WyBcXHRdKlxcMil7Mix9WyBcXHRdKig/OlxcbihbXFxzXFxTXSopKT8kLyApO1xuXG4gICAgICBpZiAoICFtICkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICB2YXIganNvbm1sID0gWyBbIFwiaHJcIiBdIF07XG5cbiAgICAgIC8vIGlmIHRoZXJlJ3MgYSBsZWFkaW5nIGFidXR0aW5nIGJsb2NrLCBwcm9jZXNzIGl0XG4gICAgICBpZiAoIG1bIDEgXSApIHtcbiAgICAgICAganNvbm1sLnVuc2hpZnQuYXBwbHkoIGpzb25tbCwgdGhpcy5wcm9jZXNzQmxvY2soIG1bIDEgXSwgW10gKSApO1xuICAgICAgfVxuXG4gICAgICAvLyBpZiB0aGVyZSdzIGEgdHJhaWxpbmcgYWJ1dHRpbmcgYmxvY2ssIHN0aWNrIGl0IGludG8gbmV4dFxuICAgICAgaWYgKCBtWyAzIF0gKSB7XG4gICAgICAgIG5leHQudW5zaGlmdCggbWtfYmxvY2soIG1bIDMgXSApICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBqc29ubWw7XG4gICAgfSxcblxuICAgIC8vIFRoZXJlIGFyZSB0d28gdHlwZXMgb2YgbGlzdHMuIFRpZ2h0IGFuZCBsb29zZS4gVGlnaHQgbGlzdHMgaGF2ZSBubyB3aGl0ZXNwYWNlXG4gICAgLy8gYmV0d2VlbiB0aGUgaXRlbXMgKGFuZCByZXN1bHQgaW4gdGV4dCBqdXN0IGluIHRoZSA8bGk+KSBhbmQgbG9vc2UgbGlzdHMsXG4gICAgLy8gd2hpY2ggaGF2ZSBhbiBlbXB0eSBsaW5lIGJldHdlZW4gbGlzdCBpdGVtcywgcmVzdWx0aW5nIGluIChvbmUgb3IgbW9yZSlcbiAgICAvLyBwYXJhZ3JhcGhzIGluc2lkZSB0aGUgPGxpPi5cbiAgICAvL1xuICAgIC8vIFRoZXJlIGFyZSBhbGwgc29ydHMgd2VpcmQgZWRnZSBjYXNlcyBhYm91dCB0aGUgb3JpZ2luYWwgbWFya2Rvd24ucGwnc1xuICAgIC8vIGhhbmRsaW5nIG9mIGxpc3RzOlxuICAgIC8vXG4gICAgLy8gKiBOZXN0ZWQgbGlzdHMgYXJlIHN1cHBvc2VkIHRvIGJlIGluZGVudGVkIGJ5IGZvdXIgY2hhcnMgcGVyIGxldmVsLiBCdXRcbiAgICAvLyAgIGlmIHRoZXkgYXJlbid0LCB5b3UgY2FuIGdldCBhIG5lc3RlZCBsaXN0IGJ5IGluZGVudGluZyBieSBsZXNzIHRoYW5cbiAgICAvLyAgIGZvdXIgc28gbG9uZyBhcyB0aGUgaW5kZW50IGRvZXNuJ3QgbWF0Y2ggYW4gaW5kZW50IG9mIGFuIGV4aXN0aW5nIGxpc3RcbiAgICAvLyAgIGl0ZW0gaW4gdGhlICduZXN0IHN0YWNrJy5cbiAgICAvL1xuICAgIC8vICogVGhlIHR5cGUgb2YgdGhlIGxpc3QgKGJ1bGxldCBvciBudW1iZXIpIGlzIGNvbnRyb2xsZWQganVzdCBieSB0aGVcbiAgICAvLyAgICBmaXJzdCBpdGVtIGF0IHRoZSBpbmRlbnQuIFN1YnNlcXVlbnQgY2hhbmdlcyBhcmUgaWdub3JlZCB1bmxlc3MgdGhleVxuICAgIC8vICAgIGFyZSBmb3IgbmVzdGVkIGxpc3RzXG4gICAgLy9cbiAgICBsaXN0czogKGZ1bmN0aW9uKCApIHtcbiAgICAgIC8vIFVzZSBhIGNsb3N1cmUgdG8gaGlkZSBhIGZldyB2YXJpYWJsZXMuXG4gICAgICB2YXIgYW55X2xpc3QgPSBcIlsqKy1dfFxcXFxkK1xcXFwuXCIsXG4gICAgICAgICAgYnVsbGV0X2xpc3QgPSAvWyorLV0vLFxuICAgICAgICAgIG51bWJlcl9saXN0ID0gL1xcZCtcXC4vLFxuICAgICAgICAgIC8vIENhcHR1cmUgbGVhZGluZyBpbmRlbnQgYXMgaXQgbWF0dGVycyBmb3IgZGV0ZXJtaW5pbmcgbmVzdGVkIGxpc3RzLlxuICAgICAgICAgIGlzX2xpc3RfcmUgPSBuZXcgUmVnRXhwKCBcIl4oIHswLDN9KShcIiArIGFueV9saXN0ICsgXCIpWyBcXHRdK1wiICksXG4gICAgICAgICAgaW5kZW50X3JlID0gXCIoPzogezAsM31cXFxcdHwgezR9KVwiO1xuXG4gICAgICAvLyBUT0RPOiBDYWNoZSB0aGlzIHJlZ2V4cCBmb3IgY2VydGFpbiBkZXB0aHMuXG4gICAgICAvLyBDcmVhdGUgYSByZWdleHAgc3VpdGFibGUgZm9yIG1hdGNoaW5nIGFuIGxpIGZvciBhIGdpdmVuIHN0YWNrIGRlcHRoXG4gICAgICBmdW5jdGlvbiByZWdleF9mb3JfZGVwdGgoIGRlcHRoICkge1xuXG4gICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFxuICAgICAgICAgIC8vIG1bMV0gPSBpbmRlbnQsIG1bMl0gPSBsaXN0X3R5cGVcbiAgICAgICAgICBcIig/Ol4oXCIgKyBpbmRlbnRfcmUgKyBcInswLFwiICsgZGVwdGggKyBcIn0gezAsM30pKFwiICsgYW55X2xpc3QgKyBcIilcXFxccyspfFwiICtcbiAgICAgICAgICAvLyBtWzNdID0gY29udFxuICAgICAgICAgIFwiKF5cIiArIGluZGVudF9yZSArIFwiezAsXCIgKyAoZGVwdGgtMSkgKyBcIn1bIF17MCw0fSlcIlxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gZXhwYW5kX3RhYiggaW5wdXQgKSB7XG4gICAgICAgIHJldHVybiBpbnB1dC5yZXBsYWNlKCAvIHswLDN9XFx0L2csIFwiICAgIFwiICk7XG4gICAgICB9XG5cbiAgICAgIC8vIEFkZCBpbmxpbmUgY29udGVudCBgaW5saW5lYCB0byBgbGlgLiBpbmxpbmUgY29tZXMgZnJvbSBwcm9jZXNzSW5saW5lXG4gICAgICAvLyBzbyBpcyBhbiBhcnJheSBvZiBjb250ZW50XG4gICAgICBmdW5jdGlvbiBhZGQobGksIGxvb3NlLCBpbmxpbmUsIG5sKSB7XG4gICAgICAgIGlmICggbG9vc2UgKSB7XG4gICAgICAgICAgbGkucHVzaCggWyBcInBhcmFcIiBdLmNvbmNhdChpbmxpbmUpICk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIEhtbW0sIHNob3VsZCB0aGlzIGJlIGFueSBibG9jayBsZXZlbCBlbGVtZW50IG9yIGp1c3QgcGFyYXM/XG4gICAgICAgIHZhciBhZGRfdG8gPSBsaVtsaS5sZW5ndGggLTFdIGluc3RhbmNlb2YgQXJyYXkgJiYgbGlbbGkubGVuZ3RoIC0gMV1bMF0gPT0gXCJwYXJhXCJcbiAgICAgICAgICAgICAgICAgICA/IGxpW2xpLmxlbmd0aCAtMV1cbiAgICAgICAgICAgICAgICAgICA6IGxpO1xuXG4gICAgICAgIC8vIElmIHRoZXJlIGlzIGFscmVhZHkgc29tZSBjb250ZW50IGluIHRoaXMgbGlzdCwgYWRkIHRoZSBuZXcgbGluZSBpblxuICAgICAgICBpZiAoIG5sICYmIGxpLmxlbmd0aCA+IDEgKSBpbmxpbmUudW5zaGlmdChubCk7XG5cbiAgICAgICAgZm9yICggdmFyIGkgPSAwOyBpIDwgaW5saW5lLmxlbmd0aDsgaSsrICkge1xuICAgICAgICAgIHZhciB3aGF0ID0gaW5saW5lW2ldLFxuICAgICAgICAgICAgICBpc19zdHIgPSB0eXBlb2Ygd2hhdCA9PSBcInN0cmluZ1wiO1xuICAgICAgICAgIGlmICggaXNfc3RyICYmIGFkZF90by5sZW5ndGggPiAxICYmIHR5cGVvZiBhZGRfdG9bYWRkX3RvLmxlbmd0aC0xXSA9PSBcInN0cmluZ1wiICkge1xuICAgICAgICAgICAgYWRkX3RvWyBhZGRfdG8ubGVuZ3RoLTEgXSArPSB3aGF0O1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGFkZF90by5wdXNoKCB3aGF0ICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIGNvbnRhaW5lZCBtZWFucyBoYXZlIGFuIGluZGVudCBncmVhdGVyIHRoYW4gdGhlIGN1cnJlbnQgb25lLiBPblxuICAgICAgLy8gKmV2ZXJ5KiBsaW5lIGluIHRoZSBibG9ja1xuICAgICAgZnVuY3Rpb24gZ2V0X2NvbnRhaW5lZF9ibG9ja3MoIGRlcHRoLCBibG9ja3MgKSB7XG5cbiAgICAgICAgdmFyIHJlID0gbmV3IFJlZ0V4cCggXCJeKFwiICsgaW5kZW50X3JlICsgXCJ7XCIgKyBkZXB0aCArIFwifS4qP1xcXFxuPykqJFwiICksXG4gICAgICAgICAgICByZXBsYWNlID0gbmV3IFJlZ0V4cChcIl5cIiArIGluZGVudF9yZSArIFwie1wiICsgZGVwdGggKyBcIn1cIiwgXCJnbVwiKSxcbiAgICAgICAgICAgIHJldCA9IFtdO1xuXG4gICAgICAgIHdoaWxlICggYmxvY2tzLmxlbmd0aCA+IDAgKSB7XG4gICAgICAgICAgaWYgKCByZS5leGVjKCBibG9ja3NbMF0gKSApIHtcbiAgICAgICAgICAgIHZhciBiID0gYmxvY2tzLnNoaWZ0KCksXG4gICAgICAgICAgICAgICAgLy8gTm93IHJlbW92ZSB0aGF0IGluZGVudFxuICAgICAgICAgICAgICAgIHggPSBiLnJlcGxhY2UoIHJlcGxhY2UsIFwiXCIpO1xuXG4gICAgICAgICAgICByZXQucHVzaCggbWtfYmxvY2soIHgsIGIudHJhaWxpbmcsIGIubGluZU51bWJlciApICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG5cbiAgICAgIC8vIHBhc3NlZCB0byBzdGFjay5mb3JFYWNoIHRvIHR1cm4gbGlzdCBpdGVtcyB1cCB0aGUgc3RhY2sgaW50byBwYXJhc1xuICAgICAgZnVuY3Rpb24gcGFyYWdyYXBoaWZ5KHMsIGksIHN0YWNrKSB7XG4gICAgICAgIHZhciBsaXN0ID0gcy5saXN0O1xuICAgICAgICB2YXIgbGFzdF9saSA9IGxpc3RbbGlzdC5sZW5ndGgtMV07XG5cbiAgICAgICAgaWYgKCBsYXN0X2xpWzFdIGluc3RhbmNlb2YgQXJyYXkgJiYgbGFzdF9saVsxXVswXSA9PSBcInBhcmFcIiApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCBpICsgMSA9PSBzdGFjay5sZW5ndGggKSB7XG4gICAgICAgICAgLy8gTGFzdCBzdGFjayBmcmFtZVxuICAgICAgICAgIC8vIEtlZXAgdGhlIHNhbWUgYXJyYXksIGJ1dCByZXBsYWNlIHRoZSBjb250ZW50c1xuICAgICAgICAgIGxhc3RfbGkucHVzaCggW1wicGFyYVwiXS5jb25jYXQoIGxhc3RfbGkuc3BsaWNlKDEsIGxhc3RfbGkubGVuZ3RoIC0gMSkgKSApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHZhciBzdWJsaXN0ID0gbGFzdF9saS5wb3AoKTtcbiAgICAgICAgICBsYXN0X2xpLnB1c2goIFtcInBhcmFcIl0uY29uY2F0KCBsYXN0X2xpLnNwbGljZSgxLCBsYXN0X2xpLmxlbmd0aCAtIDEpICksIHN1Ymxpc3QgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBUaGUgbWF0Y2hlciBmdW5jdGlvblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCBibG9jaywgbmV4dCApIHtcbiAgICAgICAgdmFyIG0gPSBibG9jay5tYXRjaCggaXNfbGlzdF9yZSApO1xuICAgICAgICBpZiAoICFtICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgICBmdW5jdGlvbiBtYWtlX2xpc3QoIG0gKSB7XG4gICAgICAgICAgdmFyIGxpc3QgPSBidWxsZXRfbGlzdC5leGVjKCBtWzJdIClcbiAgICAgICAgICAgICAgICAgICA/IFtcImJ1bGxldGxpc3RcIl1cbiAgICAgICAgICAgICAgICAgICA6IFtcIm51bWJlcmxpc3RcIl07XG5cbiAgICAgICAgICBzdGFjay5wdXNoKCB7IGxpc3Q6IGxpc3QsIGluZGVudDogbVsxXSB9ICk7XG4gICAgICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgICAgIH1cblxuXG4gICAgICAgIHZhciBzdGFjayA9IFtdLCAvLyBTdGFjayBvZiBsaXN0cyBmb3IgbmVzdGluZy5cbiAgICAgICAgICAgIGxpc3QgPSBtYWtlX2xpc3QoIG0gKSxcbiAgICAgICAgICAgIGxhc3RfbGksXG4gICAgICAgICAgICBsb29zZSA9IGZhbHNlLFxuICAgICAgICAgICAgcmV0ID0gWyBzdGFja1swXS5saXN0IF0sXG4gICAgICAgICAgICBpO1xuXG4gICAgICAgIC8vIExvb3AgdG8gc2VhcmNoIG92ZXIgYmxvY2sgbG9va2luZyBmb3IgaW5uZXIgYmxvY2sgZWxlbWVudHMgYW5kIGxvb3NlIGxpc3RzXG4gICAgICAgIGxvb3NlX3NlYXJjaDpcbiAgICAgICAgd2hpbGUgKCB0cnVlICkge1xuICAgICAgICAgIC8vIFNwbGl0IGludG8gbGluZXMgcHJlc2VydmluZyBuZXcgbGluZXMgYXQgZW5kIG9mIGxpbmVcbiAgICAgICAgICB2YXIgbGluZXMgPSBibG9jay5zcGxpdCggLyg/PVxcbikvICk7XG5cbiAgICAgICAgICAvLyBXZSBoYXZlIHRvIGdyYWIgYWxsIGxpbmVzIGZvciBhIGxpIGFuZCBjYWxsIHByb2Nlc3NJbmxpbmUgb24gdGhlbVxuICAgICAgICAgIC8vIG9uY2UgYXMgdGhlcmUgYXJlIHNvbWUgaW5saW5lIHRoaW5ncyB0aGF0IGNhbiBzcGFuIGxpbmVzLlxuICAgICAgICAgIHZhciBsaV9hY2N1bXVsYXRlID0gXCJcIjtcblxuICAgICAgICAgIC8vIExvb3Agb3ZlciB0aGUgbGluZXMgaW4gdGhpcyBibG9jayBsb29raW5nIGZvciB0aWdodCBsaXN0cy5cbiAgICAgICAgICB0aWdodF9zZWFyY2g6XG4gICAgICAgICAgZm9yICggdmFyIGxpbmVfbm8gPSAwOyBsaW5lX25vIDwgbGluZXMubGVuZ3RoOyBsaW5lX25vKysgKSB7XG4gICAgICAgICAgICB2YXIgbmwgPSBcIlwiLFxuICAgICAgICAgICAgICAgIGwgPSBsaW5lc1tsaW5lX25vXS5yZXBsYWNlKC9eXFxuLywgZnVuY3Rpb24obikgeyBubCA9IG47IHJldHVybiBcIlwiOyB9KTtcblxuICAgICAgICAgICAgLy8gVE9ETzogcmVhbGx5IHNob3VsZCBjYWNoZSB0aGlzXG4gICAgICAgICAgICB2YXIgbGluZV9yZSA9IHJlZ2V4X2Zvcl9kZXB0aCggc3RhY2subGVuZ3RoICk7XG5cbiAgICAgICAgICAgIG0gPSBsLm1hdGNoKCBsaW5lX3JlICk7XG4gICAgICAgICAgICAvL3ByaW50KCBcImxpbmU6XCIsIHVuZXZhbChsKSwgXCJcXG5saW5lIG1hdGNoOlwiLCB1bmV2YWwobSkgKTtcblxuICAgICAgICAgICAgLy8gV2UgaGF2ZSBhIGxpc3QgaXRlbVxuICAgICAgICAgICAgaWYgKCBtWzFdICE9PSB1bmRlZmluZWQgKSB7XG4gICAgICAgICAgICAgIC8vIFByb2Nlc3MgdGhlIHByZXZpb3VzIGxpc3QgaXRlbSwgaWYgYW55XG4gICAgICAgICAgICAgIGlmICggbGlfYWNjdW11bGF0ZS5sZW5ndGggKSB7XG4gICAgICAgICAgICAgICAgYWRkKCBsYXN0X2xpLCBsb29zZSwgdGhpcy5wcm9jZXNzSW5saW5lKCBsaV9hY2N1bXVsYXRlICksIG5sICk7XG4gICAgICAgICAgICAgICAgLy8gTG9vc2UgbW9kZSB3aWxsIGhhdmUgYmVlbiBkZWFsdCB3aXRoLiBSZXNldCBpdFxuICAgICAgICAgICAgICAgIGxvb3NlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgbGlfYWNjdW11bGF0ZSA9IFwiXCI7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBtWzFdID0gZXhwYW5kX3RhYiggbVsxXSApO1xuICAgICAgICAgICAgICB2YXIgd2FudGVkX2RlcHRoID0gTWF0aC5mbG9vcihtWzFdLmxlbmd0aC80KSsxO1xuICAgICAgICAgICAgICAvL3ByaW50KCBcIndhbnQ6XCIsIHdhbnRlZF9kZXB0aCwgXCJzdGFjazpcIiwgc3RhY2subGVuZ3RoKTtcbiAgICAgICAgICAgICAgaWYgKCB3YW50ZWRfZGVwdGggPiBzdGFjay5sZW5ndGggKSB7XG4gICAgICAgICAgICAgICAgLy8gRGVlcCBlbm91Z2ggZm9yIGEgbmVzdGVkIGxpc3Qgb3V0cmlnaHRcbiAgICAgICAgICAgICAgICAvL3ByaW50ICggXCJuZXcgbmVzdGVkIGxpc3RcIiApO1xuICAgICAgICAgICAgICAgIGxpc3QgPSBtYWtlX2xpc3QoIG0gKTtcbiAgICAgICAgICAgICAgICBsYXN0X2xpLnB1c2goIGxpc3QgKTtcbiAgICAgICAgICAgICAgICBsYXN0X2xpID0gbGlzdFsxXSA9IFsgXCJsaXN0aXRlbVwiIF07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gV2UgYXJlbid0IGRlZXAgZW5vdWdoIHRvIGJlIHN0cmljdGx5IGEgbmV3IGxldmVsLiBUaGlzIGlzXG4gICAgICAgICAgICAgICAgLy8gd2hlcmUgTWQucGwgZ29lcyBudXRzLiBJZiB0aGUgaW5kZW50IG1hdGNoZXMgYSBsZXZlbCBpbiB0aGVcbiAgICAgICAgICAgICAgICAvLyBzdGFjaywgcHV0IGl0IHRoZXJlLCBlbHNlIHB1dCBpdCBvbmUgZGVlcGVyIHRoZW4gdGhlXG4gICAgICAgICAgICAgICAgLy8gd2FudGVkX2RlcHRoIGRlc2VydmVzLlxuICAgICAgICAgICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZvciAoIGkgPSAwOyBpIDwgc3RhY2subGVuZ3RoOyBpKysgKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoIHN0YWNrWyBpIF0uaW5kZW50ICE9IG1bMV0gKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgIGxpc3QgPSBzdGFja1sgaSBdLmxpc3Q7XG4gICAgICAgICAgICAgICAgICBzdGFjay5zcGxpY2UoIGkrMSwgc3RhY2subGVuZ3RoIC0gKGkrMSkgKTtcbiAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghZm91bmQpIHtcbiAgICAgICAgICAgICAgICAgIC8vcHJpbnQoXCJub3QgZm91bmQuIGw6XCIsIHVuZXZhbChsKSk7XG4gICAgICAgICAgICAgICAgICB3YW50ZWRfZGVwdGgrKztcbiAgICAgICAgICAgICAgICAgIGlmICggd2FudGVkX2RlcHRoIDw9IHN0YWNrLmxlbmd0aCApIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhY2suc3BsaWNlKHdhbnRlZF9kZXB0aCwgc3RhY2subGVuZ3RoIC0gd2FudGVkX2RlcHRoKTtcbiAgICAgICAgICAgICAgICAgICAgLy9wcmludChcIkRlc2lyZWQgZGVwdGggbm93XCIsIHdhbnRlZF9kZXB0aCwgXCJzdGFjazpcIiwgc3RhY2subGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgbGlzdCA9IHN0YWNrW3dhbnRlZF9kZXB0aC0xXS5saXN0O1xuICAgICAgICAgICAgICAgICAgICAvL3ByaW50KFwibGlzdDpcIiwgdW5ldmFsKGxpc3QpICk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy9wcmludCAoXCJtYWRlIG5ldyBzdGFjayBmb3IgbWVzc3kgaW5kZW50XCIpO1xuICAgICAgICAgICAgICAgICAgICBsaXN0ID0gbWFrZV9saXN0KG0pO1xuICAgICAgICAgICAgICAgICAgICBsYXN0X2xpLnB1c2gobGlzdCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy9wcmludCggdW5ldmFsKGxpc3QpLCBcImxhc3RcIiwgbGlzdCA9PT0gc3RhY2tbc3RhY2subGVuZ3RoLTFdLmxpc3QgKTtcbiAgICAgICAgICAgICAgICBsYXN0X2xpID0gWyBcImxpc3RpdGVtXCIgXTtcbiAgICAgICAgICAgICAgICBsaXN0LnB1c2gobGFzdF9saSk7XG4gICAgICAgICAgICAgIH0gLy8gZW5kIGRlcHRoIG9mIHNoZW5lZ2FpbnNcbiAgICAgICAgICAgICAgbmwgPSBcIlwiO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBZGQgY29udGVudFxuICAgICAgICAgICAgaWYgKCBsLmxlbmd0aCA+IG1bMF0ubGVuZ3RoICkge1xuICAgICAgICAgICAgICBsaV9hY2N1bXVsYXRlICs9IG5sICsgbC5zdWJzdHIoIG1bMF0ubGVuZ3RoICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyB0aWdodF9zZWFyY2hcblxuICAgICAgICAgIGlmICggbGlfYWNjdW11bGF0ZS5sZW5ndGggKSB7XG4gICAgICAgICAgICBhZGQoIGxhc3RfbGksIGxvb3NlLCB0aGlzLnByb2Nlc3NJbmxpbmUoIGxpX2FjY3VtdWxhdGUgKSwgbmwgKTtcbiAgICAgICAgICAgIC8vIExvb3NlIG1vZGUgd2lsbCBoYXZlIGJlZW4gZGVhbHQgd2l0aC4gUmVzZXQgaXRcbiAgICAgICAgICAgIGxvb3NlID0gZmFsc2U7XG4gICAgICAgICAgICBsaV9hY2N1bXVsYXRlID0gXCJcIjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBMb29rIGF0IHRoZSBuZXh0IGJsb2NrIC0gd2UgbWlnaHQgaGF2ZSBhIGxvb3NlIGxpc3QuIE9yIGFuIGV4dHJhXG4gICAgICAgICAgLy8gcGFyYWdyYXBoIGZvciB0aGUgY3VycmVudCBsaVxuICAgICAgICAgIHZhciBjb250YWluZWQgPSBnZXRfY29udGFpbmVkX2Jsb2Nrcyggc3RhY2subGVuZ3RoLCBuZXh0ICk7XG5cbiAgICAgICAgICAvLyBEZWFsIHdpdGggY29kZSBibG9ja3Mgb3IgcHJvcGVybHkgbmVzdGVkIGxpc3RzXG4gICAgICAgICAgaWYgKCBjb250YWluZWQubGVuZ3RoID4gMCApIHtcbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBhbGwgbGlzdGl0ZW1zIHVwIHRoZSBzdGFjayBhcmUgcGFyYWdyYXBoc1xuICAgICAgICAgICAgZm9yRWFjaCggc3RhY2ssIHBhcmFncmFwaGlmeSwgdGhpcyk7XG5cbiAgICAgICAgICAgIGxhc3RfbGkucHVzaC5hcHBseSggbGFzdF9saSwgdGhpcy50b1RyZWUoIGNvbnRhaW5lZCwgW10gKSApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBuZXh0X2Jsb2NrID0gbmV4dFswXSAmJiBuZXh0WzBdLnZhbHVlT2YoKSB8fCBcIlwiO1xuXG4gICAgICAgICAgaWYgKCBuZXh0X2Jsb2NrLm1hdGNoKGlzX2xpc3RfcmUpIHx8IG5leHRfYmxvY2subWF0Y2goIC9eIC8gKSApIHtcbiAgICAgICAgICAgIGJsb2NrID0gbmV4dC5zaGlmdCgpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgYW4gSFIgZm9sbG93aW5nIGEgbGlzdDogZmVhdHVyZXMvbGlzdHMvaHJfYWJ1dHRpbmdcbiAgICAgICAgICAgIHZhciBociA9IHRoaXMuZGlhbGVjdC5ibG9jay5ob3JpelJ1bGUoIGJsb2NrLCBuZXh0ICk7XG5cbiAgICAgICAgICAgIGlmICggaHIgKSB7XG4gICAgICAgICAgICAgIHJldC5wdXNoLmFwcGx5KHJldCwgaHIpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIGFsbCBsaXN0aXRlbXMgdXAgdGhlIHN0YWNrIGFyZSBwYXJhZ3JhcGhzXG4gICAgICAgICAgICBmb3JFYWNoKCBzdGFjaywgcGFyYWdyYXBoaWZ5LCB0aGlzKTtcblxuICAgICAgICAgICAgbG9vc2UgPSB0cnVlO1xuICAgICAgICAgICAgY29udGludWUgbG9vc2Vfc2VhcmNoO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfSAvLyBsb29zZV9zZWFyY2hcblxuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfTtcbiAgICB9KSgpLFxuXG4gICAgYmxvY2txdW90ZTogZnVuY3Rpb24gYmxvY2txdW90ZSggYmxvY2ssIG5leHQgKSB7XG4gICAgICBpZiAoICFibG9jay5tYXRjaCggL14+L20gKSApXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIHZhciBqc29ubWwgPSBbXTtcblxuICAgICAgLy8gc2VwYXJhdGUgb3V0IHRoZSBsZWFkaW5nIGFidXR0aW5nIGJsb2NrLCBpZiBhbnkuIEkuZS4gaW4gdGhpcyBjYXNlOlxuICAgICAgLy9cbiAgICAgIC8vICBhXG4gICAgICAvLyAgPiBiXG4gICAgICAvL1xuICAgICAgaWYgKCBibG9ja1sgMCBdICE9IFwiPlwiICkge1xuICAgICAgICB2YXIgbGluZXMgPSBibG9jay5zcGxpdCggL1xcbi8gKSxcbiAgICAgICAgICAgIHByZXYgPSBbXSxcbiAgICAgICAgICAgIGxpbmVfbm8gPSBibG9jay5saW5lTnVtYmVyO1xuXG4gICAgICAgIC8vIGtlZXAgc2hpZnRpbmcgbGluZXMgdW50aWwgeW91IGZpbmQgYSBjcm90Y2hldFxuICAgICAgICB3aGlsZSAoIGxpbmVzLmxlbmd0aCAmJiBsaW5lc1sgMCBdWyAwIF0gIT0gXCI+XCIgKSB7XG4gICAgICAgICAgICBwcmV2LnB1c2goIGxpbmVzLnNoaWZ0KCkgKTtcbiAgICAgICAgICAgIGxpbmVfbm8rKztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhYnV0dGluZyA9IG1rX2Jsb2NrKCBwcmV2LmpvaW4oIFwiXFxuXCIgKSwgXCJcXG5cIiwgYmxvY2subGluZU51bWJlciApO1xuICAgICAgICBqc29ubWwucHVzaC5hcHBseSgganNvbm1sLCB0aGlzLnByb2Nlc3NCbG9jayggYWJ1dHRpbmcsIFtdICkgKTtcbiAgICAgICAgLy8gcmVhc3NlbWJsZSBuZXcgYmxvY2sgb2YganVzdCBibG9jayBxdW90ZXMhXG4gICAgICAgIGJsb2NrID0gbWtfYmxvY2soIGxpbmVzLmpvaW4oIFwiXFxuXCIgKSwgYmxvY2sudHJhaWxpbmcsIGxpbmVfbm8gKTtcbiAgICAgIH1cblxuXG4gICAgICAvLyBpZiB0aGUgbmV4dCBibG9jayBpcyBhbHNvIGEgYmxvY2txdW90ZSBtZXJnZSBpdCBpblxuICAgICAgd2hpbGUgKCBuZXh0Lmxlbmd0aCAmJiBuZXh0WyAwIF1bIDAgXSA9PSBcIj5cIiApIHtcbiAgICAgICAgdmFyIGIgPSBuZXh0LnNoaWZ0KCk7XG4gICAgICAgIGJsb2NrID0gbWtfYmxvY2soIGJsb2NrICsgYmxvY2sudHJhaWxpbmcgKyBiLCBiLnRyYWlsaW5nLCBibG9jay5saW5lTnVtYmVyICk7XG4gICAgICB9XG5cbiAgICAgIC8vIFN0cmlwIG9mZiB0aGUgbGVhZGluZyBcIj4gXCIgYW5kIHJlLXByb2Nlc3MgYXMgYSBibG9jay5cbiAgICAgIHZhciBpbnB1dCA9IGJsb2NrLnJlcGxhY2UoIC9ePiA/L2dtLCBcIlwiICksXG4gICAgICAgICAgb2xkX3RyZWUgPSB0aGlzLnRyZWUsXG4gICAgICAgICAgcHJvY2Vzc2VkQmxvY2sgPSB0aGlzLnRvVHJlZSggaW5wdXQsIFsgXCJibG9ja3F1b3RlXCIgXSApLFxuICAgICAgICAgIGF0dHIgPSBleHRyYWN0X2F0dHIoIHByb2Nlc3NlZEJsb2NrICk7XG5cbiAgICAgIC8vIElmIGFueSBsaW5rIHJlZmVyZW5jZXMgd2VyZSBmb3VuZCBnZXQgcmlkIG9mIHRoZW1cbiAgICAgIGlmICggYXR0ciAmJiBhdHRyLnJlZmVyZW5jZXMgKSB7XG4gICAgICAgIGRlbGV0ZSBhdHRyLnJlZmVyZW5jZXM7XG4gICAgICAgIC8vIEFuZCB0aGVuIHJlbW92ZSB0aGUgYXR0cmlidXRlIG9iamVjdCBpZiBpdCdzIGVtcHR5XG4gICAgICAgIGlmICggaXNFbXB0eSggYXR0ciApICkge1xuICAgICAgICAgIHByb2Nlc3NlZEJsb2NrLnNwbGljZSggMSwgMSApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGpzb25tbC5wdXNoKCBwcm9jZXNzZWRCbG9jayApO1xuICAgICAgcmV0dXJuIGpzb25tbDtcbiAgICB9LFxuXG4gICAgcmVmZXJlbmNlRGVmbjogZnVuY3Rpb24gcmVmZXJlbmNlRGVmbiggYmxvY2ssIG5leHQpIHtcbiAgICAgIHZhciByZSA9IC9eXFxzKlxcWyguKj8pXFxdOlxccyooXFxTKykoPzpcXHMrKD86KFsnXCJdKSguKj8pXFwzfFxcKCguKj8pXFwpKSk/XFxuPy87XG4gICAgICAvLyBpbnRlcmVzdGluZyBtYXRjaGVzIGFyZSBbICwgcmVmX2lkLCB1cmwsICwgdGl0bGUsIHRpdGxlIF1cblxuICAgICAgaWYgKCAhYmxvY2subWF0Y2gocmUpIClcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgLy8gbWFrZSBhbiBhdHRyaWJ1dGUgbm9kZSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICBpZiAoICFleHRyYWN0X2F0dHIoIHRoaXMudHJlZSApICkge1xuICAgICAgICB0aGlzLnRyZWUuc3BsaWNlKCAxLCAwLCB7fSApO1xuICAgICAgfVxuXG4gICAgICB2YXIgYXR0cnMgPSBleHRyYWN0X2F0dHIoIHRoaXMudHJlZSApO1xuXG4gICAgICAvLyBtYWtlIGEgcmVmZXJlbmNlcyBoYXNoIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgIGlmICggYXR0cnMucmVmZXJlbmNlcyA9PT0gdW5kZWZpbmVkICkge1xuICAgICAgICBhdHRycy5yZWZlcmVuY2VzID0ge307XG4gICAgICB9XG5cbiAgICAgIHZhciBiID0gdGhpcy5sb29wX3JlX292ZXJfYmxvY2socmUsIGJsb2NrLCBmdW5jdGlvbiggbSApIHtcblxuICAgICAgICBpZiAoIG1bMl0gJiYgbVsyXVswXSA9PSBcIjxcIiAmJiBtWzJdW21bMl0ubGVuZ3RoLTFdID09IFwiPlwiIClcbiAgICAgICAgICBtWzJdID0gbVsyXS5zdWJzdHJpbmcoIDEsIG1bMl0ubGVuZ3RoIC0gMSApO1xuXG4gICAgICAgIHZhciByZWYgPSBhdHRycy5yZWZlcmVuY2VzWyBtWzFdLnRvTG93ZXJDYXNlKCkgXSA9IHtcbiAgICAgICAgICBocmVmOiBtWzJdXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKCBtWzRdICE9PSB1bmRlZmluZWQgKVxuICAgICAgICAgIHJlZi50aXRsZSA9IG1bNF07XG4gICAgICAgIGVsc2UgaWYgKCBtWzVdICE9PSB1bmRlZmluZWQgKVxuICAgICAgICAgIHJlZi50aXRsZSA9IG1bNV07XG5cbiAgICAgIH0gKTtcblxuICAgICAgaWYgKCBiLmxlbmd0aCApXG4gICAgICAgIG5leHQudW5zaGlmdCggbWtfYmxvY2soIGIsIGJsb2NrLnRyYWlsaW5nICkgKTtcblxuICAgICAgcmV0dXJuIFtdO1xuICAgIH0sXG5cbiAgICBwYXJhOiBmdW5jdGlvbiBwYXJhKCBibG9jaywgbmV4dCApIHtcbiAgICAgIC8vIGV2ZXJ5dGhpbmcncyBhIHBhcmEhXG4gICAgICByZXR1cm4gWyBbXCJwYXJhXCJdLmNvbmNhdCggdGhpcy5wcm9jZXNzSW5saW5lKCBibG9jayApICkgXTtcbiAgICB9XG4gIH1cbn07XG5cbk1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5pbmxpbmUgPSB7XG5cbiAgICBfX29uZUVsZW1lbnRfXzogZnVuY3Rpb24gb25lRWxlbWVudCggdGV4dCwgcGF0dGVybnNfb3JfcmUsIHByZXZpb3VzX25vZGVzICkge1xuICAgICAgdmFyIG0sXG4gICAgICAgICAgcmVzLFxuICAgICAgICAgIGxhc3RJbmRleCA9IDA7XG5cbiAgICAgIHBhdHRlcm5zX29yX3JlID0gcGF0dGVybnNfb3JfcmUgfHwgdGhpcy5kaWFsZWN0LmlubGluZS5fX3BhdHRlcm5zX187XG4gICAgICB2YXIgcmUgPSBuZXcgUmVnRXhwKCBcIihbXFxcXHNcXFxcU10qPykoXCIgKyAocGF0dGVybnNfb3JfcmUuc291cmNlIHx8IHBhdHRlcm5zX29yX3JlKSArIFwiKVwiICk7XG5cbiAgICAgIG0gPSByZS5leGVjKCB0ZXh0ICk7XG4gICAgICBpZiAoIW0pIHtcbiAgICAgICAgLy8gSnVzdCBib3JpbmcgdGV4dFxuICAgICAgICByZXR1cm4gWyB0ZXh0Lmxlbmd0aCwgdGV4dCBdO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAoIG1bMV0gKSB7XG4gICAgICAgIC8vIFNvbWUgdW4taW50ZXJlc3RpbmcgdGV4dCBtYXRjaGVkLiBSZXR1cm4gdGhhdCBmaXJzdFxuICAgICAgICByZXR1cm4gWyBtWzFdLmxlbmd0aCwgbVsxXSBdO1xuICAgICAgfVxuXG4gICAgICB2YXIgcmVzO1xuICAgICAgaWYgKCBtWzJdIGluIHRoaXMuZGlhbGVjdC5pbmxpbmUgKSB7XG4gICAgICAgIHJlcyA9IHRoaXMuZGlhbGVjdC5pbmxpbmVbIG1bMl0gXS5jYWxsKFxuICAgICAgICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgICAgICAgIHRleHQuc3Vic3RyKCBtLmluZGV4ICksIG0sIHByZXZpb3VzX25vZGVzIHx8IFtdICk7XG4gICAgICB9XG4gICAgICAvLyBEZWZhdWx0IGZvciBub3cgdG8gbWFrZSBkZXYgZWFzaWVyLiBqdXN0IHNsdXJwIHNwZWNpYWwgYW5kIG91dHB1dCBpdC5cbiAgICAgIHJlcyA9IHJlcyB8fCBbIG1bMl0ubGVuZ3RoLCBtWzJdIF07XG4gICAgICByZXR1cm4gcmVzO1xuICAgIH0sXG5cbiAgICBfX2NhbGxfXzogZnVuY3Rpb24gaW5saW5lKCB0ZXh0LCBwYXR0ZXJucyApIHtcblxuICAgICAgdmFyIG91dCA9IFtdLFxuICAgICAgICAgIHJlcztcblxuICAgICAgZnVuY3Rpb24gYWRkKHgpIHtcbiAgICAgICAgLy9EOnNlbGYuZGVidWcoXCIgIGFkZGluZyBvdXRwdXRcIiwgdW5ldmFsKHgpKTtcbiAgICAgICAgaWYgKCB0eXBlb2YgeCA9PSBcInN0cmluZ1wiICYmIHR5cGVvZiBvdXRbb3V0Lmxlbmd0aC0xXSA9PSBcInN0cmluZ1wiIClcbiAgICAgICAgICBvdXRbIG91dC5sZW5ndGgtMSBdICs9IHg7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBvdXQucHVzaCh4KTtcbiAgICAgIH1cblxuICAgICAgd2hpbGUgKCB0ZXh0Lmxlbmd0aCA+IDAgKSB7XG4gICAgICAgIHJlcyA9IHRoaXMuZGlhbGVjdC5pbmxpbmUuX19vbmVFbGVtZW50X18uY2FsbCh0aGlzLCB0ZXh0LCBwYXR0ZXJucywgb3V0ICk7XG4gICAgICAgIHRleHQgPSB0ZXh0LnN1YnN0ciggcmVzLnNoaWZ0KCkgKTtcbiAgICAgICAgZm9yRWFjaChyZXMsIGFkZCApXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvdXQ7XG4gICAgfSxcblxuICAgIC8vIFRoZXNlIGNoYXJhY3RlcnMgYXJlIGludGVyc3RpbmcgZWxzZXdoZXJlLCBzbyBoYXZlIHJ1bGVzIGZvciB0aGVtIHNvIHRoYXRcbiAgICAvLyBjaHVua3Mgb2YgcGxhaW4gdGV4dCBibG9ja3MgZG9uJ3QgaW5jbHVkZSB0aGVtXG4gICAgXCJdXCI6IGZ1bmN0aW9uICgpIHt9LFxuICAgIFwifVwiOiBmdW5jdGlvbiAoKSB7fSxcblxuICAgIF9fZXNjYXBlX18gOiAvXlxcXFxbXFxcXGBcXCpfe31cXFtcXF0oKSNcXCsuIVxcLV0vLFxuXG4gICAgXCJcXFxcXCI6IGZ1bmN0aW9uIGVzY2FwZWQoIHRleHQgKSB7XG4gICAgICAvLyBbIGxlbmd0aCBvZiBpbnB1dCBwcm9jZXNzZWQsIG5vZGUvY2hpbGRyZW4gdG8gYWRkLi4uIF1cbiAgICAgIC8vIE9ubHkgZXNhY2FwZTogXFwgYCAqIF8geyB9IFsgXSAoICkgIyAqICsgLSAuICFcbiAgICAgIGlmICggdGhpcy5kaWFsZWN0LmlubGluZS5fX2VzY2FwZV9fLmV4ZWMoIHRleHQgKSApXG4gICAgICAgIHJldHVybiBbIDIsIHRleHQuY2hhckF0KCAxICkgXTtcbiAgICAgIGVsc2VcbiAgICAgICAgLy8gTm90IGFuIGVzYWNwZVxuICAgICAgICByZXR1cm4gWyAxLCBcIlxcXFxcIiBdO1xuICAgIH0sXG5cbiAgICBcIiFbXCI6IGZ1bmN0aW9uIGltYWdlKCB0ZXh0ICkge1xuXG4gICAgICAvLyBVbmxpa2UgaW1hZ2VzLCBhbHQgdGV4dCBpcyBwbGFpbiB0ZXh0IG9ubHkuIG5vIG90aGVyIGVsZW1lbnRzIGFyZVxuICAgICAgLy8gYWxsb3dlZCBpbiB0aGVyZVxuXG4gICAgICAvLyAhW0FsdCB0ZXh0XSgvcGF0aC90by9pbWcuanBnIFwiT3B0aW9uYWwgdGl0bGVcIilcbiAgICAgIC8vICAgICAgMSAgICAgICAgICAyICAgICAgICAgICAgMyAgICAgICA0ICAgICAgICAgPC0tLSBjYXB0dXJlc1xuICAgICAgdmFyIG0gPSB0ZXh0Lm1hdGNoKCAvXiFcXFsoLio/KVxcXVsgXFx0XSpcXChbIFxcdF0qKFteXCIpXSo/KSg/OlsgXFx0XSsoW1wiJ10pKC4qPylcXDMpP1sgXFx0XSpcXCkvICk7XG5cbiAgICAgIGlmICggbSApIHtcbiAgICAgICAgaWYgKCBtWzJdICYmIG1bMl1bMF0gPT0gXCI8XCIgJiYgbVsyXVttWzJdLmxlbmd0aC0xXSA9PSBcIj5cIiApXG4gICAgICAgICAgbVsyXSA9IG1bMl0uc3Vic3RyaW5nKCAxLCBtWzJdLmxlbmd0aCAtIDEgKTtcblxuICAgICAgICBtWzJdID0gdGhpcy5kaWFsZWN0LmlubGluZS5fX2NhbGxfXy5jYWxsKCB0aGlzLCBtWzJdLCAvXFxcXC8gKVswXTtcblxuICAgICAgICB2YXIgYXR0cnMgPSB7IGFsdDogbVsxXSwgaHJlZjogbVsyXSB8fCBcIlwiIH07XG4gICAgICAgIGlmICggbVs0XSAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIGF0dHJzLnRpdGxlID0gbVs0XTtcblxuICAgICAgICByZXR1cm4gWyBtWzBdLmxlbmd0aCwgWyBcImltZ1wiLCBhdHRycyBdIF07XG4gICAgICB9XG5cbiAgICAgIC8vICFbQWx0IHRleHRdW2lkXVxuICAgICAgbSA9IHRleHQubWF0Y2goIC9eIVxcWyguKj8pXFxdWyBcXHRdKlxcWyguKj8pXFxdLyApO1xuXG4gICAgICBpZiAoIG0gKSB7XG4gICAgICAgIC8vIFdlIGNhbid0IGNoZWNrIGlmIHRoZSByZWZlcmVuY2UgaXMga25vd24gaGVyZSBhcyBpdCBsaWtlbHkgd29udCBiZVxuICAgICAgICAvLyBmb3VuZCB0aWxsIGFmdGVyLiBDaGVjayBpdCBpbiBtZCB0cmVlLT5obXRsIHRyZWUgY29udmVyc2lvblxuICAgICAgICByZXR1cm4gWyBtWzBdLmxlbmd0aCwgWyBcImltZ19yZWZcIiwgeyBhbHQ6IG1bMV0sIHJlZjogbVsyXS50b0xvd2VyQ2FzZSgpLCBvcmlnaW5hbDogbVswXSB9IF0gXTtcbiAgICAgIH1cblxuICAgICAgLy8gSnVzdCBjb25zdW1lIHRoZSAnIVsnXG4gICAgICByZXR1cm4gWyAyLCBcIiFbXCIgXTtcbiAgICB9LFxuXG4gICAgXCJbXCI6IGZ1bmN0aW9uIGxpbmsoIHRleHQgKSB7XG5cbiAgICAgIHZhciBvcmlnID0gU3RyaW5nKHRleHQpO1xuICAgICAgLy8gSW5saW5lIGNvbnRlbnQgaXMgcG9zc2libGUgaW5zaWRlIGBsaW5rIHRleHRgXG4gICAgICB2YXIgcmVzID0gTWFya2Rvd24uRGlhbGVjdEhlbHBlcnMuaW5saW5lX3VudGlsX2NoYXIuY2FsbCggdGhpcywgdGV4dC5zdWJzdHIoMSksIFwiXVwiICk7XG5cbiAgICAgIC8vIE5vIGNsb3NpbmcgJ10nIGZvdW5kLiBKdXN0IGNvbnN1bWUgdGhlIFtcbiAgICAgIGlmICggIXJlcyApIHJldHVybiBbIDEsIFwiW1wiIF07XG5cbiAgICAgIHZhciBjb25zdW1lZCA9IDEgKyByZXNbIDAgXSxcbiAgICAgICAgICBjaGlsZHJlbiA9IHJlc1sgMSBdLFxuICAgICAgICAgIGxpbmssXG4gICAgICAgICAgYXR0cnM7XG5cbiAgICAgIC8vIEF0IHRoaXMgcG9pbnQgdGhlIGZpcnN0IFsuLi5dIGhhcyBiZWVuIHBhcnNlZC4gU2VlIHdoYXQgZm9sbG93cyB0byBmaW5kXG4gICAgICAvLyBvdXQgd2hpY2gga2luZCBvZiBsaW5rIHdlIGFyZSAocmVmZXJlbmNlIG9yIGRpcmVjdCB1cmwpXG4gICAgICB0ZXh0ID0gdGV4dC5zdWJzdHIoIGNvbnN1bWVkICk7XG5cbiAgICAgIC8vIFtsaW5rIHRleHRdKC9wYXRoL3RvL2ltZy5qcGcgXCJPcHRpb25hbCB0aXRsZVwiKVxuICAgICAgLy8gICAgICAgICAgICAgICAgIDEgICAgICAgICAgICAyICAgICAgIDMgICAgICAgICA8LS0tIGNhcHR1cmVzXG4gICAgICAvLyBUaGlzIHdpbGwgY2FwdHVyZSB1cCB0byB0aGUgbGFzdCBwYXJlbiBpbiB0aGUgYmxvY2suIFdlIHRoZW4gcHVsbFxuICAgICAgLy8gYmFjayBiYXNlZCBvbiBpZiB0aGVyZSBhIG1hdGNoaW5nIG9uZXMgaW4gdGhlIHVybFxuICAgICAgLy8gICAgKFtoZXJlXSgvdXJsLyh0ZXN0KSlcbiAgICAgIC8vIFRoZSBwYXJlbnMgaGF2ZSB0byBiZSBiYWxhbmNlZFxuICAgICAgdmFyIG0gPSB0ZXh0Lm1hdGNoKCAvXlxccypcXChbIFxcdF0qKFteXCInXSopKD86WyBcXHRdKyhbXCInXSkoLio/KVxcMik/WyBcXHRdKlxcKS8gKTtcbiAgICAgIGlmICggbSApIHtcbiAgICAgICAgdmFyIHVybCA9IG1bMV07XG4gICAgICAgIGNvbnN1bWVkICs9IG1bMF0ubGVuZ3RoO1xuXG4gICAgICAgIGlmICggdXJsICYmIHVybFswXSA9PSBcIjxcIiAmJiB1cmxbdXJsLmxlbmd0aC0xXSA9PSBcIj5cIiApXG4gICAgICAgICAgdXJsID0gdXJsLnN1YnN0cmluZyggMSwgdXJsLmxlbmd0aCAtIDEgKTtcblxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBhIHRpdGxlIHdlIGRvbid0IGhhdmUgdG8gd29ycnkgYWJvdXQgcGFyZW5zIGluIHRoZSB1cmxcbiAgICAgICAgaWYgKCAhbVszXSApIHtcbiAgICAgICAgICB2YXIgb3Blbl9wYXJlbnMgPSAxOyAvLyBPbmUgb3BlbiB0aGF0IGlzbid0IGluIHRoZSBjYXB0dXJlXG4gICAgICAgICAgZm9yICggdmFyIGxlbiA9IDA7IGxlbiA8IHVybC5sZW5ndGg7IGxlbisrICkge1xuICAgICAgICAgICAgc3dpdGNoICggdXJsW2xlbl0gKSB7XG4gICAgICAgICAgICBjYXNlIFwiKFwiOlxuICAgICAgICAgICAgICBvcGVuX3BhcmVucysrO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCIpXCI6XG4gICAgICAgICAgICAgIGlmICggLS1vcGVuX3BhcmVucyA9PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3VtZWQgLT0gdXJsLmxlbmd0aCAtIGxlbjtcbiAgICAgICAgICAgICAgICB1cmwgPSB1cmwuc3Vic3RyaW5nKDAsIGxlbik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvY2VzcyBlc2NhcGVzIG9ubHlcbiAgICAgICAgdXJsID0gdGhpcy5kaWFsZWN0LmlubGluZS5fX2NhbGxfXy5jYWxsKCB0aGlzLCB1cmwsIC9cXFxcLyApWzBdO1xuXG4gICAgICAgIGF0dHJzID0geyBocmVmOiB1cmwgfHwgXCJcIiB9O1xuICAgICAgICBpZiAoIG1bM10gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICBhdHRycy50aXRsZSA9IG1bM107XG5cbiAgICAgICAgbGluayA9IFsgXCJsaW5rXCIsIGF0dHJzIF0uY29uY2F0KCBjaGlsZHJlbiApO1xuICAgICAgICByZXR1cm4gWyBjb25zdW1lZCwgbGluayBdO1xuICAgICAgfVxuXG4gICAgICAvLyBbQWx0IHRleHRdW2lkXVxuICAgICAgLy8gW0FsdCB0ZXh0XSBbaWRdXG4gICAgICBtID0gdGV4dC5tYXRjaCggL15cXHMqXFxbKC4qPylcXF0vICk7XG5cbiAgICAgIGlmICggbSApIHtcblxuICAgICAgICBjb25zdW1lZCArPSBtWyAwIF0ubGVuZ3RoO1xuXG4gICAgICAgIC8vIFtsaW5rc11bXSB1c2VzIGxpbmtzIGFzIGl0cyByZWZlcmVuY2VcbiAgICAgICAgYXR0cnMgPSB7IHJlZjogKCBtWyAxIF0gfHwgU3RyaW5nKGNoaWxkcmVuKSApLnRvTG93ZXJDYXNlKCksICBvcmlnaW5hbDogb3JpZy5zdWJzdHIoIDAsIGNvbnN1bWVkICkgfTtcblxuICAgICAgICBsaW5rID0gWyBcImxpbmtfcmVmXCIsIGF0dHJzIF0uY29uY2F0KCBjaGlsZHJlbiApO1xuXG4gICAgICAgIC8vIFdlIGNhbid0IGNoZWNrIGlmIHRoZSByZWZlcmVuY2UgaXMga25vd24gaGVyZSBhcyBpdCBsaWtlbHkgd29udCBiZVxuICAgICAgICAvLyBmb3VuZCB0aWxsIGFmdGVyLiBDaGVjayBpdCBpbiBtZCB0cmVlLT5obXRsIHRyZWUgY29udmVyc2lvbi5cbiAgICAgICAgLy8gU3RvcmUgdGhlIG9yaWdpbmFsIHNvIHRoYXQgY29udmVyc2lvbiBjYW4gcmV2ZXJ0IGlmIHRoZSByZWYgaXNuJ3QgZm91bmQuXG4gICAgICAgIHJldHVybiBbIGNvbnN1bWVkLCBsaW5rIF07XG4gICAgICB9XG5cbiAgICAgIC8vIFtpZF1cbiAgICAgIC8vIE9ubHkgaWYgaWQgaXMgcGxhaW4gKG5vIGZvcm1hdHRpbmcuKVxuICAgICAgaWYgKCBjaGlsZHJlbi5sZW5ndGggPT0gMSAmJiB0eXBlb2YgY2hpbGRyZW5bMF0gPT0gXCJzdHJpbmdcIiApIHtcblxuICAgICAgICBhdHRycyA9IHsgcmVmOiBjaGlsZHJlblswXS50b0xvd2VyQ2FzZSgpLCAgb3JpZ2luYWw6IG9yaWcuc3Vic3RyKCAwLCBjb25zdW1lZCApIH07XG4gICAgICAgIGxpbmsgPSBbIFwibGlua19yZWZcIiwgYXR0cnMsIGNoaWxkcmVuWzBdIF07XG4gICAgICAgIHJldHVybiBbIGNvbnN1bWVkLCBsaW5rIF07XG4gICAgICB9XG5cbiAgICAgIC8vIEp1c3QgY29uc3VtZSB0aGUgXCJbXCJcbiAgICAgIHJldHVybiBbIDEsIFwiW1wiIF07XG4gICAgfSxcblxuXG4gICAgXCI8XCI6IGZ1bmN0aW9uIGF1dG9MaW5rKCB0ZXh0ICkge1xuICAgICAgdmFyIG07XG5cbiAgICAgIGlmICggKCBtID0gdGV4dC5tYXRjaCggL148KD86KChodHRwcz98ZnRwfG1haWx0byk6W14+XSspfCguKj9ALio/XFwuW2EtekEtWl0rKSk+LyApICkgIT0gbnVsbCApIHtcbiAgICAgICAgaWYgKCBtWzNdICkge1xuICAgICAgICAgIHJldHVybiBbIG1bMF0ubGVuZ3RoLCBbIFwibGlua1wiLCB7IGhyZWY6IFwibWFpbHRvOlwiICsgbVszXSB9LCBtWzNdIF0gXTtcblxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCBtWzJdID09IFwibWFpbHRvXCIgKSB7XG4gICAgICAgICAgcmV0dXJuIFsgbVswXS5sZW5ndGgsIFsgXCJsaW5rXCIsIHsgaHJlZjogbVsxXSB9LCBtWzFdLnN1YnN0cihcIm1haWx0bzpcIi5sZW5ndGggKSBdIF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZVxuICAgICAgICAgIHJldHVybiBbIG1bMF0ubGVuZ3RoLCBbIFwibGlua1wiLCB7IGhyZWY6IG1bMV0gfSwgbVsxXSBdIF07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBbIDEsIFwiPFwiIF07XG4gICAgfSxcblxuICAgIFwiYFwiOiBmdW5jdGlvbiBpbmxpbmVDb2RlKCB0ZXh0ICkge1xuICAgICAgLy8gSW5saW5lIGNvZGUgYmxvY2suIGFzIG1hbnkgYmFja3RpY2tzIGFzIHlvdSBsaWtlIHRvIHN0YXJ0IGl0XG4gICAgICAvLyBBbHdheXMgc2tpcCBvdmVyIHRoZSBvcGVuaW5nIHRpY2tzLlxuICAgICAgdmFyIG0gPSB0ZXh0Lm1hdGNoKCAvKGArKSgoW1xcc1xcU10qPylcXDEpLyApO1xuXG4gICAgICBpZiAoIG0gJiYgbVsyXSApXG4gICAgICAgIHJldHVybiBbIG1bMV0ubGVuZ3RoICsgbVsyXS5sZW5ndGgsIFsgXCJpbmxpbmVjb2RlXCIsIG1bM10gXSBdO1xuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIFRPRE86IE5vIG1hdGNoaW5nIGVuZCBjb2RlIGZvdW5kIC0gd2FybiFcbiAgICAgICAgcmV0dXJuIFsgMSwgXCJgXCIgXTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgXCIgIFxcblwiOiBmdW5jdGlvbiBsaW5lQnJlYWsoIHRleHQgKSB7XG4gICAgICByZXR1cm4gWyAzLCBbIFwibGluZWJyZWFrXCIgXSBdO1xuICAgIH1cblxufTtcblxuLy8gTWV0YSBIZWxwZXIvZ2VuZXJhdG9yIG1ldGhvZCBmb3IgZW0gYW5kIHN0cm9uZyBoYW5kbGluZ1xuZnVuY3Rpb24gc3Ryb25nX2VtKCB0YWcsIG1kICkge1xuXG4gIHZhciBzdGF0ZV9zbG90ID0gdGFnICsgXCJfc3RhdGVcIixcbiAgICAgIG90aGVyX3Nsb3QgPSB0YWcgPT0gXCJzdHJvbmdcIiA/IFwiZW1fc3RhdGVcIiA6IFwic3Ryb25nX3N0YXRlXCI7XG5cbiAgZnVuY3Rpb24gQ2xvc2VUYWcobGVuKSB7XG4gICAgdGhpcy5sZW5fYWZ0ZXIgPSBsZW47XG4gICAgdGhpcy5uYW1lID0gXCJjbG9zZV9cIiArIG1kO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICggdGV4dCwgb3JpZ19tYXRjaCApIHtcblxuICAgIGlmICggdGhpc1tzdGF0ZV9zbG90XVswXSA9PSBtZCApIHtcbiAgICAgIC8vIE1vc3QgcmVjZW50IGVtIGlzIG9mIHRoaXMgdHlwZVxuICAgICAgLy9EOnRoaXMuZGVidWcoXCJjbG9zaW5nXCIsIG1kKTtcbiAgICAgIHRoaXNbc3RhdGVfc2xvdF0uc2hpZnQoKTtcblxuICAgICAgLy8gXCJDb25zdW1lXCIgZXZlcnl0aGluZyB0byBnbyBiYWNrIHRvIHRoZSByZWNydXNpb24gaW4gdGhlIGVsc2UtYmxvY2sgYmVsb3dcbiAgICAgIHJldHVyblsgdGV4dC5sZW5ndGgsIG5ldyBDbG9zZVRhZyh0ZXh0Lmxlbmd0aC1tZC5sZW5ndGgpIF07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgLy8gU3RvcmUgYSBjbG9uZSBvZiB0aGUgZW0vc3Ryb25nIHN0YXRlc1xuICAgICAgdmFyIG90aGVyID0gdGhpc1tvdGhlcl9zbG90XS5zbGljZSgpLFxuICAgICAgICAgIHN0YXRlID0gdGhpc1tzdGF0ZV9zbG90XS5zbGljZSgpO1xuXG4gICAgICB0aGlzW3N0YXRlX3Nsb3RdLnVuc2hpZnQobWQpO1xuXG4gICAgICAvL0Q6dGhpcy5kZWJ1Z19pbmRlbnQgKz0gXCIgIFwiO1xuXG4gICAgICAvLyBSZWN1cnNlXG4gICAgICB2YXIgcmVzID0gdGhpcy5wcm9jZXNzSW5saW5lKCB0ZXh0LnN1YnN0ciggbWQubGVuZ3RoICkgKTtcbiAgICAgIC8vRDp0aGlzLmRlYnVnX2luZGVudCA9IHRoaXMuZGVidWdfaW5kZW50LnN1YnN0cigyKTtcblxuICAgICAgdmFyIGxhc3QgPSByZXNbcmVzLmxlbmd0aCAtIDFdO1xuXG4gICAgICAvL0Q6dGhpcy5kZWJ1ZyhcInByb2Nlc3NJbmxpbmUgZnJvbVwiLCB0YWcgKyBcIjogXCIsIHVuZXZhbCggcmVzICkgKTtcblxuICAgICAgdmFyIGNoZWNrID0gdGhpc1tzdGF0ZV9zbG90XS5zaGlmdCgpO1xuICAgICAgaWYgKCBsYXN0IGluc3RhbmNlb2YgQ2xvc2VUYWcgKSB7XG4gICAgICAgIHJlcy5wb3AoKTtcbiAgICAgICAgLy8gV2UgbWF0Y2hlZCEgSHV6emFoLlxuICAgICAgICB2YXIgY29uc3VtZWQgPSB0ZXh0Lmxlbmd0aCAtIGxhc3QubGVuX2FmdGVyO1xuICAgICAgICByZXR1cm4gWyBjb25zdW1lZCwgWyB0YWcgXS5jb25jYXQocmVzKSBdO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIFJlc3RvcmUgdGhlIHN0YXRlIG9mIHRoZSBvdGhlciBraW5kLiBXZSBtaWdodCBoYXZlIG1pc3Rha2VubHkgY2xvc2VkIGl0LlxuICAgICAgICB0aGlzW290aGVyX3Nsb3RdID0gb3RoZXI7XG4gICAgICAgIHRoaXNbc3RhdGVfc2xvdF0gPSBzdGF0ZTtcblxuICAgICAgICAvLyBXZSBjYW4ndCByZXVzZSB0aGUgcHJvY2Vzc2VkIHJlc3VsdCBhcyBpdCBjb3VsZCBoYXZlIHdyb25nIHBhcnNpbmcgY29udGV4dHMgaW4gaXQuXG4gICAgICAgIHJldHVybiBbIG1kLmxlbmd0aCwgbWQgXTtcbiAgICAgIH1cbiAgICB9XG4gIH07IC8vIEVuZCByZXR1cm5lZCBmdW5jdGlvblxufVxuXG5NYXJrZG93bi5kaWFsZWN0cy5HcnViZXIuaW5saW5lW1wiKipcIl0gPSBzdHJvbmdfZW0oXCJzdHJvbmdcIiwgXCIqKlwiKTtcbk1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5pbmxpbmVbXCJfX1wiXSA9IHN0cm9uZ19lbShcInN0cm9uZ1wiLCBcIl9fXCIpO1xuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZVtcIipcIl0gID0gc3Ryb25nX2VtKFwiZW1cIiwgXCIqXCIpO1xuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZVtcIl9cIl0gID0gc3Ryb25nX2VtKFwiZW1cIiwgXCJfXCIpO1xuXG5cbi8vIEJ1aWxkIGRlZmF1bHQgb3JkZXIgZnJvbSBpbnNlcnRpb24gb3JkZXIuXG5NYXJrZG93bi5idWlsZEJsb2NrT3JkZXIgPSBmdW5jdGlvbihkKSB7XG4gIHZhciBvcmQgPSBbXTtcbiAgZm9yICggdmFyIGkgaW4gZCApIHtcbiAgICBpZiAoIGkgPT0gXCJfX29yZGVyX19cIiB8fCBpID09IFwiX19jYWxsX19cIiApIGNvbnRpbnVlO1xuICAgIG9yZC5wdXNoKCBpICk7XG4gIH1cbiAgZC5fX29yZGVyX18gPSBvcmQ7XG59O1xuXG4vLyBCdWlsZCBwYXR0ZXJucyBmb3IgaW5saW5lIG1hdGNoZXJcbk1hcmtkb3duLmJ1aWxkSW5saW5lUGF0dGVybnMgPSBmdW5jdGlvbihkKSB7XG4gIHZhciBwYXR0ZXJucyA9IFtdO1xuXG4gIGZvciAoIHZhciBpIGluIGQgKSB7XG4gICAgLy8gX19mb29fXyBpcyByZXNlcnZlZCBhbmQgbm90IGEgcGF0dGVyblxuICAgIGlmICggaS5tYXRjaCggL15fXy4qX18kLykgKSBjb250aW51ZTtcbiAgICB2YXIgbCA9IGkucmVwbGFjZSggLyhbXFxcXC4qKz98KClcXFtcXF17fV0pL2csIFwiXFxcXCQxXCIgKVxuICAgICAgICAgICAgIC5yZXBsYWNlKCAvXFxuLywgXCJcXFxcblwiICk7XG4gICAgcGF0dGVybnMucHVzaCggaS5sZW5ndGggPT0gMSA/IGwgOiBcIig/OlwiICsgbCArIFwiKVwiICk7XG4gIH1cblxuICBwYXR0ZXJucyA9IHBhdHRlcm5zLmpvaW4oXCJ8XCIpO1xuICBkLl9fcGF0dGVybnNfXyA9IHBhdHRlcm5zO1xuICAvL3ByaW50KFwicGF0dGVybnM6XCIsIHVuZXZhbCggcGF0dGVybnMgKSApO1xuXG4gIHZhciBmbiA9IGQuX19jYWxsX187XG4gIGQuX19jYWxsX18gPSBmdW5jdGlvbih0ZXh0LCBwYXR0ZXJuKSB7XG4gICAgaWYgKCBwYXR0ZXJuICE9IHVuZGVmaW5lZCApIHtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoaXMsIHRleHQsIHBhdHRlcm4pO1xuICAgIH1cbiAgICBlbHNlXG4gICAge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhpcywgdGV4dCwgcGF0dGVybnMpO1xuICAgIH1cbiAgfTtcbn07XG5cbk1hcmtkb3duLkRpYWxlY3RIZWxwZXJzID0ge307XG5NYXJrZG93bi5EaWFsZWN0SGVscGVycy5pbmxpbmVfdW50aWxfY2hhciA9IGZ1bmN0aW9uKCB0ZXh0LCB3YW50ICkge1xuICB2YXIgY29uc3VtZWQgPSAwLFxuICAgICAgbm9kZXMgPSBbXTtcblxuICB3aGlsZSAoIHRydWUgKSB7XG4gICAgaWYgKCB0ZXh0LmNoYXJBdCggY29uc3VtZWQgKSA9PSB3YW50ICkge1xuICAgICAgLy8gRm91bmQgdGhlIGNoYXJhY3RlciB3ZSB3ZXJlIGxvb2tpbmcgZm9yXG4gICAgICBjb25zdW1lZCsrO1xuICAgICAgcmV0dXJuIFsgY29uc3VtZWQsIG5vZGVzIF07XG4gICAgfVxuXG4gICAgaWYgKCBjb25zdW1lZCA+PSB0ZXh0Lmxlbmd0aCApIHtcbiAgICAgIC8vIE5vIGNsb3NpbmcgY2hhciBmb3VuZC4gQWJvcnQuXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgcmVzID0gdGhpcy5kaWFsZWN0LmlubGluZS5fX29uZUVsZW1lbnRfXy5jYWxsKHRoaXMsIHRleHQuc3Vic3RyKCBjb25zdW1lZCApICk7XG4gICAgY29uc3VtZWQgKz0gcmVzWyAwIF07XG4gICAgLy8gQWRkIGFueSByZXR1cm5lZCBub2Rlcy5cbiAgICBub2Rlcy5wdXNoLmFwcGx5KCBub2RlcywgcmVzLnNsaWNlKCAxICkgKTtcbiAgfVxufVxuXG4vLyBIZWxwZXIgZnVuY3Rpb24gdG8gbWFrZSBzdWItY2xhc3NpbmcgYSBkaWFsZWN0IGVhc2llclxuTWFya2Rvd24uc3ViY2xhc3NEaWFsZWN0ID0gZnVuY3Rpb24oIGQgKSB7XG4gIGZ1bmN0aW9uIEJsb2NrKCkge31cbiAgQmxvY2sucHJvdG90eXBlID0gZC5ibG9jaztcbiAgZnVuY3Rpb24gSW5saW5lKCkge31cbiAgSW5saW5lLnByb3RvdHlwZSA9IGQuaW5saW5lO1xuXG4gIHJldHVybiB7IGJsb2NrOiBuZXcgQmxvY2soKSwgaW5saW5lOiBuZXcgSW5saW5lKCkgfTtcbn07XG5cbk1hcmtkb3duLmJ1aWxkQmxvY2tPcmRlciAoIE1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5ibG9jayApO1xuTWFya2Rvd24uYnVpbGRJbmxpbmVQYXR0ZXJucyggTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZSApO1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UgPSBNYXJrZG93bi5zdWJjbGFzc0RpYWxlY3QoIE1hcmtkb3duLmRpYWxlY3RzLkdydWJlciApO1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UucHJvY2Vzc01ldGFIYXNoID0gZnVuY3Rpb24gcHJvY2Vzc01ldGFIYXNoKCBtZXRhX3N0cmluZyApIHtcbiAgdmFyIG1ldGEgPSBzcGxpdF9tZXRhX2hhc2goIG1ldGFfc3RyaW5nICksXG4gICAgICBhdHRyID0ge307XG5cbiAgZm9yICggdmFyIGkgPSAwOyBpIDwgbWV0YS5sZW5ndGg7ICsraSApIHtcbiAgICAvLyBpZDogI2Zvb1xuICAgIGlmICggL14jLy50ZXN0KCBtZXRhWyBpIF0gKSApIHtcbiAgICAgIGF0dHIuaWQgPSBtZXRhWyBpIF0uc3Vic3RyaW5nKCAxICk7XG4gICAgfVxuICAgIC8vIGNsYXNzOiAuZm9vXG4gICAgZWxzZSBpZiAoIC9eXFwuLy50ZXN0KCBtZXRhWyBpIF0gKSApIHtcbiAgICAgIC8vIGlmIGNsYXNzIGFscmVhZHkgZXhpc3RzLCBhcHBlbmQgdGhlIG5ldyBvbmVcbiAgICAgIGlmICggYXR0cltcImNsYXNzXCJdICkge1xuICAgICAgICBhdHRyW1wiY2xhc3NcIl0gPSBhdHRyW1wiY2xhc3NcIl0gKyBtZXRhWyBpIF0ucmVwbGFjZSggLy4vLCBcIiBcIiApO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGF0dHJbXCJjbGFzc1wiXSA9IG1ldGFbIGkgXS5zdWJzdHJpbmcoIDEgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gYXR0cmlidXRlOiBmb289YmFyXG4gICAgZWxzZSBpZiAoIC9cXD0vLnRlc3QoIG1ldGFbIGkgXSApICkge1xuICAgICAgdmFyIHMgPSBtZXRhWyBpIF0uc3BsaXQoIC9cXD0vICk7XG4gICAgICBhdHRyWyBzWyAwIF0gXSA9IHNbIDEgXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYXR0cjtcbn1cblxuZnVuY3Rpb24gc3BsaXRfbWV0YV9oYXNoKCBtZXRhX3N0cmluZyApIHtcbiAgdmFyIG1ldGEgPSBtZXRhX3N0cmluZy5zcGxpdCggXCJcIiApLFxuICAgICAgcGFydHMgPSBbIFwiXCIgXSxcbiAgICAgIGluX3F1b3RlcyA9IGZhbHNlO1xuXG4gIHdoaWxlICggbWV0YS5sZW5ndGggKSB7XG4gICAgdmFyIGxldHRlciA9IG1ldGEuc2hpZnQoKTtcbiAgICBzd2l0Y2ggKCBsZXR0ZXIgKSB7XG4gICAgICBjYXNlIFwiIFwiIDpcbiAgICAgICAgLy8gaWYgd2UncmUgaW4gYSBxdW90ZWQgc2VjdGlvbiwga2VlcCBpdFxuICAgICAgICBpZiAoIGluX3F1b3RlcyApIHtcbiAgICAgICAgICBwYXJ0c1sgcGFydHMubGVuZ3RoIC0gMSBdICs9IGxldHRlcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2UgbWFrZSBhIG5ldyBwYXJ0XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHBhcnRzLnB1c2goIFwiXCIgKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCInXCIgOlxuICAgICAgY2FzZSAnXCInIDpcbiAgICAgICAgLy8gcmV2ZXJzZSB0aGUgcXVvdGVzIGFuZCBtb3ZlIHN0cmFpZ2h0IG9uXG4gICAgICAgIGluX3F1b3RlcyA9ICFpbl9xdW90ZXM7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcIlxcXFxcIiA6XG4gICAgICAgIC8vIHNoaWZ0IG9mZiB0aGUgbmV4dCBsZXR0ZXIgdG8gYmUgdXNlZCBzdHJhaWdodCBhd2F5LlxuICAgICAgICAvLyBpdCB3YXMgZXNjYXBlZCBzbyB3ZSdsbCBrZWVwIGl0IHdoYXRldmVyIGl0IGlzXG4gICAgICAgIGxldHRlciA9IG1ldGEuc2hpZnQoKTtcbiAgICAgIGRlZmF1bHQgOlxuICAgICAgICBwYXJ0c1sgcGFydHMubGVuZ3RoIC0gMSBdICs9IGxldHRlcjtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHBhcnRzO1xufVxuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2suZG9jdW1lbnRfbWV0YSA9IGZ1bmN0aW9uIGRvY3VtZW50X21ldGEoIGJsb2NrLCBuZXh0ICkge1xuICAvLyB3ZSdyZSBvbmx5IGludGVyZXN0ZWQgaW4gdGhlIGZpcnN0IGJsb2NrXG4gIGlmICggYmxvY2subGluZU51bWJlciA+IDEgKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIC8vIGRvY3VtZW50X21ldGEgYmxvY2tzIGNvbnNpc3Qgb2Ygb25lIG9yIG1vcmUgbGluZXMgb2YgYEtleTogVmFsdWVcXG5gXG4gIGlmICggISBibG9jay5tYXRjaCggL14oPzpcXHcrOi4qXFxuKSpcXHcrOi4qJC8gKSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgLy8gbWFrZSBhbiBhdHRyaWJ1dGUgbm9kZSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gIGlmICggIWV4dHJhY3RfYXR0ciggdGhpcy50cmVlICkgKSB7XG4gICAgdGhpcy50cmVlLnNwbGljZSggMSwgMCwge30gKTtcbiAgfVxuXG4gIHZhciBwYWlycyA9IGJsb2NrLnNwbGl0KCAvXFxuLyApO1xuICBmb3IgKCBwIGluIHBhaXJzICkge1xuICAgIHZhciBtID0gcGFpcnNbIHAgXS5tYXRjaCggLyhcXHcrKTpcXHMqKC4qKSQvICksXG4gICAgICAgIGtleSA9IG1bIDEgXS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICB2YWx1ZSA9IG1bIDIgXTtcblxuICAgIHRoaXMudHJlZVsgMSBdWyBrZXkgXSA9IHZhbHVlO1xuICB9XG5cbiAgLy8gZG9jdW1lbnRfbWV0YSBwcm9kdWNlcyBubyBjb250ZW50IVxuICByZXR1cm4gW107XG59O1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2suYmxvY2tfbWV0YSA9IGZ1bmN0aW9uIGJsb2NrX21ldGEoIGJsb2NrLCBuZXh0ICkge1xuICAvLyBjaGVjayBpZiB0aGUgbGFzdCBsaW5lIG9mIHRoZSBibG9jayBpcyBhbiBtZXRhIGhhc2hcbiAgdmFyIG0gPSBibG9jay5tYXRjaCggLyhefFxcbikgezAsM31cXHs6XFxzKigoPzpcXFxcXFx9fFteXFx9XSkqKVxccypcXH0kLyApO1xuICBpZiAoICFtICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAvLyBwcm9jZXNzIHRoZSBtZXRhIGhhc2hcbiAgdmFyIGF0dHIgPSB0aGlzLmRpYWxlY3QucHJvY2Vzc01ldGFIYXNoKCBtWyAyIF0gKTtcblxuICB2YXIgaGFzaDtcblxuICAvLyBpZiB3ZSBtYXRjaGVkIF4gdGhlbiB3ZSBuZWVkIHRvIGFwcGx5IG1ldGEgdG8gdGhlIHByZXZpb3VzIGJsb2NrXG4gIGlmICggbVsgMSBdID09PSBcIlwiICkge1xuICAgIHZhciBub2RlID0gdGhpcy50cmVlWyB0aGlzLnRyZWUubGVuZ3RoIC0gMSBdO1xuICAgIGhhc2ggPSBleHRyYWN0X2F0dHIoIG5vZGUgKTtcblxuICAgIC8vIGlmIHRoZSBub2RlIGlzIGEgc3RyaW5nIChyYXRoZXIgdGhhbiBKc29uTUwpLCBiYWlsXG4gICAgaWYgKCB0eXBlb2Ygbm9kZSA9PT0gXCJzdHJpbmdcIiApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAvLyBjcmVhdGUgdGhlIGF0dHJpYnV0ZSBoYXNoIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICBpZiAoICFoYXNoICkge1xuICAgICAgaGFzaCA9IHt9O1xuICAgICAgbm9kZS5zcGxpY2UoIDEsIDAsIGhhc2ggKTtcbiAgICB9XG5cbiAgICAvLyBhZGQgdGhlIGF0dHJpYnV0ZXMgaW5cbiAgICBmb3IgKCBhIGluIGF0dHIgKSB7XG4gICAgICBoYXNoWyBhIF0gPSBhdHRyWyBhIF07XG4gICAgfVxuXG4gICAgLy8gcmV0dXJuIG5vdGhpbmcgc28gdGhlIG1ldGEgaGFzaCBpcyByZW1vdmVkXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLy8gcHVsbCB0aGUgbWV0YSBoYXNoIG9mZiB0aGUgYmxvY2sgYW5kIHByb2Nlc3Mgd2hhdCdzIGxlZnRcbiAgdmFyIGIgPSBibG9jay5yZXBsYWNlKCAvXFxuLiokLywgXCJcIiApLFxuICAgICAgcmVzdWx0ID0gdGhpcy5wcm9jZXNzQmxvY2soIGIsIFtdICk7XG5cbiAgLy8gZ2V0IG9yIG1ha2UgdGhlIGF0dHJpYnV0ZXMgaGFzaFxuICBoYXNoID0gZXh0cmFjdF9hdHRyKCByZXN1bHRbIDAgXSApO1xuICBpZiAoICFoYXNoICkge1xuICAgIGhhc2ggPSB7fTtcbiAgICByZXN1bHRbIDAgXS5zcGxpY2UoIDEsIDAsIGhhc2ggKTtcbiAgfVxuXG4gIC8vIGF0dGFjaCB0aGUgYXR0cmlidXRlcyB0byB0aGUgYmxvY2tcbiAgZm9yICggYSBpbiBhdHRyICkge1xuICAgIGhhc2hbIGEgXSA9IGF0dHJbIGEgXTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2suZGVmaW5pdGlvbl9saXN0ID0gZnVuY3Rpb24gZGVmaW5pdGlvbl9saXN0KCBibG9jaywgbmV4dCApIHtcbiAgLy8gb25lIG9yIG1vcmUgdGVybXMgZm9sbG93ZWQgYnkgb25lIG9yIG1vcmUgZGVmaW5pdGlvbnMsIGluIGEgc2luZ2xlIGJsb2NrXG4gIHZhciB0aWdodCA9IC9eKCg/OlteXFxzOl0uKlxcbikrKTpcXHMrKFtcXHNcXFNdKykkLyxcbiAgICAgIGxpc3QgPSBbIFwiZGxcIiBdLFxuICAgICAgaSwgbTtcblxuICAvLyBzZWUgaWYgd2UncmUgZGVhbGluZyB3aXRoIGEgdGlnaHQgb3IgbG9vc2UgYmxvY2tcbiAgaWYgKCAoIG0gPSBibG9jay5tYXRjaCggdGlnaHQgKSApICkge1xuICAgIC8vIHB1bGwgc3Vic2VxdWVudCB0aWdodCBETCBibG9ja3Mgb3V0IG9mIGBuZXh0YFxuICAgIHZhciBibG9ja3MgPSBbIGJsb2NrIF07XG4gICAgd2hpbGUgKCBuZXh0Lmxlbmd0aCAmJiB0aWdodC5leGVjKCBuZXh0WyAwIF0gKSApIHtcbiAgICAgIGJsb2Nrcy5wdXNoKCBuZXh0LnNoaWZ0KCkgKTtcbiAgICB9XG5cbiAgICBmb3IgKCB2YXIgYiA9IDA7IGIgPCBibG9ja3MubGVuZ3RoOyArK2IgKSB7XG4gICAgICB2YXIgbSA9IGJsb2Nrc1sgYiBdLm1hdGNoKCB0aWdodCApLFxuICAgICAgICAgIHRlcm1zID0gbVsgMSBdLnJlcGxhY2UoIC9cXG4kLywgXCJcIiApLnNwbGl0KCAvXFxuLyApLFxuICAgICAgICAgIGRlZm5zID0gbVsgMiBdLnNwbGl0KCAvXFxuOlxccysvICk7XG5cbiAgICAgIC8vIHByaW50KCB1bmV2YWwoIG0gKSApO1xuXG4gICAgICBmb3IgKCBpID0gMDsgaSA8IHRlcm1zLmxlbmd0aDsgKytpICkge1xuICAgICAgICBsaXN0LnB1c2goIFsgXCJkdFwiLCB0ZXJtc1sgaSBdIF0gKTtcbiAgICAgIH1cblxuICAgICAgZm9yICggaSA9IDA7IGkgPCBkZWZucy5sZW5ndGg7ICsraSApIHtcbiAgICAgICAgLy8gcnVuIGlubGluZSBwcm9jZXNzaW5nIG92ZXIgdGhlIGRlZmluaXRpb25cbiAgICAgICAgbGlzdC5wdXNoKCBbIFwiZGRcIiBdLmNvbmNhdCggdGhpcy5wcm9jZXNzSW5saW5lKCBkZWZuc1sgaSBdLnJlcGxhY2UoIC8oXFxuKVxccysvLCBcIiQxXCIgKSApICkgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZWxzZSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiBbIGxpc3QgXTtcbn07XG5cbi8vIHNwbGl0cyBvbiB1bmVzY2FwZWQgaW5zdGFuY2VzIG9mIEBjaC4gSWYgQGNoIGlzIG5vdCBhIGNoYXJhY3RlciB0aGUgcmVzdWx0XG4vLyBjYW4gYmUgdW5wcmVkaWN0YWJsZVxuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2sudGFibGUgPSBmdW5jdGlvbiB0YWJsZSAoYmxvY2ssIG5leHQpIHtcblxuICAgIHZhciBfc3BsaXRfb25fdW5lc2NhcGVkID0gZnVuY3Rpb24ocywgY2gpIHtcbiAgICAgICAgY2ggPSBjaCB8fCAnXFxcXHMnO1xuICAgICAgICBpZiAoY2gubWF0Y2goL15bXFxcXHxcXFtcXF17fT8qLiteJF0kLykpIHsgY2ggPSAnXFxcXCcgKyBjaDsgfVxuICAgICAgICB2YXIgcmVzID0gWyBdLFxuICAgICAgICAgICAgciA9IG5ldyBSZWdFeHAoJ14oKD86XFxcXFxcXFwufFteXFxcXFxcXFwnICsgY2ggKyAnXSkqKScgKyBjaCArICcoLiopJyksXG4gICAgICAgICAgICBtO1xuICAgICAgICB3aGlsZShtID0gcy5tYXRjaChyKSkge1xuICAgICAgICAgICAgcmVzLnB1c2gobVsxXSk7XG4gICAgICAgICAgICBzID0gbVsyXTtcbiAgICAgICAgfVxuICAgICAgICByZXMucHVzaChzKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICB2YXIgbGVhZGluZ19waXBlID0gL14gezAsM31cXHwoLispXFxuIHswLDN9XFx8XFxzKihbXFwtOl0rW1xcLXwgOl0qKVxcbigoPzpcXHMqXFx8LiooPzpcXG58JCkpKikoPz1cXG58JCkvLFxuICAgICAgICAvLyBmaW5kIGF0IGxlYXN0IGFuIHVuZXNjYXBlZCBwaXBlIGluIGVhY2ggbGluZVxuICAgICAgICBub19sZWFkaW5nX3BpcGUgPSAvXiB7MCwzfShcXFMoPzpcXFxcLnxbXlxcXFx8XSkqXFx8LiopXFxuIHswLDN9KFtcXC06XStcXHMqXFx8W1xcLXwgOl0qKVxcbigoPzooPzpcXFxcLnxbXlxcXFx8XSkqXFx8LiooPzpcXG58JCkpKikoPz1cXG58JCkvLFxuICAgICAgICBpLCBtO1xuICAgIGlmIChtID0gYmxvY2subWF0Y2gobGVhZGluZ19waXBlKSkge1xuICAgICAgICAvLyByZW1vdmUgbGVhZGluZyBwaXBlcyBpbiBjb250ZW50c1xuICAgICAgICAvLyAoaGVhZGVyIGFuZCBob3Jpem9udGFsIHJ1bGUgYWxyZWFkeSBoYXZlIHRoZSBsZWFkaW5nIHBpcGUgbGVmdCBvdXQpXG4gICAgICAgIG1bM10gPSBtWzNdLnJlcGxhY2UoL15cXHMqXFx8L2dtLCAnJyk7XG4gICAgfSBlbHNlIGlmICghICggbSA9IGJsb2NrLm1hdGNoKG5vX2xlYWRpbmdfcGlwZSkpKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgdmFyIHRhYmxlID0gWyBcInRhYmxlXCIsIFsgXCJ0aGVhZFwiLCBbIFwidHJcIiBdIF0sIFsgXCJ0Ym9keVwiIF0gXTtcblxuICAgIC8vIHJlbW92ZSB0cmFpbGluZyBwaXBlcywgdGhlbiBzcGxpdCBvbiBwaXBlc1xuICAgIC8vIChubyBlc2NhcGVkIHBpcGVzIGFyZSBhbGxvd2VkIGluIGhvcml6b250YWwgcnVsZSlcbiAgICBtWzJdID0gbVsyXS5yZXBsYWNlKC9cXHxcXHMqJC8sICcnKS5zcGxpdCgnfCcpO1xuXG4gICAgLy8gcHJvY2VzcyBhbGlnbm1lbnRcbiAgICB2YXIgaHRtbF9hdHRycyA9IFsgXTtcbiAgICBmb3JFYWNoIChtWzJdLCBmdW5jdGlvbiAocykge1xuICAgICAgICBpZiAocy5tYXRjaCgvXlxccyotKzpcXHMqJC8pKSAgICAgICBodG1sX2F0dHJzLnB1c2goe2FsaWduOiBcInJpZ2h0XCJ9KTtcbiAgICAgICAgZWxzZSBpZiAocy5tYXRjaCgvXlxccyo6LStcXHMqJC8pKSAgaHRtbF9hdHRycy5wdXNoKHthbGlnbjogXCJsZWZ0XCJ9KTtcbiAgICAgICAgZWxzZSBpZiAocy5tYXRjaCgvXlxccyo6LSs6XFxzKiQvKSkgaHRtbF9hdHRycy5wdXNoKHthbGlnbjogXCJjZW50ZXJcIn0pO1xuICAgICAgICBlbHNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbF9hdHRycy5wdXNoKHt9KTtcbiAgICB9KTtcblxuICAgIC8vIG5vdyBmb3IgdGhlIGhlYWRlciwgYXZvaWQgZXNjYXBlZCBwaXBlc1xuICAgIG1bMV0gPSBfc3BsaXRfb25fdW5lc2NhcGVkKG1bMV0ucmVwbGFjZSgvXFx8XFxzKiQvLCAnJyksICd8Jyk7XG4gICAgZm9yIChpID0gMDsgaSA8IG1bMV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGFibGVbMV1bMV0ucHVzaChbJ3RoJywgaHRtbF9hdHRyc1tpXSB8fCB7fV0uY29uY2F0KFxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzSW5saW5lKG1bMV1baV0udHJpbSgpKSkpO1xuICAgIH1cblxuICAgIC8vIG5vdyBmb3IgYm9keSBjb250ZW50c1xuICAgIGZvckVhY2ggKG1bM10ucmVwbGFjZSgvXFx8XFxzKiQvbWcsICcnKS5zcGxpdCgnXFxuJyksIGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIGh0bWxfcm93ID0gWyd0ciddO1xuICAgICAgICByb3cgPSBfc3BsaXRfb25fdW5lc2NhcGVkKHJvdywgJ3wnKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJvdy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaHRtbF9yb3cucHVzaChbJ3RkJywgaHRtbF9hdHRyc1tpXSB8fCB7fV0uY29uY2F0KHRoaXMucHJvY2Vzc0lubGluZShyb3dbaV0udHJpbSgpKSkpO1xuICAgICAgICB9XG4gICAgICAgIHRhYmxlWzJdLnB1c2goaHRtbF9yb3cpO1xuICAgIH0sIHRoaXMpO1xuXG4gICAgcmV0dXJuIFt0YWJsZV07XG59XG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5pbmxpbmVbIFwiezpcIiBdID0gZnVuY3Rpb24gaW5saW5lX21ldGEoIHRleHQsIG1hdGNoZXMsIG91dCApIHtcbiAgaWYgKCAhb3V0Lmxlbmd0aCApIHtcbiAgICByZXR1cm4gWyAyLCBcIns6XCIgXTtcbiAgfVxuXG4gIC8vIGdldCB0aGUgcHJlY2VlZGluZyBlbGVtZW50XG4gIHZhciBiZWZvcmUgPSBvdXRbIG91dC5sZW5ndGggLSAxIF07XG5cbiAgaWYgKCB0eXBlb2YgYmVmb3JlID09PSBcInN0cmluZ1wiICkge1xuICAgIHJldHVybiBbIDIsIFwiezpcIiBdO1xuICB9XG5cbiAgLy8gbWF0Y2ggYSBtZXRhIGhhc2hcbiAgdmFyIG0gPSB0ZXh0Lm1hdGNoKCAvXlxcezpcXHMqKCg/OlxcXFxcXH18W15cXH1dKSopXFxzKlxcfS8gKTtcblxuICAvLyBubyBtYXRjaCwgZmFsc2UgYWxhcm1cbiAgaWYgKCAhbSApIHtcbiAgICByZXR1cm4gWyAyLCBcIns6XCIgXTtcbiAgfVxuXG4gIC8vIGF0dGFjaCB0aGUgYXR0cmlidXRlcyB0byB0aGUgcHJlY2VlZGluZyBlbGVtZW50XG4gIHZhciBtZXRhID0gdGhpcy5kaWFsZWN0LnByb2Nlc3NNZXRhSGFzaCggbVsgMSBdICksXG4gICAgICBhdHRyID0gZXh0cmFjdF9hdHRyKCBiZWZvcmUgKTtcblxuICBpZiAoICFhdHRyICkge1xuICAgIGF0dHIgPSB7fTtcbiAgICBiZWZvcmUuc3BsaWNlKCAxLCAwLCBhdHRyICk7XG4gIH1cblxuICBmb3IgKCB2YXIgayBpbiBtZXRhICkge1xuICAgIGF0dHJbIGsgXSA9IG1ldGFbIGsgXTtcbiAgfVxuXG4gIC8vIGN1dCBvdXQgdGhlIHN0cmluZyBhbmQgcmVwbGFjZSBpdCB3aXRoIG5vdGhpbmdcbiAgcmV0dXJuIFsgbVsgMCBdLmxlbmd0aCwgXCJcIiBdO1xufTtcblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmlubGluZS5fX2VzY2FwZV9fID0gL15cXFxcW1xcXFxgXFwqX3t9XFxbXFxdKCkjXFwrLiFcXC18Ol0vO1xuXG5NYXJrZG93bi5idWlsZEJsb2NrT3JkZXIgKCBNYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2sgKTtcbk1hcmtkb3duLmJ1aWxkSW5saW5lUGF0dGVybnMoIE1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5pbmxpbmUgKTtcblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uKG9iaikge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT0gXCJbb2JqZWN0IEFycmF5XVwiO1xufTtcblxudmFyIGZvckVhY2g7XG4vLyBEb24ndCBtZXNzIHdpdGggQXJyYXkucHJvdG90eXBlLiBJdHMgbm90IGZyaWVuZGx5XG5pZiAoIEFycmF5LnByb3RvdHlwZS5mb3JFYWNoICkge1xuICBmb3JFYWNoID0gZnVuY3Rpb24oIGFyciwgY2IsIHRoaXNwICkge1xuICAgIHJldHVybiBhcnIuZm9yRWFjaCggY2IsIHRoaXNwICk7XG4gIH07XG59XG5lbHNlIHtcbiAgZm9yRWFjaCA9IGZ1bmN0aW9uKGFyciwgY2IsIHRoaXNwKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNiLmNhbGwodGhpc3AgfHwgYXJyLCBhcnJbaV0sIGksIGFycik7XG4gICAgfVxuICB9XG59XG5cbnZhciBpc0VtcHR5ID0gZnVuY3Rpb24oIG9iaiApIHtcbiAgZm9yICggdmFyIGtleSBpbiBvYmogKSB7XG4gICAgaWYgKCBoYXNPd25Qcm9wZXJ0eS5jYWxsKCBvYmosIGtleSApICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0X2F0dHIoIGpzb25tbCApIHtcbiAgcmV0dXJuIGlzQXJyYXkoanNvbm1sKVxuICAgICAgJiYganNvbm1sLmxlbmd0aCA+IDFcbiAgICAgICYmIHR5cGVvZiBqc29ubWxbIDEgXSA9PT0gXCJvYmplY3RcIlxuICAgICAgJiYgISggaXNBcnJheShqc29ubWxbIDEgXSkgKVxuICAgICAgPyBqc29ubWxbIDEgXVxuICAgICAgOiB1bmRlZmluZWQ7XG59XG5cblxuXG4vKipcbiAqICByZW5kZXJKc29uTUwoIGpzb25tbFssIG9wdGlvbnNdICkgLT4gU3RyaW5nXG4gKiAgLSBqc29ubWwgKEFycmF5KTogSnNvbk1MIGFycmF5IHRvIHJlbmRlciB0byBYTUxcbiAqICAtIG9wdGlvbnMgKE9iamVjdCk6IG9wdGlvbnNcbiAqXG4gKiAgQ29udmVydHMgdGhlIGdpdmVuIEpzb25NTCBpbnRvIHdlbGwtZm9ybWVkIFhNTC5cbiAqXG4gKiAgVGhlIG9wdGlvbnMgY3VycmVudGx5IHVuZGVyc3Rvb2QgYXJlOlxuICpcbiAqICAtIHJvb3QgKEJvb2xlYW4pOiB3ZXRoZXIgb3Igbm90IHRoZSByb290IG5vZGUgc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZVxuICogICAgb3V0cHV0LCBvciBqdXN0IGl0cyBjaGlsZHJlbi4gVGhlIGRlZmF1bHQgYGZhbHNlYCBpcyB0byBub3QgaW5jbHVkZSB0aGVcbiAqICAgIHJvb3QgaXRzZWxmLlxuICovXG5leHBvc2UucmVuZGVySnNvbk1MID0gZnVuY3Rpb24oIGpzb25tbCwgb3B0aW9ucyApIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIC8vIGluY2x1ZGUgdGhlIHJvb3QgZWxlbWVudCBpbiB0aGUgcmVuZGVyZWQgb3V0cHV0P1xuICBvcHRpb25zLnJvb3QgPSBvcHRpb25zLnJvb3QgfHwgZmFsc2U7XG5cbiAgdmFyIGNvbnRlbnQgPSBbXTtcblxuICBpZiAoIG9wdGlvbnMucm9vdCApIHtcbiAgICBjb250ZW50LnB1c2goIHJlbmRlcl90cmVlKCBqc29ubWwgKSApO1xuICB9XG4gIGVsc2Uge1xuICAgIGpzb25tbC5zaGlmdCgpOyAvLyBnZXQgcmlkIG9mIHRoZSB0YWdcbiAgICBpZiAoIGpzb25tbC5sZW5ndGggJiYgdHlwZW9mIGpzb25tbFsgMCBdID09PSBcIm9iamVjdFwiICYmICEoIGpzb25tbFsgMCBdIGluc3RhbmNlb2YgQXJyYXkgKSApIHtcbiAgICAgIGpzb25tbC5zaGlmdCgpOyAvLyBnZXQgcmlkIG9mIHRoZSBhdHRyaWJ1dGVzXG4gICAgfVxuXG4gICAgd2hpbGUgKCBqc29ubWwubGVuZ3RoICkge1xuICAgICAgY29udGVudC5wdXNoKCByZW5kZXJfdHJlZSgganNvbm1sLnNoaWZ0KCkgKSApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjb250ZW50LmpvaW4oIFwiXFxuXFxuXCIgKTtcbn07XG5cbmZ1bmN0aW9uIGVzY2FwZUhUTUwoIHRleHQgKSB7XG4gIHJldHVybiB0ZXh0LnJlcGxhY2UoIC8mL2csIFwiJmFtcDtcIiApXG4gICAgICAgICAgICAgLnJlcGxhY2UoIC88L2csIFwiJmx0O1wiIClcbiAgICAgICAgICAgICAucmVwbGFjZSggLz4vZywgXCImZ3Q7XCIgKVxuICAgICAgICAgICAgIC5yZXBsYWNlKCAvXCIvZywgXCImcXVvdDtcIiApXG4gICAgICAgICAgICAgLnJlcGxhY2UoIC8nL2csIFwiJiMzOTtcIiApO1xufVxuXG5mdW5jdGlvbiByZW5kZXJfdHJlZSgganNvbm1sICkge1xuICAvLyBiYXNpYyBjYXNlXG4gIGlmICggdHlwZW9mIGpzb25tbCA9PT0gXCJzdHJpbmdcIiApIHtcbiAgICByZXR1cm4gZXNjYXBlSFRNTCgganNvbm1sICk7XG4gIH1cblxuICB2YXIgdGFnID0ganNvbm1sLnNoaWZ0KCksXG4gICAgICBhdHRyaWJ1dGVzID0ge30sXG4gICAgICBjb250ZW50ID0gW107XG5cbiAgaWYgKCBqc29ubWwubGVuZ3RoICYmIHR5cGVvZiBqc29ubWxbIDAgXSA9PT0gXCJvYmplY3RcIiAmJiAhKCBqc29ubWxbIDAgXSBpbnN0YW5jZW9mIEFycmF5ICkgKSB7XG4gICAgYXR0cmlidXRlcyA9IGpzb25tbC5zaGlmdCgpO1xuICB9XG5cbiAgd2hpbGUgKCBqc29ubWwubGVuZ3RoICkge1xuICAgIGNvbnRlbnQucHVzaCggcmVuZGVyX3RyZWUoIGpzb25tbC5zaGlmdCgpICkgKTtcbiAgfVxuXG4gIHZhciB0YWdfYXR0cnMgPSBcIlwiO1xuICBmb3IgKCB2YXIgYSBpbiBhdHRyaWJ1dGVzICkge1xuICAgIHRhZ19hdHRycyArPSBcIiBcIiArIGEgKyAnPVwiJyArIGVzY2FwZUhUTUwoIGF0dHJpYnV0ZXNbIGEgXSApICsgJ1wiJztcbiAgfVxuXG4gIC8vIGJlIGNhcmVmdWwgYWJvdXQgYWRkaW5nIHdoaXRlc3BhY2UgaGVyZSBmb3IgaW5saW5lIGVsZW1lbnRzXG4gIGlmICggdGFnID09IFwiaW1nXCIgfHwgdGFnID09IFwiYnJcIiB8fCB0YWcgPT0gXCJoclwiICkge1xuICAgIHJldHVybiBcIjxcIisgdGFnICsgdGFnX2F0dHJzICsgXCIvPlwiO1xuICB9XG4gIGVsc2Uge1xuICAgIHJldHVybiBcIjxcIisgdGFnICsgdGFnX2F0dHJzICsgXCI+XCIgKyBjb250ZW50LmpvaW4oIFwiXCIgKSArIFwiPC9cIiArIHRhZyArIFwiPlwiO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRfdHJlZV90b19odG1sKCB0cmVlLCByZWZlcmVuY2VzLCBvcHRpb25zICkge1xuICB2YXIgaTtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgLy8gc2hhbGxvdyBjbG9uZVxuICB2YXIganNvbm1sID0gdHJlZS5zbGljZSggMCApO1xuXG4gIGlmICggdHlwZW9mIG9wdGlvbnMucHJlcHJvY2Vzc1RyZWVOb2RlID09PSBcImZ1bmN0aW9uXCIgKSB7XG4gICAgICBqc29ubWwgPSBvcHRpb25zLnByZXByb2Nlc3NUcmVlTm9kZShqc29ubWwsIHJlZmVyZW5jZXMpO1xuICB9XG5cbiAgLy8gQ2xvbmUgYXR0cmlidXRlcyBpZiB0aGV5IGV4aXN0XG4gIHZhciBhdHRycyA9IGV4dHJhY3RfYXR0cigganNvbm1sICk7XG4gIGlmICggYXR0cnMgKSB7XG4gICAganNvbm1sWyAxIF0gPSB7fTtcbiAgICBmb3IgKCBpIGluIGF0dHJzICkge1xuICAgICAganNvbm1sWyAxIF1bIGkgXSA9IGF0dHJzWyBpIF07XG4gICAgfVxuICAgIGF0dHJzID0ganNvbm1sWyAxIF07XG4gIH1cblxuICAvLyBiYXNpYyBjYXNlXG4gIGlmICggdHlwZW9mIGpzb25tbCA9PT0gXCJzdHJpbmdcIiApIHtcbiAgICByZXR1cm4ganNvbm1sO1xuICB9XG5cbiAgLy8gY29udmVydCB0aGlzIG5vZGVcbiAgc3dpdGNoICgganNvbm1sWyAwIF0gKSB7XG4gICAgY2FzZSBcImhlYWRlclwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImhcIiArIGpzb25tbFsgMSBdLmxldmVsO1xuICAgICAgZGVsZXRlIGpzb25tbFsgMSBdLmxldmVsO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImJ1bGxldGxpc3RcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJ1bFwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcIm51bWJlcmxpc3RcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJvbFwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImxpc3RpdGVtXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwibGlcIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJwYXJhXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwicFwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcIm1hcmtkb3duXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiaHRtbFwiO1xuICAgICAgaWYgKCBhdHRycyApIGRlbGV0ZSBhdHRycy5yZWZlcmVuY2VzO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImNvZGVfYmxvY2tcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJwcmVcIjtcbiAgICAgIGkgPSBhdHRycyA/IDIgOiAxO1xuICAgICAgdmFyIGNvZGUgPSBbIFwiY29kZVwiIF07XG4gICAgICBjb2RlLnB1c2guYXBwbHkoIGNvZGUsIGpzb25tbC5zcGxpY2UoIGksIGpzb25tbC5sZW5ndGggLSBpICkgKTtcbiAgICAgIGpzb25tbFsgaSBdID0gY29kZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJpbmxpbmVjb2RlXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiY29kZVwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImltZ1wiOlxuICAgICAganNvbm1sWyAxIF0uc3JjID0ganNvbm1sWyAxIF0uaHJlZjtcbiAgICAgIGRlbGV0ZSBqc29ubWxbIDEgXS5ocmVmO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImxpbmVicmVha1wiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImJyXCI7XG4gICAgYnJlYWs7XG4gICAgY2FzZSBcImxpbmtcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJhXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwibGlua19yZWZcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJhXCI7XG5cbiAgICAgIC8vIGdyYWIgdGhpcyByZWYgYW5kIGNsZWFuIHVwIHRoZSBhdHRyaWJ1dGUgbm9kZVxuICAgICAgdmFyIHJlZiA9IHJlZmVyZW5jZXNbIGF0dHJzLnJlZiBdO1xuXG4gICAgICAvLyBpZiB0aGUgcmVmZXJlbmNlIGV4aXN0cywgbWFrZSB0aGUgbGlua1xuICAgICAgaWYgKCByZWYgKSB7XG4gICAgICAgIGRlbGV0ZSBhdHRycy5yZWY7XG5cbiAgICAgICAgLy8gYWRkIGluIHRoZSBocmVmIGFuZCB0aXRsZSwgaWYgcHJlc2VudFxuICAgICAgICBhdHRycy5ocmVmID0gcmVmLmhyZWY7XG4gICAgICAgIGlmICggcmVmLnRpdGxlICkge1xuICAgICAgICAgIGF0dHJzLnRpdGxlID0gcmVmLnRpdGxlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZ2V0IHJpZCBvZiB0aGUgdW5uZWVkZWQgb3JpZ2luYWwgdGV4dFxuICAgICAgICBkZWxldGUgYXR0cnMub3JpZ2luYWw7XG4gICAgICB9XG4gICAgICAvLyB0aGUgcmVmZXJlbmNlIGRvZXNuJ3QgZXhpc3QsIHNvIHJldmVydCB0byBwbGFpbiB0ZXh0XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGF0dHJzLm9yaWdpbmFsO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImltZ19yZWZcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJpbWdcIjtcblxuICAgICAgLy8gZ3JhYiB0aGlzIHJlZiBhbmQgY2xlYW4gdXAgdGhlIGF0dHJpYnV0ZSBub2RlXG4gICAgICB2YXIgcmVmID0gcmVmZXJlbmNlc1sgYXR0cnMucmVmIF07XG5cbiAgICAgIC8vIGlmIHRoZSByZWZlcmVuY2UgZXhpc3RzLCBtYWtlIHRoZSBsaW5rXG4gICAgICBpZiAoIHJlZiApIHtcbiAgICAgICAgZGVsZXRlIGF0dHJzLnJlZjtcblxuICAgICAgICAvLyBhZGQgaW4gdGhlIGhyZWYgYW5kIHRpdGxlLCBpZiBwcmVzZW50XG4gICAgICAgIGF0dHJzLnNyYyA9IHJlZi5ocmVmO1xuICAgICAgICBpZiAoIHJlZi50aXRsZSApIHtcbiAgICAgICAgICBhdHRycy50aXRsZSA9IHJlZi50aXRsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGdldCByaWQgb2YgdGhlIHVubmVlZGVkIG9yaWdpbmFsIHRleHRcbiAgICAgICAgZGVsZXRlIGF0dHJzLm9yaWdpbmFsO1xuICAgICAgfVxuICAgICAgLy8gdGhlIHJlZmVyZW5jZSBkb2Vzbid0IGV4aXN0LCBzbyByZXZlcnQgdG8gcGxhaW4gdGV4dFxuICAgICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBhdHRycy5vcmlnaW5hbDtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgLy8gY29udmVydCBhbGwgdGhlIGNoaWxkcmVuXG4gIGkgPSAxO1xuXG4gIC8vIGRlYWwgd2l0aCB0aGUgYXR0cmlidXRlIG5vZGUsIGlmIGl0IGV4aXN0c1xuICBpZiAoIGF0dHJzICkge1xuICAgIC8vIGlmIHRoZXJlIGFyZSBrZXlzLCBza2lwIG92ZXIgaXRcbiAgICBmb3IgKCB2YXIga2V5IGluIGpzb25tbFsgMSBdICkge1xuICAgICAgICBpID0gMjtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIC8vIGlmIHRoZXJlIGFyZW4ndCwgcmVtb3ZlIGl0XG4gICAgaWYgKCBpID09PSAxICkge1xuICAgICAganNvbm1sLnNwbGljZSggaSwgMSApO1xuICAgIH1cbiAgfVxuXG4gIGZvciAoIDsgaSA8IGpzb25tbC5sZW5ndGg7ICsraSApIHtcbiAgICBqc29ubWxbIGkgXSA9IGNvbnZlcnRfdHJlZV90b19odG1sKCBqc29ubWxbIGkgXSwgcmVmZXJlbmNlcywgb3B0aW9ucyApO1xuICB9XG5cbiAgcmV0dXJuIGpzb25tbDtcbn1cblxuXG4vLyBtZXJnZXMgYWRqYWNlbnQgdGV4dCBub2RlcyBpbnRvIGEgc2luZ2xlIG5vZGVcbmZ1bmN0aW9uIG1lcmdlX3RleHRfbm9kZXMoIGpzb25tbCApIHtcbiAgLy8gc2tpcCB0aGUgdGFnIG5hbWUgYW5kIGF0dHJpYnV0ZSBoYXNoXG4gIHZhciBpID0gZXh0cmFjdF9hdHRyKCBqc29ubWwgKSA/IDIgOiAxO1xuXG4gIHdoaWxlICggaSA8IGpzb25tbC5sZW5ndGggKSB7XG4gICAgLy8gaWYgaXQncyBhIHN0cmluZyBjaGVjayB0aGUgbmV4dCBpdGVtIHRvb1xuICAgIGlmICggdHlwZW9mIGpzb25tbFsgaSBdID09PSBcInN0cmluZ1wiICkge1xuICAgICAgaWYgKCBpICsgMSA8IGpzb25tbC5sZW5ndGggJiYgdHlwZW9mIGpzb25tbFsgaSArIDEgXSA9PT0gXCJzdHJpbmdcIiApIHtcbiAgICAgICAgLy8gbWVyZ2UgdGhlIHNlY29uZCBzdHJpbmcgaW50byB0aGUgZmlyc3QgYW5kIHJlbW92ZSBpdFxuICAgICAgICBqc29ubWxbIGkgXSArPSBqc29ubWwuc3BsaWNlKCBpICsgMSwgMSApWyAwIF07XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgKytpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBpZiBpdCdzIG5vdCBhIHN0cmluZyByZWN1cnNlXG4gICAgZWxzZSB7XG4gICAgICBtZXJnZV90ZXh0X25vZGVzKCBqc29ubWxbIGkgXSApO1xuICAgICAgKytpO1xuICAgIH1cbiAgfVxufVxuXG59ICkoIChmdW5jdGlvbigpIHtcbiAgaWYgKCB0eXBlb2YgZXhwb3J0cyA9PT0gXCJ1bmRlZmluZWRcIiApIHtcbiAgICB3aW5kb3cubWFya2Rvd24gPSB7fTtcbiAgICByZXR1cm4gd2luZG93Lm1hcmtkb3duO1xuICB9XG4gIGVsc2Uge1xuICAgIHJldHVybiBleHBvcnRzO1xuICB9XG59ICkoKSApO1xuIiwiKGZ1bmN0aW9uKGYpe2lmKHR5cGVvZiBleHBvcnRzPT09XCJvYmplY3RcIiYmdHlwZW9mIG1vZHVsZSE9PVwidW5kZWZpbmVkXCIpe21vZHVsZS5leHBvcnRzPWYoKX1lbHNlIGlmKHR5cGVvZiBkZWZpbmU9PT1cImZ1bmN0aW9uXCImJmRlZmluZS5hbWQpe2RlZmluZShbXSxmKX1lbHNle3ZhciBnO2lmKHR5cGVvZiB3aW5kb3chPT1cInVuZGVmaW5lZFwiKXtnPXdpbmRvd31lbHNlIGlmKHR5cGVvZiBnbG9iYWwhPT1cInVuZGVmaW5lZFwiKXtnPWdsb2JhbH1lbHNlIGlmKHR5cGVvZiBzZWxmIT09XCJ1bmRlZmluZWRcIil7Zz1zZWxmfWVsc2V7Zz10aGlzfWcudG9NYXJrZG93biA9IGYoKX19KShmdW5jdGlvbigpe3ZhciBkZWZpbmUsbW9kdWxlLGV4cG9ydHM7cmV0dXJuIChmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pKHsxOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiB0by1tYXJrZG93biAtIGFuIEhUTUwgdG8gTWFya2Rvd24gY29udmVydGVyXG4gKlxuICogQ29weXJpZ2h0IDIwMTErLCBEb20gQ2hyaXN0aWVcbiAqIExpY2VuY2VkIHVuZGVyIHRoZSBNSVQgbGljZW5jZVxuICpcbiAqL1xuXG4ndXNlIHN0cmljdCdcblxudmFyIHRvTWFya2Rvd25cbnZhciBjb252ZXJ0ZXJzXG52YXIgbWRDb252ZXJ0ZXJzID0gcmVxdWlyZSgnLi9saWIvbWQtY29udmVydGVycycpXG52YXIgZ2ZtQ29udmVydGVycyA9IHJlcXVpcmUoJy4vbGliL2dmbS1jb252ZXJ0ZXJzJylcbnZhciBIdG1sUGFyc2VyID0gcmVxdWlyZSgnLi9saWIvaHRtbC1wYXJzZXInKVxudmFyIGNvbGxhcHNlID0gcmVxdWlyZSgnY29sbGFwc2Utd2hpdGVzcGFjZScpXG5cbi8qXG4gKiBVdGlsaXRpZXNcbiAqL1xuXG52YXIgYmxvY2tzID0gWydhZGRyZXNzJywgJ2FydGljbGUnLCAnYXNpZGUnLCAnYXVkaW8nLCAnYmxvY2txdW90ZScsICdib2R5JyxcbiAgJ2NhbnZhcycsICdjZW50ZXInLCAnZGQnLCAnZGlyJywgJ2RpdicsICdkbCcsICdkdCcsICdmaWVsZHNldCcsICdmaWdjYXB0aW9uJyxcbiAgJ2ZpZ3VyZScsICdmb290ZXInLCAnZm9ybScsICdmcmFtZXNldCcsICdoMScsICdoMicsICdoMycsICdoNCcsICdoNScsICdoNicsXG4gICdoZWFkZXInLCAnaGdyb3VwJywgJ2hyJywgJ2h0bWwnLCAnaXNpbmRleCcsICdsaScsICdtYWluJywgJ21lbnUnLCAnbmF2JyxcbiAgJ25vZnJhbWVzJywgJ25vc2NyaXB0JywgJ29sJywgJ291dHB1dCcsICdwJywgJ3ByZScsICdzZWN0aW9uJywgJ3RhYmxlJyxcbiAgJ3Rib2R5JywgJ3RkJywgJ3Rmb290JywgJ3RoJywgJ3RoZWFkJywgJ3RyJywgJ3VsJ1xuXVxuXG5mdW5jdGlvbiBpc0Jsb2NrIChub2RlKSB7XG4gIHJldHVybiBibG9ja3MuaW5kZXhPZihub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkpICE9PSAtMVxufVxuXG52YXIgdm9pZHMgPSBbXG4gICdhcmVhJywgJ2Jhc2UnLCAnYnInLCAnY29sJywgJ2NvbW1hbmQnLCAnZW1iZWQnLCAnaHInLCAnaW1nJywgJ2lucHV0JyxcbiAgJ2tleWdlbicsICdsaW5rJywgJ21ldGEnLCAncGFyYW0nLCAnc291cmNlJywgJ3RyYWNrJywgJ3dicidcbl1cblxuZnVuY3Rpb24gaXNWb2lkIChub2RlKSB7XG4gIHJldHVybiB2b2lkcy5pbmRleE9mKG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSkgIT09IC0xXG59XG5cbmZ1bmN0aW9uIGh0bWxUb0RvbSAoc3RyaW5nKSB7XG4gIHZhciB0cmVlID0gbmV3IEh0bWxQYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcoc3RyaW5nLCAndGV4dC9odG1sJylcbiAgY29sbGFwc2UodHJlZS5kb2N1bWVudEVsZW1lbnQsIGlzQmxvY2spXG4gIHJldHVybiB0cmVlXG59XG5cbi8qXG4gKiBGbGF0dGVucyBET00gdHJlZSBpbnRvIHNpbmdsZSBhcnJheVxuICovXG5cbmZ1bmN0aW9uIGJmc09yZGVyIChub2RlKSB7XG4gIHZhciBpbnF1ZXVlID0gW25vZGVdXG4gIHZhciBvdXRxdWV1ZSA9IFtdXG4gIHZhciBlbGVtXG4gIHZhciBjaGlsZHJlblxuICB2YXIgaVxuXG4gIHdoaWxlIChpbnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICBlbGVtID0gaW5xdWV1ZS5zaGlmdCgpXG4gICAgb3V0cXVldWUucHVzaChlbGVtKVxuICAgIGNoaWxkcmVuID0gZWxlbS5jaGlsZE5vZGVzXG4gICAgZm9yIChpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoY2hpbGRyZW5baV0ubm9kZVR5cGUgPT09IDEpIGlucXVldWUucHVzaChjaGlsZHJlbltpXSlcbiAgICB9XG4gIH1cbiAgb3V0cXVldWUuc2hpZnQoKVxuICByZXR1cm4gb3V0cXVldWVcbn1cblxuLypcbiAqIENvbnRydWN0cyBhIE1hcmtkb3duIHN0cmluZyBvZiByZXBsYWNlbWVudCB0ZXh0IGZvciBhIGdpdmVuIG5vZGVcbiAqL1xuXG5mdW5jdGlvbiBnZXRDb250ZW50IChub2RlKSB7XG4gIHZhciB0ZXh0ID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAobm9kZS5jaGlsZE5vZGVzW2ldLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICB0ZXh0ICs9IG5vZGUuY2hpbGROb2Rlc1tpXS5fcmVwbGFjZW1lbnRcbiAgICB9IGVsc2UgaWYgKG5vZGUuY2hpbGROb2Rlc1tpXS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgdGV4dCArPSBub2RlLmNoaWxkTm9kZXNbaV0uZGF0YVxuICAgIH0gZWxzZSBjb250aW51ZVxuICB9XG4gIHJldHVybiB0ZXh0XG59XG5cbi8qXG4gKiBSZXR1cm5zIHRoZSBIVE1MIHN0cmluZyBvZiBhbiBlbGVtZW50IHdpdGggaXRzIGNvbnRlbnRzIGNvbnZlcnRlZFxuICovXG5cbmZ1bmN0aW9uIG91dGVyIChub2RlLCBjb250ZW50KSB7XG4gIHJldHVybiBub2RlLmNsb25lTm9kZShmYWxzZSkub3V0ZXJIVE1MLnJlcGxhY2UoJz48JywgJz4nICsgY29udGVudCArICc8Jylcbn1cblxuZnVuY3Rpb24gY2FuQ29udmVydCAobm9kZSwgZmlsdGVyKSB7XG4gIGlmICh0eXBlb2YgZmlsdGVyID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmaWx0ZXIgPT09IG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKVxuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KGZpbHRlcikpIHtcbiAgICByZXR1cm4gZmlsdGVyLmluZGV4T2Yobm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSAhPT0gLTFcbiAgfSBlbHNlIGlmICh0eXBlb2YgZmlsdGVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGZpbHRlci5jYWxsKHRvTWFya2Rvd24sIG5vZGUpXG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYGZpbHRlcmAgbmVlZHMgdG8gYmUgYSBzdHJpbmcsIGFycmF5LCBvciBmdW5jdGlvbicpXG4gIH1cbn1cblxuZnVuY3Rpb24gaXNGbGFua2VkQnlXaGl0ZXNwYWNlIChzaWRlLCBub2RlKSB7XG4gIHZhciBzaWJsaW5nXG4gIHZhciByZWdFeHBcbiAgdmFyIGlzRmxhbmtlZFxuXG4gIGlmIChzaWRlID09PSAnbGVmdCcpIHtcbiAgICBzaWJsaW5nID0gbm9kZS5wcmV2aW91c1NpYmxpbmdcbiAgICByZWdFeHAgPSAvICQvXG4gIH0gZWxzZSB7XG4gICAgc2libGluZyA9IG5vZGUubmV4dFNpYmxpbmdcbiAgICByZWdFeHAgPSAvXiAvXG4gIH1cblxuICBpZiAoc2libGluZykge1xuICAgIGlmIChzaWJsaW5nLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICBpc0ZsYW5rZWQgPSByZWdFeHAudGVzdChzaWJsaW5nLm5vZGVWYWx1ZSlcbiAgICB9IGVsc2UgaWYgKHNpYmxpbmcubm9kZVR5cGUgPT09IDEgJiYgIWlzQmxvY2soc2libGluZykpIHtcbiAgICAgIGlzRmxhbmtlZCA9IHJlZ0V4cC50ZXN0KHNpYmxpbmcudGV4dENvbnRlbnQpXG4gICAgfVxuICB9XG4gIHJldHVybiBpc0ZsYW5rZWRcbn1cblxuZnVuY3Rpb24gZmxhbmtpbmdXaGl0ZXNwYWNlIChub2RlLCBjb250ZW50KSB7XG4gIHZhciBsZWFkaW5nID0gJydcbiAgdmFyIHRyYWlsaW5nID0gJydcblxuICBpZiAoIWlzQmxvY2sobm9kZSkpIHtcbiAgICB2YXIgaGFzTGVhZGluZyA9IC9eWyBcXHJcXG5cXHRdLy50ZXN0KGNvbnRlbnQpXG4gICAgdmFyIGhhc1RyYWlsaW5nID0gL1sgXFxyXFxuXFx0XSQvLnRlc3QoY29udGVudClcblxuICAgIGlmIChoYXNMZWFkaW5nICYmICFpc0ZsYW5rZWRCeVdoaXRlc3BhY2UoJ2xlZnQnLCBub2RlKSkge1xuICAgICAgbGVhZGluZyA9ICcgJ1xuICAgIH1cbiAgICBpZiAoaGFzVHJhaWxpbmcgJiYgIWlzRmxhbmtlZEJ5V2hpdGVzcGFjZSgncmlnaHQnLCBub2RlKSkge1xuICAgICAgdHJhaWxpbmcgPSAnICdcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBsZWFkaW5nOiBsZWFkaW5nLCB0cmFpbGluZzogdHJhaWxpbmcgfVxufVxuXG4vKlxuICogRmluZHMgYSBNYXJrZG93biBjb252ZXJ0ZXIsIGdldHMgdGhlIHJlcGxhY2VtZW50LCBhbmQgc2V0cyBpdCBvblxuICogYF9yZXBsYWNlbWVudGBcbiAqL1xuXG5mdW5jdGlvbiBwcm9jZXNzIChub2RlKSB7XG4gIHZhciByZXBsYWNlbWVudFxuICB2YXIgY29udGVudCA9IGdldENvbnRlbnQobm9kZSlcblxuICAvLyBSZW1vdmUgYmxhbmsgbm9kZXNcbiAgaWYgKCFpc1ZvaWQobm9kZSkgJiYgIS9BfFRIfFRELy50ZXN0KG5vZGUubm9kZU5hbWUpICYmIC9eXFxzKiQvaS50ZXN0KGNvbnRlbnQpKSB7XG4gICAgbm9kZS5fcmVwbGFjZW1lbnQgPSAnJ1xuICAgIHJldHVyblxuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb252ZXJ0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGNvbnZlcnRlciA9IGNvbnZlcnRlcnNbaV1cblxuICAgIGlmIChjYW5Db252ZXJ0KG5vZGUsIGNvbnZlcnRlci5maWx0ZXIpKSB7XG4gICAgICBpZiAodHlwZW9mIGNvbnZlcnRlci5yZXBsYWNlbWVudCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICdgcmVwbGFjZW1lbnRgIG5lZWRzIHRvIGJlIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgc3RyaW5nJ1xuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIHZhciB3aGl0ZXNwYWNlID0gZmxhbmtpbmdXaGl0ZXNwYWNlKG5vZGUsIGNvbnRlbnQpXG5cbiAgICAgIGlmICh3aGl0ZXNwYWNlLmxlYWRpbmcgfHwgd2hpdGVzcGFjZS50cmFpbGluZykge1xuICAgICAgICBjb250ZW50ID0gY29udGVudC50cmltKClcbiAgICAgIH1cbiAgICAgIHJlcGxhY2VtZW50ID0gd2hpdGVzcGFjZS5sZWFkaW5nICtcbiAgICAgICAgY29udmVydGVyLnJlcGxhY2VtZW50LmNhbGwodG9NYXJrZG93biwgY29udGVudCwgbm9kZSkgK1xuICAgICAgICB3aGl0ZXNwYWNlLnRyYWlsaW5nXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIG5vZGUuX3JlcGxhY2VtZW50ID0gcmVwbGFjZW1lbnRcbn1cblxudG9NYXJrZG93biA9IGZ1bmN0aW9uIChpbnB1dCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIGlmICh0eXBlb2YgaW5wdXQgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihpbnB1dCArICcgaXMgbm90IGEgc3RyaW5nJylcbiAgfVxuXG4gIGlmIChpbnB1dCA9PT0gJycpIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIC8vIEVzY2FwZSBwb3RlbnRpYWwgb2wgdHJpZ2dlcnNcbiAgaW5wdXQgPSBpbnB1dC5yZXBsYWNlKC8oXFxkKylcXC4gL2csICckMVxcXFwuICcpXG5cbiAgdmFyIGNsb25lID0gaHRtbFRvRG9tKGlucHV0KS5ib2R5XG4gIHZhciBub2RlcyA9IGJmc09yZGVyKGNsb25lKVxuICB2YXIgb3V0cHV0XG5cbiAgY29udmVydGVycyA9IG1kQ29udmVydGVycy5zbGljZSgwKVxuICBpZiAob3B0aW9ucy5nZm0pIHtcbiAgICBjb252ZXJ0ZXJzID0gZ2ZtQ29udmVydGVycy5jb25jYXQoY29udmVydGVycylcbiAgfVxuXG4gIGlmIChvcHRpb25zLmNvbnZlcnRlcnMpIHtcbiAgICBjb252ZXJ0ZXJzID0gb3B0aW9ucy5jb252ZXJ0ZXJzLmNvbmNhdChjb252ZXJ0ZXJzKVxuICB9XG5cbiAgLy8gUHJvY2VzcyB0aHJvdWdoIG5vZGVzIGluIHJldmVyc2UgKHNvIGRlZXBlc3QgY2hpbGQgZWxlbWVudHMgYXJlIGZpcnN0KS5cbiAgZm9yICh2YXIgaSA9IG5vZGVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgcHJvY2Vzcyhub2Rlc1tpXSlcbiAgfVxuICBvdXRwdXQgPSBnZXRDb250ZW50KGNsb25lKVxuXG4gIHJldHVybiBvdXRwdXQucmVwbGFjZSgvXltcXHRcXHJcXG5dK3xbXFx0XFxyXFxuXFxzXSskL2csICcnKVxuICAgIC5yZXBsYWNlKC9cXG5cXHMrXFxuL2csICdcXG5cXG4nKVxuICAgIC5yZXBsYWNlKC9cXG57Myx9L2csICdcXG5cXG4nKVxufVxuXG50b01hcmtkb3duLmlzQmxvY2sgPSBpc0Jsb2NrXG50b01hcmtkb3duLmlzVm9pZCA9IGlzVm9pZFxudG9NYXJrZG93bi5vdXRlciA9IG91dGVyXG5cbm1vZHVsZS5leHBvcnRzID0gdG9NYXJrZG93blxuXG59LHtcIi4vbGliL2dmbS1jb252ZXJ0ZXJzXCI6MixcIi4vbGliL2h0bWwtcGFyc2VyXCI6MyxcIi4vbGliL21kLWNvbnZlcnRlcnNcIjo0LFwiY29sbGFwc2Utd2hpdGVzcGFjZVwiOjd9XSwyOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5mdW5jdGlvbiBjZWxsIChjb250ZW50LCBub2RlKSB7XG4gIHZhciBpbmRleCA9IEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwobm9kZS5wYXJlbnROb2RlLmNoaWxkTm9kZXMsIG5vZGUpXG4gIHZhciBwcmVmaXggPSAnICdcbiAgaWYgKGluZGV4ID09PSAwKSBwcmVmaXggPSAnfCAnXG4gIHJldHVybiBwcmVmaXggKyBjb250ZW50ICsgJyB8J1xufVxuXG52YXIgaGlnaGxpZ2h0UmVnRXggPSAvaGlnaGxpZ2h0IGhpZ2hsaWdodC0oXFxTKykvXG5cbm1vZHVsZS5leHBvcnRzID0gW1xuICB7XG4gICAgZmlsdGVyOiAnYnInLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ1xcbidcbiAgICB9XG4gIH0sXG4gIHtcbiAgICBmaWx0ZXI6IFsnZGVsJywgJ3MnLCAnc3RyaWtlJ10sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJ35+JyArIGNvbnRlbnQgKyAnfn4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS50eXBlID09PSAnY2hlY2tib3gnICYmIG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSA9PT0gJ0xJJ1xuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gKG5vZGUuY2hlY2tlZCA/ICdbeF0nIDogJ1sgXScpICsgJyAnXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsndGgnLCAndGQnXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHJldHVybiBjZWxsKGNvbnRlbnQsIG5vZGUpXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICd0cicsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICB2YXIgYm9yZGVyQ2VsbHMgPSAnJ1xuICAgICAgdmFyIGFsaWduTWFwID0geyBsZWZ0OiAnOi0tJywgcmlnaHQ6ICctLTonLCBjZW50ZXI6ICc6LTonIH1cblxuICAgICAgaWYgKG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSA9PT0gJ1RIRUFEJykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBhbGlnbiA9IG5vZGUuY2hpbGROb2Rlc1tpXS5hdHRyaWJ1dGVzLmFsaWduXG4gICAgICAgICAgdmFyIGJvcmRlciA9ICctLS0nXG5cbiAgICAgICAgICBpZiAoYWxpZ24pIGJvcmRlciA9IGFsaWduTWFwW2FsaWduLnZhbHVlXSB8fCBib3JkZXJcblxuICAgICAgICAgIGJvcmRlckNlbGxzICs9IGNlbGwoYm9yZGVyLCBub2RlLmNoaWxkTm9kZXNbaV0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAnXFxuJyArIGNvbnRlbnQgKyAoYm9yZGVyQ2VsbHMgPyAnXFxuJyArIGJvcmRlckNlbGxzIDogJycpXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICd0YWJsZScsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJ1xcblxcbicgKyBjb250ZW50ICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogWyd0aGVhZCcsICd0Ym9keScsICd0Zm9vdCddLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuIGNvbnRlbnRcbiAgICB9XG4gIH0sXG5cbiAgLy8gRmVuY2VkIGNvZGUgYmxvY2tzXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ1BSRScgJiZcbiAgICAgIG5vZGUuZmlyc3RDaGlsZCAmJlxuICAgICAgbm9kZS5maXJzdENoaWxkLm5vZGVOYW1lID09PSAnQ09ERSdcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgcmV0dXJuICdcXG5cXG5gYGBcXG4nICsgbm9kZS5maXJzdENoaWxkLnRleHRDb250ZW50ICsgJ1xcbmBgYFxcblxcbidcbiAgICB9XG4gIH0sXG5cbiAgLy8gU3ludGF4LWhpZ2hsaWdodGVkIGNvZGUgYmxvY2tzXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ1BSRScgJiZcbiAgICAgIG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSA9PT0gJ0RJVicgJiZcbiAgICAgIGhpZ2hsaWdodFJlZ0V4LnRlc3Qobm9kZS5wYXJlbnROb2RlLmNsYXNzTmFtZSlcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgdmFyIGxhbmd1YWdlID0gbm9kZS5wYXJlbnROb2RlLmNsYXNzTmFtZS5tYXRjaChoaWdobGlnaHRSZWdFeClbMV1cbiAgICAgIHJldHVybiAnXFxuXFxuYGBgJyArIGxhbmd1YWdlICsgJ1xcbicgKyBub2RlLnRleHRDb250ZW50ICsgJ1xcbmBgYFxcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnRElWJyAmJlxuICAgICAgaGlnaGxpZ2h0UmVnRXgudGVzdChub2RlLmNsYXNzTmFtZSlcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICdcXG5cXG4nICsgY29udGVudCArICdcXG5cXG4nXG4gICAgfVxuICB9XG5dXG5cbn0se31dLDM6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFNldCB1cCB3aW5kb3cgZm9yIE5vZGUuanNcbiAqL1xuXG52YXIgX3dpbmRvdyA9ICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMpXG5cbi8qXG4gKiBQYXJzaW5nIEhUTUwgc3RyaW5nc1xuICovXG5cbmZ1bmN0aW9uIGNhblBhcnNlSHRtbE5hdGl2ZWx5ICgpIHtcbiAgdmFyIFBhcnNlciA9IF93aW5kb3cuRE9NUGFyc2VyXG4gIHZhciBjYW5QYXJzZSA9IGZhbHNlXG5cbiAgLy8gQWRhcHRlZCBmcm9tIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tLzExMjkwMzFcbiAgLy8gRmlyZWZveC9PcGVyYS9JRSB0aHJvdyBlcnJvcnMgb24gdW5zdXBwb3J0ZWQgdHlwZXNcbiAgdHJ5IHtcbiAgICAvLyBXZWJLaXQgcmV0dXJucyBudWxsIG9uIHVuc3VwcG9ydGVkIHR5cGVzXG4gICAgaWYgKG5ldyBQYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcoJycsICd0ZXh0L2h0bWwnKSkge1xuICAgICAgY2FuUGFyc2UgPSB0cnVlXG4gICAgfVxuICB9IGNhdGNoIChlKSB7fVxuXG4gIHJldHVybiBjYW5QYXJzZVxufVxuXG5mdW5jdGlvbiBjcmVhdGVIdG1sUGFyc2VyICgpIHtcbiAgdmFyIFBhcnNlciA9IGZ1bmN0aW9uICgpIHt9XG5cbiAgLy8gRm9yIE5vZGUuanMgZW52aXJvbm1lbnRzXG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdmFyIGpzZG9tID0gcmVxdWlyZSgnanNkb20nKVxuICAgIFBhcnNlci5wcm90b3R5cGUucGFyc2VGcm9tU3RyaW5nID0gZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgcmV0dXJuIGpzZG9tLmpzZG9tKHN0cmluZywge1xuICAgICAgICBmZWF0dXJlczoge1xuICAgICAgICAgIEZldGNoRXh0ZXJuYWxSZXNvdXJjZXM6IFtdLFxuICAgICAgICAgIFByb2Nlc3NFeHRlcm5hbFJlc291cmNlczogZmFsc2VcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFzaG91bGRVc2VBY3RpdmVYKCkpIHtcbiAgICAgIFBhcnNlci5wcm90b3R5cGUucGFyc2VGcm9tU3RyaW5nID0gZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICB2YXIgZG9jID0gZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCcnKVxuICAgICAgICBkb2Mub3BlbigpXG4gICAgICAgIGRvYy53cml0ZShzdHJpbmcpXG4gICAgICAgIGRvYy5jbG9zZSgpXG4gICAgICAgIHJldHVybiBkb2NcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgUGFyc2VyLnByb3RvdHlwZS5wYXJzZUZyb21TdHJpbmcgPSBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHZhciBkb2MgPSBuZXcgd2luZG93LkFjdGl2ZVhPYmplY3QoJ2h0bWxmaWxlJylcbiAgICAgICAgZG9jLmRlc2lnbk1vZGUgPSAnb24nIC8vIGRpc2FibGUgb24tcGFnZSBzY3JpcHRzXG4gICAgICAgIGRvYy5vcGVuKClcbiAgICAgICAgZG9jLndyaXRlKHN0cmluZylcbiAgICAgICAgZG9jLmNsb3NlKClcbiAgICAgICAgcmV0dXJuIGRvY1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gUGFyc2VyXG59XG5cbmZ1bmN0aW9uIHNob3VsZFVzZUFjdGl2ZVggKCkge1xuICB2YXIgdXNlQWN0aXZlWCA9IGZhbHNlXG5cbiAgdHJ5IHtcbiAgICBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoJycpLm9wZW4oKVxuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKHdpbmRvdy5BY3RpdmVYT2JqZWN0KSB1c2VBY3RpdmVYID0gdHJ1ZVxuICB9XG5cbiAgcmV0dXJuIHVzZUFjdGl2ZVhcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjYW5QYXJzZUh0bWxOYXRpdmVseSgpID8gX3dpbmRvdy5ET01QYXJzZXIgOiBjcmVhdGVIdG1sUGFyc2VyKClcblxufSx7XCJqc2RvbVwiOjZ9XSw0OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IFtcbiAge1xuICAgIGZpbHRlcjogJ3AnLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICdcXG5cXG4nICsgY29udGVudCArICdcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICdicicsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnICBcXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsnaDEnLCAnaDInLCAnaDMnLCAnaDQnLCAnaDUnLCAnaDYnXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHZhciBoTGV2ZWwgPSBub2RlLm5vZGVOYW1lLmNoYXJBdCgxKVxuICAgICAgdmFyIGhQcmVmaXggPSAnJ1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoTGV2ZWw7IGkrKykge1xuICAgICAgICBoUHJlZml4ICs9ICcjJ1xuICAgICAgfVxuICAgICAgcmV0dXJuICdcXG5cXG4nICsgaFByZWZpeCArICcgJyArIGNvbnRlbnQgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAnaHInLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ1xcblxcbiogKiAqXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBbJ2VtJywgJ2knXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnXycgKyBjb250ZW50ICsgJ18nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsnc3Ryb25nJywgJ2InXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnKionICsgY29udGVudCArICcqKidcbiAgICB9XG4gIH0sXG5cbiAgLy8gSW5saW5lIGNvZGVcbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHZhciBoYXNTaWJsaW5ncyA9IG5vZGUucHJldmlvdXNTaWJsaW5nIHx8IG5vZGUubmV4dFNpYmxpbmdcbiAgICAgIHZhciBpc0NvZGVCbG9jayA9IG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSA9PT0gJ1BSRScgJiYgIWhhc1NpYmxpbmdzXG5cbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnQ09ERScgJiYgIWlzQ29kZUJsb2NrXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnYCcgKyBjb250ZW50ICsgJ2AnXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ0EnICYmIG5vZGUuZ2V0QXR0cmlidXRlKCdocmVmJylcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgdmFyIHRpdGxlUGFydCA9IG5vZGUudGl0bGUgPyAnIFwiJyArIG5vZGUudGl0bGUgKyAnXCInIDogJydcbiAgICAgIHJldHVybiAnWycgKyBjb250ZW50ICsgJ10oJyArIG5vZGUuZ2V0QXR0cmlidXRlKCdocmVmJykgKyB0aXRsZVBhcnQgKyAnKSdcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ2ltZycsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICB2YXIgYWx0ID0gbm9kZS5hbHQgfHwgJydcbiAgICAgIHZhciBzcmMgPSBub2RlLmdldEF0dHJpYnV0ZSgnc3JjJykgfHwgJydcbiAgICAgIHZhciB0aXRsZSA9IG5vZGUudGl0bGUgfHwgJydcbiAgICAgIHZhciB0aXRsZVBhcnQgPSB0aXRsZSA/ICcgXCInICsgdGl0bGUgKyAnXCInIDogJydcbiAgICAgIHJldHVybiBzcmMgPyAnIVsnICsgYWx0ICsgJ10nICsgJygnICsgc3JjICsgdGl0bGVQYXJ0ICsgJyknIDogJydcbiAgICB9XG4gIH0sXG5cbiAgLy8gQ29kZSBibG9ja3NcbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnUFJFJyAmJiBub2RlLmZpcnN0Q2hpbGQubm9kZU5hbWUgPT09ICdDT0RFJ1xuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gJ1xcblxcbiAgICAnICsgbm9kZS5maXJzdENoaWxkLnRleHRDb250ZW50LnJlcGxhY2UoL1xcbi9nLCAnXFxuICAgICcpICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ2Jsb2NrcXVvdGUnLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgY29udGVudCA9IGNvbnRlbnQudHJpbSgpXG4gICAgICBjb250ZW50ID0gY29udGVudC5yZXBsYWNlKC9cXG57Myx9L2csICdcXG5cXG4nKVxuICAgICAgY29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvXi9nbSwgJz4gJylcbiAgICAgIHJldHVybiAnXFxuXFxuJyArIGNvbnRlbnQgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAnbGknLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgY29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvXlxccysvLCAnJykucmVwbGFjZSgvXFxuL2dtLCAnXFxuICAgICcpXG4gICAgICB2YXIgcHJlZml4ID0gJyogICAnXG4gICAgICB2YXIgcGFyZW50ID0gbm9kZS5wYXJlbnROb2RlXG4gICAgICB2YXIgaW5kZXggPSBBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKHBhcmVudC5jaGlsZHJlbiwgbm9kZSkgKyAxXG5cbiAgICAgIHByZWZpeCA9IC9vbC9pLnRlc3QocGFyZW50Lm5vZGVOYW1lKSA/IGluZGV4ICsgJy4gICcgOiAnKiAgICdcbiAgICAgIHJldHVybiBwcmVmaXggKyBjb250ZW50XG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsndWwnLCAnb2wnXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHZhciBzdHJpbmdzID0gW11cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHN0cmluZ3MucHVzaChub2RlLmNoaWxkTm9kZXNbaV0uX3JlcGxhY2VtZW50KVxuICAgICAgfVxuXG4gICAgICBpZiAoL2xpL2kudGVzdChub2RlLnBhcmVudE5vZGUubm9kZU5hbWUpKSB7XG4gICAgICAgIHJldHVybiAnXFxuJyArIHN0cmluZ3Muam9pbignXFxuJylcbiAgICAgIH1cbiAgICAgIHJldHVybiAnXFxuXFxuJyArIHN0cmluZ3Muam9pbignXFxuJykgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgcmV0dXJuIHRoaXMuaXNCbG9jayhub2RlKVxuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gJ1xcblxcbicgKyB0aGlzLm91dGVyKG5vZGUsIGNvbnRlbnQpICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAgLy8gQW55dGhpbmcgZWxzZSFcbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgcmV0dXJuIHRoaXMub3V0ZXIobm9kZSwgY29udGVudClcbiAgICB9XG4gIH1cbl1cblxufSx7fV0sNTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiAqIFRoaXMgZmlsZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBmcm9tIGBidWlsZC5qc2AuXG4gKiBEbyBub3QgbWFudWFsbHkgZWRpdC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IFtcbiAgXCJhZGRyZXNzXCIsXG4gIFwiYXJ0aWNsZVwiLFxuICBcImFzaWRlXCIsXG4gIFwiYXVkaW9cIixcbiAgXCJibG9ja3F1b3RlXCIsXG4gIFwiY2FudmFzXCIsXG4gIFwiZGRcIixcbiAgXCJkaXZcIixcbiAgXCJkbFwiLFxuICBcImZpZWxkc2V0XCIsXG4gIFwiZmlnY2FwdGlvblwiLFxuICBcImZpZ3VyZVwiLFxuICBcImZvb3RlclwiLFxuICBcImZvcm1cIixcbiAgXCJoMVwiLFxuICBcImgyXCIsXG4gIFwiaDNcIixcbiAgXCJoNFwiLFxuICBcImg1XCIsXG4gIFwiaDZcIixcbiAgXCJoZWFkZXJcIixcbiAgXCJoZ3JvdXBcIixcbiAgXCJoclwiLFxuICBcIm1haW5cIixcbiAgXCJuYXZcIixcbiAgXCJub3NjcmlwdFwiLFxuICBcIm9sXCIsXG4gIFwib3V0cHV0XCIsXG4gIFwicFwiLFxuICBcInByZVwiLFxuICBcInNlY3Rpb25cIixcbiAgXCJ0YWJsZVwiLFxuICBcInRmb290XCIsXG4gIFwidWxcIixcbiAgXCJ2aWRlb1wiXG5dO1xuXG59LHt9XSw2OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcblxufSx7fV0sNzpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCc7XG5cbnZhciB2b2lkRWxlbWVudHMgPSByZXF1aXJlKCd2b2lkLWVsZW1lbnRzJyk7XG5PYmplY3Qua2V5cyh2b2lkRWxlbWVudHMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgdm9pZEVsZW1lbnRzW25hbWUudG9VcHBlckNhc2UoKV0gPSAxO1xufSk7XG5cbnZhciBibG9ja0VsZW1lbnRzID0ge307XG5yZXF1aXJlKCdibG9jay1lbGVtZW50cycpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgYmxvY2tFbGVtZW50c1tuYW1lLnRvVXBwZXJDYXNlKCldID0gMTtcbn0pO1xuXG4vKipcbiAqIGlzQmxvY2tFbGVtKG5vZGUpIGRldGVybWluZXMgaWYgdGhlIGdpdmVuIG5vZGUgaXMgYSBibG9jayBlbGVtZW50LlxuICpcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNCbG9ja0VsZW0obm9kZSkge1xuICByZXR1cm4gISEobm9kZSAmJiBibG9ja0VsZW1lbnRzW25vZGUubm9kZU5hbWVdKTtcbn1cblxuLyoqXG4gKiBpc1ZvaWQobm9kZSkgZGV0ZXJtaW5lcyBpZiB0aGUgZ2l2ZW4gbm9kZSBpcyBhIHZvaWQgZWxlbWVudC5cbiAqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGVcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzVm9pZChub2RlKSB7XG4gIHJldHVybiAhIShub2RlICYmIHZvaWRFbGVtZW50c1tub2RlLm5vZGVOYW1lXSk7XG59XG5cbi8qKlxuICogd2hpdGVzcGFjZShlbGVtIFssIGlzQmxvY2tdKSByZW1vdmVzIGV4dHJhbmVvdXMgd2hpdGVzcGFjZSBmcm9tIGFuXG4gKiB0aGUgZ2l2ZW4gZWxlbWVudC4gVGhlIGZ1bmN0aW9uIGlzQmxvY2sgbWF5IG9wdGlvbmFsbHkgYmUgcGFzc2VkIGluXG4gKiB0byBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgYW4gZWxlbWVudCBpcyBhIGJsb2NrIGVsZW1lbnQ7IGlmIG5vbmVcbiAqIGlzIHByb3ZpZGVkLCBkZWZhdWx0cyB0byB1c2luZyB0aGUgbGlzdCBvZiBibG9jayBlbGVtZW50cyBwcm92aWRlZFxuICogYnkgdGhlIGBibG9jay1lbGVtZW50c2AgbW9kdWxlLlxuICpcbiAqIEBwYXJhbSB7Tm9kZX0gZWxlbVxuICogQHBhcmFtIHtGdW5jdGlvbn0gYmxvY2tUZXN0XG4gKi9cbmZ1bmN0aW9uIGNvbGxhcHNlV2hpdGVzcGFjZShlbGVtLCBpc0Jsb2NrKSB7XG4gIGlmICghZWxlbS5maXJzdENoaWxkIHx8IGVsZW0ubm9kZU5hbWUgPT09ICdQUkUnKSByZXR1cm47XG5cbiAgaWYgKHR5cGVvZiBpc0Jsb2NrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgaXNCbG9jayA9IGlzQmxvY2tFbGVtO1xuICB9XG5cbiAgdmFyIHByZXZUZXh0ID0gbnVsbDtcbiAgdmFyIHByZXZWb2lkID0gZmFsc2U7XG5cbiAgdmFyIHByZXYgPSBudWxsO1xuICB2YXIgbm9kZSA9IG5leHQocHJldiwgZWxlbSk7XG5cbiAgd2hpbGUgKG5vZGUgIT09IGVsZW0pIHtcbiAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgLy8gTm9kZS5URVhUX05PREVcbiAgICAgIHZhciB0ZXh0ID0gbm9kZS5kYXRhLnJlcGxhY2UoL1sgXFxyXFxuXFx0XSsvZywgJyAnKTtcblxuICAgICAgaWYgKCghcHJldlRleHQgfHwgLyAkLy50ZXN0KHByZXZUZXh0LmRhdGEpKSAmJiAhcHJldlZvaWQgJiYgdGV4dFswXSA9PT0gJyAnKSB7XG4gICAgICAgIHRleHQgPSB0ZXh0LnN1YnN0cigxKTtcbiAgICAgIH1cblxuICAgICAgLy8gYHRleHRgIG1pZ2h0IGJlIGVtcHR5IGF0IHRoaXMgcG9pbnQuXG4gICAgICBpZiAoIXRleHQpIHtcbiAgICAgICAgbm9kZSA9IHJlbW92ZShub2RlKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIG5vZGUuZGF0YSA9IHRleHQ7XG4gICAgICBwcmV2VGV4dCA9IG5vZGU7XG4gICAgfSBlbHNlIGlmIChub2RlLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICAvLyBOb2RlLkVMRU1FTlRfTk9ERVxuICAgICAgaWYgKGlzQmxvY2sobm9kZSkgfHwgbm9kZS5ub2RlTmFtZSA9PT0gJ0JSJykge1xuICAgICAgICBpZiAocHJldlRleHQpIHtcbiAgICAgICAgICBwcmV2VGV4dC5kYXRhID0gcHJldlRleHQuZGF0YS5yZXBsYWNlKC8gJC8sICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByZXZUZXh0ID0gbnVsbDtcbiAgICAgICAgcHJldlZvaWQgPSBmYWxzZTtcbiAgICAgIH0gZWxzZSBpZiAoaXNWb2lkKG5vZGUpKSB7XG4gICAgICAgIC8vIEF2b2lkIHRyaW1taW5nIHNwYWNlIGFyb3VuZCBub24tYmxvY2ssIG5vbi1CUiB2b2lkIGVsZW1lbnRzLlxuICAgICAgICBwcmV2VGV4dCA9IG51bGw7XG4gICAgICAgIHByZXZWb2lkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbm9kZSA9IHJlbW92ZShub2RlKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBuZXh0Tm9kZSA9IG5leHQocHJldiwgbm9kZSk7XG4gICAgcHJldiA9IG5vZGU7XG4gICAgbm9kZSA9IG5leHROb2RlO1xuICB9XG5cbiAgaWYgKHByZXZUZXh0KSB7XG4gICAgcHJldlRleHQuZGF0YSA9IHByZXZUZXh0LmRhdGEucmVwbGFjZSgvICQvLCAnJyk7XG4gICAgaWYgKCFwcmV2VGV4dC5kYXRhKSB7XG4gICAgICByZW1vdmUocHJldlRleHQpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIHJlbW92ZShub2RlKSByZW1vdmVzIHRoZSBnaXZlbiBub2RlIGZyb20gdGhlIERPTSBhbmQgcmV0dXJucyB0aGVcbiAqIG5leHQgbm9kZSBpbiB0aGUgc2VxdWVuY2UuXG4gKlxuICogQHBhcmFtIHtOb2RlfSBub2RlXG4gKiBAcmV0dXJuIHtOb2RlfSBub2RlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZShub2RlKSB7XG4gIHZhciBuZXh0ID0gbm9kZS5uZXh0U2libGluZyB8fCBub2RlLnBhcmVudE5vZGU7XG5cbiAgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuXG4gIHJldHVybiBuZXh0O1xufVxuXG4vKipcbiAqIG5leHQocHJldiwgY3VycmVudCkgcmV0dXJucyB0aGUgbmV4dCBub2RlIGluIHRoZSBzZXF1ZW5jZSwgZ2l2ZW4gdGhlXG4gKiBjdXJyZW50IGFuZCBwcmV2aW91cyBub2Rlcy5cbiAqXG4gKiBAcGFyYW0ge05vZGV9IHByZXZcbiAqIEBwYXJhbSB7Tm9kZX0gY3VycmVudFxuICogQHJldHVybiB7Tm9kZX1cbiAqL1xuZnVuY3Rpb24gbmV4dChwcmV2LCBjdXJyZW50KSB7XG4gIGlmIChwcmV2ICYmIHByZXYucGFyZW50Tm9kZSA9PT0gY3VycmVudCB8fCBjdXJyZW50Lm5vZGVOYW1lID09PSAnUFJFJykge1xuICAgIHJldHVybiBjdXJyZW50Lm5leHRTaWJsaW5nIHx8IGN1cnJlbnQucGFyZW50Tm9kZTtcbiAgfVxuXG4gIHJldHVybiBjdXJyZW50LmZpcnN0Q2hpbGQgfHwgY3VycmVudC5uZXh0U2libGluZyB8fCBjdXJyZW50LnBhcmVudE5vZGU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY29sbGFwc2VXaGl0ZXNwYWNlO1xuXG59LHtcImJsb2NrLWVsZW1lbnRzXCI6NSxcInZvaWQtZWxlbWVudHNcIjo4fV0sODpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiAqIFRoaXMgZmlsZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBmcm9tIGBwcmUtcHVibGlzaC5qc2AuXG4gKiBEbyBub3QgbWFudWFsbHkgZWRpdC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgXCJhcmVhXCI6IHRydWUsXG4gIFwiYmFzZVwiOiB0cnVlLFxuICBcImJyXCI6IHRydWUsXG4gIFwiY29sXCI6IHRydWUsXG4gIFwiZW1iZWRcIjogdHJ1ZSxcbiAgXCJoclwiOiB0cnVlLFxuICBcImltZ1wiOiB0cnVlLFxuICBcImlucHV0XCI6IHRydWUsXG4gIFwia2V5Z2VuXCI6IHRydWUsXG4gIFwibGlua1wiOiB0cnVlLFxuICBcIm1lbnVpdGVtXCI6IHRydWUsXG4gIFwibWV0YVwiOiB0cnVlLFxuICBcInBhcmFtXCI6IHRydWUsXG4gIFwic291cmNlXCI6IHRydWUsXG4gIFwidHJhY2tcIjogdHJ1ZSxcbiAgXCJ3YnJcIjogdHJ1ZVxufTtcblxufSx7fV19LHt9LFsxXSkoMSlcbn0pOyIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogYm9vdHN0cmFwLW1hcmtkb3duLmpzIHYyLjEwLjBcbiAqIGh0dHA6Ly9naXRodWIuY29tL3Rvb3BheS9ib290c3RyYXAtbWFya2Rvd25cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29weXJpZ2h0IDIwMTMtMjAxNiBUYXVmYW4gQWRpdHlhXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cbihmdW5jdGlvbihmYWN0b3J5KXtcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgLy9SZXF1aXJlSlNcbiAgICAgICAgZGVmaW5lKFtcImpxdWVyeVwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgLy9CYWNrYm9uZS5qc1xuICAgICAgICBmYWN0b3J5KHJlcXVpcmUoJ2pxdWVyeScpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvL0pxdWVyeSBwbHVnaW5cbiAgICAgICAgZmFjdG9yeShqUXVlcnkpO1xuICAgIH1cbn0oZnVuY3Rpb24oJCl7XG4gIFwidXNlIHN0cmljdFwiOyAvLyBqc2hpbnQgO187XG5cbiAgLyogTUFSS0RPV04gQ0xBU1MgREVGSU5JVElPTlxuICAgKiA9PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG4gIHZhciBNYXJrZG93biA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgLy8gQFRPRE8gOiByZW1vdmUgdGhpcyBCQyBvbiBuZXh0IG1ham9yIHJlbGVhc2VcbiAgICAvLyBAc2VlIDogaHR0cHM6Ly9naXRodWIuY29tL3Rvb3BheS9ib290c3RyYXAtbWFya2Rvd24vaXNzdWVzLzEwOVxuICAgIHZhciBvcHRzID0gWydhdXRvZm9jdXMnLCAnc2F2YWJsZScsICdoaWRlYWJsZScsICd3aWR0aCcsIFxuICAgICAgJ2hlaWdodCcsICdyZXNpemUnLCAnaWNvbmxpYnJhcnknLCAnbGFuZ3VhZ2UnLCBcbiAgICAgICdmb290ZXInLCAnZnVsbHNjcmVlbicsICdoaWRkZW5CdXR0b25zJywgJ2Rpc2FibGVkQnV0dG9ucyddO1xuICAgICQuZWFjaChvcHRzLGZ1bmN0aW9uKF8sIG9wdCl7XG4gICAgICBpZiAodHlwZW9mICQoZWxlbWVudCkuZGF0YShvcHQpICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBvcHRpb25zID0gdHlwZW9mIG9wdGlvbnMgPT0gJ29iamVjdCcgPyBvcHRpb25zIDoge31cbiAgICAgICAgb3B0aW9uc1tvcHRdID0gJChlbGVtZW50KS5kYXRhKG9wdClcbiAgICAgIH1cbiAgICB9KTtcbiAgICAvLyBFbmQgQkNcblxuICAgIC8vIENsYXNzIFByb3BlcnRpZXNcbiAgICB0aGlzLiRucyAgICAgICAgICAgPSAnYm9vdHN0cmFwLW1hcmtkb3duJztcbiAgICB0aGlzLiRlbGVtZW50ICAgICAgPSAkKGVsZW1lbnQpO1xuICAgIHRoaXMuJGVkaXRhYmxlICAgICA9IHtlbDpudWxsLCB0eXBlOm51bGwsYXR0cktleXM6W10sIGF0dHJWYWx1ZXM6W10sIGNvbnRlbnQ6bnVsbH07XG4gICAgdGhpcy4kb3B0aW9ucyAgICAgID0gJC5leHRlbmQodHJ1ZSwge30sICQuZm4ubWFya2Rvd24uZGVmYXVsdHMsIG9wdGlvbnMsIHRoaXMuJGVsZW1lbnQuZGF0YSgnb3B0aW9ucycpKTtcbiAgICB0aGlzLiRvbGRDb250ZW50ICAgPSBudWxsO1xuICAgIHRoaXMuJGlzUHJldmlldyAgICA9IGZhbHNlO1xuICAgIHRoaXMuJGlzRnVsbHNjcmVlbiA9IGZhbHNlO1xuICAgIHRoaXMuJGVkaXRvciAgICAgICA9IG51bGw7XG4gICAgdGhpcy4kdGV4dGFyZWEgICAgID0gbnVsbDtcbiAgICB0aGlzLiRoYW5kbGVyICAgICAgPSBbXTtcbiAgICB0aGlzLiRjYWxsYmFjayAgICAgPSBbXTtcbiAgICB0aGlzLiRuZXh0VGFiICAgICAgPSBbXTtcblxuICAgIHRoaXMuc2hvd0VkaXRvcigpO1xuICB9O1xuXG4gIE1hcmtkb3duLnByb3RvdHlwZSA9IHtcblxuICAgIGNvbnN0cnVjdG9yOiBNYXJrZG93blxuXG4gICwgX19hbHRlckJ1dHRvbnM6IGZ1bmN0aW9uKG5hbWUsYWx0ZXIpIHtcbiAgICAgIHZhciBoYW5kbGVyID0gdGhpcy4kaGFuZGxlciwgaXNBbGwgPSAobmFtZSA9PSAnYWxsJyksdGhhdCA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChoYW5kbGVyLGZ1bmN0aW9uKGssdikge1xuICAgICAgICB2YXIgaGFsdCA9IHRydWU7XG4gICAgICAgIGlmIChpc0FsbCkge1xuICAgICAgICAgIGhhbHQgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBoYWx0ID0gdi5pbmRleE9mKG5hbWUpIDwgMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChoYWx0ID09PSBmYWxzZSkge1xuICAgICAgICAgIGFsdGVyKHRoYXQuJGVkaXRvci5maW5kKCdidXR0b25bZGF0YS1oYW5kbGVyPVwiJyt2KydcIl0nKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAsIF9fYnVpbGRCdXR0b25zOiBmdW5jdGlvbihidXR0b25zQXJyYXksIGNvbnRhaW5lcikge1xuICAgICAgdmFyIGksXG4gICAgICAgICAgbnMgPSB0aGlzLiRucyxcbiAgICAgICAgICBoYW5kbGVyID0gdGhpcy4kaGFuZGxlcixcbiAgICAgICAgICBjYWxsYmFjayA9IHRoaXMuJGNhbGxiYWNrO1xuXG4gICAgICBmb3IgKGk9MDtpPGJ1dHRvbnNBcnJheS5sZW5ndGg7aSsrKSB7XG4gICAgICAgIC8vIEJ1aWxkIGVhY2ggZ3JvdXAgY29udGFpbmVyXG4gICAgICAgIHZhciB5LCBidG5Hcm91cHMgPSBidXR0b25zQXJyYXlbaV07XG4gICAgICAgIGZvciAoeT0wO3k8YnRuR3JvdXBzLmxlbmd0aDt5KyspIHtcbiAgICAgICAgICAvLyBCdWlsZCBlYWNoIGJ1dHRvbiBncm91cFxuICAgICAgICAgIHZhciB6LFxuICAgICAgICAgICAgICBidXR0b25zID0gYnRuR3JvdXBzW3ldLmRhdGEsXG4gICAgICAgICAgICAgIGJ0bkdyb3VwQ29udGFpbmVyID0gJCgnPGRpdi8+Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ2J0bi1ncm91cCdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgIGZvciAoej0wO3o8YnV0dG9ucy5sZW5ndGg7eisrKSB7XG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gYnV0dG9uc1t6XSxcbiAgICAgICAgICAgICAgICBidXR0b25Db250YWluZXIsIGJ1dHRvbkljb25Db250YWluZXIsXG4gICAgICAgICAgICAgICAgYnV0dG9uSGFuZGxlciA9IG5zKyctJytidXR0b24ubmFtZSxcbiAgICAgICAgICAgICAgICBidXR0b25JY29uID0gdGhpcy5fX2dldEljb24oYnV0dG9uLmljb24pLFxuICAgICAgICAgICAgICAgIGJ0blRleHQgPSBidXR0b24uYnRuVGV4dCA/IGJ1dHRvbi5idG5UZXh0IDogJycsXG4gICAgICAgICAgICAgICAgYnRuQ2xhc3MgPSBidXR0b24uYnRuQ2xhc3MgPyBidXR0b24uYnRuQ2xhc3MgOiAnYnRuJyxcbiAgICAgICAgICAgICAgICB0YWJJbmRleCA9IGJ1dHRvbi50YWJJbmRleCA/IGJ1dHRvbi50YWJJbmRleCA6ICctMScsXG4gICAgICAgICAgICAgICAgaG90a2V5ID0gdHlwZW9mIGJ1dHRvbi5ob3RrZXkgIT09ICd1bmRlZmluZWQnID8gYnV0dG9uLmhvdGtleSA6ICcnLFxuICAgICAgICAgICAgICAgIGhvdGtleUNhcHRpb24gPSB0eXBlb2YgalF1ZXJ5LmhvdGtleXMgIT09ICd1bmRlZmluZWQnICYmIGhvdGtleSAhPT0gJycgPyAnICgnK2hvdGtleSsnKScgOiAnJztcblxuICAgICAgICAgICAgLy8gQ29uc3RydWN0IHRoZSBidXR0b24gb2JqZWN0XG4gICAgICAgICAgICBidXR0b25Db250YWluZXIgPSAkKCc8YnV0dG9uPjwvYnV0dG9uPicpO1xuICAgICAgICAgICAgYnV0dG9uQ29udGFpbmVyLnRleHQoJyAnICsgdGhpcy5fX2xvY2FsaXplKGJ0blRleHQpKS5hZGRDbGFzcygnYnRuLWRlZmF1bHQgYnRuLXNtJykuYWRkQ2xhc3MoYnRuQ2xhc3MpO1xuICAgICAgICAgICAgaWYoYnRuQ2xhc3MubWF0Y2goL2J0blxcLShwcmltYXJ5fHN1Y2Nlc3N8aW5mb3x3YXJuaW5nfGRhbmdlcnxsaW5rKS8pKXtcbiAgICAgICAgICAgICAgICBidXR0b25Db250YWluZXIucmVtb3ZlQ2xhc3MoJ2J0bi1kZWZhdWx0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidXR0b25Db250YWluZXIuYXR0cih7XG4gICAgICAgICAgICAgICAgJ3R5cGUnOiAnYnV0dG9uJyxcbiAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9fbG9jYWxpemUoYnV0dG9uLnRpdGxlKSArIGhvdGtleUNhcHRpb24sXG4gICAgICAgICAgICAgICAgJ3RhYmluZGV4JzogdGFiSW5kZXgsXG4gICAgICAgICAgICAgICAgJ2RhdGEtcHJvdmlkZXInOiBucyxcbiAgICAgICAgICAgICAgICAnZGF0YS1oYW5kbGVyJzogYnV0dG9uSGFuZGxlcixcbiAgICAgICAgICAgICAgICAnZGF0YS1ob3RrZXknOiBob3RrZXlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKGJ1dHRvbi50b2dnbGUgPT09IHRydWUpe1xuICAgICAgICAgICAgICBidXR0b25Db250YWluZXIuYXR0cignZGF0YS10b2dnbGUnLCAnYnV0dG9uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidXR0b25JY29uQ29udGFpbmVyID0gJCgnPHNwYW4vPicpO1xuICAgICAgICAgICAgYnV0dG9uSWNvbkNvbnRhaW5lci5hZGRDbGFzcyhidXR0b25JY29uKTtcbiAgICAgICAgICAgIGJ1dHRvbkljb25Db250YWluZXIucHJlcGVuZFRvKGJ1dHRvbkNvbnRhaW5lcik7XG5cbiAgICAgICAgICAgIC8vIEF0dGFjaCB0aGUgYnV0dG9uIG9iamVjdFxuICAgICAgICAgICAgYnRuR3JvdXBDb250YWluZXIuYXBwZW5kKGJ1dHRvbkNvbnRhaW5lcik7XG5cbiAgICAgICAgICAgIC8vIFJlZ2lzdGVyIGhhbmRsZXIgYW5kIGNhbGxiYWNrXG4gICAgICAgICAgICBoYW5kbGVyLnB1c2goYnV0dG9uSGFuZGxlcik7XG4gICAgICAgICAgICBjYWxsYmFjay5wdXNoKGJ1dHRvbi5jYWxsYmFjayk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQXR0YWNoIHRoZSBidXR0b24gZ3JvdXAgaW50byBjb250YWluZXIgZG9tXG4gICAgICAgICAgY29udGFpbmVyLmFwcGVuZChidG5Hcm91cENvbnRhaW5lcik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbnRhaW5lcjtcbiAgICB9XG4gICwgX19zZXRMaXN0ZW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAvLyBTZXQgc2l6ZSBhbmQgcmVzaXphYmxlIFByb3BlcnRpZXNcbiAgICAgIHZhciBoYXNSb3dzID0gdHlwZW9mIHRoaXMuJHRleHRhcmVhLmF0dHIoJ3Jvd3MnKSAhPT0gJ3VuZGVmaW5lZCcsXG4gICAgICAgICAgbWF4Um93cyA9IHRoaXMuJHRleHRhcmVhLnZhbCgpLnNwbGl0KFwiXFxuXCIpLmxlbmd0aCA+IDUgPyB0aGlzLiR0ZXh0YXJlYS52YWwoKS5zcGxpdChcIlxcblwiKS5sZW5ndGggOiAnNScsXG4gICAgICAgICAgcm93c1ZhbCA9IGhhc1Jvd3MgPyB0aGlzLiR0ZXh0YXJlYS5hdHRyKCdyb3dzJykgOiBtYXhSb3dzO1xuXG4gICAgICB0aGlzLiR0ZXh0YXJlYS5hdHRyKCdyb3dzJyxyb3dzVmFsKTtcbiAgICAgIGlmICh0aGlzLiRvcHRpb25zLnJlc2l6ZSkge1xuICAgICAgICB0aGlzLiR0ZXh0YXJlYS5jc3MoJ3Jlc2l6ZScsdGhpcy4kb3B0aW9ucy5yZXNpemUpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLiR0ZXh0YXJlYS5vbih7XG4gICAgICAgICAgJ2ZvY3VzJyA6ICQucHJveHkodGhpcy5mb2N1cywgdGhpcyksXG4gICAgICAgICAgJ2tleXVwJyA6ICQucHJveHkodGhpcy5rZXl1cCwgdGhpcyksXG4gICAgICAgICAgJ2NoYW5nZScgOiAkLnByb3h5KHRoaXMuY2hhbmdlLCB0aGlzKSxcbiAgICAgICAgICAnc2VsZWN0JyA6ICQucHJveHkodGhpcy5zZWxlY3QsIHRoaXMpXG4gICAgICB9KTtcblxuICAgICAgaWYgKHRoaXMuZXZlbnRTdXBwb3J0ZWQoJ2tleWRvd24nKSkge1xuICAgICAgICB0aGlzLiR0ZXh0YXJlYS5vbigna2V5ZG93bicsICQucHJveHkodGhpcy5rZXlkb3duLCB0aGlzKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmV2ZW50U3VwcG9ydGVkKCdrZXlwcmVzcycpKSB7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhLm9uKCdrZXlwcmVzcycsICQucHJveHkodGhpcy5rZXlwcmVzcywgdGhpcykpXG4gICAgICB9XG5cbiAgICAgIC8vIFJlLWF0dGFjaCBtYXJrZG93biBkYXRhXG4gICAgICB0aGlzLiR0ZXh0YXJlYS5kYXRhKCdtYXJrZG93bicsdGhpcyk7XG4gICAgfVxuXG4gICwgX19oYW5kbGU6IGZ1bmN0aW9uKGUpIHtcbiAgICAgIHZhciB0YXJnZXQgPSAkKGUuY3VycmVudFRhcmdldCksXG4gICAgICAgICAgaGFuZGxlciA9IHRoaXMuJGhhbmRsZXIsXG4gICAgICAgICAgY2FsbGJhY2sgPSB0aGlzLiRjYWxsYmFjayxcbiAgICAgICAgICBoYW5kbGVyTmFtZSA9IHRhcmdldC5hdHRyKCdkYXRhLWhhbmRsZXInKSxcbiAgICAgICAgICBjYWxsYmFja0luZGV4ID0gaGFuZGxlci5pbmRleE9mKGhhbmRsZXJOYW1lKSxcbiAgICAgICAgICBjYWxsYmFja0hhbmRsZXIgPSBjYWxsYmFja1tjYWxsYmFja0luZGV4XTtcblxuICAgICAgLy8gVHJpZ2dlciB0aGUgZm9jdXNpblxuICAgICAgJChlLmN1cnJlbnRUYXJnZXQpLmZvY3VzKCk7XG5cbiAgICAgIGNhbGxiYWNrSGFuZGxlcih0aGlzKTtcblxuICAgICAgLy8gVHJpZ2dlciBvbkNoYW5nZSBmb3IgZWFjaCBidXR0b24gaGFuZGxlXG4gICAgICB0aGlzLmNoYW5nZSh0aGlzKTtcblxuICAgICAgLy8gVW5sZXNzIGl0IHdhcyB0aGUgc2F2ZSBoYW5kbGVyLFxuICAgICAgLy8gZm9jdXNpbiB0aGUgdGV4dGFyZWFcbiAgICAgIGlmIChoYW5kbGVyTmFtZS5pbmRleE9mKCdjbWRTYXZlJykgPCAwKSB7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhLmZvY3VzKCk7XG4gICAgICB9XG5cbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgLCBfX2xvY2FsaXplOiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgIHZhciBtZXNzYWdlcyA9ICQuZm4ubWFya2Rvd24ubWVzc2FnZXMsXG4gICAgICAgICAgbGFuZ3VhZ2UgPSB0aGlzLiRvcHRpb25zLmxhbmd1YWdlO1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgbWVzc2FnZXMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIHR5cGVvZiBtZXNzYWdlc1tsYW5ndWFnZV0gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIHR5cGVvZiBtZXNzYWdlc1tsYW5ndWFnZV1bc3RyaW5nXSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbWVzc2FnZXNbbGFuZ3VhZ2VdW3N0cmluZ107XG4gICAgICB9XG4gICAgICByZXR1cm4gc3RyaW5nO1xuICAgIH1cblxuICAsIF9fZ2V0SWNvbjogZnVuY3Rpb24oc3JjKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBzcmMgPT0gJ29iamVjdCcgPyBzcmNbdGhpcy4kb3B0aW9ucy5pY29ubGlicmFyeV0gOiBzcmM7XG4gIH1cblxuICAsIHNldEZ1bGxzY3JlZW46IGZ1bmN0aW9uKG1vZGUpIHtcbiAgICB2YXIgJGVkaXRvciA9IHRoaXMuJGVkaXRvcixcbiAgICAgICAgJHRleHRhcmVhID0gdGhpcy4kdGV4dGFyZWE7XG5cbiAgICBpZiAobW9kZSA9PT0gdHJ1ZSkge1xuICAgICAgJGVkaXRvci5hZGRDbGFzcygnbWQtZnVsbHNjcmVlbi1tb2RlJyk7XG4gICAgICAkKCdib2R5JykuYWRkQ2xhc3MoJ21kLW5vb3ZlcmZsb3cnKTtcbiAgICAgIHRoaXMuJG9wdGlvbnMub25GdWxsc2NyZWVuKHRoaXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAkZWRpdG9yLnJlbW92ZUNsYXNzKCdtZC1mdWxsc2NyZWVuLW1vZGUnKTtcbiAgICAgICQoJ2JvZHknKS5yZW1vdmVDbGFzcygnbWQtbm9vdmVyZmxvdycpO1xuXG4gICAgICBpZiAodGhpcy4kaXNQcmV2aWV3ID09IHRydWUpIHRoaXMuaGlkZVByZXZpZXcoKS5zaG93UHJldmlldygpXG4gICAgfVxuXG4gICAgdGhpcy4kaXNGdWxsc2NyZWVuID0gbW9kZTtcbiAgICAkdGV4dGFyZWEuZm9jdXMoKTtcbiAgfVxuXG4gICwgc2hvd0VkaXRvcjogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgaW5zdGFuY2UgPSB0aGlzLFxuICAgICAgICAgIHRleHRhcmVhLFxuICAgICAgICAgIG5zID0gdGhpcy4kbnMsXG4gICAgICAgICAgY29udGFpbmVyID0gdGhpcy4kZWxlbWVudCxcbiAgICAgICAgICBvcmlnaW5hbEhlaWd0aCA9IGNvbnRhaW5lci5jc3MoJ2hlaWdodCcpLFxuICAgICAgICAgIG9yaWdpbmFsV2lkdGggPSBjb250YWluZXIuY3NzKCd3aWR0aCcpLFxuICAgICAgICAgIGVkaXRhYmxlID0gdGhpcy4kZWRpdGFibGUsXG4gICAgICAgICAgaGFuZGxlciA9IHRoaXMuJGhhbmRsZXIsXG4gICAgICAgICAgY2FsbGJhY2sgPSB0aGlzLiRjYWxsYmFjayxcbiAgICAgICAgICBvcHRpb25zID0gdGhpcy4kb3B0aW9ucyxcbiAgICAgICAgICBlZGl0b3IgPSAkKCAnPGRpdi8+Jywge1xuICAgICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtZC1lZGl0b3InLFxuICAgICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgLy8gUHJlcGFyZSB0aGUgZWRpdG9yXG4gICAgICBpZiAodGhpcy4kZWRpdG9yID09PSBudWxsKSB7XG4gICAgICAgIC8vIENyZWF0ZSB0aGUgcGFuZWxcbiAgICAgICAgdmFyIGVkaXRvckhlYWRlciA9ICQoJzxkaXYvPicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWQtaGVhZGVyIGJ0bi10b29sYmFyJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIC8vIE1lcmdlIHRoZSBtYWluICYgYWRkaXRpb25hbCBidXR0b24gZ3JvdXBzIHRvZ2V0aGVyXG4gICAgICAgIHZhciBhbGxCdG5Hcm91cHMgPSBbXTtcbiAgICAgICAgaWYgKG9wdGlvbnMuYnV0dG9ucy5sZW5ndGggPiAwKSBhbGxCdG5Hcm91cHMgPSBhbGxCdG5Hcm91cHMuY29uY2F0KG9wdGlvbnMuYnV0dG9uc1swXSk7XG4gICAgICAgIGlmIChvcHRpb25zLmFkZGl0aW9uYWxCdXR0b25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAvLyBpdGVyYXRlIHRoZSBhZGRpdGlvbmFsIGJ1dHRvbiBncm91cHNcbiAgICAgICAgICAkLmVhY2gob3B0aW9ucy5hZGRpdGlvbmFsQnV0dG9uc1swXSwgZnVuY3Rpb24oaWR4LCBidXR0b25Hcm91cCl7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIHNlZSBpZiB0aGUgZ3JvdXAgbmFtZSBvZiB0aGUgYWRkaW9uYWwgZ3JvdXAgbWF0Y2hlcyBhbiBleGlzdGluZyBncm91cFxuICAgICAgICAgICAgdmFyIG1hdGNoaW5nR3JvdXBzID0gJC5ncmVwKGFsbEJ0bkdyb3VwcywgZnVuY3Rpb24oYWxsQnV0dG9uR3JvdXAsIGFsbElkeCl7XG4gICAgICAgICAgICAgIHJldHVybiBhbGxCdXR0b25Hcm91cC5uYW1lID09PSBidXR0b25Hcm91cC5uYW1lO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIGlmIGl0IG1hdGNoZXMgYWRkIHRoZSBhZGRpb25hbCBidXR0b25zIHRvIHRoYXQgZ3JvdXAsIGlmIG5vdCBqdXN0IGFkZCBpdCB0byB0aGUgYWxsIGJ1dHRvbnMgZ3JvdXBcbiAgICAgICAgICAgIGlmKG1hdGNoaW5nR3JvdXBzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgbWF0Y2hpbmdHcm91cHNbMF0uZGF0YSA9IG1hdGNoaW5nR3JvdXBzWzBdLmRhdGEuY29uY2F0KGJ1dHRvbkdyb3VwLmRhdGEpO1xuICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICBhbGxCdG5Hcm91cHMucHVzaChvcHRpb25zLmFkZGl0aW9uYWxCdXR0b25zWzBdW2lkeF0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gXG5cbiAgICAgICAgLy8gUmVkdWNlIGFuZC9vciByZW9yZGVyIHRoZSBidXR0b24gZ3JvdXBzXG4gICAgICAgIGlmIChvcHRpb25zLnJlb3JkZXJCdXR0b25Hcm91cHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGFsbEJ0bkdyb3VwcyA9IGFsbEJ0bkdyb3Vwc1xuICAgICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKGJ0bkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5pbmRleE9mKGJ0bkdyb3VwLm5hbWUpID4gLTE7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5yZW9yZGVyQnV0dG9uR3JvdXBzLmluZGV4T2YoYS5uYW1lKSA8IG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5pbmRleE9mKGIubmFtZSkpIHJldHVybiAtMTtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5yZW9yZGVyQnV0dG9uR3JvdXBzLmluZGV4T2YoYS5uYW1lKSA+IG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5pbmRleE9mKGIubmFtZSkpIHJldHVybiAxO1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJ1aWxkIHRoZSBidXR0b25zXG4gICAgICAgIGlmIChhbGxCdG5Hcm91cHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGVkaXRvckhlYWRlciA9IHRoaXMuX19idWlsZEJ1dHRvbnMoW2FsbEJ0bkdyb3Vwc10sIGVkaXRvckhlYWRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5mdWxsc2NyZWVuLmVuYWJsZSkge1xuICAgICAgICAgIGVkaXRvckhlYWRlci5hcHBlbmQoJzxkaXYgY2xhc3M9XCJtZC1jb250cm9sc1wiPjxhIGNsYXNzPVwibWQtY29udHJvbCBtZC1jb250cm9sLWZ1bGxzY3JlZW5cIiBocmVmPVwiI1wiPjxzcGFuIGNsYXNzPVwiJyt0aGlzLl9fZ2V0SWNvbihvcHRpb25zLmZ1bGxzY3JlZW4uaWNvbnMuZnVsbHNjcmVlbk9uKSsnXCI+PC9zcGFuPjwvYT48L2Rpdj4nKS5vbignY2xpY2snLCAnLm1kLWNvbnRyb2wtZnVsbHNjcmVlbicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICBpbnN0YW5jZS5zZXRGdWxsc2NyZWVuKHRydWUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgZWRpdG9yLmFwcGVuZChlZGl0b3JIZWFkZXIpO1xuXG4gICAgICAgIC8vIFdyYXAgdGhlIHRleHRhcmVhXG4gICAgICAgIGlmIChjb250YWluZXIuaXMoJ3RleHRhcmVhJykpIHtcbiAgICAgICAgICBjb250YWluZXIuYmVmb3JlKGVkaXRvcik7XG4gICAgICAgICAgdGV4dGFyZWEgPSBjb250YWluZXI7XG4gICAgICAgICAgdGV4dGFyZWEuYWRkQ2xhc3MoJ21kLWlucHV0Jyk7XG4gICAgICAgICAgZWRpdG9yLmFwcGVuZCh0ZXh0YXJlYSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHJhd0NvbnRlbnQgPSAodHlwZW9mIHRvTWFya2Rvd24gPT0gJ2Z1bmN0aW9uJykgPyB0b01hcmtkb3duKGNvbnRhaW5lci5odG1sKCkpIDogY29udGFpbmVyLmh0bWwoKSxcbiAgICAgICAgICAgICAgY3VycmVudENvbnRlbnQgPSAkLnRyaW0ocmF3Q29udGVudCk7XG5cbiAgICAgICAgICAvLyBUaGlzIGlzIHNvbWUgYXJiaXRyYXJ5IGNvbnRlbnQgdGhhdCBjb3VsZCBiZSBlZGl0ZWRcbiAgICAgICAgICB0ZXh0YXJlYSA9ICQoJzx0ZXh0YXJlYS8+Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWQtaW5wdXQnLFxuICAgICAgICAgICAgICAgICAgICAgICAndmFsJyA6IGN1cnJlbnRDb250ZW50XG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICBlZGl0b3IuYXBwZW5kKHRleHRhcmVhKTtcblxuICAgICAgICAgIC8vIFNhdmUgdGhlIGVkaXRhYmxlXG4gICAgICAgICAgZWRpdGFibGUuZWwgPSBjb250YWluZXI7XG4gICAgICAgICAgZWRpdGFibGUudHlwZSA9IGNvbnRhaW5lci5wcm9wKCd0YWdOYW1lJykudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICBlZGl0YWJsZS5jb250ZW50ID0gY29udGFpbmVyLmh0bWwoKTtcblxuICAgICAgICAgICQoY29udGFpbmVyWzBdLmF0dHJpYnV0ZXMpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIGVkaXRhYmxlLmF0dHJLZXlzLnB1c2godGhpcy5ub2RlTmFtZSk7XG4gICAgICAgICAgICBlZGl0YWJsZS5hdHRyVmFsdWVzLnB1c2godGhpcy5ub2RlVmFsdWUpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gU2V0IGVkaXRvciB0byBibG9ja2VkIHRoZSBvcmlnaW5hbCBjb250YWluZXJcbiAgICAgICAgICBjb250YWluZXIucmVwbGFjZVdpdGgoZWRpdG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBlZGl0b3JGb290ZXIgPSAkKCc8ZGl2Lz4nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWQtZm9vdGVyJ1xuICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgY3JlYXRlRm9vdGVyID0gZmFsc2UsXG4gICAgICAgICAgICBmb290ZXIgPSAnJztcbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBmb290ZXIgaWYgc2F2YWJsZVxuICAgICAgICBpZiAob3B0aW9ucy5zYXZhYmxlKSB7XG4gICAgICAgICAgY3JlYXRlRm9vdGVyID0gdHJ1ZTtcbiAgICAgICAgICB2YXIgc2F2ZUhhbmRsZXIgPSAnY21kU2F2ZSc7XG5cbiAgICAgICAgICAvLyBSZWdpc3RlciBoYW5kbGVyIGFuZCBjYWxsYmFja1xuICAgICAgICAgIGhhbmRsZXIucHVzaChzYXZlSGFuZGxlcik7XG4gICAgICAgICAgY2FsbGJhY2sucHVzaChvcHRpb25zLm9uU2F2ZSk7XG5cbiAgICAgICAgICBlZGl0b3JGb290ZXIuYXBwZW5kKCc8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzXCIgZGF0YS1wcm92aWRlcj1cIidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgbnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgJ1wiIGRhdGEtaGFuZGxlcj1cIidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgc2F2ZUhhbmRsZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgJ1wiPjxpIGNsYXNzPVwiaWNvbiBpY29uLXdoaXRlIGljb24tb2tcIj48L2k+ICdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgdGhpcy5fX2xvY2FsaXplKCdTYXZlJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgJzwvYnV0dG9uPicpO1xuXG5cbiAgICAgICAgfVxuXG4gICAgICAgIGZvb3RlciA9IHR5cGVvZiBvcHRpb25zLmZvb3RlciA9PT0gJ2Z1bmN0aW9uJyA/IG9wdGlvbnMuZm9vdGVyKHRoaXMpIDogb3B0aW9ucy5mb290ZXI7XG5cbiAgICAgICAgaWYgKCQudHJpbShmb290ZXIpICE9PSAnJykge1xuICAgICAgICAgIGNyZWF0ZUZvb3RlciA9IHRydWU7XG4gICAgICAgICAgZWRpdG9yRm9vdGVyLmFwcGVuZChmb290ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNyZWF0ZUZvb3RlcikgZWRpdG9yLmFwcGVuZChlZGl0b3JGb290ZXIpO1xuXG4gICAgICAgIC8vIFNldCB3aWR0aFxuICAgICAgICBpZiAob3B0aW9ucy53aWR0aCAmJiBvcHRpb25zLndpZHRoICE9PSAnaW5oZXJpdCcpIHtcbiAgICAgICAgICBpZiAoalF1ZXJ5LmlzTnVtZXJpYyhvcHRpb25zLndpZHRoKSkge1xuICAgICAgICAgICAgZWRpdG9yLmNzcygnZGlzcGxheScsICd0YWJsZScpO1xuICAgICAgICAgICAgdGV4dGFyZWEuY3NzKCd3aWR0aCcsIG9wdGlvbnMud2lkdGggKyAncHgnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWRpdG9yLmFkZENsYXNzKG9wdGlvbnMud2lkdGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCBoZWlnaHRcbiAgICAgICAgaWYgKG9wdGlvbnMuaGVpZ2h0ICYmIG9wdGlvbnMuaGVpZ2h0ICE9PSAnaW5oZXJpdCcpIHtcbiAgICAgICAgICBpZiAoalF1ZXJ5LmlzTnVtZXJpYyhvcHRpb25zLmhlaWdodCkpIHtcbiAgICAgICAgICAgIHZhciBoZWlnaHQgPSBvcHRpb25zLmhlaWdodDtcbiAgICAgICAgICAgIGlmIChlZGl0b3JIZWFkZXIpIGhlaWdodCA9IE1hdGgubWF4KDAsIGhlaWdodCAtIGVkaXRvckhlYWRlci5vdXRlckhlaWdodCgpKTtcbiAgICAgICAgICAgIGlmIChlZGl0b3JGb290ZXIpIGhlaWdodCA9IE1hdGgubWF4KDAsIGhlaWdodCAtIGVkaXRvckZvb3Rlci5vdXRlckhlaWdodCgpKTtcbiAgICAgICAgICAgIHRleHRhcmVhLmNzcygnaGVpZ2h0JywgaGVpZ2h0ICsgJ3B4Jyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVkaXRvci5hZGRDbGFzcyhvcHRpb25zLmhlaWdodCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVmZXJlbmNlXG4gICAgICAgIHRoaXMuJGVkaXRvciAgICAgPSBlZGl0b3I7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhICAgPSB0ZXh0YXJlYTtcbiAgICAgICAgdGhpcy4kZWRpdGFibGUgICA9IGVkaXRhYmxlO1xuICAgICAgICB0aGlzLiRvbGRDb250ZW50ID0gdGhpcy5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgdGhpcy5fX3NldExpc3RlbmVyKCk7XG5cbiAgICAgICAgLy8gU2V0IGVkaXRvciBhdHRyaWJ1dGVzLCBkYXRhIHNob3J0LWhhbmQgQVBJIGFuZCBsaXN0ZW5lclxuICAgICAgICB0aGlzLiRlZGl0b3IuYXR0cignaWQnLChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkpO1xuICAgICAgICB0aGlzLiRlZGl0b3Iub24oJ2NsaWNrJywgJ1tkYXRhLXByb3ZpZGVyPVwiYm9vdHN0cmFwLW1hcmtkb3duXCJdJywgJC5wcm94eSh0aGlzLl9faGFuZGxlLCB0aGlzKSk7XG5cbiAgICAgICAgaWYgKHRoaXMuJGVsZW1lbnQuaXMoJzpkaXNhYmxlZCcpIHx8IHRoaXMuJGVsZW1lbnQuaXMoJ1tyZWFkb25seV0nKSkge1xuICAgICAgICAgIHRoaXMuJGVkaXRvci5hZGRDbGFzcygnbWQtZWRpdG9yLWRpc2FibGVkJyk7XG4gICAgICAgICAgdGhpcy5kaXNhYmxlQnV0dG9ucygnYWxsJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5ldmVudFN1cHBvcnRlZCgna2V5ZG93bicpICYmIHR5cGVvZiBqUXVlcnkuaG90a2V5cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBlZGl0b3JIZWFkZXIuZmluZCgnW2RhdGEtcHJvdmlkZXI9XCJib290c3RyYXAtbWFya2Rvd25cIl0nKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyICRidXR0b24gPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgIGhvdGtleSA9ICRidXR0b24uYXR0cignZGF0YS1ob3RrZXknKTtcbiAgICAgICAgICAgIGlmIChob3RrZXkudG9Mb3dlckNhc2UoKSAhPT0gJycpIHtcbiAgICAgICAgICAgICAgdGV4dGFyZWEuYmluZCgna2V5ZG93bicsIGhvdGtleSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgJGJ1dHRvbi50cmlnZ2VyKCdjbGljaycpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5pbml0aWFsc3RhdGUgPT09ICdwcmV2aWV3Jykge1xuICAgICAgICAgIHRoaXMuc2hvd1ByZXZpZXcoKTtcbiAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmluaXRpYWxzdGF0ZSA9PT0gJ2Z1bGxzY3JlZW4nICYmIG9wdGlvbnMuZnVsbHNjcmVlbi5lbmFibGUpIHtcbiAgICAgICAgICB0aGlzLnNldEZ1bGxzY3JlZW4odHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy4kZWRpdG9yLnNob3coKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuYXV0b2ZvY3VzKSB7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhLmZvY3VzKCk7XG4gICAgICAgIHRoaXMuJGVkaXRvci5hZGRDbGFzcygnYWN0aXZlJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLmZ1bGxzY3JlZW4uZW5hYmxlICYmIG9wdGlvbnMuZnVsbHNjcmVlbiAhPT0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy4kZWRpdG9yLmFwcGVuZCgnPGRpdiBjbGFzcz1cIm1kLWZ1bGxzY3JlZW4tY29udHJvbHNcIj4nXG4gICAgICAgICAgICAgICAgICAgICAgICArICc8YSBocmVmPVwiI1wiIGNsYXNzPVwiZXhpdC1mdWxsc2NyZWVuXCIgdGl0bGU9XCJFeGl0IGZ1bGxzY3JlZW5cIj48c3BhbiBjbGFzcz1cIicgKyB0aGlzLl9fZ2V0SWNvbihvcHRpb25zLmZ1bGxzY3JlZW4uaWNvbnMuZnVsbHNjcmVlbk9mZikgKyAnXCI+J1xuICAgICAgICAgICAgICAgICAgICAgICAgKyAnPC9zcGFuPjwvYT4nXG4gICAgICAgICAgICAgICAgICAgICAgICArICc8L2Rpdj4nKTtcbiAgICAgICAgdGhpcy4kZWRpdG9yLm9uKCdjbGljaycsICcuZXhpdC1mdWxsc2NyZWVuJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICBpbnN0YW5jZS5zZXRGdWxsc2NyZWVuKGZhbHNlKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIGhpZGUgaGlkZGVuIGJ1dHRvbnMgZnJvbSBvcHRpb25zXG4gICAgICB0aGlzLmhpZGVCdXR0b25zKG9wdGlvbnMuaGlkZGVuQnV0dG9ucyk7XG5cbiAgICAgIC8vIGRpc2FibGUgZGlzYWJsZWQgYnV0dG9ucyBmcm9tIG9wdGlvbnNcbiAgICAgIHRoaXMuZGlzYWJsZUJ1dHRvbnMob3B0aW9ucy5kaXNhYmxlZEJ1dHRvbnMpO1xuXG4gICAgICAvLyBUcmlnZ2VyIHRoZSBvblNob3cgaG9va1xuICAgICAgb3B0aW9ucy5vblNob3codGhpcyk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIHBhcnNlQ29udGVudDogZnVuY3Rpb24odmFsKSB7XG4gICAgICB2YXIgY29udGVudDtcblxuICAgICAgLy8gcGFyc2Ugd2l0aCBzdXBwb3J0ZWQgbWFya2Rvd24gcGFyc2VyXG4gICAgICB2YXIgdmFsID0gdmFsIHx8IHRoaXMuJHRleHRhcmVhLnZhbCgpO1xuXG4gICAgICBpZiAodGhpcy4kb3B0aW9ucy5wYXJzZXIpIHtcbiAgICAgICAgY29udGVudCA9IHRoaXMuJG9wdGlvbnMucGFyc2VyKHZhbCk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBtYXJrZG93biA9PSAnb2JqZWN0Jykge1xuICAgICAgICBjb250ZW50ID0gbWFya2Rvd24udG9IVE1MKHZhbCk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBtYXJrZWQgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjb250ZW50ID0gbWFya2VkKHZhbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZW50ID0gdmFsO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gY29udGVudDtcbiAgICB9XG5cbiAgLCBzaG93UHJldmlldzogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuJG9wdGlvbnMsXG4gICAgICAgICAgY29udGFpbmVyID0gdGhpcy4kdGV4dGFyZWEsXG4gICAgICAgICAgYWZ0ZXJDb250YWluZXIgPSBjb250YWluZXIubmV4dCgpLFxuICAgICAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyID0gJCgnPGRpdi8+Jyx7J2NsYXNzJzonbWQtcHJldmlldycsJ2RhdGEtcHJvdmlkZXInOidtYXJrZG93bi1wcmV2aWV3J30pLFxuICAgICAgICAgIGNvbnRlbnQsXG4gICAgICAgICAgY2FsbGJhY2tDb250ZW50O1xuXG4gICAgICBpZiAodGhpcy4kaXNQcmV2aWV3ID09IHRydWUpIHtcbiAgICAgICAgLy8gQXZvaWQgc2VxdWVuY2VkIGVsZW1lbnQgY3JlYXRpb24gb24gbWlzc3VzZWQgc2NlbmFyaW9cbiAgICAgICAgLy8gQHNlZSBodHRwczovL2dpdGh1Yi5jb20vdG9vcGF5L2Jvb3RzdHJhcC1tYXJrZG93bi9pc3N1ZXMvMTcwXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBHaXZlIGZsYWcgdGhhdCB0ZWxsIHRoZSBlZGl0b3IgZW50ZXIgcHJldmlldyBtb2RlXG4gICAgICB0aGlzLiRpc1ByZXZpZXcgPSB0cnVlO1xuICAgICAgLy8gRGlzYWJsZSBhbGwgYnV0dG9uc1xuICAgICAgdGhpcy5kaXNhYmxlQnV0dG9ucygnYWxsJykuZW5hYmxlQnV0dG9ucygnY21kUHJldmlldycpO1xuXG4gICAgICAvLyBUcnkgdG8gZ2V0IHRoZSBjb250ZW50IGZyb20gY2FsbGJhY2tcbiAgICAgIGNhbGxiYWNrQ29udGVudCA9IG9wdGlvbnMub25QcmV2aWV3KHRoaXMpO1xuICAgICAgLy8gU2V0IHRoZSBjb250ZW50IGJhc2VkIGZyb20gdGhlIGNhbGxiYWNrIGNvbnRlbnQgaWYgc3RyaW5nIG90aGVyd2lzZSBwYXJzZSB2YWx1ZSBmcm9tIHRleHRhcmVhXG4gICAgICBjb250ZW50ID0gdHlwZW9mIGNhbGxiYWNrQ29udGVudCA9PSAnc3RyaW5nJyA/IGNhbGxiYWNrQ29udGVudCA6IHRoaXMucGFyc2VDb250ZW50KCk7XG5cbiAgICAgIC8vIEJ1aWxkIHByZXZpZXcgZWxlbWVudFxuICAgICAgcmVwbGFjZW1lbnRDb250YWluZXIuaHRtbChjb250ZW50KTtcblxuICAgICAgaWYgKGFmdGVyQ29udGFpbmVyICYmIGFmdGVyQ29udGFpbmVyLmF0dHIoJ2NsYXNzJykgPT0gJ21kLWZvb3RlcicpIHtcbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgZm9vdGVyIGVsZW1lbnQsIGluc2VydCB0aGUgcHJldmlldyBjb250YWluZXIgYmVmb3JlIGl0XG4gICAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyLmluc2VydEJlZm9yZShhZnRlckNvbnRhaW5lcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBPdGhlcndpc2UsIGp1c3QgYXBwZW5kIGl0IGFmdGVyIHRleHRhcmVhXG4gICAgICAgIGNvbnRhaW5lci5wYXJlbnQoKS5hcHBlbmQocmVwbGFjZW1lbnRDb250YWluZXIpO1xuICAgICAgfVxuXG4gICAgICAvLyBTZXQgdGhlIHByZXZpZXcgZWxlbWVudCBkaW1lbnNpb25zXG4gICAgICByZXBsYWNlbWVudENvbnRhaW5lci5jc3Moe1xuICAgICAgICB3aWR0aDogY29udGFpbmVyLm91dGVyV2lkdGgoKSArICdweCcsXG4gICAgICAgIGhlaWdodDogY29udGFpbmVyLm91dGVySGVpZ2h0KCkgKyAncHgnXG4gICAgICB9KTtcblxuICAgICAgaWYgKHRoaXMuJG9wdGlvbnMucmVzaXplKSB7XG4gICAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyLmNzcygncmVzaXplJyx0aGlzLiRvcHRpb25zLnJlc2l6ZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEhpZGUgdGhlIGxhc3QtYWN0aXZlIHRleHRhcmVhXG4gICAgICBjb250YWluZXIuaGlkZSgpO1xuXG4gICAgICAvLyBBdHRhY2ggdGhlIGVkaXRvciBpbnN0YW5jZXNcbiAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyLmRhdGEoJ21hcmtkb3duJyx0aGlzKTtcblxuICAgICAgaWYgKHRoaXMuJGVsZW1lbnQuaXMoJzpkaXNhYmxlZCcpIHx8IHRoaXMuJGVsZW1lbnQuaXMoJ1tyZWFkb25seV0nKSkge1xuICAgICAgICB0aGlzLiRlZGl0b3IuYWRkQ2xhc3MoJ21kLWVkaXRvci1kaXNhYmxlZCcpO1xuICAgICAgICB0aGlzLmRpc2FibGVCdXR0b25zKCdhbGwnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgaGlkZVByZXZpZXc6IGZ1bmN0aW9uKCkge1xuICAgICAgLy8gR2l2ZSBmbGFnIHRoYXQgdGVsbCB0aGUgZWRpdG9yIHF1aXQgcHJldmlldyBtb2RlXG4gICAgICB0aGlzLiRpc1ByZXZpZXcgPSBmYWxzZTtcblxuICAgICAgLy8gT2J0YWluIHRoZSBwcmV2aWV3IGNvbnRhaW5lclxuICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuJGVkaXRvci5maW5kKCdkaXZbZGF0YS1wcm92aWRlcj1cIm1hcmtkb3duLXByZXZpZXdcIl0nKTtcblxuICAgICAgLy8gUmVtb3ZlIHRoZSBwcmV2aWV3IGNvbnRhaW5lclxuICAgICAgY29udGFpbmVyLnJlbW92ZSgpO1xuXG4gICAgICAvLyBFbmFibGUgYWxsIGJ1dHRvbnNcbiAgICAgIHRoaXMuZW5hYmxlQnV0dG9ucygnYWxsJyk7XG4gICAgICAvLyBEaXNhYmxlIGNvbmZpZ3VyZWQgZGlzYWJsZWQgYnV0dG9uc1xuICAgICAgdGhpcy5kaXNhYmxlQnV0dG9ucyh0aGlzLiRvcHRpb25zLmRpc2FibGVkQnV0dG9ucyk7XG5cbiAgICAgIC8vIEJhY2sgdG8gdGhlIGVkaXRvclxuICAgICAgdGhpcy4kdGV4dGFyZWEuc2hvdygpO1xuICAgICAgdGhpcy5fX3NldExpc3RlbmVyKCk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGlzRGlydHk6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuJG9sZENvbnRlbnQgIT0gdGhpcy5nZXRDb250ZW50KCk7XG4gICAgfVxuXG4gICwgZ2V0Q29udGVudDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy4kdGV4dGFyZWEudmFsKCk7XG4gICAgfVxuXG4gICwgc2V0Q29udGVudDogZnVuY3Rpb24oY29udGVudCkge1xuICAgICAgdGhpcy4kdGV4dGFyZWEudmFsKGNvbnRlbnQpO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBmaW5kU2VsZWN0aW9uOiBmdW5jdGlvbihjaHVuaykge1xuICAgIHZhciBjb250ZW50ID0gdGhpcy5nZXRDb250ZW50KCksIHN0YXJ0Q2h1bmtQb3NpdGlvbjtcblxuICAgIGlmIChzdGFydENodW5rUG9zaXRpb24gPSBjb250ZW50LmluZGV4T2YoY2h1bmspLCBzdGFydENodW5rUG9zaXRpb24gPj0gMCAmJiBjaHVuay5sZW5ndGggPiAwKSB7XG4gICAgICB2YXIgb2xkU2VsZWN0aW9uID0gdGhpcy5nZXRTZWxlY3Rpb24oKSwgc2VsZWN0aW9uO1xuXG4gICAgICB0aGlzLnNldFNlbGVjdGlvbihzdGFydENodW5rUG9zaXRpb24sc3RhcnRDaHVua1Bvc2l0aW9uK2NodW5rLmxlbmd0aCk7XG4gICAgICBzZWxlY3Rpb24gPSB0aGlzLmdldFNlbGVjdGlvbigpO1xuXG4gICAgICB0aGlzLnNldFNlbGVjdGlvbihvbGRTZWxlY3Rpb24uc3RhcnQsb2xkU2VsZWN0aW9uLmVuZCk7XG5cbiAgICAgIHJldHVybiBzZWxlY3Rpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gICwgZ2V0U2VsZWN0aW9uOiBmdW5jdGlvbigpIHtcblxuICAgICAgdmFyIGUgPSB0aGlzLiR0ZXh0YXJlYVswXTtcblxuICAgICAgcmV0dXJuIChcblxuICAgICAgICAgICgnc2VsZWN0aW9uU3RhcnQnIGluIGUgJiYgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIHZhciBsID0gZS5zZWxlY3Rpb25FbmQgLSBlLnNlbGVjdGlvblN0YXJ0O1xuICAgICAgICAgICAgICByZXR1cm4geyBzdGFydDogZS5zZWxlY3Rpb25TdGFydCwgZW5kOiBlLnNlbGVjdGlvbkVuZCwgbGVuZ3RoOiBsLCB0ZXh0OiBlLnZhbHVlLnN1YnN0cihlLnNlbGVjdGlvblN0YXJ0LCBsKSB9O1xuICAgICAgICAgIH0pIHx8XG5cbiAgICAgICAgICAvKiBicm93c2VyIG5vdCBzdXBwb3J0ZWQgKi9cbiAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cblxuICAgICAgKSgpO1xuXG4gICAgfVxuXG4gICwgc2V0U2VsZWN0aW9uOiBmdW5jdGlvbihzdGFydCxlbmQpIHtcblxuICAgICAgdmFyIGUgPSB0aGlzLiR0ZXh0YXJlYVswXTtcblxuICAgICAgcmV0dXJuIChcblxuICAgICAgICAgICgnc2VsZWN0aW9uU3RhcnQnIGluIGUgJiYgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIGUuc2VsZWN0aW9uU3RhcnQgPSBzdGFydDtcbiAgICAgICAgICAgICAgZS5zZWxlY3Rpb25FbmQgPSBlbmQ7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9KSB8fFxuXG4gICAgICAgICAgLyogYnJvd3NlciBub3Qgc3VwcG9ydGVkICovXG4gICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG5cbiAgICAgICkoKTtcblxuICAgIH1cblxuICAsIHJlcGxhY2VTZWxlY3Rpb246IGZ1bmN0aW9uKHRleHQpIHtcblxuICAgICAgdmFyIGUgPSB0aGlzLiR0ZXh0YXJlYVswXTtcblxuICAgICAgcmV0dXJuIChcblxuICAgICAgICAgICgnc2VsZWN0aW9uU3RhcnQnIGluIGUgJiYgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIGUudmFsdWUgPSBlLnZhbHVlLnN1YnN0cigwLCBlLnNlbGVjdGlvblN0YXJ0KSArIHRleHQgKyBlLnZhbHVlLnN1YnN0cihlLnNlbGVjdGlvbkVuZCwgZS52YWx1ZS5sZW5ndGgpO1xuICAgICAgICAgICAgICAvLyBTZXQgY3Vyc29yIHRvIHRoZSBsYXN0IHJlcGxhY2VtZW50IGVuZFxuICAgICAgICAgICAgICBlLnNlbGVjdGlvblN0YXJ0ID0gZS52YWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgIH0pIHx8XG5cbiAgICAgICAgICAvKiBicm93c2VyIG5vdCBzdXBwb3J0ZWQgKi9cbiAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgZS52YWx1ZSArPSB0ZXh0O1xuICAgICAgICAgICAgICByZXR1cm4galF1ZXJ5KGUpO1xuICAgICAgICAgIH1cblxuICAgICAgKSgpO1xuICAgIH1cblxuICAsIGdldE5leHRUYWI6IGZ1bmN0aW9uKCkge1xuICAgICAgLy8gU2hpZnQgdGhlIG5leHRUYWJcbiAgICAgIGlmICh0aGlzLiRuZXh0VGFiLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBuZXh0VGFiLCB0YWIgPSB0aGlzLiRuZXh0VGFiLnNoaWZ0KCk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB0YWIgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIG5leHRUYWIgPSB0YWIoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGFiID09ICdvYmplY3QnICYmIHRhYi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgbmV4dFRhYiA9IHRhYjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXh0VGFiO1xuICAgICAgfVxuICAgIH1cblxuICAsIHNldE5leHRUYWI6IGZ1bmN0aW9uKHN0YXJ0LGVuZCkge1xuICAgICAgLy8gUHVzaCBuZXcgc2VsZWN0aW9uIGludG8gbmV4dFRhYiBjb2xsZWN0aW9uc1xuICAgICAgaWYgKHR5cGVvZiBzdGFydCA9PSAnc3RyaW5nJykge1xuICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgIHRoaXMuJG5leHRUYWIucHVzaChmdW5jdGlvbigpe1xuICAgICAgICAgIHJldHVybiB0aGF0LmZpbmRTZWxlY3Rpb24oc3RhcnQpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHN0YXJ0ID09ICdudW1iZXInICYmIHR5cGVvZiBlbmQgPT0gJ251bWJlcicpIHtcbiAgICAgICAgdmFyIG9sZFNlbGVjdGlvbiA9IHRoaXMuZ2V0U2VsZWN0aW9uKCk7XG5cbiAgICAgICAgdGhpcy5zZXRTZWxlY3Rpb24oc3RhcnQsZW5kKTtcbiAgICAgICAgdGhpcy4kbmV4dFRhYi5wdXNoKHRoaXMuZ2V0U2VsZWN0aW9uKCkpO1xuXG4gICAgICAgIHRoaXMuc2V0U2VsZWN0aW9uKG9sZFNlbGVjdGlvbi5zdGFydCxvbGRTZWxlY3Rpb24uZW5kKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAsIF9fcGFyc2VCdXR0b25OYW1lUGFyYW06IGZ1bmN0aW9uIChuYW1lcykge1xuICAgICAgcmV0dXJuIHR5cGVvZiBuYW1lcyA9PSAnc3RyaW5nJyA/XG4gICAgICAgICAgICAgICAgICAgICAgbmFtZXMuc3BsaXQoJyAnKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbmFtZXM7XG5cbiAgICB9XG5cbiAgLCBlbmFibGVCdXR0b25zOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgICB2YXIgYnV0dG9ucyA9IHRoaXMuX19wYXJzZUJ1dHRvbk5hbWVQYXJhbShuYW1lKSxcbiAgICAgICAgdGhhdCA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChidXR0b25zLCBmdW5jdGlvbihpLCB2KSB7XG4gICAgICAgIHRoYXQuX19hbHRlckJ1dHRvbnMoYnV0dG9uc1tpXSwgZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgZWwucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgZGlzYWJsZUJ1dHRvbnM6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBidXR0b25zID0gdGhpcy5fX3BhcnNlQnV0dG9uTmFtZVBhcmFtKG5hbWUpLFxuICAgICAgICB0aGF0ID0gdGhpcztcblxuICAgICAgJC5lYWNoKGJ1dHRvbnMsIGZ1bmN0aW9uKGksIHYpIHtcbiAgICAgICAgdGhhdC5fX2FsdGVyQnV0dG9ucyhidXR0b25zW2ldLCBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICBlbC5hdHRyKCdkaXNhYmxlZCcsJ2Rpc2FibGVkJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGhpZGVCdXR0b25zOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgICB2YXIgYnV0dG9ucyA9IHRoaXMuX19wYXJzZUJ1dHRvbk5hbWVQYXJhbShuYW1lKSxcbiAgICAgICAgdGhhdCA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChidXR0b25zLCBmdW5jdGlvbihpLCB2KSB7XG4gICAgICAgIHRoYXQuX19hbHRlckJ1dHRvbnMoYnV0dG9uc1tpXSwgZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgZWwuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBzaG93QnV0dG9uczogZnVuY3Rpb24obmFtZSkge1xuICAgICAgdmFyIGJ1dHRvbnMgPSB0aGlzLl9fcGFyc2VCdXR0b25OYW1lUGFyYW0obmFtZSksXG4gICAgICAgIHRoYXQgPSB0aGlzO1xuXG4gICAgICAkLmVhY2goYnV0dG9ucywgZnVuY3Rpb24oaSwgdikge1xuICAgICAgICB0aGF0Ll9fYWx0ZXJCdXR0b25zKGJ1dHRvbnNbaV0sIGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIGVsLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgZXZlbnRTdXBwb3J0ZWQ6IGZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuICAgICAgdmFyIGlzU3VwcG9ydGVkID0gZXZlbnROYW1lIGluIHRoaXMuJGVsZW1lbnQ7XG4gICAgICBpZiAoIWlzU3VwcG9ydGVkKSB7XG4gICAgICAgIHRoaXMuJGVsZW1lbnQuc2V0QXR0cmlidXRlKGV2ZW50TmFtZSwgJ3JldHVybjsnKTtcbiAgICAgICAgaXNTdXBwb3J0ZWQgPSB0eXBlb2YgdGhpcy4kZWxlbWVudFtldmVudE5hbWVdID09PSAnZnVuY3Rpb24nO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzU3VwcG9ydGVkO1xuICAgIH1cblxuICAsIGtleXVwOiBmdW5jdGlvbiAoZSkge1xuICAgICAgdmFyIGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgIHN3aXRjaChlLmtleUNvZGUpIHtcbiAgICAgICAgY2FzZSA0MDogLy8gZG93biBhcnJvd1xuICAgICAgICBjYXNlIDM4OiAvLyB1cCBhcnJvd1xuICAgICAgICBjYXNlIDE2OiAvLyBzaGlmdFxuICAgICAgICBjYXNlIDE3OiAvLyBjdHJsXG4gICAgICAgIGNhc2UgMTg6IC8vIGFsdFxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgOTogLy8gdGFiXG4gICAgICAgICAgdmFyIG5leHRUYWI7XG4gICAgICAgICAgaWYgKG5leHRUYWIgPSB0aGlzLmdldE5leHRUYWIoKSxuZXh0VGFiICE9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBHZXQgdGhlIG5leHRUYWIgaWYgZXhpc3RzXG4gICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgIHRoYXQuc2V0U2VsZWN0aW9uKG5leHRUYWIuc3RhcnQsbmV4dFRhYi5lbmQpO1xuICAgICAgICAgICAgfSw1MDApO1xuXG4gICAgICAgICAgICBibG9ja2VkID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhlIG5leHQgdGFiIG1lbW9yeSBjb250YWlucyBub3RoaW5nLi4uXG4gICAgICAgICAgICAvLyBjaGVjayB0aGUgY3Vyc29yIHBvc2l0aW9uIHRvIGRldGVybWluZSB0YWIgYWN0aW9uXG4gICAgICAgICAgICB2YXIgY3Vyc29yID0gdGhpcy5nZXRTZWxlY3Rpb24oKTtcblxuICAgICAgICAgICAgaWYgKGN1cnNvci5zdGFydCA9PSBjdXJzb3IuZW5kICYmIGN1cnNvci5lbmQgPT0gdGhpcy5nZXRDb250ZW50KCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIC8vIFRoZSBjdXJzb3IgYWxyZWFkeSByZWFjaCB0aGUgZW5kIG9mIHRoZSBjb250ZW50XG4gICAgICAgICAgICAgIGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIFB1dCB0aGUgY3Vyc29yIHRvIHRoZSBlbmRcbiAgICAgICAgICAgICAgdGhpcy5zZXRTZWxlY3Rpb24odGhpcy5nZXRDb250ZW50KCkubGVuZ3RoLHRoaXMuZ2V0Q29udGVudCgpLmxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgYmxvY2tlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAxMzogLy8gZW50ZXJcbiAgICAgICAgICBibG9ja2VkID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjc6IC8vIGVzY2FwZVxuICAgICAgICAgIGlmICh0aGlzLiRpc0Z1bGxzY3JlZW4pIHRoaXMuc2V0RnVsbHNjcmVlbihmYWxzZSk7XG4gICAgICAgICAgYmxvY2tlZCA9IGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgYmxvY2tlZCA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAoYmxvY2tlZCkge1xuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuJG9wdGlvbnMub25DaGFuZ2UodGhpcyk7XG4gICAgfVxuXG4gICwgY2hhbmdlOiBmdW5jdGlvbihlKSB7XG4gICAgICB0aGlzLiRvcHRpb25zLm9uQ2hhbmdlKHRoaXMpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAsIHNlbGVjdDogZnVuY3Rpb24gKGUpIHtcbiAgICAgIHRoaXMuJG9wdGlvbnMub25TZWxlY3QodGhpcyk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICwgZm9jdXM6IGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuJG9wdGlvbnMsXG4gICAgICAgICAgaXNIaWRlYWJsZSA9IG9wdGlvbnMuaGlkZWFibGUsXG4gICAgICAgICAgZWRpdG9yID0gdGhpcy4kZWRpdG9yO1xuXG4gICAgICBlZGl0b3IuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXG4gICAgICAvLyBCbHVyIG90aGVyIG1hcmtkb3duKHMpXG4gICAgICAkKGRvY3VtZW50KS5maW5kKCcubWQtZWRpdG9yJykuZWFjaChmdW5jdGlvbigpe1xuICAgICAgICBpZiAoJCh0aGlzKS5hdHRyKCdpZCcpICE9PSBlZGl0b3IuYXR0cignaWQnKSkge1xuICAgICAgICAgIHZhciBhdHRhY2hlZE1hcmtkb3duO1xuXG4gICAgICAgICAgaWYgKGF0dGFjaGVkTWFya2Rvd24gPSAkKHRoaXMpLmZpbmQoJ3RleHRhcmVhJykuZGF0YSgnbWFya2Rvd24nKSxcbiAgICAgICAgICAgICAgYXR0YWNoZWRNYXJrZG93biA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICBhdHRhY2hlZE1hcmtkb3duID0gJCh0aGlzKS5maW5kKCdkaXZbZGF0YS1wcm92aWRlcj1cIm1hcmtkb3duLXByZXZpZXdcIl0nKS5kYXRhKCdtYXJrZG93bicpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChhdHRhY2hlZE1hcmtkb3duKSB7XG4gICAgICAgICAgICBhdHRhY2hlZE1hcmtkb3duLmJsdXIoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBUcmlnZ2VyIHRoZSBvbkZvY3VzIGhvb2tcbiAgICAgIG9wdGlvbnMub25Gb2N1cyh0aGlzKTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgYmx1cjogZnVuY3Rpb24gKGUpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy4kb3B0aW9ucyxcbiAgICAgICAgICBpc0hpZGVhYmxlID0gb3B0aW9ucy5oaWRlYWJsZSxcbiAgICAgICAgICBlZGl0b3IgPSB0aGlzLiRlZGl0b3IsXG4gICAgICAgICAgZWRpdGFibGUgPSB0aGlzLiRlZGl0YWJsZTtcblxuICAgICAgaWYgKGVkaXRvci5oYXNDbGFzcygnYWN0aXZlJykgfHwgdGhpcy4kZWxlbWVudC5wYXJlbnQoKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZWRpdG9yLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblxuICAgICAgICBpZiAoaXNIaWRlYWJsZSkge1xuICAgICAgICAgIC8vIENoZWNrIGZvciBlZGl0YWJsZSBlbGVtZW50c1xuICAgICAgICAgIGlmIChlZGl0YWJsZS5lbCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gQnVpbGQgdGhlIG9yaWdpbmFsIGVsZW1lbnRcbiAgICAgICAgICAgIHZhciBvbGRFbGVtZW50ID0gJCgnPCcrZWRpdGFibGUudHlwZSsnLz4nKSxcbiAgICAgICAgICAgICAgICBjb250ZW50ID0gdGhpcy5nZXRDb250ZW50KCksXG4gICAgICAgICAgICAgICAgY3VycmVudENvbnRlbnQgPSB0aGlzLnBhcnNlQ29udGVudChjb250ZW50KTtcblxuICAgICAgICAgICAgJChlZGl0YWJsZS5hdHRyS2V5cykuZWFjaChmdW5jdGlvbihrLHYpIHtcbiAgICAgICAgICAgICAgb2xkRWxlbWVudC5hdHRyKGVkaXRhYmxlLmF0dHJLZXlzW2tdLGVkaXRhYmxlLmF0dHJWYWx1ZXNba10pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIEdldCB0aGUgZWRpdG9yIGNvbnRlbnRcbiAgICAgICAgICAgIG9sZEVsZW1lbnQuaHRtbChjdXJyZW50Q29udGVudCk7XG5cbiAgICAgICAgICAgIGVkaXRvci5yZXBsYWNlV2l0aChvbGRFbGVtZW50KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWRpdG9yLmhpZGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmlnZ2VyIHRoZSBvbkJsdXIgaG9va1xuICAgICAgICBvcHRpb25zLm9uQmx1cih0aGlzKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gIH07XG5cbiAvKiBNQVJLRE9XTiBQTFVHSU4gREVGSU5JVElPTlxuICAqID09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cbiAgdmFyIG9sZCA9ICQuZm4ubWFya2Rvd247XG5cbiAgJC5mbi5tYXJrZG93biA9IGZ1bmN0aW9uIChvcHRpb24pIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkdGhpcyA9ICQodGhpcylcbiAgICAgICAgLCBkYXRhID0gJHRoaXMuZGF0YSgnbWFya2Rvd24nKVxuICAgICAgICAsIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvbjtcbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnbWFya2Rvd24nLCAoZGF0YSA9IG5ldyBNYXJrZG93bih0aGlzLCBvcHRpb25zKSkpXG4gICAgfSlcbiAgfTtcblxuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzID0ge307XG5cbiAgJC5mbi5tYXJrZG93bi5kZWZhdWx0cyA9IHtcbiAgICAvKiBFZGl0b3IgUHJvcGVydGllcyAqL1xuICAgIGF1dG9mb2N1czogZmFsc2UsXG4gICAgaGlkZWFibGU6IGZhbHNlLFxuICAgIHNhdmFibGU6IGZhbHNlLFxuICAgIHdpZHRoOiAnaW5oZXJpdCcsXG4gICAgaGVpZ2h0OiAnaW5oZXJpdCcsXG4gICAgcmVzaXplOiAnbm9uZScsXG4gICAgaWNvbmxpYnJhcnk6ICdnbHlwaCcsXG4gICAgbGFuZ3VhZ2U6ICdlbicsXG4gICAgaW5pdGlhbHN0YXRlOiAnZWRpdG9yJyxcbiAgICBwYXJzZXI6IG51bGwsXG5cbiAgICAvKiBCdXR0b25zIFByb3BlcnRpZXMgKi9cbiAgICBidXR0b25zOiBbXG4gICAgICBbe1xuICAgICAgICBuYW1lOiAnZ3JvdXBGb250JyxcbiAgICAgICAgZGF0YTogW3tcbiAgICAgICAgICBuYW1lOiAnY21kQm9sZCcsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtCJyxcbiAgICAgICAgICB0aXRsZTogJ0JvbGQnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWJvbGQnLCBmYTogJ2ZhIGZhLWJvbGQnLCAnZmEtMyc6ICdpY29uLWJvbGQnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gR2l2ZS9yZW1vdmUgKiogc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnc3Ryb25nIHRleHQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgIGlmIChjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC0yLDIpID09PSAnKionXG4gICAgICAgICAgICAgICAgJiYgY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuZW5kLDIpID09PSAnKionICkge1xuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihzZWxlY3RlZC5zdGFydC0yLHNlbGVjdGVkLmVuZCsyKTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKGNodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQtMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignKionK2NodW5rKycqKicpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSx7XG4gICAgICAgICAgbmFtZTogJ2NtZEl0YWxpYycsXG4gICAgICAgICAgdGl0bGU6ICdJdGFsaWMnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrSScsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24taXRhbGljJywgZmE6ICdmYSBmYS1pdGFsaWMnLCAnZmEtMyc6ICdpY29uLWl0YWxpYycgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBHaXZlL3JlbW92ZSAqIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKTtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2VtcGhhc2l6ZWQgdGV4dCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLnN0YXJ0LTEsMSkgPT09ICdfJ1xuICAgICAgICAgICAgICAgICYmIGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLmVuZCwxKSA9PT0gJ18nICkge1xuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihzZWxlY3RlZC5zdGFydC0xLHNlbGVjdGVkLmVuZCsxKTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKGNodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQtMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignXycrY2h1bmsrJ18nKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0se1xuICAgICAgICAgIG5hbWU6ICdjbWRIZWFkaW5nJyxcbiAgICAgICAgICB0aXRsZTogJ0hlYWRpbmcnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrSCcsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24taGVhZGVyJywgZmE6ICdmYSBmYS1oZWFkZXInLCAnZmEtMyc6ICdpY29uLWZvbnQnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gQXBwZW5kL3JlbW92ZSAjIyMgc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpLCBwb2ludGVyLCBwcmV2Q2hhcjtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2hlYWRpbmcgdGV4dCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0ICsgJ1xcbic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoKHBvaW50ZXIgPSA0LCBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC1wb2ludGVyLHBvaW50ZXIpID09PSAnIyMjICcpXG4gICAgICAgICAgICAgICAgfHwgKHBvaW50ZXIgPSAzLCBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC1wb2ludGVyLHBvaW50ZXIpID09PSAnIyMjJykpIHtcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oc2VsZWN0ZWQuc3RhcnQtcG9pbnRlcixzZWxlY3RlZC5lbmQpO1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oY2h1bmspO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydC1wb2ludGVyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzZWxlY3RlZC5zdGFydCA+IDAgJiYgKHByZXZDaGFyID0gY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtMSwxKSwgISFwcmV2Q2hhciAmJiBwcmV2Q2hhciAhPSAnXFxuJykpIHtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdcXG5cXG4jIyMgJytjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzY7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBFbXB0eSBzdHJpbmcgYmVmb3JlIGVsZW1lbnRcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCcjIyMgJytjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XVxuICAgICAgfSx7XG4gICAgICAgIG5hbWU6ICdncm91cExpbmsnLFxuICAgICAgICBkYXRhOiBbe1xuICAgICAgICAgIG5hbWU6ICdjbWRVcmwnLFxuICAgICAgICAgIHRpdGxlOiAnVVJML0xpbmsnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrTCcsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tbGluaycsIGZhOiAnZmEgZmEtbGluaycsICdmYS0zJzogJ2ljb24tbGluaycgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBHaXZlIFtdIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb24gYW5kIHByZXBlbmQgdGhlIGxpbmtcbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKSwgbGluaztcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsaW5rID0gcHJvbXB0KGUuX19sb2NhbGl6ZSgnSW5zZXJ0IEh5cGVybGluaycpLCdodHRwOi8vJyk7XG5cbiAgICAgICAgICAgIHZhciB1cmxSZWdleCA9IG5ldyBSZWdFeHAoJ14oKGh0dHB8aHR0cHMpOi8vfChtYWlsdG86KXwoLy8pKVthLXowLTldJywgJ2knKTtcbiAgICAgICAgICAgIGlmIChsaW5rICE9PSBudWxsICYmIGxpbmsgIT09ICcnICYmIGxpbmsgIT09ICdodHRwOi8vJyAmJiB1cmxSZWdleC50ZXN0KGxpbmspKSB7XG4gICAgICAgICAgICAgIHZhciBzYW5pdGl6ZWRMaW5rID0gJCgnPGRpdj4nK2xpbmsrJzwvZGl2PicpLnRleHQoKTtcblxuICAgICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ1snK2NodW5rKyddKCcrc2FuaXRpemVkTGluaysnKScpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsxO1xuXG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0se1xuICAgICAgICAgIG5hbWU6ICdjbWRJbWFnZScsXG4gICAgICAgICAgdGl0bGU6ICdJbWFnZScsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtHJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1waWN0dXJlJywgZmE6ICdmYSBmYS1waWN0dXJlLW8nLCAnZmEtMyc6ICdpY29uLXBpY3R1cmUnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gR2l2ZSAhW10gc3Vycm91bmQgdGhlIHNlbGVjdGlvbiBhbmQgcHJlcGVuZCB0aGUgaW1hZ2UgbGlua1xuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpLCBsaW5rO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsaW5rID0gcHJvbXB0KGUuX19sb2NhbGl6ZSgnSW5zZXJ0IEltYWdlIEh5cGVybGluaycpLCdodHRwOi8vJyk7XG5cbiAgICAgICAgICAgIHZhciB1cmxSZWdleCA9IG5ldyBSZWdFeHAoJ14oKGh0dHB8aHR0cHMpOi8vfCgvLykpW2EtejAtOV0nLCAnaScpO1xuICAgICAgICAgICAgaWYgKGxpbmsgIT09IG51bGwgJiYgbGluayAhPT0gJycgJiYgbGluayAhPT0gJ2h0dHA6Ly8nICYmIHVybFJlZ2V4LnRlc3QobGluaykpIHtcbiAgICAgICAgICAgICAgdmFyIHNhbml0aXplZExpbmsgPSAkKCc8ZGl2PicrbGluaysnPC9kaXY+JykudGV4dCgpO1xuXG4gICAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignIVsnK2NodW5rKyddKCcrc2FuaXRpemVkTGluaysnIFwiJytlLl9fbG9jYWxpemUoJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnKSsnXCIpJyk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG5cbiAgICAgICAgICAgICAgLy8gU2V0IHRoZSBuZXh0IHRhYlxuICAgICAgICAgICAgICBlLnNldE5leHRUYWIoZS5fX2xvY2FsaXplKCdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJykpO1xuXG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1dXG4gICAgICB9LHtcbiAgICAgICAgbmFtZTogJ2dyb3VwTWlzYycsXG4gICAgICAgIGRhdGE6IFt7XG4gICAgICAgICAgbmFtZTogJ2NtZExpc3QnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrVScsXG4gICAgICAgICAgdGl0bGU6ICdVbm9yZGVyZWQgTGlzdCcsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tbGlzdCcsIGZhOiAnZmEgZmEtbGlzdCcsICdmYS0zJzogJ2ljb24tbGlzdC11bCcgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBQcmVwZW5kL0dpdmUgLSBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnbGlzdCB0ZXh0IGhlcmUnKTtcblxuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJy0gJytjaHVuayk7XG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWQudGV4dC5pbmRleE9mKCdcXG4nKSA8IDApIHtcbiAgICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJy0gJytjaHVuayk7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpc3QgPSBbXTtcblxuICAgICAgICAgICAgICAgIGxpc3QgPSBzZWxlY3RlZC50ZXh0LnNwbGl0KCdcXG4nKTtcbiAgICAgICAgICAgICAgICBjaHVuayA9IGxpc3RbMF07XG5cbiAgICAgICAgICAgICAgICAkLmVhY2gobGlzdCxmdW5jdGlvbihrLHYpIHtcbiAgICAgICAgICAgICAgICAgIGxpc3Rba10gPSAnLSAnK3Y7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ1xcblxcbicrbGlzdC5qb2luKCdcXG4nKSk7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnY21kTGlzdE8nLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrTycsXG4gICAgICAgICAgdGl0bGU6ICdPcmRlcmVkIExpc3QnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLXRoLWxpc3QnLCBmYTogJ2ZhIGZhLWxpc3Qtb2wnLCAnZmEtMyc6ICdpY29uLWxpc3Qtb2wnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpIHtcblxuICAgICAgICAgICAgLy8gUHJlcGVuZC9HaXZlIC0gc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2xpc3QgdGV4dCBoZXJlJyk7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignMS4gJytjaHVuayk7XG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWQudGV4dC5pbmRleE9mKCdcXG4nKSA8IDApIHtcbiAgICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJzEuICcrY2h1bmspO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCszO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ID0gW107XG5cbiAgICAgICAgICAgICAgICBsaXN0ID0gc2VsZWN0ZWQudGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBsaXN0WzBdO1xuXG4gICAgICAgICAgICAgICAgJC5lYWNoKGxpc3QsZnVuY3Rpb24oayx2KSB7XG4gICAgICAgICAgICAgICAgICBsaXN0W2tdID0gJzEuICcrdjtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignXFxuXFxuJytsaXN0LmpvaW4oJ1xcbicpKTtcblxuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrNTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdjbWRDb2RlJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK0snLFxuICAgICAgICAgIHRpdGxlOiAnQ29kZScsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tYXN0ZXJpc2snLCBmYTogJ2ZhIGZhLWNvZGUnLCAnZmEtMyc6ICdpY29uLWNvZGUnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIC8vIEdpdmUvcmVtb3ZlICoqIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKTtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2NvZGUgdGV4dCBoZXJlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtNCw0KSA9PT0gJ2BgYFxcbidcbiAgICAgICAgICAgICAgICAmJiBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5lbmQsNCkgPT09ICdcXG5gYGAnKSB7XG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKHNlbGVjdGVkLnN0YXJ0LTQsIHNlbGVjdGVkLmVuZCs0KTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKGNodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQtNDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtMSwxKSA9PT0gJ2AnXG4gICAgICAgICAgICAgICAgJiYgY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuZW5kLDEpID09PSAnYCcpIHtcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oc2VsZWN0ZWQuc3RhcnQtMSxzZWxlY3RlZC5lbmQrMSk7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbihjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0LTE7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbnRlbnQuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ2BgYFxcbicrY2h1bmsrJ1xcbmBgYCcpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCs0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdgJytjaHVuaysnYCcpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdjbWRRdW90ZScsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtRJyxcbiAgICAgICAgICB0aXRsZTogJ1F1b3RlJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1jb21tZW50JywgZmE6ICdmYSBmYS1xdW90ZS1sZWZ0JywgJ2ZhLTMnOiAnaWNvbi1xdW90ZS1sZWZ0JyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAvLyBQcmVwZW5kL0dpdmUgLSBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgncXVvdGUgaGVyZScpO1xuXG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignPiAnK2NodW5rKTtcblxuICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkLnRleHQuaW5kZXhPZignXFxuJykgPCAwKSB7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuXG4gICAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCc+ICcrY2h1bmspO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ID0gW107XG5cbiAgICAgICAgICAgICAgICBsaXN0ID0gc2VsZWN0ZWQudGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBsaXN0WzBdO1xuXG4gICAgICAgICAgICAgICAgJC5lYWNoKGxpc3QsZnVuY3Rpb24oayx2KSB7XG4gICAgICAgICAgICAgICAgICBsaXN0W2tdID0gJz4gJyt2O1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdcXG5cXG4nK2xpc3Quam9pbignXFxuJykpO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCs0O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XVxuICAgICAgfSx7XG4gICAgICAgIG5hbWU6ICdncm91cFV0aWwnLFxuICAgICAgICBkYXRhOiBbe1xuICAgICAgICAgIG5hbWU6ICdjbWRQcmV2aWV3JyxcbiAgICAgICAgICB0b2dnbGU6IHRydWUsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtQJyxcbiAgICAgICAgICB0aXRsZTogJ1ByZXZpZXcnLFxuICAgICAgICAgIGJ0blRleHQ6ICdQcmV2aWV3JyxcbiAgICAgICAgICBidG5DbGFzczogJ2J0biBidG4tcHJpbWFyeSBidG4tc20nLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLXNlYXJjaCcsIGZhOiAnZmEgZmEtc2VhcmNoJywgJ2ZhLTMnOiAnaWNvbi1zZWFyY2gnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHByZXZpZXcgbW9kZSBhbmQgdG9nZ2xlIGJhc2VkIG9uIHRoaXMgZmxhZ1xuICAgICAgICAgICAgdmFyIGlzUHJldmlldyA9IGUuJGlzUHJldmlldyxjb250ZW50O1xuXG4gICAgICAgICAgICBpZiAoaXNQcmV2aWV3ID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGZsYWcgdGhhdCB0ZWxsIHRoZSBlZGl0b3IgZW50ZXIgcHJldmlldyBtb2RlXG4gICAgICAgICAgICAgIGUuc2hvd1ByZXZpZXcoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGUuaGlkZVByZXZpZXcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1dXG4gICAgICB9XVxuICAgIF0sXG4gICAgYWRkaXRpb25hbEJ1dHRvbnM6W10sIC8vIFBsYWNlIHRvIGhvb2sgbW9yZSBidXR0b25zIGJ5IGNvZGVcbiAgICByZW9yZGVyQnV0dG9uR3JvdXBzOltdLFxuICAgIGhpZGRlbkJ1dHRvbnM6W10sIC8vIERlZmF1bHQgaGlkZGVuIGJ1dHRvbnNcbiAgICBkaXNhYmxlZEJ1dHRvbnM6W10sIC8vIERlZmF1bHQgZGlzYWJsZWQgYnV0dG9uc1xuICAgIGZvb3RlcjogJycsXG4gICAgZnVsbHNjcmVlbjoge1xuICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgaWNvbnM6IHtcbiAgICAgICAgZnVsbHNjcmVlbk9uOiB7XG4gICAgICAgICAgZmE6ICdmYSBmYS1leHBhbmQnLFxuICAgICAgICAgIGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1mdWxsc2NyZWVuJyxcbiAgICAgICAgICAnZmEtMyc6ICdpY29uLXJlc2l6ZS1mdWxsJ1xuICAgICAgICB9LFxuICAgICAgICBmdWxsc2NyZWVuT2ZmOiB7XG4gICAgICAgICAgZmE6ICdmYSBmYS1jb21wcmVzcycsXG4gICAgICAgICAgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWZ1bGxzY3JlZW4nLFxuICAgICAgICAgICdmYS0zJzogJ2ljb24tcmVzaXplLXNtYWxsJ1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcblxuICAgIC8qIEV2ZW50cyBob29rICovXG4gICAgb25TaG93OiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25QcmV2aWV3OiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25TYXZlOiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25CbHVyOiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25Gb2N1czogZnVuY3Rpb24gKGUpIHt9LFxuICAgIG9uQ2hhbmdlOiBmdW5jdGlvbihlKSB7fSxcbiAgICBvbkZ1bGxzY3JlZW46IGZ1bmN0aW9uKGUpIHt9LFxuICAgIG9uU2VsZWN0OiBmdW5jdGlvbiAoZSkge31cbiAgfTtcblxuICAkLmZuLm1hcmtkb3duLkNvbnN0cnVjdG9yID0gTWFya2Rvd247XG5cblxuIC8qIE1BUktET1dOIE5PIENPTkZMSUNUXG4gICogPT09PT09PT09PT09PT09PT09PT0gKi9cblxuICAkLmZuLm1hcmtkb3duLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi5tYXJrZG93biA9IG9sZDtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICAvKiBNQVJLRE9XTiBHTE9CQUwgRlVOQ1RJT04gJiBEQVRBLUFQSVxuICAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuICB2YXIgaW5pdE1hcmtkb3duID0gZnVuY3Rpb24oZWwpIHtcbiAgICB2YXIgJHRoaXMgPSBlbDtcblxuICAgIGlmICgkdGhpcy5kYXRhKCdtYXJrZG93bicpKSB7XG4gICAgICAkdGhpcy5kYXRhKCdtYXJrZG93bicpLnNob3dFZGl0b3IoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAkdGhpcy5tYXJrZG93bigpXG4gIH07XG5cbiAgdmFyIGJsdXJOb25Gb2N1c2VkID0gZnVuY3Rpb24oZSkge1xuICAgIHZhciAkYWN0aXZlRWxlbWVudCA9ICQoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCk7XG5cbiAgICAvLyBCbHVyIGV2ZW50XG4gICAgJChkb2N1bWVudCkuZmluZCgnLm1kLWVkaXRvcicpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgIHZhciAkdGhpcyAgICAgICAgICAgID0gJCh0aGlzKSxcbiAgICAgICAgICBmb2N1c2VkICAgICAgICAgID0gJGFjdGl2ZUVsZW1lbnQuY2xvc2VzdCgnLm1kLWVkaXRvcicpWzBdID09PSB0aGlzLFxuICAgICAgICAgIGF0dGFjaGVkTWFya2Rvd24gPSAkdGhpcy5maW5kKCd0ZXh0YXJlYScpLmRhdGEoJ21hcmtkb3duJykgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMuZmluZCgnZGl2W2RhdGEtcHJvdmlkZXI9XCJtYXJrZG93bi1wcmV2aWV3XCJdJykuZGF0YSgnbWFya2Rvd24nKTtcblxuICAgICAgaWYgKGF0dGFjaGVkTWFya2Rvd24gJiYgIWZvY3VzZWQpIHtcbiAgICAgICAgYXR0YWNoZWRNYXJrZG93bi5ibHVyKCk7XG4gICAgICB9XG4gICAgfSlcbiAgfTtcblxuICAkKGRvY3VtZW50KVxuICAgIC5vbignY2xpY2subWFya2Rvd24uZGF0YS1hcGknLCAnW2RhdGEtcHJvdmlkZT1cIm1hcmtkb3duLWVkaXRhYmxlXCJdJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGluaXRNYXJrZG93bigkKHRoaXMpKTtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9KVxuICAgIC5vbignY2xpY2sgZm9jdXNpbicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBibHVyTm9uRm9jdXNlZChlKTtcbiAgICB9KVxuICAgIC5yZWFkeShmdW5jdGlvbigpe1xuICAgICAgJCgndGV4dGFyZWFbZGF0YS1wcm92aWRlPVwibWFya2Rvd25cIl0nKS5lYWNoKGZ1bmN0aW9uKCl7XG4gICAgICAgIGluaXRNYXJrZG93bigkKHRoaXMpKTtcbiAgICAgIH0pXG4gICAgfSk7XG5cbn0pKTtcbiIsIi8qXG4gKiBBcmFiaWMgdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogR2VvcmdlIEFqYW0gPGdlb3JnZS5lamFhbUBnbWFpbC5jb20+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLm5sID0ge1xuICAgICdCb2xkJzogXCLYutin2YXZglwiLFxuICAgICdJdGFsaWMnOiBcItmF2KfYptmEXCIsXG4gICAgJ0hlYWRpbmcnOiBcIti52YbZiNin2YZcIixcbiAgICAnVVJML0xpbmsnOiBcIlVSTC/Ysdin2KjYt1wiLFxuICAgICdJbWFnZSc6IFwi2LXZiNix2KlcIixcbiAgICAnTGlzdCc6IFwi2YLYp9im2YXYqVwiLFxuICAgICdQcmV2aWV3JzogXCLYp9iz2KrYudix2KfYtlwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwi2YbYtSDYutin2YXZglwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcItmG2LUg2YfYp9mFXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwi2KfZhNi52YbZiNin2YZcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCLYp9iv2K7ZhCDZiNi12YEg2KfZhNix2KfYqNi3INmH2YbYp1wiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCLYp9iv2K7ZhCDYp9mE2LHYp9io2Lcg2YfZhtinXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcItin2K/YrtmEINmI2LXZgSDYp9mE2LXZiNix2Kkg2YfZhtinXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcItin2K/YrtmEINix2KfYqNi3INin2YTYtdmI2LHYqSDZh9mG2KdcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwi2KfYr9iu2YQg2LnZhtmI2KfZhiDYp9mE2LXZiNix2Kkg2YfZhtinXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCLYp9mD2KrYqCDYp9mE2YbYtSDZh9mG2KdcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogQ3plY2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogVsOtdCBLYWJlbGUgPHZpdEBrYWJlbGUubWU+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLmNzID0ge1xuICAgICdCb2xkJzogXCJUdcSNbsSbXCIsXG4gICAgJ0l0YWxpYyc6IFwiS3VyesOtdmFcIixcbiAgICAnSGVhZGluZyc6IFwiTmFkcGlzXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJVUkwvT2RrYXpcIixcbiAgICAnSW1hZ2UnOiBcIk9icsOhemVrXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJTZXpuYW1cIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCJTZcWZYXplbsO9IHNlem5hbVwiLFxuICAgICdDb2RlJzogXCLDmnNlayBrw7NkdVwiLFxuICAgICdRdW90ZSc6IFwiQ2l0YWNlXCIsXG4gICAgJ1ByZXZpZXcnOiBcIk7DoWhsZWRcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcInR1xI1uw70gdGV4dFwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcInpkxa9yYXpuxJtuw70gdGV4dFwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcInRleHQgbmFkcGlzdVwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcInNlbSB2bG/FviBwb3BpcyBvZGthenVcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiVmxvxb5pdCBIeXBlcmxpbmtcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwic2VtIHZsb8W+IHBvcGlzIG9icsOhemt1XCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIlZsb8W+IGFkcmVzdSBvYnLDoXprdVwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJzZW0gdmxvxb4gcG9waXMgb2Jyw6F6a3VcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcInBvbG/FvmthIHNlem5hbXVcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogRGFuaXNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIERhbiBTdG9ybSA8c3Rvcm1AY2F0YWx5c3Rjb2RlLm5ldD5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMubmIgPSB7XG4gICAgJ0JvbGQnOiAnRmVkJyxcbiAgICAnSXRhbGljJzogJ0t1cnNpdicsXG4gICAgJ0hlYWRpbmcnOiAnT3ZlcnNrcmlmdCcsXG4gICAgJ1VSTC9MaW5rJzogJ1VSTC9MaW5rJyxcbiAgICAnSW1hZ2UnOiAnQmlsbGVkZScsXG4gICAgJ0xpc3QnOiAnTGlzdGUnLFxuICAgICdQcmV2aWV3JzogJ0ZvcmjDpW5kc3Zpc25pbmcnLFxuICAgICdzdHJvbmcgdGV4dCc6ICdzdMOmcmsgdGVrc3QnLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiAnZnJlbWjDpnZldCB0ZWtzdCcsXG4gICAgJ2hlYWRpbmcgdGV4dCc6ICdvdmVyc2tyaWZ0IHRla3N0JyxcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogJ1Nrcml2IGxpbmsgYmVza3JpdmVsc2UgaGVyJyxcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6ICdJbmRzw6Z0IGxpbmsnLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogJ0luZHPDpnQgYmlsbGVkZSBiZXNrcml2ZWxzZSBoZXInLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogJ0luZHPDpnQgYmlsbGVkZSBsaW5rJyxcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6ICdJbmRzw6Z0IGJpbGxlZGUgdGl0ZWwnLFxuICAgICdsaXN0IHRleHQgaGVyZSc6ICdJbmRzw6Z0IGxpc3RlIHRla3N0IGhlcicsXG4gICAgJ3F1b3RlIGhlcmUnOiAnSW5kc8OmdCBjaXRhdCBoZXInLFxuICAgICdjb2RlIHRleHQgaGVyZSc6ICdJbmRzw6Z0IGtvZGUgaGVyJ1xuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogR2VybWFuIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIFRvYmlhcyBOaXRzY2hlIDx0b2JpYXMtbml0c2NoZUBnbXgubmV0PlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5kZSA9IHtcbiAgICAnQm9sZCc6IFwiRmV0dFwiLFxuICAgICdJdGFsaWMnOiBcIkt1cnNpdlwiLFxuICAgICdIZWFkaW5nJzogXCLDnGJlcnNjaHJpZnRcIixcbiAgICAnVVJML0xpbmsnOiBcIkxpbmsgaGluenVmw7xnZW5cIixcbiAgICAnSW1hZ2UnOiBcIkJpbGQgaGluenVmw7xnZW5cIixcbiAgICAnVW5vcmRlcmVkIExpc3QnOiBcIlVubnVtbWVyaWVydGUgTGlzdGVcIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCJOdW1tZXJpZXJ0ZSBMaXN0ZVwiLFxuICAgICdDb2RlJzogXCJRdWVsbHRleHRcIixcbiAgICAnUXVvdGUnOiBcIlppdGF0XCIsXG4gICAgJ1ByZXZpZXcnOiBcIlZvcnNjaGF1XCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJTZWhyIGJldG9udGVyIFRleHRcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJCZXRvbnRlciBUZXh0XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwiw5xiZXJzY2hyaWZ0IFRleHRcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJMaW5rYmVzY2hyZWlidW5nXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIlVSTFwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJCaWxkYmVzY2hyZWlidW5nXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIkJpbGQtVVJMXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIlRpdGVsIGRlcyBCaWxkZXNcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcIkF1ZnrDpGhsdW5ncy1UZXh0XCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIFNwYW5pc2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogYnkgTGVhbmRybyBQb2JsZXQgPGxlYW5kcm9kcmhvdXNlQGdtYWlsLmNvbT5cbiAqL1xuOyhmdW5jdGlvbigkKXtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlc1snZXMnXSA9IHtcbiAgICAnQm9sZCc6IFwiTmVncml0YVwiLFxuICAgICdJdGFsaWMnOiBcIkl0w6FsaWNhXCIsXG4gICAgJ0hlYWRpbmcnOiBcIlTDrXR1bG9cIixcbiAgICAnVVJML0xpbmsnOiBcIkluc2VydGUgdW4gbGlua1wiLFxuICAgICdJbWFnZSc6IFwiSW5zZXJ0ZSB1bmEgaW1hZ2VuXCIsXG4gICAgJ0xpc3QnOiBcIkxpc3RhIGRlIGl0ZW1zXCIsXG4gICAgJ1ByZXZpZXcnOiBcIlByZXZpc3VhbGl6YXJcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcInRleHRvIGltcG9ydGFudGVcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJ0ZXh0byBjb24gw6luZmFzaXNcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJ0ZXh0byB0aXR1bGFyXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwiZGVzY3JpcGNpw7NuIGRlbCBsaW5rXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIkluc2VydGUgdW4gaGlwZXJ2w61uY3Vsb1wiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJkZXNjcmlwY2nDs24gZGUgbGEgaW1hZ2VuXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIkluc2VydGUgdW5hIGltYWdlbiBjb24gdW4gaGlwZXJ2w61uY3Vsb1wiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJJbnNlcnRlIHVuYSBpbWFnZW4gY29uIHTDrXR1bG9cIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcImxpc3RhIGNvbiB0ZXh0b1wiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBQZXJzaWFuKEZhcnNpKSB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBTYWphZCBEZWhzaGlyaSA8UGVsYWt3ZWIuaXI+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLmZhID0ge1xuICAgICdCb2xkJzogXCLYqtmI2b7YsVwiLFxuICAgICdJdGFsaWMnOiBcItmF2YjYsdioXCIsXG4gICAgJ0hlYWRpbmcnOiBcIti52YbZiNin2YZcIixcbiAgICAnVVJML0xpbmsnOiBcItm+24zZiNmG2K9cIixcbiAgICAnSW1hZ2UnOiBcItiq2LXZiNuM2LFcIixcbiAgICAnTGlzdCc6IFwi2YHZh9ix2LPYqlwiLFxuICAgICdQcmV2aWV3JzogXCLZvtuM2LQg2YbZhdin24zYtFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwi2YXYqtmGINi22K7bjNmFXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwi2YbZiNi02KrZhyDYqtin2qnbjNiv24xcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLYudmG2YjYp9mGXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwi2KrZiNi224zYrdin2Kog2b7bjNmI2YbYryDYsdinINio2YbZiNuM2LPbjNivLlwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCLZvtuM2YjZhtivINix2Kcg2K/YsdisINmG2YXYp9uM24zYrzpcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwi2KrZiNi224zYrduMINio2LHYp9uMINiq2LXZiNuMINio2YbZiNuM2LPbjNivLlwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCLYotiv2LHYsyDYqti12YjbjNixINix2Kcg2KjZhtmI24zYs9uM2K8uXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIti52YbZiNin2YYg2KrYtdmI24zYsSDYsdinINin24zZhtis2Kcg2KjZhtmI24zYs9uM2K9cIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcItmF2K3ZhCDZhdiq2YYg2YHZh9ix2LPYqlwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBGcmVuY2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogQmVub8OudCBCb3VyZ2VvaXMgPGJpZXJkb2tAZ21haWwuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5mciA9IHtcbiAgICAnQm9sZCc6IFwiR3Jhc1wiLFxuICAgICdJdGFsaWMnOiBcIkl0YWxpcXVlXCIsXG4gICAgJ0hlYWRpbmcnOiBcIlRpdHJlXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJJbnPDqXJlciB1biBsaWVuIEhUVFBcIixcbiAgICAnSW1hZ2UnOiBcIkluc8OpcmVyIHVuZSBpbWFnZVwiLFxuICAgICdMaXN0JzogXCJMaXN0ZSDDoCBwdWNlc1wiLFxuICAgICdQcmV2aWV3JzogXCJQcsOpdmlzdWFsaXNlclwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwidGV4dGUgaW1wb3J0YW50XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwidGV4dGUgZW4gaXRhbGlxdWVcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJ0ZXh0ZSBkJ2VudMOqdGVcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJlbnRyZXogbGEgZGVzY3JpcHRpb24gZHUgbGllbiBpY2lcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiSW5zw6lyZXogbGUgbGllbiBoeXBlcnRleHRlXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcImVudHJleiBsYSBkZXNjcmlwdGlvbiBkZSBsJ2ltYWdlIGljaVwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJJbnPDqXJleiBsZSBsaWVuIGh5cGVydGV4dGUgZGUgbCdpbWFnZVwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJlbnRyZXogbGUgdGl0cmUgZGUgbCdpbWFnZSBpY2lcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcInRleHRlIMOgIHB1Y2UgaWNpXCIsXG4gICAgJ1NhdmUnOiBcIlNhdXZlZ2FyZGVyXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwiTGlzdGUgb3Jkb25uw6llXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJMaXN0ZSBkw6lzb3Jkb25uw6llXCIsXG4gICAgJ1F1b3RlJzogXCJDaXRhdGlvblwiLFxuICAgICdxdW90ZSBoZXJlJzogXCJWb3RyZSBjaXRhdGlvblwiLFxuICAgICdDb2RlJzogXCJDb2RlXCIsXG4gICAgJ2NvZGUgdGV4dCBoZXJlJzogXCLDqWNyaXJlIGR1IGNvZGUgaWNpXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIEphcGFuZXNlIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIEtlbnRhIE11cmFrYW1pIDxrbnRtcmttQGdtYWlsLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXNbJ2phJ10gPSB7XG4gICAgJ0JvbGQnOiBcIuWkquWtl1wiLFxuICAgICdJdGFsaWMnOiBcIuaWnOS9k1wiLFxuICAgICdIZWFkaW5nJzogXCLopovlh7rjgZdcIixcbiAgICAnVVJML0xpbmsnOiBcIuODquODs+OCr1wiLFxuICAgICdJbWFnZSc6IFwi55S75YOPXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCLjg6rjgrnjg4hcIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCLmlbDlrZfjg6rjgrnjg4hcIixcbiAgICAnQ29kZSc6IFwi44Kz44O844OJXCIsXG4gICAgJ1F1b3RlJzogXCLlvJXnlKhcIixcbiAgICAnUHJldmlldyc6IFwi44OX44Os44OT44Ol44O8XCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCLlpKrlrZdcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCLlvLfoqr9cIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLopovlh7rjgZdcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCLjg6rjg7Pjgq/oqqzmmI5cIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwi44Oq44Oz44Kv5oy/5YWlXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcIueUu+WDj+iqrOaYjlwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCLnlLvlg4/mjL/lhaVcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwi55S75YOP44K/44Kk44OI44OrXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCLjg6rjgrnjg4jmjL/lhaVcIixcbiAgICAnY29kZSB0ZXh0IGhlcmUnOiBcIuOCs+ODvOODiVwiLFxuICAgICdxdW90ZSBoZXJlJzogXCLlvJXnlKjmjL/lhaVcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICsgKiBLb3JlYW4gdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICsgKiBXb29uZ0JpIEtpbSA8c3NpbnNzQGdtYWlsLmNvbT5cbiArICovXG47KGZ1bmN0aW9uKCQpe1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzWydrciddID0ge1xuICAgICdCb2xkJzogXCLsp4TtlZjqsoxcIixcbiAgICAnSXRhbGljJzogXCLsnbTtg6Trpq3ssrRcIixcbiAgICAnSGVhZGluZyc6IFwi66i466as6riAXCIsXG4gICAgJ1VSTC9MaW5rJzogXCLrp4Htgazso7zshoxcIixcbiAgICAnSW1hZ2UnOiBcIuydtOuvuOyngFwiLFxuICAgICdMaXN0JzogXCLrpqzsiqTtirhcIixcbiAgICAnUHJldmlldyc6IFwi66+466as67O06riwXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCLqsJXtlZwg6rCV7KGwIO2FjeyKpO2KuFwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcIuqwleyhsCDthY3siqTtirhcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLrqLjrpqzquIAg7YWN7Iqk7Yq4XCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwi7Jes6riw7JeQIOunge2BrOydmCDshKTrqoXsnYQg7KCB7Jy87IS47JqUXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIu2VmOydtO2NvOunge2BrCDsgr3snoVcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwi7Jes6riw7IS4IOydtOuvuOyngCDshKTrqoXsnYQg7KCB7Jy87IS47JqUXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIuydtOuvuOyngCDrp4Htgawg7IK97J6FXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIuyXrOq4sOyXkCDsnbTrr7jsp4Ag7KCc66qp7J2EIOyggeycvOyEuOyalFwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwi66as7Iqk7Yq4IO2FjeyKpO2KuFwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBOb3J3ZWdpYW4gYm9rbcOlbCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBUb2JpYXMgQm9od2FsbGkgPGhpQGZ1dGhyLmlvPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5uYiA9IHtcbiAgICAnQm9sZCc6ICdGZXQnLFxuICAgICdJdGFsaWMnOiAnS3Vyc2l2JyxcbiAgICAnSGVhZGluZyc6ICdPdmVyc2tyaWZ0JyxcbiAgICAnVVJML0xpbmsnOiAnVVJML0xlbmtlJyxcbiAgICAnSW1hZ2UnOiAnQmlsZGUnLFxuICAgICdMaXN0JzogJ0xpc3RlJyxcbiAgICAnUHJldmlldyc6ICdGb3Jow6VuZHN2aXNuaW5nJyxcbiAgICAnc3Ryb25nIHRleHQnOiAnc3RlcmsgdGVrc3QnLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiAnc3RyZWtldCB0ZWtzdCcsXG4gICAgJ2hlYWRpbmcgdGV4dCc6ICdvdmVyc2tyaWZ0ZW4gdGVrc3QnLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiAnU2tyaXYgbGlua2VuIGJlc2tyaXZlbHNlIGhlcicsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiAnU2V0dCBpbm4gbGVua2UnLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogJ0FuZ2kgYmlsZGViZXNrcml2ZWxzZSBoZXInLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogJ1NldHQgaW5uIGxlbmtlIGZvciBiaWxkZScsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiAnQW5naSBiaWxkZXRpdHRlbCBoZXInLFxuICAgICdsaXN0IHRleHQgaGVyZSc6ICdsaXN0ZSB0ZWtzdCBoZXInXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBEdXRjaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBKZXJvZW4gVGhvcmEgPGplcm9lbnRob3JhQGdtYWlsLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMubmwgPSB7XG4gICAgJ0JvbGQnOiBcIlZldFwiLFxuICAgICdJdGFsaWMnOiBcIkN1cnNpZWZcIixcbiAgICAnSGVhZGluZyc6IFwiVGl0ZWxcIixcbiAgICAnVVJML0xpbmsnOiBcIlVSTC9MaW5rXCIsXG4gICAgJ0ltYWdlJzogXCJBZmJlZWxkaW5nXCIsXG4gICAgJ0xpc3QnOiBcIkxpanN0XCIsXG4gICAgJ1ByZXZpZXcnOiBcIlZvb3JiZWVsZFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwidmV0IGdlZHJ1a3RlIHRla3N0XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwic2NodWluIGdlZHJ1a3RlIHRla3N0XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwiVGl0ZWxcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJWb2VyIGVlbiBsaW5rIGJlc2NocmlqdmluZyBpblwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJWb2VyIGVlbiBodHRwIGxpbmsgaW5cIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwiVm9lciBlZW4gYWZiZWVsZGluZyBiZXNjaHJpanZpbmcgaW5cIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiVm9lciBlZW4gYWZiZWVsZGluZyBsaW5rIGluXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIlZvZXIgZGUgYWZiZWVsZGluZyB0aXRlbCBpblwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwibGlqc3QgaXRlbVwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBQb2xpc2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogTWFyZWsgS2FwdXRcbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMucGwgPSB7XG4gICAgJ0JvbGQnOiBcIlBvZ3J1YmllbmllXCIsXG4gICAgJ0l0YWxpYyc6IFwiS3Vyc3l3YVwiLFxuICAgICdIZWFkaW5nJzogXCJOYWfFgsOzd2VrXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJXc3RhdyBsaW5rXCIsXG4gICAgJ0ltYWdlJzogXCJXc3RhdyBvYnJhemVrXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJMaXN0YSBwdW5rdG93YW5hXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwiTGlzdGEgbnVtZXJvd2FuYVwiLFxuICAgICdDb2RlJzogXCJLb2Qgxbpyw7NkxYJvd3lcIixcbiAgICAnUXVvdGUnOiBcIkN5dGF0XCIsXG4gICAgJ1ByZXZpZXcnOiBcIlBvZGdsxIVkXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJwb2dydWJpb255IHRla3N0XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwicG9jaHlsb255IHRla3N0XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwibmFnxYLDs3dla1wiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIm9waXMgbGlua2FcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiV3N0YXcgbGlua1wiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJvcGlzIG9icmF6a2FcIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiV3N0YXcgb2JyYXpla1wiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJ0eXR1xYIgb2JyYXprYVwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwibGlzdGFcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogU2xvdmVuaWFuIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIERhdm9yIFBhZG92YW4gPGRhdm9yLnBhZG92YW5AZ21haWwuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5zbCA9IHtcbiAgICAnQm9sZCc6IFwiT2RlYmVsamVub1wiLFxuICAgICdJdGFsaWMnOiBcIlBvxaFldm5vXCIsXG4gICAgJ0hlYWRpbmcnOiBcIk5hc2xvdlwiLFxuICAgICdVUkwvTGluayc6IFwiUG92ZXphdmFcIixcbiAgICAnSW1hZ2UnOiBcIlNsaWthXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJOZXVyZWplbiBzZXpuYW1cIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCJVcmVqZW4gc2V6bmFtXCIsXG4gICAgJ0NvZGUnOiBcIktvZGFcIixcbiAgICAnUXVvdGUnOiBcIkNpdGF0XCIsXG4gICAgJ1ByZXZpZXcnOiBcIlByZWRvZ2xlZFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwib2RlYmVsamVubyBiZXNlZGlsb1wiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcInBvxaFldm5vIGJlc2VkaWxvXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwibmFzbG92XCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwib3BpcyBwb3ZlemF2ZVwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJWc3RhdmkgcG92ZXphdm9cIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwib3BpcyBzbGlrZVwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJWc3RhdmkgcG92ZXphdm8gZG8gc2xpa2VcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwibmFzbG92IHNsaWtlXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJzZXpuYW1cIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogU3dlZGlzaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBUb2JpYXMgQm9od2FsbGkgPGhpQGZ1dGhyLmlvPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5zdiA9IHtcbiAgICAnQm9sZCc6ICdGZXQnLFxuICAgICdJdGFsaWMnOiAnS3Vyc2l2JyxcbiAgICAnSGVhZGluZyc6ICdSdWJyaWsnLFxuICAgICdVUkwvTGluayc6ICdVUkwvTMOkbmsnLFxuICAgICdJbWFnZSc6ICdCaWxkJyxcbiAgICAnTGlzdCc6ICdMaXN0YScsXG4gICAgJ1ByZXZpZXcnOiAnRsO2cmhhbmRzZ3JhbnNrYScsXG4gICAgJ3N0cm9uZyB0ZXh0JzogJ2ZldCB0ZXh0JyxcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogJ8O2dmVyc3RydWtlbiB0ZXh0JyxcbiAgICAnaGVhZGluZyB0ZXh0JzogJ1J1YnJpaycsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6ICdBbmdlIGzDpG5rIGJlc2tyaXZuaW5nIGjDpHInLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogJ1PDpHR0IGluIGzDpG5rJyxcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6ICdBbmdlIGJpbGQgYmVza3Jpdm5pbmcgaMOkcicsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiAnU8OkdHQgaW4gbMOkbmsgZsO2ciBiaWxkJyxcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6ICdBbmdlIGJpbGQgcnVicmlrIGjDpHInLFxuICAgICdsaXN0IHRleHQgaGVyZSc6ICdsaXN0IHRleHQnXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBUdXJraXNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIFNlcmthbiBBbGd1ciA8aW5mb0B3cGFkYW1pLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMudHIgPSB7XG4gICAgJ0JvbGQnOiBcIkthbMSxblwiLFxuICAgICdJdGFsaWMnOiBcIsSwdGFsaWtcIixcbiAgICAnSGVhZGluZyc6IFwiQmHFn2zEsWtcIixcbiAgICAnVVJML0xpbmsnOiBcIkxpbmsgZWtsZVwiLFxuICAgICdJbWFnZSc6IFwiUmVzaW0gZWtsZVwiLFxuICAgICdMaXN0JzogXCJMaXN0ZSBPbHXFn3R1cnVuXCIsXG4gICAgJ1ByZXZpZXcnOiBcIsOWbml6bGVtZVwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwia2FsxLFuIHlhesSxXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwiaXRhbGlrIHlhesSxXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwiQmHFn2zEsWsgWWF6xLFzxLFcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJMaW5rIGHDp8Sxa2xhbWFzxLFuxLEgYnVyYXlhIGdpcmluXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIsSwbnRlcm5ldCBhZHJlc2kgZ2lyaW5cIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwicmVzaW0gYcOnxLFrbGFtYXPEsW7EsSBidXJheWEgZWtsZXlpblwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJSZXNpbSBsaW5raW5pIGVrbGV5aW5cIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwicmVzaW0gYmHFn2zEscSfxLFuxLEgYnVyYXlhIGVrbGV5aW5cIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcImxpc3RlIHlhesSxc8SxXCIsXG4gICAgJ1NhdmUnIDogXCJLYXlkZXRcIixcbiAgICAnT3JkZXJlZCBMaXN0JyA6IFwiTnVtYXJhbMSxIExpc3RlXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JyA6IFwiTWFkZGUgaW1saSBsaXN0ZVwiLFxuICAgICdRdW90ZScgOiBcIkFsxLFudMSxXCIsXG4gICAgJ3F1b3RlIGhlcmUnIDogXCJhbMSxbnTEsXnEsSBidXJheWEgZWtsZXlpblwiLFxuICAgICdDb2RlJyA6IFwiS29kXCIsXG4gICAgJ2NvZGUgdGV4dCBoZXJlJyA6IFwia29kdSBidXJheWEgZWtsZXlpblwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBDaGluZXNlIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIGJlbmhhaWxlIDxkZW5naGFpZXJAMTYzLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMuemggPSB7XG4gICAgJ0JvbGQnOiBcIueyl+S9k1wiLFxuICAgICdJdGFsaWMnOiBcIuaWnOS9k1wiLFxuICAgICdIZWFkaW5nJzogXCLmoIfpophcIixcbiAgICAnVVJML0xpbmsnOiBcIumTvuaOpVwiLFxuICAgICdJbWFnZSc6IFwi5Zu+54mHXCIsXG4gICAgJ0xpc3QnOiBcIuWIl+ihqFwiLFxuICAgICdVbm9yZGVyZWQgTGlzdCc6IFwi5peg5bqP5YiX6KGoXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwi5pyJ5bqP5YiX6KGoXCIsXG4gICAgJ0NvZGUnOiBcIuS7o+eggVwiLFxuICAgICdRdW90ZSc6IFwi5byV55SoXCIsXG4gICAgJ1ByZXZpZXcnOiBcIumihOiniFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwi57KX5L2TXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwi5by66LCDXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwi5qCH6aKYXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwi6L6T5YWl6ZO+5o6l6K+05piOXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIlVSTOWcsOWdgFwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCLovpPlhaXlm77niYfor7TmmI5cIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwi5Zu+54mHVVJM5Zyw5Z2AXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIuWcqOi/memHjOi+k+WFpeWbvueJh+agh+mimFwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwi6L+Z6YeM5piv5YiX6KGo5paH5pysXCIsXG4gICAgJ2NvZGUgdGV4dCBoZXJlJzogXCLov5nph4zovpPlhaXku6PnoIFcIixcbiAgICAncXVvdGUgaGVyZSc6IFwi6L+Z6YeM6L6T5YWl5byV55So5paH5pysXCJcblxuXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiKGZ1bmN0aW9uKGdsb2JhbCxmYWN0b3J5KXt0eXBlb2YgZXhwb3J0cz09PVwib2JqZWN0XCImJnR5cGVvZiBtb2R1bGUhPT1cInVuZGVmaW5lZFwiP21vZHVsZS5leHBvcnRzPWZhY3RvcnkoKTp0eXBlb2YgZGVmaW5lPT09XCJmdW5jdGlvblwiJiZkZWZpbmUuYW1kP2RlZmluZShmYWN0b3J5KTooZ2xvYmFsPWdsb2JhbHx8c2VsZixnbG9iYWwuTXVzdGFjaGU9ZmFjdG9yeSgpKX0pKHRoaXMsZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgb2JqZWN0VG9TdHJpbmc9T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzt2YXIgaXNBcnJheT1BcnJheS5pc0FycmF5fHxmdW5jdGlvbiBpc0FycmF5UG9seWZpbGwob2JqZWN0KXtyZXR1cm4gb2JqZWN0VG9TdHJpbmcuY2FsbChvYmplY3QpPT09XCJbb2JqZWN0IEFycmF5XVwifTtmdW5jdGlvbiBpc0Z1bmN0aW9uKG9iamVjdCl7cmV0dXJuIHR5cGVvZiBvYmplY3Q9PT1cImZ1bmN0aW9uXCJ9ZnVuY3Rpb24gdHlwZVN0cihvYmope3JldHVybiBpc0FycmF5KG9iaik/XCJhcnJheVwiOnR5cGVvZiBvYmp9ZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHN0cmluZyl7cmV0dXJuIHN0cmluZy5yZXBsYWNlKC9bXFwtXFxbXFxde30oKSorPy4sXFxcXFxcXiR8I1xcc10vZyxcIlxcXFwkJlwiKX1mdW5jdGlvbiBoYXNQcm9wZXJ0eShvYmoscHJvcE5hbWUpe3JldHVybiBvYmohPW51bGwmJnR5cGVvZiBvYmo9PT1cIm9iamVjdFwiJiZwcm9wTmFtZSBpbiBvYmp9ZnVuY3Rpb24gcHJpbWl0aXZlSGFzT3duUHJvcGVydHkocHJpbWl0aXZlLHByb3BOYW1lKXtyZXR1cm4gcHJpbWl0aXZlIT1udWxsJiZ0eXBlb2YgcHJpbWl0aXZlIT09XCJvYmplY3RcIiYmcHJpbWl0aXZlLmhhc093blByb3BlcnR5JiZwcmltaXRpdmUuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpfXZhciByZWdFeHBUZXN0PVJlZ0V4cC5wcm90b3R5cGUudGVzdDtmdW5jdGlvbiB0ZXN0UmVnRXhwKHJlLHN0cmluZyl7cmV0dXJuIHJlZ0V4cFRlc3QuY2FsbChyZSxzdHJpbmcpfXZhciBub25TcGFjZVJlPS9cXFMvO2Z1bmN0aW9uIGlzV2hpdGVzcGFjZShzdHJpbmcpe3JldHVybiF0ZXN0UmVnRXhwKG5vblNwYWNlUmUsc3RyaW5nKX12YXIgZW50aXR5TWFwPXtcIiZcIjpcIiZhbXA7XCIsXCI8XCI6XCImbHQ7XCIsXCI+XCI6XCImZ3Q7XCIsJ1wiJzpcIiZxdW90O1wiLFwiJ1wiOlwiJiMzOTtcIixcIi9cIjpcIiYjeDJGO1wiLFwiYFwiOlwiJiN4NjA7XCIsXCI9XCI6XCImI3gzRDtcIn07ZnVuY3Rpb24gZXNjYXBlSHRtbChzdHJpbmcpe3JldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC9bJjw+XCInYD1cXC9dL2csZnVuY3Rpb24gZnJvbUVudGl0eU1hcChzKXtyZXR1cm4gZW50aXR5TWFwW3NdfSl9dmFyIHdoaXRlUmU9L1xccyovO3ZhciBzcGFjZVJlPS9cXHMrLzt2YXIgZXF1YWxzUmU9L1xccyo9Lzt2YXIgY3VybHlSZT0vXFxzKlxcfS87dmFyIHRhZ1JlPS8jfFxcXnxcXC98PnxcXHt8Jnw9fCEvO2Z1bmN0aW9uIHBhcnNlVGVtcGxhdGUodGVtcGxhdGUsdGFncyl7aWYoIXRlbXBsYXRlKXJldHVybltdO3ZhciBsaW5lSGFzTm9uU3BhY2U9ZmFsc2U7dmFyIHNlY3Rpb25zPVtdO3ZhciB0b2tlbnM9W107dmFyIHNwYWNlcz1bXTt2YXIgaGFzVGFnPWZhbHNlO3ZhciBub25TcGFjZT1mYWxzZTt2YXIgaW5kZW50YXRpb249XCJcIjt2YXIgdGFnSW5kZXg9MDtmdW5jdGlvbiBzdHJpcFNwYWNlKCl7aWYoaGFzVGFnJiYhbm9uU3BhY2Upe3doaWxlKHNwYWNlcy5sZW5ndGgpZGVsZXRlIHRva2Vuc1tzcGFjZXMucG9wKCldfWVsc2V7c3BhY2VzPVtdfWhhc1RhZz1mYWxzZTtub25TcGFjZT1mYWxzZX12YXIgb3BlbmluZ1RhZ1JlLGNsb3NpbmdUYWdSZSxjbG9zaW5nQ3VybHlSZTtmdW5jdGlvbiBjb21waWxlVGFncyh0YWdzVG9Db21waWxlKXtpZih0eXBlb2YgdGFnc1RvQ29tcGlsZT09PVwic3RyaW5nXCIpdGFnc1RvQ29tcGlsZT10YWdzVG9Db21waWxlLnNwbGl0KHNwYWNlUmUsMik7aWYoIWlzQXJyYXkodGFnc1RvQ29tcGlsZSl8fHRhZ3NUb0NvbXBpbGUubGVuZ3RoIT09Mil0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHRhZ3M6IFwiK3RhZ3NUb0NvbXBpbGUpO29wZW5pbmdUYWdSZT1uZXcgUmVnRXhwKGVzY2FwZVJlZ0V4cCh0YWdzVG9Db21waWxlWzBdKStcIlxcXFxzKlwiKTtjbG9zaW5nVGFnUmU9bmV3IFJlZ0V4cChcIlxcXFxzKlwiK2VzY2FwZVJlZ0V4cCh0YWdzVG9Db21waWxlWzFdKSk7Y2xvc2luZ0N1cmx5UmU9bmV3IFJlZ0V4cChcIlxcXFxzKlwiK2VzY2FwZVJlZ0V4cChcIn1cIit0YWdzVG9Db21waWxlWzFdKSl9Y29tcGlsZVRhZ3ModGFnc3x8bXVzdGFjaGUudGFncyk7dmFyIHNjYW5uZXI9bmV3IFNjYW5uZXIodGVtcGxhdGUpO3ZhciBzdGFydCx0eXBlLHZhbHVlLGNocix0b2tlbixvcGVuU2VjdGlvbjt3aGlsZSghc2Nhbm5lci5lb3MoKSl7c3RhcnQ9c2Nhbm5lci5wb3M7dmFsdWU9c2Nhbm5lci5zY2FuVW50aWwob3BlbmluZ1RhZ1JlKTtpZih2YWx1ZSl7Zm9yKHZhciBpPTAsdmFsdWVMZW5ndGg9dmFsdWUubGVuZ3RoO2k8dmFsdWVMZW5ndGg7KytpKXtjaHI9dmFsdWUuY2hhckF0KGkpO2lmKGlzV2hpdGVzcGFjZShjaHIpKXtzcGFjZXMucHVzaCh0b2tlbnMubGVuZ3RoKTtpbmRlbnRhdGlvbis9Y2hyfWVsc2V7bm9uU3BhY2U9dHJ1ZTtsaW5lSGFzTm9uU3BhY2U9dHJ1ZTtpbmRlbnRhdGlvbis9XCIgXCJ9dG9rZW5zLnB1c2goW1widGV4dFwiLGNocixzdGFydCxzdGFydCsxXSk7c3RhcnQrPTE7aWYoY2hyPT09XCJcXG5cIil7c3RyaXBTcGFjZSgpO2luZGVudGF0aW9uPVwiXCI7dGFnSW5kZXg9MDtsaW5lSGFzTm9uU3BhY2U9ZmFsc2V9fX1pZighc2Nhbm5lci5zY2FuKG9wZW5pbmdUYWdSZSkpYnJlYWs7aGFzVGFnPXRydWU7dHlwZT1zY2FubmVyLnNjYW4odGFnUmUpfHxcIm5hbWVcIjtzY2FubmVyLnNjYW4od2hpdGVSZSk7aWYodHlwZT09PVwiPVwiKXt2YWx1ZT1zY2FubmVyLnNjYW5VbnRpbChlcXVhbHNSZSk7c2Nhbm5lci5zY2FuKGVxdWFsc1JlKTtzY2FubmVyLnNjYW5VbnRpbChjbG9zaW5nVGFnUmUpfWVsc2UgaWYodHlwZT09PVwie1wiKXt2YWx1ZT1zY2FubmVyLnNjYW5VbnRpbChjbG9zaW5nQ3VybHlSZSk7c2Nhbm5lci5zY2FuKGN1cmx5UmUpO3NjYW5uZXIuc2NhblVudGlsKGNsb3NpbmdUYWdSZSk7dHlwZT1cIiZcIn1lbHNle3ZhbHVlPXNjYW5uZXIuc2NhblVudGlsKGNsb3NpbmdUYWdSZSl9aWYoIXNjYW5uZXIuc2NhbihjbG9zaW5nVGFnUmUpKXRocm93IG5ldyBFcnJvcihcIlVuY2xvc2VkIHRhZyBhdCBcIitzY2FubmVyLnBvcyk7aWYodHlwZT09XCI+XCIpe3Rva2VuPVt0eXBlLHZhbHVlLHN0YXJ0LHNjYW5uZXIucG9zLGluZGVudGF0aW9uLHRhZ0luZGV4LGxpbmVIYXNOb25TcGFjZV19ZWxzZXt0b2tlbj1bdHlwZSx2YWx1ZSxzdGFydCxzY2FubmVyLnBvc119dGFnSW5kZXgrKzt0b2tlbnMucHVzaCh0b2tlbik7aWYodHlwZT09PVwiI1wifHx0eXBlPT09XCJeXCIpe3NlY3Rpb25zLnB1c2godG9rZW4pfWVsc2UgaWYodHlwZT09PVwiL1wiKXtvcGVuU2VjdGlvbj1zZWN0aW9ucy5wb3AoKTtpZighb3BlblNlY3Rpb24pdGhyb3cgbmV3IEVycm9yKCdVbm9wZW5lZCBzZWN0aW9uIFwiJyt2YWx1ZSsnXCIgYXQgJytzdGFydCk7aWYob3BlblNlY3Rpb25bMV0hPT12YWx1ZSl0aHJvdyBuZXcgRXJyb3IoJ1VuY2xvc2VkIHNlY3Rpb24gXCInK29wZW5TZWN0aW9uWzFdKydcIiBhdCAnK3N0YXJ0KX1lbHNlIGlmKHR5cGU9PT1cIm5hbWVcInx8dHlwZT09PVwie1wifHx0eXBlPT09XCImXCIpe25vblNwYWNlPXRydWV9ZWxzZSBpZih0eXBlPT09XCI9XCIpe2NvbXBpbGVUYWdzKHZhbHVlKX19c3RyaXBTcGFjZSgpO29wZW5TZWN0aW9uPXNlY3Rpb25zLnBvcCgpO2lmKG9wZW5TZWN0aW9uKXRocm93IG5ldyBFcnJvcignVW5jbG9zZWQgc2VjdGlvbiBcIicrb3BlblNlY3Rpb25bMV0rJ1wiIGF0ICcrc2Nhbm5lci5wb3MpO3JldHVybiBuZXN0VG9rZW5zKHNxdWFzaFRva2Vucyh0b2tlbnMpKX1mdW5jdGlvbiBzcXVhc2hUb2tlbnModG9rZW5zKXt2YXIgc3F1YXNoZWRUb2tlbnM9W107dmFyIHRva2VuLGxhc3RUb2tlbjtmb3IodmFyIGk9MCxudW1Ub2tlbnM9dG9rZW5zLmxlbmd0aDtpPG51bVRva2VuczsrK2kpe3Rva2VuPXRva2Vuc1tpXTtpZih0b2tlbil7aWYodG9rZW5bMF09PT1cInRleHRcIiYmbGFzdFRva2VuJiZsYXN0VG9rZW5bMF09PT1cInRleHRcIil7bGFzdFRva2VuWzFdKz10b2tlblsxXTtsYXN0VG9rZW5bM109dG9rZW5bM119ZWxzZXtzcXVhc2hlZFRva2Vucy5wdXNoKHRva2VuKTtsYXN0VG9rZW49dG9rZW59fX1yZXR1cm4gc3F1YXNoZWRUb2tlbnN9ZnVuY3Rpb24gbmVzdFRva2Vucyh0b2tlbnMpe3ZhciBuZXN0ZWRUb2tlbnM9W107dmFyIGNvbGxlY3Rvcj1uZXN0ZWRUb2tlbnM7dmFyIHNlY3Rpb25zPVtdO3ZhciB0b2tlbixzZWN0aW9uO2Zvcih2YXIgaT0wLG51bVRva2Vucz10b2tlbnMubGVuZ3RoO2k8bnVtVG9rZW5zOysraSl7dG9rZW49dG9rZW5zW2ldO3N3aXRjaCh0b2tlblswXSl7Y2FzZVwiI1wiOmNhc2VcIl5cIjpjb2xsZWN0b3IucHVzaCh0b2tlbik7c2VjdGlvbnMucHVzaCh0b2tlbik7Y29sbGVjdG9yPXRva2VuWzRdPVtdO2JyZWFrO2Nhc2VcIi9cIjpzZWN0aW9uPXNlY3Rpb25zLnBvcCgpO3NlY3Rpb25bNV09dG9rZW5bMl07Y29sbGVjdG9yPXNlY3Rpb25zLmxlbmd0aD4wP3NlY3Rpb25zW3NlY3Rpb25zLmxlbmd0aC0xXVs0XTpuZXN0ZWRUb2tlbnM7YnJlYWs7ZGVmYXVsdDpjb2xsZWN0b3IucHVzaCh0b2tlbil9fXJldHVybiBuZXN0ZWRUb2tlbnN9ZnVuY3Rpb24gU2Nhbm5lcihzdHJpbmcpe3RoaXMuc3RyaW5nPXN0cmluZzt0aGlzLnRhaWw9c3RyaW5nO3RoaXMucG9zPTB9U2Nhbm5lci5wcm90b3R5cGUuZW9zPWZ1bmN0aW9uIGVvcygpe3JldHVybiB0aGlzLnRhaWw9PT1cIlwifTtTY2FubmVyLnByb3RvdHlwZS5zY2FuPWZ1bmN0aW9uIHNjYW4ocmUpe3ZhciBtYXRjaD10aGlzLnRhaWwubWF0Y2gocmUpO2lmKCFtYXRjaHx8bWF0Y2guaW5kZXghPT0wKXJldHVyblwiXCI7dmFyIHN0cmluZz1tYXRjaFswXTt0aGlzLnRhaWw9dGhpcy50YWlsLnN1YnN0cmluZyhzdHJpbmcubGVuZ3RoKTt0aGlzLnBvcys9c3RyaW5nLmxlbmd0aDtyZXR1cm4gc3RyaW5nfTtTY2FubmVyLnByb3RvdHlwZS5zY2FuVW50aWw9ZnVuY3Rpb24gc2NhblVudGlsKHJlKXt2YXIgaW5kZXg9dGhpcy50YWlsLnNlYXJjaChyZSksbWF0Y2g7c3dpdGNoKGluZGV4KXtjYXNlLTE6bWF0Y2g9dGhpcy50YWlsO3RoaXMudGFpbD1cIlwiO2JyZWFrO2Nhc2UgMDptYXRjaD1cIlwiO2JyZWFrO2RlZmF1bHQ6bWF0Y2g9dGhpcy50YWlsLnN1YnN0cmluZygwLGluZGV4KTt0aGlzLnRhaWw9dGhpcy50YWlsLnN1YnN0cmluZyhpbmRleCl9dGhpcy5wb3MrPW1hdGNoLmxlbmd0aDtyZXR1cm4gbWF0Y2h9O2Z1bmN0aW9uIENvbnRleHQodmlldyxwYXJlbnRDb250ZXh0KXt0aGlzLnZpZXc9dmlldzt0aGlzLmNhY2hlPXtcIi5cIjp0aGlzLnZpZXd9O3RoaXMucGFyZW50PXBhcmVudENvbnRleHR9Q29udGV4dC5wcm90b3R5cGUucHVzaD1mdW5jdGlvbiBwdXNoKHZpZXcpe3JldHVybiBuZXcgQ29udGV4dCh2aWV3LHRoaXMpfTtDb250ZXh0LnByb3RvdHlwZS5sb29rdXA9ZnVuY3Rpb24gbG9va3VwKG5hbWUpe3ZhciBjYWNoZT10aGlzLmNhY2hlO3ZhciB2YWx1ZTtpZihjYWNoZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSl7dmFsdWU9Y2FjaGVbbmFtZV19ZWxzZXt2YXIgY29udGV4dD10aGlzLGludGVybWVkaWF0ZVZhbHVlLG5hbWVzLGluZGV4LGxvb2t1cEhpdD1mYWxzZTt3aGlsZShjb250ZXh0KXtpZihuYW1lLmluZGV4T2YoXCIuXCIpPjApe2ludGVybWVkaWF0ZVZhbHVlPWNvbnRleHQudmlldztuYW1lcz1uYW1lLnNwbGl0KFwiLlwiKTtpbmRleD0wO3doaWxlKGludGVybWVkaWF0ZVZhbHVlIT1udWxsJiZpbmRleDxuYW1lcy5sZW5ndGgpe2lmKGluZGV4PT09bmFtZXMubGVuZ3RoLTEpbG9va3VwSGl0PWhhc1Byb3BlcnR5KGludGVybWVkaWF0ZVZhbHVlLG5hbWVzW2luZGV4XSl8fHByaW1pdGl2ZUhhc093blByb3BlcnR5KGludGVybWVkaWF0ZVZhbHVlLG5hbWVzW2luZGV4XSk7aW50ZXJtZWRpYXRlVmFsdWU9aW50ZXJtZWRpYXRlVmFsdWVbbmFtZXNbaW5kZXgrK11dfX1lbHNle2ludGVybWVkaWF0ZVZhbHVlPWNvbnRleHQudmlld1tuYW1lXTtsb29rdXBIaXQ9aGFzUHJvcGVydHkoY29udGV4dC52aWV3LG5hbWUpfWlmKGxvb2t1cEhpdCl7dmFsdWU9aW50ZXJtZWRpYXRlVmFsdWU7YnJlYWt9Y29udGV4dD1jb250ZXh0LnBhcmVudH1jYWNoZVtuYW1lXT12YWx1ZX1pZihpc0Z1bmN0aW9uKHZhbHVlKSl2YWx1ZT12YWx1ZS5jYWxsKHRoaXMudmlldyk7cmV0dXJuIHZhbHVlfTtmdW5jdGlvbiBXcml0ZXIoKXt0aGlzLnRlbXBsYXRlQ2FjaGU9e19jYWNoZTp7fSxzZXQ6ZnVuY3Rpb24gc2V0KGtleSx2YWx1ZSl7dGhpcy5fY2FjaGVba2V5XT12YWx1ZX0sZ2V0OmZ1bmN0aW9uIGdldChrZXkpe3JldHVybiB0aGlzLl9jYWNoZVtrZXldfSxjbGVhcjpmdW5jdGlvbiBjbGVhcigpe3RoaXMuX2NhY2hlPXt9fX19V3JpdGVyLnByb3RvdHlwZS5jbGVhckNhY2hlPWZ1bmN0aW9uIGNsZWFyQ2FjaGUoKXtpZih0eXBlb2YgdGhpcy50ZW1wbGF0ZUNhY2hlIT09XCJ1bmRlZmluZWRcIil7dGhpcy50ZW1wbGF0ZUNhY2hlLmNsZWFyKCl9fTtXcml0ZXIucHJvdG90eXBlLnBhcnNlPWZ1bmN0aW9uIHBhcnNlKHRlbXBsYXRlLHRhZ3Mpe3ZhciBjYWNoZT10aGlzLnRlbXBsYXRlQ2FjaGU7dmFyIGNhY2hlS2V5PXRlbXBsYXRlK1wiOlwiKyh0YWdzfHxtdXN0YWNoZS50YWdzKS5qb2luKFwiOlwiKTt2YXIgaXNDYWNoZUVuYWJsZWQ9dHlwZW9mIGNhY2hlIT09XCJ1bmRlZmluZWRcIjt2YXIgdG9rZW5zPWlzQ2FjaGVFbmFibGVkP2NhY2hlLmdldChjYWNoZUtleSk6dW5kZWZpbmVkO2lmKHRva2Vucz09dW5kZWZpbmVkKXt0b2tlbnM9cGFyc2VUZW1wbGF0ZSh0ZW1wbGF0ZSx0YWdzKTtpc0NhY2hlRW5hYmxlZCYmY2FjaGUuc2V0KGNhY2hlS2V5LHRva2Vucyl9cmV0dXJuIHRva2Vuc307V3JpdGVyLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24gcmVuZGVyKHRlbXBsYXRlLHZpZXcscGFydGlhbHMsY29uZmlnKXt2YXIgdGFncz10aGlzLmdldENvbmZpZ1RhZ3MoY29uZmlnKTt2YXIgdG9rZW5zPXRoaXMucGFyc2UodGVtcGxhdGUsdGFncyk7dmFyIGNvbnRleHQ9dmlldyBpbnN0YW5jZW9mIENvbnRleHQ/dmlldzpuZXcgQ29udGV4dCh2aWV3LHVuZGVmaW5lZCk7cmV0dXJuIHRoaXMucmVuZGVyVG9rZW5zKHRva2Vucyxjb250ZXh0LHBhcnRpYWxzLHRlbXBsYXRlLGNvbmZpZyl9O1dyaXRlci5wcm90b3R5cGUucmVuZGVyVG9rZW5zPWZ1bmN0aW9uIHJlbmRlclRva2Vucyh0b2tlbnMsY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlLGNvbmZpZyl7dmFyIGJ1ZmZlcj1cIlwiO3ZhciB0b2tlbixzeW1ib2wsdmFsdWU7Zm9yKHZhciBpPTAsbnVtVG9rZW5zPXRva2Vucy5sZW5ndGg7aTxudW1Ub2tlbnM7KytpKXt2YWx1ZT11bmRlZmluZWQ7dG9rZW49dG9rZW5zW2ldO3N5bWJvbD10b2tlblswXTtpZihzeW1ib2w9PT1cIiNcIil2YWx1ZT10aGlzLnJlbmRlclNlY3Rpb24odG9rZW4sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlLGNvbmZpZyk7ZWxzZSBpZihzeW1ib2w9PT1cIl5cIil2YWx1ZT10aGlzLnJlbmRlckludmVydGVkKHRva2VuLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSxjb25maWcpO2Vsc2UgaWYoc3ltYm9sPT09XCI+XCIpdmFsdWU9dGhpcy5yZW5kZXJQYXJ0aWFsKHRva2VuLGNvbnRleHQscGFydGlhbHMsY29uZmlnKTtlbHNlIGlmKHN5bWJvbD09PVwiJlwiKXZhbHVlPXRoaXMudW5lc2NhcGVkVmFsdWUodG9rZW4sY29udGV4dCk7ZWxzZSBpZihzeW1ib2w9PT1cIm5hbWVcIil2YWx1ZT10aGlzLmVzY2FwZWRWYWx1ZSh0b2tlbixjb250ZXh0LGNvbmZpZyk7ZWxzZSBpZihzeW1ib2w9PT1cInRleHRcIil2YWx1ZT10aGlzLnJhd1ZhbHVlKHRva2VuKTtpZih2YWx1ZSE9PXVuZGVmaW5lZClidWZmZXIrPXZhbHVlfXJldHVybiBidWZmZXJ9O1dyaXRlci5wcm90b3R5cGUucmVuZGVyU2VjdGlvbj1mdW5jdGlvbiByZW5kZXJTZWN0aW9uKHRva2VuLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSxjb25maWcpe3ZhciBzZWxmPXRoaXM7dmFyIGJ1ZmZlcj1cIlwiO3ZhciB2YWx1ZT1jb250ZXh0Lmxvb2t1cCh0b2tlblsxXSk7ZnVuY3Rpb24gc3ViUmVuZGVyKHRlbXBsYXRlKXtyZXR1cm4gc2VsZi5yZW5kZXIodGVtcGxhdGUsY29udGV4dCxwYXJ0aWFscyxjb25maWcpfWlmKCF2YWx1ZSlyZXR1cm47aWYoaXNBcnJheSh2YWx1ZSkpe2Zvcih2YXIgaj0wLHZhbHVlTGVuZ3RoPXZhbHVlLmxlbmd0aDtqPHZhbHVlTGVuZ3RoOysrail7YnVmZmVyKz10aGlzLnJlbmRlclRva2Vucyh0b2tlbls0XSxjb250ZXh0LnB1c2godmFsdWVbal0pLHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUsY29uZmlnKX19ZWxzZSBpZih0eXBlb2YgdmFsdWU9PT1cIm9iamVjdFwifHx0eXBlb2YgdmFsdWU9PT1cInN0cmluZ1wifHx0eXBlb2YgdmFsdWU9PT1cIm51bWJlclwiKXtidWZmZXIrPXRoaXMucmVuZGVyVG9rZW5zKHRva2VuWzRdLGNvbnRleHQucHVzaCh2YWx1ZSkscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSxjb25maWcpfWVsc2UgaWYoaXNGdW5jdGlvbih2YWx1ZSkpe2lmKHR5cGVvZiBvcmlnaW5hbFRlbXBsYXRlIT09XCJzdHJpbmdcIil0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgdXNlIGhpZ2hlci1vcmRlciBzZWN0aW9ucyB3aXRob3V0IHRoZSBvcmlnaW5hbCB0ZW1wbGF0ZVwiKTt2YWx1ZT12YWx1ZS5jYWxsKGNvbnRleHQudmlldyxvcmlnaW5hbFRlbXBsYXRlLnNsaWNlKHRva2VuWzNdLHRva2VuWzVdKSxzdWJSZW5kZXIpO2lmKHZhbHVlIT1udWxsKWJ1ZmZlcis9dmFsdWV9ZWxzZXtidWZmZXIrPXRoaXMucmVuZGVyVG9rZW5zKHRva2VuWzRdLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSxjb25maWcpfXJldHVybiBidWZmZXJ9O1dyaXRlci5wcm90b3R5cGUucmVuZGVySW52ZXJ0ZWQ9ZnVuY3Rpb24gcmVuZGVySW52ZXJ0ZWQodG9rZW4sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlLGNvbmZpZyl7dmFyIHZhbHVlPWNvbnRleHQubG9va3VwKHRva2VuWzFdKTtpZighdmFsdWV8fGlzQXJyYXkodmFsdWUpJiZ2YWx1ZS5sZW5ndGg9PT0wKXJldHVybiB0aGlzLnJlbmRlclRva2Vucyh0b2tlbls0XSxjb250ZXh0LHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUsY29uZmlnKX07V3JpdGVyLnByb3RvdHlwZS5pbmRlbnRQYXJ0aWFsPWZ1bmN0aW9uIGluZGVudFBhcnRpYWwocGFydGlhbCxpbmRlbnRhdGlvbixsaW5lSGFzTm9uU3BhY2Upe3ZhciBmaWx0ZXJlZEluZGVudGF0aW9uPWluZGVudGF0aW9uLnJlcGxhY2UoL1teIFxcdF0vZyxcIlwiKTt2YXIgcGFydGlhbEJ5Tmw9cGFydGlhbC5zcGxpdChcIlxcblwiKTtmb3IodmFyIGk9MDtpPHBhcnRpYWxCeU5sLmxlbmd0aDtpKyspe2lmKHBhcnRpYWxCeU5sW2ldLmxlbmd0aCYmKGk+MHx8IWxpbmVIYXNOb25TcGFjZSkpe3BhcnRpYWxCeU5sW2ldPWZpbHRlcmVkSW5kZW50YXRpb24rcGFydGlhbEJ5TmxbaV19fXJldHVybiBwYXJ0aWFsQnlObC5qb2luKFwiXFxuXCIpfTtXcml0ZXIucHJvdG90eXBlLnJlbmRlclBhcnRpYWw9ZnVuY3Rpb24gcmVuZGVyUGFydGlhbCh0b2tlbixjb250ZXh0LHBhcnRpYWxzLGNvbmZpZyl7aWYoIXBhcnRpYWxzKXJldHVybjt2YXIgdGFncz10aGlzLmdldENvbmZpZ1RhZ3MoY29uZmlnKTt2YXIgdmFsdWU9aXNGdW5jdGlvbihwYXJ0aWFscyk/cGFydGlhbHModG9rZW5bMV0pOnBhcnRpYWxzW3Rva2VuWzFdXTtpZih2YWx1ZSE9bnVsbCl7dmFyIGxpbmVIYXNOb25TcGFjZT10b2tlbls2XTt2YXIgdGFnSW5kZXg9dG9rZW5bNV07dmFyIGluZGVudGF0aW9uPXRva2VuWzRdO3ZhciBpbmRlbnRlZFZhbHVlPXZhbHVlO2lmKHRhZ0luZGV4PT0wJiZpbmRlbnRhdGlvbil7aW5kZW50ZWRWYWx1ZT10aGlzLmluZGVudFBhcnRpYWwodmFsdWUsaW5kZW50YXRpb24sbGluZUhhc05vblNwYWNlKX12YXIgdG9rZW5zPXRoaXMucGFyc2UoaW5kZW50ZWRWYWx1ZSx0YWdzKTtyZXR1cm4gdGhpcy5yZW5kZXJUb2tlbnModG9rZW5zLGNvbnRleHQscGFydGlhbHMsaW5kZW50ZWRWYWx1ZSxjb25maWcpfX07V3JpdGVyLnByb3RvdHlwZS51bmVzY2FwZWRWYWx1ZT1mdW5jdGlvbiB1bmVzY2FwZWRWYWx1ZSh0b2tlbixjb250ZXh0KXt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2lmKHZhbHVlIT1udWxsKXJldHVybiB2YWx1ZX07V3JpdGVyLnByb3RvdHlwZS5lc2NhcGVkVmFsdWU9ZnVuY3Rpb24gZXNjYXBlZFZhbHVlKHRva2VuLGNvbnRleHQsY29uZmlnKXt2YXIgZXNjYXBlPXRoaXMuZ2V0Q29uZmlnRXNjYXBlKGNvbmZpZyl8fG11c3RhY2hlLmVzY2FwZTt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2lmKHZhbHVlIT1udWxsKXJldHVybiB0eXBlb2YgdmFsdWU9PT1cIm51bWJlclwiJiZlc2NhcGU9PT1tdXN0YWNoZS5lc2NhcGU/U3RyaW5nKHZhbHVlKTplc2NhcGUodmFsdWUpfTtXcml0ZXIucHJvdG90eXBlLnJhd1ZhbHVlPWZ1bmN0aW9uIHJhd1ZhbHVlKHRva2VuKXtyZXR1cm4gdG9rZW5bMV19O1dyaXRlci5wcm90b3R5cGUuZ2V0Q29uZmlnVGFncz1mdW5jdGlvbiBnZXRDb25maWdUYWdzKGNvbmZpZyl7aWYoaXNBcnJheShjb25maWcpKXtyZXR1cm4gY29uZmlnfWVsc2UgaWYoY29uZmlnJiZ0eXBlb2YgY29uZmlnPT09XCJvYmplY3RcIil7cmV0dXJuIGNvbmZpZy50YWdzfWVsc2V7cmV0dXJuIHVuZGVmaW5lZH19O1dyaXRlci5wcm90b3R5cGUuZ2V0Q29uZmlnRXNjYXBlPWZ1bmN0aW9uIGdldENvbmZpZ0VzY2FwZShjb25maWcpe2lmKGNvbmZpZyYmdHlwZW9mIGNvbmZpZz09PVwib2JqZWN0XCImJiFpc0FycmF5KGNvbmZpZykpe3JldHVybiBjb25maWcuZXNjYXBlfWVsc2V7cmV0dXJuIHVuZGVmaW5lZH19O3ZhciBtdXN0YWNoZT17bmFtZTpcIm11c3RhY2hlLmpzXCIsdmVyc2lvbjpcIjQuMS4wXCIsdGFnczpbXCJ7e1wiLFwifX1cIl0sY2xlYXJDYWNoZTp1bmRlZmluZWQsZXNjYXBlOnVuZGVmaW5lZCxwYXJzZTp1bmRlZmluZWQscmVuZGVyOnVuZGVmaW5lZCxTY2FubmVyOnVuZGVmaW5lZCxDb250ZXh0OnVuZGVmaW5lZCxXcml0ZXI6dW5kZWZpbmVkLHNldCB0ZW1wbGF0ZUNhY2hlKGNhY2hlKXtkZWZhdWx0V3JpdGVyLnRlbXBsYXRlQ2FjaGU9Y2FjaGV9LGdldCB0ZW1wbGF0ZUNhY2hlKCl7cmV0dXJuIGRlZmF1bHRXcml0ZXIudGVtcGxhdGVDYWNoZX19O3ZhciBkZWZhdWx0V3JpdGVyPW5ldyBXcml0ZXI7bXVzdGFjaGUuY2xlYXJDYWNoZT1mdW5jdGlvbiBjbGVhckNhY2hlKCl7cmV0dXJuIGRlZmF1bHRXcml0ZXIuY2xlYXJDYWNoZSgpfTttdXN0YWNoZS5wYXJzZT1mdW5jdGlvbiBwYXJzZSh0ZW1wbGF0ZSx0YWdzKXtyZXR1cm4gZGVmYXVsdFdyaXRlci5wYXJzZSh0ZW1wbGF0ZSx0YWdzKX07bXVzdGFjaGUucmVuZGVyPWZ1bmN0aW9uIHJlbmRlcih0ZW1wbGF0ZSx2aWV3LHBhcnRpYWxzLGNvbmZpZyl7aWYodHlwZW9mIHRlbXBsYXRlIT09XCJzdHJpbmdcIil7dGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCB0ZW1wbGF0ZSEgVGVtcGxhdGUgc2hvdWxkIGJlIGEgXCJzdHJpbmdcIiAnKydidXQgXCInK3R5cGVTdHIodGVtcGxhdGUpKydcIiB3YXMgZ2l2ZW4gYXMgdGhlIGZpcnN0ICcrXCJhcmd1bWVudCBmb3IgbXVzdGFjaGUjcmVuZGVyKHRlbXBsYXRlLCB2aWV3LCBwYXJ0aWFscylcIil9cmV0dXJuIGRlZmF1bHRXcml0ZXIucmVuZGVyKHRlbXBsYXRlLHZpZXcscGFydGlhbHMsY29uZmlnKX07bXVzdGFjaGUuZXNjYXBlPWVzY2FwZUh0bWw7bXVzdGFjaGUuU2Nhbm5lcj1TY2FubmVyO211c3RhY2hlLkNvbnRleHQ9Q29udGV4dDttdXN0YWNoZS5Xcml0ZXI9V3JpdGVyO3JldHVybiBtdXN0YWNoZX0pO1xuIiwiLyohXG4qXG4qICBDb3B5cmlnaHQgMjAxNiBZYW5uIE1hc3NhcmQgKGh0dHBzOi8vZ2l0aHViLmNvbS95YW1hc3MpIGFuZCBvdGhlciBjb250cmlidXRvcnNcbipcbiogIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4qICB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4qICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbipcbiogIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuKlxuKiAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuKiAgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuKiAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4qICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4qICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbipcbiovXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcImxldmVuc2h0ZWluXCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIExldmVuc2h0ZWluID0gcmVxdWlyZShcImxldmVuc2h0ZWluXCIpO1xuICAgIGV4cG9ydHMua2V5Q29kZXMgPSB7XG4gICAgICAgIGJhY2tzcGFjZTogOCxcbiAgICAgICAgdGFiOiA5LFxuICAgICAgICBlbnRlcjogMTMsXG4gICAgICAgIHNoaWZ0OiAxNixcbiAgICAgICAgY3RybDogMTcsXG4gICAgICAgIGFsdDogMTgsXG4gICAgICAgIHBhdXNlOiAxOSxcbiAgICAgICAgY2Fwc19sb2NrOiAyMCxcbiAgICAgICAgZXNjYXBlOiAyNyxcbiAgICAgICAgc3BhY2U6IDMyLFxuICAgICAgICBwYWdlX3VwOiAzMyxcbiAgICAgICAgcGFnZV9kb3duOiAzNCxcbiAgICAgICAgZW5kOiAzNSxcbiAgICAgICAgaG9tZTogMzYsXG4gICAgICAgIGxlZnRfYXJyb3c6IDM3LFxuICAgICAgICB1cF9hcnJvdzogMzgsXG4gICAgICAgIHJpZ2h0X2Fycm93OiAzOSxcbiAgICAgICAgZG93bl9hcnJvdzogNDAsXG4gICAgICAgIGluc2VydDogNDUsXG4gICAgICAgIFwiZGVsZXRlXCI6IDQ2LFxuICAgICAgICBsZWZ0X3dpbmRvd19rZXk6IDkxLFxuICAgICAgICByaWdodF93aW5kb3dfa2V5OiA5MixcbiAgICAgICAgc2VsZWN0X2tleTogOTMsXG4gICAgICAgIG51bV9sb2NrOiAxNDQsXG4gICAgICAgIHNjcm9sbF9sb2NrOiAxNDUsXG4gICAgICAgIHNwZWNpYWxLZXlzOiBbOCwgOSwgMTMsIDE2LCAxNywgMTgsIDE5LCAyMCwgMjcsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDUsIDQ2LCA5MSwgOTIsIDkzLCAxNDQsIDE0NV0sXG4gICAgICAgIG51bWJlcktleXM6IFs0OCwgNDksIDUwLCA1MSwgNTIsIDUzLCA1NCwgNTUsIDU2LCA1NywgOTYsIDk3LCA5OCwgOTksIDEwMCwgMTAxLCAxMDIsIDEwMywgMTA0LCAxMDVdLFxuICAgICAgICBpc1NwZWNpYWxLZXk6IGZ1bmN0aW9uIChrZXlDb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zcGVjaWFsS2V5cy5pbmRleE9mKGtleUNvZGUpICE9IC0xO1xuICAgICAgICB9LFxuICAgICAgICBpc0RpZ2l0S2V5OiBmdW5jdGlvbiAoa2V5Q29kZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtYmVyS2V5cy5pbmRleE9mKGtleUNvZGUpICE9IC0xO1xuICAgICAgICB9LFxuICAgICAgICBpc01vZGlmaWVyS2V5OiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIFtleHBvcnRzLmtleUNvZGVzLnNoaWZ0LCBleHBvcnRzLmtleUNvZGVzLmNhcHNfbG9jaywgZXhwb3J0cy5rZXlDb2Rlcy5hbHQsIGV4cG9ydHMua2V5Q29kZXMuY3RybCwgZXhwb3J0cy5rZXlDb2Rlcy5sZWZ0X3dpbmRvd19rZXksIGV4cG9ydHMua2V5Q29kZXMucmlnaHRfd2luZG93X2tleV1cbiAgICAgICAgICAgICAgICAuaW5kZXhPZihlLndoaWNoKSAhPSAtMTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgZXhwb3J0cy5ERUZBVUxUX1RFTVBMQVRFUyA9IHtcbiAgICAgICAgaW1hZ2UyTGluZXNUZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJ0ci10ZW1wbGF0ZS1pbWFnZS0yLWxpbmVzXCI+JyArXG4gICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwiaW1nLXdyYXBwZXJcIiBzdHlsZT1cImJhY2tncm91bmQtaW1hZ2U6IHVybCh7e2ltYWdlVXJsfX0pXCI+PC9kaXY+JyArXG4gICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwiY29udGVudC13cmFwcGVyIHRyLWVkaXRvci1hcmVhXCI+ICcgK1xuICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwibWFpbi1saW5lXCI+e3tkaXNwbGF5VmFsdWV9fTwvZGl2PiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImFkZGl0aW9uYWwtaW5mb1wiPnt7YWRkaXRpb25hbEluZm99fTwvZGl2PicgK1xuICAgICAgICAgICAgJyAgPC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgcm91bmRJbWFnZTJMaW5lc0NvbG9yQnViYmxlVGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtcm91bmQtaW1hZ2UtMi1saW5lcy1jb2xvci1idWJibGVcIj4nICtcbiAgICAgICAgICAgICcgIHt7I2ltYWdlVXJsfX08ZGl2IGNsYXNzPVwiaW1nLXdyYXBwZXJcIiBzdHlsZT1cImJhY2tncm91bmQtaW1hZ2U6IHVybCh7e2ltYWdlVXJsfX0pXCI+PC9kaXY+e3svaW1hZ2VVcmx9fScgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cIm1haW4tbGluZVwiPnt7ZGlzcGxheVZhbHVlfX08L2Rpdj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJhZGRpdGlvbmFsLWluZm9cIj57eyNzdGF0dXNDb2xvcn19PHNwYW4gY2xhc3M9XCJzdGF0dXMtYnViYmxlXCIgc3R5bGU9XCJiYWNrZ3JvdW5kLWNvbG9yOiB7e3N0YXR1c0NvbG9yfX1cIj48L3NwYW4+e3svc3RhdHVzQ29sb3J9fXt7YWRkaXRpb25hbEluZm99fTwvZGl2PicgK1xuICAgICAgICAgICAgJyAgPC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgaWNvbjJMaW5lc1RlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRyLXRlbXBsYXRlLWljb24tMi1saW5lc1wiPicgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImltZy13cmFwcGVyXCIgc3R5bGU9XCJiYWNrZ3JvdW5kLWltYWdlOiB1cmwoe3tpbWFnZVVybH19KVwiPjwvZGl2PicgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cIm1haW4tbGluZVwiPnt7ZGlzcGxheVZhbHVlfX08L2Rpdj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJhZGRpdGlvbmFsLWluZm9cIj57e2FkZGl0aW9uYWxJbmZvfX08L2Rpdj4nICtcbiAgICAgICAgICAgICcgIDwvZGl2PicgK1xuICAgICAgICAgICAgJzwvZGl2PicsXG4gICAgICAgIGljb25TaW5nbGVMaW5lVGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtaWNvbi1zaW5nbGUtbGluZVwiPicgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImltZy13cmFwcGVyXCIgc3R5bGU9XCJiYWNrZ3JvdW5kLWltYWdlOiB1cmwoe3tpbWFnZVVybH19KVwiPjwvZGl2PicgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPnt7ZGlzcGxheVZhbHVlfX08L2Rpdj4nICtcbiAgICAgICAgICAgICc8L2Rpdj4nLFxuICAgICAgICBzaW5nbGVMaW5lVGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtc2luZ2xlLWxpbmVcIj4nICtcbiAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJjb250ZW50LXdyYXBwZXIgdHItZWRpdG9yLWFyZWFcIj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXY+e3tkaXNwbGF5VmFsdWV9fTwvZGl2PiAnICtcbiAgICAgICAgICAgICcgIDwvZGl2PicgK1xuICAgICAgICAgICAgJzwvZGl2PicsXG4gICAgICAgIGN1cnJlbmN5U2luZ2xlTGluZVNob3J0VGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtY3VycmVuY3ktc2luZ2xlLWxpbmUtc2hvcnRcIj4nICtcbiAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJjb250ZW50LXdyYXBwZXIgdHItZWRpdG9yLWFyZWFcIj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXY+e3sjc3ltYm9sfX08c3BhbiBjbGFzcz1cImN1cnJlbmN5LXN5bWJvbFwiPnt7c3ltYm9sfX08L3NwYW4+e3svc3ltYm9sfX0ge3sjY29kZX19PHNwYW4gY2xhc3M9XCJjdXJyZW5jeS1jb2RlXCI+e3tjb2RlfX08L3NwYW4+e3svY29kZX19PC9kaXY+ICcgK1xuICAgICAgICAgICAgJyAgPC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgY3VycmVuY3lTaW5nbGVMaW5lTG9uZ1RlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRyLXRlbXBsYXRlLWN1cnJlbmN5LXNpbmdsZS1saW5lLWxvbmdcIj4nICtcbiAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJjb250ZW50LXdyYXBwZXIgdHItZWRpdG9yLWFyZWFcIj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJzeW1ib2wtYW5kLWNvZGVcIj57eyNjb2RlfX08c3BhbiBjbGFzcz1cImN1cnJlbmN5LWNvZGVcIj57e2NvZGV9fTwvc3Bhbj57ey9jb2RlfX0ge3sjc3ltYm9sfX08c3BhbiBjbGFzcz1cImN1cnJlbmN5LXN5bWJvbFwiPnt7c3ltYm9sfX08L3NwYW4+e3svc3ltYm9sfX08L2Rpdj4nICtcbiAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImN1cnJlbmN5LW5hbWVcIj57e25hbWV9fTwvZGl2PicgK1xuICAgICAgICAgICAgJyAgPC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgY3VycmVuY3kyTGluZVRlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRyLXRlbXBsYXRlLWN1cnJlbmN5LTItbGluZXNcIj4nICtcbiAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJjb250ZW50LXdyYXBwZXIgdHItZWRpdG9yLWFyZWFcIj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJtYWluLWxpbmVcIj4nICtcbiAgICAgICAgICAgICcgICAgICA8c3BhbiBjbGFzcz1cImN1cnJlbmN5LWNvZGVcIj57e2NvZGV9fTwvc3Bhbj4nICtcbiAgICAgICAgICAgICcgICAgICA8c3BhbiBjbGFzcz1cImN1cnJlbmN5LW5hbWVcIj57e25hbWV9fTwvc3Bhbj4nICtcbiAgICAgICAgICAgICcgICAgPC9kaXY+ICcgK1xuICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwiYWRkaXRpb25hbC1pbmZvXCI+JyArXG4gICAgICAgICAgICAnICAgICAgPHNwYW4gY2xhc3M9XCJjdXJyZW5jeS1zeW1ib2xcIj57e3N5bWJvbH19PC9zcGFuPiZuYnNwOycgK1xuICAgICAgICAgICAgJyAgICAgIHt7I2V4Y2hhbmdlUmF0ZX19JyArXG4gICAgICAgICAgICAnICAgICAgPGRpdiBjbGFzcz1cImV4Y2hhbmdlXCI+JyArXG4gICAgICAgICAgICAnICAgICAgICA9ICcgK1xuICAgICAgICAgICAgJyAgICAgICAgPHNwYW4gY2xhc3M9XCJleGNoYW5nZS1yYXRlXCI+e3tleGNoYW5nZVJhdGV9fTwvc3Bhbj4nICtcbiAgICAgICAgICAgICcgICAgICAgIDxzcGFuIGNsYXNzPVwiZXhjaGFuZ2UtcmF0ZS1iYXNlXCI+e3tleGNoYW5nZVJhdGVCYXNlfX08L3NwYW4+JyArXG4gICAgICAgICAgICAnICAgICAgPC9kaXY+JyArXG4gICAgICAgICAgICAnICAgICAge3svZXhjaGFuZ2VSYXRlfX0nICtcbiAgICAgICAgICAgICcgICAgPC9kaXY+JyArXG4gICAgICAgICAgICAnICA8L2Rpdj4nICtcbiAgICAgICAgICAgICc8L2Rpdj4nLFxuICAgICAgICBkZWZhdWx0U3Bpbm5lclRlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRyLWRlZmF1bHQtc3Bpbm5lclwiPjxkaXYgY2xhc3M9XCJzcGlubmVyXCI+PC9kaXY+PGRpdj5GZXRjaGluZyBkYXRhLi4uPC9kaXY+PC9kaXY+JyxcbiAgICAgICAgZGVmYXVsdE5vRW50cmllc1RlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRyLWRlZmF1bHQtbm8tZGF0YS1kaXNwbGF5XCI+PGRpdj5ObyBtYXRjaGluZyBlbnRyaWVzLi4uPC9kaXY+PC9kaXY+J1xuICAgIH07XG4gICAgZnVuY3Rpb24gd3JhcFdpdGhEZWZhdWx0VGFnV3JhcHBlcihlbnRyeUh0bWwpIHtcbiAgICAgICAgcmV0dXJuICgnPGRpdiBjbGFzcz1cInRyLXRhZ2JveC1kZWZhdWx0LXdyYXBwZXItdGVtcGxhdGVcIj4nICtcbiAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwidHItdGFnYm94LXRhZy1jb250ZW50XCI+IyNlbnRyeUh0bWwjIzwvZGl2PicgK1xuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJ0ci1yZW1vdmUtYnV0dG9uXCI+PC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JykucmVwbGFjZShcIiMjZW50cnlIdG1sIyNcIiwgZW50cnlIdG1sKTtcbiAgICB9XG4gICAgZXhwb3J0cy53cmFwV2l0aERlZmF1bHRUYWdXcmFwcGVyID0gd3JhcFdpdGhEZWZhdWx0VGFnV3JhcHBlcjtcbiAgICBmdW5jdGlvbiBkZWZhdWx0TGlzdFF1ZXJ5RnVuY3Rpb25GYWN0b3J5KGVudHJpZXMsIG1hdGNoaW5nT3B0aW9ucykge1xuICAgICAgICBmdW5jdGlvbiBmaWx0ZXJFbGVtZW50cyhxdWVyeVN0cmluZykge1xuICAgICAgICAgICAgdmFyIHZpc2libGVFbnRyaWVzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgZW50cnkgPSBlbnRyaWVzW2ldO1xuICAgICAgICAgICAgICAgIHZhciAkZW50cnlFbGVtZW50ID0gZW50cnkuX3RyRW50cnlFbGVtZW50O1xuICAgICAgICAgICAgICAgIGlmICghcXVlcnlTdHJpbmcgfHwgdHJpdmlhbE1hdGNoKCRlbnRyeUVsZW1lbnQudGV4dCgpLnRyaW0oKS5yZXBsYWNlKC9cXHN7Mix9L2csICcgJyksIHF1ZXJ5U3RyaW5nLCBtYXRjaGluZ09wdGlvbnMpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmlzaWJsZUVudHJpZXMucHVzaChlbnRyeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZpc2libGVFbnRyaWVzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAocXVlcnlTdHJpbmcsIHJlc3VsdENhbGxiYWNrKSB7XG4gICAgICAgICAgICByZXN1bHRDYWxsYmFjayhmaWx0ZXJFbGVtZW50cyhxdWVyeVN0cmluZykpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBleHBvcnRzLmRlZmF1bHRMaXN0UXVlcnlGdW5jdGlvbkZhY3RvcnkgPSBkZWZhdWx0TGlzdFF1ZXJ5RnVuY3Rpb25GYWN0b3J5O1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVByb3h5KGRlbGVnYXRlKSB7XG4gICAgICAgIHZhciBwcm94eUNvbnN0cnVjdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB9O1xuICAgICAgICBwcm94eUNvbnN0cnVjdG9yLnByb3RvdHlwZSA9IGRlbGVnYXRlO1xuICAgICAgICB2YXIgcHJveHlDb25zdHJ1Y3RvclR5cGVzY3JpcHRIYWNrID0gcHJveHlDb25zdHJ1Y3RvcjtcbiAgICAgICAgcmV0dXJuIG5ldyBwcm94eUNvbnN0cnVjdG9yVHlwZXNjcmlwdEhhY2soKTtcbiAgICB9XG4gICAgZXhwb3J0cy5jcmVhdGVQcm94eSA9IGNyZWF0ZVByb3h5O1xuICAgIGZ1bmN0aW9uIGRlZmF1bHRFbnRyeU1hdGNoaW5nRnVuY3Rpb25GYWN0b3J5KHNlYXJjaGVkUHJvcGVydHlOYW1lcywgbWF0Y2hpbmdPcHRpb25zKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZW50cnksIHF1ZXJ5U3RyaW5nLCBkZXB0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHNlYXJjaGVkUHJvcGVydHlOYW1lc1xuICAgICAgICAgICAgICAgIC5zb21lKGZ1bmN0aW9uIChwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBlbnRyeVtwcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZSAhPSBudWxsICYmIHRyaXZpYWxNYXRjaCh2YWx1ZS50b1N0cmluZygpLCBxdWVyeVN0cmluZywgbWF0Y2hpbmdPcHRpb25zKS5sZW5ndGggPiAwO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGV4cG9ydHMuZGVmYXVsdEVudHJ5TWF0Y2hpbmdGdW5jdGlvbkZhY3RvcnkgPSBkZWZhdWx0RW50cnlNYXRjaGluZ0Z1bmN0aW9uRmFjdG9yeTtcbiAgICBmdW5jdGlvbiBkZWZhdWx0VHJlZVF1ZXJ5RnVuY3Rpb25GYWN0b3J5KHRvcExldmVsRW50cmllcywgZW50cnlNYXRjaGluZ0Z1bmN0aW9uLCBjaGlsZHJlblByb3BlcnR5TmFtZSwgZXhwYW5kZWRQcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgZnVuY3Rpb24gZmluZE1hdGNoaW5nRW50cmllc0FuZFRoZWlyQW5jZXN0b3JzKGVudHJ5LCBxdWVyeVN0cmluZywgbm9kZURlcHRoKSB7XG4gICAgICAgICAgICB2YXIgZW50cnlQcm94eSA9IGNyZWF0ZVByb3h5KGVudHJ5KTtcbiAgICAgICAgICAgIGVudHJ5UHJveHlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdID0gW107XG4gICAgICAgICAgICBlbnRyeVByb3h5W2V4cGFuZGVkUHJvcGVydHlOYW1lXSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGVudHJ5W2NoaWxkcmVuUHJvcGVydHlOYW1lXSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW50cnlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGVudHJ5W2NoaWxkcmVuUHJvcGVydHlOYW1lXVtpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkUHJveHkgPSBmaW5kTWF0Y2hpbmdFbnRyaWVzQW5kVGhlaXJBbmNlc3RvcnMoY2hpbGQsIHF1ZXJ5U3RyaW5nLCBub2RlRGVwdGggKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkUHJveHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5UHJveHlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdLnB1c2goY2hpbGRQcm94eSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbnRyeVByb3h5W2V4cGFuZGVkUHJvcGVydHlOYW1lXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaGFzTWF0Y2hpbmdDaGlsZHJlbiA9IGVudHJ5UHJveHlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICB2YXIgbWF0Y2hlc0l0c2VsZiA9IGVudHJ5TWF0Y2hpbmdGdW5jdGlvbihlbnRyeSwgcXVlcnlTdHJpbmcsIG5vZGVEZXB0aCk7XG4gICAgICAgICAgICBpZiAobWF0Y2hlc0l0c2VsZiAmJiAhaGFzTWF0Y2hpbmdDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIGVudHJ5UHJveHlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdID0gZW50cnlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXNJdHNlbGYgfHwgaGFzTWF0Y2hpbmdDaGlsZHJlbiA/IGVudHJ5UHJveHkgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAocXVlcnlTdHJpbmcsIHJlc3VsdENhbGxiYWNrKSB7XG4gICAgICAgICAgICBpZiAoIXF1ZXJ5U3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0Q2FsbGJhY2sodG9wTGV2ZWxFbnRyaWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaGluZ0VudHJpZXMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRvcExldmVsRW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWxFbnRyeSA9IHRvcExldmVsRW50cmllc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVudHJ5UHJveHkgPSBmaW5kTWF0Y2hpbmdFbnRyaWVzQW5kVGhlaXJBbmNlc3RvcnModG9wTGV2ZWxFbnRyeSwgcXVlcnlTdHJpbmcsIDApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnlQcm94eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hpbmdFbnRyaWVzLnB1c2goZW50cnlQcm94eSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0Q2FsbGJhY2sobWF0Y2hpbmdFbnRyaWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgZXhwb3J0cy5kZWZhdWx0VHJlZVF1ZXJ5RnVuY3Rpb25GYWN0b3J5ID0gZGVmYXVsdFRyZWVRdWVyeUZ1bmN0aW9uRmFjdG9yeTtcbiAgICBmdW5jdGlvbiBjdXN0b21UcmVlUXVlcnlGdW5jdGlvbkZhY3RvcnkodG9wTGV2ZWxFbnRyaWVzLCBjaGlsZHJlblByb3BlcnR5TmFtZSwgZXhwYW5kZWRQcm9wZXJ0eU5hbWUsIGN1c3RvbU5vZGVNYXRjaGluZ0Z1bmN0aW9uKSB7XG4gICAgICAgIGZ1bmN0aW9uIGZpbmRNYXRjaGluZ0VudHJpZXNBbmRUaGVpckFuY2VzdG9ycyhlbnRyeSwgcXVlcnlTdHJpbmcsIG5vZGVEZXB0aCkge1xuICAgICAgICAgICAgdmFyIGVudHJ5UHJveHkgPSBjcmVhdGVQcm94eShlbnRyeSk7XG4gICAgICAgICAgICBlbnRyeVByb3h5W2NoaWxkcmVuUHJvcGVydHlOYW1lXSA9IFtdO1xuICAgICAgICAgICAgZW50cnlQcm94eVtleHBhbmRlZFByb3BlcnR5TmFtZV0gPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChlbnRyeVtjaGlsZHJlblByb3BlcnR5TmFtZV0pIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVudHJ5W2NoaWxkcmVuUHJvcGVydHlOYW1lXS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBlbnRyeVtjaGlsZHJlblByb3BlcnR5TmFtZV1baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZFByb3h5ID0gZmluZE1hdGNoaW5nRW50cmllc0FuZFRoZWlyQW5jZXN0b3JzKGNoaWxkLCBxdWVyeVN0cmluZywgbm9kZURlcHRoICsgMSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZFByb3h5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbnRyeVByb3h5W2NoaWxkcmVuUHJvcGVydHlOYW1lXS5wdXNoKGNoaWxkUHJveHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZW50cnlQcm94eVtleHBhbmRlZFByb3BlcnR5TmFtZV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGhhc01hdGNoaW5nQ2hpbGRyZW4gPSBlbnRyeVByb3h5W2NoaWxkcmVuUHJvcGVydHlOYW1lXS5sZW5ndGggPiAwO1xuICAgICAgICAgICAgdmFyIG1hdGNoZXNJdHNlbGYgPSBjdXN0b21Ob2RlTWF0Y2hpbmdGdW5jdGlvbihlbnRyeSwgcXVlcnlTdHJpbmcsIG5vZGVEZXB0aCk7XG4gICAgICAgICAgICBpZiAobWF0Y2hlc0l0c2VsZiAmJiAhaGFzTWF0Y2hpbmdDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIGVudHJ5UHJveHlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdID0gZW50cnlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXNJdHNlbGYgfHwgaGFzTWF0Y2hpbmdDaGlsZHJlbiA/IGVudHJ5UHJveHkgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAocXVlcnlTdHJpbmcsIHJlc3VsdENhbGxiYWNrKSB7XG4gICAgICAgICAgICBpZiAoIXF1ZXJ5U3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0Q2FsbGJhY2sodG9wTGV2ZWxFbnRyaWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaGluZ0VudHJpZXMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRvcExldmVsRW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWxFbnRyeSA9IHRvcExldmVsRW50cmllc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVudHJ5UHJveHkgPSBmaW5kTWF0Y2hpbmdFbnRyaWVzQW5kVGhlaXJBbmNlc3RvcnModG9wTGV2ZWxFbnRyeSwgcXVlcnlTdHJpbmcsIDApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnlQcm94eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hpbmdFbnRyaWVzLnB1c2goZW50cnlQcm94eSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0Q2FsbGJhY2sobWF0Y2hpbmdFbnRyaWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgZXhwb3J0cy5jdXN0b21UcmVlUXVlcnlGdW5jdGlvbkZhY3RvcnkgPSBjdXN0b21UcmVlUXVlcnlGdW5jdGlvbkZhY3Rvcnk7XG4gICAgZnVuY3Rpb24gc2VsZWN0RWxlbWVudENvbnRlbnRzKGRvbUVsZW1lbnQsIHN0YXJ0LCBlbmQpIHtcbiAgICAgICAgZG9tRWxlbWVudCA9IGRvbUVsZW1lbnQuZmlyc3RDaGlsZCB8fCBkb21FbGVtZW50O1xuICAgICAgICBlbmQgPSBlbmQgfHwgc3RhcnQ7XG4gICAgICAgIHZhciByYW5nZSA9IGRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XG4gICAgICAgIHJhbmdlLnNldFN0YXJ0KGRvbUVsZW1lbnQsIHN0YXJ0KTtcbiAgICAgICAgcmFuZ2Uuc2V0RW5kKGRvbUVsZW1lbnQsIGVuZCk7XG4gICAgICAgIHZhciBzZWwgPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzZWwucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgfVxuICAgICAgICBzZWwuYWRkUmFuZ2UocmFuZ2UpO1xuICAgIH1cbiAgICBleHBvcnRzLnNlbGVjdEVsZW1lbnRDb250ZW50cyA9IHNlbGVjdEVsZW1lbnRDb250ZW50cztcbiAgICBleHBvcnRzLmVzY2FwZVNwZWNpYWxSZWdleENoYXJhY3RlciA9IGZ1bmN0aW9uIChzKSB7XG4gICAgICAgIHJldHVybiBzLnJlcGxhY2UoL1stW1xcXXt9KCkqKz8uLFxcXFxeJHwjXFxzXS9nLCBcIlxcXFwkJlwiKTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIG9iamVjdEVxdWFscyh4LCB5KSB7XG4gICAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgICAgaWYgKHggPT09IG51bGwgfHwgeCA9PT0gdW5kZWZpbmVkIHx8IHkgPT09IG51bGwgfHwgeSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4geCA9PT0geTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeC5jb25zdHJ1Y3RvciAhPT0geS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh4IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgICAgICAgIHJldHVybiB4ID09PSB5O1xuICAgICAgICB9XG4gICAgICAgIGlmICh4IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXR1cm4geCA9PT0geTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeCA9PT0geSB8fCB4LnZhbHVlT2YoKSA9PT0geS52YWx1ZU9mKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHgpICYmIHgubGVuZ3RoICE9PSB5Lmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh4IGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghKHggaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEoeSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcCA9IE9iamVjdC5rZXlzKHgpO1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoeSkuZXZlcnkoZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgIHJldHVybiBwLmluZGV4T2YoaSkgIT09IC0xO1xuICAgICAgICB9KSAmJlxuICAgICAgICAgICAgcC5ldmVyeShmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3RFcXVhbHMoeFtpXSwgeVtpXSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG4gICAgZXhwb3J0cy5vYmplY3RFcXVhbHMgPSBvYmplY3RFcXVhbHM7XG4gICAgZnVuY3Rpb24gdHJpdmlhbE1hdGNoKHRleHQsIHNlYXJjaFN0cmluZywgb3B0aW9ucykge1xuICAgICAgICBpZiAoIXNlYXJjaFN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIFt7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiAwLFxuICAgICAgICAgICAgICAgICAgICBsZW5ndGg6IHRleHQubGVuZ3RoXG4gICAgICAgICAgICAgICAgfV07XG4gICAgICAgIH1cbiAgICAgICAgb3B0aW9ucyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgIG1hdGNoaW5nTW9kZTogJ2NvbnRhaW5zJyxcbiAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICBtYXhMZXZlbnNodGVpbkRpc3RhbmNlOiAzXG4gICAgICAgIH0sIG9wdGlvbnMgfHwgbnVsbCk7XG4gICAgICAgIGlmIChvcHRpb25zLmlnbm9yZUNhc2UpIHtcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICBzZWFyY2hTdHJpbmcgPSBzZWFyY2hTdHJpbmcudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBmaW5kUmVnZXhNYXRjaGVzKHJlZ2V4KSB7XG4gICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IFtdO1xuICAgICAgICAgICAgdmFyIG1hdGNoO1xuICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gcmVnZXguZXhlYyh0ZXh0KSkge1xuICAgICAgICAgICAgICAgIG1hdGNoZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBtYXRjaC5pbmRleCxcbiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoOiBtYXRjaFswXS5sZW5ndGhcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXRjaGVzO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGZpbmRMZXZlbnNodGVpbk1hdGNoZXModGV4dCwgc2VhcmNoU3RyaW5nKSB7XG4gICAgICAgICAgICB2YXIgbGV2ZW5zaHRlaW4gPSBuZXcgTGV2ZW5zaHRlaW4odGV4dCwgc2VhcmNoU3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChsZXZlbnNodGVpbi5kaXN0YW5jZSA8PSBvcHRpb25zLm1heExldmVuc2h0ZWluRGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0OiAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoOiBzZWFyY2hTdHJpbmcubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGFuY2U6IGxldmVuc2h0ZWluLmRpc3RhbmNlXG4gICAgICAgICAgICAgICAgICAgIH1dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLm1hdGNoaW5nTW9kZSA9PSAnY29udGFpbnMnKSB7XG4gICAgICAgICAgICBzZWFyY2hTdHJpbmcgPSBzZWFyY2hTdHJpbmcucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csIFwiXFxcXCQmXCIpO1xuICAgICAgICAgICAgcmV0dXJuIGZpbmRSZWdleE1hdGNoZXMobmV3IFJlZ0V4cChzZWFyY2hTdHJpbmcsIFwiZ1wiKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3B0aW9ucy5tYXRjaGluZ01vZGUgPT0gJ3ByZWZpeCcpIHtcbiAgICAgICAgICAgIHNlYXJjaFN0cmluZyA9IHNlYXJjaFN0cmluZy5yZXBsYWNlKC9bLVtcXF17fSgpKis/LixcXFxcXiR8I1xcc10vZywgXCJcXFxcJCZcIik7XG4gICAgICAgICAgICByZXR1cm4gZmluZFJlZ2V4TWF0Y2hlcyhuZXcgUmVnRXhwKCdeJyArIHNlYXJjaFN0cmluZywgXCJnXCIpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcHRpb25zLm1hdGNoaW5nTW9kZSA9PSAncHJlZml4LXdvcmQnKSB7XG4gICAgICAgICAgICBzZWFyY2hTdHJpbmcgPSBzZWFyY2hTdHJpbmcucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csIFwiXFxcXCQmXCIpO1xuICAgICAgICAgICAgaWYgKHNlYXJjaFN0cmluZy5jaGFyQXQoMCkubWF0Y2goL15cXHcvKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmaW5kUmVnZXhNYXRjaGVzKG5ldyBSZWdFeHAoJ1xcXFxiJyArIHNlYXJjaFN0cmluZywgXCJnXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBmaW5kUmVnZXhNYXRjaGVzKG5ldyBSZWdFeHAoc2VhcmNoU3RyaW5nLCBcImdcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9wdGlvbnMubWF0Y2hpbmdNb2RlID09ICdwcmVmaXgtbGV2ZW5zaHRlaW4nKSB7XG4gICAgICAgICAgICByZXR1cm4gZmluZExldmVuc2h0ZWluTWF0Y2hlcyh0ZXh0LnN1YnN0cigwLCBNYXRoLm1pbihzZWFyY2hTdHJpbmcubGVuZ3RoLCB0ZXh0Lmxlbmd0aCkpLCBzZWFyY2hTdHJpbmcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9wdGlvbnMubWF0Y2hpbmdNb2RlID09ICdsZXZlbnNodGVpbicpIHtcbiAgICAgICAgICAgIHJldHVybiBmaW5kTGV2ZW5zaHRlaW5NYXRjaGVzKHRleHQsIHNlYXJjaFN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBcInVua25vd24gbWF0Y2hpbmdNb2RlOiBcIiArIG9wdGlvbnMubWF0Y2hpbmdNb2RlO1xuICAgICAgICB9XG4gICAgfVxuICAgIGV4cG9ydHMudHJpdmlhbE1hdGNoID0gdHJpdmlhbE1hdGNoO1xuICAgIGZ1bmN0aW9uIG1pbmltYWxseVNjcm9sbFRvKGVsZW1lbnQsIHRhcmdldCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9ICQodGFyZ2V0KTtcbiAgICAgICAgJChlbGVtZW50KS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XG4gICAgICAgICAgICB2YXIgdmlld1BvcnRNaW5ZID0gJHRoaXMuc2Nyb2xsVG9wKCk7XG4gICAgICAgICAgICB2YXIgdmlld1BvcnRNYXhZID0gdmlld1BvcnRNaW5ZICsgJHRoaXMuaW5uZXJIZWlnaHQoKTtcbiAgICAgICAgICAgIHZhciB0YXJnZXRNaW5ZID0gJCgkdGFyZ2V0KS5vZmZzZXQoKS50b3AgLSAkKHRoaXMpLm9mZnNldCgpLnRvcCArICR0aGlzLnNjcm9sbFRvcCgpO1xuICAgICAgICAgICAgdmFyIHRhcmdldE1heFkgPSB0YXJnZXRNaW5ZICsgJHRhcmdldC5oZWlnaHQoKTtcbiAgICAgICAgICAgIGlmICh0YXJnZXRNaW5ZIDwgdmlld1BvcnRNaW5ZKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2Nyb2xsVG9wKHRhcmdldE1pblkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGFyZ2V0TWF4WSA+IHZpZXdQb3J0TWF4WSkge1xuICAgICAgICAgICAgICAgICR0aGlzLnNjcm9sbFRvcChNYXRoLm1pbih0YXJnZXRNaW5ZLCB0YXJnZXRNYXhZIC0gJHRoaXMuaW5uZXJIZWlnaHQoKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHZpZXdQb3J0TWluWCA9ICR0aGlzLnNjcm9sbExlZnQoKTtcbiAgICAgICAgICAgIHZhciB2aWV3UG9ydE1heFggPSB2aWV3UG9ydE1pblggKyAkdGhpcy5pbm5lcldpZHRoKCk7XG4gICAgICAgICAgICB2YXIgdGFyZ2V0TWluWCA9ICQoJHRhcmdldCkub2Zmc2V0KCkubGVmdCAtICQodGhpcykub2Zmc2V0KCkubGVmdCArICR0aGlzLnNjcm9sbExlZnQoKTtcbiAgICAgICAgICAgIHZhciB0YXJnZXRNYXhYID0gdGFyZ2V0TWluWCArICR0YXJnZXQud2lkdGgoKTtcbiAgICAgICAgICAgIGlmICh0YXJnZXRNaW5YIDwgdmlld1BvcnRNaW5YKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2Nyb2xsTGVmdCh0YXJnZXRNaW5YKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRhcmdldE1heFggPiB2aWV3UG9ydE1heFgpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5zY3JvbGxMZWZ0KE1hdGgubWluKHRhcmdldE1pblgsIHRhcmdldE1heFggLSAkdGhpcy5pbm5lcldpZHRoKCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGV4cG9ydHMubWluaW1hbGx5U2Nyb2xsVG8gPSBtaW5pbWFsbHlTY3JvbGxUbztcbiAgICBmdW5jdGlvbiBzZXRUaW1lb3V0T3JEb0ltbWVkaWF0ZWx5KGYsIGRlbGF5KSB7XG4gICAgICAgIGlmIChkZWxheSAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LnNldFRpbWVvdXQoZigpLCBkZWxheSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdm9pZCBmKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZXhwb3J0cy5zZXRUaW1lb3V0T3JEb0ltbWVkaWF0ZWx5ID0gc2V0VGltZW91dE9yRG9JbW1lZGlhdGVseTtcbn0pO1xuXG5cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwianF1ZXJ5XCIsIFwibW9tZW50XCIsIFwiLi9Ucml2aWFsRXZlbnRcIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcbiAgICB2YXIgbW9tZW50ID0gcmVxdWlyZShcIm1vbWVudFwiKTtcbiAgICB2YXIgVHJpdmlhbEV2ZW50XzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsRXZlbnRcIik7XG4gICAgdmFyIFdlZWtEYXk7XG4gICAgKGZ1bmN0aW9uIChXZWVrRGF5KSB7XG4gICAgICAgIFdlZWtEYXlbV2Vla0RheVtcIk1PTkRBWVwiXSA9IDFdID0gXCJNT05EQVlcIjtcbiAgICAgICAgV2Vla0RheVtXZWVrRGF5W1wiVFVFU0RBWVwiXSA9IDJdID0gXCJUVUVTREFZXCI7XG4gICAgICAgIFdlZWtEYXlbV2Vla0RheVtcIldFRE5FU0RBWVwiXSA9IDNdID0gXCJXRURORVNEQVlcIjtcbiAgICAgICAgV2Vla0RheVtXZWVrRGF5W1wiVEhVUlNEQVlcIl0gPSA0XSA9IFwiVEhVUlNEQVlcIjtcbiAgICAgICAgV2Vla0RheVtXZWVrRGF5W1wiRlJJREFZXCJdID0gNV0gPSBcIkZSSURBWVwiO1xuICAgICAgICBXZWVrRGF5W1dlZWtEYXlbXCJTQVRVUkRBWVwiXSA9IDZdID0gXCJTQVRVUkRBWVwiO1xuICAgICAgICBXZWVrRGF5W1dlZWtEYXlbXCJTVU5EQVlcIl0gPSA3XSA9IFwiU1VOREFZXCI7XG4gICAgfSkoV2Vla0RheSA9IGV4cG9ydHMuV2Vla0RheSB8fCAoZXhwb3J0cy5XZWVrRGF5ID0ge30pKTtcbiAgICB2YXIgVHJpdmlhbENhbGVuZGFyQm94ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gVHJpdmlhbENhbGVuZGFyQm94KCRjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgICAgICB0aGlzLiRjb250YWluZXIgPSAkY29udGFpbmVyO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9uT25FZGl0aW5nVGltZVVuaXRDaGFuZ2UgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5jb25maWcgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWREYXRlOiBtb21lbnQoKSxcbiAgICAgICAgICAgICAgICBmaXJzdERheU9mV2VlazogV2Vla0RheS5NT05EQVksXG4gICAgICAgICAgICAgICAgbW9kZTogJ2RhdGV0aW1lJyxcbiAgICAgICAgICAgICAgICBoaWdobGlnaHRLZXlib2FyZE5hdmlnYXRpb25TdGF0ZTogZmFsc2VcbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5rZXlib2FyZE5hdmlnYXRpb25TdGF0ZSA9IHRoaXMuY29uZmlnLm1vZGUgPT0gJ3RpbWUnID8gJ2hvdXInIDogJ2RheSc7XG4gICAgICAgICAgICB0aGlzLmtleWJvYXJkTmF2Q3NzQ2xhc3MgPSB0aGlzLmNvbmZpZy5oaWdobGlnaHRLZXlib2FyZE5hdmlnYXRpb25TdGF0ZSA/IFwia2V5Ym9hcmQtbmF2XCIgOiBcIlwiO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGUgPSB0aGlzLmNvbmZpZy5zZWxlY3RlZERhdGU7XG4gICAgICAgICAgICB0aGlzLiRjYWxlbmRhckJveCA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1jYWxlbmRhcmJveFwiLz4nKS5hcHBlbmRUbyh0aGlzLiRjb250YWluZXIpO1xuICAgICAgICAgICAgdGhpcy4kY2FsZW5kYXJEaXNwbGF5ID0gJCgnPGRpdiBjbGFzcz1cInRyLWNhbGVuZGFyLWRpc3BsYXlcIi8+Jyk7XG4gICAgICAgICAgICB0aGlzLiR5ZWFyRGlzcGxheSA9ICQoJzxkaXYgY2xhc3M9XCJ5ZWFyXCI+PHNwYW4gY2xhc3M9XCJiYWNrLWJ1dHRvblwiLz48c3BhbiBjbGFzcz1cIm5hbWVcIi8+PHNwYW4gY2xhc3M9XCJmb3J3YXJkLWJ1dHRvblwiLz48L2Rpdj4nKS5hcHBlbmRUbyh0aGlzLiRjYWxlbmRhckRpc3BsYXkpO1xuICAgICAgICAgICAgdGhpcy4kbW9udGhEaXNwbGF5ID0gJCgnPGRpdiBjbGFzcz1cIm1vbnRoXCI+PHNwYW4gY2xhc3M9XCJiYWNrLWJ1dHRvblwiLz48c3BhbiBjbGFzcz1cIm5hbWVcIi8+PHNwYW4gY2xhc3M9XCJmb3J3YXJkLWJ1dHRvblwiLz48L2Rpdj4nKS5hcHBlbmRUbyh0aGlzLiRjYWxlbmRhckRpc3BsYXkpO1xuICAgICAgICAgICAgdGhpcy4kbW9udGhUYWJsZSA9ICQoJzxkaXYgY2xhc3M9XCJtb250aC10YWJsZVwiPicpLmFwcGVuZFRvKHRoaXMuJGNhbGVuZGFyRGlzcGxheSk7XG4gICAgICAgICAgICB0aGlzLiR5ZWFyID0gdGhpcy4keWVhckRpc3BsYXkuZmluZChcIi5uYW1lXCIpO1xuICAgICAgICAgICAgdGhpcy4kbW9udGggPSB0aGlzLiRtb250aERpc3BsYXkuZmluZChcIi5uYW1lXCIpO1xuICAgICAgICAgICAgdGhpcy4keWVhckRpc3BsYXkuY2xpY2sodGhpcy5zZXRLZXlib2FyZE5hdmlnYXRpb25TdGF0ZS5iaW5kKHRoaXMsIFwieWVhclwiKSk7XG4gICAgICAgICAgICB0aGlzLiR5ZWFyRGlzcGxheS5maW5kKCcuYmFjay1idXR0b24nKS5jbGljayh0aGlzLm5hdmlnYXRlQnlVbml0LmJpbmQodGhpcywgXCJ5ZWFyXCIsIFwibGVmdFwiLCB0cnVlKSk7XG4gICAgICAgICAgICB0aGlzLiR5ZWFyRGlzcGxheS5maW5kKCcuZm9yd2FyZC1idXR0b24nKS5jbGljayh0aGlzLm5hdmlnYXRlQnlVbml0LmJpbmQodGhpcywgXCJ5ZWFyXCIsIFwicmlnaHRcIiwgdHJ1ZSkpO1xuICAgICAgICAgICAgdGhpcy4kbW9udGhEaXNwbGF5LmNsaWNrKHRoaXMuc2V0S2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUuYmluZCh0aGlzLCBcIm1vbnRoXCIpKTtcbiAgICAgICAgICAgIHRoaXMuJG1vbnRoRGlzcGxheS5maW5kKCcuYmFjay1idXR0b24nKS5jbGljayh0aGlzLm5hdmlnYXRlQnlVbml0LmJpbmQodGhpcywgXCJtb250aFwiLCBcImxlZnRcIiwgdHJ1ZSkpO1xuICAgICAgICAgICAgdGhpcy4kbW9udGhEaXNwbGF5LmZpbmQoJy5mb3J3YXJkLWJ1dHRvbicpLmNsaWNrKHRoaXMubmF2aWdhdGVCeVVuaXQuYmluZCh0aGlzLCBcIm1vbnRoXCIsIFwicmlnaHRcIiwgdHJ1ZSkpO1xuICAgICAgICAgICAgdGhpcy4kY2xvY2tEaXNwbGF5ID0gJCgnPGRpdiBjbGFzcz1cInRyLWNsb2NrLWRpc3BsYXlcIi8+JylcbiAgICAgICAgICAgICAgICAuYXBwZW5kKCc8c3ZnIGNsYXNzPVwiY2xvY2tcIiB2aWV3Qm94PVwiMCAwIDEwMCAxMDBcIiB3aWR0aD1cIjEwMFwiIGhlaWdodD1cIjEwMFwiPiAnICtcbiAgICAgICAgICAgICAgICAnPGNpcmNsZSBjbGFzcz1cImNsb2NrY2lyY2xlXCIgY3g9XCI1MFwiIGN5PVwiNTBcIiByPVwiNDVcIi8+ICcgK1xuICAgICAgICAgICAgICAgICc8ZyBjbGFzcz1cInRpY2tzXCIgPiAnICtcbiAgICAgICAgICAgICAgICAnIDxsaW5lIHgxPVwiNTBcIiB5MT1cIjUuMDAwXCIgeDI9XCI1MC4wMFwiIHkyPVwiMTAuMDBcIi8+IDxsaW5lIHgxPVwiNzIuNTBcIiB5MT1cIjExLjAzXCIgeDI9XCI3MC4wMFwiIHkyPVwiMTUuMzZcIi8+IDxsaW5lIHgxPVwiODguOTdcIiB5MT1cIjI3LjUwXCIgeDI9XCI4NC42NFwiIHkyPVwiMzAuMDBcIi8+IDxsaW5lIHgxPVwiOTUuMDBcIiB5MT1cIjUwLjAwXCIgeDI9XCI5MC4wMFwiIHkyPVwiNTAuMDBcIi8+IDxsaW5lIHgxPVwiODguOTdcIiB5MT1cIjcyLjUwXCIgeDI9XCI4NC42NFwiIHkyPVwiNzAuMDBcIi8+IDxsaW5lIHgxPVwiNzIuNTBcIiB5MT1cIjg4Ljk3XCIgeDI9XCI3MC4wMFwiIHkyPVwiODQuNjRcIi8+IDxsaW5lIHgxPVwiNTAuMDBcIiB5MT1cIjk1LjAwXCIgeDI9XCI1MC4wMFwiIHkyPVwiOTAuMDBcIi8+IDxsaW5lIHgxPVwiMjcuNTBcIiB5MT1cIjg4Ljk3XCIgeDI9XCIzMC4wMFwiIHkyPVwiODQuNjRcIi8+IDxsaW5lIHgxPVwiMTEuMDNcIiB5MT1cIjcyLjUwXCIgeDI9XCIxNS4zNlwiIHkyPVwiNzAuMDBcIi8+IDxsaW5lIHgxPVwiNS4wMDBcIiB5MT1cIjUwLjAwXCIgeDI9XCIxMC4wMFwiIHkyPVwiNTAuMDBcIi8+IDxsaW5lIHgxPVwiMTEuMDNcIiB5MT1cIjI3LjUwXCIgeDI9XCIxNS4zNlwiIHkyPVwiMzAuMDBcIi8+IDxsaW5lIHgxPVwiMjcuNTBcIiB5MT1cIjExLjAzXCIgeDI9XCIzMC4wMFwiIHkyPVwiMTUuMzZcIi8+ICcgK1xuICAgICAgICAgICAgICAgICc8L2c+ICcgK1xuICAgICAgICAgICAgICAgICc8ZyBjbGFzcz1cIm51bWJlcnNcIj4nICtcbiAgICAgICAgICAgICAgICAnIDx0ZXh0IHg9XCI1MFwiIHk9XCIyMlwiPjEyPC90ZXh0PiA8dGV4dCB4PVwiODVcIiB5PVwiNTVcIj4zPC90ZXh0PiA8dGV4dCB4PVwiNTBcIiB5PVwiODhcIj42PC90ZXh0PiA8dGV4dCB4PVwiMTVcIiB5PVwiNTVcIj45PC90ZXh0PiAnICtcbiAgICAgICAgICAgICAgICAnPC9nPiAnICtcbiAgICAgICAgICAgICAgICAnPGcgY2xhc3M9XCJoYW5kc1wiPicgK1xuICAgICAgICAgICAgICAgICcgPGxpbmUgY2xhc3M9XCJtaW51dGVoYW5kXCIgeDE9XCI1MFwiIHkxPVwiNTBcIiB4Mj1cIjUwXCIgeTI9XCIyMFwiLz4nICtcbiAgICAgICAgICAgICAgICAnIDxsaW5lIGNsYXNzPVwiaG91cmhhbmRcIiB4MT1cIjUwXCIgeTE9XCI1MFwiIHgyPVwiNTBcIiB5Mj1cIjI2XCIvPiAnICtcbiAgICAgICAgICAgICAgICAnPC9nPiAnICtcbiAgICAgICAgICAgICAgICAnPGcgY2xhc3M9XCJhbS1wbS1ib3hcIj4nICtcbiAgICAgICAgICAgICAgICAnIDxyZWN0IHg9XCI1OFwiIHk9XCI1OVwiIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIxNVwiLz4nICtcbiAgICAgICAgICAgICAgICAnIDx0ZXh0IGNsYXNzPVwiYW0tcG0tdGV4dFwiIHg9XCI2MFwiIHk9XCI3MFwiID4/PzwvdGV4dD4nICtcbiAgICAgICAgICAgICAgICAnPC9nPicgK1xuICAgICAgICAgICAgICAgICc8L3N2Zz4nKS5hcHBlbmQoJzxkaXYgY2xhc3M9XCJkaWdpdGFsLXRpbWUtZGlzcGxheVwiPjxkaXYgY2xhc3M9XCJob3VyLXdyYXBwZXJcIj4nICtcbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cInVwLWJ1dHRvblwiLz48ZGl2IGNsYXNzPVwiaG91clwiPj8/PC9kaXY+PGRpdiBjbGFzcz1cImRvd24tYnV0dG9uXCIvPicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj46PGRpdiBjbGFzcz1cIm1pbnV0ZS13cmFwcGVyXCI+JyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJ1cC1idXR0b25cIi8+PGRpdiBjbGFzcz1cIm1pbnV0ZVwiPj8/PC9kaXY+PGRpdiBjbGFzcz1cImRvd24tYnV0dG9uXCIvPicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj48L2Rpdj4nKTtcbiAgICAgICAgICAgIHRoaXMuJGhvdXJIYW5kID0gdGhpcy4kY2xvY2tEaXNwbGF5LmZpbmQoJy5ob3VyaGFuZCcpO1xuICAgICAgICAgICAgdGhpcy4kbWludXRlSGFuZCA9IHRoaXMuJGNsb2NrRGlzcGxheS5maW5kKCcubWludXRlaGFuZCcpO1xuICAgICAgICAgICAgdGhpcy4kYW1QbVRleHQgPSB0aGlzLiRjbG9ja0Rpc3BsYXkuZmluZCgnLmFtLXBtLXRleHQnKTtcbiAgICAgICAgICAgIHRoaXMuJGRpZ2l0YWxUaW1lSG91ckRpc3BsYXlXcmFwcGVyID0gdGhpcy4kY2xvY2tEaXNwbGF5LmZpbmQoJy5kaWdpdGFsLXRpbWUtZGlzcGxheSAuaG91ci13cmFwcGVyJyk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZUhvdXJEaXNwbGF5ID0gdGhpcy4kY2xvY2tEaXNwbGF5LmZpbmQoJy5kaWdpdGFsLXRpbWUtZGlzcGxheSAuaG91cicpO1xuICAgICAgICAgICAgdGhpcy4kZGlnaXRhbFRpbWVIb3VyRGlzcGxheVdyYXBwZXIuY2xpY2sodGhpcy5zZXRLZXlib2FyZE5hdmlnYXRpb25TdGF0ZS5iaW5kKHRoaXMsIFwiaG91clwiKSk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZUhvdXJEaXNwbGF5V3JhcHBlci5maW5kKFwiLnVwLWJ1dHRvblwiKS5jbGljayh0aGlzLm5hdmlnYXRlQnlVbml0LmJpbmQodGhpcywgXCJob3VyXCIsIFwidXBcIiwgdHJ1ZSkpO1xuICAgICAgICAgICAgdGhpcy4kZGlnaXRhbFRpbWVIb3VyRGlzcGxheVdyYXBwZXIuZmluZChcIi5kb3duLWJ1dHRvblwiKS5jbGljayh0aGlzLm5hdmlnYXRlQnlVbml0LmJpbmQodGhpcywgXCJob3VyXCIsIFwiZG93blwiLCB0cnVlKSk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZU1pbnV0ZURpc3BsYXlXcmFwcGVyID0gdGhpcy4kY2xvY2tEaXNwbGF5LmZpbmQoJy5kaWdpdGFsLXRpbWUtZGlzcGxheSAubWludXRlLXdyYXBwZXInKTtcbiAgICAgICAgICAgIHRoaXMuJGRpZ2l0YWxUaW1lTWludXRlRGlzcGxheSA9IHRoaXMuJGNsb2NrRGlzcGxheS5maW5kKCcuZGlnaXRhbC10aW1lLWRpc3BsYXkgLm1pbnV0ZScpO1xuICAgICAgICAgICAgdGhpcy4kZGlnaXRhbFRpbWVNaW51dGVEaXNwbGF5V3JhcHBlci5jbGljayh0aGlzLnNldEtleWJvYXJkTmF2aWdhdGlvblN0YXRlLmJpbmQodGhpcywgXCJtaW51dGVcIikpO1xuICAgICAgICAgICAgdGhpcy4kZGlnaXRhbFRpbWVNaW51dGVEaXNwbGF5V3JhcHBlci5maW5kKFwiLnVwLWJ1dHRvblwiKS5jbGljayh0aGlzLm5hdmlnYXRlQnlVbml0LmJpbmQodGhpcywgXCJtaW51dGVcIiwgXCJ1cFwiLCB0cnVlKSk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZU1pbnV0ZURpc3BsYXlXcmFwcGVyLmZpbmQoXCIuZG93bi1idXR0b25cIikuY2xpY2sodGhpcy5uYXZpZ2F0ZUJ5VW5pdC5iaW5kKHRoaXMsIFwibWludXRlXCIsIFwiZG93blwiLCB0cnVlKSk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcubW9kZSA9PSAnZGF0ZScgfHwgdGhpcy5jb25maWcubW9kZSA9PSAnZGF0ZXRpbWUnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2FsZW5kYXJEaXNwbGF5LmFwcGVuZFRvKHRoaXMuJGNhbGVuZGFyQm94KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5tb2RlID09ICd0aW1lJyB8fCB0aGlzLmNvbmZpZy5tb2RlID09PSAnZGF0ZXRpbWUnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2xvY2tEaXNwbGF5LmFwcGVuZFRvKHRoaXMuJGNhbGVuZGFyQm94KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkRGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTW9udGhEaXNwbGF5KHRoaXMuc2VsZWN0ZWREYXRlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUNsb2NrRGlzcGxheSh0aGlzLnNlbGVjdGVkRGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZU1vbnRoRGlzcGxheShtb21lbnQoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVDbG9ja0Rpc3BsYXkobW9tZW50KCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5nZXREYXlzRm9yQ2FsZW5kYXJEaXNwbGF5ID0gZnVuY3Rpb24gKGRhdGVJbk1vbnRoRG9CZURpc3BsYXllZCwgZmlyc3REYXlPZldlZWspIHtcbiAgICAgICAgICAgIHZhciBmaXJzdERheU9mTW9udGggPSBkYXRlSW5Nb250aERvQmVEaXNwbGF5ZWQuY2xvbmUoKS51dGMoKS5zdGFydE9mKCdtb250aCcpLmhvdXIoMTIpO1xuICAgICAgICAgICAgdmFyIGZpcnN0RGF5VG9CZURpc3BsYXllZCA9IGZpcnN0RGF5T2ZNb250aC5jbG9uZSgpLmlzb1dlZWtkYXkoZmlyc3REYXlPZldlZWsgPD0gZmlyc3REYXlPZk1vbnRoLmlzb1dlZWtkYXkoKSA/IGZpcnN0RGF5T2ZXZWVrIDogZmlyc3REYXlPZldlZWsgLSA3KTtcbiAgICAgICAgICAgIHZhciBkYXlzT2ZNb250aCA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgZGF5ID0gZmlyc3REYXlUb0JlRGlzcGxheWVkLmNsb25lKCk7IGRheXNPZk1vbnRoLmxlbmd0aCA8IDQyOyBkYXkuYWRkKDEsICdkYXknKSkge1xuICAgICAgICAgICAgICAgIGRheXNPZk1vbnRoLnB1c2goZGF5LmNsb25lKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGRheXNPZk1vbnRoO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnVwZGF0ZU1vbnRoRGlzcGxheSA9IGZ1bmN0aW9uIChkYXRlSW5Nb250aFRvQmVEaXNwbGF5ZWQpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLiR5ZWFyLnRleHQoZGF0ZUluTW9udGhUb0JlRGlzcGxheWVkLnllYXIoKSk7XG4gICAgICAgICAgICB0aGlzLiRtb250aC50ZXh0KG1vbWVudC5tb250aHMoKVtkYXRlSW5Nb250aFRvQmVEaXNwbGF5ZWQubW9udGgoKV0pO1xuICAgICAgICAgICAgdGhpcy4kbW9udGhUYWJsZS5yZW1vdmUoKTtcbiAgICAgICAgICAgIHRoaXMuJG1vbnRoVGFibGUgPSAkKCc8ZGl2IGNsYXNzPVwibW9udGgtdGFibGVcIj4nKS5hcHBlbmRUbyh0aGlzLiRjYWxlbmRhckRpc3BsYXkpO1xuICAgICAgICAgICAgdmFyIGRheXNUb0JlRGlzcGxheWVkID0gVHJpdmlhbENhbGVuZGFyQm94LmdldERheXNGb3JDYWxlbmRhckRpc3BsYXkoZGF0ZUluTW9udGhUb0JlRGlzcGxheWVkLCAxKTtcbiAgICAgICAgICAgIHZhciAkdHIgPSAkKCc8dHI+JykuYXBwZW5kVG8odGhpcy4kbW9udGhUYWJsZSk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDc7IGkrKykge1xuICAgICAgICAgICAgICAgICR0ci5hcHBlbmQoJzx0aD4nICsgbW9tZW50LndlZWtkYXlzTWluKClbKHRoaXMuY29uZmlnLmZpcnN0RGF5T2ZXZWVrICsgaSkgJSA3XSArICc8L3RoPicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgdyA9IDA7IHcgPCBkYXlzVG9CZURpc3BsYXllZC5sZW5ndGggLyA3OyB3KyspIHtcbiAgICAgICAgICAgICAgICAkdHIgPSAkKCc8dHI+JykuYXBwZW5kVG8odGhpcy4kbW9udGhUYWJsZSk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgZCA9IDA7IGQgPCA3OyBkKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRheSA9IGRheXNUb0JlRGlzcGxheWVkW3cgKiA3ICsgZF07XG4gICAgICAgICAgICAgICAgICAgIHZhciAkdGQgPSAkKCc8dGQ+JyArIGRheS5kYXRlKCkgKyAnPC90ZD4nKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRheS5tb250aCgpID09IGRhdGVJbk1vbnRoVG9CZURpc3BsYXllZC5tb250aCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGQuYWRkQ2xhc3MoJ2N1cnJlbnQtbW9udGgnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0ZC5hZGRDbGFzcygnb3RoZXItbW9udGgnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF5LnllYXIoKSA9PSBtb21lbnQoKS55ZWFyKCkgJiYgZGF5LmRheU9mWWVhcigpID09IG1vbWVudCgpLmRheU9mWWVhcigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGQuYWRkQ2xhc3MoJ3RvZGF5Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRheS55ZWFyKCkgPT0gdGhpcy5zZWxlY3RlZERhdGUueWVhcigpICYmIGRheS5kYXlPZlllYXIoKSA9PSB0aGlzLnNlbGVjdGVkRGF0ZS5kYXlPZlllYXIoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRkLmFkZENsYXNzKCdzZWxlY3RlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUgPT09ICdkYXknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRkLmFkZENsYXNzKHRoaXMua2V5Ym9hcmROYXZDc3NDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJHRkLmNsaWNrKChmdW5jdGlvbiAoZGF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRLZXlib2FyZE5hdmlnYXRpb25TdGF0ZShcImRheVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldE1vbnRoQW5kRGF5KGRheS5tb250aCgpICsgMSwgZGF5LmRhdGUoKSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmJpbmQodGhpcywgZGF5KSk7XG4gICAgICAgICAgICAgICAgICAgICR0ci5hcHBlbmQoJHRkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUudXBkYXRlQ2xvY2tEaXNwbGF5ID0gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuJGFtUG1UZXh0LnRleHQoZGF0ZS5ob3VyKCkgPj0gMTIgPyAncG0nIDogJ2FtJyk7XG4gICAgICAgICAgICB2YXIgbWludXRlc0FuZ2xlID0gZGF0ZS5taW51dGUoKSAqIDY7XG4gICAgICAgICAgICB2YXIgaG91cnMgPSAoZGF0ZS5ob3VyKCkgJSAxMikgKyBkYXRlLm1pbnV0ZSgpIC8gNjA7XG4gICAgICAgICAgICB2YXIgaG91ckFuZ2xlID0gaG91cnMgKiAzMDtcbiAgICAgICAgICAgIHRoaXMuJGhvdXJIYW5kLmF0dHIoXCJ0cmFuc2Zvcm1cIiwgXCJyb3RhdGUoXCIgKyBob3VyQW5nbGUgKyBcIiw1MCw1MClcIik7XG4gICAgICAgICAgICB0aGlzLiRtaW51dGVIYW5kLmF0dHIoXCJ0cmFuc2Zvcm1cIiwgXCJyb3RhdGUoXCIgKyBtaW51dGVzQW5nbGUgKyBcIiw1MCw1MClcIik7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZUhvdXJEaXNwbGF5LnRleHQoZGF0ZS5mb3JtYXQoJ0hIJykpO1xuICAgICAgICAgICAgdGhpcy4kZGlnaXRhbFRpbWVNaW51dGVEaXNwbGF5LnRleHQoZGF0ZS5mb3JtYXQoJ21tJykpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnVwZGF0ZURpc3BsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU1vbnRoRGlzcGxheSh0aGlzLnNlbGVjdGVkRGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUNsb2NrRGlzcGxheSh0aGlzLnNlbGVjdGVkRGF0ZSk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5zZXRTZWxlY3RlZERhdGUgPSBmdW5jdGlvbiAobW9tZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IG1vbWVudDtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRGlzcGxheSgpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnNldFllYXIgPSBmdW5jdGlvbiAoeWVhciwgZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS55ZWFyKHllYXIpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbk9uRWRpdGluZ1RpbWVVbml0Q2hhbmdlLmZpcmUoJ3llYXInKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoJ3llYXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5zZXRNb250aCA9IGZ1bmN0aW9uIChtb250aCwgZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS5tb250aChtb250aCAtIDEpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbk9uRWRpdGluZ1RpbWVVbml0Q2hhbmdlLmZpcmUoJ21vbnRoJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCdtb250aCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnNldERheU9mTW9udGggPSBmdW5jdGlvbiAoZGF5T2ZNb250aCwgZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS5kYXRlKGRheU9mTW9udGgpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbk9uRWRpdGluZ1RpbWVVbml0Q2hhbmdlLmZpcmUoJ2RheScpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygnZGF5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUuc2V0TW9udGhBbmREYXkgPSBmdW5jdGlvbiAobW9udGgsIGRheSwgZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS5tb250aChtb250aCAtIDEpO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGUuZGF0ZShkYXkpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbk9uRWRpdGluZ1RpbWVVbml0Q2hhbmdlLmZpcmUoJ2RheScpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygnbW9udGgnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoJ2RheScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnNldEhvdXIgPSBmdW5jdGlvbiAoaG91ciwgZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS5ob3VyKGhvdXIpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbk9uRWRpdGluZ1RpbWVVbml0Q2hhbmdlLmZpcmUoJ2hvdXInKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoJ2hvdXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5zZXRNaW51dGUgPSBmdW5jdGlvbiAobWludXRlLCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLm1pbnV0ZShtaW51dGUpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbk9uRWRpdGluZ1RpbWVVbml0Q2hhbmdlLmZpcmUoJ21pbnV0ZScpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygnbWludXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUuZmlyZUNoYW5nZUV2ZW50cyA9IGZ1bmN0aW9uICh0aW1lVW5pdCkge1xuICAgICAgICAgICAgdGhpcy4kY2FsZW5kYXJCb3gudHJpZ2dlcihcImNoYW5nZVwiKTtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2UuZmlyZSh7XG4gICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuZ2V0U2VsZWN0ZWREYXRlKCksXG4gICAgICAgICAgICAgICAgdGltZVVuaXRFZGl0ZWQ6IHRpbWVVbml0XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5zZXRLZXlib2FyZE5hdmlnYXRpb25TdGF0ZSA9IGZ1bmN0aW9uIChuZXdLZXlib2FyZE5hdmlnYXRpb25TdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5rZXlib2FyZE5hdmlnYXRpb25TdGF0ZSA9IG5ld0tleWJvYXJkTmF2aWdhdGlvblN0YXRlO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmhpZ2hsaWdodEtleWJvYXJkTmF2aWdhdGlvblN0YXRlKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1lXzEgPSB0aGlzO1xuICAgICAgICAgICAgICAgICQodGhpcy4keWVhckRpc3BsYXkpLmFkZCh0aGlzLiRtb250aERpc3BsYXkpLmFkZCh0aGlzLiRtb250aFRhYmxlLmZpbmQoJ3RkLicgKyB0aGlzLmtleWJvYXJkTmF2Q3NzQ2xhc3MpKS5hZGQodGhpcy4kaG91ckhhbmQpLmFkZCh0aGlzLiRkaWdpdGFsVGltZUhvdXJEaXNwbGF5V3JhcHBlcikuYWRkKHRoaXMuJG1pbnV0ZUhhbmQpLmFkZCh0aGlzLiRkaWdpdGFsVGltZU1pbnV0ZURpc3BsYXlXcmFwcGVyKVxuICAgICAgICAgICAgICAgICAgICAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcykuYXR0cihcImNsYXNzXCIsICQodGhpcykuYXR0cihcImNsYXNzXCIpLnJlcGxhY2UobWVfMS5rZXlib2FyZE5hdkNzc0NsYXNzLCAnJykpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmtleWJvYXJkTmF2aWdhdGlvblN0YXRlID09ICd5ZWFyJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiR5ZWFyRGlzcGxheS5hZGRDbGFzcyh0aGlzLmtleWJvYXJkTmF2Q3NzQ2xhc3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0aGlzLmtleWJvYXJkTmF2aWdhdGlvblN0YXRlID09ICdtb250aCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kbW9udGhEaXNwbGF5LmFkZENsYXNzKHRoaXMua2V5Ym9hcmROYXZDc3NDbGFzcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUgPT0gJ2RheScpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kbW9udGhUYWJsZS5maW5kKFwiLnNlbGVjdGVkXCIpLmFkZENsYXNzKHRoaXMua2V5Ym9hcmROYXZDc3NDbGFzcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUgPT0gJ2hvdXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGhvdXJIYW5kLmF0dHIoXCJjbGFzc1wiLCBcImhvdXJoYW5kIFwiICsgdGhpcy5rZXlib2FyZE5hdkNzc0NsYXNzKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kZGlnaXRhbFRpbWVIb3VyRGlzcGxheVdyYXBwZXIuYWRkQ2xhc3ModGhpcy5rZXlib2FyZE5hdkNzc0NsYXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5rZXlib2FyZE5hdmlnYXRpb25TdGF0ZSA9PSAnbWludXRlJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRtaW51dGVIYW5kLmF0dHIoXCJjbGFzc1wiLCBcIm1pbnV0ZWhhbmQgXCIgKyB0aGlzLmtleWJvYXJkTmF2Q3NzQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZU1pbnV0ZURpc3BsYXlXcmFwcGVyLmFkZENsYXNzKHRoaXMua2V5Ym9hcmROYXZDc3NDbGFzcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLmdldFNlbGVjdGVkRGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkRGF0ZTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLm5hdmlnYXRlQnlVbml0ID0gZnVuY3Rpb24gKHVuaXQsIGRpcmVjdGlvbiwgZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50ID09PSB2b2lkIDApIHsgZmlyZUV2ZW50ID0gZmFsc2U7IH1cbiAgICAgICAgICAgIGlmICh1bml0ID09ICd5ZWFyJykge1xuICAgICAgICAgICAgICAgIGlmIChkaXJlY3Rpb24gPT0gJ2Rvd24nIHx8IGRpcmVjdGlvbiA9PSAnbGVmdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRZZWFyKHRoaXMuc2VsZWN0ZWREYXRlLnllYXIoKSAtIDEsIGZpcmVFdmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGRpcmVjdGlvbiA9PSAndXAnIHx8IGRpcmVjdGlvbiA9PSAncmlnaHQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0WWVhcih0aGlzLnNlbGVjdGVkRGF0ZS55ZWFyKCkgKyAxLCBmaXJlRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmaXJlRXZlbnQgJiYgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCd5ZWFyJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh1bml0ID09ICdtb250aCcpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGlyZWN0aW9uID09ICdkb3duJyB8fCBkaXJlY3Rpb24gPT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TW9udGgodGhpcy5zZWxlY3RlZERhdGUubW9udGgoKSwgZmlyZUV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGlyZWN0aW9uID09ICd1cCcgfHwgZGlyZWN0aW9uID09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRNb250aCh0aGlzLnNlbGVjdGVkRGF0ZS5tb250aCgpICsgMiwgZmlyZUV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZmlyZUV2ZW50ICYmIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygnbW9udGgnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHVuaXQgPT0gJ2RheScpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGlyZWN0aW9uID09ICdkb3duJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS5kYXlPZlllYXIodGhpcy5zZWxlY3RlZERhdGUuZGF5T2ZZZWFyKCkgKyA3KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGlyZWN0aW9uID09ICdsZWZ0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS5kYXlPZlllYXIodGhpcy5zZWxlY3RlZERhdGUuZGF5T2ZZZWFyKCkgLSAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGlyZWN0aW9uID09ICd1cCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGUuZGF5T2ZZZWFyKHRoaXMuc2VsZWN0ZWREYXRlLmRheU9mWWVhcigpIC0gNyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGRpcmVjdGlvbiA9PSAncmlnaHQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLmRheU9mWWVhcih0aGlzLnNlbGVjdGVkRGF0ZS5kYXlPZlllYXIoKSArIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgICAgICBmaXJlRXZlbnQgJiYgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCdkYXknKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHVuaXQgPT0gJ2hvdXInKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRpcmVjdGlvbiA9PSAnZG93bicgfHwgZGlyZWN0aW9uID09ICdsZWZ0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEhvdXIodGhpcy5zZWxlY3RlZERhdGUuaG91cigpIC0gMSwgZmlyZUV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGlyZWN0aW9uID09ICd1cCcgfHwgZGlyZWN0aW9uID09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRIb3VyKHRoaXMuc2VsZWN0ZWREYXRlLmhvdXIoKSArIDEsIGZpcmVFdmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpcmVFdmVudCAmJiB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoJ2hvdXInKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHVuaXQgPT0gJ21pbnV0ZScpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGlyZWN0aW9uID09ICdkb3duJyB8fCBkaXJlY3Rpb24gPT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TWludXRlKHRoaXMuc2VsZWN0ZWREYXRlLm1pbnV0ZSgpIC0gKHRoaXMuc2VsZWN0ZWREYXRlLm1pbnV0ZSgpICUgNSkgLSA1LCBmaXJlRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkaXJlY3Rpb24gPT0gJ3VwJyB8fCBkaXJlY3Rpb24gPT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldE1pbnV0ZSh0aGlzLnNlbGVjdGVkRGF0ZS5taW51dGUoKSAtICh0aGlzLnNlbGVjdGVkRGF0ZS5taW51dGUoKSAlIDUpICsgNSwgZmlyZUV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZmlyZUV2ZW50ICYmIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygnbWludXRlJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUubmF2aWdhdGUgPSBmdW5jdGlvbiAoZGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLm5hdmlnYXRlQnlVbml0KHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUsIGRpcmVjdGlvbik7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5nZXRNYWluRG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRjYWxlbmRhckJveFswXTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kY2FsZW5kYXJCb3gucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgcmV0dXJuIFRyaXZpYWxDYWxlbmRhckJveDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbENhbGVuZGFyQm94ID0gVHJpdmlhbENhbGVuZGFyQm94O1xufSk7XG5cblxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIiwgXCJqcXVlcnlcIiwgXCJtdXN0YWNoZVwiLCBcIi4vVHJpdmlhbENvcmVcIiwgXCIuL1RyaXZpYWxMaXN0Qm94XCIsIFwiLi9Ucml2aWFsRXZlbnRcIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcbiAgICB2YXIgTXVzdGFjaGUgPSByZXF1aXJlKFwibXVzdGFjaGVcIik7XG4gICAgdmFyIFRyaXZpYWxDb3JlXzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsQ29yZVwiKTtcbiAgICB2YXIgVHJpdmlhbExpc3RCb3hfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxMaXN0Qm94XCIpO1xuICAgIHZhciBUcml2aWFsRXZlbnRfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxFdmVudFwiKTtcbiAgICB2YXIgVHJpdmlhbENvbWJvQm94ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gVHJpdmlhbENvbWJvQm94KG9yaWdpbmFsSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSAkKCk7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbkZvY3VzID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMub25CbHVyID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuaXNFZGl0b3JWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmxhc3RRdWVyeVN0cmluZyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmxhc3RDb21wbGV0ZUlucHV0UXVlcnlTdHJpbmcgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEVudHJ5ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMubGFzdENvbW1pdHRlZFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuYXV0b0NvbXBsZXRlVGltZW91dElkID0gLTE7XG4gICAgICAgICAgICB0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94RGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgICAgICB2YWx1ZUZ1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHsgcmV0dXJuIGVudHJ5ID8gXCJcIiArIGVudHJ5LmlkIDogbnVsbDsgfSxcbiAgICAgICAgICAgICAgICBlbnRyeVJlbmRlcmluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE11c3RhY2hlLnJlbmRlcihUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmltYWdlMkxpbmVzVGVtcGxhdGUsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5jb25maWcuZW50cnlSZW5kZXJpbmdGdW5jdGlvbihlbnRyeSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJ5OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgc3Bpbm5lclRlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHRTcGlubmVyVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgbm9FbnRyaWVzVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdE5vRW50cmllc1RlbXBsYXRlLFxuICAgICAgICAgICAgICAgIHRleHRIaWdobGlnaHRpbmdFbnRyeUxpbWl0OiAxMDAsXG4gICAgICAgICAgICAgICAgZW50cmllczogbnVsbCxcbiAgICAgICAgICAgICAgICBxdWVyeUZ1bmN0aW9uOiBudWxsLFxuICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGVEZWxheTogMCxcbiAgICAgICAgICAgICAgICBlbnRyeVRvRWRpdG9yVGV4dEZ1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5W1wiZGlzcGxheVZhbHVlXCJdO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlRnVuY3Rpb246IGZ1bmN0aW9uIChlZGl0b3JUZXh0LCBlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWRpdG9yVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcGVydHlOYW1lIGluIGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVudHJ5Lmhhc093blByb3BlcnR5KHByb3BlcnR5TmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5VmFsdWUgPSBlbnRyeVtwcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydHlWYWx1ZSAmJiBwcm9wZXJ0eVZhbHVlLnRvU3RyaW5nKCkudG9Mb3dlckNhc2UoKS5pbmRleE9mKGVkaXRvclRleHQudG9Mb3dlckNhc2UoKSkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwcm9wZXJ0eVZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbnRyeSA/IF90aGlzLmNvbmZpZy5lbnRyeVRvRWRpdG9yVGV4dEZ1bmN0aW9uKGVudHJ5KSA6IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGFsbG93RnJlZVRleHQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGZyZWVUZXh0RW50cnlGYWN0b3J5OiBmdW5jdGlvbiAoZnJlZVRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXlWYWx1ZTogZnJlZVRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICBfaXNGcmVlVGV4dEVudHJ5OiB0cnVlXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzaG93Q2xlYXJCdXR0b246IGZhbHNlLFxuICAgICAgICAgICAgICAgIHNob3dUcmlnZ2VyOiB0cnVlLFxuICAgICAgICAgICAgICAgIG1hdGNoaW5nT3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ01vZGU6ICdjb250YWlucycsXG4gICAgICAgICAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVkaXRpbmdNb2RlOiAnZWRpdGFibGUnLFxuICAgICAgICAgICAgICAgIHNob3dEcm9wRG93bk9uUmVzdWx0c09ubHk6IGZhbHNlXG4gICAgICAgICAgICB9LCBvcHRpb25zKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLnF1ZXJ5RnVuY3Rpb24gPSBUcml2aWFsQ29yZV8xLmRlZmF1bHRMaXN0UXVlcnlGdW5jdGlvbkZhY3RvcnkodGhpcy5jb25maWcuZW50cmllcyB8fCBbXSwgdGhpcy5jb25maWcubWF0Y2hpbmdPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB0aGlzLnVzaW5nRGVmYXVsdFF1ZXJ5RnVuY3Rpb24gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gdGhpcy5jb25maWcuZW50cmllcztcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQgPSAkKG9yaWdpbmFsSW5wdXQpO1xuICAgICAgICAgICAgdGhpcy4kY29tYm9Cb3ggPSAkKCc8ZGl2IGNsYXNzPVwidHItY29tYm9ib3ggdHItaW5wdXQtd3JhcHBlclwiLz4nKVxuICAgICAgICAgICAgICAgIC5pbnNlcnRBZnRlcih0aGlzLiRvcmlnaW5hbElucHV0KTtcbiAgICAgICAgICAgIHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLWNvbWJvYm94LXNlbGVjdGVkLWVudHJ5LXdyYXBwZXJcIi8+JykuYXBwZW5kVG8odGhpcy4kY29tYm9Cb3gpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNob3dDbGVhckJ1dHRvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuJGNsZWFyQnV0dG9uID0gJCgnPGRpdiBjbGFzcz1cInRyLXJlbW92ZS1idXR0b25cIj4nKS5hcHBlbmRUbyh0aGlzLiRjb21ib0JveCk7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2xlYXJCdXR0b24ubW91c2Vkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudmFsKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KG51bGwsIHRydWUsIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kdHJpZ2dlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmlnZ2VyXCI+PHNwYW4gY2xhc3M9XCJ0ci10cmlnZ2VyLWljb25cIi8+PC9kaXY+JykuYXBwZW5kVG8odGhpcy4kY29tYm9Cb3gpO1xuICAgICAgICAgICAgICAgIHRoaXMuJHRyaWdnZXIubW91c2Vkb3duKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duID0gJCgnPGRpdiBjbGFzcz1cInRyLWRyb3Bkb3duXCI+PC9kaXY+JylcbiAgICAgICAgICAgICAgICAuc2Nyb2xsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duVGFyZ2V0RWxlbWVudCA9ICQoXCJib2R5XCIpO1xuICAgICAgICAgICAgdGhpcy5zZXRFZGl0aW5nTW9kZSh0aGlzLmNvbmZpZy5lZGl0aW5nTW9kZSk7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LmFkZENsYXNzKFwidHItb3JpZ2luYWwtaW5wdXRcIik7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IgPSAkKCc8aW5wdXQgdHlwZT1cInRleHRcIiBhdXRvY29tcGxldGU9XCJvZmZcIi8+Jyk7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IucHJlcGVuZFRvKHRoaXMuJGNvbWJvQm94KS5hZGRDbGFzcyhcInRyLWNvbWJvYm94LWVkaXRvciB0ci1lZGl0b3JcIilcbiAgICAgICAgICAgICAgICAuZm9jdXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJG9yaWdpbmFsSW5wdXQudHJpZ2dlckhhbmRsZXIoJ2ZvY3VzJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9uRm9jdXMuZmlyZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kY29tYm9Cb3guYWRkQ2xhc3MoJ2ZvY3VzJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5ibHVyKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXJIYW5kbGVyKCdibHVyJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9uQmx1ci5maXJlKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRjb21ib0JveC5yZW1vdmVDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmVkaXRvckNvbnRhaW5zRnJlZVRleHQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFUcml2aWFsQ29yZV8xLm9iamVjdEVxdWFscyhfdGhpcy5nZXRTZWxlY3RlZEVudHJ5KCksIF90aGlzLmxhc3RDb21taXR0ZWRWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KF90aGlzLmdldFNlbGVjdGVkRW50cnkoKSwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnZhbChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMubGFzdENvbW1pdHRlZFZhbHVlLCBmYWxzZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGlkZUVkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAua2V5ZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChUcml2aWFsQ29yZV8xLmtleUNvZGVzLmlzTW9kaWZpZXJLZXkoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudGFiKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gX3RoaXMubGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3BlbiAmJiBoaWdobGlnaHRlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KGhpZ2hsaWdodGVkRW50cnksIHRydWUsIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFfdGhpcy4kZWRpdG9yLnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KG51bGwsIHRydWUsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKF90aGlzLmNvbmZpZy5hbGxvd0ZyZWVUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KF90aGlzLmdldFNlbGVjdGVkRW50cnkoKSwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMubGVmdF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXNOb25JZ25vcmVkS2V5ID0gIVRyaXZpYWxDb3JlXzEua2V5Q29kZXMuaXNNb2RpZmllcktleShlKSAmJiBbVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lbnRlciwgVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lc2NhcGUsIFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudGFiXS5pbmRleE9mKGUud2hpY2gpID09PSAtMTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVkaXRvclZhbHVlRG9lc05vdENvcnJlc3BvbmRUb1NlbGVjdGVkVmFsdWUgPSBfdGhpcy5pc0VudHJ5U2VsZWN0ZWQoKSAmJiBfdGhpcy4kZWRpdG9yLnZhbCgpICE9PSBfdGhpcy5jb25maWcuZW50cnlUb0VkaXRvclRleHRGdW5jdGlvbihfdGhpcy5zZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzTm9uSWdub3JlZEtleSAmJiAoZWRpdG9yVmFsdWVEb2VzTm90Q29ycmVzcG9uZFRvU2VsZWN0ZWRWYWx1ZSB8fCBfdGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihfdGhpcy5saXN0Qm94LmdldEhpZ2hsaWdodGVkRW50cnkoKSkpICE9PSBfdGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihfdGhpcy5nZXRTZWxlY3RlZEVudHJ5KCkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KG51bGwsIGZhbHNlLCBmYWxzZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmJhY2tzcGFjZSB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZGVsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmRvd25fYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0VkaXRvclZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpcmVjdGlvbiA9IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy51cF9hcnJvdyA/IC0xIDogMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmxpc3RCb3guaGlnaGxpZ2h0TmV4dEVudHJ5KGRpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5hdXRvQ29tcGxldGVJZlBvc3NpYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRWRpdG9yVmlzaWJsZSB8fCBfdGhpcy5lZGl0b3JDb250YWluc0ZyZWVUZXh0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gX3RoaXMubGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4gJiYgaGlnaGxpZ2h0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoaGlnaGxpZ2h0ZWRFbnRyeSwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICghX3RoaXMuJGVkaXRvci52YWwoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkobnVsbCwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChfdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmhpZGVFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZXNjYXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoX3RoaXMuZWRpdG9yQ29udGFpbnNGcmVlVGV4dCgpICYmIF90aGlzLmlzRHJvcERvd25PcGVuKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGlkZUVkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci52YWwoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5lbnRyaWVzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMubGFzdENvbW1pdHRlZFZhbHVlLCBmYWxzZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0VkaXRvclZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGVkaXRvci52YWwoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMubGlzdEJveC5zZXRIaWdobGlnaHRlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICh0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJ0YWJpbmRleFwiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci5hdHRyKFwidGFiaW5kZXhcIiwgdGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcImF1dG9mb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kY29tYm9Cb3guYWRkKHRoaXMuJGRyb3BEb3duKS5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5tb3VzZXVwKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLm1vdXNlb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGNvbmZpZ1dpdGhvdXRFbnRyaWVzID0gJC5leHRlbmQoe30sIHRoaXMuY29uZmlnKTtcbiAgICAgICAgICAgIGNvbmZpZ1dpdGhvdXRFbnRyaWVzLmVudHJpZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveCA9IG5ldyBUcml2aWFsTGlzdEJveF8xLlRyaXZpYWxMaXN0Qm94KHRoaXMuJGRyb3BEb3duLCBjb25maWdXaXRob3V0RW50cmllcyk7XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3gub25TZWxlY3RlZEVudHJ5Q2hhbmdlZC5hZGRMaXN0ZW5lcihmdW5jdGlvbiAoc2VsZWN0ZWRFbnRyeSwgZXZlbnRTb3VyY2UsIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KHNlbGVjdGVkRW50cnksIHRydWUsICFUcml2aWFsQ29yZV8xLm9iamVjdEVxdWFscyhzZWxlY3RlZEVudHJ5LCBfdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUpLCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubGlzdEJveC5zZXRTZWxlY3RlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLmhpZGVFZGl0b3IoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXRTZWxlY3RlZEVudHJ5KHRoaXMuY29uZmlnLnNlbGVjdGVkRW50cnksIHRydWUsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyLmNsaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmNvbmZpZy5zaG93RHJvcERvd25PblJlc3VsdHNPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uIChoaWdobGlnaHREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgcXVlcnlTdHJpbmcgPSB0aGlzLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgIHZhciBjb21wbGV0ZUlucHV0U3RyaW5nID0gdGhpcy4kZWRpdG9yLnZhbCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMubGFzdFF1ZXJ5U3RyaW5nICE9PSBxdWVyeVN0cmluZyB8fCB0aGlzLmxhc3RDb21wbGV0ZUlucHV0UXVlcnlTdHJpbmcgIT09IGNvbXBsZXRlSW5wdXRTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy4kc3Bpbm5lcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkc3Bpbm5lciA9ICQodGhpcy5jb25maWcuc3Bpbm5lclRlbXBsYXRlKS5hcHBlbmRUbyh0aGlzLiRkcm9wRG93bik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gdGhpcy4kc3Bpbm5lcnMuYWRkKCRzcGlubmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbihxdWVyeVN0cmluZywgZnVuY3Rpb24gKG5ld0VudHJpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRW50cmllcyhuZXdFbnRyaWVzLCBoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkgJiYgbmV3RW50cmllcyAmJiBuZXdFbnRyaWVzLmxlbmd0aCA+IDAgJiYgX3RoaXMuJGVkaXRvci5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RRdWVyeVN0cmluZyA9IHF1ZXJ5U3RyaW5nO1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdENvbXBsZXRlSW5wdXRRdWVyeVN0cmluZyA9IGNvbXBsZXRlSW5wdXRTdHJpbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmZpcmVDaGFuZ2VFdmVudHMgPSBmdW5jdGlvbiAoZW50cnksIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQudHJpZ2dlcihcImNoYW5nZVwiKTtcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3RlZEVudHJ5Q2hhbmdlZC5maXJlKGVudHJ5LCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5zZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5LCBjb21taXQsIGZpcmVFdmVudCwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgaWYgKGNvbW1pdCA9PT0gdm9pZCAwKSB7IGNvbW1pdCA9IHRydWU7IH1cbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQgPT09IHZvaWQgMCkgeyBmaXJlRXZlbnQgPSBmYWxzZTsgfVxuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC52YWwodGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihlbnRyeSkpO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEVudHJ5ID0gZW50cnk7XG4gICAgICAgICAgICB2YXIgJHNlbGVjdGVkRW50cnkgPSAkKHRoaXMuY29uZmlnLnNlbGVjdGVkRW50cnlSZW5kZXJpbmdGdW5jdGlvbihlbnRyeSkpXG4gICAgICAgICAgICAgICAgLmFkZENsYXNzKFwidHItY29tYm9ib3gtZW50cnlcIik7XG4gICAgICAgICAgICB0aGlzLiRzZWxlY3RlZEVudHJ5V3JhcHBlci5lbXB0eSgpLmFwcGVuZCgkc2VsZWN0ZWRFbnRyeSk7XG4gICAgICAgICAgICBpZiAoZW50cnkgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci52YWwodGhpcy5jb25maWcuZW50cnlUb0VkaXRvclRleHRGdW5jdGlvbihlbnRyeSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbW1pdCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdENvbW1pdHRlZFZhbHVlID0gZW50cnk7XG4gICAgICAgICAgICAgICAgaWYgKGZpcmVFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoZW50cnksIG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLiRjbGVhckJ1dHRvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuJGNsZWFyQnV0dG9uLnRvZ2dsZShlbnRyeSAhPSBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzRWRpdG9yVmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcG9zaXRpb25Ecm9wRG93bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmlzRW50cnlTZWxlY3RlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkRW50cnkgIT0gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5zaG93RWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyICRlZGl0b3JBcmVhID0gdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIuZmluZChcIi50ci1lZGl0b3ItYXJlYVwiKTtcbiAgICAgICAgICAgIGlmICgkZWRpdG9yQXJlYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAkZWRpdG9yQXJlYSA9IHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kZWRpdG9yXG4gICAgICAgICAgICAgICAgLmNzcyh7XG4gICAgICAgICAgICAgICAgXCJ3aWR0aFwiOiBNYXRoLm1pbigkZWRpdG9yQXJlYVswXS5vZmZzZXRXaWR0aCwgdGhpcy4kdHJpZ2dlciA/IHRoaXMuJHRyaWdnZXJbMF0ub2Zmc2V0TGVmdCAtICRlZGl0b3JBcmVhWzBdLm9mZnNldExlZnQgOiA5OTk5OTk5OSkgKyBcInB4XCIsXG4gICAgICAgICAgICAgICAgXCJoZWlnaHRcIjogKCRlZGl0b3JBcmVhWzBdLm9mZnNldEhlaWdodCkgKyBcInB4XCJcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICBteTogXCJsZWZ0IHRvcFwiLFxuICAgICAgICAgICAgICAgIGF0OiBcImxlZnQgdG9wXCIsXG4gICAgICAgICAgICAgICAgb2Y6ICRlZGl0b3JBcmVhXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuaXNFZGl0b3JWaXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5lZGl0b3JDb250YWluc0ZyZWVUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmFsbG93RnJlZVRleHQgJiYgdGhpcy4kZWRpdG9yLnZhbCgpLmxlbmd0aCA+IDAgJiYgIXRoaXMuaXNFbnRyeVNlbGVjdGVkKCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5oaWRlRWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLndpZHRoKDApLmhlaWdodCgwKTtcbiAgICAgICAgICAgIHRoaXMuaXNFZGl0b3JWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUucmVwb3NpdGlvbkRyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duXG4gICAgICAgICAgICAgICAgLnNob3coKVxuICAgICAgICAgICAgICAgIC5wb3NpdGlvbih7XG4gICAgICAgICAgICAgICAgbXk6IFwibGVmdCB0b3BcIixcbiAgICAgICAgICAgICAgICBhdDogXCJsZWZ0IGJvdHRvbVwiLFxuICAgICAgICAgICAgICAgIG9mOiB0aGlzLiRjb21ib0JveCxcbiAgICAgICAgICAgICAgICBjb2xsaXNpb246IFwiZmxpcFwiLFxuICAgICAgICAgICAgICAgIHVzaW5nOiBmdW5jdGlvbiAoY2FsY3VsYXRlZFBvc2l0aW9uLCBpbmZvKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmZvLnZlcnRpY2FsID09PSBcInRvcFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kY29tYm9Cb3gucmVtb3ZlQ2xhc3MoXCJkcm9wZG93bi1mbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLnJlbW92ZUNsYXNzKFwiZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRjb21ib0JveC5hZGRDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24uYWRkQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5jc3Moe1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogY2FsY3VsYXRlZFBvc2l0aW9uLmxlZnQgKyAncHgnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wOiBjYWxjdWxhdGVkUG9zaXRpb24udG9wICsgJ3B4J1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC53aWR0aCh0aGlzLiRjb21ib0JveC53aWR0aCgpKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLm9wZW5Ecm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZvaWQgMDtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25OZWVkZWQoKSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxpc3RCb3hEaXJ0eSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUxpc3RCb3hFbnRyaWVzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuJGNvbWJvQm94LmFkZENsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcG9zaXRpb25Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmNsb3NlRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRjb21ib0JveC5yZW1vdmVDbGFzcyhcIm9wZW5cIik7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5oaWRlKCk7XG4gICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRlZGl0b3IudmFsKCkuc3Vic3RyaW5nKDAsIHRoaXMuJGVkaXRvclswXS5zZWxlY3Rpb25TdGFydCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuYXV0b0NvbXBsZXRlSWZQb3NzaWJsZSA9IGZ1bmN0aW9uIChkZWxheSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5hdXRvQ29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5hdXRvQ29tcGxldGVUaW1lb3V0SWQpO1xuICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5XzEgPSB0aGlzLmxpc3RCb3guZ2V0SGlnaGxpZ2h0ZWRFbnRyeSgpO1xuICAgICAgICAgICAgICAgIGlmIChoaWdobGlnaHRlZEVudHJ5XzEgJiYgIXRoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYXV0b0NvbXBsZXRlVGltZW91dElkID0gVHJpdmlhbENvcmVfMS5zZXRUaW1lb3V0T3JEb0ltbWVkaWF0ZWx5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjdXJyZW50RWRpdG9yVmFsdWUgPSBfdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXV0b0NvbXBsZXRlU3RyaW5nID0gX3RoaXMuY29uZmlnLmF1dG9Db21wbGV0ZUZ1bmN0aW9uKGN1cnJlbnRFZGl0b3JWYWx1ZSwgaGlnaGxpZ2h0ZWRFbnRyeV8xKSB8fCBjdXJyZW50RWRpdG9yVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnZhbChjdXJyZW50RWRpdG9yVmFsdWUgKyBhdXRvQ29tcGxldGVTdHJpbmcuc3Vic3RyKGN1cnJlbnRFZGl0b3JWYWx1ZS5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvclswXS5zZXRTZWxlY3Rpb25SYW5nZShjdXJyZW50RWRpdG9yVmFsdWUubGVuZ3RoLCBhdXRvQ29tcGxldGVTdHJpbmcubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSwgZGVsYXkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLnVwZGF0ZUxpc3RCb3hFbnRyaWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94LnVwZGF0ZUVudHJpZXModGhpcy5lbnRyaWVzKTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveERpcnR5ID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUudXBkYXRlRW50cmllcyA9IGZ1bmN0aW9uIChuZXdFbnRyaWVzLCBoaWdobGlnaHREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZW50cmllcyA9IG5ld0VudHJpZXM7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycy5yZW1vdmUoKTtcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gJCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUxpc3RCb3hFbnRyaWVzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3RCb3hEaXJ0eSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA9IHRoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94LmhpZ2hsaWdodFRleHRNYXRjaGVzKG5ld0VudHJpZXMubGVuZ3RoIDw9IHRoaXMuY29uZmlnLnRleHRIaWdobGlnaHRpbmdFbnRyeUxpbWl0ID8gbm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA6IG51bGwpO1xuICAgICAgICAgICAgaWYgKGhpZ2hsaWdodERpcmVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxpc3RCb3guc2V0SGlnaGxpZ2h0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGlzdEJveC5oaWdobGlnaHROZXh0RW50cnkoMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaGlnaGxpZ2h0RGlyZWN0aW9uID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5saXN0Qm94LnNldEhpZ2hsaWdodGVkRW50cnkobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3RCb3guaGlnaGxpZ2h0TmV4dEVudHJ5KGhpZ2hsaWdodERpcmVjdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmF1dG9Db21wbGV0ZUlmUG9zc2libGUodGhpcy5jb25maWcuYXV0b0NvbXBsZXRlRGVsYXkpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmlzRHJvcERvd25OZWVkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lZGl0aW5nTW9kZSA9PSAnZWRpdGFibGUnICYmICh0aGlzLmNvbmZpZy5lbnRyaWVzICYmIHRoaXMuY29uZmlnLmVudHJpZXMubGVuZ3RoID4gMCB8fCAhdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uIHx8IHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5zZXRFZGl0aW5nTW9kZSA9IGZ1bmN0aW9uIChuZXdFZGl0aW5nTW9kZSkge1xuICAgICAgICAgICAgdGhpcy5lZGl0aW5nTW9kZSA9IG5ld0VkaXRpbmdNb2RlO1xuICAgICAgICAgICAgdGhpcy4kY29tYm9Cb3gucmVtb3ZlQ2xhc3MoXCJlZGl0YWJsZSByZWFkb25seSBkaXNhYmxlZFwiKS5hZGRDbGFzcyh0aGlzLmVkaXRpbmdNb2RlKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25OZWVkZWQoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duVGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuZ2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkRW50cnkgPT0gbnVsbCAmJiAoIXRoaXMuY29uZmlnLmFsbG93RnJlZVRleHQgfHwgIXRoaXMuJGVkaXRvci52YWwoKSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRFbnRyeSA9PSBudWxsICYmIHRoaXMuY29uZmlnLmFsbG93RnJlZVRleHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZnJlZVRleHRFbnRyeUZhY3RvcnkodGhpcy4kZWRpdG9yLnZhbCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzZWxlY3RlZEVudHJ5VG9SZXR1cm4gPSAkLmV4dGVuZCh7fSwgdGhpcy5zZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJ5VG9SZXR1cm4uX3RyRW50cnlFbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHJldHVybiBzZWxlY3RlZEVudHJ5VG9SZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5mb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuZ2V0RWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGVkaXRvclswXTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5nZXREcm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRkcm9wRG93bjtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnJlbW92ZUNsYXNzKCd0ci1vcmlnaW5hbC1pbnB1dCcpLmluc2VydEJlZm9yZSh0aGlzLiRjb21ib0JveCk7XG4gICAgICAgICAgICB0aGlzLiRjb21ib0JveC5yZW1vdmUoKTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLnJlbW92ZSgpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuZ2V0TWFpbkRvbUVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kY29tYm9Cb3hbMF07XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBUcml2aWFsQ29tYm9Cb3g7XG4gICAgfSgpKTtcbiAgICBleHBvcnRzLlRyaXZpYWxDb21ib0JveCA9IFRyaXZpYWxDb21ib0JveDtcbn0pO1xuXG5cbnZhciBfX2Fzc2lnbiA9ICh0aGlzICYmIHRoaXMuX19hc3NpZ24pIHx8IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24odCkge1xuICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpXG4gICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICB9XG4gICAgcmV0dXJuIHQ7XG59O1xuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIiwgXCJtb21lbnRcIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciBtb21lbnQgPSByZXF1aXJlKFwibW9tZW50XCIpO1xuICAgIHZhciBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUob3B0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zID0gX19hc3NpZ24oeyBwcmVmZXJyZWREYXRlRm9ybWF0OiBcIllZWVktTU0tRERcIiB9LCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUucHJvdG90eXBlLmdlbmVyYXRlU3VnZ2VzdGlvbnMgPSBmdW5jdGlvbiAoc2VhcmNoU3RyaW5nLCBub3cpIHtcbiAgICAgICAgICAgIG5vdyA9IG1vbWVudChub3cpO1xuICAgICAgICAgICAgdmFyIHN1Z2dlc3Rpb25zO1xuICAgICAgICAgICAgaWYgKHNlYXJjaFN0cmluZy5tYXRjaCgvW15cXGRdLykpIHtcbiAgICAgICAgICAgICAgICB2YXIgZnJhZ21lbnRzID0gc2VhcmNoU3RyaW5nLnNwbGl0KC9bXlxcZF0vKS5maWx0ZXIoZnVuY3Rpb24gKGYpIHsgcmV0dXJuICEhZjsgfSk7XG4gICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSB0aGlzLmNyZWF0ZVN1Z2dlc3Rpb25zRm9yRnJhZ21lbnRzKGZyYWdtZW50cywgbm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zID0gdGhpcy5nZW5lcmF0ZVN1Z2dlc3Rpb25zRm9yRGlnaXRzT25seUlucHV0KHNlYXJjaFN0cmluZywgbm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBwcmVmZXJyZWRZbWRPcmRlciA9IFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5kYXRlRm9ybWF0VG9ZbWRPcmRlcih0aGlzLm9wdGlvbnMucHJlZmVycmVkRGF0ZUZvcm1hdCk7XG4gICAgICAgICAgICBzdWdnZXN0aW9ucy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZWZlcnJlZFltZE9yZGVyLmluZGV4T2YoYS55bWRPcmRlcikgPT09IC0xICYmIHByZWZlcnJlZFltZE9yZGVyLmluZGV4T2YoYi55bWRPcmRlcikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChwcmVmZXJyZWRZbWRPcmRlci5pbmRleE9mKGEueW1kT3JkZXIpICE9PSAtMSAmJiBwcmVmZXJyZWRZbWRPcmRlci5pbmRleE9mKGIueW1kT3JkZXIpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGEueW1kT3JkZXIubGVuZ3RoICE9IGIueW1kT3JkZXIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhLnltZE9yZGVyLmxlbmd0aCAtIGIueW1kT3JkZXIubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEubW9tZW50LmRpZmYobm93LCAnZGF5cycpIC0gYi5tb21lbnQuZGlmZihub3csICdkYXlzJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdWdnZXN0aW9ucyA9IHRoaXMucmVtb3ZlRHVwbGljYXRlcyhzdWdnZXN0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm4gc3VnZ2VzdGlvbnM7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5wcm90b3R5cGUucmVtb3ZlRHVwbGljYXRlcyA9IGZ1bmN0aW9uIChzdWdnZXN0aW9ucykge1xuICAgICAgICAgICAgdmFyIHNlZW5EYXRlcyA9IFtdO1xuICAgICAgICAgICAgcmV0dXJuIHN1Z2dlc3Rpb25zLmZpbHRlcihmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgIHZhciBkYXRlQWxyZWFkeUNvbnRhaW5lZCA9IHNlZW5EYXRlcy5maWx0ZXIoZnVuY3Rpb24gKHNlZW5EYXRlKSB7IHJldHVybiBzLm1vbWVudC5pc1NhbWUoc2VlbkRhdGUsICdkYXknKTsgfSkubGVuZ3RoID4gMDtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZUFscmVhZHlDb250YWluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VlbkRhdGVzLnB1c2gocy5tb21lbnQpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmRhdGVGb3JtYXRUb1ltZE9yZGVyID0gZnVuY3Rpb24gKGRhdGVGb3JtYXQpIHtcbiAgICAgICAgICAgIHZhciB5bWRJbmRleGVzID0ge1xuICAgICAgICAgICAgICAgIEQ6IGRhdGVGb3JtYXQuaW5kZXhPZihcIkRcIiksXG4gICAgICAgICAgICAgICAgTTogZGF0ZUZvcm1hdC5pbmRleE9mKFwiTVwiKSxcbiAgICAgICAgICAgICAgICBZOiBkYXRlRm9ybWF0LmluZGV4T2YoXCJZXCIpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIChbXCJEXCIsIFwiTVwiLCBcIllcIl0uc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4geW1kSW5kZXhlc1thXSAtIHltZEluZGV4ZXNbYl07IH0pLmpvaW4oXCJcIikpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbiA9IGZ1bmN0aW9uIChtb21lbnQsIHltZE9yZGVyKSB7XG4gICAgICAgICAgICByZXR1cm4geyBtb21lbnQ6IG1vbWVudCwgeW1kT3JkZXI6IHltZE9yZGVyIH07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5wcm90b3R5cGUuZ2VuZXJhdGVTdWdnZXN0aW9uc0ZvckRpZ2l0c09ubHlJbnB1dCA9IGZ1bmN0aW9uIChpbnB1dCwgdG9kYXkpIHtcbiAgICAgICAgICAgIGlucHV0ID0gaW5wdXQgfHwgXCJcIjtcbiAgICAgICAgICAgIGlmIChpbnB1dC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVTdWdnZXN0aW9uc0ZvckZyYWdtZW50cyhbXSwgdG9kYXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaW5wdXQubGVuZ3RoID4gOCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzdWdnZXN0aW9ucyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gaW5wdXQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gTWF0aC5taW4oaW5wdXQubGVuZ3RoLCBpICsgMSk7IGogPD0gaW5wdXQubGVuZ3RoICYmIGogLSBpIDw9IDQ7IGogLSBpID09PSAyID8gaiArPSAyIDogaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zID0gc3VnZ2VzdGlvbnMuY29uY2F0KHRoaXMuY3JlYXRlU3VnZ2VzdGlvbnNGb3JGcmFnbWVudHMoW2lucHV0LnN1YnN0cmluZygwLCBpKSwgaW5wdXQuc3Vic3RyaW5nKGksIGopLCBpbnB1dC5zdWJzdHJpbmcoaiwgaW5wdXQubGVuZ3RoKV0sIHRvZGF5KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN1Z2dlc3Rpb25zO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUucHJvdG90eXBlLnRvZGF5T3JGYXZvcml0ZURpcmVjdGlvbiA9IGZ1bmN0aW9uIChtLCB0b2RheSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9ucy5mYXZvclBhc3REYXRlcyA/IHRvZGF5LmlzU2FtZU9yQWZ0ZXIobSwgJ2RheScpIDogdG9kYXkuaXNTYW1lT3JCZWZvcmUobSwgJ2RheScpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUucHJvdG90eXBlLmNyZWF0ZVN1Z2dlc3Rpb25zRm9yRnJhZ21lbnRzID0gZnVuY3Rpb24gKGZyYWdtZW50cywgdG9kYXkpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICBmdW5jdGlvbiBtb2QobiwgbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoKG4gJSBtKSArIG0pICUgbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIG51bWJlclRvWWVhcihuKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNob3J0WWVhciA9IHRvZGF5LnllYXIoKSAlIDEwMDtcbiAgICAgICAgICAgICAgICB2YXIgeWVhclN1Z2dlc3Rpb25Cb3VuZGFyeSA9IChzaG9ydFllYXIgKyAyMCkgJSAxMDA7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRDZW50dXJ5ID0gTWF0aC5mbG9vcih0b2RheS55ZWFyKCkgLyAxMDApICogMTAwO1xuICAgICAgICAgICAgICAgIGlmIChuIDwgeWVhclN1Z2dlc3Rpb25Cb3VuZGFyeSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudENlbnR1cnkgKyBuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChuIDwgMTAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50Q2VudHVyeSAtIDEwMCArIG47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG4gPiB0b2RheS55ZWFyKCkgLSAxMDAgJiYgbiA8IHRvZGF5LnllYXIoKSArIDEwMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzMSA9IGZyYWdtZW50c1swXSwgczIgPSBmcmFnbWVudHNbMV0sIHMzID0gZnJhZ21lbnRzWzJdO1xuICAgICAgICAgICAgdmFyIF9hID0gW3BhcnNlSW50KHMxKSwgcGFyc2VJbnQoczIpLCBwYXJzZUludChzMyldLCBuMSA9IF9hWzBdLCBuMiA9IF9hWzFdLCBuMyA9IF9hWzJdO1xuICAgICAgICAgICAgdmFyIHN1Z2dlc3Rpb25zID0gW107XG4gICAgICAgICAgICBpZiAoIXMxICYmICFzMiAmJiAhczMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obW9tZW50KHRvZGF5KS5hZGQoKHRoaXMub3B0aW9ucy5mYXZvclBhc3REYXRlcyA/IC0xIDogMSkgKiBpLCBcImRheVwiKSwgXCJcIikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoczEgJiYgIXMyICYmICFzMykge1xuICAgICAgICAgICAgICAgIGlmIChuMSA+IDAgJiYgbjEgPD0gMzEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRWYWxpZERhdGUgPSB0aGlzLmZpbmROZXh0VmFsaWREYXRlKHsgeWVhcjogdG9kYXkueWVhcigpLCBtb250aDogdG9kYXkubW9udGgoKSwgZGF5OiBuMSB9LCBmdW5jdGlvbiAoY3VycmVudERhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeWVhcjogY3VycmVudERhdGUueWVhciArIChfdGhpcy5vcHRpb25zLmZhdm9yUGFzdERhdGVzID8gKGN1cnJlbnREYXRlLm1vbnRoID09IDAgPyAtMSA6IDApIDogKGN1cnJlbnREYXRlLm1vbnRoID09IDExID8gMSA6IDApKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb250aDogbW9kKGN1cnJlbnREYXRlLm1vbnRoICsgKF90aGlzLm9wdGlvbnMuZmF2b3JQYXN0RGF0ZXMgPyAtMSA6IDEpLCAxMiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF5OiBjdXJyZW50RGF0ZS5kYXlcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH0sIHRvZGF5KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5leHRWYWxpZERhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obmV4dFZhbGlkRGF0ZSwgXCJEXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHMxICYmIHMyICYmICFzMykge1xuICAgICAgICAgICAgICAgIGlmIChuMSA8PSAxMiAmJiBuMiA+IDAgJiYgbjIgPD0gMzEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRWYWxpZERhdGUgPSB0aGlzLmZpbmROZXh0VmFsaWREYXRlKHsgeWVhcjogdG9kYXkueWVhcigpLCBtb250aDogbjEgLSAxLCBkYXk6IG4yIH0sIGZ1bmN0aW9uIChjdXJyZW50RGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ZWFyOiBjdXJyZW50RGF0ZS55ZWFyICsgKF90aGlzLm9wdGlvbnMuZmF2b3JQYXN0RGF0ZXMgPyAtMSA6IDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vbnRoOiBjdXJyZW50RGF0ZS5tb250aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXk6IGN1cnJlbnREYXRlLmRheVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfSwgdG9kYXkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV4dFZhbGlkRGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihuZXh0VmFsaWREYXRlLCBcIk1EXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobjIgPD0gMTIgJiYgbjEgPiAwICYmIG4xIDw9IDMxKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXh0VmFsaWREYXRlID0gdGhpcy5maW5kTmV4dFZhbGlkRGF0ZSh7IHllYXI6IHRvZGF5LnllYXIoKSwgbW9udGg6IG4yIC0gMSwgZGF5OiBuMSB9LCBmdW5jdGlvbiAoY3VycmVudERhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeWVhcjogY3VycmVudERhdGUueWVhciArIChfdGhpcy5vcHRpb25zLmZhdm9yUGFzdERhdGVzID8gLTEgOiAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb250aDogY3VycmVudERhdGUubW9udGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF5OiBjdXJyZW50RGF0ZS5kYXlcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH0sIHRvZGF5KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5leHRWYWxpZERhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obmV4dFZhbGlkRGF0ZSwgXCJETVwiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgbW9tID0gdm9pZCAwO1xuICAgICAgICAgICAgICAgIG1vbSA9IG1vbWVudChbbnVtYmVyVG9ZZWFyKG4xKSwgbjIgLSAxLCBzM10pO1xuICAgICAgICAgICAgICAgIGlmIChtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obW9tLCBcIllNRFwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1vbSA9IG1vbWVudChbbnVtYmVyVG9ZZWFyKG4xKSwgbjMgLSAxLCBzMl0pO1xuICAgICAgICAgICAgICAgIGlmIChtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obW9tLCBcIllETVwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1vbSA9IG1vbWVudChbbnVtYmVyVG9ZZWFyKG4yKSwgbjEgLSAxLCBzM10pO1xuICAgICAgICAgICAgICAgIGlmIChtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obW9tLCBcIk1ZRFwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1vbSA9IG1vbWVudChbbnVtYmVyVG9ZZWFyKG4yKSwgbjMgLSAxLCBzMV0pO1xuICAgICAgICAgICAgICAgIGlmIChtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obW9tLCBcIkRZTVwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1vbSA9IG1vbWVudChbbnVtYmVyVG9ZZWFyKG4zKSwgbjEgLSAxLCBzMl0pO1xuICAgICAgICAgICAgICAgIGlmIChtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obW9tLCBcIk1EWVwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1vbSA9IG1vbWVudChbbnVtYmVyVG9ZZWFyKG4zKSwgbjIgLSAxLCBzMV0pO1xuICAgICAgICAgICAgICAgIGlmIChtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVN1Z2dlc3Rpb24obW9tLCBcIkRNWVwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN1Z2dlc3Rpb25zO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5wcm90b3R5cGUuZmluZE5leHRWYWxpZERhdGUgPSBmdW5jdGlvbiAoc3RhcnREYXRlLCBpbmNlbWVudG9yLCB0b2RheSkge1xuICAgICAgICAgICAgdmFyIGN1cnJlbnREYXRlID0gc3RhcnREYXRlO1xuICAgICAgICAgICAgdmFyIG1vbWVudEluTmV4dE1vbnRoID0gbW9tZW50KHN0YXJ0RGF0ZSk7XG4gICAgICAgICAgICB2YXIgbnVtYmVyT2ZJdGVyYXRpb25zID0gMDtcbiAgICAgICAgICAgIHdoaWxlICghKG1vbWVudEluTmV4dE1vbnRoLmlzVmFsaWQoKSAmJiB0aGlzLnRvZGF5T3JGYXZvcml0ZURpcmVjdGlvbihtb21lbnRJbk5leHRNb250aCwgdG9kYXkpKSAmJiBudW1iZXJPZkl0ZXJhdGlvbnMgPCA0KSB7XG4gICAgICAgICAgICAgICAgY3VycmVudERhdGUgPSBpbmNlbWVudG9yKGN1cnJlbnREYXRlKTtcbiAgICAgICAgICAgICAgICBtb21lbnRJbk5leHRNb250aCA9IG1vbWVudChjdXJyZW50RGF0ZSk7XG4gICAgICAgICAgICAgICAgbnVtYmVyT2ZJdGVyYXRpb25zKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbW9tZW50SW5OZXh0TW9udGguaXNWYWxpZCgpID8gbW9tZW50SW5OZXh0TW9udGggOiBudWxsO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lO1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUgPSBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmU7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIm1vbWVudFwiLCBcIm11c3RhY2hlXCIsIFwiLi9Ucml2aWFsQ29yZVwiLCBcIi4vVHJpdmlhbEV2ZW50XCIsIFwiLi9Ucml2aWFsTGlzdEJveFwiLCBcIi4vVHJpdmlhbENhbGVuZGFyQm94XCIsIFwiLi9Ucml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmVcIiwgXCIuL1RyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZVwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBtb21lbnQgPSByZXF1aXJlKFwibW9tZW50XCIpO1xuICAgIHZhciBNdXN0YWNoZSA9IHJlcXVpcmUoXCJtdXN0YWNoZVwiKTtcbiAgICB2YXIgVHJpdmlhbENvcmVfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxDb3JlXCIpO1xuICAgIHZhciBUcml2aWFsRXZlbnRfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxFdmVudFwiKTtcbiAgICB2YXIgVHJpdmlhbExpc3RCb3hfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxMaXN0Qm94XCIpO1xuICAgIHZhciBUcml2aWFsQ2FsZW5kYXJCb3hfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxDYWxlbmRhckJveFwiKTtcbiAgICB2YXIgVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lXzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmVcIik7XG4gICAgdmFyIFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lXCIpO1xuICAgIHZhciBNb2RlO1xuICAgIChmdW5jdGlvbiAoTW9kZSkge1xuICAgICAgICBNb2RlW01vZGVbXCJNT0RFX0NBTEVOREFSXCJdID0gMF0gPSBcIk1PREVfQ0FMRU5EQVJcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiTU9ERV9EQVRFX0xJU1RcIl0gPSAxXSA9IFwiTU9ERV9EQVRFX0xJU1RcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiTU9ERV9USU1FX0xJU1RcIl0gPSAyXSA9IFwiTU9ERV9USU1FX0xJU1RcIjtcbiAgICB9KShNb2RlIHx8IChNb2RlID0ge30pKTtcbiAgICB2YXIgVHJpdmlhbERhdGVUaW1lRmllbGQgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsRGF0ZVRpbWVGaWVsZChvcmlnaW5hbElucHV0LCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuZGF0ZUljb25UZW1wbGF0ZSA9IFwiPHN2ZyB2aWV3Qm94PVxcXCIwIDAgNTQwIDU0MFxcXCIgd2lkdGg9XFxcIjIyXFxcIiBoZWlnaHQ9XFxcIjIyXFxcIiBjbGFzcz1cXFwiY2FsZW5kYXItaWNvblxcXCI+XFxuICAgIDxkZWZzPlxcbiAgICAgICAgPGxpbmVhckdyYWRpZW50IGlkPVxcXCJHcmFkaWVudDFcXFwiIHgxPVxcXCIwXFxcIiB4Mj1cXFwiMFxcXCIgeTE9XFxcIjBcXFwiIHkyPVxcXCIxXFxcIj5cXG4gICAgICAgICAgICA8c3RvcCBjbGFzcz1cXFwiY2FsZW5kYXItc3ltYm9sLXJpbmctZ3JhZGllbnQtc3RvcDFcXFwiIG9mZnNldD1cXFwiMCVcXFwiLz5cXG4gICAgICAgICAgICA8c3RvcCBjbGFzcz1cXFwiY2FsZW5kYXItc3ltYm9sLXJpbmctZ3JhZGllbnQtc3RvcDJcXFwiIG9mZnNldD1cXFwiNTAlXFxcIi8+XFxuICAgICAgICAgICAgPHN0b3AgY2xhc3M9XFxcImNhbGVuZGFyLXN5bWJvbC1yaW5nLWdyYWRpZW50LXN0b3AzXFxcIiBvZmZzZXQ9XFxcIjEwMCVcXFwiLz5cXG4gICAgICAgIDwvbGluZWFyR3JhZGllbnQ+XFxuICAgIDwvZGVmcz4gICAgICAgIFxcbiAgICA8ZyBpZD1cXFwibGF5ZXIxXFxcIj5cXG4gICAgICAgIDxyZWN0IGNsYXNzPVxcXCJjYWxlbmRhci1zeW1ib2wtcGFnZS1iYWNrZ3JvdW5kXFxcIiB4PVxcXCI5MFxcXCIgeT1cXFwiOTBcXFwiIHdpZHRoPVxcXCIzNjBcXFwiIGhlaWdodD1cXFwiNDAwXFxcIiByeT1cXFwiMy44XFxcIj48L3JlY3Q+XFxuICAgICAgICA8cmVjdCBjbGFzcz1cXFwiY2FsZW5kYXItc3ltYm9sLWNvbG9yXFxcIiB4PVxcXCI5MFxcXCIgeT1cXFwiOTBcXFwiIHdpZHRoPVxcXCIzNjBcXFwiIGhlaWdodD1cXFwiMTAwXFxcIiByeT1cXFwiMy41XFxcIj48L3JlY3Q+XFxuICAgICAgICA8cmVjdCBjbGFzcz1cXFwiY2FsZW5kYXItc3ltYm9sLXBhZ2VcXFwiIHg9XFxcIjkwXFxcIiB5PVxcXCI5MFxcXCIgd2lkdGg9XFxcIjM2MFxcXCIgaGVpZ2h0PVxcXCIzOTVcXFwiIHJ5PVxcXCIzLjhcXFwiPjwvcmVjdD5cXG4gICAgICAgIDxyZWN0IGNsYXNzPVxcXCJjYWxlbmRhci1zeW1ib2wtcmluZ1xcXCIgZmlsbD1cXFwidXJsKCNHcmFkaWVudDIpXFxcIiB4PVxcXCIxNDBcXFwiIHk9XFxcIjMwXFxcIiB3aWR0aD1cXFwiNDBcXFwiIGhlaWdodD1cXFwiMTIwXFxcIiByeT1cXFwiMzAuOFxcXCI+PC9yZWN0PlxcbiAgICAgICAgPHJlY3QgY2xhc3M9XFxcImNhbGVuZGFyLXN5bWJvbC1yaW5nXFxcIiBmaWxsPVxcXCJ1cmwoI0dyYWRpZW50MilcXFwiIHg9XFxcIjI1MFxcXCIgeT1cXFwiMzBcXFwiIHdpZHRoPVxcXCI0MFxcXCIgaGVpZ2h0PVxcXCIxMjBcXFwiIHJ5PVxcXCIzMC44XFxcIj48L3JlY3Q+XFxuICAgICAgICA8cmVjdCBjbGFzcz1cXFwiY2FsZW5kYXItc3ltYm9sLXJpbmdcXFwiIGZpbGw9XFxcInVybCgjR3JhZGllbnQyKVxcXCIgeD1cXFwiMzYwXFxcIiB5PVxcXCIzMFxcXCIgd2lkdGg9XFxcIjQwXFxcIiBoZWlnaHQ9XFxcIjEyMFxcXCIgcnk9XFxcIjMwLjhcXFwiPjwvcmVjdD5cXG4gICAgICAgIDx0ZXh0IGNsYXNzPVxcXCJjYWxlbmRhci1zeW1ib2wtZGF0ZVxcXCIgeD1cXFwiMjcwXFxcIiB5PVxcXCI0MTVcXFwiIHRleHQtYW5jaG9yPVxcXCJtaWRkbGVcXFwiPnt7d2Vla0RheX19PC90ZXh0PlxcbiAgICA8L2c+XFxuPC9zdmc+XCI7XG4gICAgICAgICAgICB0aGlzLmRhdGVUZW1wbGF0ZSA9ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtaWNvbi1zaW5nbGUtbGluZVwiPidcbiAgICAgICAgICAgICAgICArIHRoaXMuZGF0ZUljb25UZW1wbGF0ZVxuICAgICAgICAgICAgICAgICsgJzxkaXYgY2xhc3M9XCJjb250ZW50LXdyYXBwZXIgdHItZWRpdG9yLWFyZWFcIj57e2Rpc3BsYXlTdHJpbmd9fTwvZGl2PidcbiAgICAgICAgICAgICAgICArICc8L2Rpdj4nO1xuICAgICAgICAgICAgdGhpcy50aW1lSWNvblRlbXBsYXRlID0gJzxzdmcgY2xhc3M9XCJjbG9jay1pY29uIG5pZ2h0LXt7aXNOaWdodH19XCIgdmlld0JveD1cIjAgMCAxMTAgMTEwXCIgd2lkdGg9XCIyMlwiIGhlaWdodD1cIjIyXCI+ICcgK1xuICAgICAgICAgICAgICAgICc8Y2lyY2xlIGNsYXNzPVwiY2xvY2tjaXJjbGVcIiBjeD1cIjU1XCIgY3k9XCI1NVwiIHI9XCI0NVwiLz4nICtcbiAgICAgICAgICAgICAgICAnPGcgY2xhc3M9XCJoYW5kc1wiPicgK1xuICAgICAgICAgICAgICAgICcgPGxpbmUgY2xhc3M9XCJob3VyaGFuZFwiIHgxPVwiNTVcIiB5MT1cIjU1XCIgeDI9XCI1NVwiIHkyPVwiMzVcIiB7eyNob3VyQW5nbGV9fXRyYW5zZm9ybT1cInJvdGF0ZSh7e2hvdXJBbmdsZX19LDU1LDU1KVwie3svaG91ckFuZ2xlfX0vPiAnICtcbiAgICAgICAgICAgICAgICAnIDxsaW5lIGNsYXNzPVwibWludXRlaGFuZFwiIHgxPVwiNTVcIiB5MT1cIjU1XCIgeDI9XCI1NVwiIHkyPVwiMjJcIiB7eyNtaW51dGVBbmdsZX19dHJhbnNmb3JtPVwicm90YXRlKHt7bWludXRlQW5nbGV9fSw1NSw1NSlcInt7L21pbnV0ZUFuZ2xlfX0vPicgK1xuICAgICAgICAgICAgICAgICc8L2c+ICcgK1xuICAgICAgICAgICAgICAgICc8L3N2Zz4nO1xuICAgICAgICAgICAgdGhpcy50aW1lVGVtcGxhdGUgPSAnPGRpdiBjbGFzcz1cInRyLXRlbXBsYXRlLWljb24tc2luZ2xlLWxpbmVcIj4nICtcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVJY29uVGVtcGxhdGUgK1xuICAgICAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJjb250ZW50LXdyYXBwZXIgdHItZWRpdG9yLWFyZWFcIj57e2Rpc3BsYXlTdHJpbmd9fTwvZGl2PicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmRhdGVWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnRpbWVWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmZvY3VzR29lc1RvT3RoZXJFZGl0b3IgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuYXV0b0NvbXBsZXRlVGltZW91dElkID0gLTE7XG4gICAgICAgICAgICB0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5jYWxlbmRhckJveEluaXRpYWxpemVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmRyb3BEb3duTW9kZSA9IE1vZGUuTU9ERV9DQUxFTkRBUjtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgdGhpcy5jb25maWcgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgZGF0ZUZvcm1hdDogXCJNTS9ERC9ZWVlZXCIsXG4gICAgICAgICAgICAgICAgdGltZUZvcm1hdDogXCJISDptbVwiLFxuICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGVEZWxheTogMCxcbiAgICAgICAgICAgICAgICBzaG93VHJpZ2dlcjogdHJ1ZSxcbiAgICAgICAgICAgICAgICBlZGl0aW5nTW9kZTogXCJlZGl0YWJsZVwiXG4gICAgICAgICAgICB9LCBvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQgPSAkKG9yaWdpbmFsSW5wdXQpLmFkZENsYXNzKFwidHItb3JpZ2luYWwtaW5wdXRcIik7XG4gICAgICAgICAgICB0aGlzLiRkYXRlVGltZUZpZWxkID0gJCgnPGRpdiBjbGFzcz1cInRyLWRhdGV0aW1lZmllbGQgdHItaW5wdXQtd3JhcHBlclwiLz4nKVxuICAgICAgICAgICAgICAgIC5hZGRDbGFzcyh0aGlzLmNvbmZpZy5lZGl0aW5nTW9kZSlcbiAgICAgICAgICAgICAgICAuaW5zZXJ0QWZ0ZXIodGhpcy4kb3JpZ2luYWxJbnB1dCk7XG4gICAgICAgICAgICB2YXIgJGVkaXRvcldyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItZWRpdG9yLXdyYXBwZXJcIj4nKS5hcHBlbmRUbyh0aGlzLiRkYXRlVGltZUZpZWxkKTtcbiAgICAgICAgICAgIHRoaXMuJGRhdGVJY29uV3JhcHBlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1kYXRlLWljb24td3JhcHBlclwiLz4nKS5hcHBlbmRUbygkZWRpdG9yV3JhcHBlcik7XG4gICAgICAgICAgICB0aGlzLiRkYXRlRWRpdG9yID0gJCgnPGRpdiBjbGFzcz1cInRyLWRhdGUtZWRpdG9yXCIgY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiLz4nKS5hcHBlbmRUbygkZWRpdG9yV3JhcHBlcik7XG4gICAgICAgICAgICB0aGlzLiR0aW1lSWNvbldyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItdGltZS1pY29uLXdyYXBwZXJcIi8+JykuYXBwZW5kVG8oJGVkaXRvcldyYXBwZXIpO1xuICAgICAgICAgICAgdGhpcy4kdGltZUVkaXRvciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10aW1lLWVkaXRvclwiIGNvbnRlbnRlZGl0YWJsZT1cInRydWVcIi8+JykuYXBwZW5kVG8oJGVkaXRvcldyYXBwZXIpO1xuICAgICAgICAgICAgdGhpcy4kZGF0ZUljb25XcmFwcGVyLmNsaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy4kYWN0aXZlRWRpdG9yID0gX3RoaXMuJGRhdGVFZGl0b3I7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2V0RHJvcERvd25Nb2RlKE1vZGUuTU9ERV9DQUxFTkRBUik7XG4gICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuJGRhdGVFZGl0b3JbMF0sIDAsIF90aGlzLiRkYXRlRWRpdG9yLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiR0aW1lSWNvbldyYXBwZXIuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLiRhY3RpdmVFZGl0b3IgPSBfdGhpcy4kdGltZUVkaXRvcjtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZXREcm9wRG93bk1vZGUoTW9kZS5NT0RFX0NBTEVOREFSKTtcbiAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy4kdGltZUVkaXRvclswXSwgMCwgX3RoaXMuJHRpbWVFZGl0b3IudGV4dCgpLmxlbmd0aCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGRhdGVFZGl0b3IuZm9jdXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLiRhY3RpdmVFZGl0b3IgPSBfdGhpcy4kZGF0ZUVkaXRvcjtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50IHx8IF90aGlzLmZvY3VzR29lc1RvT3RoZXJFZGl0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuJGRhdGVFZGl0b3JbMF0sIDAsIF90aGlzLiRkYXRlRWRpdG9yLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kdGltZUVkaXRvci5mb2N1cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuJGFjdGl2ZUVkaXRvciA9IF90aGlzLiR0aW1lRWRpdG9yO1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgfHwgX3RoaXMuZm9jdXNHb2VzVG9PdGhlckVkaXRvcikge1xuICAgICAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy4kdGltZUVkaXRvclswXSwgMCwgX3RoaXMuJHRpbWVFZGl0b3IudGV4dCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuc2hvd1RyaWdnZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHRyaWdnZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItdHJpZ2dlclwiPjxzcGFuIGNsYXNzPVwidHItdHJpZ2dlci1pY29uXCIvPjwvZGl2PicpLmFwcGVuZFRvKHRoaXMuJGRhdGVUaW1lRmllbGQpO1xuICAgICAgICAgICAgICAgICR0cmlnZ2VyLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0RHJvcERvd25Nb2RlKE1vZGUuTU9ERV9DQUxFTkRBUik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2FsZW5kYXJCb3guc2V0U2VsZWN0ZWREYXRlKF90aGlzLmRhdGVWYWx1ZSA/IF90aGlzLmRhdGVWYWx1ZS5tb21lbnQgOiBtb21lbnQoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGFjdGl2ZUVkaXRvciA9IF90aGlzLiRkYXRlRWRpdG9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKF90aGlzLiRkYXRlRWRpdG9yWzBdLCAwLCBfdGhpcy4kZGF0ZUVkaXRvci50ZXh0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93biA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1kcm9wZG93blwiPjwvZGl2PicpXG4gICAgICAgICAgICAgICAgLnNjcm9sbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmRyb3Bkb3duTmVlZGVkID0gdGhpcy5jb25maWcuZWRpdGluZ01vZGUgPT0gJ2VkaXRhYmxlJztcbiAgICAgICAgICAgIGlmICh0aGlzLmRyb3Bkb3duTmVlZGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZHJvcERvd24uYXBwZW5kVG8oXCJib2R5XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyICRkYXRlTGlzdEJveCA9ICQoJzxkaXYgY2xhc3M9XCJkYXRlLWxpc3Rib3hcIj4nKS5hcHBlbmRUbyh0aGlzLiRkcm9wRG93bik7XG4gICAgICAgICAgICB0aGlzLmRhdGVMaXN0Qm94ID0gbmV3IFRyaXZpYWxMaXN0Qm94XzEuVHJpdmlhbExpc3RCb3goJGRhdGVMaXN0Qm94LCB7XG4gICAgICAgICAgICAgICAgZW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNdXN0YWNoZS5yZW5kZXIoX3RoaXMuZGF0ZVRlbXBsYXRlLCBlbnRyeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmRhdGVMaXN0Qm94Lm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKHNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXREYXRlKHNlbGVjdGVkRW50cnksIHNlbGVjdGVkRW50cnkuZGlzcGxheVN0cmluZyAhPSAoX3RoaXMuZGF0ZVZhbHVlICYmIF90aGlzLmRhdGVWYWx1ZS5kaXNwbGF5U3RyaW5nKSk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRhdGVMaXN0Qm94LnNldFNlbGVjdGVkRW50cnkobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciAkdGltZUxpc3RCb3ggPSAkKCc8ZGl2IGNsYXNzPVwidGltZS1saXN0Ym94XCI+JykuYXBwZW5kVG8odGhpcy4kZHJvcERvd24pO1xuICAgICAgICAgICAgdGhpcy50aW1lTGlzdEJveCA9IG5ldyBUcml2aWFsTGlzdEJveF8xLlRyaXZpYWxMaXN0Qm94KCR0aW1lTGlzdEJveCwge1xuICAgICAgICAgICAgICAgIGVudHJ5UmVuZGVyaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTXVzdGFjaGUucmVuZGVyKF90aGlzLnRpbWVUZW1wbGF0ZSwgZW50cnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy50aW1lTGlzdEJveC5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmFkZExpc3RlbmVyKGZ1bmN0aW9uIChzZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0VGltZShzZWxlY3RlZEVudHJ5LCBzZWxlY3RlZEVudHJ5LmRpc3BsYXlTdHJpbmcgIT0gKF90aGlzLnRpbWVWYWx1ZSAmJiBfdGhpcy50aW1lVmFsdWUuZGlzcGxheVN0cmluZykpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5kYXRlTGlzdEJveC5zZXRTZWxlY3RlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiRjYWxlbmRhckJveCA9ICQoJzxkaXYgY2xhc3M9XCJjYWxlbmRhcmJveFwiPicpLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duKTtcbiAgICAgICAgICAgIHRoaXMuJGRhdGVFZGl0b3JcbiAgICAgICAgICAgICAgICAuYWRkKHRoaXMuJHRpbWVFZGl0b3IpXG4gICAgICAgICAgICAgICAgLmZvY3VzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy4kZGF0ZVRpbWVGaWVsZC5hZGRDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmJsdXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRhdGVUaW1lRmllbGQucmVtb3ZlQ2xhc3MoJ2ZvY3VzJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmtleWRvd24oZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5pc01vZGlmaWVyS2V5KGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnRhYikge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZWxlY3RIaWdobGlnaHRlZExpc3RCb3hFbnRyeSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5sZWZ0X2Fycm93IHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKCkgPT09IF90aGlzLiR0aW1lRWRpdG9yICYmIGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5sZWZ0X2Fycm93ICYmIHdpbmRvdy5nZXRTZWxlY3Rpb24oKS5mb2N1c09mZnNldCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuJGRhdGVFZGl0b3JbMF0sIDAsIF90aGlzLiRkYXRlRWRpdG9yLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKF90aGlzLmdldEFjdGl2ZUVkaXRvcigpID09PSBfdGhpcy4kZGF0ZUVkaXRvciAmJiBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cgJiYgd2luZG93LmdldFNlbGVjdGlvbigpLmZvY3VzT2Zmc2V0ID09PSBfdGhpcy4kZGF0ZUVkaXRvci50ZXh0KCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy4kdGltZUVkaXRvclswXSwgMCwgX3RoaXMuJHRpbWVFZGl0b3IudGV4dCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmJhY2tzcGFjZSB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZGVsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmRvd25fYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKCkuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgPyAtMSA6IDE7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0RHJvcERvd25Nb2RlKGUuY3VycmVudFRhcmdldCA9PT0gX3RoaXMuJGRhdGVFZGl0b3JbMF0gPyBNb2RlLk1PREVfREFURV9MSVNUIDogTW9kZS5NT0RFX1RJTUVfTElTVCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeShkaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZHJvcERvd25Nb2RlICE9PSBNb2RlLk1PREVfQ0FMRU5EQVIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5nZXRBY3RpdmVCb3goKS5uYXZpZ2F0ZShkaXJlY3Rpb24gPT09IDEgPyAnZG93bicgOiAndXAnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5hdXRvQ29tcGxldGVJZlBvc3NpYmxlKF90aGlzLmNvbmZpZy5hdXRvQ29tcGxldGVEZWxheSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZWxlY3RIaWdobGlnaHRlZExpc3RCb3hFbnRyeSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKClbMF0sIDAsIF90aGlzLmdldEFjdGl2ZUVkaXRvcigpLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lc2NhcGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKF90aGlzLmdldEFjdGl2ZUVkaXRvcigpWzBdLCAwLCBfdGhpcy5nZXRBY3RpdmVFZGl0b3IoKS50ZXh0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXREcm9wRG93bk1vZGUoZS5jdXJyZW50VGFyZ2V0ID09PSBfdGhpcy4kZGF0ZUVkaXRvclswXSA/IE1vZGUuTU9ERV9EQVRFX0xJU1QgOiBNb2RlLk1PREVfVElNRV9MSVNUKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoMSk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQudmFsKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFZhbHVlKG1vbWVudCh0aGlzLiRvcmlnaW5hbElucHV0LnZhbCgpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFZhbHVlKG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZGF0ZUVkaXRvci5hZGQodGhpcy4kdGltZUVkaXRvcikuYXR0cihcInRhYmluZGV4XCIsIHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJhdXRvZm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRkYXRlRWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRkYXRlVGltZUZpZWxkLmFkZCh0aGlzLiRkcm9wRG93bikubW91c2Vkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLiRkYXRlRWRpdG9yLmlzKFwiOmZvY3VzXCIpIHx8IF90aGlzLiR0aW1lRWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGUudGFyZ2V0ID09PSBfdGhpcy4kZGF0ZUVkaXRvclswXVxuICAgICAgICAgICAgICAgICAgICB8fCBlLnRhcmdldCA9PT0gX3RoaXMuJHRpbWVFZGl0b3JbMF1cbiAgICAgICAgICAgICAgICAgICAgfHwgZS50YXJnZXQgPT09IF90aGlzLiRkYXRlSWNvbldyYXBwZXJbMF1cbiAgICAgICAgICAgICAgICAgICAgfHwgZS50YXJnZXQgPT09IF90aGlzLiR0aW1lSWNvbldyYXBwZXJbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZm9jdXNHb2VzVG9PdGhlckVkaXRvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkub24oJ21vdXNldXAgbW91c2VvdXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ICYmICFfdGhpcy5mb2N1c0dvZXNUb090aGVyRWRpdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmdldEFjdGl2ZUVkaXRvcigpLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgX3RoaXMuZm9jdXNHb2VzVG9PdGhlckVkaXRvciA9IGZhbHNlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiRhY3RpdmVFZGl0b3IgPSB0aGlzLiRkYXRlRWRpdG9yO1xuICAgICAgICAgICAgdGhpcy5kYXRlU3VnZ2VzdGlvbkVuZ2luZSA9IG5ldyBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmVfMS5Ucml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUoe1xuICAgICAgICAgICAgICAgIHByZWZlcnJlZERhdGVGb3JtYXQ6IHRoaXMuY29uZmlnLmRhdGVGb3JtYXRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy50aW1lU3VnZ2VzdGlvbkVuZ2luZSA9IG5ldyBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmVfMS5Ucml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUoKTtcbiAgICAgICAgfVxuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuc2V0RHJvcERvd25Nb2RlID0gZnVuY3Rpb24gKG1vZGUpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLmRyb3BEb3duTW9kZSA9IG1vZGU7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FsZW5kYXJCb3hJbml0aWFsaXplZCAmJiBtb2RlID09PSBNb2RlLk1PREVfQ0FMRU5EQVIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGVuZGFyQm94ID0gbmV3IFRyaXZpYWxDYWxlbmRhckJveF8xLlRyaXZpYWxDYWxlbmRhckJveCh0aGlzLiRjYWxlbmRhckJveCwge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdERheU9mV2VlazogMSxcbiAgICAgICAgICAgICAgICAgICAgbW9kZTogJ2RhdGUnXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxlbmRhckJveC5zZXRLZXlib2FyZE5hdmlnYXRpb25TdGF0ZSgnbW9udGgnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGVuZGFyQm94Lm9uQ2hhbmdlLmFkZExpc3RlbmVyKGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBfYS52YWx1ZSwgdGltZVVuaXRFZGl0ZWQgPSBfYS50aW1lVW5pdEVkaXRlZDtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0RGF0ZShUcml2aWFsRGF0ZVRpbWVGaWVsZC5jcmVhdGVEYXRlQ29tYm9Cb3hFbnRyeSh2YWx1ZSwgX3RoaXMuY29uZmlnLmRhdGVGb3JtYXQpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRpbWVVbml0RWRpdGVkID09PSAnZGF5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGFjdGl2ZUVkaXRvciA9IF90aGlzLiR0aW1lRWRpdG9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuJHRpbWVFZGl0b3JbMF0sIDAsIF90aGlzLiR0aW1lRWRpdG9yLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuZmlyZUNoYW5nZUV2ZW50cygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxlbmRhckJveEluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJCb3hJbml0aWFsaXplZCAmJiAkKHRoaXMuY2FsZW5kYXJCb3guZ2V0TWFpbkRvbUVsZW1lbnQoKSkudG9nZ2xlKG1vZGUgPT09IE1vZGUuTU9ERV9DQUxFTkRBUik7XG4gICAgICAgICAgICAkKHRoaXMuZGF0ZUxpc3RCb3guZ2V0TWFpbkRvbUVsZW1lbnQoKSkudG9nZ2xlKG1vZGUgPT09IE1vZGUuTU9ERV9EQVRFX0xJU1QpO1xuICAgICAgICAgICAgJCh0aGlzLnRpbWVMaXN0Qm94LmdldE1haW5Eb21FbGVtZW50KCkpLnRvZ2dsZShtb2RlID09PSBNb2RlLk1PREVfVElNRV9MSVNUKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLmdldEFjdGl2ZUJveCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRyb3BEb3duTW9kZSA9PT0gTW9kZS5NT0RFX0NBTEVOREFSKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJCb3g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmRyb3BEb3duTW9kZSA9PT0gTW9kZS5NT0RFX0RBVEVfTElTVCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGVMaXN0Qm94O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudGltZUxpc3RCb3g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5nZXRBY3RpdmVFZGl0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kYWN0aXZlRWRpdG9yO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuc2VsZWN0SGlnaGxpZ2h0ZWRMaXN0Qm94RW50cnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5kcm9wRG93bk1vZGUgPT09IE1vZGUuTU9ERV9EQVRFX0xJU1QgfHwgdGhpcy5kcm9wRG93bk1vZGUgPT09IE1vZGUuTU9ERV9USU1FX0xJU1QpIHtcbiAgICAgICAgICAgICAgICB2YXIgaGlnaGxpZ2h0ZWRFbnRyeSA9IHRoaXMuZ2V0QWN0aXZlQm94KCkuZ2V0SGlnaGxpZ2h0ZWRFbnRyeSgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25PcGVuICYmIGhpZ2hsaWdodGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZ2V0QWN0aXZlRWRpdG9yKCkgPT09IHRoaXMuJGRhdGVFZGl0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RGF0ZShoaWdobGlnaHRlZEVudHJ5LCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0VGltZShoaWdobGlnaHRlZEVudHJ5LCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24gKGhpZ2hsaWdodERpcmVjdGlvbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBxdWVyeVN0cmluZyA9IF90aGlzLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKCkgPT09IF90aGlzLiRkYXRlRWRpdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlbnRyaWVzID0gX3RoaXMuZGF0ZVN1Z2dlc3Rpb25FbmdpbmUuZ2VuZXJhdGVTdWdnZXN0aW9ucyhxdWVyeVN0cmluZywgbW9tZW50KCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChzKSB7IHJldHVybiBUcml2aWFsRGF0ZVRpbWVGaWVsZC5jcmVhdGVEYXRlQ29tYm9Cb3hFbnRyeShzLm1vbWVudCwgX3RoaXMuY29uZmlnLmRhdGVGb3JtYXQpOyB9KTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRW50cmllcyhlbnRyaWVzLCBoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVudHJpZXMgPSBfdGhpcy50aW1lU3VnZ2VzdGlvbkVuZ2luZS5nZW5lcmF0ZVN1Z2dlc3Rpb25zKHF1ZXJ5U3RyaW5nKVxuICAgICAgICAgICAgICAgICAgICAgICAgLm1hcChmdW5jdGlvbiAocykgeyByZXR1cm4gVHJpdmlhbERhdGVUaW1lRmllbGQuY3JlYXRlVGltZUNvbWJvQm94RW50cnkocy5ob3VyLCBzLm1pbnV0ZSwgX3RoaXMuY29uZmlnLnRpbWVGb3JtYXQpOyB9KTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRW50cmllcyhlbnRyaWVzLCBoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIDApO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuZ2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5kYXRlVmFsdWUgPT0gbnVsbCAmJiB0aGlzLnRpbWVWYWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmRhdGVWYWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLnRpbWVWYWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbWVudChbXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZVZhbHVlLnllYXIsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZVZhbHVlLm1vbnRoIC0gMSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlVmFsdWUuZGF5XG4gICAgICAgICAgICAgICAgXSkuc3RhcnRPZignZGF5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9tZW50KFtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlVmFsdWUueWVhcixcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlVmFsdWUubW9udGggLSAxLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGVWYWx1ZS5kYXksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGltZVZhbHVlLmhvdXIsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGltZVZhbHVlLm1pbnV0ZVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5maXJlQ2hhbmdlRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZS5maXJlKHRoaXMuZ2V0VmFsdWUoKSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5zZXREYXRlID0gZnVuY3Rpb24gKG5ld0RhdGVWYWx1ZSwgZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50ID09PSB2b2lkIDApIHsgZmlyZUV2ZW50ID0gZmFsc2U7IH1cbiAgICAgICAgICAgIHRoaXMuZGF0ZVZhbHVlID0gbmV3RGF0ZVZhbHVlO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5zZXRUaW1lID0gZnVuY3Rpb24gKG5ld1RpbWVWYWx1ZSwgZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50ID09PSB2b2lkIDApIHsgZmlyZUV2ZW50ID0gZmFsc2U7IH1cbiAgICAgICAgICAgIHRoaXMudGltZVZhbHVlID0gbmV3VGltZVZhbHVlO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS51cGRhdGVEaXNwbGF5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZGF0ZVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZGF0ZUVkaXRvci50ZXh0KG1vbWVudChbdGhpcy5kYXRlVmFsdWUueWVhciwgdGhpcy5kYXRlVmFsdWUubW9udGggLSAxLCB0aGlzLmRhdGVWYWx1ZS5kYXldKS5mb3JtYXQodGhpcy5jb25maWcuZGF0ZUZvcm1hdCkpO1xuICAgICAgICAgICAgICAgIHRoaXMuJGRhdGVJY29uV3JhcHBlci5lbXB0eSgpLmFwcGVuZChNdXN0YWNoZS5yZW5kZXIodGhpcy5kYXRlSWNvblRlbXBsYXRlLCB0aGlzLmRhdGVWYWx1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZGF0ZUVkaXRvci50ZXh0KFwiXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuJGRhdGVJY29uV3JhcHBlci5lbXB0eSgpLmFwcGVuZChNdXN0YWNoZS5yZW5kZXIodGhpcy5kYXRlSWNvblRlbXBsYXRlLCB7fSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMudGltZVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kdGltZUVkaXRvci50ZXh0KG1vbWVudChbMTk3MCwgMCwgMSwgdGhpcy50aW1lVmFsdWUuaG91ciwgdGhpcy50aW1lVmFsdWUubWludXRlXSkuZm9ybWF0KHRoaXMuY29uZmlnLnRpbWVGb3JtYXQpKTtcbiAgICAgICAgICAgICAgICB0aGlzLiR0aW1lSWNvbldyYXBwZXIuZW1wdHkoKS5hcHBlbmQoTXVzdGFjaGUucmVuZGVyKHRoaXMudGltZUljb25UZW1wbGF0ZSwgdGhpcy50aW1lVmFsdWUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuJHRpbWVFZGl0b3IudGV4dChcIlwiKTtcbiAgICAgICAgICAgICAgICB0aGlzLiR0aW1lSWNvbldyYXBwZXIuZW1wdHkoKS5hcHBlbmQoTXVzdGFjaGUucmVuZGVyKHRoaXMudGltZUljb25UZW1wbGF0ZSwge30pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKG1vbSkge1xuICAgICAgICAgICAgdGhpcy5zZXREYXRlKG1vbSAmJiBUcml2aWFsRGF0ZVRpbWVGaWVsZC5jcmVhdGVEYXRlQ29tYm9Cb3hFbnRyeShtb20sIHRoaXMuY29uZmlnLmRhdGVGb3JtYXQpKTtcbiAgICAgICAgICAgIHRoaXMuc2V0VGltZShtb20gJiYgVHJpdmlhbERhdGVUaW1lRmllbGQuY3JlYXRlVGltZUNvbWJvQm94RW50cnkobW9tLmhvdXIoKSwgbW9tLm1pbnV0ZSgpLCB0aGlzLmNvbmZpZy50aW1lRm9ybWF0KSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5yZXBvc2l0aW9uRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd25cbiAgICAgICAgICAgICAgICAuc2hvdygpXG4gICAgICAgICAgICAgICAgLnBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICBteTogXCJsZWZ0IHRvcFwiLFxuICAgICAgICAgICAgICAgIGF0OiBcImxlZnQgYm90dG9tXCIsXG4gICAgICAgICAgICAgICAgb2Y6IHRoaXMuJGRhdGVUaW1lRmllbGQsXG4gICAgICAgICAgICAgICAgY29sbGlzaW9uOiBcImZsaXBcIixcbiAgICAgICAgICAgICAgICB1c2luZzogZnVuY3Rpb24gKGNhbGN1bGF0ZWRQb3NpdGlvbiwgaW5mbykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5mby52ZXJ0aWNhbCA9PT0gXCJ0b3BcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRhdGVUaW1lRmllbGQucmVtb3ZlQ2xhc3MoXCJkcm9wZG93bi1mbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLnJlbW92ZUNsYXNzKFwiZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRkYXRlVGltZUZpZWxkLmFkZENsYXNzKFwiZHJvcGRvd24tZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5hZGRDbGFzcyhcImZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLmNzcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiBjYWxjdWxhdGVkUG9zaXRpb24ubGVmdCArICdweCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IGNhbGN1bGF0ZWRQb3NpdGlvbi50b3AgKyAncHgnXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLndpZHRoKHRoaXMuJGRhdGVUaW1lRmllbGQud2lkdGgoKSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5vcGVuRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5kcm9wZG93bk5lZWRlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGRhdGVUaW1lRmllbGQuYWRkQ2xhc3MoXCJvcGVuXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5jbG9zZURyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kZGF0ZVRpbWVGaWVsZC5yZW1vdmVDbGFzcyhcIm9wZW5cIik7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5oaWRlKCk7XG4gICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVkaXRvclRleHQgPSB0aGlzLmdldEFjdGl2ZUVkaXRvcigpLnRleHQoKS5yZXBsYWNlKFN0cmluZy5mcm9tQ2hhckNvZGUoMTYwKSwgXCIgXCIpO1xuICAgICAgICAgICAgdmFyIHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgICAgIGlmIChzZWxlY3Rpb24uYW5jaG9yT2Zmc2V0ICE9IHNlbGVjdGlvbi5mb2N1c09mZnNldCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlZGl0b3JUZXh0LnN1YnN0cmluZygwLCBNYXRoLm1pbihzZWxlY3Rpb24uYW5jaG9yT2Zmc2V0LCBzZWxlY3Rpb24uZm9jdXNPZmZzZXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBlZGl0b3JUZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuYXV0b0NvbXBsZXRlSWZQb3NzaWJsZSA9IGZ1bmN0aW9uIChkZWxheSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5hdXRvQ29tcGxldGUgJiYgKHRoaXMuZHJvcERvd25Nb2RlID09PSBNb2RlLk1PREVfREFURV9MSVNUIHx8IHRoaXMuZHJvcERvd25Nb2RlID09PSBNb2RlLk1PREVfVElNRV9MSVNUKSkge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmF1dG9Db21wbGV0ZVRpbWVvdXRJZCk7XG4gICAgICAgICAgICAgICAgdmFyIGxpc3RCb3ggPSB0aGlzLmdldEFjdGl2ZUJveCgpO1xuICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gbGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgaWYgKGhpZ2hsaWdodGVkRW50cnkgJiYgdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGF1dG9Db21wbGV0aW5nRW50cnlEaXNwbGF5VmFsdWVfMSA9IGhpZ2hsaWdodGVkRW50cnkuZGlzcGxheVN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGF1dG9Db21wbGV0aW5nRW50cnlEaXNwbGF5VmFsdWVfMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVUaW1lb3V0SWQgPSB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9sZEVkaXRvclZhbHVlID0gX3RoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdFZGl0b3JWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXV0b0NvbXBsZXRpbmdFbnRyeURpc3BsYXlWYWx1ZV8xLnRvTG93ZXJDYXNlKCkuaW5kZXhPZihvbGRFZGl0b3JWYWx1ZS50b0xvd2VyQ2FzZSgpKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdFZGl0b3JWYWx1ZSA9IG9sZEVkaXRvclZhbHVlICsgYXV0b0NvbXBsZXRpbmdFbnRyeURpc3BsYXlWYWx1ZV8xLnN1YnN0cihvbGRFZGl0b3JWYWx1ZS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3RWRpdG9yVmFsdWUgPSBfdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmdldEFjdGl2ZUVkaXRvcigpLnRleHQobmV3RWRpdG9yVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5nZXRBY3RpdmVFZGl0b3IoKS5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy5nZXRBY3RpdmVFZGl0b3IoKVswXSwgb2xkRWRpdG9yVmFsdWUubGVuZ3RoLCBuZXdFZGl0b3JWYWx1ZS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIGRlbGF5IHx8IDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS51cGRhdGVFbnRyaWVzID0gZnVuY3Rpb24gKG5ld0VudHJpZXMsIGhpZ2hsaWdodERpcmVjdGlvbikge1xuICAgICAgICAgICAgdmFyIGxpc3RCb3ggPSB0aGlzLmdldEFjdGl2ZUJveCgpO1xuICAgICAgICAgICAgaGlnaGxpZ2h0RGlyZWN0aW9uID0gaGlnaGxpZ2h0RGlyZWN0aW9uID09PSB1bmRlZmluZWQgPyAxIDogaGlnaGxpZ2h0RGlyZWN0aW9uO1xuICAgICAgICAgICAgbGlzdEJveC51cGRhdGVFbnRyaWVzKG5ld0VudHJpZXMpO1xuICAgICAgICAgICAgbGlzdEJveC5oaWdobGlnaHRUZXh0TWF0Y2hlcyh0aGlzLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUoKSk7XG4gICAgICAgICAgICBsaXN0Qm94LmhpZ2hsaWdodE5leHRFbnRyeShoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVJZlBvc3NpYmxlKHRoaXMuY29uZmlnLmF1dG9Db21wbGV0ZURlbGF5KTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQuY3JlYXRlVGltZUNvbWJvQm94RW50cnkgPSBmdW5jdGlvbiAoaG91ciwgbWludXRlLCB0aW1lRm9ybWF0KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGhvdXI6IGhvdXIsXG4gICAgICAgICAgICAgICAgbWludXRlOiBtaW51dGUsXG4gICAgICAgICAgICAgICAgaG91clN0cmluZzogVHJpdmlhbERhdGVUaW1lRmllbGQucGFkKGhvdXIsIDIpLFxuICAgICAgICAgICAgICAgIG1pbnV0ZVN0cmluZzogVHJpdmlhbERhdGVUaW1lRmllbGQucGFkKG1pbnV0ZSwgMiksXG4gICAgICAgICAgICAgICAgZGlzcGxheVN0cmluZzogbW9tZW50KCkuaG91cihob3VyKS5taW51dGUobWludXRlKS5mb3JtYXQodGltZUZvcm1hdCksXG4gICAgICAgICAgICAgICAgaG91ckFuZ2xlOiAoKGhvdXIgJSAxMikgKyBtaW51dGUgLyA2MCkgKiAzMCxcbiAgICAgICAgICAgICAgICBtaW51dGVBbmdsZTogbWludXRlICogNixcbiAgICAgICAgICAgICAgICBpc05pZ2h0OiBob3VyIDwgNiB8fCBob3VyID49IDIwXG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wYWQgPSBmdW5jdGlvbiAobnVtLCBzaXplKSB7XG4gICAgICAgICAgICB2YXIgcyA9IG51bSArIFwiXCI7XG4gICAgICAgICAgICB3aGlsZSAocy5sZW5ndGggPCBzaXplKVxuICAgICAgICAgICAgICAgIHMgPSBcIjBcIiArIHM7XG4gICAgICAgICAgICByZXR1cm4gcztcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQuY3JlYXRlRGF0ZUNvbWJvQm94RW50cnkgPSBmdW5jdGlvbiAobSwgZGF0ZUZvcm1hdCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBtb21lbnQ6IG0sXG4gICAgICAgICAgICAgICAgZGF5OiBtLmRhdGUoKSxcbiAgICAgICAgICAgICAgICB3ZWVrRGF5OiBtLmZvcm1hdCgnZGQnKSxcbiAgICAgICAgICAgICAgICBtb250aDogbS5tb250aCgpICsgMSxcbiAgICAgICAgICAgICAgICB5ZWFyOiBtLnllYXIoKSxcbiAgICAgICAgICAgICAgICBkaXNwbGF5U3RyaW5nOiBtLmZvcm1hdChkYXRlRm9ybWF0KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHModGhpcy5nZXRBY3RpdmVFZGl0b3IoKVswXSwgMCwgdGhpcy5nZXRBY3RpdmVFZGl0b3IoKS50ZXh0KCkubGVuZ3RoKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnJlbW92ZUNsYXNzKCd0ci1vcmlnaW5hbC1pbnB1dCcpLmluc2VydEJlZm9yZSh0aGlzLiRkYXRlVGltZUZpZWxkKTtcbiAgICAgICAgICAgIHRoaXMuJGRhdGVUaW1lRmllbGQucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5yZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLmdldE1haW5Eb21FbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGRhdGVUaW1lRmllbGRbMF07XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBUcml2aWFsRGF0ZVRpbWVGaWVsZDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbERhdGVUaW1lRmllbGQgPSBUcml2aWFsRGF0ZVRpbWVGaWVsZDtcbn0pO1xuXG5cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgVHJpdmlhbEV2ZW50ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gVHJpdmlhbEV2ZW50KGV2ZW50U291cmNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U291cmNlID0gZXZlbnRTb3VyY2U7XG4gICAgICAgICAgICB0aGlzLmxpc3RlbmVycyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIFRyaXZpYWxFdmVudC5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzLnB1c2goZm4pO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxFdmVudC5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIHZhciBsaXN0ZW5lckluZGV4ID0gdGhpcy5saXN0ZW5lcnMuaW5kZXhPZihmbik7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJJbmRleCAhPSAtMSkge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzLnNwbGljZShsaXN0ZW5lckluZGV4LCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsRXZlbnQucHJvdG90eXBlLmZpcmUgPSBmdW5jdGlvbiAoZXZlbnRPYmplY3QsIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5saXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3RlbmVyc1tpXS5jYWxsKHRoaXMubGlzdGVuZXJzW2ldLCBldmVudE9iamVjdCwgdGhpcy5ldmVudFNvdXJjZSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgcmV0dXJuIFRyaXZpYWxFdmVudDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbEV2ZW50ID0gVHJpdmlhbEV2ZW50O1xufSk7XG5cblxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIiwgXCJqcXVlcnlcIiwgXCJtdXN0YWNoZVwiLCBcIi4vVHJpdmlhbENvcmVcIiwgXCIuL1RyaXZpYWxFdmVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBNdXN0YWNoZSA9IHJlcXVpcmUoXCJtdXN0YWNoZVwiKTtcbiAgICB2YXIgVHJpdmlhbENvcmVfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxDb3JlXCIpO1xuICAgIHZhciBUcml2aWFsRXZlbnRfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxFdmVudFwiKTtcbiAgICB2YXIgVHJpdmlhbExpc3RCb3ggPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsTGlzdEJveCgkY29udGFpbmVyLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuY29uZmlnID0gJC5leHRlbmQoe1xuICAgICAgICAgICAgICAgIGVudHJ5UmVuZGVyaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSBlbnRyeS50ZW1wbGF0ZSB8fCBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmltYWdlMkxpbmVzVGVtcGxhdGU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNdXN0YWNoZS5yZW5kZXIodGVtcGxhdGUsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnk6IG51bGwsXG4gICAgICAgICAgICAgICAgc3Bpbm5lclRlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHRTcGlubmVyVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgZW50cmllczogbnVsbCxcbiAgICAgICAgICAgICAgICBtYXRjaGluZ09wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hpbmdNb2RlOiAnY29udGFpbnMnLFxuICAgICAgICAgICAgICAgICAgICBpZ25vcmVDYXNlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBtYXhMZXZlbnNodGVpbkRpc3RhbmNlOiAyXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBub0VudHJpZXNUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0Tm9FbnRyaWVzVGVtcGxhdGVcbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy4kbGlzdEJveCA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1saXN0Ym94XCIvPicpLmFwcGVuZFRvKCRjb250YWluZXIpO1xuICAgICAgICAgICAgdmFyIG1lID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuJGxpc3RCb3gub24oXCJtb3VzZWRvd25cIiwgXCIudHItbGlzdGJveC1lbnRyeVwiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIG1lLnNldFNlbGVjdGVkRW50cnkoJCh0aGlzKS5kYXRhKFwiZW50cnlcIiksIGUsIHRydWUpO1xuICAgICAgICAgICAgfSkub24oXCJtb3VzZXVwXCIsIFwiLnRyLWxpc3Rib3gtZW50cnlcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBtZS4kbGlzdEJveC50cmlnZ2VyKFwibW91c2V1cFwiLCBlKTtcbiAgICAgICAgICAgIH0pLm9uKFwibW91c2VlbnRlclwiLCBcIi50ci1saXN0Ym94LWVudHJ5XCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgbWUuc2V0SGlnaGxpZ2h0ZWRFbnRyeSgkKHRoaXMpLmRhdGEoXCJlbnRyeVwiKSk7XG4gICAgICAgICAgICB9KS5vbihcIm1vdXNlbGVhdmVcIiwgXCIudHItbGlzdGJveC1lbnRyeVwiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmICghJChlLnRvRWxlbWVudCkuaXMoJy50ci1saXN0Ym94LWVudHJ5JykpIHtcbiAgICAgICAgICAgICAgICAgICAgbWUuc2V0SGlnaGxpZ2h0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGVudHJ5TGlzdCA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1saXN0Ym94LWVudHJ5LWxpc3RcIj48L2Rpdj4nKS5hcHBlbmRUbyh0aGlzLiRsaXN0Qm94KTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5lbnRyaWVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gdGhpcy5jb25maWcuZW50cmllcztcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUVudHJ5RWxlbWVudHModGhpcy5lbnRyaWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJGxpc3RCb3guZGF0YShcInRyaXZpYWxMaXN0Qm94XCIsIHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIFRyaXZpYWxMaXN0Qm94LnByb3RvdHlwZS51cGRhdGVFbnRyeUVsZW1lbnRzID0gZnVuY3Rpb24gKGVudHJpZXMpIHtcbiAgICAgICAgICAgIHRoaXMuJGVudHJ5TGlzdC5kZXRhY2goKTtcbiAgICAgICAgICAgIHRoaXMuJGVudHJ5TGlzdC5lbXB0eSgpO1xuICAgICAgICAgICAgaWYgKGVudHJpZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZW50cnkgPSBlbnRyaWVzW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgJGVudHJ5ID0gdm9pZCAwO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWVudHJ5Ll90ckVudHJ5RWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGh0bWwgPSB0aGlzLmNvbmZpZy5lbnRyeVJlbmRlcmluZ0Z1bmN0aW9uKGVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRlbnRyeSA9ICQoaHRtbCkuYWRkQ2xhc3MoXCJ0ci1saXN0Ym94LWVudHJ5IGZpbHRlcmFibGUtaXRlbVwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRlbnRyeSA9IGVudHJ5Ll90ckVudHJ5RWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAkZW50cnkuYXBwZW5kVG8odGhpcy4kZW50cnlMaXN0KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmRhdGEoXCJlbnRyeVwiLCBlbnRyeSk7XG4gICAgICAgICAgICAgICAgICAgIGVudHJ5Ll90ckVudHJ5RWxlbWVudCA9ICRlbnRyeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlbnRyeUxpc3QuYXBwZW5kKHRoaXMuY29uZmlnLm5vRW50cmllc1RlbXBsYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJGVudHJ5TGlzdC5hcHBlbmRUbyh0aGlzLiRsaXN0Qm94KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLnVwZGF0ZUVudHJpZXMgPSBmdW5jdGlvbiAobmV3RW50cmllcykge1xuICAgICAgICAgICAgaWYgKG5ld0VudHJpZXMgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG5ld0VudHJpZXMgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2V0SGlnaGxpZ2h0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgIHRoaXMuZW50cmllcyA9IG5ld0VudHJpZXM7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUVudHJ5RWxlbWVudHModGhpcy5lbnRyaWVzKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLm1pbmltYWxseVNjcm9sbFRvID0gZnVuY3Rpb24gKCRlbnRyeVdyYXBwZXIpIHtcbiAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEubWluaW1hbGx5U2Nyb2xsVG8odGhpcy4kbGlzdEJveC5wYXJlbnQoKSwgJGVudHJ5V3JhcHBlcik7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxMaXN0Qm94LnByb3RvdHlwZS5zZXRIaWdobGlnaHRlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICBpZiAoZW50cnkgIT09IHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSA9IGVudHJ5O1xuICAgICAgICAgICAgICAgIHRoaXMuJGVudHJ5TGlzdC5maW5kKCcudHItbGlzdGJveC1lbnRyeScpLnJlbW92ZUNsYXNzKCd0ci1oaWdobGlnaHRlZC1lbnRyeScpO1xuICAgICAgICAgICAgICAgIGlmIChlbnRyeSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGVudHJ5Ll90ckVudHJ5RWxlbWVudC5hZGRDbGFzcygndHItaGlnaGxpZ2h0ZWQtZW50cnknKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5taW5pbWFsbHlTY3JvbGxUbyhlbnRyeS5fdHJFbnRyeUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLmZpcmVDaGFuZ2VFdmVudHMgPSBmdW5jdGlvbiAoc2VsZWN0ZWRFbnRyeSwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgdGhpcy4kbGlzdEJveC50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmZpcmUoc2VsZWN0ZWRFbnRyeSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxMaXN0Qm94LnByb3RvdHlwZS5zZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5LCBvcmlnaW5hbEV2ZW50LCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQgPT09IHZvaWQgMCkgeyBmaXJlRXZlbnQgPSBmYWxzZTsgfVxuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEVudHJ5ID0gZW50cnk7XG4gICAgICAgICAgICB0aGlzLiRlbnRyeUxpc3QuZmluZChcIi50ci1zZWxlY3RlZC1lbnRyeVwiKS5yZW1vdmVDbGFzcyhcInRyLXNlbGVjdGVkLWVudHJ5XCIpO1xuICAgICAgICAgICAgaWYgKGVudHJ5ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cnkuX3RyRW50cnlFbGVtZW50LmFkZENsYXNzKFwidHItc2VsZWN0ZWQtZW50cnlcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKHRoaXMuc2VsZWN0ZWRFbnRyeSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxMaXN0Qm94LnByb3RvdHlwZS5oaWdobGlnaHROZXh0RW50cnkgPSBmdW5jdGlvbiAoZGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgbmV3SGlnaGxpZ2h0ZWRFbnRyeSA9IHRoaXMuZ2V0TmV4dEhpZ2hsaWdodGFibGVFbnRyeShkaXJlY3Rpb24pO1xuICAgICAgICAgICAgaWYgKG5ld0hpZ2hsaWdodGVkRW50cnkgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SGlnaGxpZ2h0ZWRFbnRyeShuZXdIaWdobGlnaHRlZEVudHJ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLmdldE5leHRIaWdobGlnaHRhYmxlRW50cnkgPSBmdW5jdGlvbiAoZGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgbmV3SGlnaGxpZ2h0ZWRFbGVtZW50SW5kZXg7XG4gICAgICAgICAgICBpZiAodGhpcy5lbnRyaWVzID09IG51bGwgfHwgdGhpcy5lbnRyaWVzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmhpZ2hsaWdodGVkRW50cnkgPT0gbnVsbCAmJiBkaXJlY3Rpb24gPiAwKSB7XG4gICAgICAgICAgICAgICAgbmV3SGlnaGxpZ2h0ZWRFbGVtZW50SW5kZXggPSAtMSArIGRpcmVjdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSA9PSBudWxsICYmIGRpcmVjdGlvbiA8IDApIHtcbiAgICAgICAgICAgICAgICBuZXdIaWdobGlnaHRlZEVsZW1lbnRJbmRleCA9IHRoaXMuZW50cmllcy5sZW5ndGggKyBkaXJlY3Rpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEhpZ2hsaWdodGVkRWxlbWVudEluZGV4ID0gdGhpcy5lbnRyaWVzLmluZGV4T2YodGhpcy5oaWdobGlnaHRlZEVudHJ5KTtcbiAgICAgICAgICAgICAgICBuZXdIaWdobGlnaHRlZEVsZW1lbnRJbmRleCA9IChjdXJyZW50SGlnaGxpZ2h0ZWRFbGVtZW50SW5kZXggKyB0aGlzLmVudHJpZXMubGVuZ3RoICsgZGlyZWN0aW9uKSAlIHRoaXMuZW50cmllcy5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbnRyaWVzW25ld0hpZ2hsaWdodGVkRWxlbWVudEluZGV4XTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLmhpZ2hsaWdodFRleHRNYXRjaGVzID0gZnVuY3Rpb24gKHNlYXJjaFN0cmluZykge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgJGVudHJ5RWxlbWVudCA9IHRoaXMuZW50cmllc1tpXS5fdHJFbnRyeUVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgJGVudHJ5RWxlbWVudC50cml2aWFsSGlnaGxpZ2h0KHNlYXJjaFN0cmluZywgdGhpcy5jb25maWcubWF0Y2hpbmdPcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLmdldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkRW50cnlUb1JldHVybiA9ICQuZXh0ZW5kKHt9LCB0aGlzLnNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlUb1JldHVybi5fdHJFbnRyeUVsZW1lbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGVjdGVkRW50cnlUb1JldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUuZ2V0SGlnaGxpZ2h0ZWRFbnRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmhpZ2hsaWdodGVkRW50cnk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLm5hdmlnYXRlID0gZnVuY3Rpb24gKGRpcmVjdGlvbikge1xuICAgICAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ3VwJykge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0TmV4dEVudHJ5KC0xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ2Rvd24nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHROZXh0RW50cnkoMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxMaXN0Qm94LnByb3RvdHlwZS5nZXRNYWluRG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRsaXN0Qm94WzBdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJGxpc3RCb3gucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgcmV0dXJuIFRyaXZpYWxMaXN0Qm94O1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsTGlzdEJveCA9IFRyaXZpYWxMaXN0Qm94O1xufSk7XG5cblxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIiwgXCJqcXVlcnlcIiwgXCJtdXN0YWNoZVwiLCBcIi4vVHJpdmlhbExpc3RCb3hcIiwgXCIuL1RyaXZpYWxDb3JlXCIsIFwiLi9Ucml2aWFsRXZlbnRcIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcbiAgICB2YXIgTXVzdGFjaGUgPSByZXF1aXJlKFwibXVzdGFjaGVcIik7XG4gICAgdmFyIFRyaXZpYWxMaXN0Qm94XzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsTGlzdEJveFwiKTtcbiAgICB2YXIgVHJpdmlhbENvcmVfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxDb3JlXCIpO1xuICAgIHZhciBUcml2aWFsRXZlbnRfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxFdmVudFwiKTtcbiAgICB2YXIgVHJpdmlhbFRhZ0NvbWJvQm94ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gVHJpdmlhbFRhZ0NvbWJvQm94KG9yaWdpbmFsSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycyA9ICQoKTtcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3RlZEVudHJ5Q2hhbmdlZCA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9uRm9jdXMgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbkJsdXIgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5sYXN0UXVlcnlTdHJpbmcgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5sYXN0Q29tcGxldGVJbnB1dFF1ZXJ5U3RyaW5nID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRFbnRyaWVzID0gW107XG4gICAgICAgICAgICB0aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmF1dG9Db21wbGV0ZVRpbWVvdXRJZCA9IC0xO1xuICAgICAgICAgICAgdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveERpcnR5ID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duU2NoZWR1bGVyID0gbnVsbDtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgdGhpcy5jb25maWcgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgdmFsdWVGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJpZXMpIHsgcmV0dXJuIGVudHJpZXMubWFwKGZ1bmN0aW9uIChlKSB7IHJldHVybiBlLl9pc0ZyZWVUZXh0RW50cnkgPyBlLmRpc3BsYXlWYWx1ZSA6IGUuaWQ7IH0pLmpvaW4oJywnKTsgfSxcbiAgICAgICAgICAgICAgICBlbnRyeVJlbmRlcmluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE11c3RhY2hlLnJlbmRlcihUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmltYWdlMkxpbmVzVGVtcGxhdGUsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUcml2aWFsQ29yZV8xLndyYXBXaXRoRGVmYXVsdFRhZ1dyYXBwZXIoX3RoaXMuY29uZmlnLmVudHJ5UmVuZGVyaW5nRnVuY3Rpb24oZW50cnkpKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNwaW5uZXJUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0U3Bpbm5lclRlbXBsYXRlLFxuICAgICAgICAgICAgICAgIG5vRW50cmllc1RlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHROb0VudHJpZXNUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICB0ZXh0SGlnaGxpZ2h0aW5nRW50cnlMaW1pdDogMTAwLFxuICAgICAgICAgICAgICAgIGVudHJpZXM6IG51bGwsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyaWVzOiBbXSxcbiAgICAgICAgICAgICAgICBtYXhTZWxlY3RlZEVudHJpZXM6IG51bGwsXG4gICAgICAgICAgICAgICAgcXVlcnlGdW5jdGlvbjogbnVsbCxcbiAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGU6IHRydWUsXG4gICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlRGVsYXk6IDAsXG4gICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlRnVuY3Rpb246IGZ1bmN0aW9uIChlZGl0b3JUZXh0LCBlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWRpdG9yVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcGVydHlOYW1lIGluIGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVudHJ5Lmhhc093blByb3BlcnR5KHByb3BlcnR5TmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5VmFsdWUgPSBlbnRyeVtwcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydHlWYWx1ZSAmJiAoXCJcIiArIHByb3BlcnR5VmFsdWUpLnRvTG93ZXJDYXNlKCkuaW5kZXhPZihlZGl0b3JUZXh0LnRvTG93ZXJDYXNlKCkpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJcIiArIHByb3BlcnR5VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhbGxvd0ZyZWVUZXh0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBmcmVlVGV4dFNlcGFyYXRvcnM6IFsnLCcsICc7J10sXG4gICAgICAgICAgICAgICAgZnJlZVRleHRFbnRyeUZhY3Rvcnk6IGZ1bmN0aW9uIChmcmVlVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheVZhbHVlOiBmcmVlVGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIF9pc0ZyZWVUZXh0RW50cnk6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNob3dUcmlnZ2VyOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRpc3RpbmN0OiB0cnVlLFxuICAgICAgICAgICAgICAgIG1hdGNoaW5nT3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ01vZGU6ICdjb250YWlucycsXG4gICAgICAgICAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVkaXRpbmdNb2RlOiBcImVkaXRhYmxlXCIsXG4gICAgICAgICAgICAgICAgc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seTogZmFsc2VcbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbiA9IFRyaXZpYWxDb3JlXzEuZGVmYXVsdExpc3RRdWVyeUZ1bmN0aW9uRmFjdG9yeSh0aGlzLmNvbmZpZy5lbnRyaWVzIHx8IFtdLCB0aGlzLmNvbmZpZy5tYXRjaGluZ09wdGlvbnMpO1xuICAgICAgICAgICAgICAgIHRoaXMudXNpbmdEZWZhdWx0UXVlcnlGdW5jdGlvbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVudHJpZXMgPSB0aGlzLmNvbmZpZy5lbnRyaWVzO1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dCA9ICQob3JpZ2luYWxJbnB1dCkuYWRkQ2xhc3MoXCJ0ci1vcmlnaW5hbC1pbnB1dFwiKTtcbiAgICAgICAgICAgIHRoaXMuJHRhZ0NvbWJvQm94ID0gJCgnPGRpdiBjbGFzcz1cInRyLXRhZ2JveCB0ci1pbnB1dC13cmFwcGVyXCIvPicpXG4gICAgICAgICAgICAgICAgLmluc2VydEFmdGVyKHRoaXMuJG9yaWdpbmFsSW5wdXQpO1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC5hcHBlbmRUbyh0aGlzLiR0YWdDb21ib0JveCk7XG4gICAgICAgICAgICB2YXIgJHRhZ0FyZWEgPSAkKCc8ZGl2IGNsYXNzPVwidHItdGFnYm94LXRhZ2FyZWFcIi8+JykuYXBwZW5kVG8odGhpcy4kdGFnQ29tYm9Cb3gpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kdHJpZ2dlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmlnZ2VyXCI+PHNwYW4gY2xhc3M9XCJ0ci10cmlnZ2VyLWljb25cIi8+PC9kaXY+JykuYXBwZW5kVG8odGhpcy4kdGFnQ29tYm9Cb3gpO1xuICAgICAgICAgICAgICAgIHRoaXMuJHRyaWdnZXIubW91c2Vkb3duKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93biA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1kcm9wZG93blwiPjwvZGl2PicpXG4gICAgICAgICAgICAgICAgLnNjcm9sbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93blRhcmdldEVsZW1lbnQgPSAkKFwiYm9keVwiKTtcbiAgICAgICAgICAgIHRoaXMuc2V0RWRpdGluZ01vZGUodGhpcy5jb25maWcuZWRpdGluZ01vZGUpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yID0gJCgnPHNwYW4gY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiIGNsYXNzPVwidGFnYm94LWVkaXRvclwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiPjwvc3Bhbj4nKTtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvci5hcHBlbmRUbygkdGFnQXJlYSkuYWRkQ2xhc3MoXCJ0ci10YWdib3gtZWRpdG9yIHRyLWVkaXRvclwiKVxuICAgICAgICAgICAgICAgIC5mb2N1cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VySGFuZGxlcignZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub25Gb2N1cy5maXJlKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiR0YWdDb21ib0JveC5hZGRDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEubWluaW1hbGx5U2Nyb2xsVG8oJHRhZ0FyZWEsIF90aGlzLiRlZGl0b3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuYmx1cihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VySGFuZGxlcignYmx1cicpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vbkJsdXIuZmlyZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdGFnQ29tYm9Cb3gucmVtb3ZlQ2xhc3MoJ2ZvY3VzJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmVudHJpZXMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCAmJiBfdGhpcy4kZWRpdG9yLnRleHQoKS50cmltKCkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5jb25maWcuZnJlZVRleHRFbnRyeUZhY3RvcnkoX3RoaXMuJGVkaXRvci50ZXh0KCkpLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnRleHQoXCJcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAua2V5ZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChUcml2aWFsQ29yZV8xLmtleUNvZGVzLmlzTW9kaWZpZXJLZXkoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudGFiKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gX3RoaXMubGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3BlbiAmJiBoaWdobGlnaHRlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KGhpZ2hsaWdodGVkRW50cnksIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmxlZnRfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnJpZ2h0X2Fycm93KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMubGVmdF9hcnJvdyAmJiBfdGhpcy4kZWRpdG9yLnRleHQoKS5sZW5ndGggPT09IDAgJiYgd2luZG93LmdldFNlbGVjdGlvbigpLmFuY2hvck9mZnNldCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IucHJldigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5pbnNlcnRCZWZvcmUoX3RoaXMuJGVkaXRvci5wcmV2KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cgJiYgX3RoaXMuJGVkaXRvci50ZXh0KCkubGVuZ3RoID09PSAwICYmIHdpbmRvdy5nZXRTZWxlY3Rpb24oKS5hbmNob3JPZmZzZXQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLm5leHQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuaW5zZXJ0QWZ0ZXIoX3RoaXMuJGVkaXRvci5uZXh0KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuYmFja3NwYWNlIHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5kZWxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IudGV4dCgpID09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0YWdUb0JlUmVtb3ZlZCA9IF90aGlzLnNlbGVjdGVkRW50cmllc1tfdGhpcy4kZWRpdG9yLmluZGV4KCkgKyAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmJhY2tzcGFjZSA/IC0xIDogMCldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRhZ1RvQmVSZW1vdmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucmVtb3ZlVGFnKHRhZ1RvQmVSZW1vdmVkLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnVwX2Fycm93IHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5kb3duX2Fycm93KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGlyZWN0aW9uID0gZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnVwX2Fycm93ID8gLTEgOiAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeShkaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMubGlzdEJveC5oaWdobGlnaHROZXh0RW50cnkoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmF1dG9Db21wbGV0ZUlmUG9zc2libGUoX3RoaXMuY29uZmlnLmF1dG9Db21wbGV0ZURlbGF5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lbnRlcikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaGlnaGxpZ2h0ZWRFbnRyeSA9IF90aGlzLmxpc3RCb3guZ2V0SGlnaGxpZ2h0ZWRFbnRyeSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4gJiYgaGlnaGxpZ2h0ZWRFbnRyeSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KGhpZ2hsaWdodGVkRW50cnksIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuZW50cmllcyA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoX3RoaXMuY29uZmlnLmFsbG93RnJlZVRleHQgJiYgX3RoaXMuJGVkaXRvci50ZXh0KCkudHJpbSgpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMuY29uZmlnLmZyZWVUZXh0RW50cnlGYWN0b3J5KF90aGlzLiRlZGl0b3IudGV4dCgpKSwgZmFsc2UsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZXNjYXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci50ZXh0KFwiXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAua2V5dXAoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBzcGxpdFN0cmluZ0J5U2VwYXJhdG9yQ2hhcnMocywgc2VwYXJhdG9yQ2hhcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMuc3BsaXQobmV3IFJlZ0V4cChcIltcIiArIFRyaXZpYWxDb3JlXzEuZXNjYXBlU3BlY2lhbFJlZ2V4Q2hhcmFjdGVyKHNlcGFyYXRvckNoYXJzLmpvaW4oKSkgKyBcIl1cIikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGVkaXRvci5maW5kKCcqJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnRleHQoX3RoaXMuJGVkaXRvci50ZXh0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLmFsbG93RnJlZVRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVkaXRvclZhbHVlQmVmb3JlQ3Vyc29yID0gX3RoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWRpdG9yVmFsdWVCZWZvcmVDdXJzb3IubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRhZ1ZhbHVlc0VudGVyZWRCeVVzZXIgPSBzcGxpdFN0cmluZ0J5U2VwYXJhdG9yQ2hhcnMoZWRpdG9yVmFsdWVCZWZvcmVDdXJzb3IsIF90aGlzLmNvbmZpZy5mcmVlVGV4dFNlcGFyYXRvcnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0YWdWYWx1ZXNFbnRlcmVkQnlVc2VyLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHRhZ1ZhbHVlc0VudGVyZWRCeVVzZXJbaV0udHJpbSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMuY29uZmlnLmZyZWVUZXh0RW50cnlGYWN0b3J5KHZhbHVlKSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudGV4dCh0YWdWYWx1ZXNFbnRlcmVkQnlVc2VyW3RhZ1ZhbHVlc0VudGVyZWRCeVVzZXIubGVuZ3RoIC0gMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKF90aGlzLiRlZGl0b3JbMF0sIF90aGlzLiRlZGl0b3IudGV4dCgpLmxlbmd0aCwgX3RoaXMuJGVkaXRvci50ZXh0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5lbnRyaWVzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICh0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJwbGFjZWhvbGRlclwiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci5hdHRyKFwicGxhY2Vob2xkZXJcIiwgdGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwicGxhY2Vob2xkZXJcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmF0dHIoXCJ0YWJpbmRleFwiLCB0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJ0YWJpbmRleFwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwiYXV0b2ZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiR0YWdDb21ib0JveC5hZGQodGhpcy4kZHJvcERvd24pLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLm1vdXNldXAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTsgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkubW91c2VvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTsgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgY29uZmlnV2l0aG91dEVudHJpZXMgPSAkLmV4dGVuZCh7fSwgdGhpcy5jb25maWcpO1xuICAgICAgICAgICAgY29uZmlnV2l0aG91dEVudHJpZXMuZW50cmllcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94ID0gbmV3IFRyaXZpYWxMaXN0Qm94XzEuVHJpdmlhbExpc3RCb3godGhpcy4kZHJvcERvd24sIGNvbmZpZ1dpdGhvdXRFbnRyaWVzKTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveC5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmFkZExpc3RlbmVyKGZ1bmN0aW9uIChzZWxlY3RlZEVudHJ5LCBldmVudFNvdXJjZSwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoc2VsZWN0ZWRFbnRyeSwgdHJ1ZSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmxpc3RCb3guc2V0U2VsZWN0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgJHRhZ0FyZWEuY2xpY2soZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmNvbmZpZy5zaG93RHJvcERvd25PblJlc3VsdHNPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgpO1xuICAgICAgICAgICAgICAgIHZhciAkdGFnV2l0aFNtYWxsZXN0RGlzdGFuY2UgPSBudWxsO1xuICAgICAgICAgICAgICAgIHZhciBzbWFsbGVzdERpc3RhbmNlWCA9IDEwMDAwMDA7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBfdGhpcy5zZWxlY3RlZEVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkRW50cnkgPSBfdGhpcy5zZWxlY3RlZEVudHJpZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHZhciAkdGFnID0gc2VsZWN0ZWRFbnRyeS5fdHJFbnRyeUVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0YWdCb3VuZGluZ1JlY3QgPSAkdGFnWzBdLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2FtZVJvdyA9IGUuY2xpZW50WSA+PSB0YWdCb3VuZGluZ1JlY3QudG9wICYmIGUuY2xpZW50WSA8IHRhZ0JvdW5kaW5nUmVjdC5ib3R0b207XG4gICAgICAgICAgICAgICAgICAgIHZhciBzYW1lQ29sID0gZS5jbGllbnRYID49IHRhZ0JvdW5kaW5nUmVjdC5sZWZ0ICYmIGUuY2xpZW50WCA8IHRhZ0JvdW5kaW5nUmVjdC5yaWdodDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RhbmNlWCA9IHNhbWVDb2wgPyAwIDogTWF0aC5taW4oTWF0aC5hYnMoZS5jbGllbnRYIC0gdGFnQm91bmRpbmdSZWN0LmxlZnQpLCBNYXRoLmFicyhlLmNsaWVudFggLSB0YWdCb3VuZGluZ1JlY3QucmlnaHQpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNhbWVSb3cgJiYgZGlzdGFuY2VYIDwgc21hbGxlc3REaXN0YW5jZVgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0YWdXaXRoU21hbGxlc3REaXN0YW5jZSA9ICR0YWc7XG4gICAgICAgICAgICAgICAgICAgICAgICBzbWFsbGVzdERpc3RhbmNlWCA9IGRpc3RhbmNlWDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkaXN0YW5jZVggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoJHRhZ1dpdGhTbWFsbGVzdERpc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0YWdCb3VuZGluZ1JlY3QgPSAkdGFnV2l0aFNtYWxsZXN0RGlzdGFuY2VbMF0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpc1JpZ2h0U2lkZSA9IGUuY2xpZW50WCA+ICh0YWdCb3VuZGluZ1JlY3QubGVmdCArIHRhZ0JvdW5kaW5nUmVjdC5yaWdodCkgLyAyO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNSaWdodFNpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuaW5zZXJ0QWZ0ZXIoJHRhZ1dpdGhTbWFsbGVzdERpc3RhbmNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuaW5zZXJ0QmVmb3JlKCR0YWdXaXRoU21hbGxlc3REaXN0YW5jZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cmllcyh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJpZXMpO1xuICAgICAgICAgICAgdGhpcy4kdGFnQ29tYm9Cb3guZGF0YShcInRyaXZpYWxUYWdDb21ib0JveFwiLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLnVwZGF0ZUxpc3RCb3hFbnRyaWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94LnVwZGF0ZUVudHJpZXModGhpcy5lbnRyaWVzKTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveERpcnR5ID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUudXBkYXRlRW50cmllcyA9IGZ1bmN0aW9uIChuZXdFbnRyaWVzLCBoaWdobGlnaHREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZW50cmllcyA9IG5ld0VudHJpZXM7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycy5yZW1vdmUoKTtcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gJCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUxpc3RCb3hFbnRyaWVzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3RCb3hEaXJ0eSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA9IHRoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94LmhpZ2hsaWdodFRleHRNYXRjaGVzKG5ld0VudHJpZXMubGVuZ3RoIDw9IHRoaXMuY29uZmlnLnRleHRIaWdobGlnaHRpbmdFbnRyeUxpbWl0ID8gbm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA6IG51bGwpO1xuICAgICAgICAgICAgaWYgKGhpZ2hsaWdodERpcmVjdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdEJveC5oaWdobGlnaHROZXh0RW50cnkoaGlnaGxpZ2h0RGlyZWN0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdEJveC5zZXRIaWdobGlnaHRlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVJZlBvc3NpYmxlKHRoaXMuY29uZmlnLmF1dG9Db21wbGV0ZURlbGF5KTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5yZW1vdmVUYWcgPSBmdW5jdGlvbiAodGFnVG9CZVJlbW92ZWQsIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBpbmRleCA9IHRoaXMuc2VsZWN0ZWRFbnRyaWVzLmluZGV4T2YodGFnVG9CZVJlbW92ZWQpO1xuICAgICAgICAgICAgaWYgKGluZGV4ID4gLTEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cmllcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGFnVG9CZVJlbW92ZWQuX3RyRW50cnlFbGVtZW50LnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC52YWwodGhpcy5jb25maWcudmFsdWVGdW5jdGlvbih0aGlzLmdldFNlbGVjdGVkRW50cmllcygpKSk7XG4gICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHModGhpcy5nZXRTZWxlY3RlZEVudHJpZXMoKSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUucXVlcnkgPSBmdW5jdGlvbiAoaGlnaGxpZ2h0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHF1ZXJ5U3RyaW5nID0gX3RoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgIHZhciBjb21wbGV0ZUlucHV0U3RyaW5nID0gX3RoaXMuJGVkaXRvci50ZXh0KCkucmVwbGFjZShTdHJpbmcuZnJvbUNoYXJDb2RlKDE2MCksIFwiIFwiKTtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMubGFzdFF1ZXJ5U3RyaW5nICE9PSBxdWVyeVN0cmluZyB8fCBfdGhpcy5sYXN0Q29tcGxldGVJbnB1dFF1ZXJ5U3RyaW5nICE9PSBjb21wbGV0ZUlucHV0U3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kc3Bpbm5lcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHNwaW5uZXIgPSAkKF90aGlzLmNvbmZpZy5zcGlubmVyVGVtcGxhdGUpLmFwcGVuZFRvKF90aGlzLiRkcm9wRG93bik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kc3Bpbm5lcnMgPSBfdGhpcy4kc3Bpbm5lcnMuYWRkKCRzcGlubmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbihxdWVyeVN0cmluZywgZnVuY3Rpb24gKG5ld0VudHJpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZUVudHJpZXMobmV3RW50cmllcywgaGlnaGxpZ2h0RGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSAmJiBuZXdFbnRyaWVzICYmIG5ld0VudHJpZXMubGVuZ3RoID4gMCAmJiBfdGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5sYXN0UXVlcnlTdHJpbmcgPSBxdWVyeVN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubGFzdENvbXBsZXRlSW5wdXRRdWVyeVN0cmluZyA9IGNvbXBsZXRlSW5wdXRTdHJpbmc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUuZmlyZUNoYW5nZUV2ZW50cyA9IGZ1bmN0aW9uIChlbnRyaWVzLCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuZmlyZShlbnRyaWVzLCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5zZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5LCBmaXJlRXZlbnQsIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50ID09PSB2b2lkIDApIHsgZmlyZUV2ZW50ID0gZmFsc2U7IH1cbiAgICAgICAgICAgIGlmIChlbnRyeSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLm1heFNlbGVjdGVkRW50cmllcyAmJiB0aGlzLnNlbGVjdGVkRW50cmllcy5sZW5ndGggPj0gdGhpcy5jb25maWcubWF4U2VsZWN0ZWRFbnRyaWVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmRpc3RpbmN0ICYmIHRoaXMuc2VsZWN0ZWRFbnRyaWVzLm1hcChmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3RoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24oW2VudHJ5XSk7XG4gICAgICAgICAgICB9KS5pbmRleE9mKHRoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24oW2VudHJ5XSkpICE9IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHRhZyA9ICQuZXh0ZW5kKHt9LCBlbnRyeSk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cmllcy5zcGxpY2UodGhpcy4kZWRpdG9yLmluZGV4KCksIDAsIHRhZyk7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCh0aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKHRoaXMuZ2V0U2VsZWN0ZWRFbnRyaWVzKCkpKTtcbiAgICAgICAgICAgIHZhciAkZW50cnkgPSAkKHRoaXMuY29uZmlnLnNlbGVjdGVkRW50cnlSZW5kZXJpbmdGdW5jdGlvbih0YWcpKTtcbiAgICAgICAgICAgIHZhciAkdGFnV3JhcHBlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10YWdib3gtdGFnXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgICAkdGFnV3JhcHBlci5hcHBlbmQoJGVudHJ5KS5pbnNlcnRCZWZvcmUodGhpcy4kZWRpdG9yKTtcbiAgICAgICAgICAgIHRhZy5fdHJFbnRyeUVsZW1lbnQgPSAkdGFnV3JhcHBlcjtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5lZGl0aW5nTW9kZSA9PSBcImVkaXRhYmxlXCIpIHtcbiAgICAgICAgICAgICAgICAkZW50cnkuZmluZCgnLnRyLXJlbW92ZS1idXR0b24nKS5jbGljayhmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5yZW1vdmVUYWcodGFnKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnRleHQoXCJcIik7XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKHRoaXMuZ2V0U2VsZWN0ZWRFbnRyaWVzKCksIG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLnJlcG9zaXRpb25Ecm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5wb3NpdGlvbih7XG4gICAgICAgICAgICAgICAgbXk6IFwibGVmdCB0b3BcIixcbiAgICAgICAgICAgICAgICBhdDogXCJsZWZ0IGJvdHRvbVwiLFxuICAgICAgICAgICAgICAgIG9mOiB0aGlzLiR0YWdDb21ib0JveCxcbiAgICAgICAgICAgICAgICBjb2xsaXNpb246IFwiZmxpcFwiLFxuICAgICAgICAgICAgICAgIHVzaW5nOiBmdW5jdGlvbiAoY2FsY3VsYXRlZFBvc2l0aW9uLCBpbmZvKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmZvLnZlcnRpY2FsID09PSBcInRvcFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdGFnQ29tYm9Cb3gucmVtb3ZlQ2xhc3MoXCJkcm9wZG93bi1mbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLnJlbW92ZUNsYXNzKFwiZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiR0YWdDb21ib0JveC5hZGRDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24uYWRkQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5jc3Moe1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogY2FsY3VsYXRlZFBvc2l0aW9uLmxlZnQgKyAncHgnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wOiBjYWxjdWxhdGVkUG9zaXRpb24udG9wICsgJ3B4J1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS53aWR0aCh0aGlzLiR0YWdDb21ib0JveC53aWR0aCgpKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5vcGVuRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk5lZWRlZCgpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubGlzdEJveERpcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTGlzdEJveEVudHJpZXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy4kdGFnQ29tYm9Cb3guYWRkQ2xhc3MoXCJvcGVuXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLnNob3coKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcG9zaXRpb25Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMucmVwb3NpdGlvbkRyb3BEb3duU2NoZWR1bGVyID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcG9zaXRpb25Ecm9wRG93blNjaGVkdWxlciA9IHdpbmRvdy5zZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5yZXBvc2l0aW9uRHJvcERvd24oKTsgfSwgMTAwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUuY2xvc2VEcm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJHRhZ0NvbWJvQm94LnJlbW92ZUNsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmhpZGUoKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlcG9zaXRpb25Ecm9wRG93blNjaGVkdWxlciAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLnJlcG9zaXRpb25Ecm9wRG93blNjaGVkdWxlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBlZGl0b3JUZXh0ID0gdGhpcy4kZWRpdG9yLnRleHQoKS5yZXBsYWNlKFN0cmluZy5mcm9tQ2hhckNvZGUoMTYwKSwgXCIgXCIpO1xuICAgICAgICAgICAgdmFyIHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgICAgIGlmIChzZWxlY3Rpb24uYW5jaG9yT2Zmc2V0ICE9IHNlbGVjdGlvbi5mb2N1c09mZnNldCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlZGl0b3JUZXh0LnN1YnN0cmluZygwLCBNYXRoLm1pbih3aW5kb3cuZ2V0U2VsZWN0aW9uKCkuYmFzZU9mZnNldCwgd2luZG93LmdldFNlbGVjdGlvbigpLmZvY3VzT2Zmc2V0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZWRpdG9yVGV4dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5hdXRvQ29tcGxldGVJZlBvc3NpYmxlID0gZnVuY3Rpb24gKGRlbGF5KSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmF1dG9Db21wbGV0ZSkge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmF1dG9Db21wbGV0ZVRpbWVvdXRJZCk7XG4gICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnlfMSA9IHRoaXMubGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgaWYgKGhpZ2hsaWdodGVkRW50cnlfMSAmJiAhdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVUaW1lb3V0SWQgPSB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY3VycmVudEVkaXRvclZhbHVlID0gX3RoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF1dG9Db21wbGV0ZVN0cmluZyA9IF90aGlzLmNvbmZpZy5hdXRvQ29tcGxldGVGdW5jdGlvbihjdXJyZW50RWRpdG9yVmFsdWUsIGhpZ2hsaWdodGVkRW50cnlfMSkgfHwgY3VycmVudEVkaXRvclZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci50ZXh0KGN1cnJlbnRFZGl0b3JWYWx1ZSArIGF1dG9Db21wbGV0ZVN0cmluZy5yZXBsYWNlKCcgJywgU3RyaW5nLmZyb21DaGFyQ29kZSgxNjApKS5zdWJzdHIoY3VycmVudEVkaXRvclZhbHVlLmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucmVwb3NpdGlvbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGVkaXRvci5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKF90aGlzLiRlZGl0b3JbMF0sIGN1cnJlbnRFZGl0b3JWYWx1ZS5sZW5ndGgsIGF1dG9Db21wbGV0ZVN0cmluZy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9LCBkZWxheSB8fCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5pc0Ryb3BEb3duTmVlZGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWRpdGluZ01vZGUgPT0gJ2VkaXRhYmxlJyAmJiAodGhpcy5jb25maWcuZW50cmllcyAmJiB0aGlzLmNvbmZpZy5lbnRyaWVzLmxlbmd0aCA+IDAgfHwgIXRoaXMudXNpbmdEZWZhdWx0UXVlcnlGdW5jdGlvbiB8fCB0aGlzLmNvbmZpZy5zaG93VHJpZ2dlcik7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUuc2V0RWRpdGluZ01vZGUgPSBmdW5jdGlvbiAobmV3RWRpdGluZ01vZGUpIHtcbiAgICAgICAgICAgIHRoaXMuZWRpdGluZ01vZGUgPSBuZXdFZGl0aW5nTW9kZTtcbiAgICAgICAgICAgIHRoaXMuJHRhZ0NvbWJvQm94LnJlbW92ZUNsYXNzKFwiZWRpdGFibGUgcmVhZG9ubHkgZGlzYWJsZWRcIikuYWRkQ2xhc3ModGhpcy5lZGl0aW5nTW9kZSk7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0Ryb3BEb3duTmVlZGVkKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5hcHBlbmRUbyh0aGlzLiRkcm9wRG93blRhcmdldEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLnNldFNlbGVjdGVkRW50cmllcyA9IGZ1bmN0aW9uIChlbnRyaWVzKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEVudHJpZXNcbiAgICAgICAgICAgICAgICAuc2xpY2UoKVxuICAgICAgICAgICAgICAgIC5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5yZW1vdmVUYWcoZSk7IH0pO1xuICAgICAgICAgICAgaWYgKGVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTZWxlY3RlZEVudHJ5KGVudHJpZXNbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5nZXRTZWxlY3RlZEVudHJpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZWN0ZWRFbnRyaWVzVG9SZXR1cm4gPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5zZWxlY3RlZEVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWRFbnRyeVRvUmV0dXJuID0gJC5leHRlbmQoe30sIHRoaXMuc2VsZWN0ZWRFbnRyaWVzW2ldKTtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJ5VG9SZXR1cm4uX3RyRW50cnlFbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cmllc1RvUmV0dXJuLnB1c2goc2VsZWN0ZWRFbnRyeVRvUmV0dXJuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzZWxlY3RlZEVudHJpZXNUb1JldHVybjtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyh0aGlzLiRlZGl0b3JbMF0sIDAsIHRoaXMuJGVkaXRvci50ZXh0KCkubGVuZ3RoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLmdldEVkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRlZGl0b3JbMF07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQucmVtb3ZlQ2xhc3MoJ3RyLW9yaWdpbmFsLWlucHV0JykuaW5zZXJ0QmVmb3JlKHRoaXMuJHRhZ0NvbWJvQm94KTtcbiAgICAgICAgICAgIHRoaXMuJHRhZ0NvbWJvQm94LnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd24ucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5nZXRNYWluRG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiR0YWdDb21ib0JveFswXTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFRyaXZpYWxUYWdDb21ib0JveDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbFRhZ0NvbWJvQm94ID0gVHJpdmlhbFRhZ0NvbWJvQm94O1xufSk7XG5cblxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUoKSB7XG4gICAgICAgIH1cbiAgICAgICAgVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLnByb3RvdHlwZS5nZW5lcmF0ZVN1Z2dlc3Rpb25zID0gZnVuY3Rpb24gKHNlYXJjaFN0cmluZykge1xuICAgICAgICAgICAgdmFyIHN1Z2dlc3Rpb25zID0gW107XG4gICAgICAgICAgICB2YXIgbWF0Y2ggPSBzZWFyY2hTdHJpbmcubWF0Y2goL1teXFxkXS8pO1xuICAgICAgICAgICAgdmFyIGNvbG9uSW5kZXggPSBtYXRjaCAhPSBudWxsID8gbWF0Y2guaW5kZXggOiBudWxsO1xuICAgICAgICAgICAgaWYgKGNvbG9uSW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgaG91clN0cmluZyA9IHNlYXJjaFN0cmluZy5zdWJzdHJpbmcoMCwgY29sb25JbmRleCk7XG4gICAgICAgICAgICAgICAgdmFyIG1pbnV0ZVN0cmluZyA9IHNlYXJjaFN0cmluZy5zdWJzdHJpbmcoY29sb25JbmRleCArIDEpO1xuICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zID0gc3VnZ2VzdGlvbnMuY29uY2F0KFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVUaW1lU3VnZ2VzdGlvbnMoVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZUhvdXJTdWdnZXN0aW9ucyhob3VyU3RyaW5nKSwgVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZU1pbnV0ZVN1Z2dlc3Rpb25zKG1pbnV0ZVN0cmluZykpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHNlYXJjaFN0cmluZy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlYXJjaFN0cmluZy5sZW5ndGggPj0gMikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaG91clN0cmluZ18xID0gc2VhcmNoU3RyaW5nLnN1YnN0cigwLCAyKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1pbnV0ZVN0cmluZ18xID0gc2VhcmNoU3RyaW5nLnN1YnN0cmluZygyLCBzZWFyY2hTdHJpbmcubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSBzdWdnZXN0aW9ucy5jb25jYXQoVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVRpbWVTdWdnZXN0aW9ucyhUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlSG91clN1Z2dlc3Rpb25zKGhvdXJTdHJpbmdfMSksIFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVNaW51dGVTdWdnZXN0aW9ucyhtaW51dGVTdHJpbmdfMSkpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGhvdXJTdHJpbmcgPSBzZWFyY2hTdHJpbmcuc3Vic3RyKDAsIDEpO1xuICAgICAgICAgICAgICAgIHZhciBtaW51dGVTdHJpbmcgPSBzZWFyY2hTdHJpbmcuc3Vic3RyaW5nKDEsIHNlYXJjaFN0cmluZy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGlmIChtaW51dGVTdHJpbmcubGVuZ3RoIDw9IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSBzdWdnZXN0aW9ucy5jb25jYXQoVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVRpbWVTdWdnZXN0aW9ucyhUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlSG91clN1Z2dlc3Rpb25zKGhvdXJTdHJpbmcpLCBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlTWludXRlU3VnZ2VzdGlvbnMobWludXRlU3RyaW5nKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zID0gc3VnZ2VzdGlvbnMuY29uY2F0KFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVUaW1lU3VnZ2VzdGlvbnMoVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmludFJhbmdlKDYsIDI0KS5jb25jYXQoVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmludFJhbmdlKDEsIDUpKSwgWzBdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3VnZ2VzdGlvbnM7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5pbnRSYW5nZSA9IGZ1bmN0aW9uIChmcm9tSW5jbHVzaXZlLCB0b0luY2x1c2l2ZSkge1xuICAgICAgICAgICAgdmFyIGludHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSBmcm9tSW5jbHVzaXZlOyBpIDw9IHRvSW5jbHVzaXZlOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpbnRzLnB1c2goaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaW50cztcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVRpbWVTdWdnZXN0aW9ucyA9IGZ1bmN0aW9uIChob3VyVmFsdWVzLCBtaW51dGVWYWx1ZXMpIHtcbiAgICAgICAgICAgIHZhciBlbnRyaWVzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhvdXJWYWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgaG91ciA9IGhvdXJWYWx1ZXNbaV07XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtaW51dGVWYWx1ZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1pbnV0ZSA9IG1pbnV0ZVZhbHVlc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgZW50cmllcy5wdXNoKHsgaG91cjogaG91ciwgbWludXRlOiBtaW51dGUgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGVudHJpZXM7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVNaW51dGVTdWdnZXN0aW9ucyA9IGZ1bmN0aW9uIChtaW51dGVTdHJpbmcpIHtcbiAgICAgICAgICAgIHZhciBtID0gcGFyc2VJbnQobWludXRlU3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChpc05hTihtKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChtaW51dGVTdHJpbmcubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbbSAlIDYwXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG0gPCA2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFttICogMTBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFttICUgNjBdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlSG91clN1Z2dlc3Rpb25zID0gZnVuY3Rpb24gKGhvdXJTdHJpbmcpIHtcbiAgICAgICAgICAgIHZhciBoID0gcGFyc2VJbnQoaG91clN0cmluZyk7XG4gICAgICAgICAgICBpZiAoaXNOYU4oaCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmludFJhbmdlKDEsIDI0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGggPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBbaCwgKGggKyAxMikgJSAyNF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChoIDw9IDI0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtoICUgMjRdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lO1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUgPSBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmU7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIm11c3RhY2hlXCIsIFwiLi9Ucml2aWFsVHJlZUJveFwiLCBcIi4vVHJpdmlhbENvcmVcIiwgXCIuL1RyaXZpYWxFdmVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBNdXN0YWNoZSA9IHJlcXVpcmUoXCJtdXN0YWNoZVwiKTtcbiAgICB2YXIgVHJpdmlhbFRyZWVCb3hfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxUcmVlQm94XCIpO1xuICAgIHZhciBUcml2aWFsQ29yZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENvcmVcIik7XG4gICAgdmFyIFRyaXZpYWxFdmVudF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpO1xuICAgIHZhciBUcml2aWFsVHJlZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFRyaXZpYWxUcmVlKG9yaWdpbmFsSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMub25Ob2RlRXhwYW5zaW9uU3RhdGVDaGFuZ2VkID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gJCgpO1xuICAgICAgICAgICAgdGhpcy5jb25maWcgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgdmFsdWVGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7IHJldHVybiBlbnRyeSA/IFwiXCIgKyBlbnRyeS5pZCA6IG51bGw7IH0sXG4gICAgICAgICAgICAgICAgY2hpbGRyZW5Qcm9wZXJ0eTogXCJjaGlsZHJlblwiLFxuICAgICAgICAgICAgICAgIGxhenlDaGlsZHJlbkZsYWdQcm9wZXJ0eTogXCJoYXNMYXp5Q2hpbGRyZW5cIixcbiAgICAgICAgICAgICAgICBzZWFyY2hCYXJNb2RlOiAnc2hvdy1pZi1maWxsZWQnLFxuICAgICAgICAgICAgICAgIGxhenlDaGlsZHJlblF1ZXJ5RnVuY3Rpb246IGZ1bmN0aW9uIChub2RlLCByZXN1bHRDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRDYWxsYmFjayhbXSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBleHBhbmRlZFByb3BlcnR5OiAnZXhwYW5kZWQnLFxuICAgICAgICAgICAgICAgIGVudHJ5UmVuZGVyaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSwgZGVwdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRlZmF1bHRUZW1wbGF0ZXMgPSBbVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5pY29uMkxpbmVzVGVtcGxhdGUsIFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuaWNvblNpbmdsZUxpbmVUZW1wbGF0ZV07XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IGVudHJ5LnRlbXBsYXRlIHx8IGRlZmF1bHRUZW1wbGF0ZXNbTWF0aC5taW4oZGVwdGgsIGRlZmF1bHRUZW1wbGF0ZXMubGVuZ3RoIC0gMSldO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTXVzdGFjaGUucmVuZGVyKHRlbXBsYXRlLCBlbnRyeSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzcGlubmVyVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdFNwaW5uZXJUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICBub0VudHJpZXNUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0Tm9FbnRyaWVzVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgZW50cmllczogbnVsbCxcbiAgICAgICAgICAgICAgICBxdWVyeUZ1bmN0aW9uOiBudWxsLFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlJZDogbnVsbCxcbiAgICAgICAgICAgICAgICBtYXRjaGluZ09wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hpbmdNb2RlOiAnY29udGFpbnMnLFxuICAgICAgICAgICAgICAgICAgICBpZ25vcmVDYXNlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBtYXhMZXZlbnNodGVpbkRpc3RhbmNlOiAyXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkaXJlY3RTZWxlY3Rpb25WaWFBcnJvd0tleXM6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHBlcmZvcm1hbmNlT3B0aW1pemF0aW9uU2V0dGluZ3M6IHtcbiAgICAgICAgICAgICAgICAgICAgdG9NYW55VmlzaWJsZUl0ZW1zUmVuZGVyRGVsYXk6IDc1MCxcbiAgICAgICAgICAgICAgICAgICAgdG9NYW55VmlzaWJsZUl0ZW1zVGhyZXNob2xkOiA3NVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbiA9IFRyaXZpYWxDb3JlXzEuZGVmYXVsdFRyZWVRdWVyeUZ1bmN0aW9uRmFjdG9yeSh0aGlzLmNvbmZpZy5lbnRyaWVzIHx8IFtdLCBUcml2aWFsQ29yZV8xLmRlZmF1bHRFbnRyeU1hdGNoaW5nRnVuY3Rpb25GYWN0b3J5KFtcImRpc3BsYXlWYWx1ZVwiLCBcImFkZGl0aW9uYWxJbmZvXCJdLCB0aGlzLmNvbmZpZy5tYXRjaGluZ09wdGlvbnMpLCB0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5LCB0aGlzLmNvbmZpZy5leHBhbmRlZFByb3BlcnR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW50cmllcyA9IHRoaXMuY29uZmlnLmVudHJpZXM7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0ID0gJChvcmlnaW5hbElucHV0KS5hZGRDbGFzcyhcInRyLW9yaWdpbmFsLWlucHV0XCIpO1xuICAgICAgICAgICAgdGhpcy4kY29tcG9uZW50V3JhcHBlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmVlXCIgdGFiaW5kZXg9XCIwXCIvPicpLmluc2VydEFmdGVyKHRoaXMuJG9yaWdpbmFsSW5wdXQpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNlYXJjaEJhck1vZGUgIT09ICdhbHdheXMtdmlzaWJsZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRjb21wb25lbnRXcmFwcGVyLmFkZENsYXNzKFwiaGlkZS1zZWFyY2hmaWVsZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJGNvbXBvbmVudFdyYXBwZXIua2V5ZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudGFiIHx8IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuaXNNb2RpZmllcktleShlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLmlzKCc6dmlzaWJsZScpICYmIFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuc3BlY2lhbEtleXMuaW5kZXhPZihlLndoaWNoKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnVwX2Fycm93IHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5kb3duX2Fycm93KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgPyAtMSA6IDE7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5lbnRyaWVzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuZGlyZWN0U2VsZWN0aW9uVmlhQXJyb3dLZXlzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMudHJlZUJveC5zZWxlY3ROZXh0RW50cnkoZGlyZWN0aW9uLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3guaGlnaGxpZ2h0TmV4dEVudHJ5KGRpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmxlZnRfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnJpZ2h0X2Fycm93KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3guc2V0SGlnaGxpZ2h0ZWROb2RlRXhwYW5kZWQoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnJpZ2h0X2Fycm93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVudGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3guc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy50cmVlQm94LmdldEhpZ2hsaWdodGVkRW50cnkoKSwgZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lc2NhcGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci52YWwoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRjb21wb25lbnRXcmFwcGVyLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvciA9ICQoJzxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwidHItdHJlZS1lZGl0b3IgdHItZWRpdG9yXCIvPicpXG4gICAgICAgICAgICAgICAgLnByZXBlbmRUbyh0aGlzLiRjb21wb25lbnRXcmFwcGVyKVxuICAgICAgICAgICAgICAgIC5hdHRyKFwidGFiaW5kZXhcIiwgdGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwiLTFcIikpXG4gICAgICAgICAgICAgICAgLmZvY3VzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy4kY29tcG9uZW50V3JhcHBlci5hZGRDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmJsdXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLiRjb21wb25lbnRXcmFwcGVyLnJlbW92ZUNsYXNzKCdmb2N1cycpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAua2V5ZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMubGVmdF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoYW5nZWRFeHBhbmRlZFN0YXRlID0gX3RoaXMudHJlZUJveC5zZXRIaWdobGlnaHRlZE5vZGVFeHBhbmRlZChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hhbmdlZEV4cGFuZGVkU3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm9uKCdrZXl1cCBjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5zZWFyY2hCYXJNb2RlID09PSAnc2hvdy1pZi1maWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kY29tcG9uZW50V3JhcHBlci5yZW1vdmVDbGFzcygnaGlkZS1zZWFyY2hmaWVsZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGNvbXBvbmVudFdyYXBwZXIuYWRkQ2xhc3MoJ2hpZGUtc2VhcmNoZmllbGQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNlYXJjaEJhck1vZGUgPT09ICdub25lJykge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci5jc3MoXCJkaXNwbGF5XCIsIFwibm9uZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJwbGFjZWhvbGRlclwiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci5hdHRyKFwicGxhY2Vob2xkZXJcIiwgdGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwicGxhY2Vob2xkZXJcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY29tcG9uZW50V3JhcHBlci5hdHRyKFwidGFiaW5kZXhcIiwgdGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcImF1dG9mb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGNvbXBvbmVudFdyYXBwZXIuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudHJlZUJveCA9IG5ldyBUcml2aWFsVHJlZUJveF8xLlRyaXZpYWxUcmVlQm94KHRoaXMuJGNvbXBvbmVudFdyYXBwZXIsIHRoaXMuY29uZmlnKTtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC5vbk5vZGVFeHBhbnNpb25TdGF0ZUNoYW5nZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5vbk5vZGVFeHBhbnNpb25TdGF0ZUNoYW5nZWQuZmlyZShub2RlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy50cmVlQm94Lm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBzZWxlY3RlZFRyZWVCb3hFbnRyeSA9IF90aGlzLnRyZWVCb3guZ2V0U2VsZWN0ZWRFbnRyeSgpO1xuICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZFRyZWVCb3hFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KHNlbGVjdGVkVHJlZUJveEVudHJ5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0ZWRFbnRyeSgodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeUlkICE9PSB1bmRlZmluZWQgJiYgdGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeUlkICE9PSBudWxsKSA/IHRoaXMuZmluZEVudHJ5QnlJZCh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5SWQpIDogbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLnVwZGF0ZUVudHJpZXMgPSBmdW5jdGlvbiAobmV3RW50cmllcykge1xuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gbmV3RW50cmllcztcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzLnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSAkKCk7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3gudXBkYXRlRW50cmllcyhuZXdFbnRyaWVzKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24gKGhpZ2hsaWdodERpcmVjdGlvbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5zZWFyY2hCYXJNb2RlID09PSAnYWx3YXlzLXZpc2libGUnIHx8IHRoaXMuY29uZmlnLnNlYXJjaEJhck1vZGUgPT09ICdzaG93LWlmLWZpbGxlZCcpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHNwaW5uZXIgPSAkKHRoaXMuY29uZmlnLnNwaW5uZXJUZW1wbGF0ZSkuYXBwZW5kVG8odGhpcy50cmVlQm94LmdldE1haW5Eb21FbGVtZW50KCkpO1xuICAgICAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gdGhpcy4kc3Bpbm5lcnMuYWRkKCRzcGlubmVyKTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29uZmlnLnF1ZXJ5RnVuY3Rpb24oX3RoaXMuJGVkaXRvci52YWwoKSwgZnVuY3Rpb24gKG5ld0VudHJpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9jZXNzVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZUVudHJpZXMobmV3RW50cmllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IudmFsKCkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy50cmVlQm94LmhpZ2hsaWdodFRleHRNYXRjaGVzKF90aGlzLiRlZGl0b3IudmFsKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmNvbmZpZy5kaXJlY3RTZWxlY3Rpb25WaWFBcnJvd0tleXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3guaGlnaGxpZ2h0TmV4dE1hdGNoaW5nRW50cnkoaGlnaGxpZ2h0RGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy50cmVlQm94LnJldmVhbFNlbGVjdGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoX3RoaXMucHJvY2Vzc1VwZGF0ZVRpbWVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb3VudFZpc2libGVFbnRyaWVzKG5ld0VudHJpZXMpIDwgX3RoaXMuY29uZmlnLnBlcmZvcm1hbmNlT3B0aW1pemF0aW9uU2V0dGluZ3MudG9NYW55VmlzaWJsZUl0ZW1zVGhyZXNob2xkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucHJvY2Vzc1VwZGF0ZVRpbWVyID0gd2luZG93LnNldFRpbWVvdXQocHJvY2Vzc1VwZGF0ZSwgX3RoaXMuY29uZmlnLnBlcmZvcm1hbmNlT3B0aW1pemF0aW9uU2V0dGluZ3MudG9NYW55VmlzaWJsZUl0ZW1zUmVuZGVyRGVsYXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLmNvdW50VmlzaWJsZUVudHJpZXMgPSBmdW5jdGlvbiAoZW50cmllcykge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBjb3VudFZpc2libGVDaGlsZHJlbkFuZFNlbGYgPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW190aGlzLmNvbmZpZy5leHBhbmRlZFByb3BlcnR5XSAmJiBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbm9kZVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0ubWFwKGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvdW50VmlzaWJsZUNoaWxkcmVuQW5kU2VsZihlbnRyeSk7XG4gICAgICAgICAgICAgICAgICAgIH0pLnJlZHVjZShmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEgKyBiO1xuICAgICAgICAgICAgICAgICAgICB9LCAwKSArIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIGVudHJpZXMubWFwKGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjb3VudFZpc2libGVDaGlsZHJlbkFuZFNlbGYoZW50cnkpO1xuICAgICAgICAgICAgfSkucmVkdWNlKGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgKyBiO1xuICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5maW5kRW50cmllcyA9IGZ1bmN0aW9uIChmaWx0ZXJGdW5jdGlvbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBmaW5kRW50cmllc0luU3ViVHJlZSA9IGZ1bmN0aW9uIChub2RlLCBsaXN0T2ZGb3VuZEVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZmlsdGVyRnVuY3Rpb24uY2FsbChfdGhpcywgbm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdE9mRm91bmRFbnRyaWVzLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVbX3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XVtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmRFbnRyaWVzSW5TdWJUcmVlKGNoaWxkLCBsaXN0T2ZGb3VuZEVudHJpZXMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBtYXRjaGluZ0VudHJpZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5lbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvb3RFbnRyeSA9IHRoaXMuZW50cmllc1tpXTtcbiAgICAgICAgICAgICAgICBmaW5kRW50cmllc0luU3ViVHJlZShyb290RW50cnksIG1hdGNoaW5nRW50cmllcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hpbmdFbnRyaWVzO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUuZmluZEVudHJ5QnlJZCA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmRFbnRyaWVzKGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihlbnRyeSkgPT09IGlkLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9KVswXTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLnNldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRFbnRyeUlkID0gZW50cnkgPyB0aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKGVudHJ5KSA6IG51bGw7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbChlbnRyeSA/IHRoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24oZW50cnkpIDogbnVsbCk7XG4gICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoZW50cnkpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUuZmlyZUNoYW5nZUV2ZW50cyA9IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgdGhpcy4kY29tcG9uZW50V3JhcHBlci50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmZpcmUoZW50cnkpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUuZ2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC5nZXRTZWxlY3RlZEVudHJ5KCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLnVwZGF0ZUNoaWxkcmVuID0gZnVuY3Rpb24gKHBhcmVudE5vZGVJZCwgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC51cGRhdGVDaGlsZHJlbihwYXJlbnROb2RlSWQsIGNoaWxkcmVuKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUudXBkYXRlTm9kZSA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3gudXBkYXRlTm9kZShub2RlKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUucmVtb3ZlTm9kZSA9IGZ1bmN0aW9uIChub2RlSWQpIHtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC5yZW1vdmVOb2RlKG5vZGVJZCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLmFkZE5vZGUgPSBmdW5jdGlvbiAocGFyZW50Tm9kZUlkLCBub2RlKSB7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3guYWRkTm9kZShwYXJlbnROb2RlSWQsIG5vZGUpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5zZWxlY3ROb2RlQnlJZCA9IGZ1bmN0aW9uIChub2RlSWQpIHtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC5zZXRTZWxlY3RlZEVudHJ5QnlJZChub2RlSWQpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5nZXRFZGl0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kZWRpdG9yWzBdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQucmVtb3ZlQ2xhc3MoJ3RyLW9yaWdpbmFsLWlucHV0JykuaW5zZXJ0QmVmb3JlKHRoaXMuJGNvbXBvbmVudFdyYXBwZXIpO1xuICAgICAgICAgICAgdGhpcy4kY29tcG9uZW50V3JhcHBlci5yZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUuZ2V0TWFpbkRvbUVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kY29tcG9uZW50V3JhcHBlclswXTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFRyaXZpYWxUcmVlO1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsVHJlZSA9IFRyaXZpYWxUcmVlO1xufSk7XG5cblxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIiwgXCJqcXVlcnlcIiwgXCJtdXN0YWNoZVwiLCBcIi4vVHJpdmlhbENvcmVcIiwgXCIuL1RyaXZpYWxFdmVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBNdXN0YWNoZSA9IHJlcXVpcmUoXCJtdXN0YWNoZVwiKTtcbiAgICB2YXIgVHJpdmlhbENvcmVfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxDb3JlXCIpO1xuICAgIHZhciBUcml2aWFsRXZlbnRfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxFdmVudFwiKTtcbiAgICB2YXIgVHJpdmlhbFRyZWVCb3ggPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsVHJlZUJveCgkY29udGFpbmVyLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMub25Ob2RlRXhwYW5zaW9uU3RhdGVDaGFuZ2VkID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuY29uZmlnID0gJC5leHRlbmQoe1xuICAgICAgICAgICAgICAgIHZhbHVlRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkgeyByZXR1cm4gZW50cnkgPyBcIlwiICsgZW50cnkuaWQgOiBudWxsOyB9LFxuICAgICAgICAgICAgICAgIGNoaWxkcmVuUHJvcGVydHk6IFwiY2hpbGRyZW5cIixcbiAgICAgICAgICAgICAgICBsYXp5Q2hpbGRyZW5GbGFnUHJvcGVydHk6IFwiaGFzTGF6eUNoaWxkcmVuXCIsXG4gICAgICAgICAgICAgICAgbGF6eUNoaWxkcmVuUXVlcnlGdW5jdGlvbjogZnVuY3Rpb24gKG5vZGUsIHJlc3VsdENhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdENhbGxiYWNrKG5vZGUuY2hpbGRyZW4gfHwgW10pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXhwYW5kZWRQcm9wZXJ0eTogJ2V4cGFuZGVkJyxcbiAgICAgICAgICAgICAgICBlbnRyeVJlbmRlcmluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnksIGRlcHRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkZWZhdWx0VGVtcGxhdGVzID0gW1RyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuaWNvbjJMaW5lc1RlbXBsYXRlLCBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmljb25TaW5nbGVMaW5lVGVtcGxhdGVdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSBlbnRyeS50ZW1wbGF0ZSB8fCBkZWZhdWx0VGVtcGxhdGVzW01hdGgubWluKGRlcHRoLCBkZWZhdWx0VGVtcGxhdGVzLmxlbmd0aCAtIDEpXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE11c3RhY2hlLnJlbmRlcih0ZW1wbGF0ZSwgZW50cnkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc3Bpbm5lclRlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHRTcGlubmVyVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgbm9FbnRyaWVzVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdE5vRW50cmllc1RlbXBsYXRlLFxuICAgICAgICAgICAgICAgIGVudHJpZXM6IG51bGwsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeUlkOiBudWxsLFxuICAgICAgICAgICAgICAgIG1hdGNoaW5nT3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ01vZGU6ICdjb250YWlucycsXG4gICAgICAgICAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGFuaW1hdGlvbkR1cmF0aW9uOiA3MCxcbiAgICAgICAgICAgICAgICBzaG93RXhwYW5kZXJzOiB0cnVlLFxuICAgICAgICAgICAgICAgIG9wZW5PblNlbGVjdGlvbjogZmFsc2UsXG4gICAgICAgICAgICAgICAgZW5mb3JjZVNpbmdsZUV4cGFuZGVkUGF0aDogZmFsc2VcbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gdGhpcy5jb25maWcuZW50cmllcztcbiAgICAgICAgICAgIHRoaXMuJGNvbXBvbmVudFdyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItdHJlZWJveFwiLz4nKS5hcHBlbmRUbygkY29udGFpbmVyKTtcbiAgICAgICAgICAgIHRoaXMuJGNvbXBvbmVudFdyYXBwZXIudG9nZ2xlQ2xhc3MoXCJoaWRlLWV4cGFuZGVyc1wiLCAhdGhpcy5jb25maWcuc2hvd0V4cGFuZGVycyk7XG4gICAgICAgICAgICB0aGlzLiR0cmVlID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyZWUtZW50cnlUcmVlXCI+PC9kaXY+JykuYXBwZW5kVG8odGhpcy4kY29tcG9uZW50V3JhcHBlcik7XG4gICAgICAgICAgICBpZiAodGhpcy5lbnRyaWVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVFbnRyaWVzKHRoaXMuZW50cmllcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkoKHRoaXMuY29uZmlnLnNlbGVjdGVkRW50cnlJZCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuY29uZmlnLnNlbGVjdGVkRW50cnlJZCAhPT0gbnVsbCkgPyB0aGlzLmZpbmRFbnRyeUJ5SWQodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeUlkKSA6IG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5pc0xlYWYgPSBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgIHJldHVybiAoZW50cnlbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0gPT0gbnVsbCB8fCBlbnRyeVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XS5sZW5ndGggPT0gMCkgJiYgIWVudHJ5W3RoaXMuY29uZmlnLmxhenlDaGlsZHJlbkZsYWdQcm9wZXJ0eV07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5jcmVhdGVFbnRyeUVsZW1lbnQgPSBmdW5jdGlvbiAoZW50cnksIGRlcHRoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIGxlYWYgPSB0aGlzLmlzTGVhZihlbnRyeSk7XG4gICAgICAgICAgICB2YXIgJG91dGVyRW50cnlXcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyZWUtZW50cnktb3V0ZXItd3JhcHBlciAnICsgKGxlYWYgPyAnJyA6ICdoYXMtY2hpbGRyZW4nKSArICdcIiBkYXRhLWRlcHRoPVwiJyArIGRlcHRoICsgJ1wiPjwvZGl2PicpO1xuICAgICAgICAgICAgZW50cnkuX3RyRW50cnlFbGVtZW50ID0gJG91dGVyRW50cnlXcmFwcGVyO1xuICAgICAgICAgICAgdmFyICRlbnRyeUFuZEV4cGFuZGVyV3JhcHBlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmVlLWVudHJ5LWFuZC1leHBhbmRlci13cmFwcGVyXCI+PC9kaXY+JylcbiAgICAgICAgICAgICAgICAuYXBwZW5kVG8oJG91dGVyRW50cnlXcmFwcGVyKTtcbiAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgZGVwdGg7IGsrKykge1xuICAgICAgICAgICAgICAgICRlbnRyeUFuZEV4cGFuZGVyV3JhcHBlci5hcHBlbmQoJzxkaXYgY2xhc3M9XCJ0ci1pbmRlbnQtc3BhY2VyXCIvPicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyICRleHBhbmRlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmVlLWV4cGFuZGVyXCI+PC9kaXY+JylcbiAgICAgICAgICAgICAgICAuYXBwZW5kVG8oJGVudHJ5QW5kRXhwYW5kZXJXcmFwcGVyKTtcbiAgICAgICAgICAgIHZhciAkZW50cnkgPSAkKHRoaXMuY29uZmlnLmVudHJ5UmVuZGVyaW5nRnVuY3Rpb24oZW50cnksIGRlcHRoKSk7XG4gICAgICAgICAgICAkZW50cnkuYWRkQ2xhc3MoXCJ0ci10cmVlLWVudHJ5IGZpbHRlcmFibGUtaXRlbVwiKS5hcHBlbmRUbygkZW50cnlBbmRFeHBhbmRlcldyYXBwZXIpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24oZW50cnkpID09PSB0aGlzLnNlbGVjdGVkRW50cnlJZCkge1xuICAgICAgICAgICAgICAgICRlbnRyeUFuZEV4cGFuZGVyV3JhcHBlci5hZGRDbGFzcyhcInRyLXNlbGVjdGVkLWVudHJ5XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGVudHJ5QW5kRXhwYW5kZXJXcmFwcGVyXG4gICAgICAgICAgICAgICAgLm1vdXNlZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLiRjb21wb25lbnRXcmFwcGVyLnRyaWdnZXIoXCJtb3VzZWRvd25cIiwgZSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShlbnRyeSk7XG4gICAgICAgICAgICB9KS5tb3VzZXVwKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuJGNvbXBvbmVudFdyYXBwZXIudHJpZ2dlcihcIm1vdXNldXBcIiwgZSk7XG4gICAgICAgICAgICB9KS5tb3VzZWVudGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZXRIaWdobGlnaHRlZEVudHJ5KGVudHJ5KTtcbiAgICAgICAgICAgIH0pLm1vdXNlbGVhdmUoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISQoZS50b0VsZW1lbnQpLmlzKCcudHItdHJlZS1lbnRyeS1vdXRlci13cmFwcGVyJykpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0SGlnaGxpZ2h0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghbGVhZikge1xuICAgICAgICAgICAgICAgIHZhciAkY2hpbGRyZW5XcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyZWUtZW50cnktY2hpbGRyZW4td3JhcHBlclwiPjwvZGl2PicpXG4gICAgICAgICAgICAgICAgICAgIC5hcHBlbmRUbygkb3V0ZXJFbnRyeVdyYXBwZXIpO1xuICAgICAgICAgICAgICAgICRleHBhbmRlci5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSkuY2xpY2soZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0Tm9kZUV4cGFuZGVkKGVudHJ5LCAhZW50cnlbX3RoaXMuY29uZmlnLmV4cGFuZGVkUHJvcGVydHldLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoZW50cnlbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVudHJ5W3RoaXMuY29uZmlnLmV4cGFuZGVkUHJvcGVydHldKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVudHJ5W3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVFbnRyeUVsZW1lbnQoZW50cnlbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV1baV0sIGRlcHRoICsgMSkuYXBwZW5kVG8oJGNoaWxkcmVuV3JhcHBlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZW50cnlbdGhpcy5jb25maWcubGF6eUNoaWxkcmVuRmxhZ1Byb3BlcnR5XSkge1xuICAgICAgICAgICAgICAgICAgICAkY2hpbGRyZW5XcmFwcGVyLmhpZGUoKS5hcHBlbmQodGhpcy5jb25maWcuc3Bpbm5lclRlbXBsYXRlKS5mYWRlSW4oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zZXROb2RlRXhwYW5kZWQoZW50cnksIGVudHJ5W3RoaXMuY29uZmlnLmV4cGFuZGVkUHJvcGVydHldLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJG91dGVyRW50cnlXcmFwcGVyO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUudXBkYXRlVHJlZUVudHJ5RWxlbWVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiR0cmVlLmRldGFjaCgpO1xuICAgICAgICAgICAgdGhpcy4kdHJlZSA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmVlLWVudHJ5VHJlZVwiPjwvZGl2PicpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZW50cmllcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVFbnRyeUVsZW1lbnQodGhpcy5lbnRyaWVzW2ldLCAwKS5hcHBlbmRUbyh0aGlzLiR0cmVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLiR0cmVlLmFwcGVuZCh0aGlzLmNvbmZpZy5ub0VudHJpZXNUZW1wbGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiR0cmVlLmFwcGVuZFRvKHRoaXMuJGNvbXBvbmVudFdyYXBwZXIpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuc2V0Tm9kZUV4cGFuZGVkID0gZnVuY3Rpb24gKG5vZGUsIGV4cGFuZGVkLCBhbmltYXRlKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIHdhc0V4cGFuZGVkID0gbm9kZVt0aGlzLmNvbmZpZy5leHBhbmRlZFByb3BlcnR5XTtcbiAgICAgICAgICAgIGlmIChleHBhbmRlZCAmJiB0aGlzLmNvbmZpZy5lbmZvcmNlU2luZ2xlRXhwYW5kZWRQYXRoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRseUV4cGFuZGVkTm9kZXMgPSB0aGlzLmZpbmRFbnRyaWVzKGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAhIShuW190aGlzLmNvbmZpZy5leHBhbmRlZFByb3BlcnR5XSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld0V4cGFuZGVkUGF0aCA9IHRoaXMuZmluZFBhdGhUb0ZpcnN0TWF0Y2hpbmdOb2RlKGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuID09PSBub2RlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY3VycmVudGx5RXhwYW5kZWROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY3VycmVudGx5RXhwYW5kZWROb2RlID0gY3VycmVudGx5RXhwYW5kZWROb2Rlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0V4cGFuZGVkUGF0aC5pbmRleE9mKGN1cnJlbnRseUV4cGFuZGVkTm9kZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldE5vZGVFeHBhbmRlZChjdXJyZW50bHlFeHBhbmRlZE5vZGUsIGZhbHNlLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5vZGVbdGhpcy5jb25maWcuZXhwYW5kZWRQcm9wZXJ0eV0gPSAhIWV4cGFuZGVkO1xuICAgICAgICAgICAgbm9kZS5fdHJFbnRyeUVsZW1lbnQudG9nZ2xlQ2xhc3MoXCJleHBhbmRlZFwiLCAhIWV4cGFuZGVkKTtcbiAgICAgICAgICAgIHZhciBub2RlSGFzVW5yZW5kZXJlZENoaWxkcmVuID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0gJiYgbm9kZVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0uc29tZShmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICFjaGlsZC5fdHJFbnRyeUVsZW1lbnQgfHwgISQuY29udGFpbnMoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCBjaGlsZC5fdHJFbnRyeUVsZW1lbnRbMF0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChleHBhbmRlZCAmJiBub2RlW3RoaXMuY29uZmlnLmxhenlDaGlsZHJlbkZsYWdQcm9wZXJ0eV0gJiYgIW5vZGVbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5sYXp5Q2hpbGRyZW5RdWVyeUZ1bmN0aW9uKG5vZGUsIGZ1bmN0aW9uIChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRDaGlsZHJlbihub2RlLCBjaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChleHBhbmRlZCAmJiBub2RlSGFzVW5yZW5kZXJlZENoaWxkcmVuKG5vZGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJDaGlsZHJlbihub2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChleHBhbmRlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWluaW1hbGx5U2Nyb2xsVG8obm9kZS5fdHJFbnRyeUVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGNoaWxkcmVuV3JhcHBlciA9IG5vZGUuX3RyRW50cnlFbGVtZW50LmZpbmQoXCI+IC50ci10cmVlLWVudHJ5LWNoaWxkcmVuLXdyYXBwZXJcIik7XG4gICAgICAgICAgICBpZiAoZXhwYW5kZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAoYW5pbWF0ZSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbldyYXBwZXIuc2xpZGVEb3duKHRoaXMuY29uZmlnLmFuaW1hdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuV3JhcHBlci5jc3MoXCJkaXNwbGF5XCIsIFwiYmxvY2tcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGFuaW1hdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW5XcmFwcGVyLnNsaWRlVXAodGhpcy5jb25maWcuYW5pbWF0aW9uRHVyYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW5XcmFwcGVyLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISF3YXNFeHBhbmRlZCAhPSAhIWV4cGFuZGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbk5vZGVFeHBhbnNpb25TdGF0ZUNoYW5nZWQuZmlyZShub2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLm5vZGVEZXB0aCA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9kZSA/IHBhcnNlSW50KG5vZGUuX3RyRW50cnlFbGVtZW50LmF0dHIoJ2RhdGEtZGVwdGgnKSkgOiAwO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuc2V0Q2hpbGRyZW4gPSBmdW5jdGlvbiAobm9kZSwgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgIG5vZGVbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0gPSBjaGlsZHJlbjtcbiAgICAgICAgICAgIG5vZGVbdGhpcy5jb25maWcubGF6eUNoaWxkcmVuRmxhZ1Byb3BlcnR5XSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJDaGlsZHJlbihub2RlKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLnJlbmRlckNoaWxkcmVuID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgIHZhciAkY2hpbGRyZW5XcmFwcGVyID0gbm9kZS5fdHJFbnRyeUVsZW1lbnQuZmluZCgnPiAudHItdHJlZS1lbnRyeS1jaGlsZHJlbi13cmFwcGVyJyk7XG4gICAgICAgICAgICAkY2hpbGRyZW5XcmFwcGVyLmVtcHR5KCk7XG4gICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSBub2RlW3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldO1xuICAgICAgICAgICAgaWYgKGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgZGVwdGggPSB0aGlzLm5vZGVEZXB0aChub2RlKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUVudHJ5RWxlbWVudChjaGlsZCwgZGVwdGggKyAxKS5hcHBlbmRUbygkY2hpbGRyZW5XcmFwcGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBub2RlLl90ckVudHJ5RWxlbWVudC5yZW1vdmVDbGFzcygnaGFzLWNoaWxkcmVuIGV4cGFuZGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS51cGRhdGVFbnRyaWVzID0gZnVuY3Rpb24gKG5ld0VudHJpZXMpIHtcbiAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmVudHJpZXMgPSBuZXdFbnRyaWVzO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVUcmVlRW50cnlFbGVtZW50cygpO1xuICAgICAgICAgICAgdmFyIHNlbGVjdGVkRW50cnkgPSB0aGlzLmZpbmRFbnRyeUJ5SWQodGhpcy5zZWxlY3RlZEVudHJ5SWQpO1xuICAgICAgICAgICAgaWYgKHNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1hcmtTZWxlY3RlZEVudHJ5KHNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuZmluZEVudHJpZXMgPSBmdW5jdGlvbiAoZmlsdGVyRnVuY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgZmluZEVudHJpZXNJblN1YlRyZWUgPSBmdW5jdGlvbiAobm9kZSwgbGlzdE9mRm91bmRFbnRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZpbHRlckZ1bmN0aW9uLmNhbGwoX3RoaXMsIG5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RPZkZvdW5kRW50cmllcy5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobm9kZVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0pIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gbm9kZVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV1baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5kRW50cmllc0luU3ViVHJlZShjaGlsZCwgbGlzdE9mRm91bmRFbnRyaWVzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgbWF0Y2hpbmdFbnRyaWVzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciByb290RW50cnkgPSB0aGlzLmVudHJpZXNbaV07XG4gICAgICAgICAgICAgICAgZmluZEVudHJpZXNJblN1YlRyZWUocm9vdEVudHJ5LCBtYXRjaGluZ0VudHJpZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hdGNoaW5nRW50cmllcztcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmZpbmRQYXRoVG9GaXJzdE1hdGNoaW5nTm9kZSA9IGZ1bmN0aW9uIChwcmVkaWNhdGVGdW5jdGlvbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBzZWFyY2hJblN1YlRyZWUgPSBmdW5jdGlvbiAobm9kZSwgcGF0aCkge1xuICAgICAgICAgICAgICAgIGlmIChwcmVkaWNhdGVGdW5jdGlvbi5jYWxsKF90aGlzLCBub2RlLCBwYXRoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRoLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobm9kZVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1BhdGggPSBwYXRoLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld1BhdGgucHVzaChub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gbm9kZVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV1baV07XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gc2VhcmNoSW5TdWJUcmVlKGNoaWxkLCBuZXdQYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5lbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvb3RFbnRyeSA9IHRoaXMuZW50cmllc1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0aCA9IHNlYXJjaEluU3ViVHJlZShyb290RW50cnksIFtdKTtcbiAgICAgICAgICAgICAgICBpZiAocGF0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5maW5kRW50cnlCeUlkID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluZEVudHJpZXMoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKGVudHJ5KSA9PT0gaWQ7XG4gICAgICAgICAgICB9KVswXTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmZpbmRQYXJlbnROb2RlID0gZnVuY3Rpb24gKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmRFbnRyaWVzKGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlbnRyeVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0gJiYgZW50cnlbX3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldLmluZGV4T2YoY2hpbGROb2RlKSAhPSAtMTtcbiAgICAgICAgICAgIH0pWzBdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuc2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uIChlbnRyeSwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEVudHJ5SWQgPSBlbnRyeSA/IHRoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24oZW50cnkpIDogbnVsbDtcbiAgICAgICAgICAgIHRoaXMubWFya1NlbGVjdGVkRW50cnkoZW50cnkpO1xuICAgICAgICAgICAgdGhpcy5zZXRIaWdobGlnaHRlZEVudHJ5KGVudHJ5KTtcbiAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cyhlbnRyeSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICBpZiAoZW50cnkgJiYgdGhpcy5jb25maWcub3Blbk9uU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXROb2RlRXhwYW5kZWQoZW50cnksIHRydWUsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuc2V0U2VsZWN0ZWRFbnRyeUJ5SWQgPSBmdW5jdGlvbiAobm9kZUlkKSB7XG4gICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkodGhpcy5maW5kRW50cnlCeUlkKG5vZGVJZCksIG51bGwpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUubWluaW1hbGx5U2Nyb2xsVG8gPSBmdW5jdGlvbiAoJGVudHJ5V3JhcHBlcikge1xuICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5taW5pbWFsbHlTY3JvbGxUbyh0aGlzLiRjb21wb25lbnRXcmFwcGVyLnBhcmVudCgpLCAkZW50cnlXcmFwcGVyKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLm1hcmtTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICB0aGlzLiR0cmVlLmZpbmQoXCIudHItc2VsZWN0ZWQtZW50cnlcIikucmVtb3ZlQ2xhc3MoXCJ0ci1zZWxlY3RlZC1lbnRyeVwiKTtcbiAgICAgICAgICAgIGlmIChlbnRyeSAmJiBlbnRyeS5fdHJFbnRyeUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgJGVudHJ5V3JhcHBlciA9IGVudHJ5Ll90ckVudHJ5RWxlbWVudC5maW5kKCc+LnRyLXRyZWUtZW50cnktYW5kLWV4cGFuZGVyLXdyYXBwZXInKTtcbiAgICAgICAgICAgICAgICAkZW50cnlXcmFwcGVyLmFkZENsYXNzKFwidHItc2VsZWN0ZWQtZW50cnlcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5maXJlQ2hhbmdlRXZlbnRzID0gZnVuY3Rpb24gKGVudHJ5LCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLiRjb21wb25lbnRXcmFwcGVyLnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuZmlyZShlbnRyeSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5zZWxlY3ROZXh0RW50cnkgPSBmdW5jdGlvbiAoZGlyZWN0aW9uLCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgbmV4dFZpc2libGVFbnRyeSA9IHRoaXMuZ2V0TmV4dFZpc2libGVFbnRyeSh0aGlzLmdldFNlbGVjdGVkRW50cnkoKSwgZGlyZWN0aW9uKTtcbiAgICAgICAgICAgIGlmIChuZXh0VmlzaWJsZUVudHJ5ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkobmV4dFZpc2libGVFbnRyeSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5zZXRIaWdobGlnaHRlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICBpZiAoZW50cnkgIT09IHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSA9IGVudHJ5O1xuICAgICAgICAgICAgICAgIHRoaXMuJHRyZWUuZmluZCgnLnRyLWhpZ2hsaWdodGVkLWVudHJ5JykucmVtb3ZlQ2xhc3MoJ3RyLWhpZ2hsaWdodGVkLWVudHJ5Jyk7XG4gICAgICAgICAgICAgICAgaWYgKGVudHJ5ICE9IG51bGwgJiYgZW50cnkuX3RyRW50cnlFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkZW50cnkgPSBlbnRyeS5fdHJFbnRyeUVsZW1lbnQuZmluZCgnPi50ci10cmVlLWVudHJ5LWFuZC1leHBhbmRlci13cmFwcGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICRlbnRyeS5hZGRDbGFzcygndHItaGlnaGxpZ2h0ZWQtZW50cnknKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5taW5pbWFsbHlTY3JvbGxUbygkZW50cnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkRW50cnkgPSB0aGlzLmdldFNlbGVjdGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSA9IHNlbGVjdGVkRW50cnk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5nZXROZXh0VmlzaWJsZUVudHJ5ID0gZnVuY3Rpb24gKGN1cnJlbnRFbnRyeSwgZGlyZWN0aW9uLCBvbmx5RW50cmllc1dpdGhUZXh0TWF0Y2hlcykge1xuICAgICAgICAgICAgaWYgKG9ubHlFbnRyaWVzV2l0aFRleHRNYXRjaGVzID09PSB2b2lkIDApIHsgb25seUVudHJpZXNXaXRoVGV4dE1hdGNoZXMgPSBmYWxzZTsgfVxuICAgICAgICAgICAgdmFyIG5ld1NlbGVjdGVkRWxlbWVudEluZGV4O1xuICAgICAgICAgICAgdmFyIHZpc2libGVFbnRyaWVzQXNMaXN0ID0gdGhpcy5maW5kRW50cmllcyhmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWVudHJ5Ll90ckVudHJ5RWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAob25seUVudHJpZXNXaXRoVGV4dE1hdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbnRyeS5fdHJFbnRyeUVsZW1lbnQuaXMoJzp2aXNpYmxlJykgJiYgZW50cnkuX3RyRW50cnlFbGVtZW50LmhhcygnPi50ci10cmVlLWVudHJ5LWFuZC1leHBhbmRlci13cmFwcGVyIC50ci1oaWdobGlnaHRlZC10ZXh0JykubGVuZ3RoID4gMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbnRyeS5fdHJFbnRyeUVsZW1lbnQuaXMoJzp2aXNpYmxlJykgfHwgZW50cnkgPT09IGN1cnJlbnRFbnRyeTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHZpc2libGVFbnRyaWVzQXNMaXN0ID09IG51bGwgfHwgdmlzaWJsZUVudHJpZXNBc0xpc3QubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGN1cnJlbnRFbnRyeSA9PSBudWxsICYmIGRpcmVjdGlvbiA+IDApIHtcbiAgICAgICAgICAgICAgICBuZXdTZWxlY3RlZEVsZW1lbnRJbmRleCA9IC0xICsgZGlyZWN0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY3VycmVudEVudHJ5ID09IG51bGwgJiYgZGlyZWN0aW9uIDwgMCkge1xuICAgICAgICAgICAgICAgIG5ld1NlbGVjdGVkRWxlbWVudEluZGV4ID0gdmlzaWJsZUVudHJpZXNBc0xpc3QubGVuZ3RoICsgZGlyZWN0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRTZWxlY3RlZEVsZW1lbnRJbmRleCA9IHZpc2libGVFbnRyaWVzQXNMaXN0LmluZGV4T2YoY3VycmVudEVudHJ5KTtcbiAgICAgICAgICAgICAgICBuZXdTZWxlY3RlZEVsZW1lbnRJbmRleCA9IChjdXJyZW50U2VsZWN0ZWRFbGVtZW50SW5kZXggKyB2aXNpYmxlRW50cmllc0FzTGlzdC5sZW5ndGggKyBkaXJlY3Rpb24pICUgdmlzaWJsZUVudHJpZXNBc0xpc3QubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZpc2libGVFbnRyaWVzQXNMaXN0W25ld1NlbGVjdGVkRWxlbWVudEluZGV4XTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmhpZ2hsaWdodFRleHRNYXRjaGVzID0gZnVuY3Rpb24gKHNlYXJjaFN0cmluZykge1xuICAgICAgICAgICAgdGhpcy4kdHJlZS5kZXRhY2goKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5lbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy5lbnRyaWVzW2ldO1xuICAgICAgICAgICAgICAgIHZhciAkZW50cnlFbGVtZW50ID0gZW50cnkuX3RyRW50cnlFbGVtZW50LmZpbmQoJy50ci10cmVlLWVudHJ5Jyk7XG4gICAgICAgICAgICAgICAgJGVudHJ5RWxlbWVudC50cml2aWFsSGlnaGxpZ2h0KHNlYXJjaFN0cmluZywgdGhpcy5jb25maWcubWF0Y2hpbmdPcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJHRyZWUuYXBwZW5kVG8odGhpcy4kY29tcG9uZW50V3JhcHBlcik7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5nZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLnNlbGVjdGVkRW50cnlJZCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc2VsZWN0ZWRFbnRyeUlkICE9PSBudWxsKSA/IHRoaXMuZmluZEVudHJ5QnlJZCh0aGlzLnNlbGVjdGVkRW50cnlJZCkgOiBudWxsO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUucmV2ZWFsU2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uIChhbmltYXRlKSB7XG4gICAgICAgICAgICBpZiAoYW5pbWF0ZSA9PT0gdm9pZCAwKSB7IGFuaW1hdGUgPSBmYWxzZTsgfVxuICAgICAgICAgICAgdmFyIHNlbGVjdGVkRW50cnkgPSB0aGlzLmdldFNlbGVjdGVkRW50cnkoKTtcbiAgICAgICAgICAgIGlmICghc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjdXJyZW50RW50cnkgPSBzZWxlY3RlZEVudHJ5O1xuICAgICAgICAgICAgd2hpbGUgKGN1cnJlbnRFbnRyeSA9IHRoaXMuZmluZFBhcmVudE5vZGUoY3VycmVudEVudHJ5KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0Tm9kZUV4cGFuZGVkKGN1cnJlbnRFbnRyeSwgdHJ1ZSwgYW5pbWF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLm1pbmltYWxseVNjcm9sbFRvKHNlbGVjdGVkRW50cnkuX3RyRW50cnlFbGVtZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmhpZ2hsaWdodE5leHRFbnRyeSA9IGZ1bmN0aW9uIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBuZXh0VmlzaWJsZUVudHJ5ID0gdGhpcy5nZXROZXh0VmlzaWJsZUVudHJ5KHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSB8fCB0aGlzLmdldFNlbGVjdGVkRW50cnkoKSwgZGlyZWN0aW9uKTtcbiAgICAgICAgICAgIGlmIChuZXh0VmlzaWJsZUVudHJ5ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEhpZ2hsaWdodGVkRW50cnkobmV4dFZpc2libGVFbnRyeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5oaWdobGlnaHROZXh0TWF0Y2hpbmdFbnRyeSA9IGZ1bmN0aW9uIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBuZXh0TWF0Y2hpbmdFbnRyeSA9IHRoaXMuZ2V0TmV4dFZpc2libGVFbnRyeSh0aGlzLmhpZ2hsaWdodGVkRW50cnkgfHwgdGhpcy5nZXRTZWxlY3RlZEVudHJ5KCksIGRpcmVjdGlvbiwgdHJ1ZSk7XG4gICAgICAgICAgICBpZiAobmV4dE1hdGNoaW5nRW50cnkgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SGlnaGxpZ2h0ZWRFbnRyeShuZXh0TWF0Y2hpbmdFbnRyeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5zZWxlY3ROZXh0TWF0Y2hpbmdFbnRyeSA9IGZ1bmN0aW9uIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBuZXh0TWF0Y2hpbmdFbnRyeSA9IHRoaXMuZ2V0TmV4dFZpc2libGVFbnRyeSh0aGlzLmhpZ2hsaWdodGVkRW50cnksIGRpcmVjdGlvbiwgdHJ1ZSk7XG4gICAgICAgICAgICBpZiAobmV4dE1hdGNoaW5nRW50cnkgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0ZWRFbnRyeShuZXh0TWF0Y2hpbmdFbnRyeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5nZXRIaWdobGlnaHRlZEVudHJ5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLnNldEhpZ2hsaWdodGVkTm9kZUV4cGFuZGVkID0gZnVuY3Rpb24gKGV4cGFuZGVkKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSB8fCB0aGlzLmlzTGVhZih0aGlzLmhpZ2hsaWdodGVkRW50cnkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHdhc0V4cGFuZGVkID0gdGhpcy5oaWdobGlnaHRlZEVudHJ5W3RoaXMuY29uZmlnLmV4cGFuZGVkUHJvcGVydHldO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0Tm9kZUV4cGFuZGVkKHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSwgZXhwYW5kZWQsIHRydWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiAhd2FzRXhwYW5kZWQgIT0gIWV4cGFuZGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUudXBkYXRlQ2hpbGRyZW4gPSBmdW5jdGlvbiAocGFyZW50Tm9kZUlkLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmZpbmRFbnRyeUJ5SWQocGFyZW50Tm9kZUlkKTtcbiAgICAgICAgICAgIGlmIChub2RlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRDaGlsZHJlbihub2RlLCBjaGlsZHJlbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2b2lkIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLnVwZGF0ZU5vZGUgPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgdmFyIG9sZE5vZGUgPSB0aGlzLmZpbmRFbnRyeUJ5SWQodGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihub2RlKSk7XG4gICAgICAgICAgICB2YXIgcGFyZW50ID0gdGhpcy5maW5kUGFyZW50Tm9kZShvbGROb2RlKTtcbiAgICAgICAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnRbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV1bcGFyZW50W3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldLmluZGV4T2Yob2xkTm9kZSldID0gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZW50cmllc1t0aGlzLmVudHJpZXMuaW5kZXhPZihvbGROb2RlKV0gPSBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jcmVhdGVFbnRyeUVsZW1lbnQobm9kZSwgdGhpcy5ub2RlRGVwdGgob2xkTm9kZSkpLmluc2VydEFmdGVyKG9sZE5vZGUuX3RyRW50cnlFbGVtZW50KTtcbiAgICAgICAgICAgIG9sZE5vZGUuX3RyRW50cnlFbGVtZW50LnJlbW92ZSgpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5yZW1vdmVOb2RlID0gZnVuY3Rpb24gKG5vZGVJZCkge1xuICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IHRoaXMuZmluZEVudHJ5QnlJZChub2RlSWQpO1xuICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gdGhpcy5maW5kUGFyZW50Tm9kZShjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGVbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0uc3BsaWNlKHBhcmVudE5vZGVbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0uaW5kZXhPZihjaGlsZE5vZGUpLCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW50cmllcy5zcGxpY2UodGhpcy5lbnRyaWVzLmluZGV4T2YoY2hpbGROb2RlKSwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNoaWxkTm9kZS5fdHJFbnRyeUVsZW1lbnQucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmFkZE5vZGUgPSBmdW5jdGlvbiAocGFyZW50Tm9kZUlkLCBub2RlKSB7XG4gICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IHRoaXMuZmluZEVudHJ5QnlJZChwYXJlbnROb2RlSWQpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNMZWFmKHBhcmVudE5vZGUpKSB7XG4gICAgICAgICAgICAgICAgdm9pZCAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFwYXJlbnROb2RlW3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldKSB7XG4gICAgICAgICAgICAgICAgcGFyZW50Tm9kZVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyZW50Tm9kZVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XS5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgdmFyIGVudHJ5RWxlbWVudCA9IHRoaXMuY3JlYXRlRW50cnlFbGVtZW50KG5vZGUsIHRoaXMubm9kZURlcHRoKHBhcmVudE5vZGUpICsgMSk7XG4gICAgICAgICAgICBlbnRyeUVsZW1lbnRcbiAgICAgICAgICAgICAgICAuYXBwZW5kVG8ocGFyZW50Tm9kZS5fdHJFbnRyeUVsZW1lbnQuZmluZCgnPi50ci10cmVlLWVudHJ5LWNoaWxkcmVuLXdyYXBwZXInKSk7XG4gICAgICAgICAgICBwYXJlbnROb2RlLl90ckVudHJ5RWxlbWVudC5hZGRDbGFzcygnaGFzLWNoaWxkcmVuJyk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRjb21wb25lbnRXcmFwcGVyLnJlbW92ZSgpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5nZXRNYWluRG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRjb21wb25lbnRXcmFwcGVyWzBdO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJpdmlhbFRyZWVCb3g7XG4gICAgfSgpKTtcbiAgICBleHBvcnRzLlRyaXZpYWxUcmVlQm94ID0gVHJpdmlhbFRyZWVCb3g7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIm11c3RhY2hlXCIsIFwiLi9Ucml2aWFsQ29yZVwiLCBcIi4vVHJpdmlhbFRyZWVCb3hcIiwgXCIuL1RyaXZpYWxFdmVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBNdXN0YWNoZSA9IHJlcXVpcmUoXCJtdXN0YWNoZVwiKTtcbiAgICB2YXIgVHJpdmlhbENvcmVfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxDb3JlXCIpO1xuICAgIHZhciBUcml2aWFsVHJlZUJveF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbFRyZWVCb3hcIik7XG4gICAgdmFyIFRyaXZpYWxFdmVudF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpO1xuICAgIHZhciBUcml2aWFsVHJlZUNvbWJvQm94ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gVHJpdmlhbFRyZWVDb21ib0JveChvcmlnaW5hbElucHV0LCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuaXNFZGl0b3JWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmxhc3RRdWVyeVN0cmluZyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmxhc3RDb21wbGV0ZUlucHV0UXVlcnlTdHJpbmcgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEVudHJ5ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMubGFzdENvbW1pdHRlZFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuYXV0b0NvbXBsZXRlVGltZW91dElkID0gLTE7XG4gICAgICAgICAgICB0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycyA9ICQoKTtcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3RlZEVudHJ5Q2hhbmdlZCA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9uRm9jdXMgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbkJsdXIgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5jb25maWcgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgdmFsdWVGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7IHJldHVybiBlbnRyeSA/IFwiXCIgKyBlbnRyeS5pZCA6IG51bGw7IH0sXG4gICAgICAgICAgICAgICAgZW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5LCBkZXB0aCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGVmYXVsdFRlbXBsYXRlcyA9IFtUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmljb24yTGluZXNUZW1wbGF0ZSwgVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5pY29uU2luZ2xlTGluZVRlbXBsYXRlXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRlbXBsYXRlID0gZGVmYXVsdFRlbXBsYXRlc1tNYXRoLm1pbihkZXB0aCwgZGVmYXVsdFRlbXBsYXRlcy5sZW5ndGggLSAxKV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNdXN0YWNoZS5yZW5kZXIodGVtcGxhdGUsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5jb25maWcuZW50cnlSZW5kZXJpbmdGdW5jdGlvbihlbnRyeSwgMCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJ5OiBudWxsLFxuICAgICAgICAgICAgICAgIHNwaW5uZXJUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0U3Bpbm5lclRlbXBsYXRlLFxuICAgICAgICAgICAgICAgIG5vRW50cmllc1RlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHROb0VudHJpZXNUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICB0ZXh0SGlnaGxpZ2h0aW5nRW50cnlMaW1pdDogMTAwLFxuICAgICAgICAgICAgICAgIGVudHJpZXM6IG51bGwsXG4gICAgICAgICAgICAgICAgcXVlcnlGdW5jdGlvbjogbnVsbCxcbiAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGU6IHRydWUsXG4gICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlRGVsYXk6IDAsXG4gICAgICAgICAgICAgICAgZW50cnlUb0VkaXRvclRleHRGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBlbnRyeVtcImRpc3BsYXlWYWx1ZVwiXTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZUZ1bmN0aW9uOiBmdW5jdGlvbiAoZWRpdG9yVGV4dCwgZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVkaXRvclRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BlcnR5TmFtZSBpbiBlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eVZhbHVlID0gZW50cnlbcHJvcGVydHlOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydHlWYWx1ZSAmJiBwcm9wZXJ0eVZhbHVlLnRvU3RyaW5nKCkudG9Mb3dlckNhc2UoKS5pbmRleE9mKGVkaXRvclRleHQudG9Mb3dlckNhc2UoKSkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb3BlcnR5VmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbnRyeSA/IF90aGlzLmNvbmZpZy5lbnRyeVRvRWRpdG9yVGV4dEZ1bmN0aW9uKGVudHJ5KSA6IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGFsbG93RnJlZVRleHQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGZyZWVUZXh0RW50cnlGYWN0b3J5OiBmdW5jdGlvbiAoZnJlZVRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXlWYWx1ZTogZnJlZVRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICBfaXNGcmVlVGV4dEVudHJ5OiB0cnVlXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzaG93Q2xlYXJCdXR0b246IGZhbHNlLFxuICAgICAgICAgICAgICAgIHNob3dUcmlnZ2VyOiB0cnVlLFxuICAgICAgICAgICAgICAgIG1hdGNoaW5nT3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ01vZGU6ICdjb250YWlucycsXG4gICAgICAgICAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNoaWxkcmVuUHJvcGVydHk6IFwiY2hpbGRyZW5cIixcbiAgICAgICAgICAgICAgICBsYXp5Q2hpbGRyZW5GbGFnUHJvcGVydHk6IFwiaGFzTGF6eUNoaWxkcmVuXCIsXG4gICAgICAgICAgICAgICAgZXhwYW5kZWRQcm9wZXJ0eTogJ2V4cGFuZGVkJyxcbiAgICAgICAgICAgICAgICBlZGl0aW5nTW9kZTogXCJlZGl0YWJsZVwiLFxuICAgICAgICAgICAgICAgIHNob3dEcm9wRG93bk9uUmVzdWx0c09ubHk6IGZhbHNlXG4gICAgICAgICAgICB9LCBvcHRpb25zKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLnF1ZXJ5RnVuY3Rpb24gPSBUcml2aWFsQ29yZV8xLmRlZmF1bHRUcmVlUXVlcnlGdW5jdGlvbkZhY3RvcnkodGhpcy5jb25maWcuZW50cmllcyB8fCBbXSwgVHJpdmlhbENvcmVfMS5kZWZhdWx0RW50cnlNYXRjaGluZ0Z1bmN0aW9uRmFjdG9yeShbXCJkaXNwbGF5VmFsdWVcIiwgXCJhZGRpdGlvbmFsSW5mb1wiXSwgdGhpcy5jb25maWcubWF0Y2hpbmdPcHRpb25zKSwgdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eSwgdGhpcy5jb25maWcuZXhwYW5kZWRQcm9wZXJ0eSk7XG4gICAgICAgICAgICAgICAgdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQgPSAkKG9yaWdpbmFsSW5wdXQpO1xuICAgICAgICAgICAgdGhpcy4kdHJlZUNvbWJvQm94ID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyZWVjb21ib2JveCB0ci1jb21ib2JveCB0ci1pbnB1dC13cmFwcGVyXCIvPicpXG4gICAgICAgICAgICAgICAgLmluc2VydEFmdGVyKHRoaXMuJG9yaWdpbmFsSW5wdXQpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItY29tYm9ib3gtc2VsZWN0ZWQtZW50cnktd3JhcHBlclwiLz4nKS5hcHBlbmRUbyh0aGlzLiR0cmVlQ29tYm9Cb3gpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNob3dDbGVhckJ1dHRvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuJGNsZWFyQnV0dG9uID0gJCgnPGRpdiBjbGFzcz1cInRyLXJlbW92ZS1idXR0b25cIj4nKS5hcHBlbmRUbyh0aGlzLiR0cmVlQ29tYm9Cb3gpO1xuICAgICAgICAgICAgICAgIHRoaXMuJGNsZWFyQnV0dG9uLm1vdXNlZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnZhbChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShudWxsLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5zaG93VHJpZ2dlcikge1xuICAgICAgICAgICAgICAgIHRoaXMuJHRyaWdnZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItdHJpZ2dlclwiPjxzcGFuIGNsYXNzPVwidHItdHJpZ2dlci1pY29uXCIvPjwvZGl2PicpLmFwcGVuZFRvKHRoaXMuJHRyZWVDb21ib0JveCk7XG4gICAgICAgICAgICAgICAgdGhpcy4kdHJpZ2dlci5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kZHJvcERvd24gPSAkKCc8ZGl2IGNsYXNzPVwidHItZHJvcGRvd25cIj48L2Rpdj4nKVxuICAgICAgICAgICAgICAgIC5zY3JvbGwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd25UYXJnZXRFbGVtZW50ID0gJChcImJvZHlcIik7XG4gICAgICAgICAgICB0aGlzLnNldEVkaXRpbmdNb2RlKHRoaXMuY29uZmlnLmVkaXRpbmdNb2RlKTtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQuYWRkQ2xhc3MoXCJ0ci1vcmlnaW5hbC1pbnB1dFwiKTtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvciA9ICQoJzxpbnB1dCB0eXBlPVwidGV4dFwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiLz4nKTtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvci5wcmVwZW5kVG8odGhpcy4kdHJlZUNvbWJvQm94KS5hZGRDbGFzcyhcInRyLWNvbWJvYm94LWVkaXRvciB0ci1lZGl0b3JcIilcbiAgICAgICAgICAgICAgICAuZm9jdXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJG9yaWdpbmFsSW5wdXQudHJpZ2dlckhhbmRsZXIoJ2ZvY3VzJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9uRm9jdXMuZmlyZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdHJlZUNvbWJvQm94LmFkZENsYXNzKCdmb2N1cycpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuYmx1cihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VySGFuZGxlcignYmx1cicpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vbkJsdXIuZmlyZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdHJlZUNvbWJvQm94LnJlbW92ZUNsYXNzKCdmb2N1cycpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZWRpdG9yQ29udGFpbnNGcmVlVGV4dCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIVRyaXZpYWxDb3JlXzEub2JqZWN0RXF1YWxzKF90aGlzLmdldFNlbGVjdGVkRW50cnkoKSwgX3RoaXMubGFzdENvbW1pdHRlZFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudmFsKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUsIGZhbHNlLCBmYWxzZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGlkZUVkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAua2V5ZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChUcml2aWFsQ29yZV8xLmtleUNvZGVzLmlzTW9kaWZpZXJLZXkoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudGFiKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gX3RoaXMudHJlZUJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3BlbiAmJiBoaWdobGlnaHRlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KGhpZ2hsaWdodGVkRW50cnksIHRydWUsIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFfdGhpcy4kZWRpdG9yLnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KG51bGwsIHRydWUsIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKF90aGlzLmNvbmZpZy5hbGxvd0ZyZWVUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KF90aGlzLmdldFNlbGVjdGVkRW50cnkoKSwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMubGVmdF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hhbmdlZEV4cGFuZGVkU3RhdGUgPSBfdGhpcy50cmVlQm94LnNldEhpZ2hsaWdodGVkTm9kZUV4cGFuZGVkKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hhbmdlZEV4cGFuZGVkU3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXNOb25JZ25vcmVkS2V5ID0gIVRyaXZpYWxDb3JlXzEua2V5Q29kZXMuaXNNb2RpZmllcktleShlKSAmJiBbVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lbnRlciwgVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lc2NhcGUsIFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudGFiXS5pbmRleE9mKGUud2hpY2gpID09PSAtMTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVkaXRvclZhbHVlRG9lc05vdENvcnJlc3BvbmRUb1NlbGVjdGVkVmFsdWUgPSBfdGhpcy5pc0VudHJ5U2VsZWN0ZWQoKSAmJiBfdGhpcy4kZWRpdG9yLnZhbCgpICE9PSBfdGhpcy5jb25maWcuZW50cnlUb0VkaXRvclRleHRGdW5jdGlvbihfdGhpcy5zZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzTm9uSWdub3JlZEtleSAmJiAoZWRpdG9yVmFsdWVEb2VzTm90Q29ycmVzcG9uZFRvU2VsZWN0ZWRWYWx1ZSB8fCBfdGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihfdGhpcy50cmVlQm94LmdldEhpZ2hsaWdodGVkRW50cnkoKSkpICE9PSBfdGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihfdGhpcy5nZXRTZWxlY3RlZEVudHJ5KCkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KG51bGwsIGZhbHNlLCBmYWxzZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmJhY2tzcGFjZSB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZGVsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmRvd25fYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0VkaXRvclZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpcmVjdGlvbiA9IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy51cF9hcnJvdyA/IC0xIDogMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3guaGlnaGxpZ2h0TmV4dEVudHJ5KGRpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5hdXRvQ29tcGxldGVJZlBvc3NpYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRWRpdG9yVmlzaWJsZSB8fCBfdGhpcy5lZGl0b3JDb250YWluc0ZyZWVUZXh0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gX3RoaXMudHJlZUJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4gJiYgaGlnaGxpZ2h0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoaGlnaGxpZ2h0ZWRFbnRyeSwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICghX3RoaXMuJGVkaXRvci52YWwoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkobnVsbCwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChfdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmhpZGVFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZXNjYXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoX3RoaXMuZWRpdG9yQ29udGFpbnNGcmVlVGV4dCgpICYmIF90aGlzLmlzRHJvcERvd25PcGVuKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGlkZUVkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci52YWwoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KF90aGlzLmxhc3RDb21taXR0ZWRWYWx1ZSwgZmFsc2UsIGZhbHNlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmlzRWRpdG9yVmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmNvbmZpZy5zaG93RHJvcERvd25PblJlc3VsdHNPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy50cmVlQm94LnNldEhpZ2hsaWdodGVkRW50cnkobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmF0dHIoXCJ0YWJpbmRleFwiLCB0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJ0YWJpbmRleFwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwiYXV0b2ZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiR0cmVlQ29tYm9Cb3guYWRkKHRoaXMuJGRyb3BEb3duKVxuICAgICAgICAgICAgICAgIC5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5tb3VzZXVwKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm1vdXNlb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy50cmVlQm94ID0gbmV3IFRyaXZpYWxUcmVlQm94XzEuVHJpdmlhbFRyZWVCb3godGhpcy4kZHJvcERvd24sIHRoaXMuY29uZmlnKTtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmFkZExpc3RlbmVyKGZ1bmN0aW9uIChzZWxlY3RlZEVudHJ5LCBldmVudFNvdXJjZSwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoc2VsZWN0ZWRFbnRyeSwgdHJ1ZSwgIVRyaXZpYWxDb3JlXzEub2JqZWN0RXF1YWxzKHNlbGVjdGVkRW50cnksIF90aGlzLmxhc3RDb21taXR0ZWRWYWx1ZSksIG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy50cmVlQm94LnNldFNlbGVjdGVkRW50cnkobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMuaGlkZUVkaXRvcigpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeSwgdHJ1ZSwgZmFsc2UsIG51bGwpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uIChoaWdobGlnaHREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgcXVlcnlTdHJpbmcgPSB0aGlzLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgIHZhciBjb21wbGV0ZUlucHV0U3RyaW5nID0gdGhpcy4kZWRpdG9yLnZhbCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMubGFzdFF1ZXJ5U3RyaW5nICE9PSBxdWVyeVN0cmluZyB8fCB0aGlzLmxhc3RDb21wbGV0ZUlucHV0UXVlcnlTdHJpbmcgIT09IGNvbXBsZXRlSW5wdXRTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy4kc3Bpbm5lcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkc3Bpbm5lciA9ICQodGhpcy5jb25maWcuc3Bpbm5lclRlbXBsYXRlKS5hcHBlbmRUbyh0aGlzLiRkcm9wRG93bik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gdGhpcy4kc3Bpbm5lcnMuYWRkKCRzcGlubmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbihxdWVyeVN0cmluZywgZnVuY3Rpb24gKG5ld0VudHJpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRW50cmllcyhuZXdFbnRyaWVzLCBoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkgJiYgbmV3RW50cmllcyAmJiBuZXdFbnRyaWVzLmxlbmd0aCA+IDAgJiYgX3RoaXMuJGVkaXRvci5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RRdWVyeVN0cmluZyA9IHF1ZXJ5U3RyaW5nO1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdENvbXBsZXRlSW5wdXRRdWVyeVN0cmluZyA9IGNvbXBsZXRlSW5wdXRTdHJpbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5maXJlQ2hhbmdlRXZlbnRzID0gZnVuY3Rpb24gKGVudHJ5LCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuZmlyZShlbnRyeSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLnNldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoZW50cnksIGNvbW1pdCwgZmlyZUV2ZW50LCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCh0aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKGVudHJ5KSk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cnkgPSBlbnRyeTtcbiAgICAgICAgICAgIHZhciAkc2VsZWN0ZWRFbnRyeSA9ICQodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeVJlbmRlcmluZ0Z1bmN0aW9uKGVudHJ5KSlcbiAgICAgICAgICAgICAgICAuYWRkQ2xhc3MoXCJ0ci1jb21ib2JveC1lbnRyeVwiKTtcbiAgICAgICAgICAgIHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyLmVtcHR5KCkuYXBwZW5kKCRzZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgICAgIGlmIChlbnRyeSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbCh0aGlzLmNvbmZpZy5lbnRyeVRvRWRpdG9yVGV4dEZ1bmN0aW9uKGVudHJ5KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29tbWl0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUgPSBlbnRyeTtcbiAgICAgICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cyhlbnRyeSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJGNsZWFyQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2xlYXJCdXR0b24udG9nZ2xlKGVudHJ5ICE9IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNFZGl0b3JWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmlzRW50cnlTZWxlY3RlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkRW50cnkgIT0gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuc2hvd0VkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciAkZWRpdG9yQXJlYSA9IHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyLmZpbmQoXCIudHItZWRpdG9yLWFyZWFcIik7XG4gICAgICAgICAgICBpZiAoJGVkaXRvckFyZWEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgJGVkaXRvckFyZWEgPSB0aGlzLiRzZWxlY3RlZEVudHJ5V3JhcHBlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJGVkaXRvclxuICAgICAgICAgICAgICAgIC5jc3Moe1xuICAgICAgICAgICAgICAgIFwid2lkdGhcIjogTWF0aC5taW4oJGVkaXRvckFyZWFbMF0ub2Zmc2V0V2lkdGgsIHRoaXMuJHRyaWdnZXIgPyB0aGlzLiR0cmlnZ2VyWzBdLm9mZnNldExlZnQgLSAkZWRpdG9yQXJlYVswXS5vZmZzZXRMZWZ0IDogOTk5OTk5OTkpICsgXCJweFwiLFxuICAgICAgICAgICAgICAgIFwiaGVpZ2h0XCI6ICgkZWRpdG9yQXJlYVswXS5vZmZzZXRIZWlnaHQpICsgXCJweFwiXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5wb3NpdGlvbih7XG4gICAgICAgICAgICAgICAgbXk6IFwibGVmdCB0b3BcIixcbiAgICAgICAgICAgICAgICBhdDogXCJsZWZ0IHRvcFwiLFxuICAgICAgICAgICAgICAgIG9mOiAkZWRpdG9yQXJlYVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmlzRWRpdG9yVmlzaWJsZSA9IHRydWU7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmVkaXRvckNvbnRhaW5zRnJlZVRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCAmJiB0aGlzLiRlZGl0b3IudmFsKCkubGVuZ3RoID4gMCAmJiAhdGhpcy5pc0VudHJ5U2VsZWN0ZWQoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5oaWRlRWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLndpZHRoKDApLmhlaWdodCgwKTtcbiAgICAgICAgICAgIHRoaXMuaXNFZGl0b3JWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLnJlcG9zaXRpb25Ecm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93blxuICAgICAgICAgICAgICAgIC5zaG93KClcbiAgICAgICAgICAgICAgICAucG9zaXRpb24oe1xuICAgICAgICAgICAgICAgIG15OiBcImxlZnQgdG9wXCIsXG4gICAgICAgICAgICAgICAgYXQ6IFwibGVmdCBib3R0b21cIixcbiAgICAgICAgICAgICAgICBvZjogdGhpcy4kdHJlZUNvbWJvQm94LFxuICAgICAgICAgICAgICAgIGNvbGxpc2lvbjogXCJmbGlwXCIsXG4gICAgICAgICAgICAgICAgdXNpbmc6IGZ1bmN0aW9uIChjYWxjdWxhdGVkUG9zaXRpb24sIGluZm8pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZm8udmVydGljYWwgPT09IFwidG9wXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiR0cmVlQ29tYm9Cb3gucmVtb3ZlQ2xhc3MoXCJkcm9wZG93bi1mbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLnJlbW92ZUNsYXNzKFwiZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiR0cmVlQ29tYm9Cb3guYWRkQ2xhc3MoXCJkcm9wZG93bi1mbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLmFkZENsYXNzKFwiZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24uY3NzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQ6IGNhbGN1bGF0ZWRQb3NpdGlvbi5sZWZ0ICsgJ3B4JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogY2FsY3VsYXRlZFBvc2l0aW9uLnRvcCArICdweCdcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAud2lkdGgodGhpcy4kdHJlZUNvbWJvQm94LndpZHRoKCkpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLm9wZW5Ecm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25OZWVkZWQoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJHRyZWVDb21ib0JveC5hZGRDbGFzcyhcIm9wZW5cIik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXBvc2l0aW9uRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuY2xvc2VEcm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJHRyZWVDb21ib0JveC5yZW1vdmVDbGFzcyhcIm9wZW5cIik7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5oaWRlKCk7XG4gICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kZWRpdG9yLnZhbCgpLnN1YnN0cmluZygwLCB0aGlzLiRlZGl0b3JbMF0uc2VsZWN0aW9uU3RhcnQpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5hdXRvQ29tcGxldGVJZlBvc3NpYmxlID0gZnVuY3Rpb24gKGRlbGF5KSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmF1dG9Db21wbGV0ZSkge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmF1dG9Db21wbGV0ZVRpbWVvdXRJZCk7XG4gICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnlfMSA9IHRoaXMudHJlZUJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgaWYgKGhpZ2hsaWdodGVkRW50cnlfMSAmJiAhdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVUaW1lb3V0SWQgPSBUcml2aWFsQ29yZV8xLnNldFRpbWVvdXRPckRvSW1tZWRpYXRlbHkoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRFZGl0b3JWYWx1ZSA9IF90aGlzLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdXRvQ29tcGxldGVTdHJpbmcgPSBfdGhpcy5jb25maWcuYXV0b0NvbXBsZXRlRnVuY3Rpb24oY3VycmVudEVkaXRvclZhbHVlLCBoaWdobGlnaHRlZEVudHJ5XzEpIHx8IGN1cnJlbnRFZGl0b3JWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudmFsKGN1cnJlbnRFZGl0b3JWYWx1ZSArIGF1dG9Db21wbGV0ZVN0cmluZy5zdWJzdHIoY3VycmVudEVkaXRvclZhbHVlLmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yWzBdLnNldFNlbGVjdGlvblJhbmdlKGN1cnJlbnRFZGl0b3JWYWx1ZS5sZW5ndGgsIGF1dG9Db21wbGV0ZVN0cmluZy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9LCBkZWxheSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLnVwZGF0ZUVudHJpZXMgPSBmdW5jdGlvbiAobmV3RW50cmllcywgaGlnaGxpZ2h0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycy5yZW1vdmUoKTtcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gJCgpO1xuICAgICAgICAgICAgdGhpcy50cmVlQm94LnVwZGF0ZUVudHJpZXMobmV3RW50cmllcyk7XG4gICAgICAgICAgICB2YXIgbm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA9IHRoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgdGhpcy50cmVlQm94LmhpZ2hsaWdodFRleHRNYXRjaGVzKG5ld0VudHJpZXMubGVuZ3RoIDw9IHRoaXMuY29uZmlnLnRleHRIaWdobGlnaHRpbmdFbnRyeUxpbWl0ID8gbm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA6IG51bGwpO1xuICAgICAgICAgICAgaWYgKGhpZ2hsaWdodERpcmVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRyZWVCb3guc2V0SGlnaGxpZ2h0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub25TZWxlY3RlZEVkaXRvclZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJlZUJveC5oaWdobGlnaHROZXh0TWF0Y2hpbmdFbnRyeSgxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJlZUJveC5oaWdobGlnaHROZXh0RW50cnkoMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChoaWdobGlnaHREaXJlY3Rpb24gPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRyZWVCb3guc2V0SGlnaGxpZ2h0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChub25TZWxlY3RlZEVkaXRvclZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50cmVlQm94LmhpZ2hsaWdodE5leHRNYXRjaGluZ0VudHJ5KDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50cmVlQm94LmhpZ2hsaWdodE5leHRFbnRyeSgxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmF1dG9Db21wbGV0ZUlmUG9zc2libGUodGhpcy5jb25maWcuYXV0b0NvbXBsZXRlRGVsYXkpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5pc0Ryb3BEb3duTmVlZGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWRpdGluZ01vZGUgPT0gJ2VkaXRhYmxlJyAmJiAodGhpcy5jb25maWcuZW50cmllcyAmJiB0aGlzLmNvbmZpZy5lbnRyaWVzLmxlbmd0aCA+IDAgfHwgIXRoaXMudXNpbmdEZWZhdWx0UXVlcnlGdW5jdGlvbiB8fCB0aGlzLmNvbmZpZy5zaG93VHJpZ2dlcik7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLnNldEVkaXRpbmdNb2RlID0gZnVuY3Rpb24gKG5ld0VkaXRpbmdNb2RlKSB7XG4gICAgICAgICAgICB0aGlzLmVkaXRpbmdNb2RlID0gbmV3RWRpdGluZ01vZGU7XG4gICAgICAgICAgICB0aGlzLiR0cmVlQ29tYm9Cb3gucmVtb3ZlQ2xhc3MoXCJlZGl0YWJsZSByZWFkb25seSBkaXNhYmxlZFwiKS5hZGRDbGFzcyh0aGlzLmVkaXRpbmdNb2RlKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25OZWVkZWQoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duVGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmdldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZWxlY3RlZEVudHJ5ID09IG51bGwgJiYgKCF0aGlzLmNvbmZpZy5hbGxvd0ZyZWVUZXh0IHx8ICF0aGlzLiRlZGl0b3IudmFsKCkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLnNlbGVjdGVkRW50cnkgPT0gbnVsbCAmJiB0aGlzLmNvbmZpZy5hbGxvd0ZyZWVUZXh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmZyZWVUZXh0RW50cnlGYWN0b3J5KHRoaXMuJGVkaXRvci52YWwoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWRFbnRyeVRvUmV0dXJuID0gJC5leHRlbmQoe30sIHRoaXMuc2VsZWN0ZWRFbnRyeSk7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeVRvUmV0dXJuLl90ckVudHJ5RWxlbWVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZWN0ZWRFbnRyeVRvUmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS51cGRhdGVDaGlsZHJlbiA9IGZ1bmN0aW9uIChwYXJlbnROb2RlSWQsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3gudXBkYXRlQ2hpbGRyZW4ocGFyZW50Tm9kZUlkLCBjaGlsZHJlbik7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLnVwZGF0ZU5vZGUgPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgdGhpcy50cmVlQm94LnVwZGF0ZU5vZGUobm9kZSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLnJlbW92ZU5vZGUgPSBmdW5jdGlvbiAobm9kZUlkKSB7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3gucmVtb3ZlTm9kZShub2RlSWQpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5mb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmdldEVkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRlZGl0b3JbMF07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmdldERyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGRyb3BEb3duO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnJlbW92ZUNsYXNzKCd0ci1vcmlnaW5hbC1pbnB1dCcpLmluc2VydEJlZm9yZSh0aGlzLiR0cmVlQ29tYm9Cb3gpO1xuICAgICAgICAgICAgdGhpcy4kdHJlZUNvbWJvQm94LnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd24ucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuZ2V0TWFpbkRvbUVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kdHJlZUNvbWJvQm94WzBdO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJpdmlhbFRyZWVDb21ib0JveDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbFRyZWVDb21ib0JveCA9IFRyaXZpYWxUcmVlQ29tYm9Cb3g7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIm11c3RhY2hlXCIsIFwiLi9Ucml2aWFsTGlzdEJveFwiLCBcIi4vVHJpdmlhbENvcmVcIiwgXCIuL1RyaXZpYWxFdmVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBNdXN0YWNoZSA9IHJlcXVpcmUoXCJtdXN0YWNoZVwiKTtcbiAgICB2YXIgVHJpdmlhbExpc3RCb3hfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxMaXN0Qm94XCIpO1xuICAgIHZhciBUcml2aWFsQ29yZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENvcmVcIik7XG4gICAgdmFyIFRyaXZpYWxFdmVudF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpO1xuICAgIHZhciBUcml2aWFsVW5pdEJveCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFRyaXZpYWxVbml0Qm94KG9yaWdpbmFsSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbkZvY3VzID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMub25CbHVyID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gJCgpO1xuICAgICAgICAgICAgdGhpcy5jb25maWcgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgdW5pdFZhbHVlUHJvcGVydHk6ICdjb2RlJyxcbiAgICAgICAgICAgICAgICB1bml0SWRQcm9wZXJ0eTogJ2NvZGUnLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxQcmVjaXNpb246IDIsXG4gICAgICAgICAgICAgICAgZGVjaW1hbFNlcGFyYXRvcjogJy4nLFxuICAgICAgICAgICAgICAgIHRob3VzYW5kc1NlcGFyYXRvcjogJywnLFxuICAgICAgICAgICAgICAgIHVuaXREaXNwbGF5UG9zaXRpb246ICdyaWdodCcsXG4gICAgICAgICAgICAgICAgYWxsb3dOdWxsQW1vdW50OiB0cnVlLFxuICAgICAgICAgICAgICAgIGVudHJ5UmVuZGVyaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTXVzdGFjaGUucmVuZGVyKFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuY3VycmVuY3kyTGluZVRlbXBsYXRlLCBlbnRyeSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJ5UmVuZGVyaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTXVzdGFjaGUucmVuZGVyKFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuY3VycmVuY3lTaW5nbGVMaW5lU2hvcnRUZW1wbGF0ZSwgZW50cnkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYW1vdW50OiBudWxsLFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnk6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBzcGlubmVyVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdFNwaW5uZXJUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICBub0VudHJpZXNUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0Tm9FbnRyaWVzVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgZW50cmllczogbnVsbCxcbiAgICAgICAgICAgICAgICBxdWVyeUZ1bmN0aW9uOiBudWxsLFxuICAgICAgICAgICAgICAgIHF1ZXJ5T25Ob25OdW1iZXJDaGFyYWN0ZXJzOiB0cnVlLFxuICAgICAgICAgICAgICAgIG9wZW5Ecm9wZG93bk9uRWRpdG9yQ2xpY2s6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHNob3dUcmlnZ2VyOiB0cnVlLFxuICAgICAgICAgICAgICAgIG1hdGNoaW5nT3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ01vZGU6ICdwcmVmaXgtd29yZCcsXG4gICAgICAgICAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVkaXRpbmdNb2RlOiAnZWRpdGFibGUnLFxuICAgICAgICAgICAgfSwgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLnF1ZXJ5RnVuY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uID0gVHJpdmlhbENvcmVfMS5kZWZhdWx0TGlzdFF1ZXJ5RnVuY3Rpb25GYWN0b3J5KHRoaXMuY29uZmlnLmVudHJpZXMgfHwgW10sIHRoaXMuY29uZmlnLm1hdGNoaW5nT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW50cmllcyA9IHRoaXMuY29uZmlnLmVudHJpZXM7XG4gICAgICAgICAgICB0aGlzLm51bWJlclJlZ2V4ID0gbmV3IFJlZ0V4cCgnXFxcXGQqXFxcXCcgKyB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yICsgJz9cXFxcZConLCAnZycpO1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dCA9ICQob3JpZ2luYWxJbnB1dCkuYWRkQ2xhc3MoXCJ0ci1vcmlnaW5hbC1pbnB1dFwiKTtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvciA9ICQoJzxpbnB1dCB0eXBlPVwidGV4dFwiLz4nKTtcbiAgICAgICAgICAgIHRoaXMuJHVuaXRCb3ggPSAkKCc8ZGl2IGNsYXNzPVwidHItdW5pdGJveCB0ci1pbnB1dC13cmFwcGVyXCIvPicpLmluc2VydEFmdGVyKHRoaXMuJG9yaWdpbmFsSW5wdXQpXG4gICAgICAgICAgICAgICAgLmFkZENsYXNzKHRoaXMuY29uZmlnLnVuaXREaXNwbGF5UG9zaXRpb24gPT09ICdsZWZ0JyA/ICd1bml0LWRpc3BsYXktbGVmdCcgOiAndW5pdC1kaXNwbGF5LXJpZ2h0Jyk7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LmFwcGVuZFRvKHRoaXMuJHVuaXRCb3gpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeUFuZFRyaWdnZXJXcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLXVuaXRib3gtc2VsZWN0ZWQtZW50cnktYW5kLXRyaWdnZXItd3JhcHBlclwiLz4nKS5hcHBlbmRUbyh0aGlzLiR1bml0Qm94KTtcbiAgICAgICAgICAgIHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLXVuaXRib3gtc2VsZWN0ZWQtZW50cnktd3JhcHBlclwiLz4nKS5hcHBlbmRUbyh0aGlzLiRzZWxlY3RlZEVudHJ5QW5kVHJpZ2dlcldyYXBwZXIpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKSB7XG4gICAgICAgICAgICAgICAgJCgnPGRpdiBjbGFzcz1cInRyLXRyaWdnZXJcIj48c3BhbiBjbGFzcz1cInRyLXRyaWdnZXItaWNvblwiLz48L2Rpdj4nKS5hcHBlbmRUbyh0aGlzLiRzZWxlY3RlZEVudHJ5QW5kVHJpZ2dlcldyYXBwZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeUFuZFRyaWdnZXJXcmFwcGVyLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoX3RoaXMuZWRpdGluZ01vZGUgPT09IFwiZWRpdGFibGVcIikge1xuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93biA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1kcm9wZG93blwiPjwvZGl2PicpXG4gICAgICAgICAgICAgICAgLnNjcm9sbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93blRhcmdldEVsZW1lbnQgPSAkKFwiYm9keVwiKTtcbiAgICAgICAgICAgIHRoaXMuc2V0RWRpdGluZ01vZGUodGhpcy5jb25maWcuZWRpdGluZ01vZGUpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnByZXBlbmRUbyh0aGlzLiR1bml0Qm94KS5hZGRDbGFzcyhcInRyLXVuaXRib3gtZWRpdG9yIHRyLWVkaXRvclwiKVxuICAgICAgICAgICAgICAgIC5mb2N1cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmVkaXRpbmdNb2RlICE9PSBcImVkaXRhYmxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5ibHVyKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vbkZvY3VzLmZpcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJHVuaXRCb3guYWRkQ2xhc3MoJ2ZvY3VzJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsZWFudXBFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmJsdXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vbkJsdXIuZmlyZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdW5pdEJveC5yZW1vdmVDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZm9ybWF0RWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmtleWRvd24oZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5pc01vZGlmaWVyS2V5KGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnRhYikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaGlnaGxpZ2h0ZWRFbnRyeSA9IF90aGlzLmxpc3RCb3guZ2V0SGlnaGxpZ2h0ZWRFbnRyeSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4gJiYgaGlnaGxpZ2h0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShoaWdobGlnaHRlZEVudHJ5LCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMubGVmdF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnVwX2Fycm93IHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5kb3duX2Fycm93KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgPyAtMSA6IDE7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMubGlzdEJveC5oaWdobGlnaHROZXh0RW50cnkoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuICYmIGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lbnRlcikge1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMubGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCksIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lc2NhcGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbGVhbnVwRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoIWUuc2hpZnRLZXkgJiYgVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5udW1iZXJLZXlzLmluZGV4T2YoZS53aGljaCkgIT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG51bWJlclBhcnQgPSBfdGhpcy5nZXRFZGl0b3JWYWx1ZU51bWJlclBhcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG51bWJlclBhcnREZWNpbWFsU2VwYXJhdG9ySW5kZXggPSBudW1iZXJQYXJ0LmluZGV4T2YoX3RoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF4RGVjaW1hbERpZ2l0c1JlYWNoZWQgPSBudW1iZXJQYXJ0RGVjaW1hbFNlcGFyYXRvckluZGV4ICE9IC0xICYmIG51bWJlclBhcnQubGVuZ3RoIC0gKG51bWJlclBhcnREZWNpbWFsU2VwYXJhdG9ySW5kZXggKyAxKSA+PSBfdGhpcy5jb25maWcuZGVjaW1hbFByZWNpc2lvbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVkaXRvclZhbHVlID0gX3RoaXMuJGVkaXRvci52YWwoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRlY2ltYWxTZXBhcmF0b3JJbmRleCA9IGVkaXRvclZhbHVlLmluZGV4T2YoX3RoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZWN0aW9uU3RhcnQgPSBfdGhpcy4kZWRpdG9yWzBdLnNlbGVjdGlvblN0YXJ0O1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZWN0aW9uRW5kID0gX3RoaXMuJGVkaXRvclswXS5zZWxlY3Rpb25FbmQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3b3VsZEFkZEFub3RoZXJEaWdpdCA9IGRlY2ltYWxTZXBhcmF0b3JJbmRleCAhPT0gLTEgJiYgc2VsZWN0aW9uRW5kID4gZGVjaW1hbFNlcGFyYXRvckluZGV4ICYmIHNlbGVjdGlvblN0YXJ0ID09PSBzZWxlY3Rpb25FbmQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXhEZWNpbWFsRGlnaXRzUmVhY2hlZCAmJiB3b3VsZEFkZEFub3RoZXJEaWdpdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKC9eXFxkJC8udGVzdChlZGl0b3JWYWx1ZVtzZWxlY3Rpb25FbmRdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudmFsKGVkaXRvclZhbHVlLnN1YnN0cmluZygwLCBzZWxlY3Rpb25FbmQpICsgZWRpdG9yVmFsdWUuc3Vic3RyaW5nKHNlbGVjdGlvbkVuZCArIDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yWzBdLnNldFNlbGVjdGlvblJhbmdlKHNlbGVjdGlvbkVuZCwgc2VsZWN0aW9uRW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmtleXVwKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuc3BlY2lhbEtleXMuaW5kZXhPZihlLndoaWNoKSAhPSAtMVxuICAgICAgICAgICAgICAgICAgICAmJiBlLndoaWNoICE9IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuYmFja3NwYWNlXG4gICAgICAgICAgICAgICAgICAgICYmIGUud2hpY2ggIT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5kZWxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgaGFzRG91YmxlRGVjaW1hbFNlcGFyYXRvciA9IG5ldyBSZWdFeHAoXCIoPzpcXFxcXCIgKyBfdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvciArIFwiLiopXCIgKyBcIlxcXFxcIiArIF90aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCBcImdcIikudGVzdChfdGhpcy4kZWRpdG9yLnZhbCgpKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzRG91YmxlRGVjaW1hbFNlcGFyYXRvcikge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbGVhbnVwRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvclswXS5zZXRTZWxlY3Rpb25SYW5nZShfdGhpcy4kZWRpdG9yLnZhbCgpLmxlbmd0aCAtIF90aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCBfdGhpcy4kZWRpdG9yLnZhbCgpLmxlbmd0aCAtIF90aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5xdWVyeU9uTm9uTnVtYmVyQ2hhcmFjdGVycykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZ2V0UXVlcnlTdHJpbmcoKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5lbnN1cmVEZWNpbWFsSW5wdXQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcub3BlbkRyb3Bkb3duT25FZGl0b3JDbGljaykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmVudHJpZXMgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNoYW5nZShmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZU9yaWdpbmFsSW5wdXRWYWx1ZSgpO1xuICAgICAgICAgICAgICAgIF90aGlzLmZpcmVDaGFuZ2VFdmVudHMoZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJHVuaXRCb3guYWRkKHRoaXMuJGRyb3BEb3duKS5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5tb3VzZXVwKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLm1vdXNlb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94ID0gbmV3IFRyaXZpYWxMaXN0Qm94XzEuVHJpdmlhbExpc3RCb3godGhpcy4kZHJvcERvd24sIHRoaXMuY29uZmlnKTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveC5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmFkZExpc3RlbmVyKGZ1bmN0aW9uIChzZWxlY3RlZEVudHJ5LCBldmVudFNvdXJjZSwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoc2VsZWN0ZWRFbnRyeSwgdHJ1ZSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmxpc3RCb3guc2V0U2VsZWN0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbCh0aGlzLmNvbmZpZy5hbW91bnQgfHwgdGhpcy4kb3JpZ2luYWxJbnB1dC52YWwoKSk7XG4gICAgICAgICAgICB0aGlzLmZvcm1hdEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeSB8fCBudWxsLCBmYWxzZSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmVuc3VyZURlY2ltYWxJbnB1dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjdXJzb3JQb3NpdGlvbiA9IHRoaXMuJGVkaXRvclswXS5zZWxlY3Rpb25FbmQ7XG4gICAgICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLiRlZGl0b3IudmFsKCk7XG4gICAgICAgICAgICB2YXIgbmV3VmFsdWUgPSBvbGRWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1teXFwtMC05JyArIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IgKyB0aGlzLmNvbmZpZy50aG91c2FuZHNTZXBhcmF0b3IgKyAnXScsICdnJyksICcnKTtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gbmV3VmFsdWUucmVwbGFjZSgvKFxcZCpcXC5cXGQqKVxcLi9nLCAnJDEnKTtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gbmV3VmFsdWUucmVwbGFjZSgvKC4pLSovZywgJyQxJyk7XG4gICAgICAgICAgICB2YXIgZGVjaW1hbFNlcGFyYXRvckluZGV4ID0gbmV3VmFsdWUuaW5kZXhPZih0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yKTtcbiAgICAgICAgICAgIGlmIChkZWNpbWFsU2VwYXJhdG9ySW5kZXggIT0gLTEgJiYgbmV3VmFsdWUubGVuZ3RoIC0gZGVjaW1hbFNlcGFyYXRvckluZGV4IC0gMSA+IHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24pIHtcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZSA9IG5ld1ZhbHVlLnN1YnN0cmluZygwLCBkZWNpbWFsU2VwYXJhdG9ySW5kZXggKyAxICsgdGhpcy5jb25maWcuZGVjaW1hbFByZWNpc2lvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2xkVmFsdWUgIT09IG5ld1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbChuZXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld0N1cnNvclBvc2l0aW9uID0gTWF0aC5taW4odGhpcy4kZWRpdG9yLnZhbCgpLmxlbmd0aCwgY3Vyc29yUG9zaXRpb24pO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvclswXS5zZXRTZWxlY3Rpb25SYW5nZShuZXdDdXJzb3JQb3NpdGlvbiwgbmV3Q3Vyc29yUG9zaXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmdldFF1ZXJ5U3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGVkaXRvci52YWwoKS5yZXBsYWNlKHRoaXMubnVtYmVyUmVnZXgsICcnKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmdldEVkaXRvclZhbHVlTnVtYmVyUGFydCA9IGZ1bmN0aW9uIChmaWxsdXBEZWNpbWFscykge1xuICAgICAgICAgICAgdmFyIHJhd051bWJlciA9IHRoaXMuJGVkaXRvci52YWwoKS5tYXRjaCh0aGlzLm51bWJlclJlZ2V4KS5qb2luKCcnKTtcbiAgICAgICAgICAgIHZhciBkZWNpbWFsRGVwYXJhdG9ySW5kZXggPSByYXdOdW1iZXIuaW5kZXhPZih0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yKTtcbiAgICAgICAgICAgIHZhciBpbnRlZ2VyUGFydDtcbiAgICAgICAgICAgIHZhciBmcmFjdGlvbmFsUGFydDtcbiAgICAgICAgICAgIGlmIChkZWNpbWFsRGVwYXJhdG9ySW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgaW50ZWdlclBhcnQgPSByYXdOdW1iZXIuc3Vic3RyaW5nKDAsIGRlY2ltYWxEZXBhcmF0b3JJbmRleCk7XG4gICAgICAgICAgICAgICAgZnJhY3Rpb25hbFBhcnQgPSByYXdOdW1iZXIuc3Vic3RyaW5nKGRlY2ltYWxEZXBhcmF0b3JJbmRleCArIDEsIHJhd051bWJlci5sZW5ndGgpLnJlcGxhY2UoL1xcRC9nLCAnJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnRlZ2VyUGFydCA9IHJhd051bWJlcjtcbiAgICAgICAgICAgICAgICBmcmFjdGlvbmFsUGFydCA9IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW50ZWdlclBhcnQubGVuZ3RoID09IDAgJiYgZnJhY3Rpb25hbFBhcnQubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChmaWxsdXBEZWNpbWFscykge1xuICAgICAgICAgICAgICAgICAgICBmcmFjdGlvbmFsUGFydCA9IChmcmFjdGlvbmFsUGFydCArIG5ldyBBcnJheSh0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uICsgMSkuam9pbihcIjBcIikpLnN1YnN0cigwLCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGludGVnZXJQYXJ0ICsgdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvciArIGZyYWN0aW9uYWxQYXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUucXVlcnkgPSBmdW5jdGlvbiAoaGlnaGxpZ2h0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyICRzcGlubmVyID0gJCh0aGlzLmNvbmZpZy5zcGlubmVyVGVtcGxhdGUpLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duKTtcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gdGhpcy4kc3Bpbm5lcnMuYWRkKCRzcGlubmVyKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uKF90aGlzLmdldFF1ZXJ5U3RyaW5nKCksIGZ1bmN0aW9uIChuZXdFbnRyaWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZUVudHJpZXMobmV3RW50cmllcyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBxdWVyeVN0cmluZyA9IF90aGlzLmdldFF1ZXJ5U3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChxdWVyeVN0cmluZy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5saXN0Qm94LmhpZ2hsaWdodFRleHRNYXRjaGVzKHF1ZXJ5U3RyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5saXN0Qm94LmhpZ2hsaWdodE5leHRFbnRyeShoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmZpcmVTZWxlY3RlZEVudHJ5Q2hhbmdlZEV2ZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmZpcmUodGhpcy5zZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmZpcmVDaGFuZ2VFdmVudHMgPSBmdW5jdGlvbiAob3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZS5maXJlKHtcbiAgICAgICAgICAgICAgICB1bml0OiB0aGlzLnNlbGVjdGVkRW50cnkgIT0gbnVsbCA/IHRoaXMuc2VsZWN0ZWRFbnRyeVt0aGlzLmNvbmZpZy51bml0VmFsdWVQcm9wZXJ0eV0gOiBudWxsLFxuICAgICAgICAgICAgICAgIHVuaXRFbnRyeTogdGhpcy5zZWxlY3RlZEVudHJ5LFxuICAgICAgICAgICAgICAgIGFtb3VudDogdGhpcy5nZXRBbW91bnQoKSxcbiAgICAgICAgICAgICAgICBhbW91bnRBc0Zsb2F0aW5nUG9pbnROdW1iZXI6IHBhcnNlRmxvYXQodGhpcy5mb3JtYXRBbW91bnQodGhpcy5nZXRBbW91bnQoKSwgdGhpcy5jb25maWcuZGVjaW1hbFByZWNpc2lvbiwgdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvciwgdGhpcy5jb25maWcudGhvdXNhbmRzU2VwYXJhdG9yKSlcbiAgICAgICAgICAgIH0sIG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuc2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uIChlbnRyeSwgZmlyZUV2ZW50LCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cnkgPSBlbnRyeTtcbiAgICAgICAgICAgIHZhciAkc2VsZWN0ZWRFbnRyeSA9ICQodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeVJlbmRlcmluZ0Z1bmN0aW9uKGVudHJ5KSlcbiAgICAgICAgICAgICAgICAuYWRkQ2xhc3MoXCJ0ci1jb21ib2JveC1lbnRyeVwiKTtcbiAgICAgICAgICAgIHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyLmVtcHR5KCkuYXBwZW5kKCRzZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgICAgIHRoaXMuY2xlYW51cEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU9yaWdpbmFsSW5wdXRWYWx1ZSgpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLiRlZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm1hdEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlU2VsZWN0ZWRFbnRyeUNoYW5nZWRFdmVudCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cyhvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmZvcm1hdEVkaXRvclZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbCh0aGlzLmZvcm1hdEFtb3VudCh0aGlzLmdldEFtb3VudCgpLCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCB0aGlzLmNvbmZpZy50aG91c2FuZHNTZXBhcmF0b3IpKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmNsZWFudXBFZGl0b3JWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLiRlZGl0b3IudmFsKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuZ2V0RWRpdG9yVmFsdWVOdW1iZXJQYXJ0KHRydWUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmZvcm1hdEFtb3VudCA9IGZ1bmN0aW9uIChpbnRlZ2VyTnVtYmVyLCBwcmVjaXNpb24sIGRlY2ltYWxTZXBhcmF0b3IsIHRob3VzYW5kc1NlcGFyYXRvcikge1xuICAgICAgICAgICAgaWYgKGludGVnZXJOdW1iZXIgPT0gbnVsbCB8fCBpc05hTihpbnRlZ2VyTnVtYmVyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGFtb3VudEFzU3RyaW5nID0gXCJcIiArIGludGVnZXJOdW1iZXI7XG4gICAgICAgICAgICBpZiAoYW1vdW50QXNTdHJpbmcubGVuZ3RoIDw9IHByZWNpc2lvbikge1xuICAgICAgICAgICAgICAgIHJldHVybiAwICsgZGVjaW1hbFNlcGFyYXRvciArIG5ldyBBcnJheShwcmVjaXNpb24gLSBhbW91bnRBc1N0cmluZy5sZW5ndGggKyAxKS5qb2luKFwiMFwiKSArIGFtb3VudEFzU3RyaW5nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGludGVnZXJQYXJ0ID0gYW1vdW50QXNTdHJpbmcuc3Vic3RyaW5nKDAsIGFtb3VudEFzU3RyaW5nLmxlbmd0aCAtIHByZWNpc2lvbik7XG4gICAgICAgICAgICAgICAgdmFyIGZvcm1hdHRlZEludGVnZXJQYXJ0ID0gaW50ZWdlclBhcnQucmVwbGFjZSgvXFxCKD89KFxcZHszfSkrKD8hXFxkKSkvZywgdGhvdXNhbmRzU2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICB2YXIgZnJhY3Rpb25hbFBhcnQgPSBhbW91bnRBc1N0cmluZy5zdWJzdHIoYW1vdW50QXNTdHJpbmcubGVuZ3RoIC0gcHJlY2lzaW9uLCBwcmVjaXNpb24pO1xuICAgICAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZWRJbnRlZ2VyUGFydCArIGRlY2ltYWxTZXBhcmF0b3IgKyBmcmFjdGlvbmFsUGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnJlcG9zaXRpb25Ecm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93blxuICAgICAgICAgICAgICAgIC5zaG93KClcbiAgICAgICAgICAgICAgICAucG9zaXRpb24oe1xuICAgICAgICAgICAgICAgIG15OiBcImxlZnQgdG9wXCIsXG4gICAgICAgICAgICAgICAgYXQ6IFwibGVmdCBib3R0b21cIixcbiAgICAgICAgICAgICAgICBvZjogdGhpcy4kdW5pdEJveCxcbiAgICAgICAgICAgICAgICBjb2xsaXNpb246IFwiZmxpcFwiLFxuICAgICAgICAgICAgICAgIHVzaW5nOiBmdW5jdGlvbiAoY2FsY3VsYXRlZFBvc2l0aW9uLCBpbmZvKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmZvLnZlcnRpY2FsID09PSBcInRvcFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdW5pdEJveC5yZW1vdmVDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24ucmVtb3ZlQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJHVuaXRCb3guYWRkQ2xhc3MoXCJkcm9wZG93bi1mbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLmFkZENsYXNzKFwiZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24uY3NzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQ6IGNhbGN1bGF0ZWRQb3NpdGlvbi5sZWZ0ICsgJ3B4JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogY2FsY3VsYXRlZFBvc2l0aW9uLnRvcCArICdweCdcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAud2lkdGgodGhpcy4kdW5pdEJveC53aWR0aCgpKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUub3BlbkRyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kdW5pdEJveC5hZGRDbGFzcyhcIm9wZW5cIik7XG4gICAgICAgICAgICB0aGlzLnJlcG9zaXRpb25Ecm9wRG93bigpO1xuICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IHRydWU7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5jbG9zZURyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kdW5pdEJveC5yZW1vdmVDbGFzcyhcIm9wZW5cIik7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5oaWRlKCk7XG4gICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS51cGRhdGVPcmlnaW5hbElucHV0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcudW5pdERpc3BsYXlQb3NpdGlvbiA9PT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC52YWwoKHRoaXMuc2VsZWN0ZWRFbnRyeSA/IHRoaXMuc2VsZWN0ZWRFbnRyeVt0aGlzLmNvbmZpZy51bml0VmFsdWVQcm9wZXJ0eV0gOiAnJykgKyB0aGlzLmZvcm1hdEFtb3VudCh0aGlzLmdldEFtb3VudCgpLCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCAnJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC52YWwodGhpcy5mb3JtYXRBbW91bnQodGhpcy5nZXRBbW91bnQoKSwgdGhpcy5jb25maWcuZGVjaW1hbFByZWNpc2lvbiwgdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvciwgJycpICsgKHRoaXMuc2VsZWN0ZWRFbnRyeSA/IHRoaXMuc2VsZWN0ZWRFbnRyeVt0aGlzLmNvbmZpZy51bml0VmFsdWVQcm9wZXJ0eV0gOiAnJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZ2V0QW1vdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVkaXRvclZhbHVlTnVtYmVyUGFydCA9IHRoaXMuZ2V0RWRpdG9yVmFsdWVOdW1iZXJQYXJ0KGZhbHNlKTtcbiAgICAgICAgICAgIGlmIChlZGl0b3JWYWx1ZU51bWJlclBhcnQubGVuZ3RoID09PSAwICYmIHRoaXMuY29uZmlnLmFsbG93TnVsbEFtb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoZWRpdG9yVmFsdWVOdW1iZXJQYXJ0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0RWRpdG9yVmFsdWVOdW1iZXJQYXJ0KHRydWUpLnJlcGxhY2UoL1xcRC9nLCBcIlwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5pc0Ryb3BEb3duTmVlZGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWRpdGluZ01vZGUgPT0gJ2VkaXRhYmxlJyAmJiAodGhpcy5jb25maWcuZW50cmllcyAmJiB0aGlzLmNvbmZpZy5lbnRyaWVzLmxlbmd0aCA+IDAgfHwgIXRoaXMudXNpbmdEZWZhdWx0UXVlcnlGdW5jdGlvbiB8fCB0aGlzLmNvbmZpZy5zaG93VHJpZ2dlcik7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5zZXRFZGl0aW5nTW9kZSA9IGZ1bmN0aW9uIChuZXdFZGl0aW5nTW9kZSkge1xuICAgICAgICAgICAgdGhpcy5lZGl0aW5nTW9kZSA9IG5ld0VkaXRpbmdNb2RlO1xuICAgICAgICAgICAgdGhpcy4kdW5pdEJveC5yZW1vdmVDbGFzcyhcImVkaXRhYmxlIHJlYWRvbmx5IGRpc2FibGVkXCIpLmFkZENsYXNzKHRoaXMuZWRpdGluZ01vZGUpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnByb3AoXCJyZWFkb25seVwiLCBuZXdFZGl0aW5nTW9kZSAhPT0gXCJlZGl0YWJsZVwiKTtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvci5hdHRyKFwidGFiaW5kZXhcIiwgbmV3RWRpdGluZ01vZGUgPT09IFwiZWRpdGFibGVcIiA/IHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpIDogXCItMVwiKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25OZWVkZWQoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duVGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5zZWxlY3RVbml0ID0gZnVuY3Rpb24gKHVuaXRJZGVudGlmaWVyKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5zZXRTZWxlY3RlZEVudHJ5KHRoaXMuZW50cmllcy5maWx0ZXIoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5W190aGlzLmNvbmZpZy51bml0SWRQcm9wZXJ0eV0gPT09IHVuaXRJZGVudGlmaWVyO1xuICAgICAgICAgICAgfSlbMF0sIGZhbHNlLCBudWxsKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnVwZGF0ZUVudHJpZXMgPSBmdW5jdGlvbiAobmV3RW50cmllcykge1xuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gbmV3RW50cmllcztcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzLnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSAkKCk7XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3gudXBkYXRlRW50cmllcyhuZXdFbnRyaWVzKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmdldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZWxlY3RlZEVudHJ5ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzZWxlY3RlZEVudHJ5VG9SZXR1cm4gPSAkLmV4dGVuZCh7fSwgdGhpcy5zZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJ5VG9SZXR1cm4uX3RyRW50cnlFbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHJldHVybiBzZWxlY3RlZEVudHJ5VG9SZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5zZXRBbW91bnQgPSBmdW5jdGlvbiAoYW1vdW50KSB7XG4gICAgICAgICAgICBpZiAoYW1vdW50ICE9IG51bGwgJiYgYW1vdW50ICE9PSBNYXRoLmZsb29yKGFtb3VudCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIlRyaXZpYWxVbml0Qm94OiBZb3UgbXVzdCBzcGVjaWZ5IGFuIGludGVnZXIgYW1vdW50IVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFtb3VudCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmFsbG93TnVsbEFtb3VudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKFwiXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbCh0aGlzLmZvcm1hdEFtb3VudCgwLCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCAnJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuJGVkaXRvci5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci52YWwodGhpcy5mb3JtYXRBbW91bnQoYW1vdW50LCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCAnJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbCh0aGlzLmZvcm1hdEFtb3VudChhbW91bnQsIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsIHRoaXMuY29uZmlnLnRob3VzYW5kc1NlcGFyYXRvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5mb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvci5zZWxlY3QoKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmdldEVkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRlZGl0b3JbMF07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC5yZW1vdmVDbGFzcygndHItb3JpZ2luYWwtaW5wdXQnKS5pbnNlcnRCZWZvcmUodGhpcy4kdW5pdEJveCk7XG4gICAgICAgICAgICB0aGlzLiR1bml0Qm94LnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd24ucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5nZXRNYWluRG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiR1bml0Qm94WzBdO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJpdmlhbFVuaXRCb3g7XG4gICAgfSgpKTtcbiAgICBleHBvcnRzLlRyaXZpYWxVbml0Qm94ID0gVHJpdmlhbFVuaXRCb3g7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcIi4vVHJpdmlhbENhbGVuZGFyQm94XCIsIFwiLi9Ucml2aWFsQ29tYm9Cb3hcIiwgXCIuL1RyaXZpYWxDb3JlXCIsIFwiLi9Ucml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmVcIiwgXCIuL1RyaXZpYWxEYXRlVGltZUZpZWxkXCIsIFwiLi9Ucml2aWFsRXZlbnRcIiwgXCIuL1RyaXZpYWxMaXN0Qm94XCIsIFwiLi9Ucml2aWFsVGFnQ29tYm9Cb3hcIiwgXCIuL1RyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZVwiLCBcIi4vVHJpdmlhbFRyZWVcIiwgXCIuL1RyaXZpYWxUcmVlQm94XCIsIFwiLi9Ucml2aWFsVHJlZUNvbWJvQm94XCIsIFwiLi9Ucml2aWFsVW5pdEJveFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBmdW5jdGlvbiBfX2V4cG9ydChtKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKCFleHBvcnRzLmhhc093blByb3BlcnR5KHApKSBleHBvcnRzW3BdID0gbVtwXTtcbiAgICB9XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIF9fZXhwb3J0KHJlcXVpcmUoXCIuL1RyaXZpYWxDYWxlbmRhckJveFwiKSk7XG4gICAgX19leHBvcnQocmVxdWlyZShcIi4vVHJpdmlhbENvbWJvQm94XCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsQ29yZVwiKSk7XG4gICAgX19leHBvcnQocmVxdWlyZShcIi4vVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lXCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsRGF0ZVRpbWVGaWVsZFwiKSk7XG4gICAgX19leHBvcnQocmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsTGlzdEJveFwiKSk7XG4gICAgX19leHBvcnQocmVxdWlyZShcIi4vVHJpdmlhbFRhZ0NvbWJvQm94XCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmVcIikpO1xuICAgIF9fZXhwb3J0KHJlcXVpcmUoXCIuL1RyaXZpYWxUcmVlXCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsVHJlZUJveFwiKSk7XG4gICAgX19leHBvcnQocmVxdWlyZShcIi4vVHJpdmlhbFRyZWVDb21ib0JveFwiKSk7XG4gICAgX19leHBvcnQocmVxdWlyZShcIi4vVHJpdmlhbFVuaXRCb3hcIikpO1xufSk7XG5cblxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIiwgXCJqcXVlcnlcIiwgXCIuL1RyaXZpYWxDb3JlXCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgalF1ZXJ5ID0gcmVxdWlyZShcImpxdWVyeVwiKTtcbiAgICB2YXIgVHJpdmlhbENvcmVfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxDb3JlXCIpO1xuICAgIChmdW5jdGlvbiAoJCkge1xuICAgICAgICAkLmV4cHJbXCI6XCJdLmNvbnRhaW5zSWdub3JlQ2FzZSA9ICQuZXhwci5jcmVhdGVQc2V1ZG8oZnVuY3Rpb24gKGFyZykge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQoZWxlbSkudGV4dCgpLnRvVXBwZXJDYXNlKCkuaW5kZXhPZihhcmcudG9VcHBlckNhc2UoKSkgPj0gMDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH0pKGpRdWVyeSk7XG4gICAgKGZ1bmN0aW9uICgkKSB7XG4gICAgICAgIHZhciBpc0lFMTEgPSAhKHdpbmRvdy5BY3RpdmVYT2JqZWN0KSAmJiBcIkFjdGl2ZVhPYmplY3RcIiBpbiB3aW5kb3c7XG4gICAgICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZUZvcklFMTEobm9kZSkge1xuICAgICAgICAgICAgaWYgKCFub2RlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT0gMykge1xuICAgICAgICAgICAgICAgIHdoaWxlIChub2RlLm5leHRTaWJsaW5nICYmIG5vZGUubmV4dFNpYmxpbmcubm9kZVR5cGUgPT0gMykge1xuICAgICAgICAgICAgICAgICAgICBub2RlLm5vZGVWYWx1ZSArPSBub2RlLm5leHRTaWJsaW5nLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUubmV4dFNpYmxpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZUZvcklFMTEobm9kZS5maXJzdENoaWxkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5vcm1hbGl6ZUZvcklFMTEobm9kZS5uZXh0U2libGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgJC5mbi50cml2aWFsSGlnaGxpZ2h0ID0gZnVuY3Rpb24gKHNlYXJjaFN0cmluZywgb3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgICAgICBoaWdobGlnaHRDbGFzc05hbWU6ICd0ci1oaWdobGlnaHRlZC10ZXh0JyxcbiAgICAgICAgICAgICAgICBtYXRjaGluZ01vZGU6ICdjb250YWlucycsXG4gICAgICAgICAgICAgICAgaWdub3JlQ2FzZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBtYXhMZXZlbnNodGVpbkRpc3RhbmNlOiAzXG4gICAgICAgICAgICB9LCBvcHRpb25zKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmQoJyonKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgICR0aGlzLmZpbmQoJy4nICsgb3B0aW9ucy5oaWdobGlnaHRDbGFzc05hbWUpLmNvbnRlbnRzKCkudW53cmFwKCk7XG4gICAgICAgICAgICAgICAgaWYgKGlzSUUxMSkge1xuICAgICAgICAgICAgICAgICAgICBub3JtYWxpemVGb3JJRTExKHRoaXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ub3JtYWxpemUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHNlYXJjaFN0cmluZyAmJiBzZWFyY2hTdHJpbmcgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLmNvbnRlbnRzKCkuZmlsdGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm5vZGVUeXBlID09IDMgJiYgVHJpdmlhbENvcmVfMS50cml2aWFsTWF0Y2godGhpcy5ub2RlVmFsdWUsIHNlYXJjaFN0cmluZywgb3B0aW9ucykubGVuZ3RoID4gMDtcbiAgICAgICAgICAgICAgICAgICAgfSkucmVwbGFjZVdpdGgoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9sZE5vZGVWYWx1ZSA9ICh0aGlzLm5vZGVWYWx1ZSB8fCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlVmFsdWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoZXMgPSBUcml2aWFsQ29yZV8xLnRyaXZpYWxNYXRjaCh0aGlzLm5vZGVWYWx1ZSwgc2VhcmNoU3RyaW5nLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvbGRNYXRjaEVuZCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hdGNoZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2ggPSBtYXRjaGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGVWYWx1ZSArPSB0aGlzLm5vZGVWYWx1ZS5zdWJzdHJpbmcob2xkTWF0Y2hFbmQsIG1hdGNoLnN0YXJ0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlVmFsdWUgKz0gXCI8c3BhbiBjbGFzcz1cXFwiXCIgKyBvcHRpb25zLmhpZ2hsaWdodENsYXNzTmFtZSArIFwiXFxcIj5cIiArIG9sZE5vZGVWYWx1ZS5zdWJzdHIobWF0Y2guc3RhcnQsIG1hdGNoLmxlbmd0aCkgKyBcIjwvc3Bhbj5cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGRNYXRjaEVuZCA9IG1hdGNoLnN0YXJ0ICsgbWF0Y2gubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZVZhbHVlICs9IG9sZE5vZGVWYWx1ZS5zdWJzdHJpbmcob2xkTWF0Y2hFbmQsIG9sZE5vZGVWYWx1ZS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGVWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgfShqUXVlcnkpKTtcbn0pO1xuXG4iXX0=
    </code></pre>    <br/>
        <br/>
    <div class='clear'></div>
    <!--
        <aside class="related-items">
            <section>
                <div class="panel panel-primary">
                    <div class="panel-heading margin-bottom">Related Artifacts</div>
                    <div class="">
                                        </div>
                </div>
            </section>
            <section>
                <div class="panel panel-primary">
                    <div class="panel-heading margin-bottom">Related Groups</div>
                    <div class="">
                                        </div>
                </div>
            </section>
        </aside>
        <div class='clear'></div>
    --></main>
    </div>
    <br/><br/>
        <div class="align-center">&copy; 2015 - 2025 <a href="/legal-notice.php">Weber Informatics LLC</a>&nbsp;|&nbsp;<a href="/data-protection.php">Privacy Policy</a></div>
    <br/><br/><br/><br/><br/><br/>
    </body>
    </html>