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

// 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 isObjectEmpty(obj) {
            if (Object.getOwnPropertyNames) {
                return (Object.getOwnPropertyNames(obj).length === 0);
            } else {
                var k;
                for (k in obj) {
                    if (obj.hasOwnProperty(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 hasOwnProp(a, b) {
            return Object.prototype.hasOwnProperty.call(a, b);
        }
    
        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,
                invalidMonth    : null,
                invalidFormat   : false,
                userInvalidated : false,
                iso             : false,
                parsedDateParts : [],
                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);
                var len = t.length >>> 0;
    
                for (var 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);
                var parsedParts = some.call(flags.parsedDateParts, function (i) {
                    return i != null;
                });
                var isNowValid = !isNaN(m._d.getTime()) &&
                    flags.overflow < 0 &&
                    !flags.empty &&
                    !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 = [];
    
        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;
        }
    
        var updateInProgress = false;
    
        // 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 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;
        }
    
        // 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;
        }
    
        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 = [];
                    var arg;
                    for (var i = 0; i < arguments.length; i++) {
                        arg = '';
                        if (typeof arguments[i] === 'object') {
                            arg += '\n[' + i + '] ';
                            for (var key in arguments[0]) {
                                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 input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
        }
    
        function set (config) {
            var prop, i;
            for (i in config) {
                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;
        }
    
        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.replace(/MMMM|MM|DD|dddd/g, function (val) {
                return val.slice(1);
            });
    
            return this._longDateFormat[key];
        }
    
        var defaultInvalidDate = 'Invalid date';
    
        function invalidDate () {
            return this._invalidDate;
        }
    
        var defaultOrdinal = '%d';
        var 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',
            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 = [];
            for (var u in unitsObj) {
                units.push({unit: u, priority: priorities[u]});
            }
            units.sort(function (a, b) {
                return a.priority - b.priority;
            });
            return units;
        }
    
        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?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
    
        var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
    
        var formatFunctions = {};
    
        var 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 match1         = /\d/;            //       0 - 9
        var match2         = /\d\d/;          //      00 - 99
        var match3         = /\d{3}/;         //     000 - 999
        var match4         = /\d{4}/;         //    0000 - 9999
        var match6         = /[+-]?\d{6}/;    // -999999 - 999999
        var match1to2      = /\d\d?/;         //       0 - 99
        var match3to4      = /\d\d\d\d?/;     //     999 - 9999
        var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
        var match1to3      = /\d{1,3}/;       //       0 - 999
        var match1to4      = /\d{1,4}/;       //       0 - 9999
        var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
    
        var matchUnsigned  = /\d+/;           //       0 - inf
        var matchSigned    = /[+-]?\d+/;      //    -inf - inf
    
        var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
        var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
    
        var 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
        var 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;
    
        var 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;
        var MONTH = 1;
        var DATE = 2;
        var HOUR = 3;
        var MINUTE = 4;
        var SECOND = 5;
        var MILLISECOND = 6;
        var WEEK = 7;
        var WEEKDAY = 8;
    
        // FORMATTING
    
        addFormatToken('Y', 0, 0, function () {
            var y = this.year();
            return y <= 9999 ? '' + y : '+' + 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;
        }
    
        function isLeapYear(year) {
            return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
        }
    
        // 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 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) {
                    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);
                for (var 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;
        }
    
        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 MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
        var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
        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()];
        }
    
        var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
        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());
        }
    
        var defaultMonthsShortRegex = matchWord;
        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;
            }
        }
    
        var defaultMonthsRegex = matchWord;
        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');
        }
    
        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;
            // the Date.UTC function remaps years 0-99 to 1900-1999
            if (y < 100 && y >= 0) {
                var 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('_');
        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;
        }
    
        var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
        function localeWeekdaysShort (m) {
            return (m === true) ? shiftWeekdays(this._weekdaysShort, this._week.dow)
                : (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
        }
    
        var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
        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;
            }
        }
    
        var defaultWeekdaysRegex = matchWord;
        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;
            }
        }
    
        var defaultWeekdaysShortRegex = matchWord;
        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;
            }
        }
    
        var defaultWeekdaysMinRegex = matchWord;
        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 = this.weekdaysMin(mom, '');
                shortp = this.weekdaysShort(mom, '');
                longp = 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);
            for (i = 0; i < 7; i++) {
                shortPieces[i] = regexEscape(shortPieces[i]);
                longPieces[i] = regexEscape(longPieces[i]);
                mixedPieces[i] = regexEscape(mixedPieces[i]);
            }
    
            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;
            var 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;
            var 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;
        function localeMeridiem (hours, minutes, isLower) {
            if (hours > 11) {
                return isLower ? 'pm' : 'PM';
            } else {
                return isLower ? 'am' : 'AM';
            }
        }
    
    
        // MOMENTS
    
        // 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.
        var getSetHour = makeGetSet('Hours', true);
    
        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 = {};
        var localeFamilies = {};
        var globalLocale;
    
        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 && compareArrays(split, next, true) >= 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;
            // TODO: Find a better way to register and load all the locales in Node
            if (!locales[name] && (typeof module !== 'undefined') &&
                    module && module.exports) {
                try {
                    oldLocale = globalLocale._abbr;
                    var aliasedRequire = require;
                    aliasedRequire('./locale/' + name);
                    getSetGlobalLocale(oldLocale);
                } catch (e) {}
            }
            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;
                // MERGE
                tmpLocale = loadLocale(name);
                if (tmpLocale != null) {
                    parentConfig = tmpLocale._config;
                }
                config = mergeConfigs(parentConfig, config);
                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;
                    } 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;
            var 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;
        }
    
        // 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;
    
            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;
    
                var 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;
            }
        }
    
        // 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)?)?$/;
        var 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)?)?$/;
    
        var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
    
        var 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}/],
            // YYYYMM is NOT allowed by the standard
            ['GGGG[W]WWE', /\d{4}W\d{3}/],
            ['GGGG[W]WW', /\d{4}W\d{2}/, false],
            ['YYYYDDD', /\d{7}/]
        ];
    
        // iso time formats and regexes
        var 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/]
        ];
    
        var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
    
        // 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;
            }
        }
    
        // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
        var 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}))$/;
    
        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 indepentent 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;
        }
    
        var 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
        };
    
        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);
                var 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));
            if (match) {
                var 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 iso format or fallback
        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;
            }
    
            // 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 and will be removed in an upcoming major release. Please refer to ' +
            'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
            function (config) {
                config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
            }
        );
    
        // 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;
    
            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];
                // console.log('token', token, 'parsedInput', parsedInput,
                //         'regex', getParseRegexForToken(token, config));
                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);
    
            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;
    
            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;
                tempConfig = copyConfig({}, config);
                if (config._useUTC != null) {
                    tempConfig._useUTC = config._useUTC;
                }
                tempConfig._f = config._f[i];
                configFromStringAndFormat(tempConfig);
    
                if (!isValid(tempConfig)) {
                    continue;
                }
    
                // 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 (scoreToBeat == null || currentScore < scoreToBeat) {
                    scoreToBeat = currentScore;
                    bestMoment = tempConfig;
                }
            }
    
            extend(config, bestMoment || tempConfig);
        }
    
        function configFromObject(config) {
            if (config._d) {
                return;
            }
    
            var i = normalizeObjectUnits(config._i);
            config._a = map([i.year, i.month, i.day || i.date, 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 (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();
                }
            }
        );
    
        var 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) {
            for (var key in m) {
                if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
                    return false;
                }
            }
    
            var unitHasDecimal = false;
            for (var 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);
            }
        }
    
        // FORMATTING
    
        function offset (token, separator) {
            addFormatToken(token, 0, 0, function () {
                var offset = this.utcOffset();
                var 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);
    
            if (matches === null) {
                return null;
            }
    
            var chunk   = matches[matches.length - 1] || [];
            var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
            var 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() / 15) * 15;
        }
    
        // 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 = {};
    
            copyConfig(c, this);
            c = prepareConfig(c);
    
            if (c._a) {
                var 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
        var 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)) {
                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;
            }
    
            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;
                }
    
                val = typeof val === 'string' ? +val : val;
                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');
        var subtract = createAdder(-1, 'subtract');
    
        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) {
            // 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';
    
            var 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) {
            // 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;
            var 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';
            var zone = '';
            if (!this.isLocal()) {
                func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
                zone = 'Z';
            }
            var prefix = '[' + func + '("]';
            var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
            var datetime = '-MM-DD[T]HH:mm:ss.SSS';
            var 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;
        var MS_PER_MINUTE = 60 * MS_PER_SECOND;
        var MS_PER_HOUR = 60 * MS_PER_MINUTE;
        var 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;
            units = normalizeUnits(units);
            if (units === undefined || units === 'millisecond' || !this.isValid()) {
                return this;
            }
    
            var 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;
            units = normalizeUnits(units);
            if (units === undefined || units === 'millisecond' || !this.isValid()) {
                return this;
            }
    
            var 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
            };
        }
    
        // 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 getWeeksInYear () {
            var weekInfo = this.localeData()._week;
            return weeksInYear(this.year(), 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;
        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);
        }
        // MOMENTS
    
        var 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;
        proto.toJSON            = toJSON;
        proto.toString          = toString;
        proto.unix              = unix;
        proto.valueOf           = valueOf;
        proto.creationData      = creationData;
        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.isoWeeksInYear = getISOWeeksInYear;
        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.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();
            var 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;
            var 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;
    
            if (index != null) {
                return get$1(format, (index + shift) % 7, field, 'day');
            }
    
            var i;
            var out = [];
            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', {
            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;
            var days         = this._days;
            var months       = this._months;
            var data         = this._data;
            var 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;
            var months;
            var 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');
        var asSeconds      = makeAs('s');
        var asMinutes      = makeAs('m');
        var asHours        = makeAs('h');
        var asDays         = makeAs('d');
        var asWeeks        = makeAs('w');
        var asMonths       = makeAs('M');
        var asQuarters     = makeAs('Q');
        var 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');
        var seconds      = makeGetter('seconds');
        var minutes      = makeGetter('minutes');
        var hours        = makeGetter('hours');
        var days         = makeGetter('days');
        var months       = makeGetter('months');
        var years        = makeGetter('years');
    
        function weeks () {
            return absFloor(this.days() / 7);
        }
    
        var round = Math.round;
        var 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
            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, locale) {
            var duration = createDuration(posNegDuration).abs();
            var seconds  = round(duration.as('s'));
            var minutes  = round(duration.as('m'));
            var hours    = round(duration.as('h'));
            var days     = round(duration.as('d'));
            var months   = round(duration.as('M'));
            var years    = round(duration.as('y'));
    
            var 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]    ||
                    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 (withSuffix) {
            if (!this.isValid()) {
                return this.localeData().invalidDate();
            }
    
            var locale = this.localeData();
            var output = relativeTime$1(this, !withSuffix, 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;
            var days         = abs$1(this._days);
            var months       = abs$1(this._months);
            var minutes, hours, years;
    
            // 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
            var Y = years;
            var M = months;
            var D = days;
            var h = hours;
            var m = minutes;
            var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
            var total = this.asSeconds();
    
            if (!total) {
                // this is the same as C#'s (Noda) and python (isodate)...
                // but not other JS (goog.date)
                return 'P0D';
            }
    
            var totalSign = total < 0 ? '-' : '';
            var ymSign = sign(this._months) !== sign(total) ? '-' : '';
            var daysSign = sign(this._days) !== sign(total) ? '-' : '';
            var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
    
            return totalSign + 'P' +
                (Y ? ymSign + Y + 'Y' : '') +
                (M ? ymSign + M + 'M' : '') +
                (D ? daysSign + D + 'D' : '') +
                ((h || m || s) ? 'T' : '') +
                (h ? hmsSign + h + 'H' : '') +
                (m ? hmsSign + m + 'M' : '') +
                (s ? 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;
    
        // Side effect imports
    
        // 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, 10) * 1000);
        });
        addParseToken('x', function (input, array, config) {
            config._d = new Date(toInt(input));
        });
    
        // Side effect imports
    
        //! moment.js
    
        hooks.version = '2.24.0';
    
        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
    
        hooks.defineLocale('ar-dz', {
            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 : 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 = 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-ly', {
            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')
            },
            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 : 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 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$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', {
            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, 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 : 'birneçə 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 дни',
                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', {
            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 === 'রাত' && 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$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('bo', {
            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 : '[བདུན་ཕྲག་རྗེས་མ], 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
    
        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);
        }
    
        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('_'),
            weekdaysParseExact : true,
            longDateFormat : {
                LT : 'h[e]mm A',
                LTS : 'h[e]mm:ss A',
                L : 'DD/MM/YYYY',
                LL : 'D [a viz] MMMM YYYY',
                LLL : 'D [a viz] MMMM YYYY h[e]mm A',
                LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
            },
            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.
            }
        });
    
        //! 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$3 = '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('_');
    
        var monthsParse = [/^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'.
        var monthsRegex$1 = /^(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';
                    }
                    break;
                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';
                    }
                    break;
                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';
                    }
                    break;
                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';
                    }
                    break;
                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';
                    }
                    break;
                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';
                    }
                    break;
            }
        }
    
        hooks.defineLocale('cs', {
            months : months$3,
            monthsShort : monthsShort,
            monthsRegex : monthsRegex$1,
            monthsShortRegex : monthsRegex$1,
            // 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,
            longMonthsParse : monthsParse,
            shortMonthsParse : monthsParse,
            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'],
                '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,
                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'],
                '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,
                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'],
                '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,
                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$4 = [
            'ޖެނުއަރީ',
            'ފެބްރުއަރީ',
            'މާރިޗު',
            'އޭޕްރީލު',
            'މޭ',
            'ޖޫން',
            'ޖުލައި',
            'އޯގަސްޓު',
            'ސެޕްޓެމްބަރު',
            'އޮކްޓޯބަރު',
            'ނޮވެމްބަރު',
            'ޑިސެމްބަރު'
        ], weekdays = [
            'އާދިއްތަ',
            'ހޯމަ',
            'އަންގާރަ',
            'ބުދަ',
            'ބުރާސްފަތި',
            'ހުކުރު',
            'ހޮނިހިރު'
        ];
    
        hooks.defineLocale('dv', {
            months : months$4,
            monthsShort : months$4,
            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
    
        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(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-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('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 : 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-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',
                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-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('eo', {
            months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'),
            monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_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 : 'D[-a de] MMMM, YYYY',
                LLL : 'D[-a de] MMMM, YYYY HH:mm',
                LLLL : 'dddd, [la] D[-a de] MMMM, 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 [je] LT',
                lastDay : '[Hieraŭ je] LT',
                lastWeek : '[pasinta] dddd [je] LT',
                sameElse : 'L'
            },
            relativeTime : {
                future : 'post %s',
                past : 'antaŭ %s',
                s : 'sekundoj',
                ss : '%d sekundoj',
                m : 'minuto',
                mm : '%d minutoj',
                h : 'horo',
                hh : '%d horoj',
                d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo
                dd : '%d tagoj',
                M : 'monato',
                MM : '%d monatoj',
                y : '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('_');
    
        var monthsParse$1 = [/^ene/i, /^feb/i, /^mar/i, /^abr/i, /^may/i, /^jun/i, /^jul/i, /^ago/i, /^sep/i, /^oct/i, /^nov/i, /^dic/i];
        var monthsRegex$2 = /^(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$2,
            monthsShortRegex: monthsRegex$2,
            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$1,
            longMonthsParse: monthsParse$1,
            shortMonthsParse: monthsParse$1,
            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',
                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('_');
    
        var 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];
        var 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-us', {
            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$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 : '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',
                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$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('_');
    
        var 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];
        var 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', {
            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$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',
                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
    
        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$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('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$4[match];
                }).replace(/،/g, ',');
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$5[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':
                    return isFuture ? 'sekunnin' : 'sekuntia';
                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('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
    
        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('_'),
            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|)/,
            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$5 = [
            'Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine', 'Méitheamh', 'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deaireadh Fómhair', 'Samhain', 'Nollaig'
        ];
    
        var monthsShort$4 = ['Eaná', 'Feab', 'Márt', 'Aibr', 'Beal', 'Méit', 'Iúil', 'Lúna', 'Meán', 'Deai', 'Samh', 'Noll'];
    
        var weekdays$1 = ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt', 'Dé Céadaoin', 'Déardaoin', 'Dé hAoine', 'Dé Satharn'];
    
        var weekdaysShort = ['Dom', 'Lua', 'Mái', 'Céa', 'Déa', 'hAo', 'Sat'];
    
        var weekdaysMin = ['Do', 'Lu', 'Má', 'Ce', 'Dé', 'hA', 'Sa'];
    
        hooks.defineLocale('ga', {
            months: months$5,
            monthsShort: monthsShort$4,
            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é aig] 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í',
                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$6 = [
            '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'
        ];
    
        var monthsShort$5 = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'];
    
        var weekdays$2 = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'];
    
        var weekdaysShort$1 = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'];
    
        var weekdaysMin$1 = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'];
    
        hooks.defineLocale('gd', {
            months : months$6,
            monthsShort : monthsShort$5,
            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': ['thodde secondanim', 'thodde second'],
                'ss': [number + ' secondanim', number + ' second'],
                'm': ['eka mintan', 'ek minute'],
                'mm': [number + ' mintanim', number + ' mintam'],
                'h': ['eka voran', 'ek vor'],
                'hh': [number + ' voranim', number + ' voram'],
                'd': ['eka disan', 'ek dis'],
                'dd': [number + ' disanim', number + ' dis'],
                'M': ['eka mhoinean', 'ek mhoino'],
                'MM': [number + ' mhoineanim', number + ' mhoine'],
                'y': ['eka vorsan', 'ek voros'],
                'yy': [number + ' vorsanim', number + ' vorsam']
            };
            return withoutSuffix ? format[key][0] : format[key][1];
        }
    
        hooks.defineLocale('gom-latn', {
            months : 'Janer_Febrer_Mars_Abril_Mai_Jun_Julai_Agost_Setembr_Otubr_Novembr_Dezembr'.split('_'),
            monthsShort : 'Jan._Feb._Mars_Abr._Mai_Jun_Jul._Ago._Set._Otu._Nov._Dez.'.split('_'),
            monthsParseExact : true,
            weekdays : 'Aitar_Somar_Mongllar_Budvar_Brestar_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[achea] Do, YYYY, A h:mm [vazta]',
                llll: 'ddd, D MMM YYYY, A h:mm [vazta]'
            },
            calendar : {
                sameDay: '[Aiz] LT',
                nextDay: '[Faleam] LT',
                nextWeek: '[Ieta to] dddd[,] LT',
                lastDay: '[Kal] LT',
                lastWeek: '[Fatlo] dddd[,] LT',
                sameElse: 'L'
            },
            relativeTime : {
                future : '%s',
                past : '%s adim',
                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}(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 : 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: /rati|sokalli|donparam|sanje/,
            meridiemHour : function (hour, meridiem) {
                if (hour === 12) {
                    hour = 0;
                }
                if (meridiem === 'rati') {
                    return hour < 4 ? hour : hour + 12;
                } else if (meridiem === 'sokalli') {
                    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 'sokalli';
                } else if (hour < 16) {
                    return 'donparam';
                } else if (hour < 20) {
                    return 'sanje';
                } else {
                    return 'rati';
                }
            }
        });
    
        //! 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('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$5[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$6[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$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('hi', {
            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];
                });
            },
            // 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 : '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$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('_'),
            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 : 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$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: '[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('ja', {
            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/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 '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 : {
                standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
                format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
            },
            monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'),
            weekdays : {
                standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
                format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'),
                isFormat: /(წინა|შემდეგ)/
            },
            weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'),
            weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.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 : '[დღეს] LT[-ზე]',
                nextDay : '[ხვალ] LT[-ზე]',
                lastDay : '[გუშინ] LT[-ზე]',
                nextWeek : '[შემდეგ] dddd LT[-ზე]',
                lastWeek : '[წინა] dddd LT-ზე',
                sameElse : 'L'
            },
            relativeTime : {
                future : function (s) {
                    return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
                        s.replace(/ი$/, 'ში') :
                        s + 'ში';
                },
                past : function (s) {
                    if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
                        return s.replace(/(ი|ე)$/, 'ის წინ');
                    }
                    if ((/წელი/).test(s)) {
                        return s.replace(/წელი$/, 'წლის წინ');
                    }
                },
                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$8 = {
            '1': '១',
            '2': '២',
            '3': '៣',
            '4': '៤',
            '5': '៥',
            '6': '៦',
            '7': '៧',
            '8': '៨',
            '9': '៩',
            '0': '០'
        }, numberMap$7 = {
            '១': '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$7[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$8[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$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('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$8[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$9[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$a = {
            '1': '١',
            '2': '٢',
            '3': '٣',
            '4': '٤',
            '5': '٥',
            '6': '٦',
            '7': '٧',
            '8': '٨',
            '9': '٩',
            '0': '٠'
        }, numberMap$9 = {
            '١': '1',
            '٢': '2',
            '٣': '3',
            '٤': '4',
            '٥': '5',
            '٦': '6',
            '٧': '7',
            '٨': '8',
            '٩': '9',
            '٠': '0'
        },
        months$7 = [
            'کانونی دووەم',
            'شوبات',
            'ئازار',
            'نیسان',
            'ئایار',
            'حوزەیران',
            'تەمموز',
            'ئاب',
            'ئەیلوول',
            'تشرینی یەكەم',
            'تشرینی دووەم',
            'كانونی یەکەم'
        ];
    
    
        hooks.defineLocale('ku', {
            months : months$7,
            monthsShort : months$7,
            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$9[match];
                }).replace(/،/g, ',');
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$a[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$5(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$5,
                mm : '%d Minutten',
                h : processRelativeTime$5,
                hh : '%d Stonnen',
                d : processRelativeTime$5,
                dd : '%d Deeg',
                M : processRelativeTime$5,
                MM : '%d Méint',
                y : processRelativeTime$5,
                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$b = {
            '1': '१',
            '2': '२',
            '3': '३',
            '4': '४',
            '5': '५',
            '6': '६',
            '7': '७',
            '8': '८',
            '9': '९',
            '0': '०'
        },
        numberMap$a = {
            '१': '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$a[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$b[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 'रात्री';
                }
            },
            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$c = {
            '1': '၁',
            '2': '၂',
            '3': '၃',
            '4': '၄',
            '5': '၅',
            '6': '၆',
            '7': '၇',
            '8': '၈',
            '9': '၉',
            '0': '၀'
        }, numberMap$b = {
            '၁': '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$b[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$c[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_april_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',
                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$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('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$c[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$d[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('_');
    
        var monthsParse$4 = [/^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];
        var monthsRegex$5 = /^(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$5,
            monthsShortRegex: monthsRegex$5,
            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$4,
            longMonthsParse : monthsParse$4,
            shortMonthsParse : monthsParse$4,
    
            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('_');
    
        var monthsParse$5 = [/^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];
        var monthsRegex$6 = /^(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$6,
            monthsShortRegex: monthsRegex$6,
            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$5,
            longMonthsParse : monthsParse$5,
            shortMonthsParse : monthsParse$5,
    
            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
    
        hooks.defineLocale('nn', {
            months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
            monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
            weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'),
            weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'),
            weekdaysMin : 'su_må_ty_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 [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',
                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
    
        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('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$d[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$e[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('_');
        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 '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 (format === '') {
                    // Hack: if format empty we know this is used to generate
                    // RegExp by moment. Give then back both valid forms of months
                    // in RegExp ready format.
                    return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')';
                } 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('_'),
            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',
                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º'
        });
    
        //! 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',
                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',
                    '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._febr._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,
                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': 'день_дня_дней',
                'MM': 'месяц_месяца_месяцев',
                'yy': 'год_года_лет'
            };
            if (key === 'm') {
                return withoutSuffix ? 'минута' : 'минуту';
            }
            else {
                return number + ' ' + plural$4(format[key], +number);
            }
        }
        var monthsParse$6 = [/^янв/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$6,
            longMonthsParse : monthsParse$6,
            shortMonthsParse : monthsParse$6,
    
            // полные названия с падежами, по три буквы, для некоторых, по 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,
                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$8 = [
            'جنوري',
            'فيبروري',
            'مارچ',
            'اپريل',
            'مئي',
            'جون',
            'جولاءِ',
            'آگسٽ',
            'سيپٽمبر',
            'آڪٽوبر',
            'نومبر',
            'ڊسمبر'
        ];
        var days$1 = [
            'آچر',
            'سومر',
            'اڱارو',
            'اربع',
            'خميس',
            'جمع',
            'ڇنڇر'
        ];
    
        hooks.defineLocale('sd', {
            months : months$8,
            monthsShort : months$8,
            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$9 = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'),
            monthsShort$6 = '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';
                    }
                    break;
                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';
                    }
                    break;
                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';
                    }
                    break;
                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';
                    }
                    break;
                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';
                    }
                    break;
                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';
                    }
                    break;
            }
        }
    
        hooks.defineLocale('sk', {
            months : months$9,
            monthsShort : monthsShort$6,
            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$6(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$6,
                ss     : processRelativeTime$6,
                m      : processRelativeTime$6,
                mm     : processRelativeTime$6,
                h      : processRelativeTime$6,
                hh     : processRelativeTime$6,
                d      : processRelativeTime$6,
                dd     : processRelativeTime$6,
                M      : processRelativeTime$6,
                MM     : processRelativeTime$6,
                y      : processRelativeTime$6,
                yy     : processRelativeTime$6
            },
            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: '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',
                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 7th 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: '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] [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',
                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 : 'masiku %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$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('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$e[match];
                });
            },
            postformat: function (string) {
                return string.replace(/\d/g, function (match) {
                    return symbolMap$f[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 : 'minutu balun',
                ss : 'minutu %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 : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.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 วัน',
                M : '1 เดือน',
                MM : '%d เดือน',
                y : '1 ปี',
                yy : '%d ปี'
            }
        });
    
        //! 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.
            }
        });
    
        var suffixes$4 = {
            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('_'),
            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',
                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$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
    
        // 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$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 : 4  // The week that contains Jan 4th is the first week of the year.
            }
        });
    
        function processRelativeTime$7(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 language 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('_')
            };
    
            if (m === true) {
                return weekdays['nominative'].slice(1, 7).concat(weekdays['nominative'].slice(0, 1));
            }
            if (!m) {
                return weekdays['nominative'];
            }
    
            var 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$a = [
            'جنوری',
            'فروری',
            'مارچ',
            'اپریل',
            'مئی',
            'جون',
            'جولائی',
            'اگست',
            'ستمبر',
            'اکتوبر',
            'نومبر',
            'دسمبر'
        ];
        var days$2 = [
            'اتوار',
            'پیر',
            'منگل',
            'بدھ',
            'جمعرات',
            'جمعہ',
            'ہفتہ'
        ];
    
        hooks.defineLocale('ur', {
            months : months$a,
            monthsShort : months$a,
            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 : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.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 rồi 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',
                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 : '[下]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 年'
            },
            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 < 1130) {
                    return '上午';
                } else if (hm < 1230) {
                    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-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";var e,i={},f={},u={},c={};s&&"string"==typeof s.version||A("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 a(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+a(o.charCodeAt(e));for(e=0;e<r.length;e++)s/=60,i+=a(r.charCodeAt(e))*s;return i*f}function l(t){for(var e=0;e<t.length;e++)t[e]=r(t[e])}function h(t,e){var n,o=[];for(n=0;n<e.length;n++)o[n]=t[e[n]];return o}function p(t){var e=t.split("|"),n=e[2].split(" "),o=e[3].split(""),r=e[4].split(" ");return l(n),l(o),l(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:h(e[1].split(" "),o),offsets:h(n,o),untils:r,population:0|e[5]}}function m(t){t&&this._set(p(t))}function d(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 z(t){this.zone=t,this.offsetScore=0,this.abbrScore=0}function v(t,e){for(var n,o;o=6e4*((e.at-t.at)/12e4|0);)(n=new d(new Date(t.at+o))).offset===t.offset?t=n:e=n;return t}function b(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 g(t,e){var n,o;for(l(e),n=0;n<e.length;n++)o=e[n],c[o]=c[o]||{},c[o][t]=!0}function _(){try{var t=Intl.DateTimeFormat().resolvedOptions().timeZone;if(t&&3<t.length){var e=u[w(t)];if(e)return e;A("Moment Timezone found "+t+" from the Intl api, but did not have that data loaded.")}}catch(t){}var n,o,r,s=function(){var t,e,n,o=(new Date).getFullYear()-2,r=new d(new Date(o,0,1)),s=[r];for(n=1;n<48;n++)(e=new d(new Date(o,n,1))).offset!==r.offset&&(t=v(r,e),s.push(t),s.push(new d(new Date(t.at+6e4)))),r=e;for(n=0;n<4;n++)s.push(new d(new Date(o+n,0,1))),s.push(new d(new Date(o+n,6,1)));return s}(),i=s.length,f=function(t){var e,n,o,r=t.length,s={},i=[];for(e=0;e<r;e++)for(n in o=c[t[e].offset]||{})o.hasOwnProperty(n)&&(s[n]=!0);for(e in s)s.hasOwnProperty(e)&&i.push(u[e]);return i}(s),a=[];for(o=0;o<f.length;o++){for(n=new z(O(f[o]),i),r=0;r<i;r++)n.scoreOffsetAt(s[r]);a.push(n)}return a.sort(b),0<a.length?a[0].zone.name:void 0}function w(t){return(t||"").toLowerCase().replace(/\//g,"_")}function y(t){var e,n,o,r;for("string"==typeof t&&(t=[t]),e=0;e<t.length;e++)r=w(n=(o=t[e].split("|"))[0]),i[r]=t[e],u[r]=n,g(r,o[2].split(" "))}function O(t,e){t=w(t);var n,o=i[t];return o instanceof m?o:"string"==typeof o?(o=new m(o),i[t]=o):f[t]&&e!==O&&(n=O(f[t],O))?((o=i[t]=new m)._set(n),o.name=u[t],o):null}function S(t){var e,n,o,r;for("string"==typeof t&&(t=[t]),e=0;e<t.length;e++)o=w((n=t[e].split("|"))[0]),r=w(n[1]),f[o]=r,u[o]=n[0],f[r]=o,u[r]=n[1]}function M(t){var e="X"===t._f||"x"===t._f;return!(!t._a||void 0!==t._tzm||e)}function A(t){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(t)}function j(t){var e=Array.prototype.slice.call(arguments,0,-1),n=arguments[arguments.length-1],o=O(n),r=s.utc.apply(null,e);return o&&!s.isMoment(t)&&M(r)&&r.add(o.parse(r),"minutes"),r.tz(n),r}(n<2||2==n&&o<6)&&A("Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js "+s.version+". See momentjs.com"),m.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){var e,n=+t,o=this.untils;for(e=0;e<o.length;e++)if(n<o[e])return e},parse:function(t){var e,n,o,r,s=+t,i=this.offsets,f=this.untils,a=f.length-1;for(r=0;r<a;r++)if(e=i[r],n=i[r+1],o=i[r?r-1:r],e<n&&j.moveAmbiguousForward?e=n:o<e&&j.moveInvalidForward&&(e=o),s<f[r]-6e4*e)return i[r];return i[a]},abbr:function(t){return this.abbrs[this._index(t)]},offset:function(t){return A("zone.offset has been deprecated in favor of zone.utcOffset"),this.offsets[this._index(t)]},utcOffset:function(t){return this.offsets[this._index(t)]}},z.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++},j.version="0.5.27",j.dataVersion="",j._zones=i,j._links=f,j._names=u,j.add=y,j.link=S,j.load=function(t){y(t.zones),S(t.links),j.dataVersion=t.version},j.zone=O,j.zoneExists=function t(e){return t.didShowError||(t.didShowError=!0,A("moment.tz.zoneExists('"+e+"') has been deprecated in favor of !moment.tz.zone('"+e+"')")),!!O(e)},j.guess=function(t){return e&&!t||(e=_()),e},j.names=function(){var t,e=[];for(t in u)u.hasOwnProperty(t)&&(i[t]||i[f[t]])&&u[t]&&e.push(u[t]);return e.sort()},j.Zone=m,j.unpack=p,j.unpackBase60=r,j.needsOffset=M,j.moveInvalidForward=!0,j.moveAmbiguousForward=!1;var T,D=s.fn;function x(t){return function(){return this._z?this._z.abbr(this):t.call(this)}}function Z(t){return function(){return this._z=null,t.apply(this,arguments)}}s.tz=j,s.defaultZone=null,s.updateOffset=function(t,e){var n,o=s.defaultZone;if(void 0===t._z&&(o&&M(t)&&!t._isUTC&&(t._d=s.utc(t._a)._d,t.utc().add(o.parse(t),"minutes")),t._z=o),t._z)if(n=t._z.utcOffset(t),Math.abs(n)<16&&(n/=60),void 0!==t.utcOffset){var r=t._z;t.utcOffset(-n,e),t._z=r}else t.zone(n,e)},D.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=O(t),this._z?s.updateOffset(this,e):A("Moment Timezone has no data for "+t+". See http://momentjs.com/timezone/docs/#/data-loading/."),this}if(this._z)return this._z.name},D.zoneName=x(D.zoneName),D.zoneAbbr=x(D.zoneAbbr),D.utc=Z(D.utc),D.local=Z(D.local),D.utcOffset=(T=D.utcOffset,function(){return 0<arguments.length&&(this._z=null),T.apply(this,arguments)}),s.tz.setDefault=function(t){return(n<2||2==n&&o<9)&&A("Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js "+s.version+"."),s.defaultZone=t?O(t):null,s};var C=s.momentProperties;return"[object Array]"===Object.prototype.toString.call(C)?(C.push("_z"),C.push("_a")):C&&(C._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) {
        // ReSharper disable InconsistentNaming
        var 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 = {};
    
        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: {
                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-delete',
                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,
            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: ','
        };
    
        // 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._int();
            }
    
            /**
             * @return {string}
             */
    
    
            //private
    
            DateTimePicker.prototype._int = function _int() {
                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.options(this._options);
    
                this._initFormatting();
    
                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._options.inline) {
                    this.show();
                }
            };
    
            DateTimePicker.prototype._update = function _update() {
                if (!this.widget) {
                    return;
                }
                this._fillDate();
                this._fillTime();
            };
    
            DateTimePicker.prototype._setValue = function _setValue(targetMoment, index) {
                var oldDate = this.unset ? null : this._dates[index];
                var outpValue = '';
                // case of calling setValue(null or false)
                if (!targetMoment) {
                    if (!this._options.allowMultidate || this._dates.length === 1) {
                        this.unset = true;
                        this._dates = [];
                        this._datesFormatted = [];
                    } else {
                        outpValue = this._element.data('date') + ',';
                        outpValue = outpValue.replace(oldDate.format(this.actualFormat) + ',', '').replace(',,', '').replace(/,\s*$/, '');
                        this._dates.splice(index, 1);
                        this._datesFormatted.splice(index, 1);
                    }
                    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
                    });
                    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)) {
                    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(/,\s*$/, '');
                    } else {
                        outpValue = this._dates[index].format(this.actualFormat);
                    }
                    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
                    });
                } else {
                    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
                        });
                    }
                    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);
                e.stopImmediatePropagation();
                return false;
            };
    
            //noinspection JSMethodCanBeStatic
    
    
            DateTimePicker.prototype._getOptions = function _getOptions(options) {
                options = $.extend(true, {}, Default, 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._notifyEvent = function _notifyEvent(e) {
                if (e.type === DateTimePicker.Event.CHANGE && (e.date && e.date.isSame(e.oldDate)) || !e.date && !e.oldDate) {
                    return;
                }
                this._element.trigger(e);
            };
    
            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.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) {
                if (this._options.parseInputDate === undefined) {
                    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._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() {
                return this._dates[this._getLastPickedDateIndex()];
            };
    
            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) {
                    returnMoment = moment(); //TODO should this use format? and 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.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;
                $.each(this._options, function (key, value) {
                    if (self[key] !== undefined) {
                        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]');
                }
    
                this._setValue(newDate === null ? null : this._parseInputDate(newDate), index);
            };
    
            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._viewUpdate();
            };
    
            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' || _multidateSeparator.length > 1) {
                    throw new TypeError('multidateSeparator expects a single character 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.1.2 (https://tempusdominus.github.io/bootstrap-4/)
     * Copyright 2016-2018 Jonathan Peterson
     * 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 () {
    
    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
    
    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 _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
    
    function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
    
    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) {
        // ReSharper disable InconsistentNaming
        var 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 = {};
    
        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: {
                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-delete',
                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,
            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: ','
        };
    
        // 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._int();
            }
    
            /**
             * @return {string}
             */
    
    
            //private
    
            DateTimePicker.prototype._int = function _int() {
                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.options(this._options);
    
                this._initFormatting();
    
                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._options.inline) {
                    this.show();
                }
            };
    
            DateTimePicker.prototype._update = function _update() {
                if (!this.widget) {
                    return;
                }
                this._fillDate();
                this._fillTime();
            };
    
            DateTimePicker.prototype._setValue = function _setValue(targetMoment, index) {
                var oldDate = this.unset ? null : this._dates[index];
                var outpValue = '';
                // case of calling setValue(null or false)
                if (!targetMoment) {
                    if (!this._options.allowMultidate || this._dates.length === 1) {
                        this.unset = true;
                        this._dates = [];
                        this._datesFormatted = [];
                    } else {
                        outpValue = this._element.data('date') + ',';
                        outpValue = outpValue.replace(oldDate.format(this.actualFormat) + ',', '').replace(',,', '').replace(/,\s*$/, '');
                        this._dates.splice(index, 1);
                        this._datesFormatted.splice(index, 1);
                    }
                    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
                    });
                    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)) {
                    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(/,\s*$/, '');
                    } else {
                        outpValue = this._dates[index].format(this.actualFormat);
                    }
                    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
                    });
                } else {
                    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
                        });
                    }
                    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);
                e.stopImmediatePropagation();
                return false;
            };
    
            //noinspection JSMethodCanBeStatic
    
    
            DateTimePicker.prototype._getOptions = function _getOptions(options) {
                options = $.extend(true, {}, Default, 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._notifyEvent = function _notifyEvent(e) {
                if (e.type === DateTimePicker.Event.CHANGE && (e.date && e.date.isSame(e.oldDate)) || !e.date && !e.oldDate) {
                    return;
                }
                this._element.trigger(e);
            };
    
            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.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) {
                if (this._options.parseInputDate === undefined) {
                    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._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() {
                return this._dates[this._getLastPickedDateIndex()];
            };
    
            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) {
                    returnMoment = moment(); //TODO should this use format? and 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.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;
                $.each(this._options, function (key, value) {
                    if (self[key] !== undefined) {
                        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]');
                }
    
                this._setValue(newDate === null ? null : this._parseInputDate(newDate), index);
            };
    
            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._viewUpdate();
            };
    
            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' || _multidateSeparator.length > 1) {
                    throw new TypeError('multidateSeparator expects a single character 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 */
    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 = void 0;
    
            if (!selector) {
                selector = $element.attr('href') || '';
                selector = /^#[a-z]/i.test(selector) ? selector : null;
            }
            $selector = $(selector);
            if ($selector.length === 0) {
                return $selector;
            }
    
            if (!$selector.data(DateTimePicker.DATA_KEY)) {
                $.extend({}, $selector.data(), $(this).data());
            }
    
            return $selector;
        };
    
        // ReSharper disable once InconsistentNaming
    
        var TempusDominusBootstrap4 = function (_DateTimePicker) {
            _inherits(TempusDominusBootstrap4, _DateTimePicker);
    
            function TempusDominusBootstrap4(element, options) {
                _classCallCheck(this, TempusDominusBootstrap4);
    
                var _this = _possibleConstructorReturn(this, _DateTimePicker.call(this, element, options));
    
                _this._init();
                return _this;
            }
    
            TempusDominusBootstrap4.prototype._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;
                    }
                }
            };
    
            TempusDominusBootstrap4.prototype._getDatePickerTemplate = function _getDatePickerTemplate() {
                var headTemplate = $('<thead>').append($('<tr>').append($('<th>').addClass('prev').attr('data-action', 'previous').append($('<span>').addClass(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($('<span>').addClass(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()))];
            };
    
            TempusDominusBootstrap4.prototype._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($('<span>').addClass(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($('<span>').addClass(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($('<span>').addClass(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($('<span>').addClass(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($('<span>').addClass(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($('<span>').addClass(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]));
            };
    
            TempusDominusBootstrap4.prototype._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;
            };
    
            TempusDominusBootstrap4.prototype._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($('<span>').addClass(this._options.icons.today))));
                }
                if (!this._options.sideBySide && this._hasDate() && this._hasTime()) {
                    var title = void 0,
                        icon = void 0;
                    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($('<span>').addClass(icon))));
                }
                if (this._options.buttons.showClear) {
                    row.push($('<td>').append($('<a>').attr({
                        href: '#',
                        tabindex: '-1',
                        'data-action': 'clear',
                        'title': this._options.tooltips.clear
                    }).append($('<span>').addClass(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($('<span>').addClass(this._options.icons.close))));
                }
                return row.length === 0 ? '' : $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
            };
    
            TempusDominusBootstrap4.prototype._getTemplate = function _getTemplate() {
                var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'),
                    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' : '')).append(this._getToolbar());
    
                if (this._options.inline) {
                    template.removeClass('dropdown-menu');
                }
    
                if (this.use24Hours) {
                    template.addClass('usetwentyfour');
                }
                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);
            };
    
            TempusDominusBootstrap4.prototype._place = function _place(e) {
                var self = e && e.data && e.data.picker || this,
                    vertical = self._options.widgetPositioning.vertical,
                    horizontal = self._options.widgetPositioning.horizontal,
                    parent = void 0;
                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'
                });
            };
    
            TempusDominusBootstrap4.prototype._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);
            };
    
            TempusDominusBootstrap4.prototype._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);
            };
    
            TempusDominusBootstrap4.prototype._updateMonths = function _updateMonths() {
                var monthsView = this.widget.find('.datepicker-months'),
                    monthsViewHeader = monthsView.find('th'),
                    months = monthsView.find('tbody').find('span'),
                    self = this;
    
                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 (this._getLastPickedDate().isSame(this._viewDate, 'y') && !this.unset) {
                    months.eq(this._getLastPickedDate().month()).addClass('active');
                }
    
                months.each(function (index) {
                    if (!self._isValid(self._viewDate.clone().month(index), 'M')) {
                        $(this).addClass('disabled');
                    }
                });
            };
    
            TempusDominusBootstrap4.prototype._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];
            };
    
            TempusDominusBootstrap4.prototype._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);
            };
    
            TempusDominusBootstrap4.prototype._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]);
                var minDateDecade = false,
                    maxDateDecade = false,
                    endDecadeYear = void 0,
                    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' + (this._getLastPickedDate().isAfter(startDecade) && this._getLastPickedDate().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);
            };
    
            TempusDominusBootstrap4.prototype._fillDate = function _fillDate() {
                var daysView = this.widget.find('.datepicker-days'),
                    daysViewHeader = daysView.find('th'),
                    html = [];
                var currentDate = void 0,
                    row = void 0,
                    clsName = void 0,
                    i = void 0;
    
                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');
                }
    
                daysView.find('tbody').empty().append(html);
    
                this._updateMonths();
    
                this._updateYears();
    
                this._updateDecades();
            };
    
            TempusDominusBootstrap4.prototype._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);
            };
    
            TempusDominusBootstrap4.prototype._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);
            };
    
            TempusDominusBootstrap4.prototype._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);
            };
    
            TempusDominusBootstrap4.prototype._fillTime = function _fillTime() {
                var toggle = void 0,
                    newDate = void 0;
                var timeComponents = this.widget.find('.timepicker span[data-time-component]');
    
                if (!this.use24Hours) {
                    toggle = this.widget.find('.timepicker [data-action=togglePeriod]');
                    newDate = this._getLastPickedDate().clone().add(this._getLastPickedDate().hours() >= 12 ? -12 : 12, 'h');
    
                    toggle.text(this._getLastPickedDate().format('A'));
    
                    if (this._isValid(newDate, 'h')) {
                        toggle.removeClass('disabled');
                    } else {
                        toggle.addClass('disabled');
                    }
                }
                timeComponents.filter('[data-time-component=hours]').text(this._getLastPickedDate().format('' + (this.use24Hours ? 'HH' : 'hh')));
                timeComponents.filter('[data-time-component=minutes]').text(this._getLastPickedDate().format('mm'));
                timeComponents.filter('[data-time-component=seconds]').text(this._getLastPickedDate().format('ss'));
    
                this._fillHours();
                this._fillMinutes();
                this._fillSeconds();
            };
    
            TempusDominusBootstrap4.prototype._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':
                        {
                            var newDate = lastPicked.clone().add(1, 'h');
                            if (this._isValid(newDate, 'h')) {
                                this._setValue(newDate, this._getLastPickedDateIndex());
                            }
                            break;
                        }
                    case 'incrementMinutes':
                        {
                            var _newDate = lastPicked.clone().add(this._options.stepping, 'm');
                            if (this._isValid(_newDate, 'm')) {
                                this._setValue(_newDate, this._getLastPickedDateIndex());
                            }
                            break;
                        }
                    case 'incrementSeconds':
                        {
                            var _newDate2 = lastPicked.clone().add(1, 's');
                            if (this._isValid(_newDate2, 's')) {
                                this._setValue(_newDate2, this._getLastPickedDateIndex());
                            }
                            break;
                        }
                    case 'decrementHours':
                        {
                            var _newDate3 = lastPicked.clone().subtract(1, 'h');
                            if (this._isValid(_newDate3, 'h')) {
                                this._setValue(_newDate3, this._getLastPickedDateIndex());
                            }
                            break;
                        }
                    case 'decrementMinutes':
                        {
                            var _newDate4 = lastPicked.clone().subtract(this._options.stepping, 'm');
                            if (this._isValid(_newDate4, 'm')) {
                                this._setValue(_newDate4, this._getLastPickedDateIndex());
                            }
                            break;
                        }
                    case 'decrementSeconds':
                        {
                            var _newDate5 = lastPicked.clone().subtract(1, 's');
                            if (this._isValid(_newDate5, 's')) {
                                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 = void 0;
    
                            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');
                                }
                                $span.toggleClass(this._options.icons.time + ' ' + this._options.icons.date);
    
                                if ($span.hasClass(this._options.icons.date)) {
                                    $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
    
    
            TempusDominusBootstrap4.prototype.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;
    
                this._notifyEvent({
                    type: DateTimePicker.Event.HIDE,
                    date: this._getLastPickedDate().clone()
                });
    
                if (this.input !== undefined) {
                    this.input.blur();
                }
    
                this._viewDate = this._getLastPickedDate().clone();
            };
    
            TempusDominusBootstrap4.prototype.show = function show() {
                var currentMoment = void 0;
                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()), 0);
                    } else if (this.unset && this._options.useCurrent) {
                        currentMoment = this.getMoment();
                        if (typeof this._options.useCurrent === 'string') {
                            currentMoment = useCurrentGranularity[this._options.useCurrent](currentMoment);
                        }
                        this._setValue(currentMoment, 0);
                    }
                } else if (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
                });
            };
    
            TempusDominusBootstrap4.prototype.destroy = function destroy() {
                this.hide();
                //todo doc off?
                this._element.removeData(DateTimePicker.DATA_KEY);
                this._element.removeData('date');
            };
    
            TempusDominusBootstrap4.prototype.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
                }
            };
    
            TempusDominusBootstrap4.prototype.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
                }
            };
    
            TempusDominusBootstrap4.prototype.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();
                }
            };
    
            TempusDominusBootstrap4.prototype.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();
            };
    
            TempusDominusBootstrap4.prototype.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();
                }
            };
    
            //static
    
    
            TempusDominusBootstrap4._jQueryHandleThis = function _jQueryHandleThis(me, option, argument) {
                var data = $(me).data(DateTimePicker.DATA_KEY);
                if ((typeof option === 'undefined' ? 'undefined' : _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 {
                        return data[option](argument);
                    }
                }
            };
    
            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 $target = getSelectorFromElement($(this));
            if ($target.length === 0) {
                return;
            }
            TempusDominusBootstrap4._jQueryInterface.call($target, 'toggle');
        }).on(DateTimePicker.Event.CHANGE, '.' + DateTimePicker.ClassName.INPUT, function (event) {
            var $target = getSelectorFromElement($(this));
            if ($target.length === 0) {
                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);
    
    }();
    
    /*!
    * jquery.inputmask.bundle.js
    * https://github.com/RobinHerbots/Inputmask
    * Copyright (c) 2010 - 2019 Robin Herbots
    * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
    * Version: 4.0.9
    */
    
    (function(modules) {
        var installedModules = {};
        function __webpack_require__(moduleId) {
            if (installedModules[moduleId]) {
                return installedModules[moduleId].exports;
            }
            var module = installedModules[moduleId] = {
                i: moduleId,
                l: false,
                exports: {}
            };
            modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
            module.l = true;
            return module.exports;
        }
        __webpack_require__.m = modules;
        __webpack_require__.c = installedModules;
        __webpack_require__.d = function(exports, name, getter) {
            if (!__webpack_require__.o(exports, name)) {
                Object.defineProperty(exports, name, {
                    enumerable: true,
                    get: getter
                });
            }
        };
        __webpack_require__.r = function(exports) {
            if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
                Object.defineProperty(exports, Symbol.toStringTag, {
                    value: "Module"
                });
            }
            Object.defineProperty(exports, "__esModule", {
                value: true
            });
        };
        __webpack_require__.t = function(value, mode) {
            if (mode & 1) value = __webpack_require__(value);
            if (mode & 8) return value;
            if (mode & 4 && typeof value === "object" && value && value.__esModule) return value;
            var ns = Object.create(null);
            __webpack_require__.r(ns);
            Object.defineProperty(ns, "default", {
                enumerable: true,
                value: value
            });
            if (mode & 2 && typeof value != "string") 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;
            };
            __webpack_require__.d(getter, "a", getter);
            return getter;
        };
        __webpack_require__.o = function(object, property) {
            return Object.prototype.hasOwnProperty.call(object, property);
        };
        __webpack_require__.p = "";
        return __webpack_require__(__webpack_require__.s = 0);
    })([ function(module, exports, __webpack_require__) {
        "use strict";
        __webpack_require__(1);
        __webpack_require__(6);
        __webpack_require__(7);
        var _inputmask = __webpack_require__(2);
        var _inputmask2 = _interopRequireDefault(_inputmask);
        var _inputmask3 = __webpack_require__(3);
        var _inputmask4 = _interopRequireDefault(_inputmask3);
        var _jquery = __webpack_require__(4);
        var _jquery2 = _interopRequireDefault(_jquery);
        function _interopRequireDefault(obj) {
            return obj && obj.__esModule ? obj : {
                default: obj
            };
        }
        if (_inputmask4.default === _jquery2.default) {
            __webpack_require__(8);
        }
        window.Inputmask = _inputmask2.default;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        (function(factory) {
            if (true) {
                !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 
                __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
                __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
            } else {}
        })(function(Inputmask) {
            Inputmask.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"
                }
            });
            Inputmask.extendAliases({
                cssunit: {
                    regex: "[+-]?[0-9]+\\.?([0-9]+)?(px|em|rem|ex|%|in|cm|mm|pt|pc)"
                },
                url: {
                    regex: "(https?|ftp)//.*",
                    autoUnmask: false
                },
                ip: {
                    mask: "i[i[i]].i[i[i]].i[i[i]].i[i[i]]",
                    definitions: {
                        i: {
                            validator: function validator(chrs, maskset, pos, strict, opts) {
                                if (pos - 1 > -1 && maskset.buffer[pos - 1] !== ".") {
                                    chrs = maskset.buffer[pos - 1] + chrs;
                                    if (pos - 2 > -1 && maskset.buffer[pos - 2] !== ".") {
                                        chrs = maskset.buffer[pos - 2] + chrs;
                                    } else chrs = "0" + chrs;
                                } else chrs = "00" + chrs;
                                return new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]").test(chrs);
                            }
                        }
                    },
                    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: false,
                    casing: "lower",
                    onBeforePaste: function onBeforePaste(pastedValue, opts) {
                        pastedValue = pastedValue.toLowerCase();
                        return 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: true,
                    autoUnmask: true
                }
            });
            return Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        (function(factory) {
            if (true) {
                !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(3), __webpack_require__(5) ], 
                __WEBPACK_AMD_DEFINE_FACTORY__ = factory, __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
                __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
            } else {}
        })(function($, window, undefined) {
            var document = window.document, ua = navigator.userAgent, ie = ua.indexOf("MSIE ") > 0 || ua.indexOf("Trident/") > 0, mobile = isInputEventSupported("touchstart"), iemobile = /iemobile/i.test(ua), iphone = /iphone/i.test(ua) && !iemobile;
            function Inputmask(alias, options, internal) {
                if (!(this instanceof Inputmask)) {
                    return new Inputmask(alias, options, internal);
                }
                this.el = undefined;
                this.events = {};
                this.maskset = undefined;
                this.refreshValue = false;
                if (internal !== true) {
                    if ($.isPlainObject(alias)) {
                        options = alias;
                    } else {
                        options = options || {};
                        if (alias) options.alias = alias;
                    }
                    this.opts = $.extend(true, {}, this.defaults, options);
                    this.noMasksCache = options && options.definitions !== undefined;
                    this.userOptions = options || {};
                    this.isRTL = this.opts.numericInput;
                    resolveAlias(this.opts.alias, options, this.opts);
                }
            }
            Inputmask.prototype = {
                dataAttribute: "data-inputmask",
                defaults: {
                    placeholder: "_",
                    optionalmarker: [ "[", "]" ],
                    quantifiermarker: [ "{", "}" ],
                    groupmarker: [ "(", ")" ],
                    alternatormarker: "|",
                    escapeChar: "\\",
                    mask: null,
                    regex: null,
                    oncomplete: $.noop,
                    onincomplete: $.noop,
                    oncleared: $.noop,
                    repeat: 0,
                    greedy: false,
                    autoUnmask: false,
                    removeMaskOnSubmit: false,
                    clearMaskOnLostFocus: true,
                    insertMode: true,
                    clearIncomplete: false,
                    alias: null,
                    onKeyDown: $.noop,
                    onBeforeMask: null,
                    onBeforePaste: function onBeforePaste(pastedValue, opts) {
                        return $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(this, pastedValue, opts) : pastedValue;
                    },
                    onBeforeWrite: null,
                    onUnMask: null,
                    showMaskOnFocus: true,
                    showMaskOnHover: true,
                    onKeyValidation: $.noop,
                    skipOptionalPartCharacter: " ",
                    numericInput: false,
                    rightAlign: false,
                    undoOnEscape: true,
                    radixPoint: "",
                    _radixDance: false,
                    groupSeparator: "",
                    keepStatic: null,
                    positionCaretOnTab: true,
                    tabThrough: false,
                    supportsInputType: [ "text", "tel", "url", "password", "search" ],
                    ignorables: [ 8, 9, 13, 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: undefined,
                    jitMasking: false,
                    nullable: true,
                    inputEventOnly: false,
                    noValuePatching: false,
                    positionCaretOnClick: "lvp",
                    casing: null,
                    inputmode: "verbatim",
                    colorMask: false,
                    disablePredictiveText: false,
                    importDataAttributes: true,
                    shiftPositions: true
                },
                definitions: {
                    9: {
                        validator: "[0-9\uff11-\uff19]",
                        definitionSymbol: "*"
                    },
                    a: {
                        validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
                        definitionSymbol: "*"
                    },
                    "*": {
                        validator: "[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]"
                    }
                },
                aliases: {},
                masksCache: {},
                mask: function mask(elems) {
                    var that = this;
                    function importAttributeOptions(npt, opts, userOptions, dataAttribute) {
                        if (opts.importDataAttributes === true) {
                            var attrOptions = npt.getAttribute(dataAttribute), option, dataoptions, optionData, p;
                            var importOption = function importOption(option, optionData) {
                                optionData = optionData !== undefined ? optionData : npt.getAttribute(dataAttribute + "-" + option);
                                if (optionData !== null) {
                                    if (typeof optionData === "string") {
                                        if (option.indexOf("on") === 0) optionData = window[optionData]; else if (optionData === "false") optionData = false; else if (optionData === "true") optionData = true;
                                    }
                                    userOptions[option] = optionData;
                                }
                            };
                            if (attrOptions && attrOptions !== "") {
                                attrOptions = attrOptions.replace(/'/g, '"');
                                dataoptions = JSON.parse("{" + attrOptions + "}");
                            }
                            if (dataoptions) {
                                optionData = undefined;
                                for (p in dataoptions) {
                                    if (p.toLowerCase() === "alias") {
                                        optionData = dataoptions[p];
                                        break;
                                    }
                                }
                            }
                            importOption("alias", optionData);
                            if (userOptions.alias) {
                                resolveAlias(userOptions.alias, userOptions, opts);
                            }
                            for (option in opts) {
                                if (dataoptions) {
                                    optionData = undefined;
                                    for (p in dataoptions) {
                                        if (p.toLowerCase() === option.toLowerCase()) {
                                            optionData = dataoptions[p];
                                            break;
                                        }
                                    }
                                }
                                importOption(option, optionData);
                            }
                        }
                        $.extend(true, opts, userOptions);
                        if (npt.dir === "rtl" || opts.rightAlign) {
                            npt.style.textAlign = "right";
                        }
                        if (npt.dir === "rtl" || opts.numericInput) {
                            npt.dir = "ltr";
                            npt.removeAttribute("dir");
                            opts.isRTL = true;
                        }
                        return Object.keys(userOptions).length;
                    }
                    if (typeof elems === "string") {
                        elems = document.getElementById(elems) || document.querySelectorAll(elems);
                    }
                    elems = elems.nodeName ? [ elems ] : elems;
                    $.each(elems, function(ndx, el) {
                        var scopedOpts = $.extend(true, {}, that.opts);
                        if (importAttributeOptions(el, scopedOpts, $.extend(true, {}, that.userOptions), that.dataAttribute)) {
                            var maskset = generateMaskSet(scopedOpts, that.noMasksCache);
                            if (maskset !== undefined) {
                                if (el.inputmask !== undefined) {
                                    el.inputmask.opts.autoUnmask = true;
                                    el.inputmask.remove();
                                }
                                el.inputmask = new Inputmask(undefined, undefined, true);
                                el.inputmask.opts = scopedOpts;
                                el.inputmask.noMasksCache = that.noMasksCache;
                                el.inputmask.userOptions = $.extend(true, {}, that.userOptions);
                                el.inputmask.isRTL = scopedOpts.isRTL || scopedOpts.numericInput;
                                el.inputmask.el = el;
                                el.inputmask.maskset = maskset;
                                $.data(el, "_inputmask_opts", scopedOpts);
                                maskScope.call(el.inputmask, {
                                    action: "mask"
                                });
                            }
                        }
                    });
                    return elems && elems[0] ? elems[0].inputmask || this : this;
                },
                option: function option(options, noremask) {
                    if (typeof options === "string") {
                        return this.opts[options];
                    } else if ((typeof options === "undefined" ? "undefined" : _typeof(options)) === "object") {
                        $.extend(this.userOptions, options);
                        if (this.el && noremask !== true) {
                            this.mask(this.el);
                        }
                        return this;
                    }
                },
                unmaskedvalue: function unmaskedvalue(value) {
                    this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
                    return maskScope.call(this, {
                        action: "unmaskedvalue",
                        value: value
                    });
                },
                remove: function remove() {
                    return maskScope.call(this, {
                        action: "remove"
                    });
                },
                getemptymask: function getemptymask() {
                    this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
                    return maskScope.call(this, {
                        action: "getemptymask"
                    });
                },
                hasMaskedValue: function hasMaskedValue() {
                    return !this.opts.autoUnmask;
                },
                isComplete: function isComplete() {
                    this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
                    return maskScope.call(this, {
                        action: "isComplete"
                    });
                },
                getmetadata: function getmetadata() {
                    this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
                    return maskScope.call(this, {
                        action: "getmetadata"
                    });
                },
                isValid: function isValid(value) {
                    this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
                    return maskScope.call(this, {
                        action: "isValid",
                        value: value
                    });
                },
                format: function format(value, metadata) {
                    this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
                    return maskScope.call(this, {
                        action: "format",
                        value: value,
                        metadata: metadata
                    });
                },
                setValue: function setValue(value) {
                    if (this.el) {
                        $(this.el).trigger("setvalue", [ value ]);
                    }
                },
                analyseMask: 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 = false, currentToken = new MaskToken(), match, m, openenings = [], maskTokens = [], openingToken, currentOpeningToken, alternator, lastMatch, groupToken;
                    function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) {
                        this.matches = [];
                        this.openGroup = isGroup || false;
                        this.alternatorGroup = false;
                        this.isGroup = isGroup || false;
                        this.isOptional = isOptional || false;
                        this.isQuantifier = isQuantifier || false;
                        this.isAlternator = isAlternator || false;
                        this.quantifier = {
                            min: 1,
                            max: 1
                        };
                    }
                    function insertTestDefinition(mtoken, element, position) {
                        position = position !== undefined ? position : mtoken.matches.length;
                        var prevMatch = mtoken.matches[position - 1];
                        if (regexMask) {
                            if (element.indexOf("[") === 0 || escaped && /\\d|\\s|\\w]/i.test(element) || element === ".") {
                                mtoken.matches.splice(position++, 0, {
                                    fn: new RegExp(element, opts.casing ? "i" : ""),
                                    optionality: false,
                                    newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== element,
                                    casing: null,
                                    def: element,
                                    placeholder: undefined,
                                    nativeDef: element
                                });
                            } else {
                                if (escaped) element = element[element.length - 1];
                                $.each(element.split(""), function(ndx, lmnt) {
                                    prevMatch = mtoken.matches[position - 1];
                                    mtoken.matches.splice(position++, 0, {
                                        fn: null,
                                        optionality: false,
                                        newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== lmnt && prevMatch.fn !== null,
                                        casing: null,
                                        def: opts.staticDefinitionSymbol || lmnt,
                                        placeholder: opts.staticDefinitionSymbol !== undefined ? lmnt : undefined,
                                        nativeDef: (escaped ? "'" : "") + lmnt
                                    });
                                });
                            }
                            escaped = false;
                        } else {
                            var maskdef = (opts.definitions ? opts.definitions[element] : undefined) || Inputmask.prototype.definitions[element];
                            if (maskdef && !escaped) {
                                mtoken.matches.splice(position++, 0, {
                                    fn: maskdef.validator ? typeof maskdef.validator == "string" ? new RegExp(maskdef.validator, opts.casing ? "i" : "") : new function() {
                                        this.test = maskdef.validator;
                                    }() : new RegExp("."),
                                    optionality: false,
                                    newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== (maskdef.definitionSymbol || element),
                                    casing: maskdef.casing,
                                    def: maskdef.definitionSymbol || element,
                                    placeholder: maskdef.placeholder,
                                    nativeDef: element
                                });
                            } else {
                                mtoken.matches.splice(position++, 0, {
                                    fn: null,
                                    optionality: false,
                                    newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== element && prevMatch.fn !== null,
                                    casing: null,
                                    def: opts.staticDefinitionSymbol || element,
                                    placeholder: opts.staticDefinitionSymbol !== undefined ? element : undefined,
                                    nativeDef: (escaped ? "'" : "") + element
                                });
                                escaped = false;
                            }
                        }
                    }
                    function verifyGroupMarker(maskToken) {
                        if (maskToken && maskToken.matches) {
                            $.each(maskToken.matches, function(ndx, token) {
                                var nextToken = maskToken.matches[ndx + 1];
                                if ((nextToken === undefined || nextToken.matches === undefined || nextToken.isQuantifier === false) && token && token.isGroup) {
                                    token.isGroup = false;
                                    if (!regexMask) {
                                        insertTestDefinition(token, opts.groupmarker[0], 0);
                                        if (token.openGroup !== true) {
                                            insertTestDefinition(token, opts.groupmarker[1]);
                                        }
                                    }
                                }
                                verifyGroupMarker(token);
                            });
                        }
                    }
                    function defaultCase() {
                        if (openenings.length > 0) {
                            currentOpeningToken = openenings[openenings.length - 1];
                            insertTestDefinition(currentOpeningToken, m);
                            if (currentOpeningToken.isAlternator) {
                                alternator = openenings.pop();
                                for (var mndx = 0; mndx < alternator.matches.length; mndx++) {
                                    if (alternator.matches[mndx].isGroup) alternator.matches[mndx].isGroup = false;
                                }
                                if (openenings.length > 0) {
                                    currentOpeningToken = openenings[openenings.length - 1];
                                    currentOpeningToken.matches.push(alternator);
                                } else {
                                    currentToken.matches.push(alternator);
                                }
                            }
                        } else {
                            insertTestDefinition(currentToken, m);
                        }
                    }
                    function reverseTokens(maskToken) {
                        function reverseStatic(st) {
                            if (st === opts.optionalmarker[0]) st = opts.optionalmarker[1]; else if (st === opts.optionalmarker[1]) st = opts.optionalmarker[0]; else if (st === opts.groupmarker[0]) st = opts.groupmarker[1]; else if (st === opts.groupmarker[1]) st = opts.groupmarker[0];
                            return st;
                        }
                        maskToken.matches = maskToken.matches.reverse();
                        for (var match in maskToken.matches) {
                            if (maskToken.matches.hasOwnProperty(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);
                                }
                                if (maskToken.matches[match].matches !== undefined) {
                                    maskToken.matches[match] = reverseTokens(maskToken.matches[match]);
                                } else {
                                    maskToken.matches[match] = reverseStatic(maskToken.matches[match]);
                                }
                            }
                        }
                        return maskToken;
                    }
                    function groupify(matches) {
                        var groupToken = new MaskToken(true);
                        groupToken.openGroup = false;
                        groupToken.matches = matches;
                        return groupToken;
                    }
                    if (regexMask) {
                        opts.optionalmarker[0] = undefined;
                        opts.optionalmarker[1] = undefined;
                    }
                    while (match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask)) {
                        m = match[0];
                        if (regexMask) {
                            switch (m.charAt(0)) {
                              case "?":
                                m = "{0,1}";
                                break;
    
                              case "+":
                              case "*":
                                m = "{" + m + "}";
                                break;
                            }
                        }
                        if (escaped) {
                            defaultCase();
                            continue;
                        }
                        switch (m.charAt(0)) {
                          case "(?=":
                            break;
    
                          case "(?!":
                            break;
    
                          case "(?<=":
                            break;
    
                          case "(?<!":
                            break;
    
                          case opts.escapeChar:
                            escaped = true;
                            if (regexMask) {
                                defaultCase();
                            }
                            break;
    
                          case opts.optionalmarker[1]:
                          case opts.groupmarker[1]:
                            openingToken = openenings.pop();
                            openingToken.openGroup = false;
                            if (openingToken !== undefined) {
                                if (openenings.length > 0) {
                                    currentOpeningToken = openenings[openenings.length - 1];
                                    currentOpeningToken.matches.push(openingToken);
                                    if (currentOpeningToken.isAlternator) {
                                        alternator = openenings.pop();
                                        for (var mndx = 0; mndx < alternator.matches.length; mndx++) {
                                            alternator.matches[mndx].isGroup = false;
                                            alternator.matches[mndx].alternatorGroup = false;
                                        }
                                        if (openenings.length > 0) {
                                            currentOpeningToken = openenings[openenings.length - 1];
                                            currentOpeningToken.matches.push(alternator);
                                        } else {
                                            currentToken.matches.push(alternator);
                                        }
                                    }
                                } else {
                                    currentToken.matches.push(openingToken);
                                }
                            } else defaultCase();
                            break;
    
                          case opts.optionalmarker[0]:
                            openenings.push(new MaskToken(false, true));
                            break;
    
                          case opts.groupmarker[0]:
                            openenings.push(new MaskToken(true));
                            break;
    
                          case opts.quantifiermarker[0]:
                            var quantifier = new MaskToken(false, false, true);
                            m = m.replace(/[{}]/g, "");
                            var mqj = m.split("|"), mq = mqj[0].split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = mq.length === 1 ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
                            if (mq0 === "*" || mq0 === "+") {
                                mq0 = mq1 === "*" ? 0 : 1;
                            }
                            quantifier.quantifier = {
                                min: mq0,
                                max: mq1,
                                jit: mqj[1]
                            };
                            var matches = openenings.length > 0 ? openenings[openenings.length - 1].matches : currentToken.matches;
                            match = matches.pop();
                            if (match.isAlternator) {
                                matches.push(match);
                                matches = match.matches;
                                var groupToken = new MaskToken(true);
                                var tmpMatch = matches.pop();
                                matches.push(groupToken);
                                matches = groupToken.matches;
                                match = tmpMatch;
                            }
                            if (!match.isGroup) {
                                match = groupify([ match ]);
                            }
                            matches.push(match);
                            matches.push(quantifier);
                            break;
    
                          case opts.alternatormarker:
                            var groupQuantifier = function groupQuantifier(matches) {
                                var lastMatch = matches.pop();
                                if (lastMatch.isQuantifier) {
                                    lastMatch = groupify([ matches.pop(), lastMatch ]);
                                }
                                return lastMatch;
                            };
                            if (openenings.length > 0) {
                                currentOpeningToken = openenings[openenings.length - 1];
                                var subToken = currentOpeningToken.matches[currentOpeningToken.matches.length - 1];
                                if (currentOpeningToken.openGroup && (subToken.matches === undefined || subToken.isGroup === false && subToken.isAlternator === false)) {
                                    lastMatch = openenings.pop();
                                } else {
                                    lastMatch = groupQuantifier(currentOpeningToken.matches);
                                }
                            } else {
                                lastMatch = groupQuantifier(currentToken.matches);
                            }
                            if (lastMatch.isAlternator) {
                                openenings.push(lastMatch);
                            } else {
                                if (lastMatch.alternatorGroup) {
                                    alternator = openenings.pop();
                                    lastMatch.alternatorGroup = false;
                                } else {
                                    alternator = new MaskToken(false, false, false, true);
                                }
                                alternator.matches.push(lastMatch);
                                openenings.push(alternator);
                                if (lastMatch.openGroup) {
                                    lastMatch.openGroup = false;
                                    var alternatorGroup = new MaskToken(true);
                                    alternatorGroup.alternatorGroup = true;
                                    openenings.push(alternatorGroup);
                                }
                            }
                            break;
    
                          default:
                            defaultCase();
                        }
                    }
                    while (openenings.length > 0) {
                        openingToken = openenings.pop();
                        currentToken.matches.push(openingToken);
                    }
                    if (currentToken.matches.length > 0) {
                        verifyGroupMarker(currentToken);
                        maskTokens.push(currentToken);
                    }
                    if (opts.numericInput || opts.isRTL) {
                        reverseTokens(maskTokens[0]);
                    }
                    return maskTokens;
                },
                positionColorMask: function positionColorMask(input, template) {
                    input.style.left = template.offsetLeft + "px";
                }
            };
            Inputmask.extendDefaults = function(options) {
                $.extend(true, Inputmask.prototype.defaults, options);
            };
            Inputmask.extendDefinitions = function(definition) {
                $.extend(true, Inputmask.prototype.definitions, definition);
            };
            Inputmask.extendAliases = function(alias) {
                $.extend(true, 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) {
                if (typeof elems === "string") {
                    elems = document.getElementById(elems) || document.querySelectorAll(elems);
                }
                elems = elems.nodeName ? [ elems ] : elems;
                $.each(elems, function(ndx, el) {
                    if (el.inputmask) el.inputmask.remove();
                });
            };
            Inputmask.setValue = function(elems, value) {
                if (typeof elems === "string") {
                    elems = document.getElementById(elems) || document.querySelectorAll(elems);
                }
                elems = elems.nodeName ? [ elems ] : elems;
                $.each(elems, function(ndx, el) {
                    if (el.inputmask) el.inputmask.setValue(value); else $(el).trigger("setvalue", [ value ]);
                });
            };
            Inputmask.escapeRegex = function(str) {
                var specials = [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^" ];
                return str.replace(new RegExp("(\\" + specials.join("|\\") + ")", "gim"), "\\$1");
            };
            Inputmask.keyCode = {
                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
            };
            Inputmask.dependencyLib = $;
            function resolveAlias(aliasStr, options, opts) {
                var aliasDefinition = Inputmask.prototype.aliases[aliasStr];
                if (aliasDefinition) {
                    if (aliasDefinition.alias) resolveAlias(aliasDefinition.alias, undefined, opts);
                    $.extend(true, opts, aliasDefinition);
                    $.extend(true, opts, options);
                    return true;
                } else if (opts.mask === null) {
                    opts.mask = aliasStr;
                }
                return false;
            }
            function generateMaskSet(opts, nocache) {
                function generateMask(mask, metadata, opts) {
                    var regexMask = false;
                    if (mask === null || mask === "") {
                        regexMask = opts.regex !== null;
                        if (regexMask) {
                            mask = opts.regex;
                            mask = mask.replace(/^(\^)(.*)(\$)$/, "$2");
                        } else {
                            regexMask = true;
                            mask = ".*";
                        }
                    }
                    if (mask.length === 1 && opts.greedy === false && opts.repeat !== 0) {
                        opts.placeholder = "";
                    }
                    if (opts.repeat > 0 || 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];
                    }
                    var masksetDefinition, maskdefKey = regexMask ? "regex_" + opts.regex : opts.numericInput ? mask.split("").reverse().join("") : mask;
                    if (Inputmask.prototype.masksCache[maskdefKey] === undefined || nocache === true) {
                        masksetDefinition = {
                            mask: mask,
                            maskToken: Inputmask.prototype.analyseMask(mask, regexMask, opts),
                            validPositions: {},
                            _buffer: undefined,
                            buffer: undefined,
                            tests: {},
                            excludes: {},
                            metadata: metadata,
                            maskLength: undefined,
                            jitOffset: {}
                        };
                        if (nocache !== true) {
                            Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition;
                            masksetDefinition = $.extend(true, {}, Inputmask.prototype.masksCache[maskdefKey]);
                        }
                    } else masksetDefinition = $.extend(true, {}, Inputmask.prototype.masksCache[maskdefKey]);
                    return masksetDefinition;
                }
                var ms;
                if ($.isFunction(opts.mask)) {
                    opts.mask = opts.mask(opts);
                }
                if ($.isArray(opts.mask)) {
                    if (opts.mask.length > 1) {
                        if (opts.keepStatic === null) {
                            opts.keepStatic = "auto";
                            for (var i = 0; i < opts.mask.length; i++) {
                                if (opts.mask[i].charAt(0) !== opts.mask[0].charAt(0)) {
                                    opts.keepStatic = true;
                                    break;
                                }
                            }
                        }
                        var altMask = opts.groupmarker[0];
                        $.each(opts.isRTL ? opts.mask.reverse() : opts.mask, function(ndx, msk) {
                            if (altMask.length > 1) {
                                altMask += opts.groupmarker[1] + opts.alternatormarker + opts.groupmarker[0];
                            }
                            if (msk.mask !== undefined && !$.isFunction(msk.mask)) {
                                altMask += msk.mask;
                            } else {
                                altMask += msk;
                            }
                        });
                        altMask += opts.groupmarker[1];
                        return generateMask(altMask, opts.mask, opts);
                    } else opts.mask = opts.mask.pop();
                }
                if (opts.mask && opts.mask.mask !== undefined && !$.isFunction(opts.mask.mask)) {
                    ms = generateMask(opts.mask.mask, opts.mask, opts);
                } else {
                    ms = generateMask(opts.mask, opts.mask, opts);
                }
                return ms;
            }
            function isInputEventSupported(eventName) {
                var el = document.createElement("input"), evName = "on" + eventName, isSupported = evName in el;
                if (!isSupported) {
                    el.setAttribute(evName, "return;");
                    isSupported = typeof el[evName] === "function";
                }
                el = null;
                return isSupported;
            }
            function maskScope(actionObj, maskset, opts) {
                maskset = maskset || this.maskset;
                opts = opts || this.opts;
                var inputmask = this, el = this.el, isRTL = this.isRTL, undoValue, $el, skipKeyPressEvent = false, skipInputEvent = false, ignorable = false, maxLength, mouseEnter = false, colorMask, originalPlaceholder;
                var getMaskTemplate = function getMaskTemplate(baseOnInput, minimalPos, includeMode, noJit, clearOptionalTail) {
                    var greedy = opts.greedy;
                    if (clearOptionalTail) opts.greedy = false;
                    minimalPos = minimalPos || 0;
                    var maskTemplate = [], ndxIntlzr, pos = 0, test, testPos, lvp = getLastValidPosition();
                    do {
                        if (baseOnInput === true && getMaskSet().validPositions[pos]) {
                            testPos = clearOptionalTail && getMaskSet().validPositions[pos].match.optionality === true && getMaskSet().validPositions[pos + 1] === undefined && (getMaskSet().validPositions[pos].generatedInput === true || getMaskSet().validPositions[pos].input == opts.skipOptionalPartCharacter && pos > 0) ? determineTestTemplate(pos, getTests(pos, ndxIntlzr, pos - 1)) : getMaskSet().validPositions[pos];
                            test = testPos.match;
                            ndxIntlzr = testPos.locator.slice();
                            maskTemplate.push(includeMode === true ? testPos.input : includeMode === false ? test.nativeDef : getPlaceholder(pos, test));
                        } else {
                            testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
                            test = testPos.match;
                            ndxIntlzr = testPos.locator.slice();
                            var jitMasking = noJit === true ? false : opts.jitMasking !== false ? opts.jitMasking : test.jit;
                            if (jitMasking === false || jitMasking === undefined || typeof jitMasking === "number" && isFinite(jitMasking) && jitMasking > pos) {
                                maskTemplate.push(includeMode === false ? test.nativeDef : getPlaceholder(pos, test));
                            }
                        }
                        if (opts.keepStatic === "auto") {
                            if (test.newBlockMarker && test.fn !== null) {
                                opts.keepStatic = pos - 1;
                            }
                        }
                        pos++;
                    } while ((maxLength === undefined || pos < maxLength) && (test.fn !== null || test.def !== "") || minimalPos > pos);
                    if (maskTemplate[maskTemplate.length - 1] === "") {
                        maskTemplate.pop();
                    }
                    if (includeMode !== false || getMaskSet().maskLength === undefined) getMaskSet().maskLength = pos - 1;
                    opts.greedy = greedy;
                    return maskTemplate;
                };
                function getMaskSet() {
                    return maskset;
                }
                function resetMaskSet(soft) {
                    var maskset = getMaskSet();
                    maskset.buffer = undefined;
                    if (soft !== true) {
                        maskset.validPositions = {};
                        maskset.p = 0;
                    }
                }
                function getLastValidPosition(closestTo, strict, validPositions) {
                    var before = -1, after = -1, valids = validPositions || getMaskSet().validPositions;
                    if (closestTo === undefined) closestTo = -1;
                    for (var posNdx in valids) {
                        var psNdx = parseInt(posNdx);
                        if (valids[psNdx] && (strict || valids[psNdx].generatedInput !== true)) {
                            if (psNdx <= closestTo) before = psNdx;
                            if (psNdx >= closestTo) after = psNdx;
                        }
                    }
                    return before === -1 || before == closestTo ? after : after == -1 ? before : closestTo - before < after - closestTo ? before : after;
                }
                function getDecisionTaker(tst) {
                    var decisionTaker = tst.locator[tst.alternation];
                    if (typeof decisionTaker == "string" && decisionTaker.length > 0) {
                        decisionTaker = decisionTaker.split(",")[0];
                    }
                    return decisionTaker !== undefined ? decisionTaker.toString() : "";
                }
                function getLocator(tst, align) {
                    var locator = (tst.alternation != undefined ? tst.mloc[getDecisionTaker(tst)] : tst.locator).join("");
                    if (locator !== "") while (locator.length < align) {
                        locator += "0";
                    }
                    return locator;
                }
                function determineTestTemplate(pos, tests) {
                    pos = pos > 0 ? pos - 1 : 0;
                    var altTest = getTest(pos), targetLocator = getLocator(altTest), tstLocator, closest, bestMatch;
                    for (var ndx = 0; ndx < tests.length; ndx++) {
                        var tst = tests[ndx];
                        tstLocator = getLocator(tst, targetLocator.length);
                        var distance = Math.abs(tstLocator - targetLocator);
                        if (closest === undefined || tstLocator !== "" && distance < closest || bestMatch && !opts.greedy && bestMatch.match.optionality && bestMatch.match.newBlockMarker === "master" && (!tst.match.optionality || !tst.match.newBlockMarker) || bestMatch && bestMatch.match.optionalQuantifier && !tst.match.optionalQuantifier) {
                            closest = distance;
                            bestMatch = tst;
                        }
                    }
                    return bestMatch;
                }
                function getTestTemplate(pos, ndxIntlzr, tstPs) {
                    return getMaskSet().validPositions[pos] || determineTestTemplate(pos, getTests(pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs));
                }
                function getTest(pos, tests) {
                    if (getMaskSet().validPositions[pos]) {
                        return getMaskSet().validPositions[pos];
                    }
                    return (tests || getTests(pos))[0];
                }
                function positionCanMatchDefinition(pos, def) {
                    var valid = false, tests = getTests(pos);
                    for (var tndx = 0; tndx < tests.length; tndx++) {
                        if (tests[tndx].match && tests[tndx].match.def === def) {
                            valid = true;
                            break;
                        }
                    }
                    return valid;
                }
                function getTests(pos, ndxIntlzr, tstPs) {
                    var maskTokens = getMaskSet().maskToken, testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [ 0 ], matches = [], insertStop = false, latestMatch, cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : "";
                    function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) {
                        function handleMatch(match, loopNdx, quantifierRecurse) {
                            function isFirstMatch(latestMatch, tokenGroup) {
                                var firstMatch = $.inArray(latestMatch, tokenGroup.matches) === 0;
                                if (!firstMatch) {
                                    $.each(tokenGroup.matches, function(ndx, match) {
                                        if (match.isQuantifier === true) firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]); else if (match.hasOwnProperty("matches")) firstMatch = isFirstMatch(latestMatch, match);
                                        if (firstMatch) return false;
                                    });
                                }
                                return firstMatch;
                            }
                            function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {
                                var bestMatch, indexPos;
                                if (getMaskSet().tests[pos] || getMaskSet().validPositions[pos]) {
                                    $.each(getMaskSet().tests[pos] || [ getMaskSet().validPositions[pos] ], function(ndx, lmnt) {
                                        if (lmnt.mloc[alternateNdx]) {
                                            bestMatch = lmnt;
                                            return false;
                                        }
                                        var alternation = targetAlternation !== undefined ? targetAlternation : lmnt.alternation, ndxPos = lmnt.locator[alternation] !== undefined ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1;
                                        if ((indexPos === undefined || ndxPos < indexPos) && ndxPos !== -1) {
                                            bestMatch = lmnt;
                                            indexPos = ndxPos;
                                        }
                                    });
                                }
                                if (bestMatch) {
                                    var bestMatchAltIndex = bestMatch.locator[bestMatch.alternation];
                                    var locator = bestMatch.mloc[alternateNdx] || bestMatch.mloc[bestMatchAltIndex] || bestMatch.locator;
                                    return locator.slice((targetAlternation !== undefined ? targetAlternation : bestMatch.alternation) + 1);
                                } else {
                                    return targetAlternation !== undefined ? resolveNdxInitializer(pos, alternateNdx) : undefined;
                                }
                            }
                            function isSubsetOf(source, target) {
                                function expand(pattern) {
                                    var expanded = [], start, end;
                                    for (var i = 0, l = pattern.length; i < l; i++) {
                                        if (pattern.charAt(i) === "-") {
                                            end = pattern.charCodeAt(i + 1);
                                            while (++start < end) {
                                                expanded.push(String.fromCharCode(start));
                                            }
                                        } else {
                                            start = pattern.charCodeAt(i);
                                            expanded.push(pattern.charAt(i));
                                        }
                                    }
                                    return expanded.join("");
                                }
                                if (opts.regex && source.match.fn !== null && target.match.fn !== null) {
                                    return expand(target.match.def.replace(/[\[\]]/g, "")).indexOf(expand(source.match.def.replace(/[\[\]]/g, ""))) !== -1;
                                }
                                return source.match.def === target.match.nativeDef;
                            }
                            function staticCanMatchDefinition(source, target) {
                                var sloc = source.locator.slice(source.alternation).join(""), tloc = target.locator.slice(target.alternation).join(""), canMatch = sloc == tloc;
                                canMatch = canMatch && source.match.fn === null && target.match.fn !== null ? target.match.fn.test(source.match.def, getMaskSet(), pos, false, opts, false) : false;
                                return canMatch;
                            }
                            function setMergeLocators(targetMatch, altMatch) {
                                if (altMatch === undefined || targetMatch.alternation === altMatch.alternation && targetMatch.locator[targetMatch.alternation].toString().indexOf(altMatch.locator[altMatch.alternation]) === -1) {
                                    targetMatch.mloc = targetMatch.mloc || {};
                                    var locNdx = targetMatch.locator[targetMatch.alternation];
                                    if (locNdx === undefined) targetMatch.alternation = undefined; else {
                                        if (typeof locNdx === "string") locNdx = locNdx.split(",")[0];
                                        if (targetMatch.mloc[locNdx] === undefined) targetMatch.mloc[locNdx] = targetMatch.locator.slice();
                                        if (altMatch !== undefined) {
                                            for (var ndx in altMatch.mloc) {
                                                if (typeof ndx === "string") ndx = ndx.split(",")[0];
                                                if (targetMatch.mloc[ndx] === undefined) targetMatch.mloc[ndx] = altMatch.mloc[ndx];
                                            }
                                            targetMatch.locator[targetMatch.alternation] = Object.keys(targetMatch.mloc).join(",");
                                        }
                                        return true;
                                    }
                                }
                                return false;
                            }
                            if (testPos > 500 && quantifierRecurse !== undefined) {
                                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. " + getMaskSet().mask;
                            }
                            if (testPos === pos && match.matches === undefined) {
                                matches.push({
                                    match: match,
                                    locator: loopNdx.reverse(),
                                    cd: cacheDependency,
                                    mloc: {}
                                });
                                return true;
                            } else if (match.matches !== undefined) {
                                if (match.isGroup && quantifierRecurse !== match) {
                                    match = handleMatch(maskToken.matches[$.inArray(match, maskToken.matches) + 1], loopNdx, quantifierRecurse);
                                    if (match) return true;
                                } else if (match.isOptional) {
                                    var optionalToken = match;
                                    match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
                                    if (match) {
                                        $.each(matches, function(ndx, mtch) {
                                            mtch.match.optionality = true;
                                        });
                                        latestMatch = matches[matches.length - 1].match;
                                        if (quantifierRecurse === undefined && isFirstMatch(latestMatch, optionalToken)) {
                                            insertStop = true;
                                            testPos = pos;
                                        } else return true;
                                    }
                                } else if (match.isAlternator) {
                                    var alternateToken = match, malternateMatches = [], maltMatches, currentMatches = matches.slice(), loopNdxCnt = loopNdx.length;
                                    var altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
                                    if (altIndex === -1 || typeof altIndex === "string") {
                                        var currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr = [], amndx;
                                        if (typeof altIndex == "string") {
                                            altIndexArr = altIndex.split(",");
                                        } else {
                                            for (amndx = 0; amndx < alternateToken.matches.length; amndx++) {
                                                altIndexArr.push(amndx.toString());
                                            }
                                        }
                                        if (getMaskSet().excludes[pos]) {
                                            var altIndexArrClone = altIndexArr.slice();
                                            for (var i = 0, el = getMaskSet().excludes[pos].length; i < el; i++) {
                                                altIndexArr.splice(altIndexArr.indexOf(getMaskSet().excludes[pos][i].toString()), 1);
                                            }
                                            if (altIndexArr.length === 0) {
                                                getMaskSet().excludes[pos] = undefined;
                                                altIndexArr = altIndexArrClone;
                                            }
                                        }
                                        if (opts.keepStatic === true || isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic) altIndexArr = altIndexArr.slice(0, 1);
                                        var unMatchedAlternation = false;
                                        for (var ndx = 0; ndx < altIndexArr.length; ndx++) {
                                            amndx = parseInt(altIndexArr[ndx]);
                                            matches = [];
                                            ndxInitializer = typeof altIndex === "string" ? resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice() : ndxInitializerClone.slice();
                                            if (alternateToken.matches[amndx] && handleMatch(alternateToken.matches[amndx], [ amndx ].concat(loopNdx), quantifierRecurse)) match = true; else if (ndx === 0) {
                                                unMatchedAlternation = true;
                                            }
                                            maltMatches = matches.slice();
                                            testPos = currentPos;
                                            matches = [];
                                            for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
                                                var altMatch = maltMatches[ndx1], dropMatch = false;
                                                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 (typeof altIndex !== "string" || altMatch.alternation !== undefined && $.inArray(altMatch.locator[altMatch.alternation].toString(), altIndexArr) !== -1) {
                                                        if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {
                                                            dropMatch = true;
                                                            setMergeLocators(altMatch2, altMatch);
                                                            break;
                                                        } else if (isSubsetOf(altMatch, altMatch2)) {
                                                            if (setMergeLocators(altMatch, altMatch2)) {
                                                                dropMatch = true;
                                                                malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
                                                            }
                                                            break;
                                                        } else if (isSubsetOf(altMatch2, altMatch)) {
                                                            setMergeLocators(altMatch2, altMatch);
                                                            break;
                                                        } else if (staticCanMatchDefinition(altMatch, altMatch2)) {
                                                            if (setMergeLocators(altMatch, altMatch2)) {
                                                                dropMatch = true;
                                                                malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
                                                            }
                                                            break;
                                                        }
                                                    }
                                                }
                                                if (!dropMatch) {
                                                    malternateMatches.push(altMatch);
                                                }
                                            }
                                        }
                                        matches = currentMatches.concat(malternateMatches);
                                        testPos = pos;
                                        insertStop = matches.length > 0;
                                        match = malternateMatches.length > 0;
                                        ndxInitializer = ndxInitializerClone.slice();
                                    } else match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [ altIndex ].concat(loopNdx), quantifierRecurse);
                                    if (match) return true;
                                } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[$.inArray(match, maskToken.matches) - 1]) {
                                    var qt = match;
                                    for (var qndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max) && testPos <= pos; qndx++) {
                                        var tokenGroup = maskToken.matches[$.inArray(qt, maskToken.matches) - 1];
                                        match = handleMatch(tokenGroup, [ qndx ].concat(loopNdx), tokenGroup);
                                        if (match) {
                                            latestMatch = matches[matches.length - 1].match;
                                            latestMatch.optionalQuantifier = qndx >= qt.quantifier.min;
                                            latestMatch.jit = (qndx || 1) * tokenGroup.matches.indexOf(latestMatch) >= qt.quantifier.jit;
                                            if (latestMatch.optionalQuantifier && isFirstMatch(latestMatch, tokenGroup)) {
                                                insertStop = true;
                                                testPos = pos;
                                                break;
                                            }
                                            if (latestMatch.jit) {
                                                getMaskSet().jitOffset[pos] = tokenGroup.matches.indexOf(latestMatch);
                                            }
                                            return true;
                                        }
                                    }
                                } else {
                                    match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
                                    if (match) return true;
                                }
                            } else {
                                testPos++;
                            }
                        }
                        for (var tndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; tndx < maskToken.matches.length; tndx++) {
                            if (maskToken.matches[tndx].isQuantifier !== true) {
                                var match = handleMatch(maskToken.matches[tndx], [ tndx ].concat(loopNdx), quantifierRecurse);
                                if (match && testPos === pos) {
                                    return match;
                                } else if (testPos > pos) {
                                    break;
                                }
                            }
                        }
                    }
                    function mergeLocators(pos, tests) {
                        var locator = [];
                        if (!$.isArray(tests)) tests = [ tests ];
                        if (tests.length > 0) {
                            if (tests[0].alternation === undefined) {
                                locator = determineTestTemplate(pos, tests.slice()).locator.slice();
                                if (locator.length === 0) locator = tests[0].locator.slice();
                            } else {
                                $.each(tests, function(ndx, tst) {
                                    if (tst.def !== "") {
                                        if (locator.length === 0) locator = tst.locator.slice(); else {
                                            for (var i = 0; i < locator.length; i++) {
                                                if (tst.locator[i] && locator[i].toString().indexOf(tst.locator[i]) === -1) {
                                                    locator[i] += "," + tst.locator[i];
                                                }
                                            }
                                        }
                                    }
                                });
                            }
                        }
                        return locator;
                    }
                    if (pos > -1) {
                        if (ndxIntlzr === undefined) {
                            var previousPos = pos - 1, test;
                            while ((test = getMaskSet().validPositions[previousPos] || getMaskSet().tests[previousPos]) === undefined && previousPos > -1) {
                                previousPos--;
                            }
                            if (test !== undefined && previousPos > -1) {
                                ndxInitializer = mergeLocators(previousPos, test);
                                cacheDependency = ndxInitializer.join("");
                                testPos = previousPos;
                            }
                        }
                        if (getMaskSet().tests[pos] && getMaskSet().tests[pos][0].cd === cacheDependency) {
                            return getMaskSet().tests[pos];
                        }
                        for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length; mtndx++) {
                            var match = resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [ mtndx ]);
                            if (match && testPos === pos || testPos > pos) {
                                break;
                            }
                        }
                    }
                    if (matches.length === 0 || insertStop) {
                        matches.push({
                            match: {
                                fn: null,
                                optionality: false,
                                casing: null,
                                def: "",
                                placeholder: ""
                            },
                            locator: [],
                            mloc: {},
                            cd: cacheDependency
                        });
                    }
                    if (ndxIntlzr !== undefined && getMaskSet().tests[pos]) {
                        return $.extend(true, [], matches);
                    }
                    getMaskSet().tests[pos] = $.extend(true, [], matches);
                    return getMaskSet().tests[pos];
                }
                function getBufferTemplate() {
                    if (getMaskSet()._buffer === undefined) {
                        getMaskSet()._buffer = getMaskTemplate(false, 1);
                        if (getMaskSet().buffer === undefined) getMaskSet().buffer = getMaskSet()._buffer.slice();
                    }
                    return getMaskSet()._buffer;
                }
                function getBuffer(noCache) {
                    if (getMaskSet().buffer === undefined || noCache === true) {
                        getMaskSet().buffer = getMaskTemplate(true, getLastValidPosition(), true);
                        if (getMaskSet()._buffer === undefined) getMaskSet()._buffer = getMaskSet().buffer.slice();
                    }
                    return getMaskSet().buffer;
                }
                function refreshFromBuffer(start, end, buffer) {
                    var i, p;
                    if (start === true) {
                        resetMaskSet();
                        start = 0;
                        end = buffer.length;
                    } else {
                        for (i = start; i < end; i++) {
                            delete getMaskSet().validPositions[i];
                        }
                    }
                    p = start;
                    for (i = start; i < end; i++) {
                        resetMaskSet(true);
                        if (buffer[i] !== opts.skipOptionalPartCharacter) {
                            var valResult = isValid(p, buffer[i], true, true);
                            if (valResult !== false) {
                                resetMaskSet(true);
                                p = valResult.caret !== undefined ? valResult.caret : valResult.pos + 1;
                            }
                        }
                    }
                }
                function casing(elem, test, pos) {
                    switch (opts.casing || test.casing) {
                      case "upper":
                        elem = elem.toUpperCase();
                        break;
    
                      case "lower":
                        elem = elem.toLowerCase();
                        break;
    
                      case "title":
                        var posBefore = getMaskSet().validPositions[pos - 1];
                        if (pos === 0 || posBefore && posBefore.input === String.fromCharCode(Inputmask.keyCode.SPACE)) {
                            elem = elem.toUpperCase();
                        } else {
                            elem = elem.toLowerCase();
                        }
                        break;
    
                      default:
                        if ($.isFunction(opts.casing)) {
                            var args = Array.prototype.slice.call(arguments);
                            args.push(getMaskSet().validPositions);
                            elem = opts.casing.apply(this, args);
                        }
                    }
                    return elem;
                }
                function checkAlternationMatch(altArr1, altArr2, na) {
                    var altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), isMatch = false, naArr = na !== undefined ? na.split(",") : [], naNdx;
                    for (var i = 0; i < naArr.length; i++) {
                        if ((naNdx = altArr1.indexOf(naArr[i])) !== -1) {
                            altArr1.splice(naNdx, 1);
                        }
                    }
                    for (var alndx = 0; alndx < altArr1.length; alndx++) {
                        if ($.inArray(altArr1[alndx], altArrC) !== -1) {
                            isMatch = true;
                            break;
                        }
                    }
                    return isMatch;
                }
                function alternate(pos, c, strict, fromSetValid, rAltPos) {
                    var validPsClone = $.extend(true, {}, getMaskSet().validPositions), lastAlt, alternation, isValidRslt = false, altPos, prevAltPos, i, validPos, decisionPos, lAltPos = rAltPos !== undefined ? rAltPos : getLastValidPosition();
                    if (lAltPos === -1 && rAltPos === undefined) {
                        lastAlt = 0;
                        prevAltPos = getTest(lastAlt);
                        alternation = prevAltPos.alternation;
                    } else {
                        for (;lAltPos >= 0; lAltPos--) {
                            altPos = getMaskSet().validPositions[lAltPos];
                            if (altPos && altPos.alternation !== undefined) {
                                if (prevAltPos && prevAltPos.locator[altPos.alternation] !== altPos.locator[altPos.alternation]) {
                                    break;
                                }
                                lastAlt = lAltPos;
                                alternation = getMaskSet().validPositions[lastAlt].alternation;
                                prevAltPos = altPos;
                            }
                        }
                    }
                    if (alternation !== undefined) {
                        decisionPos = parseInt(lastAlt);
                        getMaskSet().excludes[decisionPos] = getMaskSet().excludes[decisionPos] || [];
                        if (pos !== true) {
                            getMaskSet().excludes[decisionPos].push(getDecisionTaker(prevAltPos));
                        }
                        var validInputsClone = [], staticInputsBeforePos = 0;
                        for (i = decisionPos; i < getLastValidPosition(undefined, true) + 1; i++) {
                            validPos = getMaskSet().validPositions[i];
                            if (validPos && validPos.generatedInput !== true) {
                                validInputsClone.push(validPos.input);
                            } else if (i < pos) staticInputsBeforePos++;
                            delete getMaskSet().validPositions[i];
                        }
                        while (getMaskSet().excludes[decisionPos] && getMaskSet().excludes[decisionPos].length < 10) {
                            var posOffset = staticInputsBeforePos * -1, validInputs = validInputsClone.slice();
                            getMaskSet().tests[decisionPos] = undefined;
                            resetMaskSet(true);
                            isValidRslt = true;
                            while (validInputs.length > 0) {
                                var input = validInputs.shift();
                                if (!(isValidRslt = isValid(getLastValidPosition(undefined, true) + 1, input, false, fromSetValid, true))) {
                                    break;
                                }
                            }
                            if (isValidRslt && c !== undefined) {
                                var targetLvp = getLastValidPosition(pos) + 1;
                                for (i = decisionPos; i < getLastValidPosition() + 1; i++) {
                                    validPos = getMaskSet().validPositions[i];
                                    if ((validPos === undefined || validPos.match.fn == null) && i < pos + posOffset) {
                                        posOffset++;
                                    }
                                }
                                pos = pos + posOffset;
                                isValidRslt = isValid(pos > targetLvp ? targetLvp : pos, c, strict, fromSetValid, true);
                            }
                            if (!isValidRslt) {
                                resetMaskSet();
                                prevAltPos = getTest(decisionPos);
                                getMaskSet().validPositions = $.extend(true, {}, validPsClone);
                                if (getMaskSet().excludes[decisionPos]) {
                                    var decisionTaker = getDecisionTaker(prevAltPos);
                                    if (getMaskSet().excludes[decisionPos].indexOf(decisionTaker) !== -1) {
                                        isValidRslt = alternate(pos, c, strict, fromSetValid, decisionPos - 1);
                                        break;
                                    }
                                    getMaskSet().excludes[decisionPos].push(decisionTaker);
                                    for (i = decisionPos; i < getLastValidPosition(undefined, true) + 1; i++) {
                                        delete getMaskSet().validPositions[i];
                                    }
                                } else {
                                    isValidRslt = alternate(pos, c, strict, fromSetValid, decisionPos - 1);
                                    break;
                                }
                            } else break;
                        }
                    }
                    getMaskSet().excludes[decisionPos] = undefined;
                    return isValidRslt;
                }
                function isValid(pos, c, strict, fromSetValid, fromAlternate, validateOnly) {
                    function isSelection(posObj) {
                        return isRTL ? posObj.begin - posObj.end > 1 || posObj.begin - posObj.end === 1 : posObj.end - posObj.begin > 1 || posObj.end - posObj.begin === 1;
                    }
                    strict = strict === true;
                    var maskPos = pos;
                    if (pos.begin !== undefined) {
                        maskPos = isRTL ? pos.end : pos.begin;
                    }
                    function _isValid(position, c, strict) {
                        var rslt = false;
                        $.each(getTests(position), function(ndx, tst) {
                            var test = tst.match;
                            getBuffer(true);
                            rslt = test.fn != null ? test.fn.test(c, getMaskSet(), position, strict, opts, isSelection(pos)) : (c === test.def || c === opts.skipOptionalPartCharacter) && test.def !== "" ? {
                                c: getPlaceholder(position, test, true) || test.def,
                                pos: position
                            } : false;
                            if (rslt !== false) {
                                var elem = rslt.c !== undefined ? rslt.c : c, validatedPos = position;
                                elem = elem === opts.skipOptionalPartCharacter && test.fn === null ? getPlaceholder(position, test, true) || test.def : elem;
                                if (rslt.remove !== undefined) {
                                    if (!$.isArray(rslt.remove)) rslt.remove = [ rslt.remove ];
                                    $.each(rslt.remove.sort(function(a, b) {
                                        return b - a;
                                    }), function(ndx, lmnt) {
                                        revalidateMask({
                                            begin: lmnt,
                                            end: lmnt + 1
                                        });
                                    });
                                }
                                if (rslt.insert !== undefined) {
                                    if (!$.isArray(rslt.insert)) rslt.insert = [ rslt.insert ];
                                    $.each(rslt.insert.sort(function(a, b) {
                                        return a - b;
                                    }), function(ndx, lmnt) {
                                        isValid(lmnt.pos, lmnt.c, true, fromSetValid);
                                    });
                                }
                                if (rslt !== true && rslt.pos !== undefined && rslt.pos !== position) {
                                    validatedPos = rslt.pos;
                                }
                                if (rslt !== true && rslt.pos === undefined && rslt.c === undefined) {
                                    return false;
                                }
                                if (!revalidateMask(pos, $.extend({}, tst, {
                                    input: casing(elem, test, validatedPos)
                                }), fromSetValid, validatedPos)) {
                                    rslt = false;
                                }
                                return false;
                            }
                        });
                        return rslt;
                    }
                    var result = true, positionsClone = $.extend(true, {}, getMaskSet().validPositions);
                    if ($.isFunction(opts.preValidation) && !strict && fromSetValid !== true && validateOnly !== true) {
                        result = opts.preValidation(getBuffer(), maskPos, c, isSelection(pos), opts, getMaskSet());
                    }
                    if (result === true) {
                        trackbackPositions(undefined, maskPos, true);
                        if (maxLength === undefined || maskPos < maxLength) {
                            result = _isValid(maskPos, c, strict);
                            if ((!strict || fromSetValid === true) && result === false && validateOnly !== true) {
                                var currentPosValid = getMaskSet().validPositions[maskPos];
                                if (currentPosValid && currentPosValid.match.fn === null && (currentPosValid.match.def === c || c === opts.skipOptionalPartCharacter)) {
                                    result = {
                                        caret: seekNext(maskPos)
                                    };
                                } else {
                                    if ((opts.insertMode || getMaskSet().validPositions[seekNext(maskPos)] === undefined) && (!isMask(maskPos, true) || getMaskSet().jitOffset[maskPos])) {
                                        if (getMaskSet().jitOffset[maskPos] && getMaskSet().validPositions[seekNext(maskPos)] === undefined) {
                                            result = isValid(maskPos + getMaskSet().jitOffset[maskPos], c, strict);
                                            if (result !== false) result.caret = maskPos;
                                        } else for (var nPos = maskPos + 1, snPos = seekNext(maskPos); nPos <= snPos; nPos++) {
                                            result = _isValid(nPos, c, strict);
                                            if (result !== false) {
                                                result = trackbackPositions(maskPos, result.pos !== undefined ? result.pos : nPos) || result;
                                                maskPos = nPos;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (result === false && opts.keepStatic !== false && (opts.regex == null || isComplete(getBuffer())) && !strict && fromAlternate !== true) {
                            result = alternate(maskPos, c, strict, fromSetValid);
                        }
                        if (result === true) {
                            result = {
                                pos: maskPos
                            };
                        }
                    }
                    if ($.isFunction(opts.postValidation) && result !== false && !strict && fromSetValid !== true && validateOnly !== true) {
                        var postResult = opts.postValidation(getBuffer(true), pos.begin !== undefined ? isRTL ? pos.end : pos.begin : pos, result, opts);
                        if (postResult !== undefined) {
                            if (postResult.refreshFromBuffer && postResult.buffer) {
                                var refresh = postResult.refreshFromBuffer;
                                refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, postResult.buffer);
                            }
                            result = postResult === true ? result : postResult;
                        }
                    }
                    if (result && result.pos === undefined) {
                        result.pos = maskPos;
                    }
                    if (result === false || validateOnly === true) {
                        resetMaskSet(true);
                        getMaskSet().validPositions = $.extend(true, {}, positionsClone);
                    }
                    return result;
                }
                function trackbackPositions(originalPos, newPos, fillOnly) {
                    var result;
                    if (originalPos === undefined) {
                        for (originalPos = newPos - 1; originalPos > 0; originalPos--) {
                            if (getMaskSet().validPositions[originalPos]) break;
                        }
                    }
                    for (var ps = originalPos; ps < newPos; ps++) {
                        if (getMaskSet().validPositions[ps] === undefined && !isMask(ps, true)) {
                            var vp = ps == 0 ? getTest(ps) : getMaskSet().validPositions[ps - 1];
                            if (vp) {
                                var tests = getTests(ps).slice();
                                if (tests[tests.length - 1].match.def === "") tests.pop();
                                var bestMatch = determineTestTemplate(ps, tests);
                                bestMatch = $.extend({}, bestMatch, {
                                    input: getPlaceholder(ps, bestMatch.match, true) || bestMatch.match.def
                                });
                                bestMatch.generatedInput = true;
                                revalidateMask(ps, bestMatch, true);
                                if (fillOnly !== true) {
                                    var cvpInput = getMaskSet().validPositions[newPos].input;
                                    getMaskSet().validPositions[newPos] = undefined;
                                    result = isValid(newPos, cvpInput, true, true);
                                }
                            }
                        }
                    }
                    return result;
                }
                function revalidateMask(pos, validTest, fromSetValid, validatedPos) {
                    function IsEnclosedStatic(pos, valids, selection) {
                        var posMatch = valids[pos];
                        if (posMatch !== undefined && (posMatch.match.fn === null && posMatch.match.optionality !== true || posMatch.input === opts.radixPoint)) {
                            var prevMatch = selection.begin <= pos - 1 ? valids[pos - 1] && valids[pos - 1].match.fn === null && valids[pos - 1] : valids[pos - 1], nextMatch = selection.end > pos + 1 ? valids[pos + 1] && valids[pos + 1].match.fn === null && valids[pos + 1] : valids[pos + 1];
                            return prevMatch && nextMatch;
                        }
                        return false;
                    }
                    var begin = pos.begin !== undefined ? pos.begin : pos, end = pos.end !== undefined ? pos.end : pos;
                    if (pos.begin > pos.end) {
                        begin = pos.end;
                        end = pos.begin;
                    }
                    validatedPos = validatedPos !== undefined ? validatedPos : begin;
                    if (begin !== end || opts.insertMode && getMaskSet().validPositions[validatedPos] !== undefined && fromSetValid === undefined) {
                        var positionsClone = $.extend(true, {}, getMaskSet().validPositions), lvp = getLastValidPosition(undefined, true), i;
                        getMaskSet().p = begin;
                        for (i = lvp; i >= begin; i--) {
                            if (getMaskSet().validPositions[i] && getMaskSet().validPositions[i].match.nativeDef === "+") {
                                opts.isNegative = false;
                            }
                            delete getMaskSet().validPositions[i];
                        }
                        var valid = true, j = validatedPos, vps = getMaskSet().validPositions, needsValidation = false, posMatch = j, i = j;
                        if (validTest) {
                            getMaskSet().validPositions[validatedPos] = $.extend(true, {}, validTest);
                            posMatch++;
                            j++;
                            if (begin < end) i++;
                        }
                        for (;i <= lvp; i++) {
                            var t = positionsClone[i];
                            if (t !== undefined && (i >= end || i >= begin && t.generatedInput !== true && IsEnclosedStatic(i, positionsClone, {
                                begin: begin,
                                end: end
                            }))) {
                                while (getTest(posMatch).match.def !== "") {
                                    if (needsValidation === false && positionsClone[posMatch] && positionsClone[posMatch].match.nativeDef === t.match.nativeDef) {
                                        getMaskSet().validPositions[posMatch] = $.extend(true, {}, positionsClone[posMatch]);
                                        getMaskSet().validPositions[posMatch].input = t.input;
                                        trackbackPositions(undefined, posMatch, true);
                                        j = posMatch + 1;
                                        valid = true;
                                    } else if (opts.shiftPositions && positionCanMatchDefinition(posMatch, t.match.def)) {
                                        var result = isValid(posMatch, t.input, true, true);
                                        valid = result !== false;
                                        j = result.caret || result.insert ? getLastValidPosition() : posMatch + 1;
                                        needsValidation = true;
                                    } else {
                                        valid = t.generatedInput === true || t.input === opts.radixPoint && opts.numericInput === true;
                                    }
                                    if (valid) break;
                                    if (!valid && posMatch > end && isMask(posMatch, true) && (t.match.fn !== null || posMatch > getMaskSet().maskLength)) {
                                        break;
                                    }
                                    posMatch++;
                                }
                                if (getTest(posMatch).match.def == "") valid = false;
                                posMatch = j;
                            }
                            if (!valid) break;
                        }
                        if (!valid) {
                            getMaskSet().validPositions = $.extend(true, {}, positionsClone);
                            resetMaskSet(true);
                            return false;
                        }
                    } else if (validTest) {
                        getMaskSet().validPositions[validatedPos] = $.extend(true, {}, validTest);
                    }
                    resetMaskSet(true);
                    return true;
                }
                function isMask(pos, strict) {
                    var test = getTestTemplate(pos).match;
                    if (test.def === "") test = getTest(pos).match;
                    if (test.fn != null) {
                        return test.fn;
                    }
                    if (strict !== true && pos > -1) {
                        var tests = getTests(pos);
                        return tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0);
                    }
                    return false;
                }
                function seekNext(pos, newBlock) {
                    var position = pos + 1;
                    while (getTest(position).match.def !== "" && (newBlock === true && (getTest(position).match.newBlockMarker !== true || !isMask(position)) || newBlock !== true && !isMask(position))) {
                        position++;
                    }
                    return position;
                }
                function seekPrevious(pos, newBlock) {
                    var position = pos, tests;
                    if (position <= 0) return 0;
                    while (--position > 0 && (newBlock === true && getTest(position).match.newBlockMarker !== true || newBlock !== true && !isMask(position) && (tests = getTests(position), 
                    tests.length < 2 || tests.length === 2 && tests[1].match.def === ""))) {}
                    return position;
                }
                function writeBuffer(input, buffer, caretPos, event, triggerEvents) {
                    if (event && $.isFunction(opts.onBeforeWrite)) {
                        var result = opts.onBeforeWrite.call(inputmask, event, buffer, caretPos, opts);
                        if (result) {
                            if (result.refreshFromBuffer) {
                                var refresh = result.refreshFromBuffer;
                                refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, result.buffer || buffer);
                                buffer = getBuffer(true);
                            }
                            if (caretPos !== undefined) caretPos = result.caret !== undefined ? result.caret : caretPos;
                        }
                    }
                    if (input !== undefined) {
                        input.inputmask._valueSet(buffer.join(""));
                        if (caretPos !== undefined && (event === undefined || event.type !== "blur")) {
                            caret(input, caretPos);
                        } else renderColorMask(input, caretPos, buffer.length === 0);
                        if (triggerEvents === true) {
                            var $input = $(input), nptVal = input.inputmask._valueGet();
                            skipInputEvent = true;
                            $input.trigger("input");
                            setTimeout(function() {
                                if (nptVal === getBufferTemplate().join("")) {
                                    $input.trigger("cleared");
                                } else if (isComplete(buffer) === true) {
                                    $input.trigger("complete");
                                }
                            }, 0);
                        }
                    }
                }
                function getPlaceholder(pos, test, returnPL) {
                    test = test || getTest(pos).match;
                    if (test.placeholder !== undefined || returnPL === true) {
                        return $.isFunction(test.placeholder) ? test.placeholder(opts) : test.placeholder;
                    } else if (test.fn === null) {
                        if (pos > -1 && getMaskSet().validPositions[pos] === undefined) {
                            var tests = getTests(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.optionality !== true && tests[i].match.optionalQuantifier !== true && (tests[i].match.fn === null || prevTest === undefined || tests[i].match.fn.test(prevTest.match.def, getMaskSet(), pos, true, opts) !== false)) {
                                        staticAlternations.push(tests[i]);
                                        if (tests[i].match.fn === null) prevTest = tests[i];
                                        if (staticAlternations.length > 1) {
                                            if (/[0-9a-bA-Z]/.test(staticAlternations[0].match.def)) {
                                                return opts.placeholder.charAt(pos % opts.placeholder.length);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        return test.def;
                    }
                    return opts.placeholder.charAt(pos % opts.placeholder.length);
                }
                function HandleNativePlaceholder(npt, value) {
                    if (ie) {
                        if (npt.inputmask._valueGet() !== value && (npt.placeholder !== value || npt.placeholder === "")) {
                            var buffer = getBuffer().slice(), nptValue = npt.inputmask._valueGet();
                            if (nptValue !== value) {
                                var lvp = getLastValidPosition();
                                if (lvp === -1 && nptValue === getBufferTemplate().join("")) {
                                    buffer = [];
                                } else if (lvp !== -1) {
                                    clearOptionalTail(buffer);
                                }
                                writeBuffer(npt, buffer);
                            }
                        }
                    } else if (npt.placeholder !== value) {
                        npt.placeholder = value;
                        if (npt.placeholder === "") npt.removeAttribute("placeholder");
                    }
                }
                var EventRuler = {
                    on: function on(input, eventName, eventHandler) {
                        var ev = function ev(e) {
                            var that = this;
                            if (that.inputmask === undefined && this.nodeName !== "FORM") {
                                var imOpts = $.data(that, "_inputmask_opts");
                                if (imOpts) new Inputmask(imOpts).mask(that); else EventRuler.off(that);
                            } else if (e.type !== "setvalue" && this.nodeName !== "FORM" && (that.disabled || that.readOnly && !(e.type === "keydown" && e.ctrlKey && e.keyCode === 67 || opts.tabThrough === false && e.keyCode === Inputmask.keyCode.TAB))) {
                                e.preventDefault();
                            } else {
                                switch (e.type) {
                                  case "input":
                                    if (skipInputEvent === true) {
                                        skipInputEvent = false;
                                        return e.preventDefault();
                                    }
                                    if (mobile) {
                                        var args = arguments;
                                        setTimeout(function() {
                                            eventHandler.apply(that, args);
                                            caret(that, that.inputmask.caretPos, undefined, true);
                                        }, 0);
                                        return false;
                                    }
                                    break;
    
                                  case "keydown":
                                    skipKeyPressEvent = false;
                                    skipInputEvent = false;
                                    break;
    
                                  case "keypress":
                                    if (skipKeyPressEvent === true) {
                                        return e.preventDefault();
                                    }
                                    skipKeyPressEvent = true;
                                    break;
    
                                  case "click":
                                    if (iemobile || iphone) {
                                        var args = arguments;
                                        setTimeout(function() {
                                            eventHandler.apply(that, args);
                                        }, 0);
                                        return false;
                                    }
                                    break;
                                }
                                var returnVal = eventHandler.apply(that, arguments);
                                if (returnVal === false) {
                                    e.preventDefault();
                                    e.stopPropagation();
                                }
                                return returnVal;
                            }
                        };
                        input.inputmask.events[eventName] = input.inputmask.events[eventName] || [];
                        input.inputmask.events[eventName].push(ev);
                        if ($.inArray(eventName, [ "submit", "reset" ]) !== -1) {
                            if (input.form !== null) $(input.form).on(eventName, ev);
                        } else {
                            $(input).on(eventName, ev);
                        }
                    },
                    off: function off(input, event) {
                        if (input.inputmask && input.inputmask.events) {
                            var events;
                            if (event) {
                                events = [];
                                events[event] = input.inputmask.events[event];
                            } else {
                                events = input.inputmask.events;
                            }
                            $.each(events, function(eventName, evArr) {
                                while (evArr.length > 0) {
                                    var ev = evArr.pop();
                                    if ($.inArray(eventName, [ "submit", "reset" ]) !== -1) {
                                        if (input.form !== null) $(input.form).off(eventName, ev);
                                    } else {
                                        $(input).off(eventName, ev);
                                    }
                                }
                                delete input.inputmask.events[eventName];
                            });
                        }
                    }
                };
                var EventHandlers = {
                    keydownEvent: function keydownEvent(e) {
                        var input = this, $input = $(input), k = e.keyCode, pos = caret(input);
                        if (k === Inputmask.keyCode.BACKSPACE || k === Inputmask.keyCode.DELETE || iphone && k === Inputmask.keyCode.BACKSPACE_SAFARI || e.ctrlKey && k === Inputmask.keyCode.X && !isInputEventSupported("cut")) {
                            e.preventDefault();
                            handleRemove(input, k, pos);
                            writeBuffer(input, getBuffer(true), getMaskSet().p, e, input.inputmask._valueGet() !== getBuffer().join(""));
                        } else if (k === Inputmask.keyCode.END || k === Inputmask.keyCode.PAGE_DOWN) {
                            e.preventDefault();
                            var caretPos = seekNext(getLastValidPosition());
                            caret(input, e.shiftKey ? pos.begin : caretPos, caretPos, true);
                        } else if (k === Inputmask.keyCode.HOME && !e.shiftKey || k === Inputmask.keyCode.PAGE_UP) {
                            e.preventDefault();
                            caret(input, 0, e.shiftKey ? pos.begin : 0, true);
                        } else if ((opts.undoOnEscape && k === Inputmask.keyCode.ESCAPE || k === 90 && e.ctrlKey) && e.altKey !== true) {
                            checkVal(input, true, false, undoValue.split(""));
                            $input.trigger("click");
                        } else if (k === Inputmask.keyCode.INSERT && !(e.shiftKey || e.ctrlKey)) {
                            opts.insertMode = !opts.insertMode;
                            input.setAttribute("im-insert", opts.insertMode);
                        } else if (opts.tabThrough === true && k === Inputmask.keyCode.TAB) {
                            if (e.shiftKey === true) {
                                if (getTest(pos.begin).match.fn === null) {
                                    pos.begin = seekNext(pos.begin);
                                }
                                pos.end = seekPrevious(pos.begin, true);
                                pos.begin = seekPrevious(pos.end, true);
                            } else {
                                pos.begin = seekNext(pos.begin, true);
                                pos.end = seekNext(pos.begin, true);
                                if (pos.end < getMaskSet().maskLength) pos.end--;
                            }
                            if (pos.begin < getMaskSet().maskLength) {
                                e.preventDefault();
                                caret(input, pos.begin, pos.end);
                            }
                        }
                        opts.onKeyDown.call(this, e, getBuffer(), caret(input).begin, opts);
                        ignorable = $.inArray(k, opts.ignorables) !== -1;
                    },
                    keypressEvent: function keypressEvent(e, checkval, writeOut, strict, ndx) {
                        var input = this, $input = $(input), k = e.which || e.charCode || e.keyCode;
                        if (checkval !== true && !(e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable)) {
                            if (k === Inputmask.keyCode.ENTER && undoValue !== getBuffer().join("")) {
                                undoValue = getBuffer().join("");
                                setTimeout(function() {
                                    $input.trigger("change");
                                }, 0);
                            }
                            return true;
                        } else {
                            if (k) {
                                if (k === 46 && e.shiftKey === false && opts.radixPoint !== "") k = opts.radixPoint.charCodeAt(0);
                                var pos = checkval ? {
                                    begin: ndx,
                                    end: ndx
                                } : caret(input), forwardPosition, c = String.fromCharCode(k), offset = 0;
                                if (opts._radixDance && opts.numericInput) {
                                    var caretPos = getBuffer().indexOf(opts.radixPoint.charAt(0)) + 1;
                                    if (pos.begin <= caretPos) {
                                        if (k === opts.radixPoint.charCodeAt(0)) offset = 1;
                                        pos.begin -= 1;
                                        pos.end -= 1;
                                    }
                                }
                                getMaskSet().writeOutBuffer = true;
                                var valResult = isValid(pos, c, strict);
                                if (valResult !== false) {
                                    resetMaskSet(true);
                                    forwardPosition = valResult.caret !== undefined ? valResult.caret : seekNext(valResult.pos.begin ? valResult.pos.begin : valResult.pos);
                                    getMaskSet().p = forwardPosition;
                                }
                                forwardPosition = (opts.numericInput && valResult.caret === undefined ? seekPrevious(forwardPosition) : forwardPosition) + offset;
                                if (writeOut !== false) {
                                    setTimeout(function() {
                                        opts.onKeyValidation.call(input, k, valResult, opts);
                                    }, 0);
                                    if (getMaskSet().writeOutBuffer && valResult !== false) {
                                        var buffer = getBuffer();
                                        writeBuffer(input, buffer, forwardPosition, e, checkval !== true);
                                    }
                                }
                                e.preventDefault();
                                if (checkval) {
                                    if (valResult !== false) valResult.forwardPosition = forwardPosition;
                                    return valResult;
                                }
                            }
                        }
                    },
                    pasteEvent: function pasteEvent(e) {
                        var input = this, ev = e.originalEvent || e, $input = $(input), inputValue = input.inputmask._valueGet(true), caretPos = caret(input), tempValue;
                        if (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 === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(0, caretPos.begin).join("")) valueBeforeCaret = "";
                        if (valueAfterCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(caretPos.end).join("")) valueAfterCaret = "";
                        if (window.clipboardData && window.clipboardData.getData) {
                            inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret;
                        } else if (ev.clipboardData && ev.clipboardData.getData) {
                            inputValue = valueBeforeCaret + ev.clipboardData.getData("text/plain") + valueAfterCaret;
                        } else return true;
                        var pasteValue = inputValue;
                        if ($.isFunction(opts.onBeforePaste)) {
                            pasteValue = opts.onBeforePaste.call(inputmask, inputValue, opts);
                            if (pasteValue === false) {
                                return e.preventDefault();
                            }
                            if (!pasteValue) {
                                pasteValue = inputValue;
                            }
                        }
                        checkVal(input, false, false, pasteValue.toString().split(""));
                        writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()), e, undoValue !== getBuffer().join(""));
                        return e.preventDefault();
                    },
                    inputFallBackEvent: function inputFallBackEvent(e) {
                        function radixPointHandler(input, inputValue, caretPos) {
                            if (inputValue.charAt(caretPos.begin - 1) === "." && opts.radixPoint !== "") {
                                inputValue = inputValue.split("");
                                inputValue[caretPos.begin - 1] = opts.radixPoint.charAt(0);
                                inputValue = inputValue.join("");
                            }
                            return inputValue;
                        }
                        function ieMobileHandler(input, inputValue, caretPos) {
                            if (iemobile) {
                                var inputChar = inputValue.replace(getBuffer().join(""), "");
                                if (inputChar.length === 1) {
                                    var iv = inputValue.split("");
                                    iv.splice(caretPos.begin, 0, inputChar);
                                    inputValue = iv.join("");
                                }
                            }
                            return inputValue;
                        }
                        var input = this, inputValue = input.inputmask._valueGet();
                        if (getBuffer().join("") !== inputValue) {
                            var caretPos = caret(input);
                            inputValue = radixPointHandler(input, inputValue, caretPos);
                            inputValue = ieMobileHandler(input, inputValue, caretPos);
                            if (getBuffer().join("") !== inputValue) {
                                var buffer = getBuffer().join(""), offset = !opts.numericInput && inputValue.length > buffer.length ? -1 : 0, frontPart = inputValue.substr(0, caretPos.begin), backPart = inputValue.substr(caretPos.begin), frontBufferPart = buffer.substr(0, caretPos.begin + offset), backBufferPart = buffer.substr(caretPos.begin + offset);
                                var selection = caretPos, entries = "", isEntry = false;
                                if (frontPart !== frontBufferPart) {
                                    var fpl = (isEntry = frontPart.length >= frontBufferPart.length) ? frontPart.length : frontBufferPart.length, i;
                                    for (i = 0; frontPart.charAt(i) === frontBufferPart.charAt(i) && i < fpl; i++) {}
                                    if (isEntry) {
                                        selection.begin = i - offset;
                                        entries += frontPart.slice(i, selection.end);
                                    }
                                }
                                if (backPart !== backBufferPart) {
                                    if (backPart.length > backBufferPart.length) {
                                        entries += backPart.slice(0, 1);
                                    } else {
                                        if (backPart.length < backBufferPart.length) {
                                            selection.end += backBufferPart.length - backPart.length;
                                            if (!isEntry && opts.radixPoint !== "" && backPart === "" && frontPart.charAt(selection.begin + offset - 1) === opts.radixPoint) {
                                                selection.begin--;
                                                entries = opts.radixPoint;
                                            }
                                        }
                                    }
                                }
                                writeBuffer(input, getBuffer(), {
                                    begin: selection.begin + offset,
                                    end: selection.end + offset
                                });
                                if (entries.length > 0) {
                                    $.each(entries.split(""), function(ndx, entry) {
                                        var keypress = new $.Event("keypress");
                                        keypress.which = entry.charCodeAt(0);
                                        ignorable = false;
                                        EventHandlers.keypressEvent.call(input, keypress);
                                    });
                                } else {
                                    if (selection.begin === selection.end - 1) {
                                        selection.begin = seekPrevious(selection.begin + 1);
                                        if (selection.begin === selection.end - 1) {
                                            caret(input, selection.begin);
                                        } else {
                                            caret(input, selection.begin, selection.end);
                                        }
                                    }
                                    var keydown = new $.Event("keydown");
                                    keydown.keyCode = opts.numericInput ? Inputmask.keyCode.BACKSPACE : Inputmask.keyCode.DELETE;
                                    EventHandlers.keydownEvent.call(input, keydown);
                                }
                                e.preventDefault();
                            }
                        }
                    },
                    beforeInputEvent: function beforeInputEvent(e) {
                        if (e.cancelable) {
                            var input = this;
                            switch (e.inputType) {
                              case "insertText":
                                $.each(e.data.split(""), function(ndx, entry) {
                                    var keypress = new $.Event("keypress");
                                    keypress.which = entry.charCodeAt(0);
                                    ignorable = false;
                                    EventHandlers.keypressEvent.call(input, keypress);
                                });
                                return e.preventDefault();
    
                              case "deleteContentBackward":
                                var keydown = new $.Event("keydown");
                                keydown.keyCode = Inputmask.keyCode.BACKSPACE;
                                EventHandlers.keydownEvent.call(input, keydown);
                                return e.preventDefault();
    
                              case "deleteContentForward":
                                var keydown = new $.Event("keydown");
                                keydown.keyCode = Inputmask.keyCode.DELETE;
                                EventHandlers.keydownEvent.call(input, keydown);
                                return e.preventDefault();
                            }
                        }
                    },
                    setValueEvent: function setValueEvent(e) {
                        this.inputmask.refreshValue = false;
                        var input = this, value = e && e.detail ? e.detail[0] : arguments[1], value = value || input.inputmask._valueGet(true);
                        if ($.isFunction(opts.onBeforeMask)) value = opts.onBeforeMask.call(inputmask, value, opts) || value;
                        value = value.toString().split("");
                        checkVal(input, true, false, value);
                        undoValue = getBuffer().join("");
                        if ((opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === getBufferTemplate().join("")) {
                            input.inputmask._valueSet("");
                        }
                    },
                    focusEvent: function focusEvent(e) {
                        var input = this, nptValue = input.inputmask._valueGet();
                        if (opts.showMaskOnFocus) {
                            if (nptValue !== getBuffer().join("")) {
                                writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()));
                            } else if (mouseEnter === false) {
                                caret(input, seekNext(getLastValidPosition()));
                            }
                        }
                        if (opts.positionCaretOnTab === true && mouseEnter === false) {
                            EventHandlers.clickEvent.apply(input, [ e, true ]);
                        }
                        undoValue = getBuffer().join("");
                    },
                    mouseleaveEvent: function mouseleaveEvent(e) {
                        var input = this;
                        mouseEnter = false;
                        if (opts.clearMaskOnLostFocus && document.activeElement !== input) {
                            HandleNativePlaceholder(input, originalPlaceholder);
                        }
                    },
                    clickEvent: function clickEvent(e, tabbed) {
                        function doRadixFocus(clickPos) {
                            if (opts.radixPoint !== "") {
                                var vps = getMaskSet().validPositions;
                                if (vps[clickPos] === undefined || vps[clickPos].input === getPlaceholder(clickPos)) {
                                    if (clickPos < seekNext(-1)) return true;
                                    var radixPos = $.inArray(opts.radixPoint, getBuffer());
                                    if (radixPos !== -1) {
                                        for (var vp in vps) {
                                            if (radixPos < vp && vps[vp].input !== getPlaceholder(vp)) {
                                                return false;
                                            }
                                        }
                                        return true;
                                    }
                                }
                            }
                            return false;
                        }
                        var input = this;
                        setTimeout(function() {
                            if (document.activeElement === input) {
                                var selectedCaret = caret(input);
                                if (tabbed) {
                                    if (isRTL) {
                                        selectedCaret.end = selectedCaret.begin;
                                    } else {
                                        selectedCaret.begin = selectedCaret.end;
                                    }
                                }
                                if (selectedCaret.begin === selectedCaret.end) {
                                    switch (opts.positionCaretOnClick) {
                                      case "none":
                                        break;
    
                                      case "select":
                                        caret(input, 0, getBuffer().length);
                                        break;
    
                                      case "ignore":
                                        caret(input, seekNext(getLastValidPosition()));
                                        break;
    
                                      case "radixFocus":
                                        if (doRadixFocus(selectedCaret.begin)) {
                                            var radixPos = getBuffer().join("").indexOf(opts.radixPoint);
                                            caret(input, opts.numericInput ? seekNext(radixPos) : radixPos);
                                            break;
                                        }
    
                                      default:
                                        var clickPosition = selectedCaret.begin, lvclickPosition = getLastValidPosition(clickPosition, true), lastPosition = seekNext(lvclickPosition);
                                        if (clickPosition < lastPosition) {
                                            caret(input, !isMask(clickPosition, true) && !isMask(clickPosition - 1, true) ? seekNext(clickPosition) : clickPosition);
                                        } else {
                                            var lvp = getMaskSet().validPositions[lvclickPosition], tt = getTestTemplate(lastPosition, lvp ? lvp.match.locator : undefined, lvp), placeholder = getPlaceholder(lastPosition, tt.match);
                                            if (placeholder !== "" && getBuffer()[lastPosition] !== placeholder && tt.match.optionalQuantifier !== true && tt.match.newBlockMarker !== true || !isMask(lastPosition, opts.keepStatic) && tt.match.def === placeholder) {
                                                var newPos = seekNext(lastPosition);
                                                if (clickPosition >= newPos || clickPosition === lastPosition) {
                                                    lastPosition = newPos;
                                                }
                                            }
                                            caret(input, lastPosition);
                                        }
                                        break;
                                    }
                                }
                            }
                        }, 0);
                    },
                    cutEvent: function cutEvent(e) {
                        var input = this, $input = $(input), pos = caret(input), ev = e.originalEvent || e;
                        var clipboardData = window.clipboardData || ev.clipboardData, clipData = isRTL ? getBuffer().slice(pos.end, pos.begin) : getBuffer().slice(pos.begin, pos.end);
                        clipboardData.setData("text", isRTL ? clipData.reverse().join("") : clipData.join(""));
                        if (document.execCommand) document.execCommand("copy");
                        handleRemove(input, Inputmask.keyCode.DELETE, pos);
                        writeBuffer(input, getBuffer(), getMaskSet().p, e, undoValue !== getBuffer().join(""));
                    },
                    blurEvent: function blurEvent(e) {
                        var $input = $(this), input = this;
                        if (input.inputmask) {
                            HandleNativePlaceholder(input, originalPlaceholder);
                            var nptValue = input.inputmask._valueGet(), buffer = getBuffer().slice();
                            if (nptValue !== "" || colorMask !== undefined) {
                                if (opts.clearMaskOnLostFocus) {
                                    if (getLastValidPosition() === -1 && nptValue === getBufferTemplate().join("")) {
                                        buffer = [];
                                    } else {
                                        clearOptionalTail(buffer);
                                    }
                                }
                                if (isComplete(buffer) === false) {
                                    setTimeout(function() {
                                        $input.trigger("incomplete");
                                    }, 0);
                                    if (opts.clearIncomplete) {
                                        resetMaskSet();
                                        if (opts.clearMaskOnLostFocus) {
                                            buffer = [];
                                        } else {
                                            buffer = getBufferTemplate().slice();
                                        }
                                    }
                                }
                                writeBuffer(input, buffer, undefined, e);
                            }
                            if (undoValue !== getBuffer().join("")) {
                                undoValue = buffer.join("");
                                $input.trigger("change");
                            }
                        }
                    },
                    mouseenterEvent: function mouseenterEvent(e) {
                        var input = this;
                        mouseEnter = true;
                        if (document.activeElement !== input && opts.showMaskOnHover) {
                            HandleNativePlaceholder(input, (isRTL ? getBuffer().slice().reverse() : getBuffer()).join(""));
                        }
                    },
                    submitEvent: function submitEvent(e) {
                        if (undoValue !== getBuffer().join("")) {
                            $el.trigger("change");
                        }
                        if (opts.clearMaskOnLostFocus && getLastValidPosition() === -1 && el.inputmask._valueGet && el.inputmask._valueGet() === getBufferTemplate().join("")) {
                            el.inputmask._valueSet("");
                        }
                        if (opts.clearIncomplete && isComplete(getBuffer()) === false) {
                            el.inputmask._valueSet("");
                        }
                        if (opts.removeMaskOnSubmit) {
                            el.inputmask._valueSet(el.inputmask.unmaskedvalue(), true);
                            setTimeout(function() {
                                writeBuffer(el, getBuffer());
                            }, 0);
                        }
                    },
                    resetEvent: function resetEvent(e) {
                        el.inputmask.refreshValue = true;
                        setTimeout(function() {
                            $el.trigger("setvalue");
                        }, 0);
                    }
                };
                function checkVal(input, writeOut, strict, nptvl, initiatingEvent) {
                    var inputmask = this || input.inputmask, inputValue = nptvl.slice(), charCodes = "", initialNdx = -1, result = undefined;
                    function isTemplateMatch(ndx, charCodes) {
                        var charCodeNdx = getMaskTemplate(true, 0, false).slice(ndx, seekNext(ndx)).join("").replace(/'/g, "").indexOf(charCodes);
                        return charCodeNdx !== -1 && !isMask(ndx) && (getTest(ndx).match.nativeDef === charCodes.charAt(0) || getTest(ndx).match.fn === null && getTest(ndx).match.nativeDef === "'" + charCodes.charAt(0) || getTest(ndx).match.nativeDef === " " && (getTest(ndx + 1).match.nativeDef === charCodes.charAt(0) || getTest(ndx + 1).match.fn === null && getTest(ndx + 1).match.nativeDef === "'" + charCodes.charAt(0)));
                    }
                    resetMaskSet();
                    if (!strict && opts.autoUnmask !== true) {
                        var staticInput = getBufferTemplate().slice(0, seekNext(-1)).join(""), matches = inputValue.join("").match(new RegExp("^" + Inputmask.escapeRegex(staticInput), "g"));
                        if (matches && matches.length > 0) {
                            inputValue.splice(0, matches.length * staticInput.length);
                            initialNdx = seekNext(initialNdx);
                        }
                    } else {
                        initialNdx = seekNext(initialNdx);
                    }
                    if (initialNdx === -1) {
                        getMaskSet().p = seekNext(initialNdx);
                        initialNdx = 0;
                    } else getMaskSet().p = initialNdx;
                    inputmask.caretPos = {
                        begin: initialNdx
                    };
                    $.each(inputValue, function(ndx, charCode) {
                        if (charCode !== undefined) {
                            if (getMaskSet().validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder(ndx) && isMask(ndx, true) && isValid(ndx, inputValue[ndx], true, undefined, undefined, true) === false) {
                                getMaskSet().p++;
                            } else {
                                var keypress = new $.Event("_checkval");
                                keypress.which = charCode.charCodeAt(0);
                                charCodes += charCode;
                                var lvp = getLastValidPosition(undefined, true);
                                if (!isTemplateMatch(initialNdx, charCodes)) {
                                    result = EventHandlers.keypressEvent.call(input, keypress, true, false, strict, inputmask.caretPos.begin);
                                    if (result) {
                                        initialNdx = inputmask.caretPos.begin + 1;
                                        charCodes = "";
                                    }
                                } else {
                                    result = EventHandlers.keypressEvent.call(input, keypress, true, false, strict, lvp + 1);
                                }
                                if (result) {
                                    writeBuffer(undefined, getBuffer(), result.forwardPosition, keypress, false);
                                    inputmask.caretPos = {
                                        begin: result.forwardPosition,
                                        end: result.forwardPosition
                                    };
                                }
                            }
                        }
                    });
                    if (writeOut) writeBuffer(input, getBuffer(), result ? result.forwardPosition : undefined, initiatingEvent || new $.Event("checkval"), initiatingEvent && initiatingEvent.type === "input");
                }
                function unmaskedvalue(input) {
                    if (input) {
                        if (input.inputmask === undefined) {
                            return input.value;
                        }
                        if (input.inputmask && input.inputmask.refreshValue) {
                            EventHandlers.setValueEvent.call(input);
                        }
                    }
                    var umValue = [], vps = getMaskSet().validPositions;
                    for (var pndx in vps) {
                        if (vps[pndx].match && vps[pndx].match.fn != null) {
                            umValue.push(vps[pndx].input);
                        }
                    }
                    var unmaskedValue = umValue.length === 0 ? "" : (isRTL ? umValue.reverse() : umValue).join("");
                    if ($.isFunction(opts.onUnMask)) {
                        var bufferValue = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join("");
                        unmaskedValue = opts.onUnMask.call(inputmask, bufferValue, unmaskedValue, opts);
                    }
                    return unmaskedValue;
                }
                function caret(input, begin, end, notranslate) {
                    function translatePosition(pos) {
                        if (isRTL && typeof pos === "number" && (!opts.greedy || opts.placeholder !== "") && el) {
                            pos = el.inputmask._valueGet().length - pos;
                        }
                        return pos;
                    }
                    var range;
                    if (begin !== undefined) {
                        if ($.isArray(begin)) {
                            end = isRTL ? begin[0] : begin[1];
                            begin = isRTL ? begin[1] : begin[0];
                        }
                        if (begin.begin !== undefined) {
                            end = isRTL ? begin.begin : begin.end;
                            begin = isRTL ? begin.end : begin.begin;
                        }
                        if (typeof begin === "number") {
                            begin = notranslate ? begin : translatePosition(begin);
                            end = notranslate ? end : translatePosition(end);
                            end = typeof end == "number" ? end : begin;
                            var scrollCalc = parseInt(((input.ownerDocument.defaultView || window).getComputedStyle ? (input.ownerDocument.defaultView || window).getComputedStyle(input, null) : input.currentStyle).fontSize) * end;
                            input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0;
                            input.inputmask.caretPos = {
                                begin: begin,
                                end: end
                            };
                            if (input === document.activeElement) {
                                if ("selectionStart" in input) {
                                    input.selectionStart = begin;
                                    input.selectionEnd = end;
                                } else if (window.getSelection) {
                                    range = document.createRange();
                                    if (input.firstChild === undefined || input.firstChild === null) {
                                        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(true);
                                    var sel = window.getSelection();
                                    sel.removeAllRanges();
                                    sel.addRange(range);
                                } else if (input.createTextRange) {
                                    range = input.createTextRange();
                                    range.collapse(true);
                                    range.moveEnd("character", end);
                                    range.moveStart("character", begin);
                                    range.select();
                                }
                                renderColorMask(input, {
                                    begin: begin,
                                    end: end
                                });
                            }
                        }
                    } else {
                        if ("selectionStart" in input) {
                            begin = input.selectionStart;
                            end = input.selectionEnd;
                        } else if (window.getSelection) {
                            range = window.getSelection().getRangeAt(0);
                            if (range.commonAncestorContainer.parentNode === input || range.commonAncestorContainer === input) {
                                begin = range.startOffset;
                                end = range.endOffset;
                            }
                        } else if (document.selection && document.selection.createRange) {
                            range = document.selection.createRange();
                            begin = 0 - range.duplicate().moveStart("character", -input.inputmask._valueGet().length);
                            end = begin + range.text.length;
                        }
                        return {
                            begin: notranslate ? begin : translatePosition(begin),
                            end: notranslate ? end : translatePosition(end)
                        };
                    }
                }
                function determineLastRequiredPosition(returnDefinition) {
                    var buffer = getMaskTemplate(true, getLastValidPosition(), true, true), bl = buffer.length, pos, lvp = getLastValidPosition(), positions = {}, lvTest = getMaskSet().validPositions[lvp], ndxIntlzr = lvTest !== undefined ? lvTest.locator.slice() : undefined, testPos;
                    for (pos = lvp + 1; pos < buffer.length; pos++) {
                        testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
                        ndxIntlzr = testPos.locator.slice();
                        positions[pos] = $.extend(true, {}, testPos);
                    }
                    var lvTestAlt = lvTest && lvTest.alternation !== undefined ? lvTest.locator[lvTest.alternation] : undefined;
                    for (pos = bl - 1; pos > lvp; pos--) {
                        testPos = positions[pos];
                        if ((testPos.match.optionality || testPos.match.optionalQuantifier && testPos.match.newBlockMarker || lvTestAlt && (lvTestAlt !== positions[pos].locator[lvTest.alternation] && testPos.match.fn != null || testPos.match.fn === null && testPos.locator[lvTest.alternation] && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.toString().split(",")) && getTests(pos)[0].def !== "")) && buffer[pos] === getPlaceholder(pos, testPos.match)) {
                            bl--;
                        } else break;
                    }
                    return returnDefinition ? {
                        l: bl,
                        def: positions[bl] ? positions[bl].match : undefined
                    } : bl;
                }
                function clearOptionalTail(buffer) {
                    buffer.length = 0;
                    var template = getMaskTemplate(true, 0, true, undefined, true), lmnt, validPos;
                    while (lmnt = template.shift(), lmnt !== undefined) {
                        buffer.push(lmnt);
                    }
                    return buffer;
                }
                function isComplete(buffer) {
                    if ($.isFunction(opts.isComplete)) return opts.isComplete(buffer, opts);
                    if (opts.repeat === "*") return undefined;
                    var complete = false, lrp = determineLastRequiredPosition(true), aml = seekPrevious(lrp.l);
                    if (lrp.def === undefined || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) {
                        complete = true;
                        for (var i = 0; i <= aml; i++) {
                            var test = getTestTemplate(i).match;
                            if (test.fn !== null && getMaskSet().validPositions[i] === undefined && test.optionality !== true && test.optionalQuantifier !== true || test.fn === null && buffer[i] !== getPlaceholder(i, test)) {
                                complete = false;
                                break;
                            }
                        }
                    }
                    return complete;
                }
                function handleRemove(input, k, pos, strict, fromIsValid) {
                    if (opts.numericInput || isRTL) {
                        if (k === Inputmask.keyCode.BACKSPACE) {
                            k = Inputmask.keyCode.DELETE;
                        } else if (k === Inputmask.keyCode.DELETE) {
                            k = Inputmask.keyCode.BACKSPACE;
                        }
                        if (isRTL) {
                            var pend = pos.end;
                            pos.end = pos.begin;
                            pos.begin = pend;
                        }
                    }
                    if (k === Inputmask.keyCode.BACKSPACE && pos.end - pos.begin < 1) {
                        pos.begin = seekPrevious(pos.begin);
                        if (getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator) {
                            pos.begin--;
                        }
                    } else if (k === Inputmask.keyCode.DELETE && pos.begin === pos.end) {
                        pos.end = isMask(pos.end, true) && getMaskSet().validPositions[pos.end] && getMaskSet().validPositions[pos.end].input !== opts.radixPoint ? pos.end + 1 : seekNext(pos.end) + 1;
                        if (getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator) {
                            pos.end++;
                        }
                    }
                    revalidateMask(pos);
                    if (strict !== true && opts.keepStatic !== false || opts.regex !== null) {
                        var result = alternate(true);
                        if (result) {
                            var newPos = result.caret !== undefined ? result.caret : result.pos ? seekNext(result.pos.begin ? result.pos.begin : result.pos) : getLastValidPosition(-1, true);
                            if (k !== Inputmask.keyCode.DELETE || pos.begin > newPos) {
                                pos.begin == newPos;
                            }
                        }
                    }
                    var lvp = getLastValidPosition(pos.begin, true);
                    if (lvp < pos.begin || pos.begin === -1) {
                        getMaskSet().p = seekNext(lvp);
                    } else if (strict !== true) {
                        getMaskSet().p = pos.begin;
                        if (fromIsValid !== true) {
                            while (getMaskSet().p < lvp && getMaskSet().validPositions[getMaskSet().p] === undefined) {
                                getMaskSet().p++;
                            }
                        }
                    }
                }
                function initializeColorMask(input) {
                    var computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null);
                    function findCaretPos(clientx) {
                        var e = document.createElement("span"), caretPos;
                        for (var style in computedStyle) {
                            if (isNaN(style) && style.indexOf("font") !== -1) {
                                e.style[style] = computedStyle[style];
                            }
                        }
                        e.style.textTransform = computedStyle.textTransform;
                        e.style.letterSpacing = computedStyle.letterSpacing;
                        e.style.position = "absolute";
                        e.style.height = "auto";
                        e.style.width = "auto";
                        e.style.visibility = "hidden";
                        e.style.whiteSpace = "nowrap";
                        document.body.appendChild(e);
                        var inputText = input.inputmask._valueGet(), previousWidth = 0, itl;
                        for (caretPos = 0, itl = inputText.length; caretPos <= itl; caretPos++) {
                            e.innerHTML += inputText.charAt(caretPos) || "_";
                            if (e.offsetWidth >= clientx) {
                                var offset1 = clientx - previousWidth;
                                var offset2 = e.offsetWidth - clientx;
                                e.innerHTML = inputText.charAt(caretPos);
                                offset1 -= e.offsetWidth / 3;
                                caretPos = offset1 < offset2 ? caretPos - 1 : caretPos;
                                break;
                            }
                            previousWidth = e.offsetWidth;
                        }
                        document.body.removeChild(e);
                        return caretPos;
                    }
                    var template = document.createElement("div");
                    template.style.width = computedStyle.width;
                    template.style.textAlign = computedStyle.textAlign;
                    colorMask = document.createElement("div");
                    input.inputmask.colorMask = colorMask;
                    colorMask.className = "im-colormask";
                    input.parentNode.insertBefore(colorMask, input);
                    input.parentNode.removeChild(input);
                    colorMask.appendChild(input);
                    colorMask.appendChild(template);
                    input.style.left = template.offsetLeft + "px";
                    $(colorMask).on("mouseleave", function(e) {
                        return EventHandlers.mouseleaveEvent.call(input, [ e ]);
                    });
                    $(colorMask).on("mouseenter", function(e) {
                        return EventHandlers.mouseenterEvent.call(input, [ e ]);
                    });
                    $(colorMask).on("click", function(e) {
                        caret(input, findCaretPos(e.clientX));
                        return EventHandlers.clickEvent.call(input, [ e ]);
                    });
                }
                function renderColorMask(input, caretPos, clear) {
                    var maskTemplate = [], isStatic = false, test, testPos, ndxIntlzr, pos = 0;
                    function setEntry(entry) {
                        if (entry === undefined) entry = "";
                        if (!isStatic && (test.fn === null || testPos.input === undefined)) {
                            isStatic = true;
                            maskTemplate.push("<span class='im-static'>" + entry);
                        } else if (isStatic && (test.fn !== null && testPos.input !== undefined || test.def === "")) {
                            isStatic = false;
                            var mtl = maskTemplate.length;
                            maskTemplate[mtl - 1] = maskTemplate[mtl - 1] + "</span>";
                            maskTemplate.push(entry);
                        } else maskTemplate.push(entry);
                    }
                    function setCaret() {
                        if (document.activeElement === input) {
                            maskTemplate.splice(caretPos.begin, 0, caretPos.begin === caretPos.end || caretPos.end > getMaskSet().maskLength ? '<mark class="im-caret" style="border-right-width: 1px;border-right-style: solid;">' : '<mark class="im-caret-select">');
                            maskTemplate.splice(caretPos.end + 1, 0, "</mark>");
                        }
                    }
                    if (colorMask !== undefined) {
                        var buffer = getBuffer();
                        if (caretPos === undefined) {
                            caretPos = caret(input);
                        } else if (caretPos.begin === undefined) {
                            caretPos = {
                                begin: caretPos,
                                end: caretPos
                            };
                        }
                        if (clear !== true) {
                            var lvp = getLastValidPosition();
                            do {
                                if (getMaskSet().validPositions[pos]) {
                                    testPos = getMaskSet().validPositions[pos];
                                    test = testPos.match;
                                    ndxIntlzr = testPos.locator.slice();
                                    setEntry(buffer[pos]);
                                } else {
                                    testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
                                    test = testPos.match;
                                    ndxIntlzr = testPos.locator.slice();
                                    if (opts.jitMasking === false || pos < lvp || typeof opts.jitMasking === "number" && isFinite(opts.jitMasking) && opts.jitMasking > pos) {
                                        setEntry(getPlaceholder(pos, test));
                                    } else isStatic = false;
                                }
                                pos++;
                            } while ((maxLength === undefined || pos < maxLength) && (test.fn !== null || test.def !== "") || lvp > pos || isStatic);
                            if (isStatic) setEntry();
                            setCaret();
                        }
                        var template = colorMask.getElementsByTagName("div")[0];
                        template.innerHTML = maskTemplate.join("");
                        input.inputmask.positionColorMask(input, template);
                    }
                }
                function mask(elem) {
                    function isElementTypeSupported(input, opts) {
                        function patchValueProperty(npt) {
                            var valueGet;
                            var valueSet;
                            function patchValhook(type) {
                                if ($.valHooks && ($.valHooks[type] === undefined || $.valHooks[type].inputmaskpatch !== true)) {
                                    var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function(elem) {
                                        return elem.value;
                                    };
                                    var valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function(elem, value) {
                                        elem.value = value;
                                        return elem;
                                    };
                                    $.valHooks[type] = {
                                        get: function get(elem) {
                                            if (elem.inputmask) {
                                                if (elem.inputmask.opts.autoUnmask) {
                                                    return elem.inputmask.unmaskedvalue();
                                                } else {
                                                    var result = valhookGet(elem);
                                                    return getLastValidPosition(undefined, undefined, elem.inputmask.maskset.validPositions) !== -1 || opts.nullable !== true ? result : "";
                                                }
                                            } else return valhookGet(elem);
                                        },
                                        set: function set(elem, value) {
                                            var $elem = $(elem), result;
                                            result = valhookSet(elem, value);
                                            if (elem.inputmask) {
                                                $elem.trigger("setvalue", [ value ]);
                                            }
                                            return result;
                                        },
                                        inputmaskpatch: true
                                    };
                                }
                            }
                            function getter() {
                                if (this.inputmask) {
                                    return this.inputmask.opts.autoUnmask ? this.inputmask.unmaskedvalue() : getLastValidPosition() !== -1 || opts.nullable !== true ? document.activeElement === this && opts.clearMaskOnLostFocus ? (isRTL ? clearOptionalTail(getBuffer().slice()).reverse() : clearOptionalTail(getBuffer().slice())).join("") : valueGet.call(this) : "";
                                } else return valueGet.call(this);
                            }
                            function setter(value) {
                                valueSet.call(this, value);
                                if (this.inputmask) {
                                    $(this).trigger("setvalue", [ value ]);
                                }
                            }
                            function installNativeValueSetFallback(npt) {
                                EventRuler.on(npt, "mouseenter", function(event) {
                                    var $input = $(this), input = this, value = input.inputmask._valueGet();
                                    if (value !== getBuffer().join("")) {
                                        $input.trigger("setvalue");
                                    }
                                });
                            }
                            if (!npt.inputmask.__valueGet) {
                                if (opts.noValuePatching !== true) {
                                    if (Object.getOwnPropertyDescriptor) {
                                        if (typeof Object.getPrototypeOf !== "function") {
                                            Object.getPrototypeOf = _typeof("test".__proto__) === "object" ? function(object) {
                                                return object.__proto__;
                                            } : function(object) {
                                                return object.constructor.prototype;
                                            };
                                        }
                                        var valueProperty = Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt), "value") : undefined;
                                        if (valueProperty && valueProperty.get && valueProperty.set) {
                                            valueGet = valueProperty.get;
                                            valueSet = valueProperty.set;
                                            Object.defineProperty(npt, "value", {
                                                get: getter,
                                                set: setter,
                                                configurable: true
                                            });
                                        } else if (npt.tagName !== "INPUT") {
                                            valueGet = function valueGet() {
                                                return this.textContent;
                                            };
                                            valueSet = function valueSet(value) {
                                                this.textContent = value;
                                            };
                                            Object.defineProperty(npt, "value", {
                                                get: getter,
                                                set: setter,
                                                configurable: true
                                            });
                                        }
                                    } else if (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 isRTL && overruleRTL !== true ? valueGet.call(this.el).split("").reverse().join("") : valueGet.call(this.el);
                                };
                                npt.inputmask._valueSet = function(value, overruleRTL) {
                                    valueSet.call(this.el, value === null || value === undefined ? "" : overruleRTL !== true && isRTL ? value.split("").reverse().join("") : value);
                                };
                                if (valueGet === undefined) {
                                    valueGet = function valueGet() {
                                        return this.value;
                                    };
                                    valueSet = function valueSet(value) {
                                        this.value = value;
                                    };
                                    patchValhook(npt.type);
                                    installNativeValueSetFallback(npt);
                                }
                            }
                        }
                        var elementType = input.getAttribute("type");
                        var isSupported = input.tagName === "INPUT" && $.inArray(elementType, opts.supportsInputType) !== -1 || input.isContentEditable || input.tagName === "TEXTAREA";
                        if (!isSupported) {
                            if (input.tagName === "INPUT") {
                                var el = document.createElement("input");
                                el.setAttribute("type", elementType);
                                isSupported = el.type === "text";
                                el = null;
                            } else isSupported = "partial";
                        }
                        if (isSupported !== false) {
                            patchValueProperty(input);
                        } else input.inputmask = undefined;
                        return isSupported;
                    }
                    EventRuler.off(elem);
                    var isSupported = isElementTypeSupported(elem, opts);
                    if (isSupported !== false) {
                        el = elem;
                        $el = $(el);
                        originalPlaceholder = el.placeholder;
                        maxLength = el !== undefined ? el.maxLength : undefined;
                        if (maxLength === -1) maxLength = undefined;
                        if (opts.colorMask === true) {
                            initializeColorMask(el);
                        }
                        if (mobile) {
                            if ("inputMode" in el) {
                                el.inputmode = opts.inputmode;
                                el.setAttribute("inputmode", opts.inputmode);
                            }
                            if (opts.disablePredictiveText === true) {
                                if ("autocorrect" in el) {
                                    el.autocorrect = false;
                                } else {
                                    if (opts.colorMask !== true) {
                                        initializeColorMask(el);
                                    }
                                    el.type = "password";
                                }
                            }
                        }
                        if (isSupported === true) {
                            el.setAttribute("im-insert", opts.insertMode);
                            EventRuler.on(el, "submit", EventHandlers.submitEvent);
                            EventRuler.on(el, "reset", EventHandlers.resetEvent);
                            EventRuler.on(el, "blur", EventHandlers.blurEvent);
                            EventRuler.on(el, "focus", EventHandlers.focusEvent);
                            if (opts.colorMask !== true) {
                                EventRuler.on(el, "click", EventHandlers.clickEvent);
                                EventRuler.on(el, "mouseleave", EventHandlers.mouseleaveEvent);
                                EventRuler.on(el, "mouseenter", EventHandlers.mouseenterEvent);
                            }
                            EventRuler.on(el, "paste", EventHandlers.pasteEvent);
                            EventRuler.on(el, "cut", EventHandlers.cutEvent);
                            EventRuler.on(el, "complete", opts.oncomplete);
                            EventRuler.on(el, "incomplete", opts.onincomplete);
                            EventRuler.on(el, "cleared", opts.oncleared);
                            if (!mobile && opts.inputEventOnly !== true) {
                                EventRuler.on(el, "keydown", EventHandlers.keydownEvent);
                                EventRuler.on(el, "keypress", EventHandlers.keypressEvent);
                            } else {
                                el.removeAttribute("maxLength");
                            }
                            EventRuler.on(el, "input", EventHandlers.inputFallBackEvent);
                            EventRuler.on(el, "beforeinput", EventHandlers.beforeInputEvent);
                        }
                        EventRuler.on(el, "setvalue", EventHandlers.setValueEvent);
                        undoValue = getBufferTemplate().join("");
                        if (el.inputmask._valueGet(true) !== "" || opts.clearMaskOnLostFocus === false || document.activeElement === el) {
                            var initialValue = $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, el.inputmask._valueGet(true), opts) || el.inputmask._valueGet(true) : el.inputmask._valueGet(true);
                            if (initialValue !== "") checkVal(el, true, false, initialValue.split(""));
                            var buffer = getBuffer().slice();
                            undoValue = buffer.join("");
                            if (isComplete(buffer) === false) {
                                if (opts.clearIncomplete) {
                                    resetMaskSet();
                                }
                            }
                            if (opts.clearMaskOnLostFocus && document.activeElement !== el) {
                                if (getLastValidPosition() === -1) {
                                    buffer = [];
                                } else {
                                    clearOptionalTail(buffer);
                                }
                            }
                            if (opts.clearMaskOnLostFocus === false || opts.showMaskOnFocus && document.activeElement === el || el.inputmask._valueGet(true) !== "") writeBuffer(el, buffer);
                            if (document.activeElement === el) {
                                caret(el, seekNext(getLastValidPosition()));
                            }
                        }
                    }
                }
                var valueBuffer;
                if (actionObj !== undefined) {
                    switch (actionObj.action) {
                      case "isComplete":
                        el = actionObj.el;
                        return isComplete(getBuffer());
    
                      case "unmaskedvalue":
                        if (el === undefined || actionObj.value !== undefined) {
                            valueBuffer = actionObj.value;
                            valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, valueBuffer, opts) || valueBuffer : valueBuffer).split("");
                            checkVal.call(this, undefined, false, false, valueBuffer);
                            if ($.isFunction(opts.onBeforeWrite)) opts.onBeforeWrite.call(inputmask, undefined, getBuffer(), 0, opts);
                        }
                        return unmaskedvalue(el);
    
                      case "mask":
                        mask(el);
                        break;
    
                      case "format":
                        valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, actionObj.value, opts) || actionObj.value : actionObj.value).split("");
                        checkVal.call(this, undefined, true, false, valueBuffer);
                        if (actionObj.metadata) {
                            return {
                                value: isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""),
                                metadata: maskScope.call(this, {
                                    action: "getmetadata"
                                }, maskset, opts)
                            };
                        }
                        return isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join("");
    
                      case "isValid":
                        if (actionObj.value) {
                            valueBuffer = actionObj.value.split("");
                            checkVal.call(this, undefined, true, true, valueBuffer);
                        } else {
                            actionObj.value = getBuffer().join("");
                        }
                        var buffer = getBuffer();
                        var rl = determineLastRequiredPosition(), lmib = buffer.length - 1;
                        for (;lmib > rl; lmib--) {
                            if (isMask(lmib)) break;
                        }
                        buffer.splice(rl, lmib + 1 - rl);
                        return isComplete(buffer) && actionObj.value === getBuffer().join("");
    
                      case "getemptymask":
                        return getBufferTemplate().join("");
    
                      case "remove":
                        if (el && el.inputmask) {
                            $.data(el, "_inputmask_opts", null);
                            $el = $(el);
                            el.inputmask._valueSet(opts.autoUnmask ? unmaskedvalue(el) : el.inputmask._valueGet(true));
                            EventRuler.off(el);
                            if (el.inputmask.colorMask) {
                                colorMask = el.inputmask.colorMask;
                                colorMask.removeChild(el);
                                colorMask.parentNode.insertBefore(el, colorMask);
                                colorMask.parentNode.removeChild(colorMask);
                            }
                            var valueProperty;
                            if (Object.getOwnPropertyDescriptor && Object.getPrototypeOf) {
                                valueProperty = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value");
                                if (valueProperty) {
                                    if (el.inputmask.__valueGet) {
                                        Object.defineProperty(el, "value", {
                                            get: el.inputmask.__valueGet,
                                            set: el.inputmask.__valueSet,
                                            configurable: true
                                        });
                                    }
                                }
                            } else if (document.__lookupGetter__ && el.__lookupGetter__("value")) {
                                if (el.inputmask.__valueGet) {
                                    el.__defineGetter__("value", el.inputmask.__valueGet);
                                    el.__defineSetter__("value", el.inputmask.__valueSet);
                                }
                            }
                            el.inputmask = undefined;
                        }
                        return el;
                        break;
    
                      case "getmetadata":
                        if ($.isArray(maskset.metadata)) {
                            var maskTarget = getMaskTemplate(true, 0, false).join("");
                            $.each(maskset.metadata, function(ndx, mtdt) {
                                if (mtdt.mask === maskTarget) {
                                    maskTarget = mtdt;
                                    return false;
                                }
                            });
                            return maskTarget;
                        }
                        return maskset.metadata;
                    }
                }
            }
            return Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        (function(factory) {
            if (true) {
                !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(4) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 
                __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
                __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
            } else {}
        })(function($) {
            return $;
        });
    }, function(module, exports) {
        module.exports = jQuery;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_RESULT__;
        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        if (true) !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
            return typeof window !== "undefined" ? window : new (eval("require('jsdom').JSDOM"))("").window;
        }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); else {}
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        (function(factory) {
            if (true) {
                !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 
                __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
                __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
            } else {}
        })(function(Inputmask) {
            var $ = Inputmask.dependencyLib;
            var 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);
                } ],
                hhh: [ "[0-9]+", Date.prototype.setHours, "hours", 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);
                } ],
                HHH: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ],
                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);
                } ],
                ss: [ "[0-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 getTokenizer(opts) {
                if (!opts.tokenizer) {
                    var tokens = [];
                    for (var ndx in formatCode) {
                        if (tokens.indexOf(ndx[0]) === -1) tokens.push(ndx[0]);
                    }
                    opts.tokenizer = "(" + tokens.join("+|") + ")+?|.";
                    opts.tokenizer = new RegExp(opts.tokenizer, "g");
                }
                return opts.tokenizer;
            }
            function isValidDate(dateParts, currentResult) {
                return !isFinite(dateParts.rawday) || dateParts.day == "29" && !isFinite(dateParts.rawyear) || new Date(dateParts.date.getFullYear(), isFinite(dateParts.rawmonth) ? dateParts.month : dateParts.date.getMonth() + 1, 0).getDate() >= dateParts.day ? currentResult : false;
            }
            function isDateInRange(dateParts, opts) {
                var result = true;
                if (opts.min) {
                    if (dateParts["rawyear"]) {
                        var rawYear = dateParts["rawyear"].replace(/[^0-9]/g, ""), minYear = opts.min.year.substr(0, rawYear.length);
                        result = minYear <= rawYear;
                    }
                    if (dateParts["year"] === dateParts["rawyear"]) {
                        if (opts.min.date.getTime() === opts.min.date.getTime()) {
                            result = opts.min.date.getTime() <= dateParts.date.getTime();
                        }
                    }
                }
                if (result && opts.max && opts.max.date.getTime() === opts.max.date.getTime()) {
                    result = opts.max.date.getTime() >= dateParts.date.getTime();
                }
                return result;
            }
            function parse(format, dateObjValue, opts, raw) {
                var mask = "", match;
                while (match = getTokenizer(opts).exec(format)) {
                    if (dateObjValue === undefined) {
                        if (formatCode[match[0]]) {
                            mask += "(" + formatCode[match[0]][0] + ")";
                        } else {
                            switch (match[0]) {
                              case "[":
                                mask += "(";
                                break;
    
                              case "]":
                                mask += ")?";
                                break;
    
                              default:
                                mask += Inputmask.escapeRegex(match[0]);
                            }
                        }
                    } else {
                        if (formatCode[match[0]]) {
                            if (raw !== true && formatCode[match[0]][3]) {
                                var getFn = formatCode[match[0]][3];
                                mask += getFn.call(dateObjValue.date);
                            } else if (formatCode[match[0]][2]) mask += dateObjValue["raw" + formatCode[match[0]][2]]; else mask += match[0];
                        } else mask += match[0];
                    }
                }
                return mask;
            }
            function pad(val, len) {
                val = String(val);
                len = len || 2;
                while (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, targetValidator;
                function extendProperty(value) {
                    var correctedValue = value.replace(/[^0-9]/g, "0");
                    if (correctedValue != value) {
                        var enteredPart = value.replace(/[^0-9]/g, ""), min = (opts.min && opts.min[targetProp] || value).toString(), max = (opts.max && opts.max[targetProp] || value).toString();
                        correctedValue = enteredPart + (enteredPart < min.slice(0, enteredPart.length) ? min.slice(enteredPart.length) : enteredPart > max.slice(0, enteredPart.length) ? max.slice(enteredPart.length) : correctedValue.toString().slice(enteredPart.length));
                    }
                    return correctedValue;
                }
                function setValue(dateObj, value, opts) {
                    dateObj[targetProp] = extendProperty(value);
                    dateObj["raw" + targetProp] = value;
                    if (dateOperation !== undefined) dateOperation.call(dateObj.date, targetProp == "month" ? parseInt(dateObj[targetProp]) - 1 : dateObj[targetProp]);
                }
                if (typeof mask === "string") {
                    while (match = getTokenizer(opts).exec(format)) {
                        var value = mask.slice(0, match[0].length);
                        if (formatCode.hasOwnProperty(match[0])) {
                            targetValidator = formatCode[match[0]][0];
                            targetProp = formatCode[match[0]][2];
                            dateOperation = formatCode[match[0]][1];
                            setValue(dateObj, value, opts);
                        }
                        mask = mask.slice(value.length);
                    }
                    return dateObj;
                } else if (mask && (typeof mask === "undefined" ? "undefined" : _typeof(mask)) === "object" && mask.hasOwnProperty("date")) {
                    return mask;
                }
                return undefined;
            }
            Inputmask.extendAliases({
                datetime: {
                    mask: function mask(opts) {
                        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, undefined, opts);
                        return null;
                    },
                    placeholder: "",
                    inputFormat: "isoDateTime",
                    displayFormat: undefined,
                    outputFormat: undefined,
                    min: null,
                    max: null,
                    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" ]
                    },
                    postValidation: function postValidation(buffer, pos, currentResult, opts) {
                        opts.min = analyseMask(opts.min, opts.inputFormat, opts);
                        opts.max = analyseMask(opts.max, opts.inputFormat, opts);
                        var result = currentResult, dateParts = analyseMask(buffer.join(""), opts.inputFormat, opts);
                        if (result && dateParts.date.getTime() === dateParts.date.getTime()) {
                            result = isValidDate(dateParts, result);
                            result = result && isDateInRange(dateParts, opts);
                        }
                        if (pos && result && currentResult.pos !== pos) {
                            return {
                                buffer: parse(opts.inputFormat, dateParts, opts),
                                refreshFromBuffer: {
                                    start: pos,
                                    end: currentResult.pos
                                }
                            };
                        }
                        return result;
                    },
                    onKeyDown: function onKeyDown(e, buffer, caretPos, opts) {
                        var input = this;
                        if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
                            var today = new Date(), match, date = "";
                            while (match = getTokenizer(opts).exec(opts.inputFormat)) {
                                if (match[0].charAt(0) === "d") {
                                    date += pad(today.getDate(), match[0].length);
                                } else if (match[0].charAt(0) === "m") {
                                    date += pad(today.getMonth() + 1, match[0].length);
                                } else if (match[0] === "yyyy") {
                                    date += today.getFullYear().toString();
                                } else if (match[0].charAt(0) === "y") {
                                    date += pad(today.getYear(), match[0].length);
                                }
                            }
                            input.inputmask._valueSet(date);
                            $(input).trigger("setvalue");
                        }
                    },
                    onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                        return parse(opts.outputFormat, analyseMask(maskedValue, opts.inputFormat, opts), opts, true);
                    },
                    casing: function casing(elem, test, pos, validPositions) {
                        if (test.nativeDef.indexOf("[ap]") == 0) return elem.toLowerCase();
                        if (test.nativeDef.indexOf("[AP]") == 0) return elem.toUpperCase();
                        return elem;
                    },
                    insertMode: false,
                    shiftPositions: false
                }
            });
            return Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        (function(factory) {
            if (true) {
                !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 
                __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
                __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
            } else {}
        })(function(Inputmask) {
            var $ = Inputmask.dependencyLib;
            function autoEscape(txt, opts) {
                var escapedTxt = "";
                for (var i = 0; i < txt.length; i++) {
                    if (Inputmask.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker.start === txt.charAt(i) || opts.optionalmarker.end === txt.charAt(i) || opts.quantifiermarker.start === txt.charAt(i) || opts.quantifiermarker.end === txt.charAt(i) || opts.groupmarker.start === txt.charAt(i) || opts.groupmarker.end === txt.charAt(i) || opts.alternatormarker === txt.charAt(i)) {
                        escapedTxt += "\\" + txt.charAt(i);
                    } else escapedTxt += txt.charAt(i);
                }
                return escapedTxt;
            }
            function alignDigits(buffer, digits, opts) {
                if (digits > 0) {
                    var radixPosition = $.inArray(opts.radixPoint, buffer);
                    if (radixPosition === -1) {
                        buffer.push(opts.radixPoint);
                        radixPosition = buffer.length - 1;
                    }
                    for (var i = 1; i <= digits; i++) {
                        buffer[radixPosition + i] = buffer[radixPosition + i] || "0";
                    }
                }
                return buffer;
            }
            Inputmask.extendAliases({
                numeric: {
                    mask: function mask(opts) {
                        if (opts.repeat !== 0 && isNaN(opts.integerDigits)) {
                            opts.integerDigits = opts.repeat;
                        }
                        opts.repeat = 0;
                        if (opts.groupSeparator === opts.radixPoint && opts.digits && opts.digits !== "0") {
                            if (opts.radixPoint === ".") {
                                opts.groupSeparator = ",";
                            } else if (opts.radixPoint === ",") {
                                opts.groupSeparator = ".";
                            } else opts.groupSeparator = "";
                        }
                        if (opts.groupSeparator === " ") {
                            opts.skipOptionalPartCharacter = undefined;
                        }
                        opts.autoGroup = opts.autoGroup && opts.groupSeparator !== "";
                        if (opts.autoGroup) {
                            if (typeof opts.groupSize == "string" && isFinite(opts.groupSize)) opts.groupSize = parseInt(opts.groupSize);
                            if (isFinite(opts.integerDigits)) {
                                var seps = Math.floor(opts.integerDigits / opts.groupSize);
                                var mod = opts.integerDigits % opts.groupSize;
                                opts.integerDigits = parseInt(opts.integerDigits) + (mod === 0 ? seps - 1 : seps);
                                if (opts.integerDigits < 1) {
                                    opts.integerDigits = "*";
                                }
                            }
                        }
                        if (opts.placeholder.length > 1) {
                            opts.placeholder = opts.placeholder.charAt(0);
                        }
                        if (opts.positionCaretOnClick === "radixFocus" && opts.placeholder === "" && opts.integerOptional === false) {
                            opts.positionCaretOnClick = "lvp";
                        }
                        opts.definitions[";"] = opts.definitions["~"];
                        opts.definitions[";"].definitionSymbol = "~";
                        if (opts.numericInput === true) {
                            opts.positionCaretOnClick = opts.positionCaretOnClick === "radixFocus" ? "lvp" : opts.positionCaretOnClick;
                            opts.digitsOptional = false;
                            if (isNaN(opts.digits)) opts.digits = 2;
                            opts.decimalProtect = false;
                        }
                        var mask = "[+]";
                        mask += autoEscape(opts.prefix, opts);
                        if (opts.integerOptional === true) {
                            mask += "~{1," + opts.integerDigits + "}";
                        } else mask += "~{" + opts.integerDigits + "}";
                        if (opts.digits !== undefined) {
                            var radixDef = opts.decimalProtect ? ":" : opts.radixPoint;
                            var dq = opts.digits.toString().split(",");
                            if (isFinite(dq[0]) && dq[1] && isFinite(dq[1])) {
                                mask += radixDef + ";{" + opts.digits + "}";
                            } else if (isNaN(opts.digits) || parseInt(opts.digits) > 0) {
                                if (opts.digitsOptional) {
                                    mask += "[" + radixDef + ";{1," + opts.digits + "}]";
                                } else mask += radixDef + ";{" + opts.digits + "}";
                            }
                        }
                        mask += autoEscape(opts.suffix, opts);
                        mask += "[-]";
                        opts.greedy = false;
                        return mask;
                    },
                    placeholder: "",
                    greedy: false,
                    digits: "*",
                    digitsOptional: true,
                    enforceDigitsOnBlur: false,
                    radixPoint: ".",
                    positionCaretOnClick: "radixFocus",
                    groupSize: 3,
                    groupSeparator: "",
                    autoGroup: false,
                    allowMinus: true,
                    negationSymbol: {
                        front: "-",
                        back: ""
                    },
                    integerDigits: "+",
                    integerOptional: true,
                    prefix: "",
                    suffix: "",
                    rightAlign: true,
                    decimalProtect: true,
                    min: null,
                    max: null,
                    step: 1,
                    insertMode: true,
                    autoUnmask: false,
                    unmaskAsNumber: false,
                    inputType: "text",
                    inputmode: "numeric",
                    preValidation: function preValidation(buffer, pos, c, isSelection, opts, maskset) {
                        if (c === "-" || c === opts.negationSymbol.front) {
                            if (opts.allowMinus !== true) return false;
                            opts.isNegative = opts.isNegative === undefined ? true : !opts.isNegative;
                            if (buffer.join("") === "") return true;
                            return {
                                caret: maskset.validPositions[pos] ? pos : undefined,
                                dopost: true
                            };
                        }
                        if (isSelection === false && c === opts.radixPoint && opts.digits !== undefined && (isNaN(opts.digits) || parseInt(opts.digits) > 0)) {
                            var radixPos = $.inArray(opts.radixPoint, buffer);
                            if (radixPos !== -1 && maskset.validPositions[radixPos] !== undefined) {
                                if (opts.numericInput === true) {
                                    return pos === radixPos;
                                }
                                return {
                                    caret: radixPos + 1
                                };
                            }
                        }
                        return true;
                    },
                    postValidation: function postValidation(buffer, pos, currentResult, opts) {
                        function buildPostMask(buffer, opts) {
                            var postMask = "";
                            postMask += "(" + opts.groupSeparator + "*{" + opts.groupSize + "}){*}";
                            if (opts.radixPoint !== "") {
                                var radixSplit = buffer.join("").split(opts.radixPoint);
                                if (radixSplit[1]) {
                                    postMask += opts.radixPoint + "*{" + radixSplit[1].match(/^\d*\??\d*/)[0].length + "}";
                                }
                            }
                            return postMask;
                        }
                        var suffix = opts.suffix.split(""), prefix = opts.prefix.split("");
                        if (currentResult.pos === undefined && currentResult.caret !== undefined && currentResult.dopost !== true) return currentResult;
                        var caretPos = currentResult.caret !== undefined ? currentResult.caret : currentResult.pos;
                        var maskedValue = buffer.slice();
                        if (opts.numericInput) {
                            caretPos = maskedValue.length - caretPos - 1;
                            maskedValue = maskedValue.reverse();
                        }
                        var charAtPos = maskedValue[caretPos];
                        if (charAtPos === opts.groupSeparator) {
                            caretPos += 1;
                            charAtPos = maskedValue[caretPos];
                        }
                        if (caretPos === maskedValue.length - opts.suffix.length - 1 && charAtPos === opts.radixPoint) return currentResult;
                        if (charAtPos !== undefined) {
                            if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) {
                                maskedValue[caretPos] = "?";
                                if (opts.prefix.length > 0 && caretPos >= (opts.isNegative === false ? 1 : 0) && caretPos < opts.prefix.length - 1 + (opts.isNegative === false ? 1 : 0)) {
                                    prefix[caretPos - (opts.isNegative === false ? 1 : 0)] = "?";
                                } else if (opts.suffix.length > 0 && caretPos >= maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0)) {
                                    suffix[caretPos - (maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0))] = "?";
                                }
                            }
                        }
                        prefix = prefix.join("");
                        suffix = suffix.join("");
                        var processValue = maskedValue.join("").replace(prefix, "");
                        processValue = processValue.replace(suffix, "");
                        processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
                        processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "");
                        processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
                        if (isNaN(opts.placeholder)) {
                            processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.placeholder), "g"), "");
                        }
                        if (processValue.length > 1 && processValue.indexOf(opts.radixPoint) !== 1) {
                            if (charAtPos === "0") {
                                processValue = processValue.replace(/^\?/g, "");
                            }
                            processValue = processValue.replace(/^0/g, "");
                        }
                        if (processValue.charAt(0) === opts.radixPoint && opts.radixPoint !== "" && opts.numericInput !== true) {
                            processValue = "0" + processValue;
                        }
                        if (processValue !== "") {
                            processValue = processValue.split("");
                            if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && isFinite(opts.digits)) {
                                var radixPosition = $.inArray(opts.radixPoint, processValue);
                                var rpb = $.inArray(opts.radixPoint, maskedValue);
                                if (radixPosition === -1) {
                                    processValue.push(opts.radixPoint);
                                    radixPosition = processValue.length - 1;
                                }
                                for (var i = 1; i <= opts.digits; i++) {
                                    if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && (processValue[radixPosition + i] === undefined || processValue[radixPosition + i] === opts.placeholder.charAt(0))) {
                                        processValue[radixPosition + i] = currentResult.placeholder || opts.placeholder.charAt(0);
                                    } else if (rpb !== -1 && maskedValue[rpb + i] !== undefined) {
                                        processValue[radixPosition + i] = processValue[radixPosition + i] || maskedValue[rpb + i];
                                    }
                                }
                            }
                            if (opts.autoGroup === true && opts.groupSeparator !== "" && (charAtPos !== opts.radixPoint || currentResult.pos !== undefined || currentResult.dopost)) {
                                var addRadix = processValue[processValue.length - 1] === opts.radixPoint && currentResult.c === opts.radixPoint;
                                processValue = Inputmask(buildPostMask(processValue, opts), {
                                    numericInput: true,
                                    jitMasking: true,
                                    definitions: {
                                        "*": {
                                            validator: "[0-9?]",
                                            cardinality: 1
                                        }
                                    }
                                }).format(processValue.join(""));
                                if (addRadix) processValue += opts.radixPoint;
                                if (processValue.charAt(0) === opts.groupSeparator) {
                                    processValue.substr(1);
                                }
                            } else processValue = processValue.join("");
                        }
                        if (opts.isNegative && currentResult.event === "blur") {
                            opts.isNegative = processValue !== "0";
                        }
                        processValue = prefix + processValue;
                        processValue += suffix;
                        if (opts.isNegative) {
                            processValue = opts.negationSymbol.front + processValue;
                            processValue += opts.negationSymbol.back;
                        }
                        processValue = processValue.split("");
                        if (charAtPos !== undefined) {
                            if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) {
                                caretPos = $.inArray("?", processValue);
                                if (caretPos > -1) {
                                    processValue[caretPos] = charAtPos;
                                } else caretPos = currentResult.caret || 0;
                            } else if (charAtPos === opts.radixPoint || charAtPos === opts.negationSymbol.front || charAtPos === opts.negationSymbol.back) {
                                var newCaretPos = $.inArray(charAtPos, processValue);
                                if (newCaretPos !== -1) caretPos = newCaretPos;
                            }
                        }
                        if (opts.numericInput) {
                            caretPos = processValue.length - caretPos - 1;
                            processValue = processValue.reverse();
                        }
                        var rslt = {
                            caret: (charAtPos === undefined || currentResult.pos !== undefined) && caretPos !== undefined ? caretPos + (opts.numericInput ? -1 : 1) : caretPos,
                            buffer: processValue,
                            refreshFromBuffer: currentResult.dopost || buffer.join("") !== processValue.join("")
                        };
                        return rslt.refreshFromBuffer ? rslt : currentResult;
                    },
                    onBeforeWrite: function onBeforeWrite(e, buffer, caretPos, opts) {
                        function parseMinMaxOptions(opts) {
                            if (opts.parseMinMaxOptions === undefined) {
                                if (opts.min !== null) {
                                    opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
                                    if (opts.radixPoint === ",") opts.min = opts.min.replace(opts.radixPoint, ".");
                                    opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN;
                                    if (isNaN(opts.min)) opts.min = Number.MIN_VALUE;
                                }
                                if (opts.max !== null) {
                                    opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
                                    if (opts.radixPoint === ",") opts.max = opts.max.replace(opts.radixPoint, ".");
                                    opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN;
                                    if (isNaN(opts.max)) opts.max = Number.MAX_VALUE;
                                }
                                opts.parseMinMaxOptions = "done";
                            }
                        }
                        if (e) {
                            switch (e.type) {
                              case "keydown":
                                return opts.postValidation(buffer, caretPos, {
                                    caret: caretPos,
                                    dopost: true
                                }, opts);
    
                              case "blur":
                              case "checkval":
                                var unmasked;
                                parseMinMaxOptions(opts);
                                if (opts.min !== null || opts.max !== null) {
                                    unmasked = opts.onUnMask(buffer.join(""), undefined, $.extend({}, opts, {
                                        unmaskAsNumber: true
                                    }));
                                    if (opts.min !== null && unmasked < opts.min) {
                                        opts.isNegative = opts.min < 0;
                                        return opts.postValidation(opts.min.toString().replace(".", opts.radixPoint).split(""), caretPos, {
                                            caret: caretPos,
                                            dopost: true,
                                            placeholder: "0"
                                        }, opts);
                                    } else if (opts.max !== null && unmasked > opts.max) {
                                        opts.isNegative = opts.max < 0;
                                        return opts.postValidation(opts.max.toString().replace(".", opts.radixPoint).split(""), caretPos, {
                                            caret: caretPos,
                                            dopost: true,
                                            placeholder: "0"
                                        }, opts);
                                    }
                                }
                                return opts.postValidation(buffer, caretPos, {
                                    caret: caretPos,
                                    placeholder: "0",
                                    event: "blur"
                                }, opts);
    
                              case "_checkval":
                                return {
                                    caret: caretPos
                                };
    
                              default:
                                break;
                            }
                        }
                    },
                    regex: {
                        integerPart: function integerPart(opts, emptyCheck) {
                            return emptyCheck ? new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?") : new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+");
                        },
                        integerNPart: function integerNPart(opts) {
                            return new RegExp("[\\d" + Inputmask.escapeRegex(opts.groupSeparator) + Inputmask.escapeRegex(opts.placeholder.charAt(0)) + "]+");
                        }
                    },
                    definitions: {
                        "~": {
                            validator: function validator(chrs, maskset, pos, strict, opts, isSelection) {
                                var isValid, l;
                                if (chrs === "k" || chrs === "m") {
                                    isValid = {
                                        insert: [],
                                        c: 0
                                    };
                                    for (var i = 0, l = chrs === "k" ? 2 : 5; i < l; i++) {
                                        isValid.insert.push({
                                            pos: pos + i,
                                            c: 0
                                        });
                                    }
                                    isValid.pos = pos + l;
                                    return isValid;
                                }
                                isValid = strict ? new RegExp("[0-9" + Inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs);
                                if (isValid === true) {
                                    if (opts.numericInput !== true && maskset.validPositions[pos] !== undefined && maskset.validPositions[pos].match.def === "~" && !isSelection) {
                                        var processValue = maskset.buffer.join("");
                                        processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "");
                                        processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
                                        var pvRadixSplit = processValue.split(opts.radixPoint);
                                        if (pvRadixSplit.length > 1) {
                                            pvRadixSplit[1] = pvRadixSplit[1].replace(/0/g, opts.placeholder.charAt(0));
                                        }
                                        if (pvRadixSplit[0] === "0") {
                                            pvRadixSplit[0] = pvRadixSplit[0].replace(/0/g, opts.placeholder.charAt(0));
                                        }
                                        processValue = pvRadixSplit[0] + opts.radixPoint + pvRadixSplit[1] || "";
                                        var bufferTemplate = maskset._buffer.join("");
                                        if (processValue === opts.radixPoint) {
                                            processValue = bufferTemplate;
                                        }
                                        while (processValue.match(Inputmask.escapeRegex(bufferTemplate) + "$") === null) {
                                            bufferTemplate = bufferTemplate.slice(1);
                                        }
                                        processValue = processValue.replace(bufferTemplate, "");
                                        processValue = processValue.split("");
                                        if (processValue[pos] === undefined) {
                                            isValid = {
                                                pos: pos,
                                                remove: pos
                                            };
                                        } else {
                                            isValid = {
                                                pos: pos
                                            };
                                        }
                                    }
                                } else if (!strict && chrs === opts.radixPoint && maskset.validPositions[pos - 1] === undefined) {
                                    isValid = {
                                        insert: {
                                            pos: pos,
                                            c: 0
                                        },
                                        pos: pos + 1
                                    };
                                }
                                return isValid;
                            },
                            cardinality: 1
                        },
                        "+": {
                            validator: function validator(chrs, maskset, pos, strict, opts) {
                                return opts.allowMinus && (chrs === "-" || chrs === opts.negationSymbol.front);
                            },
                            cardinality: 1,
                            placeholder: ""
                        },
                        "-": {
                            validator: function validator(chrs, maskset, pos, strict, opts) {
                                return opts.allowMinus && chrs === opts.negationSymbol.back;
                            },
                            cardinality: 1,
                            placeholder: ""
                        },
                        ":": {
                            validator: function validator(chrs, maskset, pos, strict, opts) {
                                var radix = "[" + Inputmask.escapeRegex(opts.radixPoint) + "]";
                                var isValid = new RegExp(radix).test(chrs);
                                if (isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder === opts.radixPoint) {
                                    isValid = {
                                        caret: pos + 1
                                    };
                                }
                                return isValid;
                            },
                            cardinality: 1,
                            placeholder: function placeholder(opts) {
                                return opts.radixPoint;
                            }
                        }
                    },
                    onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                        if (unmaskedValue === "" && opts.nullable === true) {
                            return unmaskedValue;
                        }
                        var processValue = maskedValue.replace(opts.prefix, "");
                        processValue = processValue.replace(opts.suffix, "");
                        processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
                        if (opts.placeholder.charAt(0) !== "") {
                            processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0");
                        }
                        if (opts.unmaskAsNumber) {
                            if (opts.radixPoint !== "" && processValue.indexOf(opts.radixPoint) !== -1) processValue = processValue.replace(Inputmask.escapeRegex.call(this, opts.radixPoint), ".");
                            processValue = processValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-");
                            processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
                            return Number(processValue);
                        }
                        return processValue;
                    },
                    isComplete: function isComplete(buffer, opts) {
                        var maskedValue = (opts.numericInput ? buffer.slice().reverse() : buffer).join("");
                        maskedValue = maskedValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-");
                        maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
                        maskedValue = maskedValue.replace(opts.prefix, "");
                        maskedValue = maskedValue.replace(opts.suffix, "");
                        maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator) + "([0-9]{3})", "g"), "$1");
                        if (opts.radixPoint === ",") maskedValue = maskedValue.replace(Inputmask.escapeRegex(opts.radixPoint), ".");
                        return isFinite(maskedValue);
                    },
                    onBeforeMask: function onBeforeMask(initialValue, opts) {
                        opts.isNegative = undefined;
                        var radixPoint = opts.radixPoint || ",";
                        if ((typeof initialValue == "number" || opts.inputType === "number") && radixPoint !== "") {
                            initialValue = initialValue.toString().replace(".", radixPoint);
                        }
                        var valueParts = initialValue.split(radixPoint), integerPart = valueParts[0].replace(/[^\-0-9]/g, ""), decimalPart = valueParts.length > 1 ? valueParts[1].replace(/[^0-9]/g, "") : "";
                        initialValue = integerPart + (decimalPart !== "" ? radixPoint + decimalPart : decimalPart);
                        var digits = 0;
                        if (radixPoint !== "") {
                            digits = decimalPart.length;
                            if (decimalPart !== "") {
                                var digitsFactor = Math.pow(10, digits || 1);
                                if (isFinite(opts.digits)) {
                                    digits = parseInt(opts.digits);
                                    digitsFactor = Math.pow(10, digits);
                                }
                                initialValue = initialValue.replace(Inputmask.escapeRegex(radixPoint), ".");
                                if (isFinite(initialValue)) initialValue = Math.round(parseFloat(initialValue) * digitsFactor) / digitsFactor;
                                initialValue = initialValue.toString().replace(".", radixPoint);
                            }
                        }
                        if (opts.digits === 0 && initialValue.indexOf(Inputmask.escapeRegex(radixPoint)) !== -1) {
                            initialValue = initialValue.substring(0, initialValue.indexOf(Inputmask.escapeRegex(radixPoint)));
                        }
                        return alignDigits(initialValue.toString().split(""), digits, opts).join("");
                    },
                    onKeyDown: function onKeyDown(e, buffer, caretPos, opts) {
                        var $input = $(this);
                        if (e.ctrlKey) {
                            switch (e.keyCode) {
                              case Inputmask.keyCode.UP:
                                $input.val(parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step));
                                $input.trigger("setvalue");
                                break;
    
                              case Inputmask.keyCode.DOWN:
                                $input.val(parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step));
                                $input.trigger("setvalue");
                                break;
                            }
                        }
                    }
                },
                currency: {
                    prefix: "$ ",
                    groupSeparator: ",",
                    alias: "numeric",
                    placeholder: "0",
                    autoGroup: true,
                    digits: 2,
                    digitsOptional: false,
                    clearMaskOnLostFocus: false
                },
                decimal: {
                    alias: "numeric"
                },
                integer: {
                    alias: "numeric",
                    digits: 0,
                    radixPoint: ""
                },
                percentage: {
                    alias: "numeric",
                    digits: 2,
                    digitsOptional: true,
                    radixPoint: ".",
                    placeholder: "0",
                    autoGroup: false,
                    min: 0,
                    max: 100,
                    suffix: " %",
                    allowMinus: false
                }
            });
            return Inputmask;
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
            return typeof obj;
        } : function(obj) {
            return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
        (function(factory) {
            if (true) {
                !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(4), __webpack_require__(2) ], 
                __WEBPACK_AMD_DEFINE_FACTORY__ = factory, __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
                __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
            } else {}
        })(function($, Inputmask) {
            if ($.fn.inputmask === undefined) {
                $.fn.inputmask = function(fn, options) {
                    var nptmask, input = this[0];
                    if (options === undefined) options = {};
                    if (typeof fn === "string") {
                        switch (fn) {
                          case "unmaskedvalue":
                            return input && input.inputmask ? input.inputmask.unmaskedvalue() : $(input).val();
    
                          case "remove":
                            return this.each(function() {
                                if (this.inputmask) this.inputmask.remove();
                            });
    
                          case "getemptymask":
                            return input && input.inputmask ? input.inputmask.getemptymask() : "";
    
                          case "hasMaskedValue":
                            return input && input.inputmask ? input.inputmask.hasMaskedValue() : false;
    
                          case "isComplete":
                            return input && input.inputmask ? input.inputmask.isComplete() : true;
    
                          case "getmetadata":
                            return input && input.inputmask ? input.inputmask.getmetadata() : undefined;
    
                          case "setvalue":
                            Inputmask.setValue(input, options);
                            break;
    
                          case "option":
                            if (typeof options === "string") {
                                if (input && input.inputmask !== undefined) {
                                    return input.inputmask.option(options);
                                }
                            } else {
                                return this.each(function() {
                                    if (this.inputmask !== undefined) {
                                        return this.inputmask.option(options);
                                    }
                                });
                            }
                            break;
    
                          default:
                            options.alias = fn;
                            nptmask = new Inputmask(options);
                            return this.each(function() {
                                nptmask.mask(this);
                            });
                        }
                    } else if (Array.isArray(fn)) {
                        options.alias = fn;
                        nptmask = new Inputmask(options);
                        return this.each(function() {
                            nptmask.mask(this);
                        });
                    } else if ((typeof fn === "undefined" ? "undefined" : _typeof(fn)) == "object") {
                        nptmask = new Inputmask(fn);
                        if (fn.mask === undefined && fn.alias === undefined) {
                            return this.each(function() {
                                if (this.inputmask !== undefined) {
                                    return this.inputmask.option(fn);
                                } else nptmask.mask(this);
                            });
                        } else {
                            return this.each(function() {
                                nptmask.mask(this);
                            });
                        }
                    } else if (fn === undefined) {
                        return this.each(function() {
                            nptmask = new Inputmask(options);
                            nptmask.mask(this);
                        });
                    }
                };
            }
            return $.fn.inputmask;
        });
    } ]);
    ( 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 defineMustache(global,factory){if(typeof exports==="object"&&exports&&typeof exports.nodeName!=="string"){factory(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],factory)}else{global.Mustache={};factory(global.Mustache)}})(this,function mustacheFactory(mustache){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.cache={}}Writer.prototype.clearCache=function clearCache(){this.cache={}};Writer.prototype.parse=function parse(template,tags){var cache=this.cache;var cacheKey=template+":"+(tags||mustache.tags).join(":");var tokens=cache[cacheKey];if(tokens==null)tokens=cache[cacheKey]=parseTemplate(template,tags);return tokens};Writer.prototype.render=function render(template,view,partials,tags){var tokens=this.parse(template,tags);var context=view instanceof Context?view:new Context(view);return this.renderTokens(tokens,context,partials,template,tags)};Writer.prototype.renderTokens=function renderTokens(tokens,context,partials,originalTemplate,tags){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);else if(symbol==="^")value=this.renderInverted(token,context,partials,originalTemplate);else if(symbol===">")value=this.renderPartial(token,context,partials,tags);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials)}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)}}else if(typeof value==="object"||typeof value==="string"||typeof value==="number"){buffer+=this.renderTokens(token[4],context.push(value),partials,originalTemplate)}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)}return buffer};Writer.prototype.renderInverted=function renderInverted(token,context,partials,originalTemplate){var value=context.lookup(token[1]);if(!value||isArray(value)&&value.length===0)return this.renderTokens(token[4],context,partials,originalTemplate)};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,tags){if(!partials)return;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)}return this.renderTokens(this.parse(indentedValue,tags),context,partials,indentedValue)}};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){var value=context.lookup(token[1]);if(value!=null)return mustache.escape(value)};Writer.prototype.rawValue=function rawValue(token){return token[1]};mustache.name="mustache.js";mustache.version="3.1.0";mustache.tags=["{{","}}"];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,tags){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,tags)};mustache.to_html=function to_html(template,view,partials,send){var result=mustache.render(template,view,partials);if(isFunction(send)){send(result)}else{return result}};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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInByZXR0aWZ5LmpzIiwibW9tZW50LXdpdGgtbG9jYWxlcy5qcyIsIm1vbWVudC10aW1lem9uZS5taW4uanMiLCJ0ZW1wdXNkb21pbnVzLWNvcmUuanMiLCJ0ZW1wdXNkb21pbnVzLWJvb3RzdHJhcC00LmpzIiwianF1ZXJ5LmlucHV0bWFzay5idW5kbGUuanMiLCJ2ZXJzaW9uLmpzIiwicG9zaXRpb24uanMiLCJzaG93ZG93bi5qcyIsIm1hcmtkb3duLmpzIiwidG8tbWFya2Rvd24uanMiLCJib290c3RyYXAtbWFya2Rvd24uanMiLCJib290c3RyYXAtbWFya2Rvd24uYXIuanMiLCJib290c3RyYXAtbWFya2Rvd24uY3MuanMiLCJib290c3RyYXAtbWFya2Rvd24uZGEuanMiLCJib290c3RyYXAtbWFya2Rvd24uZGUuanMiLCJib290c3RyYXAtbWFya2Rvd24uZXMuanMiLCJib290c3RyYXAtbWFya2Rvd24uZmEuanMiLCJib290c3RyYXAtbWFya2Rvd24uZnIuanMiLCJib290c3RyYXAtbWFya2Rvd24uamEuanMiLCJib290c3RyYXAtbWFya2Rvd24ua3IuanMiLCJib290c3RyYXAtbWFya2Rvd24ubmIuanMiLCJib290c3RyYXAtbWFya2Rvd24ubmwuanMiLCJib290c3RyYXAtbWFya2Rvd24ucGwuanMiLCJib290c3RyYXAtbWFya2Rvd24uc2wuanMiLCJib290c3RyYXAtbWFya2Rvd24uc3YuanMiLCJib290c3RyYXAtbWFya2Rvd24udHIuanMiLCJib290c3RyYXAtbWFya2Rvd24uemguanMiLCJtdXN0YWNoZS5taW4uanMiLCJ0cml2aWFsLWNvbXBvbmVudHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDdm5EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM3NmNBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN0Z0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMzdEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzF4SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDbGZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN2aEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDN3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNweEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM5MkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2hDQTtBQUNBO0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImJ1dHRlcmZhY2VzLXRoaXJkLXBhcnR5LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChDKSAyMDA2IEdvb2dsZSBJbmMuXG4vL1xuLy8gTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbi8vIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbi8vIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuLy9cbi8vICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4vL1xuLy8gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuLy8gZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuLy8gV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4vLyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4vLyBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXdcbiAqIHNvbWUgZnVuY3Rpb25zIGZvciBicm93c2VyLXNpZGUgcHJldHR5IHByaW50aW5nIG9mIGNvZGUgY29udGFpbmVkIGluIGh0bWwuXG4gKlxuICogPHA+XG4gKiBGb3IgYSBmYWlybHkgY29tcHJlaGVuc2l2ZSBzZXQgb2YgbGFuZ3VhZ2VzIHNlZSB0aGVcbiAqIDxhIGhyZWY9XCJodHRwOi8vZ29vZ2xlLWNvZGUtcHJldHRpZnkuZ29vZ2xlY29kZS5jb20vc3ZuL3RydW5rL1JFQURNRS5odG1sI2xhbmdzXCI+UkVBRE1FPC9hPlxuICogZmlsZSB0aGF0IGNhbWUgd2l0aCB0aGlzIHNvdXJjZS4gIEF0IGEgbWluaW11bSwgdGhlIGxleGVyIHNob3VsZCB3b3JrIG9uIGFcbiAqIG51bWJlciBvZiBsYW5ndWFnZXMgaW5jbHVkaW5nIEMgYW5kIGZyaWVuZHMsIEphdmEsIFB5dGhvbiwgQmFzaCwgU1FMLCBIVE1MLFxuICogWE1MLCBDU1MsIEphdmFzY3JpcHQsIGFuZCBNYWtlZmlsZXMuICBJdCB3b3JrcyBwYXNzYWJseSBvbiBSdWJ5LCBQSFAgYW5kIEF3a1xuICogYW5kIGEgc3Vic2V0IG9mIFBlcmwsIGJ1dCwgYmVjYXVzZSBvZiBjb21tZW50aW5nIGNvbnZlbnRpb25zLCBkb2Vzbid0IHdvcmsgb25cbiAqIFNtYWxsdGFsaywgTGlzcC1saWtlLCBvciBDQU1MLWxpa2UgbGFuZ3VhZ2VzIHdpdGhvdXQgYW4gZXhwbGljaXQgbGFuZyBjbGFzcy5cbiAqIDxwPlxuICogVXNhZ2U6IDxvbD5cbiAqIDxsaT4gaW5jbHVkZSB0aGlzIHNvdXJjZSBmaWxlIGluIGFuIGh0bWwgcGFnZSB2aWFcbiAqICAge0Bjb2RlIDxzY3JpcHQgdHlwZT1cInRleHQvamF2YXNjcmlwdFwiIHNyYz1cIi9wYXRoL3RvL3ByZXR0aWZ5LmpzXCI+PC9zY3JpcHQ+fVxuICogPGxpPiBkZWZpbmUgc3R5bGUgcnVsZXMuICBTZWUgdGhlIGV4YW1wbGUgcGFnZSBmb3IgZXhhbXBsZXMuXG4gKiA8bGk+IG1hcmsgdGhlIHtAY29kZSA8cHJlPn0gYW5kIHtAY29kZSA8Y29kZT59IHRhZ3MgaW4geW91ciBzb3VyY2Ugd2l0aFxuICogICAge0Bjb2RlIGNsYXNzPXByZXR0eXByaW50Ln1cbiAqICAgIFlvdSBjYW4gYWxzbyB1c2UgdGhlIChodG1sIGRlcHJlY2F0ZWQpIHtAY29kZSA8eG1wPn0gdGFnLCBidXQgdGhlIHByZXR0eVxuICogICAgcHJpbnRlciBuZWVkcyB0byBkbyBtb3JlIHN1YnN0YW50aWFsIERPTSBtYW5pcHVsYXRpb25zIHRvIHN1cHBvcnQgdGhhdCwgc29cbiAqICAgIHNvbWUgY3NzIHN0eWxlcyBtYXkgbm90IGJlIHByZXNlcnZlZC5cbiAqIDwvb2w+XG4gKiBUaGF0J3MgaXQuICBJIHdhbnRlZCB0byBrZWVwIHRoZSBBUEkgYXMgc2ltcGxlIGFzIHBvc3NpYmxlLCBzbyB0aGVyZSdzIG5vXG4gKiBuZWVkIHRvIHNwZWNpZnkgd2hpY2ggbGFuZ3VhZ2UgdGhlIGNvZGUgaXMgaW4sIGJ1dCBpZiB5b3Ugd2lzaCwgeW91IGNhbiBhZGRcbiAqIGFub3RoZXIgY2xhc3MgdG8gdGhlIHtAY29kZSA8cHJlPn0gb3Ige0Bjb2RlIDxjb2RlPn0gZWxlbWVudCB0byBzcGVjaWZ5IHRoZVxuICogbGFuZ3VhZ2UsIGFzIGluIHtAY29kZSA8cHJlIGNsYXNzPVwicHJldHR5cHJpbnQgbGFuZy1qYXZhXCI+fS4gIEFueSBjbGFzcyB0aGF0XG4gKiBzdGFydHMgd2l0aCBcImxhbmctXCIgZm9sbG93ZWQgYnkgYSBmaWxlIGV4dGVuc2lvbiwgc3BlY2lmaWVzIHRoZSBmaWxlIHR5cGUuXG4gKiBTZWUgdGhlIFwibGFuZy0qLmpzXCIgZmlsZXMgaW4gdGhpcyBkaXJlY3RvcnkgZm9yIGNvZGUgdGhhdCBpbXBsZW1lbnRzXG4gKiBwZXItbGFuZ3VhZ2UgZmlsZSBoYW5kbGVycy5cbiAqIDxwPlxuICogQ2hhbmdlIGxvZzo8YnI+XG4gKiBjYmV1c3QsIDIwMDYvMDgvMjJcbiAqIDxibG9ja3F1b3RlPlxuICogICBKYXZhIGFubm90YXRpb25zIChzdGFydCB3aXRoIFwiQFwiKSBhcmUgbm93IGNhcHR1cmVkIGFzIGxpdGVyYWxzIChcImxpdFwiKVxuICogPC9ibG9ja3F1b3RlPlxuICogQHJlcXVpcmVzIGNvbnNvbGVcbiAqL1xuXG4vLyBKU0xpbnQgZGVjbGFyYXRpb25zXG4vKmdsb2JhbCBjb25zb2xlLCBkb2N1bWVudCwgbmF2aWdhdG9yLCBzZXRUaW1lb3V0LCB3aW5kb3csIGRlZmluZSAqL1xuXG4vKiogQGRlZmluZSB7Ym9vbGVhbn0gKi9cbnZhciBJTl9HTE9CQUxfU0NPUEUgPSB0cnVlO1xuXG4vKipcbiAqIFNwbGl0IHtAY29kZSBwcmV0dHlQcmludH0gaW50byBtdWx0aXBsZSB0aW1lb3V0cyBzbyBhcyBub3QgdG8gaW50ZXJmZXJlIHdpdGhcbiAqIFVJIGV2ZW50cy5cbiAqIElmIHNldCB0byB7QGNvZGUgZmFsc2V9LCB7QGNvZGUgcHJldHR5UHJpbnQoKX0gaXMgc3luY2hyb25vdXMuXG4gKi9cbndpbmRvd1snUFJfU0hPVUxEX1VTRV9DT05USU5VQVRJT04nXSA9IHRydWU7XG5cbi8qKlxuICogUHJldHR5IHByaW50IGEgY2h1bmsgb2YgY29kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2VDb2RlSHRtbCBUaGUgSFRNTCB0byBwcmV0dHkgcHJpbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0X2xhbmdFeHRlbnNpb24gVGhlIGxhbmd1YWdlIG5hbWUgdG8gdXNlLlxuICogICAgIFR5cGljYWxseSwgYSBmaWxlbmFtZSBleHRlbnNpb24gbGlrZSAnY3BwJyBvciAnamF2YScuXG4gKiBAcGFyYW0ge251bWJlcnxib29sZWFufSBvcHRfbnVtYmVyTGluZXMgVHJ1ZSB0byBudW1iZXIgbGluZXMsXG4gKiAgICAgb3IgdGhlIDEtaW5kZXhlZCBudW1iZXIgb2YgdGhlIGZpcnN0IGxpbmUgaW4gc291cmNlQ29kZUh0bWwuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IGNvZGUgYXMgaHRtbCwgYnV0IHByZXR0aWVyXG4gKi9cbnZhciBwcmV0dHlQcmludE9uZTtcbi8qKlxuICogRmluZCBhbGwgdGhlIHtAY29kZSA8cHJlPn0gYW5kIHtAY29kZSA8Y29kZT59IHRhZ3MgaW4gdGhlIERPTSB3aXRoXG4gKiB7QGNvZGUgY2xhc3M9cHJldHR5cHJpbnR9IGFuZCBwcmV0dGlmeSB0aGVtLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG9wdF93aGVuRG9uZSBjYWxsZWQgd2hlbiBwcmV0dGlmeWluZyBpcyBkb25lLlxuICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MRG9jdW1lbnR9IG9wdF9yb290IGFuIGVsZW1lbnQgb3IgZG9jdW1lbnRcbiAqICAgY29udGFpbmluZyBhbGwgdGhlIGVsZW1lbnRzIHRvIHByZXR0eSBwcmludC5cbiAqICAgRGVmYXVsdHMgdG8ge0Bjb2RlIGRvY3VtZW50LmJvZHl9LlxuICovXG52YXIgcHJldHR5UHJpbnQ7XG5cblxuKGZ1bmN0aW9uICgpIHtcbiAgdmFyIHdpbiA9IHdpbmRvdztcbiAgLy8gS2V5d29yZCBsaXN0cyBmb3IgdmFyaW91cyBsYW5ndWFnZXMuXG4gIC8vIFdlIHVzZSB0aGluZ3MgdGhhdCBjb2VyY2UgdG8gc3RyaW5ncyB0byBtYWtlIHRoZW0gY29tcGFjdCB3aGVuIG1pbmlmaWVkXG4gIC8vIGFuZCB0byBkZWZlYXQgYWdncmVzc2l2ZSBvcHRpbWl6ZXJzIHRoYXQgZm9sZCBsYXJnZSBzdHJpbmcgY29uc3RhbnRzLlxuICB2YXIgRkxPV19DT05UUk9MX0tFWVdPUkRTID0gW1wiYnJlYWssY29udGludWUsZG8sZWxzZSxmb3IsaWYscmV0dXJuLHdoaWxlXCJdO1xuICB2YXIgQ19LRVlXT1JEUyA9IFtGTE9XX0NPTlRST0xfS0VZV09SRFMsXCJhdXRvLGNhc2UsY2hhcixjb25zdCxkZWZhdWx0LFwiICsgXG4gICAgICBcImRvdWJsZSxlbnVtLGV4dGVybixmbG9hdCxnb3RvLGlubGluZSxpbnQsbG9uZyxyZWdpc3RlcixzaG9ydCxzaWduZWQsXCIgK1xuICAgICAgXCJzaXplb2Ysc3RhdGljLHN0cnVjdCxzd2l0Y2gsdHlwZWRlZix1bmlvbix1bnNpZ25lZCx2b2lkLHZvbGF0aWxlXCJdO1xuICB2YXIgQ09NTU9OX0tFWVdPUkRTID0gW0NfS0VZV09SRFMsXCJjYXRjaCxjbGFzcyxkZWxldGUsZmFsc2UsaW1wb3J0LFwiICtcbiAgICAgIFwibmV3LG9wZXJhdG9yLHByaXZhdGUscHJvdGVjdGVkLHB1YmxpYyx0aGlzLHRocm93LHRydWUsdHJ5LHR5cGVvZlwiXTtcbiAgdmFyIENQUF9LRVlXT1JEUyA9IFtDT01NT05fS0VZV09SRFMsXCJhbGlnbm9mLGFsaWduX3VuaW9uLGFzbSxheGlvbSxib29sLFwiICtcbiAgICAgIFwiY29uY2VwdCxjb25jZXB0X21hcCxjb25zdF9jYXN0LGNvbnN0ZXhwcixkZWNsdHlwZSxkZWxlZ2F0ZSxcIiArXG4gICAgICBcImR5bmFtaWNfY2FzdCxleHBsaWNpdCxleHBvcnQsZnJpZW5kLGdlbmVyaWMsbGF0ZV9jaGVjayxcIiArXG4gICAgICBcIm11dGFibGUsbmFtZXNwYWNlLG51bGxwdHIscHJvcGVydHkscmVpbnRlcnByZXRfY2FzdCxzdGF0aWNfYXNzZXJ0LFwiICtcbiAgICAgIFwic3RhdGljX2Nhc3QsdGVtcGxhdGUsdHlwZWlkLHR5cGVuYW1lLHVzaW5nLHZpcnR1YWwsd2hlcmVcIl07XG4gIHZhciBKQVZBX0tFWVdPUkRTID0gW0NPTU1PTl9LRVlXT1JEUyxcbiAgICAgIFwiYWJzdHJhY3QsYXNzZXJ0LGJvb2xlYW4sYnl0ZSxleHRlbmRzLGZpbmFsLGZpbmFsbHksaW1wbGVtZW50cyxpbXBvcnQsXCIgK1xuICAgICAgXCJpbnN0YW5jZW9mLGludGVyZmFjZSxudWxsLG5hdGl2ZSxwYWNrYWdlLHN0cmljdGZwLHN1cGVyLHN5bmNocm9uaXplZCxcIiArXG4gICAgICBcInRocm93cyx0cmFuc2llbnRcIl07XG4gIHZhciBDU0hBUlBfS0VZV09SRFMgPSBbSkFWQV9LRVlXT1JEUyxcbiAgICAgIFwiYXMsYmFzZSxieSxjaGVja2VkLGRlY2ltYWwsZGVsZWdhdGUsZGVzY2VuZGluZyxkeW5hbWljLGV2ZW50LFwiICtcbiAgICAgIFwiZml4ZWQsZm9yZWFjaCxmcm9tLGdyb3VwLGltcGxpY2l0LGluLGludGVybmFsLGludG8saXMsbGV0LFwiICtcbiAgICAgIFwibG9jayxvYmplY3Qsb3V0LG92ZXJyaWRlLG9yZGVyYnkscGFyYW1zLHBhcnRpYWwscmVhZG9ubHkscmVmLHNieXRlLFwiICtcbiAgICAgIFwic2VhbGVkLHN0YWNrYWxsb2Msc3RyaW5nLHNlbGVjdCx1aW50LHVsb25nLHVuY2hlY2tlZCx1bnNhZmUsdXNob3J0LFwiICtcbiAgICAgIFwidmFyLHZpcnR1YWwsd2hlcmVcIl07XG4gIHZhciBDT0ZGRUVfS0VZV09SRFMgPSBcImFsbCxhbmQsYnksY2F0Y2gsY2xhc3MsZWxzZSxleHRlbmRzLGZhbHNlLGZpbmFsbHksXCIgK1xuICAgICAgXCJmb3IsaWYsaW4saXMsaXNudCxsb29wLG5ldyxubyxub3QsbnVsbCxvZixvZmYsb24sb3IscmV0dXJuLHN1cGVyLHRoZW4sXCIgK1xuICAgICAgXCJ0aHJvdyx0cnVlLHRyeSx1bmxlc3MsdW50aWwsd2hlbix3aGlsZSx5ZXNcIjtcbiAgdmFyIEpTQ1JJUFRfS0VZV09SRFMgPSBbQ09NTU9OX0tFWVdPUkRTLFxuICAgICAgXCJkZWJ1Z2dlcixldmFsLGV4cG9ydCxmdW5jdGlvbixnZXQsbnVsbCxzZXQsdW5kZWZpbmVkLHZhcix3aXRoLFwiICtcbiAgICAgIFwiSW5maW5pdHksTmFOXCJdO1xuICB2YXIgUEVSTF9LRVlXT1JEUyA9IFwiY2FsbGVyLGRlbGV0ZSxkaWUsZG8sZHVtcCxlbHNpZixldmFsLGV4aXQsZm9yZWFjaCxmb3IsXCIgK1xuICAgICAgXCJnb3RvLGlmLGltcG9ydCxsYXN0LGxvY2FsLG15LG5leHQsbm8sb3VyLHByaW50LHBhY2thZ2UscmVkbyxyZXF1aXJlLFwiICtcbiAgICAgIFwic3ViLHVuZGVmLHVubGVzcyx1bnRpbCx1c2Usd2FudGFycmF5LHdoaWxlLEJFR0lOLEVORFwiO1xuICB2YXIgUFlUSE9OX0tFWVdPUkRTID0gW0ZMT1dfQ09OVFJPTF9LRVlXT1JEUywgXCJhbmQsYXMsYXNzZXJ0LGNsYXNzLGRlZixkZWwsXCIgK1xuICAgICAgXCJlbGlmLGV4Y2VwdCxleGVjLGZpbmFsbHksZnJvbSxnbG9iYWwsaW1wb3J0LGluLGlzLGxhbWJkYSxcIiArXG4gICAgICBcIm5vbmxvY2FsLG5vdCxvcixwYXNzLHByaW50LHJhaXNlLHRyeSx3aXRoLHlpZWxkLFwiICtcbiAgICAgIFwiRmFsc2UsVHJ1ZSxOb25lXCJdO1xuICB2YXIgUlVCWV9LRVlXT1JEUyA9IFtGTE9XX0NPTlRST0xfS0VZV09SRFMsIFwiYWxpYXMsYW5kLGJlZ2luLGNhc2UsY2xhc3MsXCIgK1xuICAgICAgXCJkZWYsZGVmaW5lZCxlbHNpZixlbmQsZW5zdXJlLGZhbHNlLGluLG1vZHVsZSxuZXh0LG5pbCxub3Qsb3IscmVkbyxcIiArXG4gICAgICBcInJlc2N1ZSxyZXRyeSxzZWxmLHN1cGVyLHRoZW4sdHJ1ZSx1bmRlZix1bmxlc3MsdW50aWwsd2hlbix5aWVsZCxcIiArXG4gICAgICBcIkJFR0lOLEVORFwiXTtcbiAgIHZhciBSVVNUX0tFWVdPUkRTID0gW0ZMT1dfQ09OVFJPTF9LRVlXT1JEUywgXCJhcyxhc3NlcnQsY29uc3QsY29weSxkcm9wLFwiICtcbiAgICAgIFwiZW51bSxleHRlcm4sZmFpbCxmYWxzZSxmbixpbXBsLGxldCxsb2csbG9vcCxtYXRjaCxtb2QsbW92ZSxtdXQscHJpdixcIiArXG4gICAgICBcInB1YixwdXJlLHJlZixzZWxmLHN0YXRpYyxzdHJ1Y3QsdHJ1ZSx0cmFpdCx0eXBlLHVuc2FmZSx1c2VcIl07XG4gIHZhciBTSF9LRVlXT1JEUyA9IFtGTE9XX0NPTlRST0xfS0VZV09SRFMsIFwiY2FzZSxkb25lLGVsaWYsZXNhYyxldmFsLGZpLFwiICtcbiAgICAgIFwiZnVuY3Rpb24saW4sbG9jYWwsc2V0LHRoZW4sdW50aWxcIl07XG4gIHZhciBBTExfS0VZV09SRFMgPSBbXG4gICAgICBDUFBfS0VZV09SRFMsIENTSEFSUF9LRVlXT1JEUywgSlNDUklQVF9LRVlXT1JEUywgUEVSTF9LRVlXT1JEUyxcbiAgICAgIFBZVEhPTl9LRVlXT1JEUywgUlVCWV9LRVlXT1JEUywgU0hfS0VZV09SRFNdO1xuICB2YXIgQ19UWVBFUyA9IC9eKERJUnxGSUxFfHZlY3RvcnwoZGV8cHJpb3JpdHlfKT9xdWV1ZXxsaXN0fHN0YWNrfChjb25zdF8pP2l0ZXJhdG9yfChtdWx0aSk/KHNldHxtYXApfGJpdHNldHx1PyhpbnR8ZmxvYXQpXFxkKilcXGIvO1xuXG4gIC8vIHRva2VuIHN0eWxlIG5hbWVzLiAgY29ycmVzcG9uZCB0byBjc3MgY2xhc3Nlc1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGEgc3RyaW5nIGxpdGVyYWxcbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfU1RSSU5HID0gJ3N0cic7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYSBrZXl3b3JkXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX0tFWVdPUkQgPSAna3dkJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhIGNvbW1lbnRcbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfQ09NTUVOVCA9ICdjb20nO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGEgdHlwZVxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9UWVBFID0gJ3R5cCc7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYSBsaXRlcmFsIHZhbHVlLiAgZS5nLiAxLCBudWxsLCB0cnVlLlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9MSVRFUkFMID0gJ2xpdCc7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYSBwdW5jdHVhdGlvbiBzdHJpbmcuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX1BVTkNUVUFUSU9OID0gJ3B1bic7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgcGxhaW4gdGV4dC5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfUExBSU4gPSAncGxuJztcblxuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGFuIHNnbWwgdGFnLlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9UQUcgPSAndGFnJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBhIG1hcmt1cCBkZWNsYXJhdGlvbiBzdWNoIGFzIGEgRE9DVFlQRS5cbiAgICogQGNvbnN0XG4gICAqL1xuICB2YXIgUFJfREVDTEFSQVRJT04gPSAnZGVjJztcbiAgLyoqXG4gICAqIHRva2VuIHN0eWxlIGZvciBlbWJlZGRlZCBzb3VyY2UuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX1NPVVJDRSA9ICdzcmMnO1xuICAvKipcbiAgICogdG9rZW4gc3R5bGUgZm9yIGFuIHNnbWwgYXR0cmlidXRlIG5hbWUuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX0FUVFJJQl9OQU1FID0gJ2F0bic7XG4gIC8qKlxuICAgKiB0b2tlbiBzdHlsZSBmb3IgYW4gc2dtbCBhdHRyaWJ1dGUgdmFsdWUuXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFBSX0FUVFJJQl9WQUxVRSA9ICdhdHYnO1xuXG4gIC8qKlxuICAgKiBBIGNsYXNzIHRoYXQgaW5kaWNhdGVzIGEgc2VjdGlvbiBvZiBtYXJrdXAgdGhhdCBpcyBub3QgY29kZSwgZS5nLiB0byBhbGxvd1xuICAgKiBlbWJlZGRpbmcgb2YgbGluZSBudW1iZXJzIHdpdGhpbiBjb2RlIGxpc3RpbmdzLlxuICAgKiBAY29uc3RcbiAgICovXG4gIHZhciBQUl9OT0NPREUgPSAnbm9jb2RlJztcblxuICBcbiAgXG4gIC8qKlxuICAgKiBBIHNldCBvZiB0b2tlbnMgdGhhdCBjYW4gcHJlY2VkZSBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBsaXRlcmFsIGluXG4gICAqIGphdmFzY3JpcHRcbiAgICogaHR0cDovL3dlYi5hcmNoaXZlLm9yZy93ZWIvMjAwNzA3MTcxNDI1MTUvaHR0cDovL3d3dy5tb3ppbGxhLm9yZy9qcy9sYW5ndWFnZS9qczIwL3JhdGlvbmFsZS9zeW50YXguaHRtbFxuICAgKiBoYXMgdGhlIGZ1bGwgbGlzdCwgYnV0IEkndmUgcmVtb3ZlZCBvbmVzIHRoYXQgbWlnaHQgYmUgcHJvYmxlbWF0aWMgd2hlblxuICAgKiBzZWVuIGluIGxhbmd1YWdlcyB0aGF0IGRvbid0IHN1cHBvcnQgcmVndWxhciBleHByZXNzaW9uIGxpdGVyYWxzLlxuICAgKlxuICAgKiA8cD5TcGVjaWZpY2FsbHksIEkndmUgcmVtb3ZlZCBhbnkga2V5d29yZHMgdGhhdCBjYW4ndCBwcmVjZWRlIGEgcmVnZXhwXG4gICAqIGxpdGVyYWwgaW4gYSBzeW50YWN0aWNhbGx5IGxlZ2FsIGphdmFzY3JpcHQgcHJvZ3JhbSwgYW5kIEkndmUgcmVtb3ZlZCB0aGVcbiAgICogXCJpblwiIGtleXdvcmQgc2luY2UgaXQncyBub3QgYSBrZXl3b3JkIGluIG1hbnkgbGFuZ3VhZ2VzLCBhbmQgbWlnaHQgYmUgdXNlZFxuICAgKiBhcyBhIGNvdW50IG9mIGluY2hlcy5cbiAgICpcbiAgICogPHA+VGhlIGxpbmsgYWJvdmUgZG9lcyBub3QgYWNjdXJhdGVseSBkZXNjcmliZSBFY21hU2NyaXB0IHJ1bGVzIHNpbmNlXG4gICAqIGl0IGZhaWxzIHRvIGRpc3Rpbmd1aXNoIGJldHdlZW4gKGE9KysvYi9pKSBhbmQgKGErKy9iL2kpIGJ1dCBpdCB3b3Jrc1xuICAgKiB2ZXJ5IHdlbGwgaW4gcHJhY3RpY2UuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBjb25zdFxuICAgKi9cbiAgdmFyIFJFR0VYUF9QUkVDRURFUl9QQVRURVJOID0gJyg/Ol5eXFxcXC4/fFsrLV18WyE9XT0/PT98XFxcXCN8JT0/fCYmPz0/fFxcXFwofFxcXFwqPT98WytcXFxcLV09fC0+fFxcXFwvPT98Ojo/fDw8Pz0/fD4+Pz4/PT98LHw7fFxcXFw/fEB8XFxcXFt8fnx7fFxcXFxeXFxcXF4/PT98XFxcXHxcXFxcfD89P3xicmVha3xjYXNlfGNvbnRpbnVlfGRlbGV0ZXxkb3xlbHNlfGZpbmFsbHl8aW5zdGFuY2VvZnxyZXR1cm58dGhyb3d8dHJ5fHR5cGVvZilcXFxccyonO1xuICBcbiAgLy8gQ0FWRUFUOiB0aGlzIGRvZXMgbm90IHByb3Blcmx5IGhhbmRsZSB0aGUgY2FzZSB3aGVyZSBhIHJlZ3VsYXJcbiAgLy8gZXhwcmVzc2lvbiBpbW1lZGlhdGVseSBmb2xsb3dzIGFub3RoZXIgc2luY2UgYSByZWd1bGFyIGV4cHJlc3Npb24gbWF5XG4gIC8vIGhhdmUgZmxhZ3MgZm9yIGNhc2Utc2Vuc2l0aXZpdHkgYW5kIHRoZSBsaWtlLiAgSGF2aW5nIHJlZ2V4cCB0b2tlbnNcbiAgLy8gYWRqYWNlbnQgaXMgbm90IHZhbGlkIGluIGFueSBsYW5ndWFnZSBJJ20gYXdhcmUgb2YsIHNvIEknbSBwdW50aW5nLlxuICAvLyBUT0RPOiBtYXliZSBzdHlsZSBzcGVjaWFsIGNoYXJhY3RlcnMgaW5zaWRlIGEgcmVnZXhwIGFzIHB1bmN0dWF0aW9uLlxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIGdyb3VwIG9mIHtAbGluayBSZWdFeHB9cywgcmV0dXJucyBhIHtAY29kZSBSZWdFeHB9IHRoYXQgZ2xvYmFsbHlcbiAgICogbWF0Y2hlcyB0aGUgdW5pb24gb2YgdGhlIHNldHMgb2Ygc3RyaW5ncyBtYXRjaGVkIGJ5IHRoZSBpbnB1dCBSZWdFeHAuXG4gICAqIFNpbmNlIGl0IG1hdGNoZXMgZ2xvYmFsbHksIGlmIHRoZSBpbnB1dCBzdHJpbmdzIGhhdmUgYSBzdGFydC1vZi1pbnB1dFxuICAgKiBhbmNob3IgKC9eLi4uLyksIGl0IGlzIGlnbm9yZWQgZm9yIHRoZSBwdXJwb3NlcyBvZiB1bmlvbmluZy5cbiAgICogQHBhcmFtIHtBcnJheS48UmVnRXhwPn0gcmVnZXhzIG5vbiBtdWx0aWxpbmUsIG5vbi1nbG9iYWwgcmVnZXhzLlxuICAgKiBAcmV0dXJuIHtSZWdFeHB9IGEgZ2xvYmFsIHJlZ2V4LlxuICAgKi9cbiAgZnVuY3Rpb24gY29tYmluZVByZWZpeFBhdHRlcm5zKHJlZ2V4cykge1xuICAgIHZhciBjYXB0dXJlZEdyb3VwSW5kZXggPSAwO1xuICBcbiAgICB2YXIgbmVlZFRvRm9sZENhc2UgPSBmYWxzZTtcbiAgICB2YXIgaWdub3JlQ2FzZSA9IGZhbHNlO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gcmVnZXhzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgdmFyIHJlZ2V4ID0gcmVnZXhzW2ldO1xuICAgICAgaWYgKHJlZ2V4Lmlnbm9yZUNhc2UpIHtcbiAgICAgICAgaWdub3JlQ2FzZSA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKC9bYS16XS9pLnRlc3QocmVnZXguc291cmNlLnJlcGxhY2UoXG4gICAgICAgICAgICAgICAgICAgICAvXFxcXHVbMC05YS1mXXs0fXxcXFxceFswLTlhLWZdezJ9fFxcXFxbXnV4XS9naSwgJycpKSkge1xuICAgICAgICBuZWVkVG9Gb2xkQ2FzZSA9IHRydWU7XG4gICAgICAgIGlnbm9yZUNhc2UgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICBcbiAgICB2YXIgZXNjYXBlQ2hhclRvQ29kZVVuaXQgPSB7XG4gICAgICAnYic6IDgsXG4gICAgICAndCc6IDksXG4gICAgICAnbic6IDB4YSxcbiAgICAgICd2JzogMHhiLFxuICAgICAgJ2YnOiAweGMsXG4gICAgICAncic6IDB4ZFxuICAgIH07XG4gIFxuICAgIGZ1bmN0aW9uIGRlY29kZUVzY2FwZShjaGFyc2V0UGFydCkge1xuICAgICAgdmFyIGNjMCA9IGNoYXJzZXRQYXJ0LmNoYXJDb2RlQXQoMCk7XG4gICAgICBpZiAoY2MwICE9PSA5MiAvKiBcXFxcICovKSB7XG4gICAgICAgIHJldHVybiBjYzA7XG4gICAgICB9XG4gICAgICB2YXIgYzEgPSBjaGFyc2V0UGFydC5jaGFyQXQoMSk7XG4gICAgICBjYzAgPSBlc2NhcGVDaGFyVG9Db2RlVW5pdFtjMV07XG4gICAgICBpZiAoY2MwKSB7XG4gICAgICAgIHJldHVybiBjYzA7XG4gICAgICB9IGVsc2UgaWYgKCcwJyA8PSBjMSAmJiBjMSA8PSAnNycpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KGNoYXJzZXRQYXJ0LnN1YnN0cmluZygxKSwgOCk7XG4gICAgICB9IGVsc2UgaWYgKGMxID09PSAndScgfHwgYzEgPT09ICd4Jykge1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQoY2hhcnNldFBhcnQuc3Vic3RyaW5nKDIpLCAxNik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gY2hhcnNldFBhcnQuY2hhckNvZGVBdCgxKTtcbiAgICAgIH1cbiAgICB9XG4gIFxuICAgIGZ1bmN0aW9uIGVuY29kZUVzY2FwZShjaGFyQ29kZSkge1xuICAgICAgaWYgKGNoYXJDb2RlIDwgMHgyMCkge1xuICAgICAgICByZXR1cm4gKGNoYXJDb2RlIDwgMHgxMCA/ICdcXFxceDAnIDogJ1xcXFx4JykgKyBjaGFyQ29kZS50b1N0cmluZygxNik7XG4gICAgICB9XG4gICAgICB2YXIgY2ggPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoYXJDb2RlKTtcbiAgICAgIHJldHVybiAoY2ggPT09ICdcXFxcJyB8fCBjaCA9PT0gJy0nIHx8IGNoID09PSAnXScgfHwgY2ggPT09ICdeJylcbiAgICAgICAgICA/IFwiXFxcXFwiICsgY2ggOiBjaDtcbiAgICB9XG4gIFxuICAgIGZ1bmN0aW9uIGNhc2VGb2xkQ2hhcnNldChjaGFyU2V0KSB7XG4gICAgICB2YXIgY2hhcnNldFBhcnRzID0gY2hhclNldC5zdWJzdHJpbmcoMSwgY2hhclNldC5sZW5ndGggLSAxKS5tYXRjaChcbiAgICAgICAgICBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgICAnXFxcXFxcXFx1WzAtOUEtRmEtZl17NH0nXG4gICAgICAgICAgICAgICsgJ3xcXFxcXFxcXHhbMC05QS1GYS1mXXsyfSdcbiAgICAgICAgICAgICAgKyAnfFxcXFxcXFxcWzAtM11bMC03XXswLDJ9J1xuICAgICAgICAgICAgICArICd8XFxcXFxcXFxbMC03XXsxLDJ9J1xuICAgICAgICAgICAgICArICd8XFxcXFxcXFxbXFxcXHNcXFxcU10nXG4gICAgICAgICAgICAgICsgJ3wtJ1xuICAgICAgICAgICAgICArICd8W14tXFxcXFxcXFxdJyxcbiAgICAgICAgICAgICAgJ2cnKSk7XG4gICAgICB2YXIgcmFuZ2VzID0gW107XG4gICAgICB2YXIgaW52ZXJzZSA9IGNoYXJzZXRQYXJ0c1swXSA9PT0gJ14nO1xuICBcbiAgICAgIHZhciBvdXQgPSBbJ1snXTtcbiAgICAgIGlmIChpbnZlcnNlKSB7IG91dC5wdXNoKCdeJyk7IH1cbiAgXG4gICAgICBmb3IgKHZhciBpID0gaW52ZXJzZSA/IDEgOiAwLCBuID0gY2hhcnNldFBhcnRzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgICB2YXIgcCA9IGNoYXJzZXRQYXJ0c1tpXTtcbiAgICAgICAgaWYgKC9cXFxcW2Jkc3ddL2kudGVzdChwKSkgeyAgLy8gRG9uJ3QgbXVjayB3aXRoIG5hbWVkIGdyb3Vwcy5cbiAgICAgICAgICBvdXQucHVzaChwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgc3RhcnQgPSBkZWNvZGVFc2NhcGUocCk7XG4gICAgICAgICAgdmFyIGVuZDtcbiAgICAgICAgICBpZiAoaSArIDIgPCBuICYmICctJyA9PT0gY2hhcnNldFBhcnRzW2kgKyAxXSkge1xuICAgICAgICAgICAgZW5kID0gZGVjb2RlRXNjYXBlKGNoYXJzZXRQYXJ0c1tpICsgMl0pO1xuICAgICAgICAgICAgaSArPSAyO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbmQgPSBzdGFydDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmFuZ2VzLnB1c2goW3N0YXJ0LCBlbmRdKTtcbiAgICAgICAgICAvLyBJZiB0aGUgcmFuZ2UgbWlnaHQgaW50ZXJzZWN0IGxldHRlcnMsIHRoZW4gZXhwYW5kIGl0LlxuICAgICAgICAgIC8vIFRoaXMgY2FzZSBoYW5kbGluZyBpcyB0b28gc2ltcGxpc3RpYy5cbiAgICAgICAgICAvLyBJdCBkb2VzIG5vdCBkZWFsIHdpdGggbm9uLWxhdGluIGNhc2UgZm9sZGluZy5cbiAgICAgICAgICAvLyBJdCB3b3JrcyBmb3IgbGF0aW4gc291cmNlIGNvZGUgaWRlbnRpZmllcnMgdGhvdWdoLlxuICAgICAgICAgIGlmICghKGVuZCA8IDY1IHx8IHN0YXJ0ID4gMTIyKSkge1xuICAgICAgICAgICAgaWYgKCEoZW5kIDwgNjUgfHwgc3RhcnQgPiA5MCkpIHtcbiAgICAgICAgICAgICAgcmFuZ2VzLnB1c2goW01hdGgubWF4KDY1LCBzdGFydCkgfCAzMiwgTWF0aC5taW4oZW5kLCA5MCkgfCAzMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoZW5kIDwgOTcgfHwgc3RhcnQgPiAxMjIpKSB7XG4gICAgICAgICAgICAgIHJhbmdlcy5wdXNoKFtNYXRoLm1heCg5Nywgc3RhcnQpICYgfjMyLCBNYXRoLm1pbihlbmQsIDEyMikgJiB+MzJdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgXG4gICAgICAvLyBbWzEsIDEwXSwgWzMsIDRdLCBbOCwgMTJdLCBbMTQsIDE0XSwgWzE2LCAxNl0sIFsxNywgMTddXVxuICAgICAgLy8gLT4gW1sxLCAxMl0sIFsxNCwgMTRdLCBbMTYsIDE3XV1cbiAgICAgIHJhbmdlcy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiAoYVswXSAtIGJbMF0pIHx8IChiWzFdICAtIGFbMV0pOyB9KTtcbiAgICAgIHZhciBjb25zb2xpZGF0ZWRSYW5nZXMgPSBbXTtcbiAgICAgIHZhciBsYXN0UmFuZ2UgPSBbXTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXTtcbiAgICAgICAgaWYgKHJhbmdlWzBdIDw9IGxhc3RSYW5nZVsxXSArIDEpIHtcbiAgICAgICAgICBsYXN0UmFuZ2VbMV0gPSBNYXRoLm1heChsYXN0UmFuZ2VbMV0sIHJhbmdlWzFdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xpZGF0ZWRSYW5nZXMucHVzaChsYXN0UmFuZ2UgPSByYW5nZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbnNvbGlkYXRlZFJhbmdlcy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgcmFuZ2UgPSBjb25zb2xpZGF0ZWRSYW5nZXNbaV07XG4gICAgICAgIG91dC5wdXNoKGVuY29kZUVzY2FwZShyYW5nZVswXSkpO1xuICAgICAgICBpZiAocmFuZ2VbMV0gPiByYW5nZVswXSkge1xuICAgICAgICAgIGlmIChyYW5nZVsxXSArIDEgPiByYW5nZVswXSkgeyBvdXQucHVzaCgnLScpOyB9XG4gICAgICAgICAgb3V0LnB1c2goZW5jb2RlRXNjYXBlKHJhbmdlWzFdKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIG91dC5wdXNoKCddJyk7XG4gICAgICByZXR1cm4gb3V0LmpvaW4oJycpO1xuICAgIH1cbiAgXG4gICAgZnVuY3Rpb24gYWxsb3dBbnl3aGVyZUZvbGRDYXNlQW5kUmVudW1iZXJHcm91cHMocmVnZXgpIHtcbiAgICAgIC8vIFNwbGl0IGludG8gY2hhcmFjdGVyIHNldHMsIGVzY2FwZSBzZXF1ZW5jZXMsIHB1bmN0dWF0aW9uIHN0cmluZ3NcbiAgICAgIC8vIGxpa2UgKCcoJywgJyg/OicsICcpJywgJ14nKSwgYW5kIHJ1bnMgb2YgY2hhcmFjdGVycyB0aGF0IGRvIG5vdFxuICAgICAgLy8gaW5jbHVkZSBhbnkgb2YgdGhlIGFib3ZlLlxuICAgICAgdmFyIHBhcnRzID0gcmVnZXguc291cmNlLm1hdGNoKFxuICAgICAgICAgIG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgICcoPzonXG4gICAgICAgICAgICAgICsgJ1xcXFxbKD86W15cXFxceDVDXFxcXHg1RF18XFxcXFxcXFxbXFxcXHNcXFxcU10pKlxcXFxdJyAgLy8gYSBjaGFyYWN0ZXIgc2V0XG4gICAgICAgICAgICAgICsgJ3xcXFxcXFxcXHVbQS1GYS1mMC05XXs0fScgIC8vIGEgdW5pY29kZSBlc2NhcGVcbiAgICAgICAgICAgICAgKyAnfFxcXFxcXFxceFtBLUZhLWYwLTldezJ9JyAgLy8gYSBoZXggZXNjYXBlXG4gICAgICAgICAgICAgICsgJ3xcXFxcXFxcXFswLTldKycgIC8vIGEgYmFjay1yZWZlcmVuY2Ugb3Igb2N0YWwgZXNjYXBlXG4gICAgICAgICAgICAgICsgJ3xcXFxcXFxcXFtedXgwLTldJyAgLy8gb3RoZXIgZXNjYXBlIHNlcXVlbmNlXG4gICAgICAgICAgICAgICsgJ3xcXFxcKFxcXFw/WzohPV0nICAvLyBzdGFydCBvZiBhIG5vbi1jYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgKyAnfFtcXFxcKFxcXFwpXFxcXF5dJyAgLy8gc3RhcnQvZW5kIG9mIGEgZ3JvdXAsIG9yIGxpbmUgc3RhcnRcbiAgICAgICAgICAgICAgKyAnfFteXFxcXHg1QlxcXFx4NUNcXFxcKFxcXFwpXFxcXF5dKycgIC8vIHJ1biBvZiBvdGhlciBjaGFyYWN0ZXJzXG4gICAgICAgICAgICAgICsgJyknLFxuICAgICAgICAgICAgICAnZycpKTtcbiAgICAgIHZhciBuID0gcGFydHMubGVuZ3RoO1xuICBcbiAgICAgIC8vIE1hcHMgY2FwdHVyZWQgZ3JvdXAgbnVtYmVycyB0byB0aGUgbnVtYmVyIHRoZXkgd2lsbCBvY2N1cHkgaW5cbiAgICAgIC8vIHRoZSBvdXRwdXQgb3IgdG8gLTEgaWYgdGhhdCBoYXMgbm90IGJlZW4gZGV0ZXJtaW5lZCwgb3IgdG9cbiAgICAgIC8vIHVuZGVmaW5lZCBpZiB0aGV5IG5lZWQgbm90IGJlIGNhcHR1cmluZyBpbiB0aGUgb3V0cHV0LlxuICAgICAgdmFyIGNhcHR1cmVkR3JvdXBzID0gW107XG4gIFxuICAgICAgLy8gV2FsayBvdmVyIGFuZCBpZGVudGlmeSBiYWNrIHJlZmVyZW5jZXMgdG8gYnVpbGQgdGhlIGNhcHR1cmVkR3JvdXBzXG4gICAgICAvLyBtYXBwaW5nLlxuICAgICAgZm9yICh2YXIgaSA9IDAsIGdyb3VwSW5kZXggPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIHZhciBwID0gcGFydHNbaV07XG4gICAgICAgIGlmIChwID09PSAnKCcpIHtcbiAgICAgICAgICAvLyBncm91cHMgYXJlIDEtaW5kZXhlZCwgc28gbWF4IGdyb3VwIGluZGV4IGlzIGNvdW50IG9mICcoJ1xuICAgICAgICAgICsrZ3JvdXBJbmRleDtcbiAgICAgICAgfSBlbHNlIGlmICgnXFxcXCcgPT09IHAuY2hhckF0KDApKSB7XG4gICAgICAgICAgdmFyIGRlY2ltYWxWYWx1ZSA9ICtwLnN1YnN0cmluZygxKTtcbiAgICAgICAgICBpZiAoZGVjaW1hbFZhbHVlKSB7XG4gICAgICAgICAgICBpZiAoZGVjaW1hbFZhbHVlIDw9IGdyb3VwSW5kZXgpIHtcbiAgICAgICAgICAgICAgY2FwdHVyZWRHcm91cHNbZGVjaW1hbFZhbHVlXSA9IC0xO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gUmVwbGFjZSB3aXRoIGFuIHVuYW1iaWd1b3VzIGVzY2FwZSBzZXF1ZW5jZSBzbyB0aGF0XG4gICAgICAgICAgICAgIC8vIGFuIG9jdGFsIGVzY2FwZSBzZXF1ZW5jZSBkb2VzIG5vdCB0dXJuIGludG8gYSBiYWNrcmVmZXJlbmNlXG4gICAgICAgICAgICAgIC8vIHRvIGEgY2FwdHVyaW5nIGdyb3VwIGZyb20gYW4gZWFybGllciByZWdleC5cbiAgICAgICAgICAgICAgcGFydHNbaV0gPSBlbmNvZGVFc2NhcGUoZGVjaW1hbFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgXG4gICAgICAvLyBSZW51bWJlciBncm91cHMgYW5kIHJlZHVjZSBjYXB0dXJpbmcgZ3JvdXBzIHRvIG5vbi1jYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAvLyB3aGVyZSBwb3NzaWJsZS5cbiAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgY2FwdHVyZWRHcm91cHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWYgKC0xID09PSBjYXB0dXJlZEdyb3Vwc1tpXSkge1xuICAgICAgICAgIGNhcHR1cmVkR3JvdXBzW2ldID0gKytjYXB0dXJlZEdyb3VwSW5kZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGkgPSAwLCBncm91cEluZGV4ID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICB2YXIgcCA9IHBhcnRzW2ldO1xuICAgICAgICBpZiAocCA9PT0gJygnKSB7XG4gICAgICAgICAgKytncm91cEluZGV4O1xuICAgICAgICAgIGlmICghY2FwdHVyZWRHcm91cHNbZ3JvdXBJbmRleF0pIHtcbiAgICAgICAgICAgIHBhcnRzW2ldID0gJyg/Oic7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCdcXFxcJyA9PT0gcC5jaGFyQXQoMCkpIHtcbiAgICAgICAgICB2YXIgZGVjaW1hbFZhbHVlID0gK3Auc3Vic3RyaW5nKDEpO1xuICAgICAgICAgIGlmIChkZWNpbWFsVmFsdWUgJiYgZGVjaW1hbFZhbHVlIDw9IGdyb3VwSW5kZXgpIHtcbiAgICAgICAgICAgIHBhcnRzW2ldID0gJ1xcXFwnICsgY2FwdHVyZWRHcm91cHNbZGVjaW1hbFZhbHVlXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgXG4gICAgICAvLyBSZW1vdmUgYW55IHByZWZpeCBhbmNob3JzIHNvIHRoYXQgdGhlIG91dHB1dCB3aWxsIG1hdGNoIGFueXdoZXJlLlxuICAgICAgLy8gXl4gcmVhbGx5IGRvZXMgbWVhbiBhbiBhbmNob3JlZCBtYXRjaCB0aG91Z2guXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICBpZiAoJ14nID09PSBwYXJ0c1tpXSAmJiAnXicgIT09IHBhcnRzW2kgKyAxXSkgeyBwYXJ0c1tpXSA9ICcnOyB9XG4gICAgICB9XG4gIFxuICAgICAgLy8gRXhwYW5kIGxldHRlcnMgdG8gZ3JvdXBzIHRvIGhhbmRsZSBtaXhpbmcgb2YgY2FzZS1zZW5zaXRpdmUgYW5kXG4gICAgICAvLyBjYXNlLWluc2Vuc2l0aXZlIHBhdHRlcm5zIGlmIG5lY2Vzc2FyeS5cbiAgICAgIGlmIChyZWdleC5pZ25vcmVDYXNlICYmIG5lZWRUb0ZvbGRDYXNlKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgICAgdmFyIHAgPSBwYXJ0c1tpXTtcbiAgICAgICAgICB2YXIgY2gwID0gcC5jaGFyQXQoMCk7XG4gICAgICAgICAgaWYgKHAubGVuZ3RoID49IDIgJiYgY2gwID09PSAnWycpIHtcbiAgICAgICAgICAgIHBhcnRzW2ldID0gY2FzZUZvbGRDaGFyc2V0KHApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY2gwICE9PSAnXFxcXCcpIHtcbiAgICAgICAgICAgIC8vIFRPRE86IGhhbmRsZSBsZXR0ZXJzIGluIG51bWVyaWMgZXNjYXBlcy5cbiAgICAgICAgICAgIHBhcnRzW2ldID0gcC5yZXBsYWNlKFxuICAgICAgICAgICAgICAgIC9bYS16QS1aXS9nLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChjaCkge1xuICAgICAgICAgICAgICAgICAgdmFyIGNjID0gY2guY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiAnWycgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGNjICYgfjMyLCBjYyB8IDMyKSArICddJztcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgXG4gICAgICByZXR1cm4gcGFydHMuam9pbignJyk7XG4gICAgfVxuICBcbiAgICB2YXIgcmV3cml0dGVuID0gW107XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSByZWdleHMubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICB2YXIgcmVnZXggPSByZWdleHNbaV07XG4gICAgICBpZiAocmVnZXguZ2xvYmFsIHx8IHJlZ2V4Lm11bHRpbGluZSkgeyB0aHJvdyBuZXcgRXJyb3IoJycgKyByZWdleCk7IH1cbiAgICAgIHJld3JpdHRlbi5wdXNoKFxuICAgICAgICAgICcoPzonICsgYWxsb3dBbnl3aGVyZUZvbGRDYXNlQW5kUmVudW1iZXJHcm91cHMocmVnZXgpICsgJyknKTtcbiAgICB9XG4gIFxuICAgIHJldHVybiBuZXcgUmVnRXhwKHJld3JpdHRlbi5qb2luKCd8JyksIGlnbm9yZUNhc2UgPyAnZ2knIDogJ2cnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdCBtYXJrdXAgaW50byBhIHN0cmluZyBvZiBzb3VyY2UgY29kZSBhbmQgYW4gYXJyYXkgbWFwcGluZyByYW5nZXMgaW5cbiAgICogdGhhdCBzdHJpbmcgdG8gdGhlIHRleHQgbm9kZXMgaW4gd2hpY2ggdGhleSBhcHBlYXIuXG4gICAqXG4gICAqIDxwPlxuICAgKiBUaGUgSFRNTCBET00gc3RydWN0dXJlOjwvcD5cbiAgICogPHByZT5cbiAgICogKEVsZW1lbnQgICBcInBcIlxuICAgKiAgIChFbGVtZW50IFwiYlwiXG4gICAqICAgICAoVGV4dCAgXCJwcmludCBcIikpICAgICAgIDsgIzFcbiAgICogICAoVGV4dCAgICBcIidIZWxsbyAnXCIpICAgICAgOyAjMlxuICAgKiAgIChFbGVtZW50IFwiYnJcIikgICAgICAgICAgICA7ICMzXG4gICAqICAgKFRleHQgICAgXCIgICsgJ1dvcmxkJztcIikpIDsgIzRcbiAgICogPC9wcmU+XG4gICAqIDxwPlxuICAgKiBjb3JyZXNwb25kcyB0byB0aGUgSFRNTFxuICAgKiB7QGNvZGUgPHA+PGI+cHJpbnQgPC9iPidIZWxsbyAnPGJyPiAgKyAnV29ybGQnOzwvcD59LjwvcD5cbiAgICpcbiAgICogPHA+XG4gICAqIEl0IHdpbGwgcHJvZHVjZSB0aGUgb3V0cHV0OjwvcD5cbiAgICogPHByZT5cbiAgICoge1xuICAgKiAgIHNvdXJjZUNvZGU6IFwicHJpbnQgJ0hlbGxvICdcXG4gICsgJ1dvcmxkJztcIixcbiAgICogICAvLyAgICAgICAgICAgICAgICAgICAgIDEgICAgICAgICAgMlxuICAgKiAgIC8vICAgICAgICAgICAwMTIzNDU2Nzg5MDEyMzQgNTY3ODkwMTIzNDU2N1xuICAgKiAgIHNwYW5zOiBbMCwgIzEsIDYsICMyLCAxNCwgIzMsIDE1LCAjNF1cbiAgICogfVxuICAgKiA8L3ByZT5cbiAgICogPHA+XG4gICAqIHdoZXJlICMxIGlzIGEgcmVmZXJlbmNlIHRvIHRoZSB7QGNvZGUgXCJwcmludCBcIn0gdGV4dCBub2RlIGFib3ZlLCBhbmQgc29cbiAgICogb24gZm9yIHRoZSBvdGhlciB0ZXh0IG5vZGVzLlxuICAgKiA8L3A+XG4gICAqXG4gICAqIDxwPlxuICAgKiBUaGUge0Bjb2RlfSBzcGFucyBhcnJheSBpcyBhbiBhcnJheSBvZiBwYWlycy4gIEV2ZW4gZWxlbWVudHMgYXJlIHRoZSBzdGFydFxuICAgKiBpbmRpY2VzIG9mIHN1YnN0cmluZ3MsIGFuZCBvZGQgZWxlbWVudHMgYXJlIHRoZSB0ZXh0IG5vZGVzIChvciBCUiBlbGVtZW50cylcbiAgICogdGhhdCBjb250YWluIHRoZSB0ZXh0IGZvciB0aG9zZSBzdWJzdHJpbmdzLlxuICAgKiBTdWJzdHJpbmdzIGNvbnRpbnVlIHVudGlsIHRoZSBuZXh0IGluZGV4IG9yIHRoZSBlbmQgb2YgdGhlIHNvdXJjZS5cbiAgICogPC9wPlxuICAgKlxuICAgKiBAcGFyYW0ge05vZGV9IG5vZGUgYW4gSFRNTCBET00gc3VidHJlZSBjb250YWluaW5nIHNvdXJjZS1jb2RlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzUHJlZm9ybWF0dGVkIHRydWUgaWYgd2hpdGUtc3BhY2UgaW4gdGV4dCBub2RlcyBzaG91bGRcbiAgICogICAgYmUgY29uc2lkZXJlZCBzaWduaWZpY2FudC5cbiAgICogQHJldHVybiB7T2JqZWN0fSBzb3VyY2UgY29kZSBhbmQgdGhlIHRleHQgbm9kZXMgaW4gd2hpY2ggdGhleSBvY2N1ci5cbiAgICovXG4gIGZ1bmN0aW9uIGV4dHJhY3RTb3VyY2VTcGFucyhub2RlLCBpc1ByZWZvcm1hdHRlZCkge1xuICAgIHZhciBub2NvZGUgPSAvKD86XnxcXHMpbm9jb2RlKD86XFxzfCQpLztcbiAgXG4gICAgdmFyIGNodW5rcyA9IFtdO1xuICAgIHZhciBsZW5ndGggPSAwO1xuICAgIHZhciBzcGFucyA9IFtdO1xuICAgIHZhciBrID0gMDtcbiAgXG4gICAgZnVuY3Rpb24gd2Fsayhub2RlKSB7XG4gICAgICB2YXIgdHlwZSA9IG5vZGUubm9kZVR5cGU7XG4gICAgICBpZiAodHlwZSA9PSAxKSB7ICAvLyBFbGVtZW50XG4gICAgICAgIGlmIChub2NvZGUudGVzdChub2RlLmNsYXNzTmFtZSkpIHsgcmV0dXJuOyB9XG4gICAgICAgIGZvciAodmFyIGNoaWxkID0gbm9kZS5maXJzdENoaWxkOyBjaGlsZDsgY2hpbGQgPSBjaGlsZC5uZXh0U2libGluZykge1xuICAgICAgICAgIHdhbGsoY2hpbGQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBub2RlTmFtZSA9IG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKCdicicgPT09IG5vZGVOYW1lIHx8ICdsaScgPT09IG5vZGVOYW1lKSB7XG4gICAgICAgICAgY2h1bmtzW2tdID0gJ1xcbic7XG4gICAgICAgICAgc3BhbnNbayA8PCAxXSA9IGxlbmd0aCsrO1xuICAgICAgICAgIHNwYW5zWyhrKysgPDwgMSkgfCAxXSA9IG5vZGU7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PSAzIHx8IHR5cGUgPT0gNCkgeyAgLy8gVGV4dFxuICAgICAgICB2YXIgdGV4dCA9IG5vZGUubm9kZVZhbHVlO1xuICAgICAgICBpZiAodGV4dC5sZW5ndGgpIHtcbiAgICAgICAgICBpZiAoIWlzUHJlZm9ybWF0dGVkKSB7XG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9bIFxcdFxcclxcbl0rL2csICcgJyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcclxcbj8vZywgJ1xcbicpOyAgLy8gTm9ybWFsaXplIG5ld2xpbmVzLlxuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBUT0RPOiBoYW5kbGUgdGFicyBoZXJlP1xuICAgICAgICAgIGNodW5rc1trXSA9IHRleHQ7XG4gICAgICAgICAgc3BhbnNbayA8PCAxXSA9IGxlbmd0aDtcbiAgICAgICAgICBsZW5ndGggKz0gdGV4dC5sZW5ndGg7XG4gICAgICAgICAgc3BhbnNbKGsrKyA8PCAxKSB8IDFdID0gbm9kZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgXG4gICAgd2Fsayhub2RlKTtcbiAgXG4gICAgcmV0dXJuIHtcbiAgICAgIHNvdXJjZUNvZGU6IGNodW5rcy5qb2luKCcnKS5yZXBsYWNlKC9cXG4kLywgJycpLFxuICAgICAgc3BhbnM6IHNwYW5zXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSB0aGUgZ2l2ZW4gbGFuZ3VhZ2UgaGFuZGxlciB0byBzb3VyY2VDb2RlIGFuZCBhZGQgdGhlIHJlc3VsdGluZ1xuICAgKiBkZWNvcmF0aW9ucyB0byBvdXQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBiYXNlUG9zIHRoZSBpbmRleCBvZiBzb3VyY2VDb2RlIHdpdGhpbiB0aGUgY2h1bmsgb2Ygc291cmNlXG4gICAqICAgIHdob3NlIGRlY29yYXRpb25zIGFyZSBhbHJlYWR5IHByZXNlbnQgb24gb3V0LlxuICAgKi9cbiAgZnVuY3Rpb24gYXBwZW5kRGVjb3JhdGlvbnMoYmFzZVBvcywgc291cmNlQ29kZSwgbGFuZ0hhbmRsZXIsIG91dCkge1xuICAgIGlmICghc291cmNlQ29kZSkgeyByZXR1cm47IH1cbiAgICB2YXIgam9iID0ge1xuICAgICAgc291cmNlQ29kZTogc291cmNlQ29kZSxcbiAgICAgIGJhc2VQb3M6IGJhc2VQb3NcbiAgICB9O1xuICAgIGxhbmdIYW5kbGVyKGpvYik7XG4gICAgb3V0LnB1c2guYXBwbHkob3V0LCBqb2IuZGVjb3JhdGlvbnMpO1xuICB9XG5cbiAgdmFyIG5vdFdzID0gL1xcUy87XG5cbiAgLyoqXG4gICAqIEdpdmVuIGFuIGVsZW1lbnQsIGlmIGl0IGNvbnRhaW5zIG9ubHkgb25lIGNoaWxkIGVsZW1lbnQgYW5kIGFueSB0ZXh0IG5vZGVzXG4gICAqIGl0IGNvbnRhaW5zIGNvbnRhaW4gb25seSBzcGFjZSBjaGFyYWN0ZXJzLCByZXR1cm4gdGhlIHNvbGUgY2hpbGQgZWxlbWVudC5cbiAgICogT3RoZXJ3aXNlIHJldHVybnMgdW5kZWZpbmVkLlxuICAgKiA8cD5cbiAgICogVGhpcyBpcyBtZWFudCB0byByZXR1cm4gdGhlIENPREUgZWxlbWVudCBpbiB7QGNvZGUgPHByZT48Y29kZSAuLi4+fSB3aGVuXG4gICAqIHRoZXJlIGlzIGEgc2luZ2xlIGNoaWxkIGVsZW1lbnQgdGhhdCBjb250YWlucyBhbGwgdGhlIG5vbi1zcGFjZSB0ZXh0dWFsXG4gICAqIGNvbnRlbnQsIGJ1dCBub3QgdG8gcmV0dXJuIGFueXRoaW5nIHdoZXJlIHRoZXJlIGFyZSBtdWx0aXBsZSBjaGlsZCBlbGVtZW50c1xuICAgKiBhcyBpbiB7QGNvZGUgPHByZT48Y29kZT4uLi48L2NvZGU+PGNvZGU+Li4uPC9jb2RlPjwvcHJlPn0gb3Igd2hlbiB0aGVyZVxuICAgKiBpcyB0ZXh0dWFsIGNvbnRlbnQuXG4gICAqL1xuICBmdW5jdGlvbiBjaGlsZENvbnRlbnRXcmFwcGVyKGVsZW1lbnQpIHtcbiAgICB2YXIgd3JhcHBlciA9IHVuZGVmaW5lZDtcbiAgICBmb3IgKHZhciBjID0gZWxlbWVudC5maXJzdENoaWxkOyBjOyBjID0gYy5uZXh0U2libGluZykge1xuICAgICAgdmFyIHR5cGUgPSBjLm5vZGVUeXBlO1xuICAgICAgd3JhcHBlciA9ICh0eXBlID09PSAxKSAgLy8gRWxlbWVudCBOb2RlXG4gICAgICAgICAgPyAod3JhcHBlciA/IGVsZW1lbnQgOiBjKVxuICAgICAgICAgIDogKHR5cGUgPT09IDMpICAvLyBUZXh0IE5vZGVcbiAgICAgICAgICA/IChub3RXcy50ZXN0KGMubm9kZVZhbHVlKSA/IGVsZW1lbnQgOiB3cmFwcGVyKVxuICAgICAgICAgIDogd3JhcHBlcjtcbiAgICB9XG4gICAgcmV0dXJuIHdyYXBwZXIgPT09IGVsZW1lbnQgPyB1bmRlZmluZWQgOiB3cmFwcGVyO1xuICB9XG5cbiAgLyoqIEdpdmVuIHRyaXBsZXMgb2YgW3N0eWxlLCBwYXR0ZXJuLCBjb250ZXh0XSByZXR1cm5zIGEgbGV4aW5nIGZ1bmN0aW9uLFxuICAgICogVGhlIGxleGluZyBmdW5jdGlvbiBpbnRlcnByZXRzIHRoZSBwYXR0ZXJucyB0byBmaW5kIHRva2VuIGJvdW5kYXJpZXMgYW5kXG4gICAgKiByZXR1cm5zIGEgZGVjb3JhdGlvbiBsaXN0IG9mIHRoZSBmb3JtXG4gICAgKiBbaW5kZXhfMCwgc3R5bGVfMCwgaW5kZXhfMSwgc3R5bGVfMSwgLi4uLCBpbmRleF9uLCBzdHlsZV9uXVxuICAgICogd2hlcmUgaW5kZXhfbiBpcyBhbiBpbmRleCBpbnRvIHRoZSBzb3VyY2VDb2RlLCBhbmQgc3R5bGVfbiBpcyBhIHN0eWxlXG4gICAgKiBjb25zdGFudCBsaWtlIFBSX1BMQUlOLiAgaW5kZXhfbi0xIDw9IGluZGV4X24sIGFuZCBzdHlsZV9uLTEgYXBwbGllcyB0b1xuICAgICogYWxsIGNoYXJhY3RlcnMgaW4gc291cmNlQ29kZVtpbmRleF9uLTE6aW5kZXhfbl0uXG4gICAgKlxuICAgICogVGhlIHN0eWxlUGF0dGVybnMgaXMgYSBsaXN0IHdob3NlIGVsZW1lbnRzIGhhdmUgdGhlIGZvcm1cbiAgICAqIFtzdHlsZSA6IHN0cmluZywgcGF0dGVybiA6IFJlZ0V4cCwgREVQUkVDQVRFRCwgc2hvcnRjdXQgOiBzdHJpbmddLlxuICAgICpcbiAgICAqIFN0eWxlIGlzIGEgc3R5bGUgY29uc3RhbnQgbGlrZSBQUl9QTEFJTiwgb3IgY2FuIGJlIGEgc3RyaW5nIG9mIHRoZVxuICAgICogZm9ybSAnbGFuZy1GT08nLCB3aGVyZSBGT08gaXMgYSBsYW5ndWFnZSBleHRlbnNpb24gZGVzY3JpYmluZyB0aGVcbiAgICAqIGxhbmd1YWdlIG9mIHRoZSBwb3J0aW9uIG9mIHRoZSB0b2tlbiBpbiAkMSBhZnRlciBwYXR0ZXJuIGV4ZWN1dGVzLlxuICAgICogRS5nLiwgaWYgc3R5bGUgaXMgJ2xhbmctbGlzcCcsIGFuZCBncm91cCAxIGNvbnRhaW5zIHRoZSB0ZXh0XG4gICAgKiAnKGhlbGxvICh3b3JsZCkpJywgdGhlbiB0aGF0IHBvcnRpb24gb2YgdGhlIHRva2VuIHdpbGwgYmUgcGFzc2VkIHRvIHRoZVxuICAgICogcmVnaXN0ZXJlZCBsaXNwIGhhbmRsZXIgZm9yIGZvcm1hdHRpbmcuXG4gICAgKiBUaGUgdGV4dCBiZWZvcmUgYW5kIGFmdGVyIGdyb3VwIDEgd2lsbCBiZSByZXN0eWxlZCB1c2luZyB0aGlzIGRlY29yYXRvclxuICAgICogc28gZGVjb3JhdG9ycyBzaG91bGQgdGFrZSBjYXJlIHRoYXQgdGhpcyBkb2Vzbid0IHJlc3VsdCBpbiBpbmZpbml0ZVxuICAgICogcmVjdXJzaW9uLiAgRm9yIGV4YW1wbGUsIHRoZSBIVE1MIGxleGVyIHJ1bGUgZm9yIFNDUklQVCBlbGVtZW50cyBsb29rc1xuICAgICogc29tZXRoaW5nIGxpa2UgWydsYW5nLWpzJywgLzxbc11jcmlwdD4oLis/KTxcXC9zY3JpcHQ+L10uICBUaGlzIG1heSBtYXRjaFxuICAgICogJzxzY3JpcHQ+Zm9vKCk8XFwvc2NyaXB0PicsIHdoaWNoIHdvdWxkIGNhdXNlIHRoZSBjdXJyZW50IGRlY29yYXRvciB0b1xuICAgICogYmUgY2FsbGVkIHdpdGggJzxzY3JpcHQ+JyB3aGljaCB3b3VsZCBub3QgbWF0Y2ggdGhlIHNhbWUgcnVsZSBzaW5jZVxuICAgICogZ3JvdXAgMSBtdXN0IG5vdCBiZSBlbXB0eSwgc28gaXQgd291bGQgYmUgaW5zdGVhZCBzdHlsZWQgYXMgUFJfVEFHIGJ5XG4gICAgKiB0aGUgZ2VuZXJpYyB0YWcgcnVsZS4gIFRoZSBoYW5kbGVyIHJlZ2lzdGVyZWQgZm9yIHRoZSAnanMnIGV4dGVuc2lvbiB3b3VsZFxuICAgICogdGhlbiBiZSBjYWxsZWQgd2l0aCAnZm9vKCknLCBhbmQgZmluYWxseSwgdGhlIGN1cnJlbnQgZGVjb3JhdG9yIHdvdWxkXG4gICAgKiBiZSBjYWxsZWQgd2l0aCAnPFxcL3NjcmlwdD4nIHdoaWNoIHdvdWxkIG5vdCBtYXRjaCB0aGUgb3JpZ2luYWwgcnVsZSBhbmRcbiAgICAqIHNvIHRoZSBnZW5lcmljIHRhZyBydWxlIHdvdWxkIGlkZW50aWZ5IGl0IGFzIGEgdGFnLlxuICAgICpcbiAgICAqIFBhdHRlcm4gbXVzdCBvbmx5IG1hdGNoIHByZWZpeGVzLCBhbmQgaWYgaXQgbWF0Y2hlcyBhIHByZWZpeCwgdGhlbiB0aGF0XG4gICAgKiBtYXRjaCBpcyBjb25zaWRlcmVkIGEgdG9rZW4gd2l0aCB0aGUgc2FtZSBzdHlsZS5cbiAgICAqXG4gICAgKiBDb250ZXh0IGlzIGFwcGxpZWQgdG8gdGhlIGxhc3Qgbm9uLXdoaXRlc3BhY2UsIG5vbi1jb21tZW50IHRva2VuXG4gICAgKiByZWNvZ25pemVkLlxuICAgICpcbiAgICAqIFNob3J0Y3V0IGlzIGFuIG9wdGlvbmFsIHN0cmluZyBvZiBjaGFyYWN0ZXJzLCBhbnkgb2Ygd2hpY2gsIGlmIHRoZSBmaXJzdFxuICAgICogY2hhcmFjdGVyLCBndXJhbnRlZSB0aGF0IHRoaXMgcGF0dGVybiBhbmQgb25seSB0aGlzIHBhdHRlcm4gbWF0Y2hlcy5cbiAgICAqXG4gICAgKiBAcGFyYW0ge0FycmF5fSBzaG9ydGN1dFN0eWxlUGF0dGVybnMgcGF0dGVybnMgdGhhdCBhbHdheXMgc3RhcnQgd2l0aFxuICAgICogICBhIGtub3duIGNoYXJhY3Rlci4gIE11c3QgaGF2ZSBhIHNob3J0Y3V0IHN0cmluZy5cbiAgICAqIEBwYXJhbSB7QXJyYXl9IGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucyBwYXR0ZXJucyB0aGF0IHdpbGwgYmUgdHJpZWQgaW5cbiAgICAqICAgb3JkZXIgaWYgdGhlIHNob3J0Y3V0IG9uZXMgZmFpbC4gIE1heSBoYXZlIHNob3J0Y3V0cy5cbiAgICAqXG4gICAgKiBAcmV0dXJuIHtmdW5jdGlvbiAoT2JqZWN0KX0gYVxuICAgICogICBmdW5jdGlvbiB0aGF0IHRha2VzIHNvdXJjZSBjb2RlIGFuZCByZXR1cm5zIGEgbGlzdCBvZiBkZWNvcmF0aW9ucy5cbiAgICAqL1xuICBmdW5jdGlvbiBjcmVhdGVTaW1wbGVMZXhlcihzaG9ydGN1dFN0eWxlUGF0dGVybnMsIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucykge1xuICAgIHZhciBzaG9ydGN1dHMgPSB7fTtcbiAgICB2YXIgdG9rZW5pemVyO1xuICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgYWxsUGF0dGVybnMgPSBzaG9ydGN1dFN0eWxlUGF0dGVybnMuY29uY2F0KGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucyk7XG4gICAgICB2YXIgYWxsUmVnZXhzID0gW107XG4gICAgICB2YXIgcmVnZXhLZXlzID0ge307XG4gICAgICBmb3IgKHZhciBpID0gMCwgbiA9IGFsbFBhdHRlcm5zLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgICB2YXIgcGF0dGVyblBhcnRzID0gYWxsUGF0dGVybnNbaV07XG4gICAgICAgIHZhciBzaG9ydGN1dENoYXJzID0gcGF0dGVyblBhcnRzWzNdO1xuICAgICAgICBpZiAoc2hvcnRjdXRDaGFycykge1xuICAgICAgICAgIGZvciAodmFyIGMgPSBzaG9ydGN1dENoYXJzLmxlbmd0aDsgLS1jID49IDA7KSB7XG4gICAgICAgICAgICBzaG9ydGN1dHNbc2hvcnRjdXRDaGFycy5jaGFyQXQoYyldID0gcGF0dGVyblBhcnRzO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVnZXggPSBwYXR0ZXJuUGFydHNbMV07XG4gICAgICAgIHZhciBrID0gJycgKyByZWdleDtcbiAgICAgICAgaWYgKCFyZWdleEtleXMuaGFzT3duUHJvcGVydHkoaykpIHtcbiAgICAgICAgICBhbGxSZWdleHMucHVzaChyZWdleCk7XG4gICAgICAgICAgcmVnZXhLZXlzW2tdID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYWxsUmVnZXhzLnB1c2goL1tcXDAtXFx1ZmZmZl0vKTtcbiAgICAgIHRva2VuaXplciA9IGNvbWJpbmVQcmVmaXhQYXR0ZXJucyhhbGxSZWdleHMpO1xuICAgIH0pKCk7XG5cbiAgICB2YXIgblBhdHRlcm5zID0gZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLmxlbmd0aDtcblxuICAgIC8qKlxuICAgICAqIExleGVzIGpvYi5zb3VyY2VDb2RlIGFuZCBwcm9kdWNlcyBhbiBvdXRwdXQgYXJyYXkgam9iLmRlY29yYXRpb25zIG9mXG4gICAgICogc3R5bGUgY2xhc3NlcyBwcmVjZWRlZCBieSB0aGUgcG9zaXRpb24gYXQgd2hpY2ggdGhleSBzdGFydCBpblxuICAgICAqIGpvYi5zb3VyY2VDb2RlIGluIG9yZGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGpvYiBhbiBvYmplY3QgbGlrZSA8cHJlPntcbiAgICAgKiAgICBzb3VyY2VDb2RlOiB7c3RyaW5nfSBzb3VyY2VUZXh0IHBsYWluIHRleHQsXG4gICAgICogICAgYmFzZVBvczoge2ludH0gcG9zaXRpb24gb2Ygam9iLnNvdXJjZUNvZGUgaW4gdGhlIGxhcmdlciBjaHVuayBvZlxuICAgICAqICAgICAgICBzb3VyY2VDb2RlLlxuICAgICAqIH08L3ByZT5cbiAgICAgKi9cbiAgICB2YXIgZGVjb3JhdGUgPSBmdW5jdGlvbiAoam9iKSB7XG4gICAgICB2YXIgc291cmNlQ29kZSA9IGpvYi5zb3VyY2VDb2RlLCBiYXNlUG9zID0gam9iLmJhc2VQb3M7XG4gICAgICAvKiogRXZlbiBlbnRyaWVzIGFyZSBwb3NpdGlvbnMgaW4gc291cmNlIGluIGFzY2VuZGluZyBvcmRlci4gIE9kZCBlbnRpZXNcbiAgICAgICAgKiBhcmUgc3R5bGUgbWFya2VycyAoZS5nLiwgUFJfQ09NTUVOVCkgdGhhdCBydW4gZnJvbSB0aGF0IHBvc2l0aW9uIHVudGlsXG4gICAgICAgICogdGhlIGVuZC5cbiAgICAgICAgKiBAdHlwZSB7QXJyYXkuPG51bWJlcnxzdHJpbmc+fVxuICAgICAgICAqL1xuICAgICAgdmFyIGRlY29yYXRpb25zID0gW2Jhc2VQb3MsIFBSX1BMQUlOXTtcbiAgICAgIHZhciBwb3MgPSAwOyAgLy8gaW5kZXggaW50byBzb3VyY2VDb2RlXG4gICAgICB2YXIgdG9rZW5zID0gc291cmNlQ29kZS5tYXRjaCh0b2tlbml6ZXIpIHx8IFtdO1xuICAgICAgdmFyIHN0eWxlQ2FjaGUgPSB7fTtcblxuICAgICAgZm9yICh2YXIgdGkgPSAwLCBuVG9rZW5zID0gdG9rZW5zLmxlbmd0aDsgdGkgPCBuVG9rZW5zOyArK3RpKSB7XG4gICAgICAgIHZhciB0b2tlbiA9IHRva2Vuc1t0aV07XG4gICAgICAgIHZhciBzdHlsZSA9IHN0eWxlQ2FjaGVbdG9rZW5dO1xuICAgICAgICB2YXIgbWF0Y2ggPSB2b2lkIDA7XG5cbiAgICAgICAgdmFyIGlzRW1iZWRkZWQ7XG4gICAgICAgIGlmICh0eXBlb2Ygc3R5bGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaXNFbWJlZGRlZCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBwYXR0ZXJuUGFydHMgPSBzaG9ydGN1dHNbdG9rZW4uY2hhckF0KDApXTtcbiAgICAgICAgICBpZiAocGF0dGVyblBhcnRzKSB7XG4gICAgICAgICAgICBtYXRjaCA9IHRva2VuLm1hdGNoKHBhdHRlcm5QYXJ0c1sxXSk7XG4gICAgICAgICAgICBzdHlsZSA9IHBhdHRlcm5QYXJ0c1swXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuUGF0dGVybnM7ICsraSkge1xuICAgICAgICAgICAgICBwYXR0ZXJuUGFydHMgPSBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnNbaV07XG4gICAgICAgICAgICAgIG1hdGNoID0gdG9rZW4ubWF0Y2gocGF0dGVyblBhcnRzWzFdKTtcbiAgICAgICAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgc3R5bGUgPSBwYXR0ZXJuUGFydHNbMF07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFtYXRjaCkgeyAgLy8gbWFrZSBzdXJlIHRoYXQgd2UgbWFrZSBwcm9ncmVzc1xuICAgICAgICAgICAgICBzdHlsZSA9IFBSX1BMQUlOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlzRW1iZWRkZWQgPSBzdHlsZS5sZW5ndGggPj0gNSAmJiAnbGFuZy0nID09PSBzdHlsZS5zdWJzdHJpbmcoMCwgNSk7XG4gICAgICAgICAgaWYgKGlzRW1iZWRkZWQgJiYgIShtYXRjaCAmJiB0eXBlb2YgbWF0Y2hbMV0gPT09ICdzdHJpbmcnKSkge1xuICAgICAgICAgICAgaXNFbWJlZGRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgc3R5bGUgPSBQUl9TT1VSQ0U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFpc0VtYmVkZGVkKSB7IHN0eWxlQ2FjaGVbdG9rZW5dID0gc3R5bGU7IH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0b2tlblN0YXJ0ID0gcG9zO1xuICAgICAgICBwb3MgKz0gdG9rZW4ubGVuZ3RoO1xuXG4gICAgICAgIGlmICghaXNFbWJlZGRlZCkge1xuICAgICAgICAgIGRlY29yYXRpb25zLnB1c2goYmFzZVBvcyArIHRva2VuU3RhcnQsIHN0eWxlKTtcbiAgICAgICAgfSBlbHNlIHsgIC8vIFRyZWF0IGdyb3VwIDEgYXMgYW4gZW1iZWRkZWQgYmxvY2sgb2Ygc291cmNlIGNvZGUuXG4gICAgICAgICAgdmFyIGVtYmVkZGVkU291cmNlID0gbWF0Y2hbMV07XG4gICAgICAgICAgdmFyIGVtYmVkZGVkU291cmNlU3RhcnQgPSB0b2tlbi5pbmRleE9mKGVtYmVkZGVkU291cmNlKTtcbiAgICAgICAgICB2YXIgZW1iZWRkZWRTb3VyY2VFbmQgPSBlbWJlZGRlZFNvdXJjZVN0YXJ0ICsgZW1iZWRkZWRTb3VyY2UubGVuZ3RoO1xuICAgICAgICAgIGlmIChtYXRjaFsyXSkge1xuICAgICAgICAgICAgLy8gSWYgZW1iZWRkZWRTb3VyY2UgY2FuIGJlIGJsYW5rLCB0aGVuIGl0IHdvdWxkIG1hdGNoIGF0IHRoZVxuICAgICAgICAgICAgLy8gYmVnaW5uaW5nIHdoaWNoIHdvdWxkIGNhdXNlIHVzIHRvIGluZmluaXRlbHkgcmVjdXJzZSBvbiB0aGVcbiAgICAgICAgICAgIC8vIGVudGlyZSB0b2tlbiwgc28gd2UgY2F0Y2ggdGhlIHJpZ2h0IGNvbnRleHQgaW4gbWF0Y2hbMl0uXG4gICAgICAgICAgICBlbWJlZGRlZFNvdXJjZUVuZCA9IHRva2VuLmxlbmd0aCAtIG1hdGNoWzJdLmxlbmd0aDtcbiAgICAgICAgICAgIGVtYmVkZGVkU291cmNlU3RhcnQgPSBlbWJlZGRlZFNvdXJjZUVuZCAtIGVtYmVkZGVkU291cmNlLmxlbmd0aDtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIGxhbmcgPSBzdHlsZS5zdWJzdHJpbmcoNSk7XG4gICAgICAgICAgLy8gRGVjb3JhdGUgdGhlIGxlZnQgb2YgdGhlIGVtYmVkZGVkIHNvdXJjZVxuICAgICAgICAgIGFwcGVuZERlY29yYXRpb25zKFxuICAgICAgICAgICAgICBiYXNlUG9zICsgdG9rZW5TdGFydCxcbiAgICAgICAgICAgICAgdG9rZW4uc3Vic3RyaW5nKDAsIGVtYmVkZGVkU291cmNlU3RhcnQpLFxuICAgICAgICAgICAgICBkZWNvcmF0ZSwgZGVjb3JhdGlvbnMpO1xuICAgICAgICAgIC8vIERlY29yYXRlIHRoZSBlbWJlZGRlZCBzb3VyY2VcbiAgICAgICAgICBhcHBlbmREZWNvcmF0aW9ucyhcbiAgICAgICAgICAgICAgYmFzZVBvcyArIHRva2VuU3RhcnQgKyBlbWJlZGRlZFNvdXJjZVN0YXJ0LFxuICAgICAgICAgICAgICBlbWJlZGRlZFNvdXJjZSxcbiAgICAgICAgICAgICAgbGFuZ0hhbmRsZXJGb3JFeHRlbnNpb24obGFuZywgZW1iZWRkZWRTb3VyY2UpLFxuICAgICAgICAgICAgICBkZWNvcmF0aW9ucyk7XG4gICAgICAgICAgLy8gRGVjb3JhdGUgdGhlIHJpZ2h0IG9mIHRoZSBlbWJlZGRlZCBzZWN0aW9uXG4gICAgICAgICAgYXBwZW5kRGVjb3JhdGlvbnMoXG4gICAgICAgICAgICAgIGJhc2VQb3MgKyB0b2tlblN0YXJ0ICsgZW1iZWRkZWRTb3VyY2VFbmQsXG4gICAgICAgICAgICAgIHRva2VuLnN1YnN0cmluZyhlbWJlZGRlZFNvdXJjZUVuZCksXG4gICAgICAgICAgICAgIGRlY29yYXRlLCBkZWNvcmF0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGpvYi5kZWNvcmF0aW9ucyA9IGRlY29yYXRpb25zO1xuICAgIH07XG4gICAgcmV0dXJuIGRlY29yYXRlO1xuICB9XG5cbiAgLyoqIHJldHVybnMgYSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGEgbGlzdCBvZiBkZWNvcmF0aW9ucyBmcm9tIHNvdXJjZSB0ZXh0LlxuICAgICpcbiAgICAqIFRoaXMgY29kZSB0cmVhdHMgXCIsICcsIGFuZCBgIGFzIHN0cmluZyBkZWxpbWl0ZXJzLCBhbmQgXFwgYXMgYSBzdHJpbmdcbiAgICAqIGVzY2FwZS4gIEl0IGRvZXMgbm90IHJlY29nbml6ZSBwZXJsJ3MgcXEoKSBzdHlsZSBzdHJpbmdzLlxuICAgICogSXQgaGFzIG5vIHNwZWNpYWwgaGFuZGxpbmcgZm9yIGRvdWJsZSBkZWxpbWl0ZXIgZXNjYXBlcyBhcyBpbiBiYXNpYywgb3JcbiAgICAqIHRoZSB0cmlwbGVkIGRlbGltaXRlcnMgdXNlZCBpbiBweXRob24sIGJ1dCBzaG91bGQgd29yayBvbiB0aG9zZSByZWdhcmRsZXNzXG4gICAgKiBhbHRob3VnaCBpbiB0aG9zZSBjYXNlcyBhIHNpbmdsZSBzdHJpbmcgbGl0ZXJhbCBtYXkgYmUgYnJva2VuIHVwIGludG9cbiAgICAqIG11bHRpcGxlIGFkamFjZW50IHN0cmluZyBsaXRlcmFscy5cbiAgICAqXG4gICAgKiBJdCByZWNvZ25pemVzIEMsIEMrKywgYW5kIHNoZWxsIHN0eWxlIGNvbW1lbnRzLlxuICAgICpcbiAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIGEgc2V0IG9mIG9wdGlvbmFsIHBhcmFtZXRlcnMuXG4gICAgKiBAcmV0dXJuIHtmdW5jdGlvbiAoT2JqZWN0KX0gYSBmdW5jdGlvbiB0aGF0IGV4YW1pbmVzIHRoZSBzb3VyY2UgY29kZVxuICAgICogICAgIGluIHRoZSBpbnB1dCBqb2IgYW5kIGJ1aWxkcyB0aGUgZGVjb3JhdGlvbiBsaXN0LlxuICAgICovXG4gIGZ1bmN0aW9uIHNvdXJjZURlY29yYXRvcihvcHRpb25zKSB7XG4gICAgdmFyIHNob3J0Y3V0U3R5bGVQYXR0ZXJucyA9IFtdLCBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMgPSBbXTtcbiAgICBpZiAob3B0aW9uc1sndHJpcGxlUXVvdGVkU3RyaW5ncyddKSB7XG4gICAgICAvLyAnJydtdWx0aS1saW5lLXN0cmluZycnJywgJ3NpbmdsZS1saW5lLXN0cmluZycsIGFuZCBkb3VibGUtcXVvdGVkXG4gICAgICBzaG9ydGN1dFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBbUFJfU1RSSU5HLCAgL14oPzpcXCdcXCdcXCcoPzpbXlxcJ1xcXFxdfFxcXFxbXFxzXFxTXXxcXCd7MSwyfSg/PVteXFwnXSkpKig/OlxcJ1xcJ1xcJ3wkKXxcXFwiXFxcIlxcXCIoPzpbXlxcXCJcXFxcXXxcXFxcW1xcc1xcU118XFxcInsxLDJ9KD89W15cXFwiXSkpKig/OlxcXCJcXFwiXFxcInwkKXxcXCcoPzpbXlxcXFxcXCddfFxcXFxbXFxzXFxTXSkqKD86XFwnfCQpfFxcXCIoPzpbXlxcXFxcXFwiXXxcXFxcW1xcc1xcU10pKig/OlxcXCJ8JCkpLyxcbiAgICAgICAgICAgbnVsbCwgJ1xcJ1wiJ10pO1xuICAgIH0gZWxzZSBpZiAob3B0aW9uc1snbXVsdGlMaW5lU3RyaW5ncyddKSB7XG4gICAgICAvLyAnbXVsdGktbGluZS1zdHJpbmcnLCBcIm11bHRpLWxpbmUtc3RyaW5nXCJcbiAgICAgIHNob3J0Y3V0U3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIFtQUl9TVFJJTkcsICAvXig/OlxcJyg/OlteXFxcXFxcJ118XFxcXFtcXHNcXFNdKSooPzpcXCd8JCl8XFxcIig/OlteXFxcXFxcXCJdfFxcXFxbXFxzXFxTXSkqKD86XFxcInwkKXxcXGAoPzpbXlxcXFxcXGBdfFxcXFxbXFxzXFxTXSkqKD86XFxgfCQpKS8sXG4gICAgICAgICAgIG51bGwsICdcXCdcImAnXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vICdzaW5nbGUtbGluZS1zdHJpbmcnLCBcInNpbmdsZS1saW5lLXN0cmluZ1wiXG4gICAgICBzaG9ydGN1dFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBbUFJfU1RSSU5HLFxuICAgICAgICAgICAvXig/OlxcJyg/OlteXFxcXFxcJ1xcclxcbl18XFxcXC4pKig/OlxcJ3wkKXxcXFwiKD86W15cXFxcXFxcIlxcclxcbl18XFxcXC4pKig/OlxcXCJ8JCkpLyxcbiAgICAgICAgICAgbnVsbCwgJ1wiXFwnJ10pO1xuICAgIH1cbiAgICBpZiAob3B0aW9uc1sndmVyYmF0aW1TdHJpbmdzJ10pIHtcbiAgICAgIC8vIHZlcmJhdGltLXN0cmluZy1saXRlcmFsIHByb2R1Y3Rpb24gZnJvbSB0aGUgQyMgZ3JhbW1hci4gIFNlZSBpc3N1ZSA5My5cbiAgICAgIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIFtQUl9TVFJJTkcsIC9eQFxcXCIoPzpbXlxcXCJdfFxcXCJcXFwiKSooPzpcXFwifCQpLywgbnVsbF0pO1xuICAgIH1cbiAgICB2YXIgaGMgPSBvcHRpb25zWydoYXNoQ29tbWVudHMnXTtcbiAgICBpZiAoaGMpIHtcbiAgICAgIGlmIChvcHRpb25zWydjU3R5bGVDb21tZW50cyddKSB7XG4gICAgICAgIGlmIChoYyA+IDEpIHsgIC8vIG11bHRpbGluZSBoYXNoIGNvbW1lbnRzXG4gICAgICAgICAgc2hvcnRjdXRTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgICAgIFtQUl9DT01NRU5ULCAvXiMoPzojIyg/OlteI118Iyg/ISMjKSkqKD86IyMjfCQpfC4qKS8sIG51bGwsICcjJ10pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFN0b3AgQyBwcmVwcm9jZXNzb3IgZGVjbGFyYXRpb25zIGF0IGFuIHVuY2xvc2VkIG9wZW4gY29tbWVudFxuICAgICAgICAgIHNob3J0Y3V0U3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgICAgICBbUFJfQ09NTUVOVCwgL14jKD86KD86ZGVmaW5lfGUoPzpsfG5kKWlmfGVsc2V8ZXJyb3J8aWZuP2RlZnxpbmNsdWRlfGxpbmV8cHJhZ21hfHVuZGVmfHdhcm5pbmcpXFxifFteXFxyXFxuXSopLyxcbiAgICAgICAgICAgICAgIG51bGwsICcjJ10pO1xuICAgICAgICB9XG4gICAgICAgIC8vICNpbmNsdWRlIDxzdGRpby5oPlxuICAgICAgICBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICAgIFtQUl9TVFJJTkcsXG4gICAgICAgICAgICAgL148KD86KD86KD86XFwuXFwuXFwvKSp8XFwvPykoPzpbXFx3LV0rKD86XFwvW1xcdy1dKykrKT9bXFx3LV0rXFwuaCg/Omh8cHB8XFwrXFwrKT98W2Etel1cXHcqKT4vLFxuICAgICAgICAgICAgIG51bGxdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNob3J0Y3V0U3R5bGVQYXR0ZXJucy5wdXNoKFtQUl9DT01NRU5ULCAvXiNbXlxcclxcbl0qLywgbnVsbCwgJyMnXSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChvcHRpb25zWydjU3R5bGVDb21tZW50cyddKSB7XG4gICAgICBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMucHVzaChbUFJfQ09NTUVOVCwgL15cXC9cXC9bXlxcclxcbl0qLywgbnVsbF0pO1xuICAgICAgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgW1BSX0NPTU1FTlQsIC9eXFwvXFwqW1xcc1xcU10qPyg/OlxcKlxcL3wkKS8sIG51bGxdKTtcbiAgICB9XG4gICAgdmFyIHJlZ2V4TGl0ZXJhbHMgPSBvcHRpb25zWydyZWdleExpdGVyYWxzJ107XG4gICAgaWYgKHJlZ2V4TGl0ZXJhbHMpIHtcbiAgICAgIC8qKlxuICAgICAgICogQGNvbnN0XG4gICAgICAgKi9cbiAgICAgIHZhciByZWdleEV4Y2xzID0gcmVnZXhMaXRlcmFscyA+IDFcbiAgICAgICAgPyAnJyAgLy8gTXVsdGlsaW5lIHJlZ2V4IGxpdGVyYWxzXG4gICAgICAgIDogJ1xcblxccic7XG4gICAgICAvKipcbiAgICAgICAqIEBjb25zdFxuICAgICAgICovXG4gICAgICB2YXIgcmVnZXhBbnkgPSByZWdleEV4Y2xzID8gJy4nIDogJ1tcXFxcU1xcXFxzXSc7XG4gICAgICAvKipcbiAgICAgICAqIEBjb25zdFxuICAgICAgICovXG4gICAgICB2YXIgUkVHRVhfTElURVJBTCA9IChcbiAgICAgICAgICAvLyBBIHJlZ3VsYXIgZXhwcmVzc2lvbiBsaXRlcmFsIHN0YXJ0cyB3aXRoIGEgc2xhc2ggdGhhdCBpc1xuICAgICAgICAgIC8vIG5vdCBmb2xsb3dlZCBieSAqIG9yIC8gc28gdGhhdCBpdCBpcyBub3QgY29uZnVzZWQgd2l0aFxuICAgICAgICAgIC8vIGNvbW1lbnRzLlxuICAgICAgICAgICcvKD89W14vKicgKyByZWdleEV4Y2xzICsgJ10pJ1xuICAgICAgICAgIC8vIGFuZCB0aGVuIGNvbnRhaW5zIGFueSBudW1iZXIgb2YgcmF3IGNoYXJhY3RlcnMsXG4gICAgICAgICAgKyAnKD86W14vXFxcXHg1QlxcXFx4NUMnICsgcmVnZXhFeGNscyArICddJ1xuICAgICAgICAgIC8vIGVzY2FwZSBzZXF1ZW5jZXMgKFxceDVDKSxcbiAgICAgICAgICArICAgICd8XFxcXHg1QycgKyByZWdleEFueVxuICAgICAgICAgIC8vIG9yIG5vbi1uZXN0aW5nIGNoYXJhY3RlciBzZXRzIChcXHg1QlxceDVEKTtcbiAgICAgICAgICArICAgICd8XFxcXHg1Qig/OlteXFxcXHg1Q1xcXFx4NUQnICsgcmVnZXhFeGNscyArICddJ1xuICAgICAgICAgICsgICAgICAgICAgICAgJ3xcXFxceDVDJyArIHJlZ2V4QW55ICsgJykqKD86XFxcXHg1RHwkKSkrJ1xuICAgICAgICAgIC8vIGZpbmFsbHkgY2xvc2VkIGJ5IGEgLy5cbiAgICAgICAgICArICcvJyk7XG4gICAgICBmYWxsdGhyb3VnaFN0eWxlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBbJ2xhbmctcmVnZXgnLFxuICAgICAgICAgICBSZWdFeHAoJ14nICsgUkVHRVhQX1BSRUNFREVSX1BBVFRFUk4gKyAnKCcgKyBSRUdFWF9MSVRFUkFMICsgJyknKVxuICAgICAgICAgICBdKTtcbiAgICB9XG5cbiAgICB2YXIgdHlwZXMgPSBvcHRpb25zWyd0eXBlcyddO1xuICAgIGlmICh0eXBlcykge1xuICAgICAgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLnB1c2goW1BSX1RZUEUsIHR5cGVzXSk7XG4gICAgfVxuXG4gICAgdmFyIGtleXdvcmRzID0gKFwiXCIgKyBvcHRpb25zWydrZXl3b3JkcyddKS5yZXBsYWNlKC9eIHwgJC9nLCAnJyk7XG4gICAgaWYgKGtleXdvcmRzLmxlbmd0aCkge1xuICAgICAgZmFsbHRocm91Z2hTdHlsZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgW1BSX0tFWVdPUkQsXG4gICAgICAgICAgIG5ldyBSZWdFeHAoJ14oPzonICsga2V5d29yZHMucmVwbGFjZSgvW1xccyxdKy9nLCAnfCcpICsgJylcXFxcYicpLFxuICAgICAgICAgICBudWxsXSk7XG4gICAgfVxuXG4gICAgc2hvcnRjdXRTdHlsZVBhdHRlcm5zLnB1c2goW1BSX1BMQUlOLCAgICAgICAvXlxccysvLCBudWxsLCAnIFxcclxcblxcdFxceEEwJ10pO1xuXG4gICAgdmFyIHB1bmN0dWF0aW9uID1cbiAgICAgIC8vIFRoZSBCYXNoIG1hbiBwYWdlIHNheXNcblxuICAgICAgLy8gQSB3b3JkIGlzIGEgc2VxdWVuY2Ugb2YgY2hhcmFjdGVycyBjb25zaWRlcmVkIGFzIGEgc2luZ2xlXG4gICAgICAvLyB1bml0IGJ5IEdSVUIuIFdvcmRzIGFyZSBzZXBhcmF0ZWQgYnkgbWV0YWNoYXJhY3RlcnMsXG4gICAgICAvLyB3aGljaCBhcmUgdGhlIGZvbGxvd2luZyBwbHVzIHNwYWNlLCB0YWIsIGFuZCBuZXdsaW5lOiB7IH1cbiAgICAgIC8vIHwgJiAkIDsgPCA+XG4gICAgICAvLyAuLi5cbiAgICAgIFxuICAgICAgLy8gQSB3b3JkIGJlZ2lubmluZyB3aXRoICMgY2F1c2VzIHRoYXQgd29yZCBhbmQgYWxsIHJlbWFpbmluZ1xuICAgICAgLy8gY2hhcmFjdGVycyBvbiB0aGF0IGxpbmUgdG8gYmUgaWdub3JlZC5cblxuICAgICAgLy8gd2hpY2ggbWVhbnMgdGhhdCBvbmx5IGEgJyMnIGFmdGVyIC8oPzpefFt7fXwmJDs8Plxcc10pLyBzdGFydHMgYVxuICAgICAgLy8gY29tbWVudCBidXQgZW1waXJpY2FsbHlcbiAgICAgIC8vICQgZWNobyB7I31cbiAgICAgIC8vIHsjfVxuICAgICAgLy8gJCBlY2hvIFxcJCNcbiAgICAgIC8vICQjXG4gICAgICAvLyAkIGVjaG8gfSNcbiAgICAgIC8vIH0jXG5cbiAgICAgIC8vIHNvIC8oPzpefFt8Jjs8Plxcc10pLyBpcyBtb3JlIGFwcHJvcHJpYXRlLlxuXG4gICAgICAvLyBodHRwOi8vZ2NjLmdudS5vcmcvb25saW5lZG9jcy9nY2MtMi45NS4zL2NwcF8xLmh0bWwjU0VDM1xuICAgICAgLy8gc3VnZ2VzdHMgdGhhdCB0aGlzIGRlZmluaXRpb24gaXMgY29tcGF0aWJsZSB3aXRoIGFcbiAgICAgIC8vIGRlZmF1bHQgbW9kZSB0aGF0IHRyaWVzIHRvIHVzZSBhIHNpbmdsZSB0b2tlbiBkZWZpbml0aW9uXG4gICAgICAvLyB0byByZWNvZ25pemUgYm90aCBiYXNoL3B5dGhvbiBzdHlsZSBjb21tZW50cyBhbmQgQ1xuICAgICAgLy8gcHJlcHJvY2Vzc29yIGRpcmVjdGl2ZXMuXG5cbiAgICAgIC8vIFRoaXMgZGVmaW5pdGlvbiBvZiBwdW5jdHVhdGlvbiBkb2VzIG5vdCBpbmNsdWRlICMgaW4gdGhlIGxpc3Qgb2ZcbiAgICAgIC8vIGZvbGxvdy1vbiBleGNsdXNpb25zLCBzbyAjIHdpbGwgbm90IGJlIGJyb2tlbiBiZWZvcmUgaWYgcHJlY2VlZGVkXG4gICAgICAvLyBieSBhIHB1bmN0dWF0aW9uIGNoYXJhY3Rlci4gIFdlIGNvdWxkIHRyeSB0byBleGNsdWRlICMgYWZ0ZXJcbiAgICAgIC8vIFt8Jjs8Pl0gYnV0IHRoYXQgZG9lc24ndCBzZWVtIHRvIGNhdXNlIG1hbnkgbWFqb3IgcHJvYmxlbXMuXG4gICAgICAvLyBJZiB0aGF0IGRvZXMgdHVybiBvdXQgdG8gYmUgYSBwcm9ibGVtLCB3ZSBzaG91bGQgY2hhbmdlIHRoZSBiZWxvd1xuICAgICAgLy8gd2hlbiBoYyBpcyB0cnV0aHkgdG8gaW5jbHVkZSAjIGluIHRoZSBydW4gb2YgcHVuY3R1YXRpb24gY2hhcmFjdGVyc1xuICAgICAgLy8gb25seSB3aGVuIG5vdCBmb2xsb3dpbnQgW3wmOzw+XS5cbiAgICAgICdeLlteXFxcXHNcXFxcdy4kQFxcJ1wiYC9cXFxcXFxcXF0qJztcbiAgICBpZiAob3B0aW9uc1sncmVnZXhMaXRlcmFscyddKSB7XG4gICAgICBwdW5jdHVhdGlvbiArPSAnKD8hXFxzKlxcLyknO1xuICAgIH1cblxuICAgIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAvLyBUT0RPKG1pa2VzYW11ZWwpOiByZWNvZ25pemUgbm9uLWxhdGluIGxldHRlcnMgYW5kIG51bWVyYWxzIGluIGlkZW50c1xuICAgICAgICBbUFJfTElURVJBTCwgICAgIC9eQFthLXpfJF1bYS16XyRAMC05XSovaSwgbnVsbF0sXG4gICAgICAgIFtQUl9UWVBFLCAgICAgICAgL14oPzpbQF9dP1tBLVpdK1thLXpdW0EtWmEtel8kQDAtOV0qfFxcdytfdFxcYikvLCBudWxsXSxcbiAgICAgICAgW1BSX1BMQUlOLCAgICAgICAvXlthLXpfJF1bYS16XyRAMC05XSovaSwgbnVsbF0sXG4gICAgICAgIFtQUl9MSVRFUkFMLFxuICAgICAgICAgbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAnXig/OidcbiAgICAgICAgICAgICAvLyBBIGhleCBudW1iZXJcbiAgICAgICAgICAgICArICcweFthLWYwLTldKydcbiAgICAgICAgICAgICAvLyBvciBhbiBvY3RhbCBvciBkZWNpbWFsIG51bWJlcixcbiAgICAgICAgICAgICArICd8KD86XFxcXGQoPzpfXFxcXGQrKSpcXFxcZCooPzpcXFxcLlxcXFxkKik/fFxcXFwuXFxcXGRcXFxcKyknXG4gICAgICAgICAgICAgLy8gcG9zc2libHkgaW4gc2NpZW50aWZpYyBub3RhdGlvblxuICAgICAgICAgICAgICsgJyg/OmVbK1xcXFwtXT9cXFxcZCspPydcbiAgICAgICAgICAgICArICcpJ1xuICAgICAgICAgICAgIC8vIHdpdGggYW4gb3B0aW9uYWwgbW9kaWZpZXIgbGlrZSBVTCBmb3IgdW5zaWduZWQgbG9uZ1xuICAgICAgICAgICAgICsgJ1thLXpdKicsICdpJyksXG4gICAgICAgICBudWxsLCAnMDEyMzQ1Njc4OSddLFxuICAgICAgICAvLyBEb24ndCB0cmVhdCBlc2NhcGVkIHF1b3RlcyBpbiBiYXNoIGFzIHN0YXJ0aW5nIHN0cmluZ3MuXG4gICAgICAgIC8vIFNlZSBpc3N1ZSAxNDQuXG4gICAgICAgIFtQUl9QTEFJTiwgICAgICAgL15cXFxcW1xcc1xcU10/LywgbnVsbF0sXG4gICAgICAgIFtQUl9QVU5DVFVBVElPTiwgbmV3IFJlZ0V4cChwdW5jdHVhdGlvbiksIG51bGxdKTtcblxuICAgIHJldHVybiBjcmVhdGVTaW1wbGVMZXhlcihzaG9ydGN1dFN0eWxlUGF0dGVybnMsIGZhbGx0aHJvdWdoU3R5bGVQYXR0ZXJucyk7XG4gIH1cblxuICB2YXIgZGVjb3JhdGVTb3VyY2UgPSBzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAna2V5d29yZHMnOiBBTExfS0VZV09SRFMsXG4gICAgICAgICdoYXNoQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAnY1N0eWxlQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAnbXVsdGlMaW5lU3RyaW5ncyc6IHRydWUsXG4gICAgICAgICdyZWdleExpdGVyYWxzJzogdHJ1ZVxuICAgICAgfSk7XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgRE9NIHN1YnRyZWUsIHdyYXBzIGl0IGluIGEgbGlzdCwgYW5kIHB1dHMgZWFjaCBsaW5lIGludG8gaXRzIG93blxuICAgKiBsaXN0IGl0ZW0uXG4gICAqXG4gICAqIEBwYXJhbSB7Tm9kZX0gbm9kZSBtb2RpZmllZCBpbiBwbGFjZS4gIEl0cyBjb250ZW50IGlzIHB1bGxlZCBpbnRvIGFuXG4gICAqICAgICBIVE1MT0xpc3RFbGVtZW50LCBhbmQgZWFjaCBsaW5lIGlzIG1vdmVkIGludG8gYSBzZXBhcmF0ZSBsaXN0IGl0ZW0uXG4gICAqICAgICBUaGlzIHJlcXVpcmVzIGNsb25pbmcgZWxlbWVudHMsIHNvIHRoZSBpbnB1dCBtaWdodCBub3QgaGF2ZSB1bmlxdWVcbiAgICogICAgIElEcyBhZnRlciBudW1iZXJpbmcuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNQcmVmb3JtYXR0ZWQgdHJ1ZSBpZmYgd2hpdGUtc3BhY2UgaW4gdGV4dCBub2RlcyBzaG91bGRcbiAgICogICAgIGJlIHRyZWF0ZWQgYXMgc2lnbmlmaWNhbnQuXG4gICAqL1xuICBmdW5jdGlvbiBudW1iZXJMaW5lcyhub2RlLCBvcHRfc3RhcnRMaW5lTnVtLCBpc1ByZWZvcm1hdHRlZCkge1xuICAgIHZhciBub2NvZGUgPSAvKD86XnxcXHMpbm9jb2RlKD86XFxzfCQpLztcbiAgICB2YXIgbGluZUJyZWFrID0gL1xcclxcbj98XFxuLztcbiAgXG4gICAgdmFyIGRvY3VtZW50ID0gbm9kZS5vd25lckRvY3VtZW50O1xuICBcbiAgICB2YXIgbGkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpO1xuICAgIHdoaWxlIChub2RlLmZpcnN0Q2hpbGQpIHtcbiAgICAgIGxpLmFwcGVuZENoaWxkKG5vZGUuZmlyc3RDaGlsZCk7XG4gICAgfVxuICAgIC8vIEFuIGFycmF5IG9mIGxpbmVzLiAgV2Ugc3BsaXQgYmVsb3csIHNvIHRoaXMgaXMgaW5pdGlhbGl6ZWQgdG8gb25lXG4gICAgLy8gdW4tc3BsaXQgbGluZS5cbiAgICB2YXIgbGlzdEl0ZW1zID0gW2xpXTtcbiAgXG4gICAgZnVuY3Rpb24gd2Fsayhub2RlKSB7XG4gICAgICB2YXIgdHlwZSA9IG5vZGUubm9kZVR5cGU7XG4gICAgICBpZiAodHlwZSA9PSAxICYmICFub2NvZGUudGVzdChub2RlLmNsYXNzTmFtZSkpIHsgIC8vIEVsZW1lbnRcbiAgICAgICAgaWYgKCdicicgPT09IG5vZGUubm9kZU5hbWUpIHtcbiAgICAgICAgICBicmVha0FmdGVyKG5vZGUpO1xuICAgICAgICAgIC8vIERpc2NhcmQgdGhlIDxCUj4gc2luY2UgaXQgaXMgbm93IGZsdXNoIGFnYWluc3QgYSA8L0xJPi5cbiAgICAgICAgICBpZiAobm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICBub2RlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZvciAodmFyIGNoaWxkID0gbm9kZS5maXJzdENoaWxkOyBjaGlsZDsgY2hpbGQgPSBjaGlsZC5uZXh0U2libGluZykge1xuICAgICAgICAgICAgd2FsayhjaGlsZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCh0eXBlID09IDMgfHwgdHlwZSA9PSA0KSAmJiBpc1ByZWZvcm1hdHRlZCkgeyAgLy8gVGV4dFxuICAgICAgICB2YXIgdGV4dCA9IG5vZGUubm9kZVZhbHVlO1xuICAgICAgICB2YXIgbWF0Y2ggPSB0ZXh0Lm1hdGNoKGxpbmVCcmVhayk7XG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgIHZhciBmaXJzdExpbmUgPSB0ZXh0LnN1YnN0cmluZygwLCBtYXRjaC5pbmRleCk7XG4gICAgICAgICAgbm9kZS5ub2RlVmFsdWUgPSBmaXJzdExpbmU7XG4gICAgICAgICAgdmFyIHRhaWwgPSB0ZXh0LnN1YnN0cmluZyhtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aCk7XG4gICAgICAgICAgaWYgKHRhaWwpIHtcbiAgICAgICAgICAgIHZhciBwYXJlbnQgPSBub2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICBwYXJlbnQuaW5zZXJ0QmVmb3JlKFxuICAgICAgICAgICAgICBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh0YWlsKSwgbm9kZS5uZXh0U2libGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrQWZ0ZXIobm9kZSk7XG4gICAgICAgICAgaWYgKCFmaXJzdExpbmUpIHtcbiAgICAgICAgICAgIC8vIERvbid0IGxlYXZlIGJsYW5rIHRleHQgbm9kZXMgaW4gdGhlIERPTS5cbiAgICAgICAgICAgIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIFxuICAgIC8vIFNwbGl0IGEgbGluZSBhZnRlciB0aGUgZ2l2ZW4gbm9kZS5cbiAgICBmdW5jdGlvbiBicmVha0FmdGVyKGxpbmVFbmROb2RlKSB7XG4gICAgICAvLyBJZiB0aGVyZSdzIG5vdGhpbmcgdG8gdGhlIHJpZ2h0LCB0aGVuIHdlIGNhbiBza2lwIGVuZGluZyB0aGUgbGluZVxuICAgICAgLy8gaGVyZSwgYW5kIG1vdmUgcm9vdC13YXJkcyBzaW5jZSBzcGxpdHRpbmcganVzdCBiZWZvcmUgYW4gZW5kLXRhZ1xuICAgICAgLy8gd291bGQgcmVxdWlyZSB1cyB0byBjcmVhdGUgYSBidW5jaCBvZiBlbXB0eSBjb3BpZXMuXG4gICAgICB3aGlsZSAoIWxpbmVFbmROb2RlLm5leHRTaWJsaW5nKSB7XG4gICAgICAgIGxpbmVFbmROb2RlID0gbGluZUVuZE5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgaWYgKCFsaW5lRW5kTm9kZSkgeyByZXR1cm47IH1cbiAgICAgIH1cbiAgXG4gICAgICBmdW5jdGlvbiBicmVha0xlZnRPZihsaW1pdCwgY29weSkge1xuICAgICAgICAvLyBDbG9uZSBzaGFsbG93bHkgaWYgdGhpcyBub2RlIG5lZWRzIHRvIGJlIG9uIGJvdGggc2lkZXMgb2YgdGhlIGJyZWFrLlxuICAgICAgICB2YXIgcmlnaHRTaWRlID0gY29weSA/IGxpbWl0LmNsb25lTm9kZShmYWxzZSkgOiBsaW1pdDtcbiAgICAgICAgdmFyIHBhcmVudCA9IGxpbWl0LnBhcmVudE5vZGU7XG4gICAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgICAvLyBXZSBjbG9uZSB0aGUgcGFyZW50IGNoYWluLlxuICAgICAgICAgIC8vIFRoaXMgaGVscHMgdXMgcmVzdXJyZWN0IGltcG9ydGFudCBzdHlsaW5nIGVsZW1lbnRzIHRoYXQgY3Jvc3MgbGluZXMuXG4gICAgICAgICAgLy8gRS5nLiBpbiA8aT5Gb288YnI+QmFyPC9pPlxuICAgICAgICAgIC8vIHNob3VsZCBiZSByZXdyaXR0ZW4gdG8gPGxpPjxpPkZvbzwvaT48L2xpPjxsaT48aT5CYXI8L2k+PC9saT4uXG4gICAgICAgICAgdmFyIHBhcmVudENsb25lID0gYnJlYWtMZWZ0T2YocGFyZW50LCAxKTtcbiAgICAgICAgICAvLyBNb3ZlIHRoZSBjbG9uZSBhbmQgZXZlcnl0aGluZyB0byB0aGUgcmlnaHQgb2YgdGhlIG9yaWdpbmFsXG4gICAgICAgICAgLy8gb250byB0aGUgY2xvbmVkIHBhcmVudC5cbiAgICAgICAgICB2YXIgbmV4dCA9IGxpbWl0Lm5leHRTaWJsaW5nO1xuICAgICAgICAgIHBhcmVudENsb25lLmFwcGVuZENoaWxkKHJpZ2h0U2lkZSk7XG4gICAgICAgICAgZm9yICh2YXIgc2libGluZyA9IG5leHQ7IHNpYmxpbmc7IHNpYmxpbmcgPSBuZXh0KSB7XG4gICAgICAgICAgICBuZXh0ID0gc2libGluZy5uZXh0U2libGluZztcbiAgICAgICAgICAgIHBhcmVudENsb25lLmFwcGVuZENoaWxkKHNpYmxpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmlnaHRTaWRlO1xuICAgICAgfVxuICBcbiAgICAgIHZhciBjb3BpZWRMaXN0SXRlbSA9IGJyZWFrTGVmdE9mKGxpbmVFbmROb2RlLm5leHRTaWJsaW5nLCAwKTtcbiAgXG4gICAgICAvLyBXYWxrIHRoZSBwYXJlbnQgY2hhaW4gdW50aWwgd2UgcmVhY2ggYW4gdW5hdHRhY2hlZCBMSS5cbiAgICAgIGZvciAodmFyIHBhcmVudDtcbiAgICAgICAgICAgLy8gQ2hlY2sgbm9kZVR5cGUgc2luY2UgSUUgaW52ZW50cyBkb2N1bWVudCBmcmFnbWVudHMuXG4gICAgICAgICAgIChwYXJlbnQgPSBjb3BpZWRMaXN0SXRlbS5wYXJlbnROb2RlKSAmJiBwYXJlbnQubm9kZVR5cGUgPT09IDE7KSB7XG4gICAgICAgIGNvcGllZExpc3RJdGVtID0gcGFyZW50O1xuICAgICAgfVxuICAgICAgLy8gUHV0IGl0IG9uIHRoZSBsaXN0IG9mIGxpbmVzIGZvciBsYXRlciBwcm9jZXNzaW5nLlxuICAgICAgbGlzdEl0ZW1zLnB1c2goY29waWVkTGlzdEl0ZW0pO1xuICAgIH1cbiAgXG4gICAgLy8gU3BsaXQgbGluZXMgd2hpbGUgdGhlcmUgYXJlIGxpbmVzIGxlZnQgdG8gc3BsaXQuXG4gICAgZm9yICh2YXIgaSA9IDA7ICAvLyBOdW1iZXIgb2YgbGluZXMgdGhhdCBoYXZlIGJlZW4gc3BsaXQgc28gZmFyLlxuICAgICAgICAgaSA8IGxpc3RJdGVtcy5sZW5ndGg7ICAvLyBsZW5ndGggdXBkYXRlZCBieSBicmVha0FmdGVyIGNhbGxzLlxuICAgICAgICAgKytpKSB7XG4gICAgICB3YWxrKGxpc3RJdGVtc1tpXSk7XG4gICAgfVxuICBcbiAgICAvLyBNYWtlIHN1cmUgbnVtZXJpYyBpbmRpY2VzIHNob3cgY29ycmVjdGx5LlxuICAgIGlmIChvcHRfc3RhcnRMaW5lTnVtID09PSAob3B0X3N0YXJ0TGluZU51bXwwKSkge1xuICAgICAgbGlzdEl0ZW1zWzBdLnNldEF0dHJpYnV0ZSgndmFsdWUnLCBvcHRfc3RhcnRMaW5lTnVtKTtcbiAgICB9XG4gIFxuICAgIHZhciBvbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29sJyk7XG4gICAgb2wuY2xhc3NOYW1lID0gJ2xpbmVudW1zJztcbiAgICB2YXIgb2Zmc2V0ID0gTWF0aC5tYXgoMCwgKChvcHRfc3RhcnRMaW5lTnVtIC0gMSAvKiB6ZXJvIGluZGV4ICovKSkgfCAwKSB8fCAwO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbGlzdEl0ZW1zLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgbGkgPSBsaXN0SXRlbXNbaV07XG4gICAgICAvLyBTdGljayBhIGNsYXNzIG9uIHRoZSBMSXMgc28gdGhhdCBzdHlsZXNoZWV0cyBjYW5cbiAgICAgIC8vIGNvbG9yIG9kZC9ldmVuIHJvd3MsIG9yIGFueSBvdGhlciByb3cgcGF0dGVybiB0aGF0XG4gICAgICAvLyBpcyBjby1wcmltZSB3aXRoIDEwLlxuICAgICAgbGkuY2xhc3NOYW1lID0gJ0wnICsgKChpICsgb2Zmc2V0KSAlIDEwKTtcbiAgICAgIGlmICghbGkuZmlyc3RDaGlsZCkge1xuICAgICAgICBsaS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnXFx4QTAnKSk7XG4gICAgICB9XG4gICAgICBvbC5hcHBlbmRDaGlsZChsaSk7XG4gICAgfVxuICBcbiAgICBub2RlLmFwcGVuZENoaWxkKG9sKTtcbiAgfVxuICAvKipcbiAgICogQnJlYWtzIHtAY29kZSBqb2Iuc291cmNlQ29kZX0gYXJvdW5kIHN0eWxlIGJvdW5kYXJpZXMgaW5cbiAgICoge0Bjb2RlIGpvYi5kZWNvcmF0aW9uc30gYW5kIG1vZGlmaWVzIHtAY29kZSBqb2Iuc291cmNlTm9kZX0gaW4gcGxhY2UuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBqb2IgbGlrZSA8cHJlPntcbiAgICogICAgc291cmNlQ29kZToge3N0cmluZ30gc291cmNlIGFzIHBsYWluIHRleHQsXG4gICAqICAgIHNvdXJjZU5vZGU6IHtIVE1MRWxlbWVudH0gdGhlIGVsZW1lbnQgY29udGFpbmluZyB0aGUgc291cmNlLFxuICAgKiAgICBzcGFuczoge0FycmF5LjxudW1iZXJ8Tm9kZT59IGFsdGVybmF0aW5nIHNwYW4gc3RhcnQgaW5kaWNlcyBpbnRvIHNvdXJjZVxuICAgKiAgICAgICBhbmQgdGhlIHRleHQgbm9kZSBvciBlbGVtZW50IChlLmcuIHtAY29kZSA8QlI+fSkgY29ycmVzcG9uZGluZyB0byB0aGF0XG4gICAqICAgICAgIHNwYW4uXG4gICAqICAgIGRlY29yYXRpb25zOiB7QXJyYXkuPG51bWJlcnxzdHJpbmd9IGFuIGFycmF5IG9mIHN0eWxlIGNsYXNzZXMgcHJlY2VkZWRcbiAgICogICAgICAgYnkgdGhlIHBvc2l0aW9uIGF0IHdoaWNoIHRoZXkgc3RhcnQgaW4gam9iLnNvdXJjZUNvZGUgaW4gb3JkZXJcbiAgICogfTwvcHJlPlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZnVuY3Rpb24gcmVjb21iaW5lVGFnc0FuZERlY29yYXRpb25zKGpvYikge1xuICAgIHZhciBpc0lFOE9yRWFybGllciA9IC9cXGJNU0lFXFxzKFxcZCspLy5leGVjKG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgIGlzSUU4T3JFYXJsaWVyID0gaXNJRThPckVhcmxpZXIgJiYgK2lzSUU4T3JFYXJsaWVyWzFdIDw9IDg7XG4gICAgdmFyIG5ld2xpbmVSZSA9IC9cXG4vZztcbiAgXG4gICAgdmFyIHNvdXJjZSA9IGpvYi5zb3VyY2VDb2RlO1xuICAgIHZhciBzb3VyY2VMZW5ndGggPSBzb3VyY2UubGVuZ3RoO1xuICAgIC8vIEluZGV4IGludG8gc291cmNlIGFmdGVyIHRoZSBsYXN0IGNvZGUtdW5pdCByZWNvbWJpbmVkLlxuICAgIHZhciBzb3VyY2VJbmRleCA9IDA7XG4gIFxuICAgIHZhciBzcGFucyA9IGpvYi5zcGFucztcbiAgICB2YXIgblNwYW5zID0gc3BhbnMubGVuZ3RoO1xuICAgIC8vIEluZGV4IGludG8gc3BhbnMgYWZ0ZXIgdGhlIGxhc3Qgc3BhbiB3aGljaCBlbmRzIGF0IG9yIGJlZm9yZSBzb3VyY2VJbmRleC5cbiAgICB2YXIgc3BhbkluZGV4ID0gMDtcbiAgXG4gICAgdmFyIGRlY29yYXRpb25zID0gam9iLmRlY29yYXRpb25zO1xuICAgIHZhciBuRGVjb3JhdGlvbnMgPSBkZWNvcmF0aW9ucy5sZW5ndGg7XG4gICAgLy8gSW5kZXggaW50byBkZWNvcmF0aW9ucyBhZnRlciB0aGUgbGFzdCBkZWNvcmF0aW9uIHdoaWNoIGVuZHMgYXQgb3IgYmVmb3JlXG4gICAgLy8gc291cmNlSW5kZXguXG4gICAgdmFyIGRlY29yYXRpb25JbmRleCA9IDA7XG4gIFxuICAgIC8vIFJlbW92ZSBhbGwgemVyby1sZW5ndGggZGVjb3JhdGlvbnMuXG4gICAgZGVjb3JhdGlvbnNbbkRlY29yYXRpb25zXSA9IHNvdXJjZUxlbmd0aDtcbiAgICB2YXIgZGVjUG9zLCBpO1xuICAgIGZvciAoaSA9IGRlY1BvcyA9IDA7IGkgPCBuRGVjb3JhdGlvbnM7KSB7XG4gICAgICBpZiAoZGVjb3JhdGlvbnNbaV0gIT09IGRlY29yYXRpb25zW2kgKyAyXSkge1xuICAgICAgICBkZWNvcmF0aW9uc1tkZWNQb3MrK10gPSBkZWNvcmF0aW9uc1tpKytdO1xuICAgICAgICBkZWNvcmF0aW9uc1tkZWNQb3MrK10gPSBkZWNvcmF0aW9uc1tpKytdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaSArPSAyO1xuICAgICAgfVxuICAgIH1cbiAgICBuRGVjb3JhdGlvbnMgPSBkZWNQb3M7XG4gIFxuICAgIC8vIFNpbXBsaWZ5IGRlY29yYXRpb25zLlxuICAgIGZvciAoaSA9IGRlY1BvcyA9IDA7IGkgPCBuRGVjb3JhdGlvbnM7KSB7XG4gICAgICB2YXIgc3RhcnRQb3MgPSBkZWNvcmF0aW9uc1tpXTtcbiAgICAgIC8vIENvbmZsYXRlIGFsbCBhZGphY2VudCBkZWNvcmF0aW9ucyB0aGF0IHVzZSB0aGUgc2FtZSBzdHlsZS5cbiAgICAgIHZhciBzdGFydERlYyA9IGRlY29yYXRpb25zW2kgKyAxXTtcbiAgICAgIHZhciBlbmQgPSBpICsgMjtcbiAgICAgIHdoaWxlIChlbmQgKyAyIDw9IG5EZWNvcmF0aW9ucyAmJiBkZWNvcmF0aW9uc1tlbmQgKyAxXSA9PT0gc3RhcnREZWMpIHtcbiAgICAgICAgZW5kICs9IDI7XG4gICAgICB9XG4gICAgICBkZWNvcmF0aW9uc1tkZWNQb3MrK10gPSBzdGFydFBvcztcbiAgICAgIGRlY29yYXRpb25zW2RlY1BvcysrXSA9IHN0YXJ0RGVjO1xuICAgICAgaSA9IGVuZDtcbiAgICB9XG4gIFxuICAgIG5EZWNvcmF0aW9ucyA9IGRlY29yYXRpb25zLmxlbmd0aCA9IGRlY1BvcztcbiAgXG4gICAgdmFyIHNvdXJjZU5vZGUgPSBqb2Iuc291cmNlTm9kZTtcbiAgICB2YXIgb2xkRGlzcGxheTtcbiAgICBpZiAoc291cmNlTm9kZSkge1xuICAgICAgb2xkRGlzcGxheSA9IHNvdXJjZU5vZGUuc3R5bGUuZGlzcGxheTtcbiAgICAgIHNvdXJjZU5vZGUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIHZhciBkZWNvcmF0aW9uID0gbnVsbDtcbiAgICAgIHdoaWxlIChzcGFuSW5kZXggPCBuU3BhbnMpIHtcbiAgICAgICAgdmFyIHNwYW5TdGFydCA9IHNwYW5zW3NwYW5JbmRleF07XG4gICAgICAgIHZhciBzcGFuRW5kID0gc3BhbnNbc3BhbkluZGV4ICsgMl0gfHwgc291cmNlTGVuZ3RoO1xuICBcbiAgICAgICAgdmFyIGRlY0VuZCA9IGRlY29yYXRpb25zW2RlY29yYXRpb25JbmRleCArIDJdIHx8IHNvdXJjZUxlbmd0aDtcbiAgXG4gICAgICAgIHZhciBlbmQgPSBNYXRoLm1pbihzcGFuRW5kLCBkZWNFbmQpO1xuICBcbiAgICAgICAgdmFyIHRleHROb2RlID0gc3BhbnNbc3BhbkluZGV4ICsgMV07XG4gICAgICAgIHZhciBzdHlsZWRUZXh0O1xuICAgICAgICBpZiAodGV4dE5vZGUubm9kZVR5cGUgIT09IDEgIC8vIERvbid0IG11Y2sgd2l0aCA8QlI+cyBvciA8TEk+c1xuICAgICAgICAgICAgLy8gRG9uJ3QgaW50cm9kdWNlIHNwYW5zIGFyb3VuZCBlbXB0eSB0ZXh0IG5vZGVzLlxuICAgICAgICAgICAgJiYgKHN0eWxlZFRleHQgPSBzb3VyY2Uuc3Vic3RyaW5nKHNvdXJjZUluZGV4LCBlbmQpKSkge1xuICAgICAgICAgIC8vIFRoaXMgbWF5IHNlZW0gYml6YXJyZSwgYW5kIGl0IGlzLiAgRW1pdHRpbmcgTEYgb24gSUUgY2F1c2VzIHRoZVxuICAgICAgICAgIC8vIGNvZGUgdG8gZGlzcGxheSB3aXRoIHNwYWNlcyBpbnN0ZWFkIG9mIGxpbmUgYnJlYWtzLlxuICAgICAgICAgIC8vIEVtaXR0aW5nIFdpbmRvd3Mgc3RhbmRhcmQgaXNzdWUgbGluZWJyZWFrcyAoQ1JMRikgY2F1c2VzIGEgYmxhbmtcbiAgICAgICAgICAvLyBzcGFjZSB0byBhcHBlYXIgYXQgdGhlIGJlZ2lubmluZyBvZiBldmVyeSBsaW5lIGJ1dCB0aGUgZmlyc3QuXG4gICAgICAgICAgLy8gRW1pdHRpbmcgYW4gb2xkIE1hYyBPUyA5IGxpbmUgc2VwYXJhdG9yIG1ha2VzIGV2ZXJ5dGhpbmcgc3BpZmZ5LlxuICAgICAgICAgIGlmIChpc0lFOE9yRWFybGllcikge1xuICAgICAgICAgICAgc3R5bGVkVGV4dCA9IHN0eWxlZFRleHQucmVwbGFjZShuZXdsaW5lUmUsICdcXHInKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGV4dE5vZGUubm9kZVZhbHVlID0gc3R5bGVkVGV4dDtcbiAgICAgICAgICB2YXIgZG9jdW1lbnQgPSB0ZXh0Tm9kZS5vd25lckRvY3VtZW50O1xuICAgICAgICAgIHZhciBzcGFuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgICAgICAgIHNwYW4uY2xhc3NOYW1lID0gZGVjb3JhdGlvbnNbZGVjb3JhdGlvbkluZGV4ICsgMV07XG4gICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSB0ZXh0Tm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKHNwYW4sIHRleHROb2RlKTtcbiAgICAgICAgICBzcGFuLmFwcGVuZENoaWxkKHRleHROb2RlKTtcbiAgICAgICAgICBpZiAoc291cmNlSW5kZXggPCBzcGFuRW5kKSB7ICAvLyBTcGxpdCBvZmYgYSB0ZXh0IG5vZGUuXG4gICAgICAgICAgICBzcGFuc1tzcGFuSW5kZXggKyAxXSA9IHRleHROb2RlXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogUG9zc2libHkgb3B0aW1pemUgYnkgdXNpbmcgJycgaWYgdGhlcmUncyBubyBmbGlja2VyLlxuICAgICAgICAgICAgICAgID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoc291cmNlLnN1YnN0cmluZyhlbmQsIHNwYW5FbmQpKTtcbiAgICAgICAgICAgIHBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRleHROb2RlLCBzcGFuLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgXG4gICAgICAgIHNvdXJjZUluZGV4ID0gZW5kO1xuICBcbiAgICAgICAgaWYgKHNvdXJjZUluZGV4ID49IHNwYW5FbmQpIHtcbiAgICAgICAgICBzcGFuSW5kZXggKz0gMjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc291cmNlSW5kZXggPj0gZGVjRW5kKSB7XG4gICAgICAgICAgZGVjb3JhdGlvbkluZGV4ICs9IDI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKHNvdXJjZU5vZGUpIHtcbiAgICAgICAgc291cmNlTm9kZS5zdHlsZS5kaXNwbGF5ID0gb2xkRGlzcGxheTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiogTWFwcyBsYW5ndWFnZS1zcGVjaWZpYyBmaWxlIGV4dGVuc2lvbnMgdG8gaGFuZGxlcnMuICovXG4gIHZhciBsYW5nSGFuZGxlclJlZ2lzdHJ5ID0ge307XG4gIC8qKiBSZWdpc3RlciBhIGxhbmd1YWdlIGhhbmRsZXIgZm9yIHRoZSBnaXZlbiBmaWxlIGV4dGVuc2lvbnMuXG4gICAgKiBAcGFyYW0ge2Z1bmN0aW9uIChPYmplY3QpfSBoYW5kbGVyIGEgZnVuY3Rpb24gZnJvbSBzb3VyY2UgY29kZSB0byBhIGxpc3RcbiAgICAqICAgICAgb2YgZGVjb3JhdGlvbnMuICBUYWtlcyBhIHNpbmdsZSBhcmd1bWVudCBqb2Igd2hpY2ggZGVzY3JpYmVzIHRoZVxuICAgICogICAgICBzdGF0ZSBvZiB0aGUgY29tcHV0YXRpb24uICAgVGhlIHNpbmdsZSBwYXJhbWV0ZXIgaGFzIHRoZSBmb3JtXG4gICAgKiAgICAgIHtAY29kZSB7XG4gICAgKiAgICAgICAgc291cmNlQ29kZToge3N0cmluZ30gYXMgcGxhaW4gdGV4dC5cbiAgICAqICAgICAgICBkZWNvcmF0aW9uczoge0FycmF5LjxudW1iZXJ8c3RyaW5nPn0gYW4gYXJyYXkgb2Ygc3R5bGUgY2xhc3Nlc1xuICAgICogICAgICAgICAgICAgICAgICAgICBwcmVjZWRlZCBieSB0aGUgcG9zaXRpb24gYXQgd2hpY2ggdGhleSBzdGFydCBpblxuICAgICogICAgICAgICAgICAgICAgICAgICBqb2Iuc291cmNlQ29kZSBpbiBvcmRlci5cbiAgICAqICAgICAgICAgICAgICAgICAgICAgVGhlIGxhbmd1YWdlIGhhbmRsZXIgc2hvdWxkIGFzc2lnbmVkIHRoaXMgZmllbGQuXG4gICAgKiAgICAgICAgYmFzZVBvczoge2ludH0gdGhlIHBvc2l0aW9uIG9mIHNvdXJjZSBpbiB0aGUgbGFyZ2VyIHNvdXJjZSBjaHVuay5cbiAgICAqICAgICAgICAgICAgICAgICBBbGwgcG9zaXRpb25zIGluIHRoZSBvdXRwdXQgZGVjb3JhdGlvbnMgYXJyYXkgYXJlIHJlbGF0aXZlXG4gICAgKiAgICAgICAgICAgICAgICAgdG8gdGhlIGxhcmdlciBzb3VyY2UgY2h1bmsuXG4gICAgKiAgICAgIH0gfVxuICAgICogQHBhcmFtIHtBcnJheS48c3RyaW5nPn0gZmlsZUV4dGVuc2lvbnNcbiAgICAqL1xuICBmdW5jdGlvbiByZWdpc3RlckxhbmdIYW5kbGVyKGhhbmRsZXIsIGZpbGVFeHRlbnNpb25zKSB7XG4gICAgZm9yICh2YXIgaSA9IGZpbGVFeHRlbnNpb25zLmxlbmd0aDsgLS1pID49IDA7KSB7XG4gICAgICB2YXIgZXh0ID0gZmlsZUV4dGVuc2lvbnNbaV07XG4gICAgICBpZiAoIWxhbmdIYW5kbGVyUmVnaXN0cnkuaGFzT3duUHJvcGVydHkoZXh0KSkge1xuICAgICAgICBsYW5nSGFuZGxlclJlZ2lzdHJ5W2V4dF0gPSBoYW5kbGVyO1xuICAgICAgfSBlbHNlIGlmICh3aW5bJ2NvbnNvbGUnXSkge1xuICAgICAgICBjb25zb2xlWyd3YXJuJ10oJ2Nhbm5vdCBvdmVycmlkZSBsYW5ndWFnZSBoYW5kbGVyICVzJywgZXh0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gbGFuZ0hhbmRsZXJGb3JFeHRlbnNpb24oZXh0ZW5zaW9uLCBzb3VyY2UpIHtcbiAgICBpZiAoIShleHRlbnNpb24gJiYgbGFuZ0hhbmRsZXJSZWdpc3RyeS5oYXNPd25Qcm9wZXJ0eShleHRlbnNpb24pKSkge1xuICAgICAgLy8gVHJlYXQgaXQgYXMgbWFya3VwIGlmIHRoZSBmaXJzdCBub24gd2hpdGVzcGFjZSBjaGFyYWN0ZXIgaXMgYSA8IGFuZFxuICAgICAgLy8gdGhlIGxhc3Qgbm9uLXdoaXRlc3BhY2UgY2hhcmFjdGVyIGlzIGEgPi5cbiAgICAgIGV4dGVuc2lvbiA9IC9eXFxzKjwvLnRlc3Qoc291cmNlKVxuICAgICAgICAgID8gJ2RlZmF1bHQtbWFya3VwJ1xuICAgICAgICAgIDogJ2RlZmF1bHQtY29kZSc7XG4gICAgfVxuICAgIHJldHVybiBsYW5nSGFuZGxlclJlZ2lzdHJ5W2V4dGVuc2lvbl07XG4gIH1cbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihkZWNvcmF0ZVNvdXJjZSwgWydkZWZhdWx0LWNvZGUnXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoXG4gICAgICBjcmVhdGVTaW1wbGVMZXhlcihcbiAgICAgICAgICBbXSxcbiAgICAgICAgICBbXG4gICAgICAgICAgIFtQUl9QTEFJTiwgICAgICAgL15bXjw/XSsvXSxcbiAgICAgICAgICAgW1BSX0RFQ0xBUkFUSU9OLCAvXjwhXFx3W14+XSooPzo+fCQpL10sXG4gICAgICAgICAgIFtQUl9DT01NRU5ULCAgICAgL148XFwhLS1bXFxzXFxTXSo/KD86LVxcLT58JCkvXSxcbiAgICAgICAgICAgLy8gVW5lc2NhcGVkIGNvbnRlbnQgaW4gYW4gdW5rbm93biBsYW5ndWFnZVxuICAgICAgICAgICBbJ2xhbmctJywgICAgICAgIC9ePFxcPyhbXFxzXFxTXSs/KSg/OlxcPz58JCkvXSxcbiAgICAgICAgICAgWydsYW5nLScsICAgICAgICAvXjwlKFtcXHNcXFNdKz8pKD86JT58JCkvXSxcbiAgICAgICAgICAgW1BSX1BVTkNUVUFUSU9OLCAvXig/OjxbJT9dfFslP10+KS9dLFxuICAgICAgICAgICBbJ2xhbmctJywgICAgICAgIC9ePHhtcFxcYltePl0qPihbXFxzXFxTXSs/KTxcXC94bXBcXGJbXj5dKj4vaV0sXG4gICAgICAgICAgIC8vIFVuZXNjYXBlZCBjb250ZW50IGluIGphdmFzY3JpcHQuICAoT3IgcG9zc2libHkgdmJzY3JpcHQpLlxuICAgICAgICAgICBbJ2xhbmctanMnLCAgICAgIC9ePHNjcmlwdFxcYltePl0qPihbXFxzXFxTXSo/KSg8XFwvc2NyaXB0XFxiW14+XSo+KS9pXSxcbiAgICAgICAgICAgLy8gQ29udGFpbnMgdW5lc2NhcGVkIHN0eWxlc2hlZXQgY29udGVudFxuICAgICAgICAgICBbJ2xhbmctY3NzJywgICAgIC9ePHN0eWxlXFxiW14+XSo+KFtcXHNcXFNdKj8pKDxcXC9zdHlsZVxcYltePl0qPikvaV0sXG4gICAgICAgICAgIFsnbGFuZy1pbi50YWcnLCAgL14oPFxcLz9bYS16XVtePD5dKj4pL2ldXG4gICAgICAgICAgXSksXG4gICAgICBbJ2RlZmF1bHQtbWFya3VwJywgJ2h0bScsICdodG1sJywgJ214bWwnLCAneGh0bWwnLCAneG1sJywgJ3hzbCddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihcbiAgICAgIGNyZWF0ZVNpbXBsZUxleGVyKFxuICAgICAgICAgIFtcbiAgICAgICAgICAgW1BSX1BMQUlOLCAgICAgICAgL15bXFxzXSsvLCBudWxsLCAnIFxcdFxcclxcbiddLFxuICAgICAgICAgICBbUFJfQVRUUklCX1ZBTFVFLCAvXig/OlxcXCJbXlxcXCJdKlxcXCI/fFxcJ1teXFwnXSpcXCc/KS8sIG51bGwsICdcXFwiXFwnJ11cbiAgICAgICAgICAgXSxcbiAgICAgICAgICBbXG4gICAgICAgICAgIFtQUl9UQUcsICAgICAgICAgIC9eXjxcXC8/W2Etel0oPzpbXFx3LjotXSpcXHcpP3xcXC8/PiQvaV0sXG4gICAgICAgICAgIFtQUl9BVFRSSUJfTkFNRSwgIC9eKD8hc3R5bGVbXFxzPV18b24pW2Etel0oPzpbXFx3Oi1dKlxcdyk/L2ldLFxuICAgICAgICAgICBbJ2xhbmctdXEudmFsJywgICAvXj1cXHMqKFtePlxcJ1xcXCJcXHNdKig/OltePlxcJ1xcXCJcXHNcXC9dfFxcLyg/PVxccykpKS9dLFxuICAgICAgICAgICBbUFJfUFVOQ1RVQVRJT04sICAvXls9PD5cXC9dKy9dLFxuICAgICAgICAgICBbJ2xhbmctanMnLCAgICAgICAvXm9uXFx3K1xccyo9XFxzKlxcXCIoW15cXFwiXSspXFxcIi9pXSxcbiAgICAgICAgICAgWydsYW5nLWpzJywgICAgICAgL15vblxcdytcXHMqPVxccypcXCcoW15cXCddKylcXCcvaV0sXG4gICAgICAgICAgIFsnbGFuZy1qcycsICAgICAgIC9eb25cXHcrXFxzKj1cXHMqKFteXFxcIlxcJz5cXHNdKykvaV0sXG4gICAgICAgICAgIFsnbGFuZy1jc3MnLCAgICAgIC9ec3R5bGVcXHMqPVxccypcXFwiKFteXFxcIl0rKVxcXCIvaV0sXG4gICAgICAgICAgIFsnbGFuZy1jc3MnLCAgICAgIC9ec3R5bGVcXHMqPVxccypcXCcoW15cXCddKylcXCcvaV0sXG4gICAgICAgICAgIFsnbGFuZy1jc3MnLCAgICAgIC9ec3R5bGVcXHMqPVxccyooW15cXFwiXFwnPlxcc10rKS9pXVxuICAgICAgICAgICBdKSxcbiAgICAgIFsnaW4udGFnJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKFxuICAgICAgY3JlYXRlU2ltcGxlTGV4ZXIoW10sIFtbUFJfQVRUUklCX1ZBTFVFLCAvXltcXHNcXFNdKy9dXSksIFsndXEudmFsJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogQ1BQX0tFWVdPUkRTLFxuICAgICAgICAgICdoYXNoQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdjU3R5bGVDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ3R5cGVzJzogQ19UWVBFU1xuICAgICAgICB9KSwgWydjJywgJ2NjJywgJ2NwcCcsICdjeHgnLCAnY3ljJywgJ20nXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiAnbnVsbCx0cnVlLGZhbHNlJ1xuICAgICAgICB9KSwgWydqc29uJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogQ1NIQVJQX0tFWVdPUkRTLFxuICAgICAgICAgICdoYXNoQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdjU3R5bGVDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ3ZlcmJhdGltU3RyaW5ncyc6IHRydWUsXG4gICAgICAgICAgJ3R5cGVzJzogQ19UWVBFU1xuICAgICAgICB9KSwgWydjcyddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IEpBVkFfS0VZV09SRFMsXG4gICAgICAgICAgJ2NTdHlsZUNvbW1lbnRzJzogdHJ1ZVxuICAgICAgICB9KSwgWydqYXZhJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogU0hfS0VZV09SRFMsXG4gICAgICAgICAgJ2hhc2hDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ211bHRpTGluZVN0cmluZ3MnOiB0cnVlXG4gICAgICAgIH0pLCBbJ2Jhc2gnLCAnYnNoJywgJ2NzaCcsICdzaCddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IFBZVEhPTl9LRVlXT1JEUyxcbiAgICAgICAgICAnaGFzaENvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAnbXVsdGlMaW5lU3RyaW5ncyc6IHRydWUsXG4gICAgICAgICAgJ3RyaXBsZVF1b3RlZFN0cmluZ3MnOiB0cnVlXG4gICAgICAgIH0pLCBbJ2N2JywgJ3B5JywgJ3B5dGhvbiddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IFBFUkxfS0VZV09SRFMsXG4gICAgICAgICAgJ2hhc2hDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ211bHRpTGluZVN0cmluZ3MnOiB0cnVlLFxuICAgICAgICAgICdyZWdleExpdGVyYWxzJzogMiAgLy8gbXVsdGlsaW5lIHJlZ2V4IGxpdGVyYWxzXG4gICAgICAgIH0pLCBbJ3BlcmwnLCAncGwnLCAncG0nXSk7XG4gIHJlZ2lzdGVyTGFuZ0hhbmRsZXIoc291cmNlRGVjb3JhdG9yKHtcbiAgICAgICAgICAna2V5d29yZHMnOiBSVUJZX0tFWVdPUkRTLFxuICAgICAgICAgICdoYXNoQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdtdWx0aUxpbmVTdHJpbmdzJzogdHJ1ZSxcbiAgICAgICAgICAncmVnZXhMaXRlcmFscyc6IHRydWVcbiAgICAgICAgfSksIFsncmInLCAncnVieSddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IEpTQ1JJUFRfS0VZV09SRFMsXG4gICAgICAgICAgJ2NTdHlsZUNvbW1lbnRzJzogdHJ1ZSxcbiAgICAgICAgICAncmVnZXhMaXRlcmFscyc6IHRydWVcbiAgICAgICAgfSksIFsnamF2YXNjcmlwdCcsICdqcyddKTtcbiAgcmVnaXN0ZXJMYW5nSGFuZGxlcihzb3VyY2VEZWNvcmF0b3Ioe1xuICAgICAgICAgICdrZXl3b3Jkcyc6IENPRkZFRV9LRVlXT1JEUyxcbiAgICAgICAgICAnaGFzaENvbW1lbnRzJzogMywgIC8vICMjIyBzdHlsZSBibG9jayBjb21tZW50c1xuICAgICAgICAgICdjU3R5bGVDb21tZW50cyc6IHRydWUsXG4gICAgICAgICAgJ211bHRpbGluZVN0cmluZ3MnOiB0cnVlLFxuICAgICAgICAgICd0cmlwbGVRdW90ZWRTdHJpbmdzJzogdHJ1ZSxcbiAgICAgICAgICAncmVnZXhMaXRlcmFscyc6IHRydWVcbiAgICAgICAgfSksIFsnY29mZmVlJ10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKHNvdXJjZURlY29yYXRvcih7XG4gICAgICAgICAgJ2tleXdvcmRzJzogUlVTVF9LRVlXT1JEUyxcbiAgICAgICAgICAnY1N0eWxlQ29tbWVudHMnOiB0cnVlLFxuICAgICAgICAgICdtdWx0aWxpbmVTdHJpbmdzJzogdHJ1ZVxuICAgICAgICB9KSwgWydyYycsICdycycsICdydXN0J10pO1xuICByZWdpc3RlckxhbmdIYW5kbGVyKFxuICAgICAgY3JlYXRlU2ltcGxlTGV4ZXIoW10sIFtbUFJfU1RSSU5HLCAvXltcXHNcXFNdKy9dXSksIFsncmVnZXgnXSk7XG5cbiAgZnVuY3Rpb24gYXBwbHlEZWNvcmF0b3Ioam9iKSB7XG4gICAgdmFyIG9wdF9sYW5nRXh0ZW5zaW9uID0gam9iLmxhbmdFeHRlbnNpb247XG5cbiAgICB0cnkge1xuICAgICAgLy8gRXh0cmFjdCB0YWdzLCBhbmQgY29udmVydCB0aGUgc291cmNlIGNvZGUgdG8gcGxhaW4gdGV4dC5cbiAgICAgIHZhciBzb3VyY2VBbmRTcGFucyA9IGV4dHJhY3RTb3VyY2VTcGFucyhqb2Iuc291cmNlTm9kZSwgam9iLnByZSk7XG4gICAgICAvKiogUGxhaW4gdGV4dC4gQHR5cGUge3N0cmluZ30gKi9cbiAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VBbmRTcGFucy5zb3VyY2VDb2RlO1xuICAgICAgam9iLnNvdXJjZUNvZGUgPSBzb3VyY2U7XG4gICAgICBqb2Iuc3BhbnMgPSBzb3VyY2VBbmRTcGFucy5zcGFucztcbiAgICAgIGpvYi5iYXNlUG9zID0gMDtcblxuICAgICAgLy8gQXBwbHkgdGhlIGFwcHJvcHJpYXRlIGxhbmd1YWdlIGhhbmRsZXJcbiAgICAgIGxhbmdIYW5kbGVyRm9yRXh0ZW5zaW9uKG9wdF9sYW5nRXh0ZW5zaW9uLCBzb3VyY2UpKGpvYik7XG5cbiAgICAgIC8vIEludGVncmF0ZSB0aGUgZGVjb3JhdGlvbnMgYW5kIHRhZ3MgYmFjayBpbnRvIHRoZSBzb3VyY2UgY29kZSxcbiAgICAgIC8vIG1vZGlmeWluZyB0aGUgc291cmNlTm9kZSBpbiBwbGFjZS5cbiAgICAgIHJlY29tYmluZVRhZ3NBbmREZWNvcmF0aW9ucyhqb2IpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICh3aW5bJ2NvbnNvbGUnXSkge1xuICAgICAgICBjb25zb2xlWydsb2cnXShlICYmIGVbJ3N0YWNrJ10gfHwgZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZXR0eSBwcmludCBhIGNodW5rIG9mIGNvZGUuXG4gICAqIEBwYXJhbSBzb3VyY2VDb2RlSHRtbCB7c3RyaW5nfSBUaGUgSFRNTCB0byBwcmV0dHkgcHJpbnQuXG4gICAqIEBwYXJhbSBvcHRfbGFuZ0V4dGVuc2lvbiB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgbmFtZSB0byB1c2UuXG4gICAqICAgICBUeXBpY2FsbHksIGEgZmlsZW5hbWUgZXh0ZW5zaW9uIGxpa2UgJ2NwcCcgb3IgJ2phdmEnLlxuICAgKiBAcGFyYW0gb3B0X251bWJlckxpbmVzIHtudW1iZXJ8Ym9vbGVhbn0gVHJ1ZSB0byBudW1iZXIgbGluZXMsXG4gICAqICAgICBvciB0aGUgMS1pbmRleGVkIG51bWJlciBvZiB0aGUgZmlyc3QgbGluZSBpbiBzb3VyY2VDb2RlSHRtbC5cbiAgICovXG4gIGZ1bmN0aW9uICRwcmV0dHlQcmludE9uZShzb3VyY2VDb2RlSHRtbCwgb3B0X2xhbmdFeHRlbnNpb24sIG9wdF9udW1iZXJMaW5lcykge1xuICAgIHZhciBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAvLyBUaGlzIGNvdWxkIGNhdXNlIGltYWdlcyB0byBsb2FkIGFuZCBvbmxvYWQgbGlzdGVuZXJzIHRvIGZpcmUuXG4gICAgLy8gRS5nLiA8aW1nIG9uZXJyb3I9XCJhbGVydCgxMzM3KVwiIHNyYz1cIm5vc3VjaGltYWdlLnBuZ1wiPi5cbiAgICAvLyBXZSBhc3N1bWUgdGhhdCB0aGUgaW5uZXIgSFRNTCBpcyBmcm9tIGEgdHJ1c3RlZCBzb3VyY2UuXG4gICAgLy8gVGhlIHByZS10YWcgaXMgcmVxdWlyZWQgZm9yIElFOCB3aGljaCBzdHJpcHMgbmV3bGluZXMgZnJvbSBpbm5lckhUTUxcbiAgICAvLyB3aGVuIGl0IGlzIGluamVjdGVkIGludG8gYSA8cHJlPiB0YWcuXG4gICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80NTE0ODYvcHJlLXRhZy1sb3Nlcy1saW5lLWJyZWFrcy13aGVuLXNldHRpbmctaW5uZXJodG1sLWluLWllXG4gICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xOTUzNjMvaW5zZXJ0aW5nLWEtbmV3bGluZS1pbnRvLWEtcHJlLXRhZy1pZS1qYXZhc2NyaXB0XG4gICAgY29udGFpbmVyLmlubmVySFRNTCA9ICc8cHJlPicgKyBzb3VyY2VDb2RlSHRtbCArICc8L3ByZT4nO1xuICAgIGNvbnRhaW5lciA9IGNvbnRhaW5lci5maXJzdENoaWxkO1xuICAgIGlmIChvcHRfbnVtYmVyTGluZXMpIHtcbiAgICAgIG51bWJlckxpbmVzKGNvbnRhaW5lciwgb3B0X251bWJlckxpbmVzLCB0cnVlKTtcbiAgICB9XG5cbiAgICB2YXIgam9iID0ge1xuICAgICAgbGFuZ0V4dGVuc2lvbjogb3B0X2xhbmdFeHRlbnNpb24sXG4gICAgICBudW1iZXJMaW5lczogb3B0X251bWJlckxpbmVzLFxuICAgICAgc291cmNlTm9kZTogY29udGFpbmVyLFxuICAgICAgcHJlOiAxXG4gICAgfTtcbiAgICBhcHBseURlY29yYXRvcihqb2IpO1xuICAgIHJldHVybiBjb250YWluZXIuaW5uZXJIVE1MO1xuICB9XG5cbiAgIC8qKlxuICAgICogRmluZCBhbGwgdGhlIHtAY29kZSA8cHJlPn0gYW5kIHtAY29kZSA8Y29kZT59IHRhZ3MgaW4gdGhlIERPTSB3aXRoXG4gICAgKiB7QGNvZGUgY2xhc3M9cHJldHR5cHJpbnR9IGFuZCBwcmV0dGlmeSB0aGVtLlxuICAgICpcbiAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG9wdF93aGVuRG9uZSBjYWxsZWQgd2hlbiBwcmV0dGlmeWluZyBpcyBkb25lLlxuICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MRG9jdW1lbnR9IG9wdF9yb290IGFuIGVsZW1lbnQgb3IgZG9jdW1lbnRcbiAgICAqICAgY29udGFpbmluZyBhbGwgdGhlIGVsZW1lbnRzIHRvIHByZXR0eSBwcmludC5cbiAgICAqICAgRGVmYXVsdHMgdG8ge0Bjb2RlIGRvY3VtZW50LmJvZHl9LlxuICAgICovXG4gIGZ1bmN0aW9uICRwcmV0dHlQcmludChvcHRfd2hlbkRvbmUsIG9wdF9yb290KSB7XG4gICAgdmFyIHJvb3QgPSBvcHRfcm9vdCB8fCBkb2N1bWVudC5ib2R5O1xuICAgIHZhciBkb2MgPSByb290Lm93bmVyRG9jdW1lbnQgfHwgZG9jdW1lbnQ7XG4gICAgZnVuY3Rpb24gYnlUYWdOYW1lKHRuKSB7IHJldHVybiByb290LmdldEVsZW1lbnRzQnlUYWdOYW1lKHRuKTsgfVxuICAgIC8vIGZldGNoIGEgbGlzdCBvZiBub2RlcyB0byByZXdyaXRlXG4gICAgdmFyIGNvZGVTZWdtZW50cyA9IFtieVRhZ05hbWUoJ3ByZScpLCBieVRhZ05hbWUoJ2NvZGUnKSwgYnlUYWdOYW1lKCd4bXAnKV07XG4gICAgdmFyIGVsZW1lbnRzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2RlU2VnbWVudHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGZvciAodmFyIGogPSAwLCBuID0gY29kZVNlZ21lbnRzW2ldLmxlbmd0aDsgaiA8IG47ICsraikge1xuICAgICAgICBlbGVtZW50cy5wdXNoKGNvZGVTZWdtZW50c1tpXVtqXSk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvZGVTZWdtZW50cyA9IG51bGw7XG5cbiAgICB2YXIgY2xvY2sgPSBEYXRlO1xuICAgIGlmICghY2xvY2tbJ25vdyddKSB7XG4gICAgICBjbG9jayA9IHsgJ25vdyc6IGZ1bmN0aW9uICgpIHsgcmV0dXJuICsobmV3IERhdGUpOyB9IH07XG4gICAgfVxuXG4gICAgLy8gVGhlIGxvb3AgaXMgYnJva2VuIGludG8gYSBzZXJpZXMgb2YgY29udGludWF0aW9ucyB0byBtYWtlIHN1cmUgdGhhdCB3ZVxuICAgIC8vIGRvbid0IG1ha2UgdGhlIGJyb3dzZXIgdW5yZXNwb25zaXZlIHdoZW4gcmV3cml0aW5nIGEgbGFyZ2UgcGFnZS5cbiAgICB2YXIgayA9IDA7XG4gICAgdmFyIHByZXR0eVByaW50aW5nSm9iO1xuXG4gICAgdmFyIGxhbmdFeHRlbnNpb25SZSA9IC9cXGJsYW5nKD86dWFnZSk/LShbXFx3Ll0rKSg/IVxcUykvO1xuICAgIHZhciBwcmV0dHlQcmludFJlID0gL1xcYnByZXR0eXByaW50XFxiLztcbiAgICB2YXIgcHJldHR5UHJpbnRlZFJlID0gL1xcYnByZXR0eXByaW50ZWRcXGIvO1xuICAgIHZhciBwcmVmb3JtYXR0ZWRUYWdOYW1lUmUgPSAvcHJlfHhtcC9pO1xuICAgIHZhciBjb2RlUmUgPSAvXmNvZGUkL2k7XG4gICAgdmFyIHByZUNvZGVYbXBSZSA9IC9eKD86cHJlfGNvZGV8eG1wKSQvaTtcbiAgICB2YXIgRU1QVFkgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGRvV29yaygpIHtcbiAgICAgIHZhciBlbmRUaW1lID0gKHdpblsnUFJfU0hPVUxEX1VTRV9DT05USU5VQVRJT04nXSA/XG4gICAgICAgICAgICAgICAgICAgICBjbG9ja1snbm93J10oKSArIDI1MCAvKiBtcyAqLyA6XG4gICAgICAgICAgICAgICAgICAgICBJbmZpbml0eSk7XG4gICAgICBmb3IgKDsgayA8IGVsZW1lbnRzLmxlbmd0aCAmJiBjbG9ja1snbm93J10oKSA8IGVuZFRpbWU7IGsrKykge1xuICAgICAgICB2YXIgY3MgPSBlbGVtZW50c1trXTtcblxuICAgICAgICAvLyBMb29rIGZvciBhIHByZWNlZGluZyBjb21tZW50IGxpa2VcbiAgICAgICAgLy8gPD9wcmV0dGlmeSBsYW5nPVwiLi4uXCIgbGluZW51bXM9XCIuLi5cIj8+XG4gICAgICAgIHZhciBhdHRycyA9IEVNUFRZO1xuICAgICAgICB7XG4gICAgICAgICAgZm9yICh2YXIgcHJlY2VkZXIgPSBjczsgKHByZWNlZGVyID0gcHJlY2VkZXIucHJldmlvdXNTaWJsaW5nKTspIHtcbiAgICAgICAgICAgIHZhciBudCA9IHByZWNlZGVyLm5vZGVUeXBlO1xuICAgICAgICAgICAgLy8gPD9mb28/PiBpcyBwYXJzZWQgYnkgSFRNTCA1IHRvIGEgY29tbWVudCBub2RlICg4KVxuICAgICAgICAgICAgLy8gbGlrZSA8IS0tP2Zvbz8tLT4sIGJ1dCBpbiBYTUwgaXMgYSBwcm9jZXNzaW5nIGluc3RydWN0aW9uXG4gICAgICAgICAgICB2YXIgdmFsdWUgPSAobnQgPT09IDcgfHwgbnQgPT09IDgpICYmIHByZWNlZGVyLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgIGlmICh2YWx1ZVxuICAgICAgICAgICAgICAgID8gIS9eXFw/P3ByZXR0aWZ5XFxiLy50ZXN0KHZhbHVlKVxuICAgICAgICAgICAgICAgIDogKG50ICE9PSAzIHx8IC9cXFMvLnRlc3QocHJlY2VkZXIubm9kZVZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgLy8gU2tpcCBvdmVyIHdoaXRlLXNwYWNlIHRleHQgbm9kZXMgYnV0IG5vdCBvdGhlcnMuXG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICAgIGF0dHJzID0ge307XG4gICAgICAgICAgICAgIHZhbHVlLnJlcGxhY2UoXG4gICAgICAgICAgICAgICAgICAvXFxiKFxcdyspPShbXFx3Oi4lKy1dKykvZyxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoXywgbmFtZSwgdmFsdWUpIHsgYXR0cnNbbmFtZV0gPSB2YWx1ZTsgfSk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBjcy5jbGFzc05hbWU7XG4gICAgICAgIGlmICgoYXR0cnMgIT09IEVNUFRZIHx8IHByZXR0eVByaW50UmUudGVzdChjbGFzc05hbWUpKVxuICAgICAgICAgICAgLy8gRG9uJ3QgcmVkbyB0aGlzIGlmIHdlJ3ZlIGFscmVhZHkgZG9uZSBpdC5cbiAgICAgICAgICAgIC8vIFRoaXMgYWxsb3dzIHJlY2FsbGluZyBwcmV0dHkgcHJpbnQgdG8ganVzdCBwcmV0dHlwcmludCBlbGVtZW50c1xuICAgICAgICAgICAgLy8gdGhhdCBoYXZlIGJlZW4gYWRkZWQgdG8gdGhlIHBhZ2Ugc2luY2UgbGFzdCBjYWxsLlxuICAgICAgICAgICAgJiYgIXByZXR0eVByaW50ZWRSZS50ZXN0KGNsYXNzTmFtZSkpIHtcblxuICAgICAgICAgIC8vIG1ha2Ugc3VyZSB0aGlzIGlzIG5vdCBuZXN0ZWQgaW4gYW4gYWxyZWFkeSBwcmV0dGlmaWVkIGVsZW1lbnRcbiAgICAgICAgICB2YXIgbmVzdGVkID0gZmFsc2U7XG4gICAgICAgICAgZm9yICh2YXIgcCA9IGNzLnBhcmVudE5vZGU7IHA7IHAgPSBwLnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIHZhciB0biA9IHAudGFnTmFtZTtcbiAgICAgICAgICAgIGlmIChwcmVDb2RlWG1wUmUudGVzdCh0bilcbiAgICAgICAgICAgICAgICAmJiBwLmNsYXNzTmFtZSAmJiBwcmV0dHlQcmludFJlLnRlc3QocC5jbGFzc05hbWUpKSB7XG4gICAgICAgICAgICAgIG5lc3RlZCA9IHRydWU7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5lc3RlZCkge1xuICAgICAgICAgICAgLy8gTWFyayBkb25lLiAgSWYgd2UgZmFpbCB0byBwcmV0dHlwcmludCBmb3Igd2hhdGV2ZXIgcmVhc29uLFxuICAgICAgICAgICAgLy8gd2Ugc2hvdWxkbid0IHRyeSBhZ2Fpbi5cbiAgICAgICAgICAgIGNzLmNsYXNzTmFtZSArPSAnIHByZXR0eXByaW50ZWQnO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGUgY2xhc3NlcyBpbmNsdWRlcyBhIGxhbmd1YWdlIGV4dGVuc2lvbnMsIHVzZSBpdC5cbiAgICAgICAgICAgIC8vIExhbmd1YWdlIGV4dGVuc2lvbnMgY2FuIGJlIHNwZWNpZmllZCBsaWtlXG4gICAgICAgICAgICAvLyAgICAgPHByZSBjbGFzcz1cInByZXR0eXByaW50IGxhbmctY3BwXCI+XG4gICAgICAgICAgICAvLyB0aGUgbGFuZ3VhZ2UgZXh0ZW5zaW9uIFwiY3BwXCIgaXMgdXNlZCB0byBmaW5kIGEgbGFuZ3VhZ2UgaGFuZGxlclxuICAgICAgICAgICAgLy8gYXMgcGFzc2VkIHRvIFBSLnJlZ2lzdGVyTGFuZ0hhbmRsZXIuXG4gICAgICAgICAgICAvLyBIVE1MNSByZWNvbW1lbmRzIHRoYXQgYSBsYW5ndWFnZSBiZSBzcGVjaWZpZWQgdXNpbmcgXCJsYW5ndWFnZS1cIlxuICAgICAgICAgICAgLy8gYXMgdGhlIHByZWZpeCBpbnN0ZWFkLiAgR29vZ2xlIENvZGUgUHJldHRpZnkgc3VwcG9ydHMgYm90aC5cbiAgICAgICAgICAgIC8vIGh0dHA6Ly9kZXYudzMub3JnL2h0bWw1L3NwZWMtYXV0aG9yLXZpZXcvdGhlLWNvZGUtZWxlbWVudC5odG1sXG4gICAgICAgICAgICB2YXIgbGFuZ0V4dGVuc2lvbiA9IGF0dHJzWydsYW5nJ107XG4gICAgICAgICAgICBpZiAoIWxhbmdFeHRlbnNpb24pIHtcbiAgICAgICAgICAgICAgbGFuZ0V4dGVuc2lvbiA9IGNsYXNzTmFtZS5tYXRjaChsYW5nRXh0ZW5zaW9uUmUpO1xuICAgICAgICAgICAgICAvLyBTdXBwb3J0IDxwcmUgY2xhc3M9XCJwcmV0dHlwcmludFwiPjxjb2RlIGNsYXNzPVwibGFuZ3VhZ2UtY1wiPlxuICAgICAgICAgICAgICB2YXIgd3JhcHBlcjtcbiAgICAgICAgICAgICAgaWYgKCFsYW5nRXh0ZW5zaW9uICYmICh3cmFwcGVyID0gY2hpbGRDb250ZW50V3JhcHBlcihjcykpXG4gICAgICAgICAgICAgICAgICAmJiBjb2RlUmUudGVzdCh3cmFwcGVyLnRhZ05hbWUpKSB7XG4gICAgICAgICAgICAgICAgbGFuZ0V4dGVuc2lvbiA9IHdyYXBwZXIuY2xhc3NOYW1lLm1hdGNoKGxhbmdFeHRlbnNpb25SZSk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBpZiAobGFuZ0V4dGVuc2lvbikgeyBsYW5nRXh0ZW5zaW9uID0gbGFuZ0V4dGVuc2lvblsxXTsgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcHJlZm9ybWF0dGVkO1xuICAgICAgICAgICAgaWYgKHByZWZvcm1hdHRlZFRhZ05hbWVSZS50ZXN0KGNzLnRhZ05hbWUpKSB7XG4gICAgICAgICAgICAgIHByZWZvcm1hdHRlZCA9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB2YXIgY3VycmVudFN0eWxlID0gY3NbJ2N1cnJlbnRTdHlsZSddO1xuICAgICAgICAgICAgICB2YXIgZGVmYXVsdFZpZXcgPSBkb2MuZGVmYXVsdFZpZXc7XG4gICAgICAgICAgICAgIHZhciB3aGl0ZXNwYWNlID0gKFxuICAgICAgICAgICAgICAgICAgY3VycmVudFN0eWxlXG4gICAgICAgICAgICAgICAgICA/IGN1cnJlbnRTdHlsZVsnd2hpdGVTcGFjZSddXG4gICAgICAgICAgICAgICAgICA6IChkZWZhdWx0Vmlld1xuICAgICAgICAgICAgICAgICAgICAgJiYgZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZSlcbiAgICAgICAgICAgICAgICAgID8gZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShjcywgbnVsbClcbiAgICAgICAgICAgICAgICAgIC5nZXRQcm9wZXJ0eVZhbHVlKCd3aGl0ZS1zcGFjZScpXG4gICAgICAgICAgICAgICAgICA6IDApO1xuICAgICAgICAgICAgICBwcmVmb3JtYXR0ZWQgPSB3aGl0ZXNwYWNlXG4gICAgICAgICAgICAgICAgICAmJiAncHJlJyA9PT0gd2hpdGVzcGFjZS5zdWJzdHJpbmcoMCwgMyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExvb2sgZm9yIGEgY2xhc3MgbGlrZSBsaW5lbnVtcyBvciBsaW5lbnVtczo8bj4gd2hlcmUgPG4+IGlzIHRoZVxuICAgICAgICAgICAgLy8gMS1pbmRleGVkIG51bWJlciBvZiB0aGUgZmlyc3QgbGluZS5cbiAgICAgICAgICAgIHZhciBsaW5lTnVtcyA9IGF0dHJzWydsaW5lbnVtcyddO1xuICAgICAgICAgICAgaWYgKCEobGluZU51bXMgPSBsaW5lTnVtcyA9PT0gJ3RydWUnIHx8ICtsaW5lTnVtcykpIHtcbiAgICAgICAgICAgICAgbGluZU51bXMgPSBjbGFzc05hbWUubWF0Y2goL1xcYmxpbmVudW1zXFxiKD86OihcXGQrKSk/Lyk7XG4gICAgICAgICAgICAgIGxpbmVOdW1zID1cbiAgICAgICAgICAgICAgICBsaW5lTnVtc1xuICAgICAgICAgICAgICAgID8gbGluZU51bXNbMV0gJiYgbGluZU51bXNbMV0ubGVuZ3RoXG4gICAgICAgICAgICAgICAgICA/ICtsaW5lTnVtc1sxXSA6IHRydWVcbiAgICAgICAgICAgICAgICA6IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxpbmVOdW1zKSB7IG51bWJlckxpbmVzKGNzLCBsaW5lTnVtcywgcHJlZm9ybWF0dGVkKTsgfVxuXG4gICAgICAgICAgICAvLyBkbyB0aGUgcHJldHR5IHByaW50aW5nXG4gICAgICAgICAgICBwcmV0dHlQcmludGluZ0pvYiA9IHtcbiAgICAgICAgICAgICAgbGFuZ0V4dGVuc2lvbjogbGFuZ0V4dGVuc2lvbixcbiAgICAgICAgICAgICAgc291cmNlTm9kZTogY3MsXG4gICAgICAgICAgICAgIG51bWJlckxpbmVzOiBsaW5lTnVtcyxcbiAgICAgICAgICAgICAgcHJlOiBwcmVmb3JtYXR0ZWRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhcHBseURlY29yYXRvcihwcmV0dHlQcmludGluZ0pvYik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoayA8IGVsZW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAvLyBmaW5pc2ggdXAgaW4gYSBjb250aW51YXRpb25cbiAgICAgICAgc2V0VGltZW91dChkb1dvcmssIDI1MCk7XG4gICAgICB9IGVsc2UgaWYgKCdmdW5jdGlvbicgPT09IHR5cGVvZiBvcHRfd2hlbkRvbmUpIHtcbiAgICAgICAgb3B0X3doZW5Eb25lKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZG9Xb3JrKCk7XG4gIH1cblxuICAvKipcbiAgICogQ29udGFpbnMgZnVuY3Rpb25zIGZvciBjcmVhdGluZyBhbmQgcmVnaXN0ZXJpbmcgbmV3IGxhbmd1YWdlIGhhbmRsZXJzLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgdmFyIFBSID0gd2luWydQUiddID0ge1xuICAgICAgICAnY3JlYXRlU2ltcGxlTGV4ZXInOiBjcmVhdGVTaW1wbGVMZXhlcixcbiAgICAgICAgJ3JlZ2lzdGVyTGFuZ0hhbmRsZXInOiByZWdpc3RlckxhbmdIYW5kbGVyLFxuICAgICAgICAnc291cmNlRGVjb3JhdG9yJzogc291cmNlRGVjb3JhdG9yLFxuICAgICAgICAnUFJfQVRUUklCX05BTUUnOiBQUl9BVFRSSUJfTkFNRSxcbiAgICAgICAgJ1BSX0FUVFJJQl9WQUxVRSc6IFBSX0FUVFJJQl9WQUxVRSxcbiAgICAgICAgJ1BSX0NPTU1FTlQnOiBQUl9DT01NRU5ULFxuICAgICAgICAnUFJfREVDTEFSQVRJT04nOiBQUl9ERUNMQVJBVElPTixcbiAgICAgICAgJ1BSX0tFWVdPUkQnOiBQUl9LRVlXT1JELFxuICAgICAgICAnUFJfTElURVJBTCc6IFBSX0xJVEVSQUwsXG4gICAgICAgICdQUl9OT0NPREUnOiBQUl9OT0NPREUsXG4gICAgICAgICdQUl9QTEFJTic6IFBSX1BMQUlOLFxuICAgICAgICAnUFJfUFVOQ1RVQVRJT04nOiBQUl9QVU5DVFVBVElPTixcbiAgICAgICAgJ1BSX1NPVVJDRSc6IFBSX1NPVVJDRSxcbiAgICAgICAgJ1BSX1NUUklORyc6IFBSX1NUUklORyxcbiAgICAgICAgJ1BSX1RBRyc6IFBSX1RBRyxcbiAgICAgICAgJ1BSX1RZUEUnOiBQUl9UWVBFLFxuICAgICAgICAncHJldHR5UHJpbnRPbmUnOlxuICAgICAgICAgICBJTl9HTE9CQUxfU0NPUEVcbiAgICAgICAgICAgICA/ICh3aW5bJ3ByZXR0eVByaW50T25lJ10gPSAkcHJldHR5UHJpbnRPbmUpXG4gICAgICAgICAgICAgOiAocHJldHR5UHJpbnRPbmUgPSAkcHJldHR5UHJpbnRPbmUpLFxuICAgICAgICAncHJldHR5UHJpbnQnOiBwcmV0dHlQcmludCA9XG4gICAgICAgICAgIElOX0dMT0JBTF9TQ09QRVxuICAgICAgICAgICAgID8gKHdpblsncHJldHR5UHJpbnQnXSA9ICRwcmV0dHlQcmludClcbiAgICAgICAgICAgICA6IChwcmV0dHlQcmludCA9ICRwcmV0dHlQcmludClcbiAgICAgIH07XG5cbiAgLy8gTWFrZSBQUiBhdmFpbGFibGUgdmlhIHRoZSBBc3luY2hyb25vdXMgTW9kdWxlIERlZmluaXRpb24gKEFNRCkgQVBJLlxuICAvLyBQZXIgaHR0cHM6Ly9naXRodWIuY29tL2FtZGpzL2FtZGpzLWFwaS93aWtpL0FNRDpcbiAgLy8gVGhlIEFzeW5jaHJvbm91cyBNb2R1bGUgRGVmaW5pdGlvbiAoQU1EKSBBUEkgc3BlY2lmaWVzIGFcbiAgLy8gbWVjaGFuaXNtIGZvciBkZWZpbmluZyBtb2R1bGVzIHN1Y2ggdGhhdCB0aGUgbW9kdWxlIGFuZCBpdHNcbiAgLy8gZGVwZW5kZW5jaWVzIGNhbiBiZSBhc3luY2hyb25vdXNseSBsb2FkZWQuXG4gIC8vIC4uLlxuICAvLyBUbyBhbGxvdyBhIGNsZWFyIGluZGljYXRvciB0aGF0IGEgZ2xvYmFsIGRlZmluZSBmdW5jdGlvbiAoYXNcbiAgLy8gbmVlZGVkIGZvciBzY3JpcHQgc3JjIGJyb3dzZXIgbG9hZGluZykgY29uZm9ybXMgdG8gdGhlIEFNRCBBUEksXG4gIC8vIGFueSBnbG9iYWwgZGVmaW5lIGZ1bmN0aW9uIFNIT1VMRCBoYXZlIGEgcHJvcGVydHkgY2FsbGVkIFwiYW1kXCJcbiAgLy8gd2hvc2UgdmFsdWUgaXMgYW4gb2JqZWN0LiBUaGlzIGhlbHBzIGF2b2lkIGNvbmZsaWN0IHdpdGggYW55XG4gIC8vIG90aGVyIGV4aXN0aW5nIEphdmFTY3JpcHQgY29kZSB0aGF0IGNvdWxkIGhhdmUgZGVmaW5lZCBhIGRlZmluZSgpXG4gIC8vIGZ1bmN0aW9uIHRoYXQgZG9lcyBub3QgY29uZm9ybSB0byB0aGUgQU1EIEFQSS5cbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmVbJ2FtZCddKSB7XG4gICAgZGVmaW5lKFwiZ29vZ2xlLWNvZGUtcHJldHRpZnlcIiwgW10sIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBQUjsgXG4gICAgfSk7XG4gIH1cbn0pKCk7XG4iLCI7KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKSA6XG4gICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKGZhY3RvcnkpIDpcbiAgICBnbG9iYWwubW9tZW50ID0gZmFjdG9yeSgpXG59KHRoaXMsIChmdW5jdGlvbiAoKSB7ICd1c2Ugc3RyaWN0JztcblxuICAgIHZhciBob29rQ2FsbGJhY2s7XG5cbiAgICBmdW5jdGlvbiBob29rcyAoKSB7XG4gICAgICAgIHJldHVybiBob29rQ2FsbGJhY2suYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICB9XG5cbiAgICAvLyBUaGlzIGlzIGRvbmUgdG8gcmVnaXN0ZXIgdGhlIG1ldGhvZCBjYWxsZWQgd2l0aCBtb21lbnQoKVxuICAgIC8vIHdpdGhvdXQgY3JlYXRpbmcgY2lyY3VsYXIgZGVwZW5kZW5jaWVzLlxuICAgIGZ1bmN0aW9uIHNldEhvb2tDYWxsYmFjayAoY2FsbGJhY2spIHtcbiAgICAgICAgaG9va0NhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNBcnJheShpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQgaW5zdGFuY2VvZiBBcnJheSB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaW5wdXQpID09PSAnW29iamVjdCBBcnJheV0nO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzT2JqZWN0KGlucHV0KSB7XG4gICAgICAgIC8vIElFOCB3aWxsIHRyZWF0IHVuZGVmaW5lZCBhbmQgbnVsbCBhcyBvYmplY3QgaWYgaXQgd2Fzbid0IGZvclxuICAgICAgICAvLyBpbnB1dCAhPSBudWxsXG4gICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IE9iamVjdF0nO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzT2JqZWN0RW1wdHkob2JqKSB7XG4gICAgICAgIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcykge1xuICAgICAgICAgICAgcmV0dXJuIChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhvYmopLmxlbmd0aCA9PT0gMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgaztcbiAgICAgICAgICAgIGZvciAoayBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGspKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzVW5kZWZpbmVkKGlucHV0KSB7XG4gICAgICAgIHJldHVybiBpbnB1dCA9PT0gdm9pZCAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzTnVtYmVyKGlucHV0KSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgaW5wdXQgPT09ICdudW1iZXInIHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IE51bWJlcl0nO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzRGF0ZShpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQgaW5zdGFuY2VvZiBEYXRlIHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IERhdGVdJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYXAoYXJyLCBmbikge1xuICAgICAgICB2YXIgcmVzID0gW10sIGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIHJlcy5wdXNoKGZuKGFycltpXSwgaSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGFzT3duUHJvcChhLCBiKSB7XG4gICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYSwgYik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXh0ZW5kKGEsIGIpIHtcbiAgICAgICAgZm9yICh2YXIgaSBpbiBiKSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcChiLCBpKSkge1xuICAgICAgICAgICAgICAgIGFbaV0gPSBiW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGhhc093blByb3AoYiwgJ3RvU3RyaW5nJykpIHtcbiAgICAgICAgICAgIGEudG9TdHJpbmcgPSBiLnRvU3RyaW5nO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGhhc093blByb3AoYiwgJ3ZhbHVlT2YnKSkge1xuICAgICAgICAgICAgYS52YWx1ZU9mID0gYi52YWx1ZU9mO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGE7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlVVRDIChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCkge1xuICAgICAgICByZXR1cm4gY3JlYXRlTG9jYWxPclVUQyhpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCwgdHJ1ZSkudXRjKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGVmYXVsdFBhcnNpbmdGbGFncygpIHtcbiAgICAgICAgLy8gV2UgbmVlZCB0byBkZWVwIGNsb25lIHRoaXMgb2JqZWN0LlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZW1wdHkgICAgICAgICAgIDogZmFsc2UsXG4gICAgICAgICAgICB1bnVzZWRUb2tlbnMgICAgOiBbXSxcbiAgICAgICAgICAgIHVudXNlZElucHV0ICAgICA6IFtdLFxuICAgICAgICAgICAgb3ZlcmZsb3cgICAgICAgIDogLTIsXG4gICAgICAgICAgICBjaGFyc0xlZnRPdmVyICAgOiAwLFxuICAgICAgICAgICAgbnVsbElucHV0ICAgICAgIDogZmFsc2UsXG4gICAgICAgICAgICBpbnZhbGlkTW9udGggICAgOiBudWxsLFxuICAgICAgICAgICAgaW52YWxpZEZvcm1hdCAgIDogZmFsc2UsXG4gICAgICAgICAgICB1c2VySW52YWxpZGF0ZWQgOiBmYWxzZSxcbiAgICAgICAgICAgIGlzbyAgICAgICAgICAgICA6IGZhbHNlLFxuICAgICAgICAgICAgcGFyc2VkRGF0ZVBhcnRzIDogW10sXG4gICAgICAgICAgICBtZXJpZGllbSAgICAgICAgOiBudWxsLFxuICAgICAgICAgICAgcmZjMjgyMiAgICAgICAgIDogZmFsc2UsXG4gICAgICAgICAgICB3ZWVrZGF5TWlzbWF0Y2ggOiBmYWxzZVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFBhcnNpbmdGbGFncyhtKSB7XG4gICAgICAgIGlmIChtLl9wZiA9PSBudWxsKSB7XG4gICAgICAgICAgICBtLl9wZiA9IGRlZmF1bHRQYXJzaW5nRmxhZ3MoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbS5fcGY7XG4gICAgfVxuXG4gICAgdmFyIHNvbWU7XG4gICAgaWYgKEFycmF5LnByb3RvdHlwZS5zb21lKSB7XG4gICAgICAgIHNvbWUgPSBBcnJheS5wcm90b3R5cGUuc29tZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzb21lID0gZnVuY3Rpb24gKGZ1bikge1xuICAgICAgICAgICAgdmFyIHQgPSBPYmplY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgbGVuID0gdC5sZW5ndGggPj4+IDA7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaSBpbiB0ICYmIGZ1bi5jYWxsKHRoaXMsIHRbaV0sIGksIHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzVmFsaWQobSkge1xuICAgICAgICBpZiAobS5faXNWYWxpZCA9PSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgZmxhZ3MgPSBnZXRQYXJzaW5nRmxhZ3MobSk7XG4gICAgICAgICAgICB2YXIgcGFyc2VkUGFydHMgPSBzb21lLmNhbGwoZmxhZ3MucGFyc2VkRGF0ZVBhcnRzLCBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpICE9IG51bGw7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBpc05vd1ZhbGlkID0gIWlzTmFOKG0uX2QuZ2V0VGltZSgpKSAmJlxuICAgICAgICAgICAgICAgIGZsYWdzLm92ZXJmbG93IDwgMCAmJlxuICAgICAgICAgICAgICAgICFmbGFncy5lbXB0eSAmJlxuICAgICAgICAgICAgICAgICFmbGFncy5pbnZhbGlkTW9udGggJiZcbiAgICAgICAgICAgICAgICAhZmxhZ3MuaW52YWxpZFdlZWtkYXkgJiZcbiAgICAgICAgICAgICAgICAhZmxhZ3Mud2Vla2RheU1pc21hdGNoICYmXG4gICAgICAgICAgICAgICAgIWZsYWdzLm51bGxJbnB1dCAmJlxuICAgICAgICAgICAgICAgICFmbGFncy5pbnZhbGlkRm9ybWF0ICYmXG4gICAgICAgICAgICAgICAgIWZsYWdzLnVzZXJJbnZhbGlkYXRlZCAmJlxuICAgICAgICAgICAgICAgICghZmxhZ3MubWVyaWRpZW0gfHwgKGZsYWdzLm1lcmlkaWVtICYmIHBhcnNlZFBhcnRzKSk7XG5cbiAgICAgICAgICAgIGlmIChtLl9zdHJpY3QpIHtcbiAgICAgICAgICAgICAgICBpc05vd1ZhbGlkID0gaXNOb3dWYWxpZCAmJlxuICAgICAgICAgICAgICAgICAgICBmbGFncy5jaGFyc0xlZnRPdmVyID09PSAwICYmXG4gICAgICAgICAgICAgICAgICAgIGZsYWdzLnVudXNlZFRva2Vucy5sZW5ndGggPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgZmxhZ3MuYmlnSG91ciA9PT0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoT2JqZWN0LmlzRnJvemVuID09IG51bGwgfHwgIU9iamVjdC5pc0Zyb3plbihtKSkge1xuICAgICAgICAgICAgICAgIG0uX2lzVmFsaWQgPSBpc05vd1ZhbGlkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTm93VmFsaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG0uX2lzVmFsaWQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlSW52YWxpZCAoZmxhZ3MpIHtcbiAgICAgICAgdmFyIG0gPSBjcmVhdGVVVEMoTmFOKTtcbiAgICAgICAgaWYgKGZsYWdzICE9IG51bGwpIHtcbiAgICAgICAgICAgIGV4dGVuZChnZXRQYXJzaW5nRmxhZ3MobSksIGZsYWdzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhtKS51c2VySW52YWxpZGF0ZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG07XG4gICAgfVxuXG4gICAgLy8gUGx1Z2lucyB0aGF0IGFkZCBwcm9wZXJ0aWVzIHNob3VsZCBhbHNvIGFkZCB0aGUga2V5IGhlcmUgKG51bGwgdmFsdWUpLFxuICAgIC8vIHNvIHdlIGNhbiBwcm9wZXJseSBjbG9uZSBvdXJzZWx2ZXMuXG4gICAgdmFyIG1vbWVudFByb3BlcnRpZXMgPSBob29rcy5tb21lbnRQcm9wZXJ0aWVzID0gW107XG5cbiAgICBmdW5jdGlvbiBjb3B5Q29uZmlnKHRvLCBmcm9tKSB7XG4gICAgICAgIHZhciBpLCBwcm9wLCB2YWw7XG5cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9pc0FNb21lbnRPYmplY3QpKSB7XG4gICAgICAgICAgICB0by5faXNBTW9tZW50T2JqZWN0ID0gZnJvbS5faXNBTW9tZW50T2JqZWN0O1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5faSkpIHtcbiAgICAgICAgICAgIHRvLl9pID0gZnJvbS5faTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2YpKSB7XG4gICAgICAgICAgICB0by5fZiA9IGZyb20uX2Y7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9sKSkge1xuICAgICAgICAgICAgdG8uX2wgPSBmcm9tLl9sO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fc3RyaWN0KSkge1xuICAgICAgICAgICAgdG8uX3N0cmljdCA9IGZyb20uX3N0cmljdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX3R6bSkpIHtcbiAgICAgICAgICAgIHRvLl90em0gPSBmcm9tLl90em07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9pc1VUQykpIHtcbiAgICAgICAgICAgIHRvLl9pc1VUQyA9IGZyb20uX2lzVVRDO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fb2Zmc2V0KSkge1xuICAgICAgICAgICAgdG8uX29mZnNldCA9IGZyb20uX29mZnNldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX3BmKSkge1xuICAgICAgICAgICAgdG8uX3BmID0gZ2V0UGFyc2luZ0ZsYWdzKGZyb20pO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fbG9jYWxlKSkge1xuICAgICAgICAgICAgdG8uX2xvY2FsZSA9IGZyb20uX2xvY2FsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtb21lbnRQcm9wZXJ0aWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBtb21lbnRQcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcHJvcCA9IG1vbWVudFByb3BlcnRpZXNbaV07XG4gICAgICAgICAgICAgICAgdmFsID0gZnJvbVtwcm9wXTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKHZhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdG9bcHJvcF0gPSB2YWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRvO1xuICAgIH1cblxuICAgIHZhciB1cGRhdGVJblByb2dyZXNzID0gZmFsc2U7XG5cbiAgICAvLyBNb21lbnQgcHJvdG90eXBlIG9iamVjdFxuICAgIGZ1bmN0aW9uIE1vbWVudChjb25maWcpIHtcbiAgICAgICAgY29weUNvbmZpZyh0aGlzLCBjb25maWcpO1xuICAgICAgICB0aGlzLl9kID0gbmV3IERhdGUoY29uZmlnLl9kICE9IG51bGwgPyBjb25maWcuX2QuZ2V0VGltZSgpIDogTmFOKTtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgdGhpcy5fZCA9IG5ldyBEYXRlKE5hTik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUHJldmVudCBpbmZpbml0ZSBsb29wIGluIGNhc2UgdXBkYXRlT2Zmc2V0IGNyZWF0ZXMgbmV3IG1vbWVudFxuICAgICAgICAvLyBvYmplY3RzLlxuICAgICAgICBpZiAodXBkYXRlSW5Qcm9ncmVzcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KHRoaXMpO1xuICAgICAgICAgICAgdXBkYXRlSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNNb21lbnQgKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgTW9tZW50IHx8IChvYmogIT0gbnVsbCAmJiBvYmouX2lzQU1vbWVudE9iamVjdCAhPSBudWxsKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhYnNGbG9vciAobnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICAgICAgICAvLyAtMCAtPiAwXG4gICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKG51bWJlcikgfHwgMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKG51bWJlcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b0ludChhcmd1bWVudEZvckNvZXJjaW9uKSB7XG4gICAgICAgIHZhciBjb2VyY2VkTnVtYmVyID0gK2FyZ3VtZW50Rm9yQ29lcmNpb24sXG4gICAgICAgICAgICB2YWx1ZSA9IDA7XG5cbiAgICAgICAgaWYgKGNvZXJjZWROdW1iZXIgIT09IDAgJiYgaXNGaW5pdGUoY29lcmNlZE51bWJlcikpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYWJzRmxvb3IoY29lcmNlZE51bWJlcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLy8gY29tcGFyZSB0d28gYXJyYXlzLCByZXR1cm4gdGhlIG51bWJlciBvZiBkaWZmZXJlbmNlc1xuICAgIGZ1bmN0aW9uIGNvbXBhcmVBcnJheXMoYXJyYXkxLCBhcnJheTIsIGRvbnRDb252ZXJ0KSB7XG4gICAgICAgIHZhciBsZW4gPSBNYXRoLm1pbihhcnJheTEubGVuZ3RoLCBhcnJheTIubGVuZ3RoKSxcbiAgICAgICAgICAgIGxlbmd0aERpZmYgPSBNYXRoLmFicyhhcnJheTEubGVuZ3RoIC0gYXJyYXkyLmxlbmd0aCksXG4gICAgICAgICAgICBkaWZmcyA9IDAsXG4gICAgICAgICAgICBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlmICgoZG9udENvbnZlcnQgJiYgYXJyYXkxW2ldICE9PSBhcnJheTJbaV0pIHx8XG4gICAgICAgICAgICAgICAgKCFkb250Q29udmVydCAmJiB0b0ludChhcnJheTFbaV0pICE9PSB0b0ludChhcnJheTJbaV0pKSkge1xuICAgICAgICAgICAgICAgIGRpZmZzKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRpZmZzICsgbGVuZ3RoRGlmZjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB3YXJuKG1zZykge1xuICAgICAgICBpZiAoaG9va3Muc3VwcHJlc3NEZXByZWNhdGlvbldhcm5pbmdzID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICh0eXBlb2YgY29uc29sZSAhPT0gICd1bmRlZmluZWQnKSAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignRGVwcmVjYXRpb24gd2FybmluZzogJyArIG1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkZXByZWNhdGUobXNnLCBmbikge1xuICAgICAgICB2YXIgZmlyc3RUaW1lID0gdHJ1ZTtcblxuICAgICAgICByZXR1cm4gZXh0ZW5kKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChob29rcy5kZXByZWNhdGlvbkhhbmRsZXIgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlcihudWxsLCBtc2cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpcnN0VGltZSkge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGFyZztcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBhcmcgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhcmd1bWVudHNbaV0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgKz0gJ1xcblsnICsgaSArICddICc7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gYXJndW1lbnRzWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJnICs9IGtleSArICc6ICcgKyBhcmd1bWVudHNbMF1ba2V5XSArICcsICc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmcuc2xpY2UoMCwgLTIpOyAvLyBSZW1vdmUgdHJhaWxpbmcgY29tbWEgYW5kIHNwYWNlXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXJncy5wdXNoKGFyZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdhcm4obXNnICsgJ1xcbkFyZ3VtZW50czogJyArIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3MpLmpvaW4oJycpICsgJ1xcbicgKyAobmV3IEVycm9yKCkpLnN0YWNrKTtcbiAgICAgICAgICAgICAgICBmaXJzdFRpbWUgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9LCBmbik7XG4gICAgfVxuXG4gICAgdmFyIGRlcHJlY2F0aW9ucyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gZGVwcmVjYXRlU2ltcGxlKG5hbWUsIG1zZykge1xuICAgICAgICBpZiAoaG9va3MuZGVwcmVjYXRpb25IYW5kbGVyICE9IG51bGwpIHtcbiAgICAgICAgICAgIGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlcihuYW1lLCBtc2cpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZGVwcmVjYXRpb25zW25hbWVdKSB7XG4gICAgICAgICAgICB3YXJuKG1zZyk7XG4gICAgICAgICAgICBkZXByZWNhdGlvbnNbbmFtZV0gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3Muc3VwcHJlc3NEZXByZWNhdGlvbldhcm5pbmdzID0gZmFsc2U7XG4gICAgaG9va3MuZGVwcmVjYXRpb25IYW5kbGVyID0gbnVsbDtcblxuICAgIGZ1bmN0aW9uIGlzRnVuY3Rpb24oaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0IGluc3RhbmNlb2YgRnVuY3Rpb24gfHwgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXQgKGNvbmZpZykge1xuICAgICAgICB2YXIgcHJvcCwgaTtcbiAgICAgICAgZm9yIChpIGluIGNvbmZpZykge1xuICAgICAgICAgICAgcHJvcCA9IGNvbmZpZ1tpXTtcbiAgICAgICAgICAgIGlmIChpc0Z1bmN0aW9uKHByb3ApKSB7XG4gICAgICAgICAgICAgICAgdGhpc1tpXSA9IHByb3A7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXNbJ18nICsgaV0gPSBwcm9wO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgLy8gTGVuaWVudCBvcmRpbmFsIHBhcnNpbmcgYWNjZXB0cyBqdXN0IGEgbnVtYmVyIGluIGFkZGl0aW9uIHRvXG4gICAgICAgIC8vIG51bWJlciArIChwb3NzaWJseSkgc3R1ZmYgY29taW5nIGZyb20gX2RheU9mTW9udGhPcmRpbmFsUGFyc2UuXG4gICAgICAgIC8vIFRPRE86IFJlbW92ZSBcIm9yZGluYWxQYXJzZVwiIGZhbGxiYWNrIGluIG5leHQgbWFqb3IgcmVsZWFzZS5cbiAgICAgICAgdGhpcy5fZGF5T2ZNb250aE9yZGluYWxQYXJzZUxlbmllbnQgPSBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgKHRoaXMuX2RheU9mTW9udGhPcmRpbmFsUGFyc2Uuc291cmNlIHx8IHRoaXMuX29yZGluYWxQYXJzZS5zb3VyY2UpICtcbiAgICAgICAgICAgICAgICAnfCcgKyAoL1xcZHsxLDJ9Lykuc291cmNlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtZXJnZUNvbmZpZ3MocGFyZW50Q29uZmlnLCBjaGlsZENvbmZpZykge1xuICAgICAgICB2YXIgcmVzID0gZXh0ZW5kKHt9LCBwYXJlbnRDb25maWcpLCBwcm9wO1xuICAgICAgICBmb3IgKHByb3AgaW4gY2hpbGRDb25maWcpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wKGNoaWxkQ29uZmlnLCBwcm9wKSkge1xuICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwYXJlbnRDb25maWdbcHJvcF0pICYmIGlzT2JqZWN0KGNoaWxkQ29uZmlnW3Byb3BdKSkge1xuICAgICAgICAgICAgICAgICAgICByZXNbcHJvcF0gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgZXh0ZW5kKHJlc1twcm9wXSwgcGFyZW50Q29uZmlnW3Byb3BdKTtcbiAgICAgICAgICAgICAgICAgICAgZXh0ZW5kKHJlc1twcm9wXSwgY2hpbGRDb25maWdbcHJvcF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGRDb25maWdbcHJvcF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXNbcHJvcF0gPSBjaGlsZENvbmZpZ1twcm9wXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgcmVzW3Byb3BdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHByb3AgaW4gcGFyZW50Q29uZmlnKSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcChwYXJlbnRDb25maWcsIHByb3ApICYmXG4gICAgICAgICAgICAgICAgICAgICFoYXNPd25Qcm9wKGNoaWxkQ29uZmlnLCBwcm9wKSAmJlxuICAgICAgICAgICAgICAgICAgICBpc09iamVjdChwYXJlbnRDb25maWdbcHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgLy8gbWFrZSBzdXJlIGNoYW5nZXMgdG8gcHJvcGVydGllcyBkb24ndCBtb2RpZnkgcGFyZW50IGNvbmZpZ1xuICAgICAgICAgICAgICAgIHJlc1twcm9wXSA9IGV4dGVuZCh7fSwgcmVzW3Byb3BdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIExvY2FsZShjb25maWcpIHtcbiAgICAgICAgaWYgKGNvbmZpZyAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnNldChjb25maWcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGtleXM7XG5cbiAgICBpZiAoT2JqZWN0LmtleXMpIHtcbiAgICAgICAga2V5cyA9IE9iamVjdC5rZXlzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGtleXMgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgICAgICB2YXIgaSwgcmVzID0gW107XG4gICAgICAgICAgICBmb3IgKGkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc093blByb3Aob2JqLCBpKSkge1xuICAgICAgICAgICAgICAgICAgICByZXMucHVzaChpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0Q2FsZW5kYXIgPSB7XG4gICAgICAgIHNhbWVEYXkgOiAnW1RvZGF5IGF0XSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW1RvbW9ycm93IGF0XSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2F0XSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW1llc3RlcmRheSBhdF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbTGFzdF0gZGRkZCBbYXRdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gY2FsZW5kYXIgKGtleSwgbW9tLCBub3cpIHtcbiAgICAgICAgdmFyIG91dHB1dCA9IHRoaXMuX2NhbGVuZGFyW2tleV0gfHwgdGhpcy5fY2FsZW5kYXJbJ3NhbWVFbHNlJ107XG4gICAgICAgIHJldHVybiBpc0Z1bmN0aW9uKG91dHB1dCkgPyBvdXRwdXQuY2FsbChtb20sIG5vdykgOiBvdXRwdXQ7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb25nRGF0ZUZvcm1hdCA9IHtcbiAgICAgICAgTFRTICA6ICdoOm1tOnNzIEEnLFxuICAgICAgICBMVCAgIDogJ2g6bW0gQScsXG4gICAgICAgIEwgICAgOiAnTU0vREQvWVlZWScsXG4gICAgICAgIExMICAgOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgTExMICA6ICdNTU1NIEQsIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBNTU1NIEQsIFlZWVkgaDptbSBBJ1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBsb25nRGF0ZUZvcm1hdCAoa2V5KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldLFxuICAgICAgICAgICAgZm9ybWF0VXBwZXIgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXkudG9VcHBlckNhc2UoKV07XG5cbiAgICAgICAgaWYgKGZvcm1hdCB8fCAhZm9ybWF0VXBwZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldID0gZm9ybWF0VXBwZXIucmVwbGFjZSgvTU1NTXxNTXxERHxkZGRkL2csIGZ1bmN0aW9uICh2YWwpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWwuc2xpY2UoMSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0SW52YWxpZERhdGUgPSAnSW52YWxpZCBkYXRlJztcblxuICAgIGZ1bmN0aW9uIGludmFsaWREYXRlICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ludmFsaWREYXRlO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0T3JkaW5hbCA9ICclZCc7XG4gICAgdmFyIGRlZmF1bHREYXlPZk1vbnRoT3JkaW5hbFBhcnNlID0gL1xcZHsxLDJ9LztcblxuICAgIGZ1bmN0aW9uIG9yZGluYWwgKG51bWJlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3JkaW5hbC5yZXBsYWNlKCclZCcsIG51bWJlcik7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRSZWxhdGl2ZVRpbWUgPSB7XG4gICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgIHBhc3QgICA6ICclcyBhZ28nLFxuICAgICAgICBzICA6ICdhIGZldyBzZWNvbmRzJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kcycsXG4gICAgICAgIG0gIDogJ2EgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggIDogJ2FuIGhvdXInLFxuICAgICAgICBoaCA6ICclZCBob3VycycsXG4gICAgICAgIGQgIDogJ2EgZGF5JyxcbiAgICAgICAgZGQgOiAnJWQgZGF5cycsXG4gICAgICAgIE0gIDogJ2EgbW9udGgnLFxuICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICB5ICA6ICdhIHllYXInLFxuICAgICAgICB5eSA6ICclZCB5ZWFycydcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIG91dHB1dCA9IHRoaXMuX3JlbGF0aXZlVGltZVtzdHJpbmddO1xuICAgICAgICByZXR1cm4gKGlzRnVuY3Rpb24ob3V0cHV0KSkgP1xuICAgICAgICAgICAgb3V0cHV0KG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkgOlxuICAgICAgICAgICAgb3V0cHV0LnJlcGxhY2UoLyVkL2ksIG51bWJlcik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFzdEZ1dHVyZSAoZGlmZiwgb3V0cHV0KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB0aGlzLl9yZWxhdGl2ZVRpbWVbZGlmZiA+IDAgPyAnZnV0dXJlJyA6ICdwYXN0J107XG4gICAgICAgIHJldHVybiBpc0Z1bmN0aW9uKGZvcm1hdCkgPyBmb3JtYXQob3V0cHV0KSA6IGZvcm1hdC5yZXBsYWNlKC8lcy9pLCBvdXRwdXQpO1xuICAgIH1cblxuICAgIHZhciBhbGlhc2VzID0ge307XG5cbiAgICBmdW5jdGlvbiBhZGRVbml0QWxpYXMgKHVuaXQsIHNob3J0aGFuZCkge1xuICAgICAgICB2YXIgbG93ZXJDYXNlID0gdW5pdC50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBhbGlhc2VzW2xvd2VyQ2FzZV0gPSBhbGlhc2VzW2xvd2VyQ2FzZSArICdzJ10gPSBhbGlhc2VzW3Nob3J0aGFuZF0gPSB1bml0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZVVuaXRzKHVuaXRzKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdW5pdHMgPT09ICdzdHJpbmcnID8gYWxpYXNlc1t1bml0c10gfHwgYWxpYXNlc1t1bml0cy50b0xvd2VyQ2FzZSgpXSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub3JtYWxpemVPYmplY3RVbml0cyhpbnB1dE9iamVjdCkge1xuICAgICAgICB2YXIgbm9ybWFsaXplZElucHV0ID0ge30sXG4gICAgICAgICAgICBub3JtYWxpemVkUHJvcCxcbiAgICAgICAgICAgIHByb3A7XG5cbiAgICAgICAgZm9yIChwcm9wIGluIGlucHV0T2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcChpbnB1dE9iamVjdCwgcHJvcCkpIHtcbiAgICAgICAgICAgICAgICBub3JtYWxpemVkUHJvcCA9IG5vcm1hbGl6ZVVuaXRzKHByb3ApO1xuICAgICAgICAgICAgICAgIGlmIChub3JtYWxpemVkUHJvcCkge1xuICAgICAgICAgICAgICAgICAgICBub3JtYWxpemVkSW5wdXRbbm9ybWFsaXplZFByb3BdID0gaW5wdXRPYmplY3RbcHJvcF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRJbnB1dDtcbiAgICB9XG5cbiAgICB2YXIgcHJpb3JpdGllcyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gYWRkVW5pdFByaW9yaXR5KHVuaXQsIHByaW9yaXR5KSB7XG4gICAgICAgIHByaW9yaXRpZXNbdW5pdF0gPSBwcmlvcml0eTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRQcmlvcml0aXplZFVuaXRzKHVuaXRzT2JqKSB7XG4gICAgICAgIHZhciB1bml0cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciB1IGluIHVuaXRzT2JqKSB7XG4gICAgICAgICAgICB1bml0cy5wdXNoKHt1bml0OiB1LCBwcmlvcml0eTogcHJpb3JpdGllc1t1XX0pO1xuICAgICAgICB9XG4gICAgICAgIHVuaXRzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiBhLnByaW9yaXR5IC0gYi5wcmlvcml0eTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB1bml0cztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6ZXJvRmlsbChudW1iZXIsIHRhcmdldExlbmd0aCwgZm9yY2VTaWduKSB7XG4gICAgICAgIHZhciBhYnNOdW1iZXIgPSAnJyArIE1hdGguYWJzKG51bWJlciksXG4gICAgICAgICAgICB6ZXJvc1RvRmlsbCA9IHRhcmdldExlbmd0aCAtIGFic051bWJlci5sZW5ndGgsXG4gICAgICAgICAgICBzaWduID0gbnVtYmVyID49IDA7XG4gICAgICAgIHJldHVybiAoc2lnbiA/IChmb3JjZVNpZ24gPyAnKycgOiAnJykgOiAnLScpICtcbiAgICAgICAgICAgIE1hdGgucG93KDEwLCBNYXRoLm1heCgwLCB6ZXJvc1RvRmlsbCkpLnRvU3RyaW5nKCkuc3Vic3RyKDEpICsgYWJzTnVtYmVyO1xuICAgIH1cblxuICAgIHZhciBmb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KFtIaF1tbShzcyk/fE1vfE1NP00/TT98RG98REREb3xERD9EP0Q/fGRkZD9kP3xkbz98d1tvfHddP3xXW298V10/fFFvP3xZWVlZWVl8WVlZWVl8WVlZWXxZWXxnZyhnZ2c/KT98R0coR0dHPyk/fGV8RXxhfEF8aGg/fEhIP3xraz98bW0/fHNzP3xTezEsOX18eHxYfHp6P3xaWj98LikvZztcblxuICAgIHZhciBsb2NhbEZvcm1hdHRpbmdUb2tlbnMgPSAvKFxcW1teXFxbXSpcXF0pfChcXFxcKT8oTFRTfExUfExMP0w/TD98bHsxLDR9KS9nO1xuXG4gICAgdmFyIGZvcm1hdEZ1bmN0aW9ucyA9IHt9O1xuXG4gICAgdmFyIGZvcm1hdFRva2VuRnVuY3Rpb25zID0ge307XG5cbiAgICAvLyB0b2tlbjogICAgJ00nXG4gICAgLy8gcGFkZGVkOiAgIFsnTU0nLCAyXVxuICAgIC8vIG9yZGluYWw6ICAnTW8nXG4gICAgLy8gY2FsbGJhY2s6IGZ1bmN0aW9uICgpIHsgdGhpcy5tb250aCgpICsgMSB9XG4gICAgZnVuY3Rpb24gYWRkRm9ybWF0VG9rZW4gKHRva2VuLCBwYWRkZWQsIG9yZGluYWwsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBmdW5jID0gY2FsbGJhY2s7XG4gICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBmdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzW2NhbGxiYWNrXSgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodG9rZW4pIHtcbiAgICAgICAgICAgIGZvcm1hdFRva2VuRnVuY3Rpb25zW3Rva2VuXSA9IGZ1bmM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhZGRlZCkge1xuICAgICAgICAgICAgZm9ybWF0VG9rZW5GdW5jdGlvbnNbcGFkZGVkWzBdXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gemVyb0ZpbGwoZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCBwYWRkZWRbMV0sIHBhZGRlZFsyXSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcmRpbmFsKSB7XG4gICAgICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1tvcmRpbmFsXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkub3JkaW5hbChmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksIHRva2VuKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVGb3JtYXR0aW5nVG9rZW5zKGlucHV0KSB7XG4gICAgICAgIGlmIChpbnB1dC5tYXRjaCgvXFxbW1xcc1xcU10vKSkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL15cXFt8XFxdJC9nLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL1xcXFwvZywgJycpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VGb3JtYXRGdW5jdGlvbihmb3JtYXQpIHtcbiAgICAgICAgdmFyIGFycmF5ID0gZm9ybWF0Lm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpLCBpLCBsZW5ndGg7XG5cbiAgICAgICAgZm9yIChpID0gMCwgbGVuZ3RoID0gYXJyYXkubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChmb3JtYXRUb2tlbkZ1bmN0aW9uc1thcnJheVtpXV0pIHtcbiAgICAgICAgICAgICAgICBhcnJheVtpXSA9IGZvcm1hdFRva2VuRnVuY3Rpb25zW2FycmF5W2ldXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYXJyYXlbaV0gPSByZW1vdmVGb3JtYXR0aW5nVG9rZW5zKGFycmF5W2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAobW9tKSB7XG4gICAgICAgICAgICB2YXIgb3V0cHV0ID0gJycsIGk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBvdXRwdXQgKz0gaXNGdW5jdGlvbihhcnJheVtpXSkgPyBhcnJheVtpXS5jYWxsKG1vbSwgZm9ybWF0KSA6IGFycmF5W2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBmb3JtYXQgZGF0ZSB1c2luZyBuYXRpdmUgZGF0ZSBvYmplY3RcbiAgICBmdW5jdGlvbiBmb3JtYXRNb21lbnQobSwgZm9ybWF0KSB7XG4gICAgICAgIGlmICghbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBtLmxvY2FsZURhdGEoKS5pbnZhbGlkRGF0ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9ybWF0ID0gZXhwYW5kRm9ybWF0KGZvcm1hdCwgbS5sb2NhbGVEYXRhKCkpO1xuICAgICAgICBmb3JtYXRGdW5jdGlvbnNbZm9ybWF0XSA9IGZvcm1hdEZ1bmN0aW9uc1tmb3JtYXRdIHx8IG1ha2VGb3JtYXRGdW5jdGlvbihmb3JtYXQpO1xuXG4gICAgICAgIHJldHVybiBmb3JtYXRGdW5jdGlvbnNbZm9ybWF0XShtKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleHBhbmRGb3JtYXQoZm9ybWF0LCBsb2NhbGUpIHtcbiAgICAgICAgdmFyIGkgPSA1O1xuXG4gICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VMb25nRGF0ZUZvcm1hdFRva2VucyhpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGxvY2FsZS5sb25nRGF0ZUZvcm1hdChpbnB1dCkgfHwgaW5wdXQ7XG4gICAgICAgIH1cblxuICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcbiAgICAgICAgd2hpbGUgKGkgPj0gMCAmJiBsb2NhbEZvcm1hdHRpbmdUb2tlbnMudGVzdChmb3JtYXQpKSB7XG4gICAgICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShsb2NhbEZvcm1hdHRpbmdUb2tlbnMsIHJlcGxhY2VMb25nRGF0ZUZvcm1hdFRva2Vucyk7XG4gICAgICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcbiAgICAgICAgICAgIGkgLT0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgfVxuXG4gICAgdmFyIG1hdGNoMSAgICAgICAgID0gL1xcZC87ICAgICAgICAgICAgLy8gICAgICAgMCAtIDlcbiAgICB2YXIgbWF0Y2gyICAgICAgICAgPSAvXFxkXFxkLzsgICAgICAgICAgLy8gICAgICAwMCAtIDk5XG4gICAgdmFyIG1hdGNoMyAgICAgICAgID0gL1xcZHszfS87ICAgICAgICAgLy8gICAgIDAwMCAtIDk5OVxuICAgIHZhciBtYXRjaDQgICAgICAgICA9IC9cXGR7NH0vOyAgICAgICAgIC8vICAgIDAwMDAgLSA5OTk5XG4gICAgdmFyIG1hdGNoNiAgICAgICAgID0gL1srLV0/XFxkezZ9LzsgICAgLy8gLTk5OTk5OSAtIDk5OTk5OVxuICAgIHZhciBtYXRjaDF0bzIgICAgICA9IC9cXGRcXGQ/LzsgICAgICAgICAvLyAgICAgICAwIC0gOTlcbiAgICB2YXIgbWF0Y2gzdG80ICAgICAgPSAvXFxkXFxkXFxkXFxkPy87ICAgICAvLyAgICAgOTk5IC0gOTk5OVxuICAgIHZhciBtYXRjaDV0bzYgICAgICA9IC9cXGRcXGRcXGRcXGRcXGRcXGQ/LzsgLy8gICA5OTk5OSAtIDk5OTk5OVxuICAgIHZhciBtYXRjaDF0bzMgICAgICA9IC9cXGR7MSwzfS87ICAgICAgIC8vICAgICAgIDAgLSA5OTlcbiAgICB2YXIgbWF0Y2gxdG80ICAgICAgPSAvXFxkezEsNH0vOyAgICAgICAvLyAgICAgICAwIC0gOTk5OVxuICAgIHZhciBtYXRjaDF0bzYgICAgICA9IC9bKy1dP1xcZHsxLDZ9LzsgIC8vIC05OTk5OTkgLSA5OTk5OTlcblxuICAgIHZhciBtYXRjaFVuc2lnbmVkICA9IC9cXGQrLzsgICAgICAgICAgIC8vICAgICAgIDAgLSBpbmZcbiAgICB2YXIgbWF0Y2hTaWduZWQgICAgPSAvWystXT9cXGQrLzsgICAgICAvLyAgICAtaW5mIC0gaW5mXG5cbiAgICB2YXIgbWF0Y2hPZmZzZXQgICAgPSAvWnxbKy1dXFxkXFxkOj9cXGRcXGQvZ2k7IC8vICswMDowMCAtMDA6MDAgKzAwMDAgLTAwMDAgb3IgWlxuICAgIHZhciBtYXRjaFNob3J0T2Zmc2V0ID0gL1p8WystXVxcZFxcZCg/Ojo/XFxkXFxkKT8vZ2k7IC8vICswMCAtMDAgKzAwOjAwIC0wMDowMCArMDAwMCAtMDAwMCBvciBaXG5cbiAgICB2YXIgbWF0Y2hUaW1lc3RhbXAgPSAvWystXT9cXGQrKFxcLlxcZHsxLDN9KT8vOyAvLyAxMjM0NTY3ODkgMTIzNDU2Nzg5LjEyM1xuXG4gICAgLy8gYW55IHdvcmQgKG9yIHR3bykgY2hhcmFjdGVycyBvciBudW1iZXJzIGluY2x1ZGluZyB0d28vdGhyZWUgd29yZCBtb250aCBpbiBhcmFiaWMuXG4gICAgLy8gaW5jbHVkZXMgc2NvdHRpc2ggZ2FlbGljIHR3byB3b3JkIGFuZCBoeXBoZW5hdGVkIG1vbnRoc1xuICAgIHZhciBtYXRjaFdvcmQgPSAvWzAtOV17MCwyNTZ9WydhLXpcXHUwMEEwLVxcdTA1RkZcXHUwNzAwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGMDdcXHVGRjEwLVxcdUZGRUZdezEsMjU2fXxbXFx1MDYwMC1cXHUwNkZGXFwvXXsxLDI1Nn0oXFxzKj9bXFx1MDYwMC1cXHUwNkZGXXsxLDI1Nn0pezEsMn0vaTtcblxuICAgIHZhciByZWdleGVzID0ge307XG5cbiAgICBmdW5jdGlvbiBhZGRSZWdleFRva2VuICh0b2tlbiwgcmVnZXgsIHN0cmljdFJlZ2V4KSB7XG4gICAgICAgIHJlZ2V4ZXNbdG9rZW5dID0gaXNGdW5jdGlvbihyZWdleCkgPyByZWdleCA6IGZ1bmN0aW9uIChpc1N0cmljdCwgbG9jYWxlRGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIChpc1N0cmljdCAmJiBzdHJpY3RSZWdleCkgPyBzdHJpY3RSZWdleCA6IHJlZ2V4O1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFBhcnNlUmVnZXhGb3JUb2tlbiAodG9rZW4sIGNvbmZpZykge1xuICAgICAgICBpZiAoIWhhc093blByb3AocmVnZXhlcywgdG9rZW4pKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cCh1bmVzY2FwZUZvcm1hdCh0b2tlbikpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlZ2V4ZXNbdG9rZW5dKGNvbmZpZy5fc3RyaWN0LCBjb25maWcuX2xvY2FsZSk7XG4gICAgfVxuXG4gICAgLy8gQ29kZSBmcm9tIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzU2MTQ5My9pcy10aGVyZS1hLXJlZ2V4cC1lc2NhcGUtZnVuY3Rpb24taW4tamF2YXNjcmlwdFxuICAgIGZ1bmN0aW9uIHVuZXNjYXBlRm9ybWF0KHMpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2V4RXNjYXBlKHMucmVwbGFjZSgnXFxcXCcsICcnKS5yZXBsYWNlKC9cXFxcKFxcWyl8XFxcXChcXF0pfFxcWyhbXlxcXVxcW10qKVxcXXxcXFxcKC4pL2csIGZ1bmN0aW9uIChtYXRjaGVkLCBwMSwgcDIsIHAzLCBwNCkge1xuICAgICAgICAgICAgcmV0dXJuIHAxIHx8IHAyIHx8IHAzIHx8IHA0O1xuICAgICAgICB9KSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVnZXhFc2NhcGUocykge1xuICAgICAgICByZXR1cm4gcy5yZXBsYWNlKC9bLVxcL1xcXFxeJCorPy4oKXxbXFxde31dL2csICdcXFxcJCYnKTtcbiAgICB9XG5cbiAgICB2YXIgdG9rZW5zID0ge307XG5cbiAgICBmdW5jdGlvbiBhZGRQYXJzZVRva2VuICh0b2tlbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGksIGZ1bmMgPSBjYWxsYmFjaztcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRva2VuID0gW3Rva2VuXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNOdW1iZXIoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBmdW5jID0gZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICAgICAgICAgIGFycmF5W2NhbGxiYWNrXSA9IHRvSW50KGlucHV0KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRva2VuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0b2tlbnNbdG9rZW5baV1dID0gZnVuYztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFdlZWtQYXJzZVRva2VuICh0b2tlbiwgY2FsbGJhY2spIHtcbiAgICAgICAgYWRkUGFyc2VUb2tlbih0b2tlbiwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnLCB0b2tlbikge1xuICAgICAgICAgICAgY29uZmlnLl93ID0gY29uZmlnLl93IHx8IHt9O1xuICAgICAgICAgICAgY2FsbGJhY2soaW5wdXQsIGNvbmZpZy5fdywgY29uZmlnLCB0b2tlbik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFRpbWVUb0FycmF5RnJvbVRva2VuKHRva2VuLCBpbnB1dCwgY29uZmlnKSB7XG4gICAgICAgIGlmIChpbnB1dCAhPSBudWxsICYmIGhhc093blByb3AodG9rZW5zLCB0b2tlbikpIHtcbiAgICAgICAgICAgIHRva2Vuc1t0b2tlbl0oaW5wdXQsIGNvbmZpZy5fYSwgY29uZmlnLCB0b2tlbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgWUVBUiA9IDA7XG4gICAgdmFyIE1PTlRIID0gMTtcbiAgICB2YXIgREFURSA9IDI7XG4gICAgdmFyIEhPVVIgPSAzO1xuICAgIHZhciBNSU5VVEUgPSA0O1xuICAgIHZhciBTRUNPTkQgPSA1O1xuICAgIHZhciBNSUxMSVNFQ09ORCA9IDY7XG4gICAgdmFyIFdFRUsgPSA3O1xuICAgIHZhciBXRUVLREFZID0gODtcblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdZJywgMCwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgeSA9IHRoaXMueWVhcigpO1xuICAgICAgICByZXR1cm4geSA8PSA5OTk5ID8gJycgKyB5IDogJysnICsgeTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnWVknLCAyXSwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy55ZWFyKCkgJSAxMDA7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1lZWVknLCAgIDRdLCAgICAgICAwLCAneWVhcicpO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnWVlZWVknLCAgNV0sICAgICAgIDAsICd5ZWFyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydZWVlZWVknLCA2LCB0cnVlXSwgMCwgJ3llYXInKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygneWVhcicsICd5Jyk7XG5cbiAgICAvLyBQUklPUklUSUVTXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ3llYXInLCAxKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ1knLCAgICAgIG1hdGNoU2lnbmVkKTtcbiAgICBhZGRSZWdleFRva2VuKCdZWScsICAgICBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbignWVlZWScsICAgbWF0Y2gxdG80LCBtYXRjaDQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1lZWVlZJywgIG1hdGNoMXRvNiwgbWF0Y2g2KTtcbiAgICBhZGRSZWdleFRva2VuKCdZWVlZWVknLCBtYXRjaDF0bzYsIG1hdGNoNik7XG5cbiAgICBhZGRQYXJzZVRva2VuKFsnWVlZWVknLCAnWVlZWVlZJ10sIFlFQVIpO1xuICAgIGFkZFBhcnNlVG9rZW4oJ1lZWVknLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgICAgIGFycmF5W1lFQVJdID0gaW5wdXQubGVuZ3RoID09PSAyID8gaG9va3MucGFyc2VUd29EaWdpdFllYXIoaW5wdXQpIDogdG9JbnQoaW5wdXQpO1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oJ1lZJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICBhcnJheVtZRUFSXSA9IGhvb2tzLnBhcnNlVHdvRGlnaXRZZWFyKGlucHV0KTtcbiAgICB9KTtcbiAgICBhZGRQYXJzZVRva2VuKCdZJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICBhcnJheVtZRUFSXSA9IHBhcnNlSW50KGlucHV0LCAxMCk7XG4gICAgfSk7XG5cbiAgICAvLyBIRUxQRVJTXG5cbiAgICBmdW5jdGlvbiBkYXlzSW5ZZWFyKHllYXIpIHtcbiAgICAgICAgcmV0dXJuIGlzTGVhcFllYXIoeWVhcikgPyAzNjYgOiAzNjU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNMZWFwWWVhcih5ZWFyKSB7XG4gICAgICAgIHJldHVybiAoeWVhciAlIDQgPT09IDAgJiYgeWVhciAlIDEwMCAhPT0gMCkgfHwgeWVhciAlIDQwMCA9PT0gMDtcbiAgICB9XG5cbiAgICAvLyBIT09LU1xuXG4gICAgaG9va3MucGFyc2VUd29EaWdpdFllYXIgPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIHRvSW50KGlucHV0KSArICh0b0ludChpbnB1dCkgPiA2OCA/IDE5MDAgOiAyMDAwKTtcbiAgICB9O1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgdmFyIGdldFNldFllYXIgPSBtYWtlR2V0U2V0KCdGdWxsWWVhcicsIHRydWUpO1xuXG4gICAgZnVuY3Rpb24gZ2V0SXNMZWFwWWVhciAoKSB7XG4gICAgICAgIHJldHVybiBpc0xlYXBZZWFyKHRoaXMueWVhcigpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlR2V0U2V0ICh1bml0LCBrZWVwVGltZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHNldCQxKHRoaXMsIHVuaXQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywga2VlcFRpbWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0KHRoaXMsIHVuaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldCAobW9tLCB1bml0KSB7XG4gICAgICAgIHJldHVybiBtb20uaXNWYWxpZCgpID9cbiAgICAgICAgICAgIG1vbS5fZFsnZ2V0JyArIChtb20uX2lzVVRDID8gJ1VUQycgOiAnJykgKyB1bml0XSgpIDogTmFOO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldCQxIChtb20sIHVuaXQsIHZhbHVlKSB7XG4gICAgICAgIGlmIChtb20uaXNWYWxpZCgpICYmICFpc05hTih2YWx1ZSkpIHtcbiAgICAgICAgICAgIGlmICh1bml0ID09PSAnRnVsbFllYXInICYmIGlzTGVhcFllYXIobW9tLnllYXIoKSkgJiYgbW9tLm1vbnRoKCkgPT09IDEgJiYgbW9tLmRhdGUoKSA9PT0gMjkpIHtcbiAgICAgICAgICAgICAgICBtb20uX2RbJ3NldCcgKyAobW9tLl9pc1VUQyA/ICdVVEMnIDogJycpICsgdW5pdF0odmFsdWUsIG1vbS5tb250aCgpLCBkYXlzSW5Nb250aCh2YWx1ZSwgbW9tLm1vbnRoKCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vbS5fZFsnc2V0JyArIChtb20uX2lzVVRDID8gJ1VUQycgOiAnJykgKyB1bml0XSh2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICBmdW5jdGlvbiBzdHJpbmdHZXQgKHVuaXRzKSB7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW3VuaXRzXSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gc3RyaW5nU2V0ICh1bml0cywgdmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB1bml0cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplT2JqZWN0VW5pdHModW5pdHMpO1xuICAgICAgICAgICAgdmFyIHByaW9yaXRpemVkID0gZ2V0UHJpb3JpdGl6ZWRVbml0cyh1bml0cyk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByaW9yaXRpemVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpc1twcmlvcml0aXplZFtpXS51bml0XSh1bml0c1twcmlvcml0aXplZFtpXS51bml0XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICAgICAgICAgIGlmIChpc0Z1bmN0aW9uKHRoaXNbdW5pdHNdKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzW3VuaXRzXSh2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbW9kKG4sIHgpIHtcbiAgICAgICAgcmV0dXJuICgobiAlIHgpICsgeCkgJSB4O1xuICAgIH1cblxuICAgIHZhciBpbmRleE9mO1xuXG4gICAgaWYgKEFycmF5LnByb3RvdHlwZS5pbmRleE9mKSB7XG4gICAgICAgIGluZGV4T2YgPSBBcnJheS5wcm90b3R5cGUuaW5kZXhPZjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpbmRleE9mID0gZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgICAgIC8vIEkga25vd1xuICAgICAgICAgICAgdmFyIGk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzW2ldID09PSBvKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkYXlzSW5Nb250aCh5ZWFyLCBtb250aCkge1xuICAgICAgICBpZiAoaXNOYU4oeWVhcikgfHwgaXNOYU4obW9udGgpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtb2RNb250aCA9IG1vZChtb250aCwgMTIpO1xuICAgICAgICB5ZWFyICs9IChtb250aCAtIG1vZE1vbnRoKSAvIDEyO1xuICAgICAgICByZXR1cm4gbW9kTW9udGggPT09IDEgPyAoaXNMZWFwWWVhcih5ZWFyKSA/IDI5IDogMjgpIDogKDMxIC0gbW9kTW9udGggJSA3ICUgMik7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ00nLCBbJ01NJywgMl0sICdNbycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9udGgoKSArIDE7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignTU1NJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzU2hvcnQodGhpcywgZm9ybWF0KTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdNTU1NJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzKHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ21vbnRoJywgJ00nKTtcblxuICAgIC8vIFBSSU9SSVRZXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ21vbnRoJywgOCk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdNJywgICAgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdNTScsICAgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ01NTScsICBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLm1vbnRoc1Nob3J0UmVnZXgoaXNTdHJpY3QpO1xuICAgIH0pO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ01NTU0nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLm1vbnRoc1JlZ2V4KGlzU3RyaWN0KTtcbiAgICB9KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydNJywgJ01NJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgYXJyYXlbTU9OVEhdID0gdG9JbnQoaW5wdXQpIC0gMTtcbiAgICB9KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydNTU0nLCAnTU1NTSddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcsIHRva2VuKSB7XG4gICAgICAgIHZhciBtb250aCA9IGNvbmZpZy5fbG9jYWxlLm1vbnRoc1BhcnNlKGlucHV0LCB0b2tlbiwgY29uZmlnLl9zdHJpY3QpO1xuICAgICAgICAvLyBpZiB3ZSBkaWRuJ3QgZmluZCBhIG1vbnRoIG5hbWUsIG1hcmsgdGhlIGRhdGUgYXMgaW52YWxpZC5cbiAgICAgICAgaWYgKG1vbnRoICE9IG51bGwpIHtcbiAgICAgICAgICAgIGFycmF5W01PTlRIXSA9IG1vbnRoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZE1vbnRoID0gaW5wdXQ7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIExPQ0FMRVNcblxuICAgIHZhciBNT05USFNfSU5fRk9STUFUID0gL0Rbb0RdPyhcXFtbXlxcW1xcXV0qXFxdfFxccykrTU1NTT8vO1xuICAgIHZhciBkZWZhdWx0TG9jYWxlTW9udGhzID0gJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KCdfJyk7XG4gICAgZnVuY3Rpb24gbG9jYWxlTW9udGhzIChtLCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNBcnJheSh0aGlzLl9tb250aHMpID8gdGhpcy5fbW9udGhzIDpcbiAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNbJ3N0YW5kYWxvbmUnXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNBcnJheSh0aGlzLl9tb250aHMpID8gdGhpcy5fbW9udGhzW20ubW9udGgoKV0gOlxuICAgICAgICAgICAgdGhpcy5fbW9udGhzWyh0aGlzLl9tb250aHMuaXNGb3JtYXQgfHwgTU9OVEhTX0lOX0ZPUk1BVCkudGVzdChmb3JtYXQpID8gJ2Zvcm1hdCcgOiAnc3RhbmRhbG9uZSddW20ubW9udGgoKV07XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb2NhbGVNb250aHNTaG9ydCA9ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKTtcbiAgICBmdW5jdGlvbiBsb2NhbGVNb250aHNTaG9ydCAobSwgZm9ybWF0KSB7XG4gICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgcmV0dXJuIGlzQXJyYXkodGhpcy5fbW9udGhzU2hvcnQpID8gdGhpcy5fbW9udGhzU2hvcnQgOlxuICAgICAgICAgICAgICAgIHRoaXMuX21vbnRoc1Nob3J0WydzdGFuZGFsb25lJ107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzQXJyYXkodGhpcy5fbW9udGhzU2hvcnQpID8gdGhpcy5fbW9udGhzU2hvcnRbbS5tb250aCgpXSA6XG4gICAgICAgICAgICB0aGlzLl9tb250aHNTaG9ydFtNT05USFNfSU5fRk9STUFULnRlc3QoZm9ybWF0KSA/ICdmb3JtYXQnIDogJ3N0YW5kYWxvbmUnXVttLm1vbnRoKCldO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhbmRsZVN0cmljdFBhcnNlKG1vbnRoTmFtZSwgZm9ybWF0LCBzdHJpY3QpIHtcbiAgICAgICAgdmFyIGksIGlpLCBtb20sIGxsYyA9IG1vbnRoTmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAoIXRoaXMuX21vbnRoc1BhcnNlKSB7XG4gICAgICAgICAgICAvLyB0aGlzIGlzIG5vdCB1c2VkXG4gICAgICAgICAgICB0aGlzLl9tb250aHNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fbG9uZ01vbnRoc1BhcnNlID0gW107XG4gICAgICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlID0gW107XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7ICsraSkge1xuICAgICAgICAgICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgaV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX3Nob3J0TW9udGhzUGFyc2VbaV0gPSB0aGlzLm1vbnRoc1Nob3J0KG1vbSwgJycpLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldID0gdGhpcy5tb250aHMobW9tLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdHJpY3QpIHtcbiAgICAgICAgICAgIGlmIChmb3JtYXQgPT09ICdNTU0nKSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9sb25nTW9udGhzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChmb3JtYXQgPT09ICdNTU0nKSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbG9uZ01vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX2xvbmdNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9jYWxlTW9udGhzUGFyc2UgKG1vbnRoTmFtZSwgZm9ybWF0LCBzdHJpY3QpIHtcbiAgICAgICAgdmFyIGksIG1vbSwgcmVnZXg7XG5cbiAgICAgICAgaWYgKHRoaXMuX21vbnRoc1BhcnNlRXhhY3QpIHtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGVTdHJpY3RQYXJzZS5jYWxsKHRoaXMsIG1vbnRoTmFtZSwgZm9ybWF0LCBzdHJpY3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl9tb250aHNQYXJzZSkge1xuICAgICAgICAgICAgdGhpcy5fbW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fc2hvcnRNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVE9ETzogYWRkIHNvcnRpbmdcbiAgICAgICAgLy8gU29ydGluZyBtYWtlcyBzdXJlIGlmIG9uZSBtb250aCAob3IgYWJicikgaXMgYSBwcmVmaXggb2YgYW5vdGhlclxuICAgICAgICAvLyBzZWUgc29ydGluZyBpbiBjb21wdXRlTW9udGhzUGFyc2VcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCBpXSk7XG4gICAgICAgICAgICBpZiAoc3RyaWN0ICYmICF0aGlzLl9sb25nTW9udGhzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb25nTW9udGhzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKCdeJyArIHRoaXMubW9udGhzKG1vbSwgJycpLnJlcGxhY2UoJy4nLCAnJykgKyAnJCcsICdpJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2hvcnRNb250aHNQYXJzZVtpXSA9IG5ldyBSZWdFeHAoJ14nICsgdGhpcy5tb250aHNTaG9ydChtb20sICcnKS5yZXBsYWNlKCcuJywgJycpICsgJyQnLCAnaScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFzdHJpY3QgJiYgIXRoaXMuX21vbnRoc1BhcnNlW2ldKSB7XG4gICAgICAgICAgICAgICAgcmVnZXggPSAnXicgKyB0aGlzLm1vbnRocyhtb20sICcnKSArICd8XicgKyB0aGlzLm1vbnRoc1Nob3J0KG1vbSwgJycpO1xuICAgICAgICAgICAgICAgIHRoaXMuX21vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChyZWdleC5yZXBsYWNlKCcuJywgJycpLCAnaScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdGVzdCB0aGUgcmVnZXhcbiAgICAgICAgICAgIGlmIChzdHJpY3QgJiYgZm9ybWF0ID09PSAnTU1NTScgJiYgdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldLnRlc3QobW9udGhOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzdHJpY3QgJiYgZm9ybWF0ID09PSAnTU1NJyAmJiB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlW2ldLnRlc3QobW9udGhOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghc3RyaWN0ICYmIHRoaXMuX21vbnRoc1BhcnNlW2ldLnRlc3QobW9udGhOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gc2V0TW9udGggKG1vbSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGRheU9mTW9udGg7XG5cbiAgICAgICAgaWYgKCFtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAvLyBObyBvcFxuICAgICAgICAgICAgcmV0dXJuIG1vbTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAoL15cXGQrJC8udGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHRvSW50KHZhbHVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBtb20ubG9jYWxlRGF0YSgpLm1vbnRoc1BhcnNlKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBBbm90aGVyIHNpbGVudCBmYWlsdXJlP1xuICAgICAgICAgICAgICAgIGlmICghaXNOdW1iZXIodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtb207XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZGF5T2ZNb250aCA9IE1hdGgubWluKG1vbS5kYXRlKCksIGRheXNJbk1vbnRoKG1vbS55ZWFyKCksIHZhbHVlKSk7XG4gICAgICAgIG1vbS5fZFsnc2V0JyArIChtb20uX2lzVVRDID8gJ1VUQycgOiAnJykgKyAnTW9udGgnXSh2YWx1ZSwgZGF5T2ZNb250aCk7XG4gICAgICAgIHJldHVybiBtb207XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0TW9udGggKHZhbHVlKSB7XG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICBzZXRNb250aCh0aGlzLCB2YWx1ZSk7XG4gICAgICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywgdHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBnZXQodGhpcywgJ01vbnRoJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXREYXlzSW5Nb250aCAoKSB7XG4gICAgICAgIHJldHVybiBkYXlzSW5Nb250aCh0aGlzLnllYXIoKSwgdGhpcy5tb250aCgpKTtcbiAgICB9XG5cbiAgICB2YXIgZGVmYXVsdE1vbnRoc1Nob3J0UmVnZXggPSBtYXRjaFdvcmQ7XG4gICAgZnVuY3Rpb24gbW9udGhzU2hvcnRSZWdleCAoaXNTdHJpY3QpIHtcbiAgICAgICAgaWYgKHRoaXMuX21vbnRoc1BhcnNlRXhhY3QpIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX21vbnRoc1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlTW9udGhzUGFyc2UuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc1N0cmljdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNTaG9ydFN0cmljdFJlZ2V4O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX21vbnRoc1Nob3J0UmVnZXgnKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX21vbnRoc1Nob3J0UmVnZXggPSBkZWZhdWx0TW9udGhzU2hvcnRSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNTaG9ydFN0cmljdFJlZ2V4ICYmIGlzU3RyaWN0ID9cbiAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNTaG9ydFN0cmljdFJlZ2V4IDogdGhpcy5fbW9udGhzU2hvcnRSZWdleDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBkZWZhdWx0TW9udGhzUmVnZXggPSBtYXRjaFdvcmQ7XG4gICAgZnVuY3Rpb24gbW9udGhzUmVnZXggKGlzU3RyaWN0KSB7XG4gICAgICAgIGlmICh0aGlzLl9tb250aHNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX21vbnRoc1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNSZWdleCA9IGRlZmF1bHRNb250aHNSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNTdHJpY3RSZWdleCAmJiBpc1N0cmljdCA/XG4gICAgICAgICAgICAgICAgdGhpcy5fbW9udGhzU3RyaWN0UmVnZXggOiB0aGlzLl9tb250aHNSZWdleDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbXB1dGVNb250aHNQYXJzZSAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIGNtcExlblJldihhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gYi5sZW5ndGggLSBhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzaG9ydFBpZWNlcyA9IFtdLCBsb25nUGllY2VzID0gW10sIG1peGVkUGllY2VzID0gW10sXG4gICAgICAgICAgICBpLCBtb207XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcbiAgICAgICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgaV0pO1xuICAgICAgICAgICAgc2hvcnRQaWVjZXMucHVzaCh0aGlzLm1vbnRoc1Nob3J0KG1vbSwgJycpKTtcbiAgICAgICAgICAgIGxvbmdQaWVjZXMucHVzaCh0aGlzLm1vbnRocyhtb20sICcnKSk7XG4gICAgICAgICAgICBtaXhlZFBpZWNlcy5wdXNoKHRoaXMubW9udGhzKG1vbSwgJycpKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2godGhpcy5tb250aHNTaG9ydChtb20sICcnKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gU29ydGluZyBtYWtlcyBzdXJlIGlmIG9uZSBtb250aCAob3IgYWJicikgaXMgYSBwcmVmaXggb2YgYW5vdGhlciBpdFxuICAgICAgICAvLyB3aWxsIG1hdGNoIHRoZSBsb25nZXIgcGllY2UuXG4gICAgICAgIHNob3J0UGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICAgICAgbG9uZ1BpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIG1peGVkUGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgICAgIHNob3J0UGllY2VzW2ldID0gcmVnZXhFc2NhcGUoc2hvcnRQaWVjZXNbaV0pO1xuICAgICAgICAgICAgbG9uZ1BpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKGxvbmdQaWVjZXNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAyNDsgaSsrKSB7XG4gICAgICAgICAgICBtaXhlZFBpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKG1peGVkUGllY2VzW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX21vbnRoc1JlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgbWl4ZWRQaWVjZXMuam9pbignfCcpICsgJyknLCAnaScpO1xuICAgICAgICB0aGlzLl9tb250aHNTaG9ydFJlZ2V4ID0gdGhpcy5fbW9udGhzUmVnZXg7XG4gICAgICAgIHRoaXMuX21vbnRoc1N0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgbG9uZ1BpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgICAgIHRoaXMuX21vbnRoc1Nob3J0U3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBzaG9ydFBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRGF0ZSAoeSwgbSwgZCwgaCwgTSwgcywgbXMpIHtcbiAgICAgICAgLy8gY2FuJ3QganVzdCBhcHBseSgpIHRvIGNyZWF0ZSBhIGRhdGU6XG4gICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcS8xODEzNDhcbiAgICAgICAgdmFyIGRhdGU7XG4gICAgICAgIC8vIHRoZSBkYXRlIGNvbnN0cnVjdG9yIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgICAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDApIHtcbiAgICAgICAgICAgIC8vIHByZXNlcnZlIGxlYXAgeWVhcnMgdXNpbmcgYSBmdWxsIDQwMCB5ZWFyIGN5Y2xlLCB0aGVuIHJlc2V0XG4gICAgICAgICAgICBkYXRlID0gbmV3IERhdGUoeSArIDQwMCwgbSwgZCwgaCwgTSwgcywgbXMpO1xuICAgICAgICAgICAgaWYgKGlzRmluaXRlKGRhdGUuZ2V0RnVsbFllYXIoKSkpIHtcbiAgICAgICAgICAgICAgICBkYXRlLnNldEZ1bGxZZWFyKHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0ZSA9IG5ldyBEYXRlKHksIG0sIGQsIGgsIE0sIHMsIG1zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVVUQ0RhdGUgKHkpIHtcbiAgICAgICAgdmFyIGRhdGU7XG4gICAgICAgIC8vIHRoZSBEYXRlLlVUQyBmdW5jdGlvbiByZW1hcHMgeWVhcnMgMC05OSB0byAxOTAwLTE5OTlcbiAgICAgICAgaWYgKHkgPCAxMDAgJiYgeSA+PSAwKSB7XG4gICAgICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAvLyBwcmVzZXJ2ZSBsZWFwIHllYXJzIHVzaW5nIGEgZnVsbCA0MDAgeWVhciBjeWNsZSwgdGhlbiByZXNldFxuICAgICAgICAgICAgYXJnc1swXSA9IHkgKyA0MDA7XG4gICAgICAgICAgICBkYXRlID0gbmV3IERhdGUoRGF0ZS5VVEMuYXBwbHkobnVsbCwgYXJncykpO1xuICAgICAgICAgICAgaWYgKGlzRmluaXRlKGRhdGUuZ2V0VVRDRnVsbFllYXIoKSkpIHtcbiAgICAgICAgICAgICAgICBkYXRlLnNldFVUQ0Z1bGxZZWFyKHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDLmFwcGx5KG51bGwsIGFyZ3VtZW50cykpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfVxuXG4gICAgLy8gc3RhcnQtb2YtZmlyc3Qtd2VlayAtIHN0YXJ0LW9mLXllYXJcbiAgICBmdW5jdGlvbiBmaXJzdFdlZWtPZmZzZXQoeWVhciwgZG93LCBkb3kpIHtcbiAgICAgICAgdmFyIC8vIGZpcnN0LXdlZWsgZGF5IC0tIHdoaWNoIGphbnVhcnkgaXMgYWx3YXlzIGluIHRoZSBmaXJzdCB3ZWVrICg0IGZvciBpc28sIDEgZm9yIG90aGVyKVxuICAgICAgICAgICAgZndkID0gNyArIGRvdyAtIGRveSxcbiAgICAgICAgICAgIC8vIGZpcnN0LXdlZWsgZGF5IGxvY2FsIHdlZWtkYXkgLS0gd2hpY2ggbG9jYWwgd2Vla2RheSBpcyBmd2RcbiAgICAgICAgICAgIGZ3ZGx3ID0gKDcgKyBjcmVhdGVVVENEYXRlKHllYXIsIDAsIGZ3ZCkuZ2V0VVRDRGF5KCkgLSBkb3cpICUgNztcblxuICAgICAgICByZXR1cm4gLWZ3ZGx3ICsgZndkIC0gMTtcbiAgICB9XG5cbiAgICAvLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JU09fd2Vla19kYXRlI0NhbGN1bGF0aW5nX2FfZGF0ZV9naXZlbl90aGVfeWVhci4yQ193ZWVrX251bWJlcl9hbmRfd2Vla2RheVxuICAgIGZ1bmN0aW9uIGRheU9mWWVhckZyb21XZWVrcyh5ZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgICAgICB2YXIgbG9jYWxXZWVrZGF5ID0gKDcgKyB3ZWVrZGF5IC0gZG93KSAlIDcsXG4gICAgICAgICAgICB3ZWVrT2Zmc2V0ID0gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSxcbiAgICAgICAgICAgIGRheU9mWWVhciA9IDEgKyA3ICogKHdlZWsgLSAxKSArIGxvY2FsV2Vla2RheSArIHdlZWtPZmZzZXQsXG4gICAgICAgICAgICByZXNZZWFyLCByZXNEYXlPZlllYXI7XG5cbiAgICAgICAgaWYgKGRheU9mWWVhciA8PSAwKSB7XG4gICAgICAgICAgICByZXNZZWFyID0geWVhciAtIDE7XG4gICAgICAgICAgICByZXNEYXlPZlllYXIgPSBkYXlzSW5ZZWFyKHJlc1llYXIpICsgZGF5T2ZZZWFyO1xuICAgICAgICB9IGVsc2UgaWYgKGRheU9mWWVhciA+IGRheXNJblllYXIoeWVhcikpIHtcbiAgICAgICAgICAgIHJlc1llYXIgPSB5ZWFyICsgMTtcbiAgICAgICAgICAgIHJlc0RheU9mWWVhciA9IGRheU9mWWVhciAtIGRheXNJblllYXIoeWVhcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNZZWFyID0geWVhcjtcbiAgICAgICAgICAgIHJlc0RheU9mWWVhciA9IGRheU9mWWVhcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB5ZWFyOiByZXNZZWFyLFxuICAgICAgICAgICAgZGF5T2ZZZWFyOiByZXNEYXlPZlllYXJcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB3ZWVrT2ZZZWFyKG1vbSwgZG93LCBkb3kpIHtcbiAgICAgICAgdmFyIHdlZWtPZmZzZXQgPSBmaXJzdFdlZWtPZmZzZXQobW9tLnllYXIoKSwgZG93LCBkb3kpLFxuICAgICAgICAgICAgd2VlayA9IE1hdGguZmxvb3IoKG1vbS5kYXlPZlllYXIoKSAtIHdlZWtPZmZzZXQgLSAxKSAvIDcpICsgMSxcbiAgICAgICAgICAgIHJlc1dlZWssIHJlc1llYXI7XG5cbiAgICAgICAgaWYgKHdlZWsgPCAxKSB7XG4gICAgICAgICAgICByZXNZZWFyID0gbW9tLnllYXIoKSAtIDE7XG4gICAgICAgICAgICByZXNXZWVrID0gd2VlayArIHdlZWtzSW5ZZWFyKHJlc1llYXIsIGRvdywgZG95KTtcbiAgICAgICAgfSBlbHNlIGlmICh3ZWVrID4gd2Vla3NJblllYXIobW9tLnllYXIoKSwgZG93LCBkb3kpKSB7XG4gICAgICAgICAgICByZXNXZWVrID0gd2VlayAtIHdlZWtzSW5ZZWFyKG1vbS55ZWFyKCksIGRvdywgZG95KTtcbiAgICAgICAgICAgIHJlc1llYXIgPSBtb20ueWVhcigpICsgMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc1llYXIgPSBtb20ueWVhcigpO1xuICAgICAgICAgICAgcmVzV2VlayA9IHdlZWs7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgd2VlazogcmVzV2VlayxcbiAgICAgICAgICAgIHllYXI6IHJlc1llYXJcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB3ZWVrc0luWWVhcih5ZWFyLCBkb3csIGRveSkge1xuICAgICAgICB2YXIgd2Vla09mZnNldCA9IGZpcnN0V2Vla09mZnNldCh5ZWFyLCBkb3csIGRveSksXG4gICAgICAgICAgICB3ZWVrT2Zmc2V0TmV4dCA9IGZpcnN0V2Vla09mZnNldCh5ZWFyICsgMSwgZG93LCBkb3kpO1xuICAgICAgICByZXR1cm4gKGRheXNJblllYXIoeWVhcikgLSB3ZWVrT2Zmc2V0ICsgd2Vla09mZnNldE5leHQpIC8gNztcbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbigndycsIFsnd3cnLCAyXSwgJ3dvJywgJ3dlZWsnKTtcbiAgICBhZGRGb3JtYXRUb2tlbignVycsIFsnV1cnLCAyXSwgJ1dvJywgJ2lzb1dlZWsnKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnd2VlaycsICd3Jyk7XG4gICAgYWRkVW5pdEFsaWFzKCdpc29XZWVrJywgJ1cnKTtcblxuICAgIC8vIFBSSU9SSVRJRVNcblxuICAgIGFkZFVuaXRQcmlvcml0eSgnd2VlaycsIDUpO1xuICAgIGFkZFVuaXRQcmlvcml0eSgnaXNvV2VlaycsIDUpO1xuXG4gICAgLy8gUEFSU0lOR1xuXG4gICAgYWRkUmVnZXhUb2tlbigndycsICBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ3d3JywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1cnLCAgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdXVycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcblxuICAgIGFkZFdlZWtQYXJzZVRva2VuKFsndycsICd3dycsICdXJywgJ1dXJ10sIGZ1bmN0aW9uIChpbnB1dCwgd2VlaywgY29uZmlnLCB0b2tlbikge1xuICAgICAgICB3ZWVrW3Rva2VuLnN1YnN0cigwLCAxKV0gPSB0b0ludChpbnB1dCk7XG4gICAgfSk7XG5cbiAgICAvLyBIRUxQRVJTXG5cbiAgICAvLyBMT0NBTEVTXG5cbiAgICBmdW5jdGlvbiBsb2NhbGVXZWVrIChtb20pIHtcbiAgICAgICAgcmV0dXJuIHdlZWtPZlllYXIobW9tLCB0aGlzLl93ZWVrLmRvdywgdGhpcy5fd2Vlay5kb3kpLndlZWs7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb2NhbGVXZWVrID0ge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVGaXJzdERheU9mV2VlayAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl93ZWVrLmRvdztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVGaXJzdERheU9mWWVhciAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl93ZWVrLmRveTtcbiAgICB9XG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICBmdW5jdGlvbiBnZXRTZXRXZWVrIChpbnB1dCkge1xuICAgICAgICB2YXIgd2VlayA9IHRoaXMubG9jYWxlRGF0YSgpLndlZWsodGhpcyk7XG4gICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2VlayA6IHRoaXMuYWRkKChpbnB1dCAtIHdlZWspICogNywgJ2QnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTZXRJU09XZWVrIChpbnB1dCkge1xuICAgICAgICB2YXIgd2VlayA9IHdlZWtPZlllYXIodGhpcywgMSwgNCkud2VlaztcbiAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB3ZWVrIDogdGhpcy5hZGQoKGlucHV0IC0gd2VlaykgKiA3LCAnZCcpO1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdkJywgMCwgJ2RvJywgJ2RheScpO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ2RkJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkud2Vla2RheXNNaW4odGhpcywgZm9ybWF0KTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdkZGQnLCAwLCAwLCBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS53ZWVrZGF5c1Nob3J0KHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignZGRkZCcsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLndlZWtkYXlzKHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignZScsIDAsIDAsICd3ZWVrZGF5Jyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ0UnLCAwLCAwLCAnaXNvV2Vla2RheScpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCdkYXknLCAnZCcpO1xuICAgIGFkZFVuaXRBbGlhcygnd2Vla2RheScsICdlJyk7XG4gICAgYWRkVW5pdEFsaWFzKCdpc29XZWVrZGF5JywgJ0UnKTtcblxuICAgIC8vIFBSSU9SSVRZXG4gICAgYWRkVW5pdFByaW9yaXR5KCdkYXknLCAxMSk7XG4gICAgYWRkVW5pdFByaW9yaXR5KCd3ZWVrZGF5JywgMTEpO1xuICAgIGFkZFVuaXRQcmlvcml0eSgnaXNvV2Vla2RheScsIDExKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ2QnLCAgICBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2UnLCAgICBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0UnLCAgICBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2RkJywgICBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLndlZWtkYXlzTWluUmVnZXgoaXNTdHJpY3QpO1xuICAgIH0pO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2RkZCcsICAgZnVuY3Rpb24gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c1Nob3J0UmVnZXgoaXNTdHJpY3QpO1xuICAgIH0pO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2RkZGQnLCAgIGZ1bmN0aW9uIChpc1N0cmljdCwgbG9jYWxlKSB7XG4gICAgICAgIHJldHVybiBsb2NhbGUud2Vla2RheXNSZWdleChpc1N0cmljdCk7XG4gICAgfSk7XG5cbiAgICBhZGRXZWVrUGFyc2VUb2tlbihbJ2RkJywgJ2RkZCcsICdkZGRkJ10sIGZ1bmN0aW9uIChpbnB1dCwgd2VlaywgY29uZmlnLCB0b2tlbikge1xuICAgICAgICB2YXIgd2Vla2RheSA9IGNvbmZpZy5fbG9jYWxlLndlZWtkYXlzUGFyc2UoaW5wdXQsIHRva2VuLCBjb25maWcuX3N0cmljdCk7XG4gICAgICAgIC8vIGlmIHdlIGRpZG4ndCBnZXQgYSB3ZWVrZGF5IG5hbWUsIG1hcmsgdGhlIGRhdGUgYXMgaW52YWxpZFxuICAgICAgICBpZiAod2Vla2RheSAhPSBudWxsKSB7XG4gICAgICAgICAgICB3ZWVrLmQgPSB3ZWVrZGF5O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZFdlZWtkYXkgPSBpbnB1dDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgYWRkV2Vla1BhcnNlVG9rZW4oWydkJywgJ2UnLCAnRSddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICAgICAgd2Vla1t0b2tlbl0gPSB0b0ludChpbnB1dCk7XG4gICAgfSk7XG5cbiAgICAvLyBIRUxQRVJTXG5cbiAgICBmdW5jdGlvbiBwYXJzZVdlZWtkYXkoaW5wdXQsIGxvY2FsZSkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpc05hTihpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUludChpbnB1dCwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgaW5wdXQgPSBsb2NhbGUud2Vla2RheXNQYXJzZShpbnB1dCk7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzZUlzb1dlZWtkYXkoaW5wdXQsIGxvY2FsZSkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c1BhcnNlKGlucHV0KSAlIDcgfHwgNztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNOYU4oaW5wdXQpID8gbnVsbCA6IGlucHV0O1xuICAgIH1cblxuICAgIC8vIExPQ0FMRVNcbiAgICBmdW5jdGlvbiBzaGlmdFdlZWtkYXlzICh3cywgbikge1xuICAgICAgICByZXR1cm4gd3Muc2xpY2UobiwgNykuY29uY2F0KHdzLnNsaWNlKDAsIG4pKTtcbiAgICB9XG5cbiAgICB2YXIgZGVmYXVsdExvY2FsZVdlZWtkYXlzID0gJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpO1xuICAgIGZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzIChtLCBmb3JtYXQpIHtcbiAgICAgICAgdmFyIHdlZWtkYXlzID0gaXNBcnJheSh0aGlzLl93ZWVrZGF5cykgPyB0aGlzLl93ZWVrZGF5cyA6XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1sobSAmJiBtICE9PSB0cnVlICYmIHRoaXMuX3dlZWtkYXlzLmlzRm9ybWF0LnRlc3QoZm9ybWF0KSkgPyAnZm9ybWF0JyA6ICdzdGFuZGFsb25lJ107XG4gICAgICAgIHJldHVybiAobSA9PT0gdHJ1ZSkgPyBzaGlmdFdlZWtkYXlzKHdlZWtkYXlzLCB0aGlzLl93ZWVrLmRvdylcbiAgICAgICAgICAgIDogKG0pID8gd2Vla2RheXNbbS5kYXkoKV0gOiB3ZWVrZGF5cztcbiAgICB9XG5cbiAgICB2YXIgZGVmYXVsdExvY2FsZVdlZWtkYXlzU2hvcnQgPSAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpO1xuICAgIGZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzU2hvcnQgKG0pIHtcbiAgICAgICAgcmV0dXJuIChtID09PSB0cnVlKSA/IHNoaWZ0V2Vla2RheXModGhpcy5fd2Vla2RheXNTaG9ydCwgdGhpcy5fd2Vlay5kb3cpXG4gICAgICAgICAgICA6IChtKSA/IHRoaXMuX3dlZWtkYXlzU2hvcnRbbS5kYXkoKV0gOiB0aGlzLl93ZWVrZGF5c1Nob3J0O1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0TG9jYWxlV2Vla2RheXNNaW4gPSAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyk7XG4gICAgZnVuY3Rpb24gbG9jYWxlV2Vla2RheXNNaW4gKG0pIHtcbiAgICAgICAgcmV0dXJuIChtID09PSB0cnVlKSA/IHNoaWZ0V2Vla2RheXModGhpcy5fd2Vla2RheXNNaW4sIHRoaXMuX3dlZWsuZG93KVxuICAgICAgICAgICAgOiAobSkgPyB0aGlzLl93ZWVrZGF5c01pblttLmRheSgpXSA6IHRoaXMuX3dlZWtkYXlzTWluO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhbmRsZVN0cmljdFBhcnNlJDEod2Vla2RheU5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgICAgIHZhciBpLCBpaSwgbW9tLCBsbGMgPSB3ZWVrZGF5TmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAoIXRoaXMuX3dlZWtkYXlzUGFyc2UpIHtcbiAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZSA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgKytpKSB7XG4gICAgICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCAxXSkuZGF5KGkpO1xuICAgICAgICAgICAgICAgIHRoaXMuX21pbldlZWtkYXlzUGFyc2VbaV0gPSB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlW2ldID0gdGhpcy53ZWVrZGF5c1Nob3J0KG1vbSwgJycpLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXMobW9tLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdHJpY3QpIHtcbiAgICAgICAgICAgIGlmIChmb3JtYXQgPT09ICdkZGRkJykge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3dlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAnZGRkJykge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9taW5XZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoZm9ybWF0ID09PSAnZGRkZCcpIHtcbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAnZGRkJykge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fd2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbWluV2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9taW5XZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzUGFyc2UgKHdlZWtkYXlOYW1lLCBmb3JtYXQsIHN0cmljdCkge1xuICAgICAgICB2YXIgaSwgbW9tLCByZWdleDtcblxuICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlU3RyaWN0UGFyc2UkMS5jYWxsKHRoaXMsIHdlZWtkYXlOYW1lLCBmb3JtYXQsIHN0cmljdCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuX3dlZWtkYXlzUGFyc2UpIHtcbiAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX21pbldlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuXG4gICAgICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIDFdKS5kYXkoaSk7XG4gICAgICAgICAgICBpZiAoc3RyaWN0ICYmICF0aGlzLl9mdWxsV2Vla2RheXNQYXJzZVtpXSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxXZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzKG1vbSwgJycpLnJlcGxhY2UoJy4nLCAnXFxcXC4/JykgKyAnJCcsICdpJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzU2hvcnQobW9tLCAnJykucmVwbGFjZSgnLicsICdcXFxcLj8nKSArICckJywgJ2knKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpLnJlcGxhY2UoJy4nLCAnXFxcXC4/JykgKyAnJCcsICdpJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuX3dlZWtkYXlzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgICAgICByZWdleCA9ICdeJyArIHRoaXMud2Vla2RheXMobW9tLCAnJykgKyAnfF4nICsgdGhpcy53ZWVrZGF5c1Nob3J0KG1vbSwgJycpICsgJ3xeJyArIHRoaXMud2Vla2RheXNNaW4obW9tLCAnJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZVtpXSA9IG5ldyBSZWdFeHAocmVnZXgucmVwbGFjZSgnLicsICcnKSwgJ2knKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRlc3QgdGhlIHJlZ2V4XG4gICAgICAgICAgICBpZiAoc3RyaWN0ICYmIGZvcm1hdCA9PT0gJ2RkZGQnICYmIHRoaXMuX2Z1bGxXZWVrZGF5c1BhcnNlW2ldLnRlc3Qod2Vla2RheU5hbWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0cmljdCAmJiBmb3JtYXQgPT09ICdkZGQnICYmIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzdHJpY3QgJiYgZm9ybWF0ID09PSAnZGQnICYmIHRoaXMuX21pbldlZWtkYXlzUGFyc2VbaV0udGVzdCh3ZWVrZGF5TmFtZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXN0cmljdCAmJiB0aGlzLl93ZWVrZGF5c1BhcnNlW2ldLnRlc3Qod2Vla2RheU5hbWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICBmdW5jdGlvbiBnZXRTZXREYXlPZldlZWsgKGlucHV0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsID8gdGhpcyA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF5ID0gdGhpcy5faXNVVEMgPyB0aGlzLl9kLmdldFVUQ0RheSgpIDogdGhpcy5fZC5nZXREYXkoKTtcbiAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlucHV0ID0gcGFyc2VXZWVrZGF5KGlucHV0LCB0aGlzLmxvY2FsZURhdGEoKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoaW5wdXQgLSBkYXksICdkJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZGF5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0TG9jYWxlRGF5T2ZXZWVrIChpbnB1dCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQgIT0gbnVsbCA/IHRoaXMgOiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHdlZWtkYXkgPSAodGhpcy5kYXkoKSArIDcgLSB0aGlzLmxvY2FsZURhdGEoKS5fd2Vlay5kb3cpICUgNztcbiAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB3ZWVrZGF5IDogdGhpcy5hZGQoaW5wdXQgLSB3ZWVrZGF5LCAnZCcpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFNldElTT0RheU9mV2VlayAoaW5wdXQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ICE9IG51bGwgPyB0aGlzIDogTmFOO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gYmVoYXZlcyB0aGUgc2FtZSBhcyBtb21lbnQjZGF5IGV4Y2VwdFxuICAgICAgICAvLyBhcyBhIGdldHRlciwgcmV0dXJucyA3IGluc3RlYWQgb2YgMCAoMS03IHJhbmdlIGluc3RlYWQgb2YgMC02KVxuICAgICAgICAvLyBhcyBhIHNldHRlciwgc3VuZGF5IHNob3VsZCBiZWxvbmcgdG8gdGhlIHByZXZpb3VzIHdlZWsuXG5cbiAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciB3ZWVrZGF5ID0gcGFyc2VJc29XZWVrZGF5KGlucHV0LCB0aGlzLmxvY2FsZURhdGEoKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXkodGhpcy5kYXkoKSAlIDcgPyB3ZWVrZGF5IDogd2Vla2RheSAtIDcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF5KCkgfHwgNztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBkZWZhdWx0V2Vla2RheXNSZWdleCA9IG1hdGNoV29yZDtcbiAgICBmdW5jdGlvbiB3ZWVrZGF5c1JlZ2V4IChpc1N0cmljdCkge1xuICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU3RyaWN0UmVnZXg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1JlZ2V4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNSZWdleCA9IGRlZmF1bHRXZWVrZGF5c1JlZ2V4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzU3RyaWN0UmVnZXggOiB0aGlzLl93ZWVrZGF5c1JlZ2V4O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRXZWVrZGF5c1Nob3J0UmVnZXggPSBtYXRjaFdvcmQ7XG4gICAgZnVuY3Rpb24gd2Vla2RheXNTaG9ydFJlZ2V4IChpc1N0cmljdCkge1xuICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU2hvcnRTdHJpY3RSZWdleDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU2hvcnRSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzU2hvcnRSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4ID0gZGVmYXVsdFdlZWtkYXlzU2hvcnRSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzU2hvcnRTdHJpY3RSZWdleCA6IHRoaXMuX3dlZWtkYXlzU2hvcnRSZWdleDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBkZWZhdWx0V2Vla2RheXNNaW5SZWdleCA9IG1hdGNoV29yZDtcbiAgICBmdW5jdGlvbiB3ZWVrZGF5c01pblJlZ2V4IChpc1N0cmljdCkge1xuICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNNaW5SZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNNaW5SZWdleCA9IGRlZmF1bHRXZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXggOiB0aGlzLl93ZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBjb21wdXRlV2Vla2RheXNQYXJzZSAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIGNtcExlblJldihhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gYi5sZW5ndGggLSBhLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBtaW5QaWVjZXMgPSBbXSwgc2hvcnRQaWVjZXMgPSBbXSwgbG9uZ1BpZWNlcyA9IFtdLCBtaXhlZFBpZWNlcyA9IFtdLFxuICAgICAgICAgICAgaSwgbW9tLCBtaW5wLCBzaG9ydHAsIGxvbmdwO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcbiAgICAgICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgMV0pLmRheShpKTtcbiAgICAgICAgICAgIG1pbnAgPSB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpO1xuICAgICAgICAgICAgc2hvcnRwID0gdGhpcy53ZWVrZGF5c1Nob3J0KG1vbSwgJycpO1xuICAgICAgICAgICAgbG9uZ3AgPSB0aGlzLndlZWtkYXlzKG1vbSwgJycpO1xuICAgICAgICAgICAgbWluUGllY2VzLnB1c2gobWlucCk7XG4gICAgICAgICAgICBzaG9ydFBpZWNlcy5wdXNoKHNob3J0cCk7XG4gICAgICAgICAgICBsb25nUGllY2VzLnB1c2gobG9uZ3ApO1xuICAgICAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChtaW5wKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2goc2hvcnRwKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2gobG9uZ3ApO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgd2Vla2RheSAob3IgYWJicikgaXMgYSBwcmVmaXggb2YgYW5vdGhlciBpdFxuICAgICAgICAvLyB3aWxsIG1hdGNoIHRoZSBsb25nZXIgcGllY2UuXG4gICAgICAgIG1pblBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIHNob3J0UGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICAgICAgbG9uZ1BpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIG1peGVkUGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDc7IGkrKykge1xuICAgICAgICAgICAgc2hvcnRQaWVjZXNbaV0gPSByZWdleEVzY2FwZShzaG9ydFBpZWNlc1tpXSk7XG4gICAgICAgICAgICBsb25nUGllY2VzW2ldID0gcmVnZXhFc2NhcGUobG9uZ1BpZWNlc1tpXSk7XG4gICAgICAgICAgICBtaXhlZFBpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKG1peGVkUGllY2VzW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3dlZWtkYXlzUmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBtaXhlZFBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgICAgIHRoaXMuX3dlZWtkYXlzU2hvcnRSZWdleCA9IHRoaXMuX3dlZWtkYXlzUmVnZXg7XG4gICAgICAgIHRoaXMuX3dlZWtkYXlzTWluUmVnZXggPSB0aGlzLl93ZWVrZGF5c1JlZ2V4O1xuXG4gICAgICAgIHRoaXMuX3dlZWtkYXlzU3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBsb25nUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICAgICAgdGhpcy5fd2Vla2RheXNTaG9ydFN0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgc2hvcnRQaWVjZXMuam9pbignfCcpICsgJyknLCAnaScpO1xuICAgICAgICB0aGlzLl93ZWVrZGF5c01pblN0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgbWluUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBmdW5jdGlvbiBoRm9ybWF0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ob3VycygpICUgMTIgfHwgMTI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24ga0Zvcm1hdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaG91cnMoKSB8fCAyNDtcbiAgICB9XG5cbiAgICBhZGRGb3JtYXRUb2tlbignSCcsIFsnSEgnLCAyXSwgMCwgJ2hvdXInKTtcbiAgICBhZGRGb3JtYXRUb2tlbignaCcsIFsnaGgnLCAyXSwgMCwgaEZvcm1hdCk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ2snLCBbJ2trJywgMl0sIDAsIGtGb3JtYXQpO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ2htbScsIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICcnICsgaEZvcm1hdC5hcHBseSh0aGlzKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdobW1zcycsIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICcnICsgaEZvcm1hdC5hcHBseSh0aGlzKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKSArXG4gICAgICAgICAgICB6ZXJvRmlsbCh0aGlzLnNlY29uZHMoKSwgMik7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignSG1tJywgMCwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gJycgKyB0aGlzLmhvdXJzKCkgKyB6ZXJvRmlsbCh0aGlzLm1pbnV0ZXMoKSwgMik7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignSG1tc3MnLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAnJyArIHRoaXMuaG91cnMoKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKSArXG4gICAgICAgICAgICB6ZXJvRmlsbCh0aGlzLnNlY29uZHMoKSwgMik7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBtZXJpZGllbSAodG9rZW4sIGxvd2VyY2FzZSkge1xuICAgICAgICBhZGRGb3JtYXRUb2tlbih0b2tlbiwgMCwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLm1lcmlkaWVtKHRoaXMuaG91cnMoKSwgdGhpcy5taW51dGVzKCksIGxvd2VyY2FzZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG1lcmlkaWVtKCdhJywgdHJ1ZSk7XG4gICAgbWVyaWRpZW0oJ0EnLCBmYWxzZSk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ2hvdXInLCAnaCcpO1xuXG4gICAgLy8gUFJJT1JJVFlcbiAgICBhZGRVbml0UHJpb3JpdHkoJ2hvdXInLCAxMyk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBmdW5jdGlvbiBtYXRjaE1lcmlkaWVtIChpc1N0cmljdCwgbG9jYWxlKSB7XG4gICAgICAgIHJldHVybiBsb2NhbGUuX21lcmlkaWVtUGFyc2U7XG4gICAgfVxuXG4gICAgYWRkUmVnZXhUb2tlbignYScsICBtYXRjaE1lcmlkaWVtKTtcbiAgICBhZGRSZWdleFRva2VuKCdBJywgIG1hdGNoTWVyaWRpZW0pO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0gnLCAgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdoJywgIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignaycsICBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0hIJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2hoJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2trJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuXG4gICAgYWRkUmVnZXhUb2tlbignaG1tJywgbWF0Y2gzdG80KTtcbiAgICBhZGRSZWdleFRva2VuKCdobW1zcycsIG1hdGNoNXRvNik7XG4gICAgYWRkUmVnZXhUb2tlbignSG1tJywgbWF0Y2gzdG80KTtcbiAgICBhZGRSZWdleFRva2VuKCdIbW1zcycsIG1hdGNoNXRvNik7XG5cbiAgICBhZGRQYXJzZVRva2VuKFsnSCcsICdISCddLCBIT1VSKTtcbiAgICBhZGRQYXJzZVRva2VuKFsnaycsICdrayddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgdmFyIGtJbnB1dCA9IHRvSW50KGlucHV0KTtcbiAgICAgICAgYXJyYXlbSE9VUl0gPSBrSW5wdXQgPT09IDI0ID8gMCA6IGtJbnB1dDtcbiAgICB9KTtcbiAgICBhZGRQYXJzZVRva2VuKFsnYScsICdBJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICBjb25maWcuX2lzUG0gPSBjb25maWcuX2xvY2FsZS5pc1BNKGlucHV0KTtcbiAgICAgICAgY29uZmlnLl9tZXJpZGllbSA9IGlucHV0O1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oWydoJywgJ2hoJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICBhcnJheVtIT1VSXSA9IHRvSW50KGlucHV0KTtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHRydWU7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbignaG1tJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIHZhciBwb3MgPSBpbnB1dC5sZW5ndGggLSAyO1xuICAgICAgICBhcnJheVtIT1VSXSA9IHRvSW50KGlucHV0LnN1YnN0cigwLCBwb3MpKTtcbiAgICAgICAgYXJyYXlbTUlOVVRFXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MpKTtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHRydWU7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbignaG1tc3MnLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgdmFyIHBvczEgPSBpbnB1dC5sZW5ndGggLSA0O1xuICAgICAgICB2YXIgcG9zMiA9IGlucHV0Lmxlbmd0aCAtIDI7XG4gICAgICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvczEpKTtcbiAgICAgICAgYXJyYXlbTUlOVVRFXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MxLCAyKSk7XG4gICAgICAgIGFycmF5W1NFQ09ORF0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zMikpO1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID0gdHJ1ZTtcbiAgICB9KTtcbiAgICBhZGRQYXJzZVRva2VuKCdIbW0nLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgdmFyIHBvcyA9IGlucHV0Lmxlbmd0aCAtIDI7XG4gICAgICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvcykpO1xuICAgICAgICBhcnJheVtNSU5VVEVdID0gdG9JbnQoaW5wdXQuc3Vic3RyKHBvcykpO1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oJ0htbXNzJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIHZhciBwb3MxID0gaW5wdXQubGVuZ3RoIC0gNDtcbiAgICAgICAgdmFyIHBvczIgPSBpbnB1dC5sZW5ndGggLSAyO1xuICAgICAgICBhcnJheVtIT1VSXSA9IHRvSW50KGlucHV0LnN1YnN0cigwLCBwb3MxKSk7XG4gICAgICAgIGFycmF5W01JTlVURV0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zMSwgMikpO1xuICAgICAgICBhcnJheVtTRUNPTkRdID0gdG9JbnQoaW5wdXQuc3Vic3RyKHBvczIpKTtcbiAgICB9KTtcblxuICAgIC8vIExPQ0FMRVNcblxuICAgIGZ1bmN0aW9uIGxvY2FsZUlzUE0gKGlucHV0KSB7XG4gICAgICAgIC8vIElFOCBRdWlya3MgTW9kZSAmIElFNyBTdGFuZGFyZHMgTW9kZSBkbyBub3QgYWxsb3cgYWNjZXNzaW5nIHN0cmluZ3MgbGlrZSBhcnJheXNcbiAgICAgICAgLy8gVXNpbmcgY2hhckF0IHNob3VsZCBiZSBtb3JlIGNvbXBhdGlibGUuXG4gICAgICAgIHJldHVybiAoKGlucHV0ICsgJycpLnRvTG93ZXJDYXNlKCkuY2hhckF0KDApID09PSAncCcpO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0TG9jYWxlTWVyaWRpZW1QYXJzZSA9IC9bYXBdXFwuP20/XFwuPy9pO1xuICAgIGZ1bmN0aW9uIGxvY2FsZU1lcmlkaWVtIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAncG0nIDogJ1BNJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2FtJyA6ICdBTSc7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8vIE1PTUVOVFNcblxuICAgIC8vIFNldHRpbmcgdGhlIGhvdXIgc2hvdWxkIGtlZXAgdGhlIHRpbWUsIGJlY2F1c2UgdGhlIHVzZXIgZXhwbGljaXRseVxuICAgIC8vIHNwZWNpZmllZCB3aGljaCBob3VyIHRoZXkgd2FudC4gU28gdHJ5aW5nIHRvIG1haW50YWluIHRoZSBzYW1lIGhvdXIgKGluXG4gICAgLy8gYSBuZXcgdGltZXpvbmUpIG1ha2VzIHNlbnNlLiBBZGRpbmcvc3VidHJhY3RpbmcgaG91cnMgZG9lcyBub3QgZm9sbG93XG4gICAgLy8gdGhpcyBydWxlLlxuICAgIHZhciBnZXRTZXRIb3VyID0gbWFrZUdldFNldCgnSG91cnMnLCB0cnVlKTtcblxuICAgIHZhciBiYXNlQ29uZmlnID0ge1xuICAgICAgICBjYWxlbmRhcjogZGVmYXVsdENhbGVuZGFyLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDogZGVmYXVsdExvbmdEYXRlRm9ybWF0LFxuICAgICAgICBpbnZhbGlkRGF0ZTogZGVmYXVsdEludmFsaWREYXRlLFxuICAgICAgICBvcmRpbmFsOiBkZWZhdWx0T3JkaW5hbCxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogZGVmYXVsdERheU9mTW9udGhPcmRpbmFsUGFyc2UsXG4gICAgICAgIHJlbGF0aXZlVGltZTogZGVmYXVsdFJlbGF0aXZlVGltZSxcblxuICAgICAgICBtb250aHM6IGRlZmF1bHRMb2NhbGVNb250aHMsXG4gICAgICAgIG1vbnRoc1Nob3J0OiBkZWZhdWx0TG9jYWxlTW9udGhzU2hvcnQsXG5cbiAgICAgICAgd2VlazogZGVmYXVsdExvY2FsZVdlZWssXG5cbiAgICAgICAgd2Vla2RheXM6IGRlZmF1bHRMb2NhbGVXZWVrZGF5cyxcbiAgICAgICAgd2Vla2RheXNNaW46IGRlZmF1bHRMb2NhbGVXZWVrZGF5c01pbixcbiAgICAgICAgd2Vla2RheXNTaG9ydDogZGVmYXVsdExvY2FsZVdlZWtkYXlzU2hvcnQsXG5cbiAgICAgICAgbWVyaWRpZW1QYXJzZTogZGVmYXVsdExvY2FsZU1lcmlkaWVtUGFyc2VcbiAgICB9O1xuXG4gICAgLy8gaW50ZXJuYWwgc3RvcmFnZSBmb3IgbG9jYWxlIGNvbmZpZyBmaWxlc1xuICAgIHZhciBsb2NhbGVzID0ge307XG4gICAgdmFyIGxvY2FsZUZhbWlsaWVzID0ge307XG4gICAgdmFyIGdsb2JhbExvY2FsZTtcblxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZUxvY2FsZShrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleSA/IGtleS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoJ18nLCAnLScpIDoga2V5O1xuICAgIH1cblxuICAgIC8vIHBpY2sgdGhlIGxvY2FsZSBmcm9tIHRoZSBhcnJheVxuICAgIC8vIHRyeSBbJ2VuLWF1JywgJ2VuLWdiJ10gYXMgJ2VuLWF1JywgJ2VuLWdiJywgJ2VuJywgYXMgaW4gbW92ZSB0aHJvdWdoIHRoZSBsaXN0IHRyeWluZyBlYWNoXG4gICAgLy8gc3Vic3RyaW5nIGZyb20gbW9zdCBzcGVjaWZpYyB0byBsZWFzdCwgYnV0IG1vdmUgdG8gdGhlIG5leHQgYXJyYXkgaXRlbSBpZiBpdCdzIGEgbW9yZSBzcGVjaWZpYyB2YXJpYW50IHRoYW4gdGhlIGN1cnJlbnQgcm9vdFxuICAgIGZ1bmN0aW9uIGNob29zZUxvY2FsZShuYW1lcykge1xuICAgICAgICB2YXIgaSA9IDAsIGosIG5leHQsIGxvY2FsZSwgc3BsaXQ7XG5cbiAgICAgICAgd2hpbGUgKGkgPCBuYW1lcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHNwbGl0ID0gbm9ybWFsaXplTG9jYWxlKG5hbWVzW2ldKS5zcGxpdCgnLScpO1xuICAgICAgICAgICAgaiA9IHNwbGl0Lmxlbmd0aDtcbiAgICAgICAgICAgIG5leHQgPSBub3JtYWxpemVMb2NhbGUobmFtZXNbaSArIDFdKTtcbiAgICAgICAgICAgIG5leHQgPSBuZXh0ID8gbmV4dC5zcGxpdCgnLScpIDogbnVsbDtcbiAgICAgICAgICAgIHdoaWxlIChqID4gMCkge1xuICAgICAgICAgICAgICAgIGxvY2FsZSA9IGxvYWRMb2NhbGUoc3BsaXQuc2xpY2UoMCwgaikuam9pbignLScpKTtcbiAgICAgICAgICAgICAgICBpZiAobG9jYWxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBsb2NhbGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChuZXh0ICYmIG5leHQubGVuZ3RoID49IGogJiYgY29tcGFyZUFycmF5cyhzcGxpdCwgbmV4dCwgdHJ1ZSkgPj0gaiAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgLy90aGUgbmV4dCBhcnJheSBpdGVtIGlzIGJldHRlciB0aGFuIGEgc2hhbGxvd2VyIHN1YnN0cmluZyBvZiB0aGlzIG9uZVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaSsrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnbG9iYWxMb2NhbGU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9hZExvY2FsZShuYW1lKSB7XG4gICAgICAgIHZhciBvbGRMb2NhbGUgPSBudWxsO1xuICAgICAgICAvLyBUT0RPOiBGaW5kIGEgYmV0dGVyIHdheSB0byByZWdpc3RlciBhbmQgbG9hZCBhbGwgdGhlIGxvY2FsZXMgaW4gTm9kZVxuICAgICAgICBpZiAoIWxvY2FsZXNbbmFtZV0gJiYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICAgICAgICAgIG1vZHVsZSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBvbGRMb2NhbGUgPSBnbG9iYWxMb2NhbGUuX2FiYnI7XG4gICAgICAgICAgICAgICAgdmFyIGFsaWFzZWRSZXF1aXJlID0gcmVxdWlyZTtcbiAgICAgICAgICAgICAgICBhbGlhc2VkUmVxdWlyZSgnLi9sb2NhbGUvJyArIG5hbWUpO1xuICAgICAgICAgICAgICAgIGdldFNldEdsb2JhbExvY2FsZShvbGRMb2NhbGUpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbG9jYWxlc1tuYW1lXTtcbiAgICB9XG5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIHdpbGwgbG9hZCBsb2NhbGUgYW5kIHRoZW4gc2V0IHRoZSBnbG9iYWwgbG9jYWxlLiAgSWZcbiAgICAvLyBubyBhcmd1bWVudHMgYXJlIHBhc3NlZCBpbiwgaXQgd2lsbCBzaW1wbHkgcmV0dXJuIHRoZSBjdXJyZW50IGdsb2JhbFxuICAgIC8vIGxvY2FsZSBrZXkuXG4gICAgZnVuY3Rpb24gZ2V0U2V0R2xvYmFsTG9jYWxlIChrZXksIHZhbHVlcykge1xuICAgICAgICB2YXIgZGF0YTtcbiAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgaWYgKGlzVW5kZWZpbmVkKHZhbHVlcykpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gZ2V0TG9jYWxlKGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gZGVmaW5lTG9jYWxlKGtleSwgdmFsdWVzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAvLyBtb21lbnQuZHVyYXRpb24uX2xvY2FsZSA9IG1vbWVudC5fbG9jYWxlID0gZGF0YTtcbiAgICAgICAgICAgICAgICBnbG9iYWxMb2NhbGUgPSBkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCh0eXBlb2YgY29uc29sZSAhPT0gICd1bmRlZmluZWQnKSAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgLy93YXJuIHVzZXIgaWYgYXJndW1lbnRzIGFyZSBwYXNzZWQgYnV0IHRoZSBsb2NhbGUgY291bGQgbm90IGJlIHNldFxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0xvY2FsZSAnICsga2V5ICsgICcgbm90IGZvdW5kLiBEaWQgeW91IGZvcmdldCB0byBsb2FkIGl0PycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBnbG9iYWxMb2NhbGUuX2FiYnI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGVmaW5lTG9jYWxlIChuYW1lLCBjb25maWcpIHtcbiAgICAgICAgaWYgKGNvbmZpZyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGxvY2FsZSwgcGFyZW50Q29uZmlnID0gYmFzZUNvbmZpZztcbiAgICAgICAgICAgIGNvbmZpZy5hYmJyID0gbmFtZTtcbiAgICAgICAgICAgIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBkZXByZWNhdGVTaW1wbGUoJ2RlZmluZUxvY2FsZU92ZXJyaWRlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICd1c2UgbW9tZW50LnVwZGF0ZUxvY2FsZShsb2NhbGVOYW1lLCBjb25maWcpIHRvIGNoYW5nZSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdhbiBleGlzdGluZyBsb2NhbGUuIG1vbWVudC5kZWZpbmVMb2NhbGUobG9jYWxlTmFtZSwgJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAnY29uZmlnKSBzaG91bGQgb25seSBiZSB1c2VkIGZvciBjcmVhdGluZyBhIG5ldyBsb2NhbGUgJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAnU2VlIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvZGVmaW5lLWxvY2FsZS8gZm9yIG1vcmUgaW5mby4nKTtcbiAgICAgICAgICAgICAgICBwYXJlbnRDb25maWcgPSBsb2NhbGVzW25hbWVdLl9jb25maWc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbmZpZy5wYXJlbnRMb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmIChsb2NhbGVzW2NvbmZpZy5wYXJlbnRMb2NhbGVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Q29uZmlnID0gbG9jYWxlc1tjb25maWcucGFyZW50TG9jYWxlXS5fY29uZmlnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxvY2FsZSA9IGxvYWRMb2NhbGUoY29uZmlnLnBhcmVudExvY2FsZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Q29uZmlnID0gbG9jYWxlLl9jb25maWc7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWxvY2FsZUZhbWlsaWVzW2NvbmZpZy5wYXJlbnRMb2NhbGVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxlRmFtaWxpZXNbY29uZmlnLnBhcmVudExvY2FsZV0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsZUZhbWlsaWVzW2NvbmZpZy5wYXJlbnRMb2NhbGVdLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlnOiBjb25maWdcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsb2NhbGVzW25hbWVdID0gbmV3IExvY2FsZShtZXJnZUNvbmZpZ3MocGFyZW50Q29uZmlnLCBjb25maWcpKTtcblxuICAgICAgICAgICAgaWYgKGxvY2FsZUZhbWlsaWVzW25hbWVdKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxlRmFtaWxpZXNbbmFtZV0uZm9yRWFjaChmdW5jdGlvbiAoeCkge1xuICAgICAgICAgICAgICAgICAgICBkZWZpbmVMb2NhbGUoeC5uYW1lLCB4LmNvbmZpZyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGJhY2t3YXJkcyBjb21wYXQgZm9yIG5vdzogYWxzbyBzZXQgdGhlIGxvY2FsZVxuICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHdlIHNldCB0aGUgbG9jYWxlIEFGVEVSIGFsbCBjaGlsZCBsb2NhbGVzIGhhdmUgYmVlblxuICAgICAgICAgICAgLy8gY3JlYXRlZCwgc28gd2Ugd29uJ3QgZW5kIHVwIHdpdGggdGhlIGNoaWxkIGxvY2FsZSBzZXQuXG4gICAgICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG5cblxuICAgICAgICAgICAgcmV0dXJuIGxvY2FsZXNbbmFtZV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB1c2VmdWwgZm9yIHRlc3RpbmdcbiAgICAgICAgICAgIGRlbGV0ZSBsb2NhbGVzW25hbWVdO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVMb2NhbGUobmFtZSwgY29uZmlnKSB7XG4gICAgICAgIGlmIChjb25maWcgIT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGxvY2FsZSwgdG1wTG9jYWxlLCBwYXJlbnRDb25maWcgPSBiYXNlQ29uZmlnO1xuICAgICAgICAgICAgLy8gTUVSR0VcbiAgICAgICAgICAgIHRtcExvY2FsZSA9IGxvYWRMb2NhbGUobmFtZSk7XG4gICAgICAgICAgICBpZiAodG1wTG9jYWxlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnRDb25maWcgPSB0bXBMb2NhbGUuX2NvbmZpZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbmZpZyA9IG1lcmdlQ29uZmlncyhwYXJlbnRDb25maWcsIGNvbmZpZyk7XG4gICAgICAgICAgICBsb2NhbGUgPSBuZXcgTG9jYWxlKGNvbmZpZyk7XG4gICAgICAgICAgICBsb2NhbGUucGFyZW50TG9jYWxlID0gbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgICAgIGxvY2FsZXNbbmFtZV0gPSBsb2NhbGU7XG5cbiAgICAgICAgICAgIC8vIGJhY2t3YXJkcyBjb21wYXQgZm9yIG5vdzogYWxzbyBzZXQgdGhlIGxvY2FsZVxuICAgICAgICAgICAgZ2V0U2V0R2xvYmFsTG9jYWxlKG5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gcGFzcyBudWxsIGZvciBjb25maWcgdG8gdW51cGRhdGUsIHVzZWZ1bCBmb3IgdGVzdHNcbiAgICAgICAgICAgIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAobG9jYWxlc1tuYW1lXS5wYXJlbnRMb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBsb2NhbGVzW25hbWVdID0gbG9jYWxlc1tuYW1lXS5wYXJlbnRMb2NhbGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGxvY2FsZXNbbmFtZV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsb2NhbGVzW25hbWVdO1xuICAgIH1cblxuICAgIC8vIHJldHVybnMgbG9jYWxlIGRhdGFcbiAgICBmdW5jdGlvbiBnZXRMb2NhbGUgKGtleSkge1xuICAgICAgICB2YXIgbG9jYWxlO1xuXG4gICAgICAgIGlmIChrZXkgJiYga2V5Ll9sb2NhbGUgJiYga2V5Ll9sb2NhbGUuX2FiYnIpIHtcbiAgICAgICAgICAgIGtleSA9IGtleS5fbG9jYWxlLl9hYmJyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBnbG9iYWxMb2NhbGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWlzQXJyYXkoa2V5KSkge1xuICAgICAgICAgICAgLy9zaG9ydC1jaXJjdWl0IGV2ZXJ5dGhpbmcgZWxzZVxuICAgICAgICAgICAgbG9jYWxlID0gbG9hZExvY2FsZShrZXkpO1xuICAgICAgICAgICAgaWYgKGxvY2FsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsb2NhbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBrZXkgPSBba2V5XTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjaG9vc2VMb2NhbGUoa2V5KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaXN0TG9jYWxlcygpIHtcbiAgICAgICAgcmV0dXJuIGtleXMobG9jYWxlcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2hlY2tPdmVyZmxvdyAobSkge1xuICAgICAgICB2YXIgb3ZlcmZsb3c7XG4gICAgICAgIHZhciBhID0gbS5fYTtcblxuICAgICAgICBpZiAoYSAmJiBnZXRQYXJzaW5nRmxhZ3MobSkub3ZlcmZsb3cgPT09IC0yKSB7XG4gICAgICAgICAgICBvdmVyZmxvdyA9XG4gICAgICAgICAgICAgICAgYVtNT05USF0gICAgICAgPCAwIHx8IGFbTU9OVEhdICAgICAgID4gMTEgID8gTU9OVEggOlxuICAgICAgICAgICAgICAgIGFbREFURV0gICAgICAgIDwgMSB8fCBhW0RBVEVdICAgICAgICA+IGRheXNJbk1vbnRoKGFbWUVBUl0sIGFbTU9OVEhdKSA/IERBVEUgOlxuICAgICAgICAgICAgICAgIGFbSE9VUl0gICAgICAgIDwgMCB8fCBhW0hPVVJdICAgICAgICA+IDI0IHx8IChhW0hPVVJdID09PSAyNCAmJiAoYVtNSU5VVEVdICE9PSAwIHx8IGFbU0VDT05EXSAhPT0gMCB8fCBhW01JTExJU0VDT05EXSAhPT0gMCkpID8gSE9VUiA6XG4gICAgICAgICAgICAgICAgYVtNSU5VVEVdICAgICAgPCAwIHx8IGFbTUlOVVRFXSAgICAgID4gNTkgID8gTUlOVVRFIDpcbiAgICAgICAgICAgICAgICBhW1NFQ09ORF0gICAgICA8IDAgfHwgYVtTRUNPTkRdICAgICAgPiA1OSAgPyBTRUNPTkQgOlxuICAgICAgICAgICAgICAgIGFbTUlMTElTRUNPTkRdIDwgMCB8fCBhW01JTExJU0VDT05EXSA+IDk5OSA/IE1JTExJU0VDT05EIDpcbiAgICAgICAgICAgICAgICAtMTtcblxuICAgICAgICAgICAgaWYgKGdldFBhcnNpbmdGbGFncyhtKS5fb3ZlcmZsb3dEYXlPZlllYXIgJiYgKG92ZXJmbG93IDwgWUVBUiB8fCBvdmVyZmxvdyA+IERBVEUpKSB7XG4gICAgICAgICAgICAgICAgb3ZlcmZsb3cgPSBEQVRFO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdldFBhcnNpbmdGbGFncyhtKS5fb3ZlcmZsb3dXZWVrcyAmJiBvdmVyZmxvdyA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBvdmVyZmxvdyA9IFdFRUs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZ2V0UGFyc2luZ0ZsYWdzKG0pLl9vdmVyZmxvd1dlZWtkYXkgJiYgb3ZlcmZsb3cgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgb3ZlcmZsb3cgPSBXRUVLREFZO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MobSkub3ZlcmZsb3cgPSBvdmVyZmxvdztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtO1xuICAgIH1cblxuICAgIC8vIFBpY2sgdGhlIGZpcnN0IGRlZmluZWQgb2YgdHdvIG9yIHRocmVlIGFyZ3VtZW50cy5cbiAgICBmdW5jdGlvbiBkZWZhdWx0cyhhLCBiLCBjKSB7XG4gICAgICAgIGlmIChhICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBhO1xuICAgICAgICB9XG4gICAgICAgIGlmIChiICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGN1cnJlbnREYXRlQXJyYXkoY29uZmlnKSB7XG4gICAgICAgIC8vIGhvb2tzIGlzIGFjdHVhbGx5IHRoZSBleHBvcnRlZCBtb21lbnQgb2JqZWN0XG4gICAgICAgIHZhciBub3dWYWx1ZSA9IG5ldyBEYXRlKGhvb2tzLm5vdygpKTtcbiAgICAgICAgaWYgKGNvbmZpZy5fdXNlVVRDKSB7XG4gICAgICAgICAgICByZXR1cm4gW25vd1ZhbHVlLmdldFVUQ0Z1bGxZZWFyKCksIG5vd1ZhbHVlLmdldFVUQ01vbnRoKCksIG5vd1ZhbHVlLmdldFVUQ0RhdGUoKV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtub3dWYWx1ZS5nZXRGdWxsWWVhcigpLCBub3dWYWx1ZS5nZXRNb250aCgpLCBub3dWYWx1ZS5nZXREYXRlKCldO1xuICAgIH1cblxuICAgIC8vIGNvbnZlcnQgYW4gYXJyYXkgdG8gYSBkYXRlLlxuICAgIC8vIHRoZSBhcnJheSBzaG91bGQgbWlycm9yIHRoZSBwYXJhbWV0ZXJzIGJlbG93XG4gICAgLy8gbm90ZTogYWxsIHZhbHVlcyBwYXN0IHRoZSB5ZWFyIGFyZSBvcHRpb25hbCBhbmQgd2lsbCBkZWZhdWx0IHRvIHRoZSBsb3dlc3QgcG9zc2libGUgdmFsdWUuXG4gICAgLy8gW3llYXIsIG1vbnRoLCBkYXkgLCBob3VyLCBtaW51dGUsIHNlY29uZCwgbWlsbGlzZWNvbmRdXG4gICAgZnVuY3Rpb24gY29uZmlnRnJvbUFycmF5IChjb25maWcpIHtcbiAgICAgICAgdmFyIGksIGRhdGUsIGlucHV0ID0gW10sIGN1cnJlbnREYXRlLCBleHBlY3RlZFdlZWtkYXksIHllYXJUb1VzZTtcblxuICAgICAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjdXJyZW50RGF0ZSA9IGN1cnJlbnREYXRlQXJyYXkoY29uZmlnKTtcblxuICAgICAgICAvL2NvbXB1dGUgZGF5IG9mIHRoZSB5ZWFyIGZyb20gd2Vla3MgYW5kIHdlZWtkYXlzXG4gICAgICAgIGlmIChjb25maWcuX3cgJiYgY29uZmlnLl9hW0RBVEVdID09IG51bGwgJiYgY29uZmlnLl9hW01PTlRIXSA9PSBudWxsKSB7XG4gICAgICAgICAgICBkYXlPZlllYXJGcm9tV2Vla0luZm8oY29uZmlnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vaWYgdGhlIGRheSBvZiB0aGUgeWVhciBpcyBzZXQsIGZpZ3VyZSBvdXQgd2hhdCBpdCBpc1xuICAgICAgICBpZiAoY29uZmlnLl9kYXlPZlllYXIgIT0gbnVsbCkge1xuICAgICAgICAgICAgeWVhclRvVXNlID0gZGVmYXVsdHMoY29uZmlnLl9hW1lFQVJdLCBjdXJyZW50RGF0ZVtZRUFSXSk7XG5cbiAgICAgICAgICAgIGlmIChjb25maWcuX2RheU9mWWVhciA+IGRheXNJblllYXIoeWVhclRvVXNlKSB8fCBjb25maWcuX2RheU9mWWVhciA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLl9vdmVyZmxvd0RheU9mWWVhciA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGUgPSBjcmVhdGVVVENEYXRlKHllYXJUb1VzZSwgMCwgY29uZmlnLl9kYXlPZlllYXIpO1xuICAgICAgICAgICAgY29uZmlnLl9hW01PTlRIXSA9IGRhdGUuZ2V0VVRDTW9udGgoKTtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtEQVRFXSA9IGRhdGUuZ2V0VVRDRGF0ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmYXVsdCB0byBjdXJyZW50IGRhdGUuXG4gICAgICAgIC8vICogaWYgbm8geWVhciwgbW9udGgsIGRheSBvZiBtb250aCBhcmUgZ2l2ZW4sIGRlZmF1bHQgdG8gdG9kYXlcbiAgICAgICAgLy8gKiBpZiBkYXkgb2YgbW9udGggaXMgZ2l2ZW4sIGRlZmF1bHQgbW9udGggYW5kIHllYXJcbiAgICAgICAgLy8gKiBpZiBtb250aCBpcyBnaXZlbiwgZGVmYXVsdCBvbmx5IHllYXJcbiAgICAgICAgLy8gKiBpZiB5ZWFyIGlzIGdpdmVuLCBkb24ndCBkZWZhdWx0IGFueXRoaW5nXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAzICYmIGNvbmZpZy5fYVtpXSA9PSBudWxsOyArK2kpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtpXSA9IGlucHV0W2ldID0gY3VycmVudERhdGVbaV07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBaZXJvIG91dCB3aGF0ZXZlciB3YXMgbm90IGRlZmF1bHRlZCwgaW5jbHVkaW5nIHRpbWVcbiAgICAgICAgZm9yICg7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtpXSA9IGlucHV0W2ldID0gKGNvbmZpZy5fYVtpXSA9PSBudWxsKSA/IChpID09PSAyID8gMSA6IDApIDogY29uZmlnLl9hW2ldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgZm9yIDI0OjAwOjAwLjAwMFxuICAgICAgICBpZiAoY29uZmlnLl9hW0hPVVJdID09PSAyNCAmJlxuICAgICAgICAgICAgICAgIGNvbmZpZy5fYVtNSU5VVEVdID09PSAwICYmXG4gICAgICAgICAgICAgICAgY29uZmlnLl9hW1NFQ09ORF0gPT09IDAgJiZcbiAgICAgICAgICAgICAgICBjb25maWcuX2FbTUlMTElTRUNPTkRdID09PSAwKSB7XG4gICAgICAgICAgICBjb25maWcuX25leHREYXkgPSB0cnVlO1xuICAgICAgICAgICAgY29uZmlnLl9hW0hPVVJdID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbmZpZy5fZCA9IChjb25maWcuX3VzZVVUQyA/IGNyZWF0ZVVUQ0RhdGUgOiBjcmVhdGVEYXRlKS5hcHBseShudWxsLCBpbnB1dCk7XG4gICAgICAgIGV4cGVjdGVkV2Vla2RheSA9IGNvbmZpZy5fdXNlVVRDID8gY29uZmlnLl9kLmdldFVUQ0RheSgpIDogY29uZmlnLl9kLmdldERheSgpO1xuXG4gICAgICAgIC8vIEFwcGx5IHRpbWV6b25lIG9mZnNldCBmcm9tIGlucHV0LiBUaGUgYWN0dWFsIHV0Y09mZnNldCBjYW4gYmUgY2hhbmdlZFxuICAgICAgICAvLyB3aXRoIHBhcnNlWm9uZS5cbiAgICAgICAgaWYgKGNvbmZpZy5fdHptICE9IG51bGwpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fZC5zZXRVVENNaW51dGVzKGNvbmZpZy5fZC5nZXRVVENNaW51dGVzKCkgLSBjb25maWcuX3R6bSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnLl9uZXh0RGF5KSB7XG4gICAgICAgICAgICBjb25maWcuX2FbSE9VUl0gPSAyNDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIGZvciBtaXNtYXRjaGluZyBkYXkgb2Ygd2Vla1xuICAgICAgICBpZiAoY29uZmlnLl93ICYmIHR5cGVvZiBjb25maWcuX3cuZCAhPT0gJ3VuZGVmaW5lZCcgJiYgY29uZmlnLl93LmQgIT09IGV4cGVjdGVkV2Vla2RheSkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykud2Vla2RheU1pc21hdGNoID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRheU9mWWVhckZyb21XZWVrSW5mbyhjb25maWcpIHtcbiAgICAgICAgdmFyIHcsIHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSwgdGVtcCwgd2Vla2RheU92ZXJmbG93O1xuXG4gICAgICAgIHcgPSBjb25maWcuX3c7XG4gICAgICAgIGlmICh3LkdHICE9IG51bGwgfHwgdy5XICE9IG51bGwgfHwgdy5FICE9IG51bGwpIHtcbiAgICAgICAgICAgIGRvdyA9IDE7XG4gICAgICAgICAgICBkb3kgPSA0O1xuXG4gICAgICAgICAgICAvLyBUT0RPOiBXZSBuZWVkIHRvIHRha2UgdGhlIGN1cnJlbnQgaXNvV2Vla1llYXIsIGJ1dCB0aGF0IGRlcGVuZHMgb25cbiAgICAgICAgICAgIC8vIGhvdyB3ZSBpbnRlcnByZXQgbm93IChsb2NhbCwgdXRjLCBmaXhlZCBvZmZzZXQpLiBTbyBjcmVhdGVcbiAgICAgICAgICAgIC8vIGEgbm93IHZlcnNpb24gb2YgY3VycmVudCBjb25maWcgKHRha2UgbG9jYWwvdXRjL29mZnNldCBmbGFncywgYW5kXG4gICAgICAgICAgICAvLyBjcmVhdGUgbm93KS5cbiAgICAgICAgICAgIHdlZWtZZWFyID0gZGVmYXVsdHMody5HRywgY29uZmlnLl9hW1lFQVJdLCB3ZWVrT2ZZZWFyKGNyZWF0ZUxvY2FsKCksIDEsIDQpLnllYXIpO1xuICAgICAgICAgICAgd2VlayA9IGRlZmF1bHRzKHcuVywgMSk7XG4gICAgICAgICAgICB3ZWVrZGF5ID0gZGVmYXVsdHMody5FLCAxKTtcbiAgICAgICAgICAgIGlmICh3ZWVrZGF5IDwgMSB8fCB3ZWVrZGF5ID4gNykge1xuICAgICAgICAgICAgICAgIHdlZWtkYXlPdmVyZmxvdyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkb3cgPSBjb25maWcuX2xvY2FsZS5fd2Vlay5kb3c7XG4gICAgICAgICAgICBkb3kgPSBjb25maWcuX2xvY2FsZS5fd2Vlay5kb3k7XG5cbiAgICAgICAgICAgIHZhciBjdXJXZWVrID0gd2Vla09mWWVhcihjcmVhdGVMb2NhbCgpLCBkb3csIGRveSk7XG5cbiAgICAgICAgICAgIHdlZWtZZWFyID0gZGVmYXVsdHMody5nZywgY29uZmlnLl9hW1lFQVJdLCBjdXJXZWVrLnllYXIpO1xuXG4gICAgICAgICAgICAvLyBEZWZhdWx0IHRvIGN1cnJlbnQgd2Vlay5cbiAgICAgICAgICAgIHdlZWsgPSBkZWZhdWx0cyh3LncsIGN1cldlZWsud2Vlayk7XG5cbiAgICAgICAgICAgIGlmICh3LmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIHdlZWtkYXkgLS0gbG93IGRheSBudW1iZXJzIGFyZSBjb25zaWRlcmVkIG5leHQgd2Vla1xuICAgICAgICAgICAgICAgIHdlZWtkYXkgPSB3LmQ7XG4gICAgICAgICAgICAgICAgaWYgKHdlZWtkYXkgPCAwIHx8IHdlZWtkYXkgPiA2KSB7XG4gICAgICAgICAgICAgICAgICAgIHdlZWtkYXlPdmVyZmxvdyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh3LmUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIGxvY2FsIHdlZWtkYXkgLS0gY291bnRpbmcgc3RhcnRzIGZyb20gYmVnaW5uaW5nIG9mIHdlZWtcbiAgICAgICAgICAgICAgICB3ZWVrZGF5ID0gdy5lICsgZG93O1xuICAgICAgICAgICAgICAgIGlmICh3LmUgPCAwIHx8IHcuZSA+IDYpIHtcbiAgICAgICAgICAgICAgICAgICAgd2Vla2RheU92ZXJmbG93ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGRlZmF1bHQgdG8gYmVnaW5uaW5nIG9mIHdlZWtcbiAgICAgICAgICAgICAgICB3ZWVrZGF5ID0gZG93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh3ZWVrIDwgMSB8fCB3ZWVrID4gd2Vla3NJblllYXIod2Vla1llYXIsIGRvdywgZG95KSkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuX292ZXJmbG93V2Vla3MgPSB0cnVlO1xuICAgICAgICB9IGVsc2UgaWYgKHdlZWtkYXlPdmVyZmxvdyAhPSBudWxsKSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5fb3ZlcmZsb3dXZWVrZGF5ID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRlbXAgPSBkYXlPZlllYXJGcm9tV2Vla3Mod2Vla1llYXIsIHdlZWssIHdlZWtkYXksIGRvdywgZG95KTtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtZRUFSXSA9IHRlbXAueWVhcjtcbiAgICAgICAgICAgIGNvbmZpZy5fZGF5T2ZZZWFyID0gdGVtcC5kYXlPZlllYXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpc28gODYwMSByZWdleFxuICAgIC8vIDAwMDAtMDAtMDAgMDAwMC1XMDAgb3IgMDAwMC1XMDAtMCArIFQgKyAwMCBvciAwMDowMCBvciAwMDowMDowMCBvciAwMDowMDowMC4wMDAgKyArMDA6MDAgb3IgKzAwMDAgb3IgKzAwKVxuICAgIHZhciBleHRlbmRlZElzb1JlZ2V4ID0gL15cXHMqKCg/OlsrLV1cXGR7Nn18XFxkezR9KS0oPzpcXGRcXGQtXFxkXFxkfFdcXGRcXGQtXFxkfFdcXGRcXGR8XFxkXFxkXFxkfFxcZFxcZCkpKD86KFR8ICkoXFxkXFxkKD86OlxcZFxcZCg/OjpcXGRcXGQoPzpbLixdXFxkKyk/KT8pPykoW1xcK1xcLV1cXGRcXGQoPzo6P1xcZFxcZCk/fFxccypaKT8pPyQvO1xuICAgIHZhciBiYXNpY0lzb1JlZ2V4ID0gL15cXHMqKCg/OlsrLV1cXGR7Nn18XFxkezR9KSg/OlxcZFxcZFxcZFxcZHxXXFxkXFxkXFxkfFdcXGRcXGR8XFxkXFxkXFxkfFxcZFxcZCkpKD86KFR8ICkoXFxkXFxkKD86XFxkXFxkKD86XFxkXFxkKD86Wy4sXVxcZCspPyk/KT8pKFtcXCtcXC1dXFxkXFxkKD86Oj9cXGRcXGQpP3xcXHMqWik/KT8kLztcblxuICAgIHZhciB0elJlZ2V4ID0gL1p8WystXVxcZFxcZCg/Ojo/XFxkXFxkKT8vO1xuXG4gICAgdmFyIGlzb0RhdGVzID0gW1xuICAgICAgICBbJ1lZWVlZWS1NTS1ERCcsIC9bKy1dXFxkezZ9LVxcZFxcZC1cXGRcXGQvXSxcbiAgICAgICAgWydZWVlZLU1NLUREJywgL1xcZHs0fS1cXGRcXGQtXFxkXFxkL10sXG4gICAgICAgIFsnR0dHRy1bV11XVy1FJywgL1xcZHs0fS1XXFxkXFxkLVxcZC9dLFxuICAgICAgICBbJ0dHR0ctW1ddV1cnLCAvXFxkezR9LVdcXGRcXGQvLCBmYWxzZV0sXG4gICAgICAgIFsnWVlZWS1EREQnLCAvXFxkezR9LVxcZHszfS9dLFxuICAgICAgICBbJ1lZWVktTU0nLCAvXFxkezR9LVxcZFxcZC8sIGZhbHNlXSxcbiAgICAgICAgWydZWVlZWVlNTUREJywgL1srLV1cXGR7MTB9L10sXG4gICAgICAgIFsnWVlZWU1NREQnLCAvXFxkezh9L10sXG4gICAgICAgIC8vIFlZWVlNTSBpcyBOT1QgYWxsb3dlZCBieSB0aGUgc3RhbmRhcmRcbiAgICAgICAgWydHR0dHW1ddV1dFJywgL1xcZHs0fVdcXGR7M30vXSxcbiAgICAgICAgWydHR0dHW1ddV1cnLCAvXFxkezR9V1xcZHsyfS8sIGZhbHNlXSxcbiAgICAgICAgWydZWVlZREREJywgL1xcZHs3fS9dXG4gICAgXTtcblxuICAgIC8vIGlzbyB0aW1lIGZvcm1hdHMgYW5kIHJlZ2V4ZXNcbiAgICB2YXIgaXNvVGltZXMgPSBbXG4gICAgICAgIFsnSEg6bW06c3MuU1NTUycsIC9cXGRcXGQ6XFxkXFxkOlxcZFxcZFxcLlxcZCsvXSxcbiAgICAgICAgWydISDptbTpzcyxTU1NTJywgL1xcZFxcZDpcXGRcXGQ6XFxkXFxkLFxcZCsvXSxcbiAgICAgICAgWydISDptbTpzcycsIC9cXGRcXGQ6XFxkXFxkOlxcZFxcZC9dLFxuICAgICAgICBbJ0hIOm1tJywgL1xcZFxcZDpcXGRcXGQvXSxcbiAgICAgICAgWydISG1tc3MuU1NTUycsIC9cXGRcXGRcXGRcXGRcXGRcXGRcXC5cXGQrL10sXG4gICAgICAgIFsnSEhtbXNzLFNTU1MnLCAvXFxkXFxkXFxkXFxkXFxkXFxkLFxcZCsvXSxcbiAgICAgICAgWydISG1tc3MnLCAvXFxkXFxkXFxkXFxkXFxkXFxkL10sXG4gICAgICAgIFsnSEhtbScsIC9cXGRcXGRcXGRcXGQvXSxcbiAgICAgICAgWydISCcsIC9cXGRcXGQvXVxuICAgIF07XG5cbiAgICB2YXIgYXNwTmV0SnNvblJlZ2V4ID0gL15cXC8/RGF0ZVxcKChcXC0/XFxkKykvaTtcblxuICAgIC8vIGRhdGUgZnJvbSBpc28gZm9ybWF0XG4gICAgZnVuY3Rpb24gY29uZmlnRnJvbUlTTyhjb25maWcpIHtcbiAgICAgICAgdmFyIGksIGwsXG4gICAgICAgICAgICBzdHJpbmcgPSBjb25maWcuX2ksXG4gICAgICAgICAgICBtYXRjaCA9IGV4dGVuZGVkSXNvUmVnZXguZXhlYyhzdHJpbmcpIHx8IGJhc2ljSXNvUmVnZXguZXhlYyhzdHJpbmcpLFxuICAgICAgICAgICAgYWxsb3dUaW1lLCBkYXRlRm9ybWF0LCB0aW1lRm9ybWF0LCB0ekZvcm1hdDtcblxuICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmlzbyA9IHRydWU7XG5cbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGwgPSBpc29EYXRlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNvRGF0ZXNbaV1bMV0uZXhlYyhtYXRjaFsxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0ZUZvcm1hdCA9IGlzb0RhdGVzW2ldWzBdO1xuICAgICAgICAgICAgICAgICAgICBhbGxvd1RpbWUgPSBpc29EYXRlc1tpXVsyXSAhPT0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkYXRlRm9ybWF0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWF0Y2hbM10pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBsID0gaXNvVGltZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc29UaW1lc1tpXVsxXS5leGVjKG1hdGNoWzNdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWF0Y2hbMl0gc2hvdWxkIGJlICdUJyBvciBzcGFjZVxuICAgICAgICAgICAgICAgICAgICAgICAgdGltZUZvcm1hdCA9IChtYXRjaFsyXSB8fCAnICcpICsgaXNvVGltZXNbaV1bMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGltZUZvcm1hdCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFhbGxvd1RpbWUgJiYgdGltZUZvcm1hdCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1hdGNoWzRdKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR6UmVnZXguZXhlYyhtYXRjaFs0XSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdHpGb3JtYXQgPSAnWic7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25maWcuX2YgPSBkYXRlRm9ybWF0ICsgKHRpbWVGb3JtYXQgfHwgJycpICsgKHR6Rm9ybWF0IHx8ICcnKTtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21TdHJpbmdBbmRGb3JtYXQoY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUkZDIDI4MjIgcmVnZXg6IEZvciBkZXRhaWxzIHNlZSBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjMjgyMiNzZWN0aW9uLTMuM1xuICAgIHZhciByZmMyODIyID0gL14oPzooTW9ufFR1ZXxXZWR8VGh1fEZyaXxTYXR8U3VuKSw/XFxzKT8oXFxkezEsMn0pXFxzKEphbnxGZWJ8TWFyfEFwcnxNYXl8SnVufEp1bHxBdWd8U2VwfE9jdHxOb3Z8RGVjKVxccyhcXGR7Miw0fSlcXHMoXFxkXFxkKTooXFxkXFxkKSg/OjooXFxkXFxkKSk/XFxzKD86KFVUfEdNVHxbRUNNUF1bU0RdVCl8KFtael0pfChbKy1dXFxkezR9KSkkLztcblxuICAgIGZ1bmN0aW9uIGV4dHJhY3RGcm9tUkZDMjgyMlN0cmluZ3MoeWVhclN0ciwgbW9udGhTdHIsIGRheVN0ciwgaG91clN0ciwgbWludXRlU3RyLCBzZWNvbmRTdHIpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtcbiAgICAgICAgICAgIHVudHJ1bmNhdGVZZWFyKHllYXJTdHIpLFxuICAgICAgICAgICAgZGVmYXVsdExvY2FsZU1vbnRoc1Nob3J0LmluZGV4T2YobW9udGhTdHIpLFxuICAgICAgICAgICAgcGFyc2VJbnQoZGF5U3RyLCAxMCksXG4gICAgICAgICAgICBwYXJzZUludChob3VyU3RyLCAxMCksXG4gICAgICAgICAgICBwYXJzZUludChtaW51dGVTdHIsIDEwKVxuICAgICAgICBdO1xuXG4gICAgICAgIGlmIChzZWNvbmRTdHIpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKHBhcnNlSW50KHNlY29uZFN0ciwgMTApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdW50cnVuY2F0ZVllYXIoeWVhclN0cikge1xuICAgICAgICB2YXIgeWVhciA9IHBhcnNlSW50KHllYXJTdHIsIDEwKTtcbiAgICAgICAgaWYgKHllYXIgPD0gNDkpIHtcbiAgICAgICAgICAgIHJldHVybiAyMDAwICsgeWVhcjtcbiAgICAgICAgfSBlbHNlIGlmICh5ZWFyIDw9IDk5OSkge1xuICAgICAgICAgICAgcmV0dXJuIDE5MDAgKyB5ZWFyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB5ZWFyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHByZXByb2Nlc3NSRkMyODIyKHMpIHtcbiAgICAgICAgLy8gUmVtb3ZlIGNvbW1lbnRzIGFuZCBmb2xkaW5nIHdoaXRlc3BhY2UgYW5kIHJlcGxhY2UgbXVsdGlwbGUtc3BhY2VzIHdpdGggYSBzaW5nbGUgc3BhY2VcbiAgICAgICAgcmV0dXJuIHMucmVwbGFjZSgvXFwoW14pXSpcXCl8W1xcblxcdF0vZywgJyAnKS5yZXBsYWNlKC8oXFxzXFxzKykvZywgJyAnKS5yZXBsYWNlKC9eXFxzXFxzKi8sICcnKS5yZXBsYWNlKC9cXHNcXHMqJC8sICcnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjaGVja1dlZWtkYXkod2Vla2RheVN0ciwgcGFyc2VkSW5wdXQsIGNvbmZpZykge1xuICAgICAgICBpZiAod2Vla2RheVN0cikge1xuICAgICAgICAgICAgLy8gVE9ETzogUmVwbGFjZSB0aGUgdmFuaWxsYSBKUyBEYXRlIG9iamVjdCB3aXRoIGFuIGluZGVwZW50ZW50IGRheS1vZi13ZWVrIGNoZWNrLlxuICAgICAgICAgICAgdmFyIHdlZWtkYXlQcm92aWRlZCA9IGRlZmF1bHRMb2NhbGVXZWVrZGF5c1Nob3J0LmluZGV4T2Yod2Vla2RheVN0ciksXG4gICAgICAgICAgICAgICAgd2Vla2RheUFjdHVhbCA9IG5ldyBEYXRlKHBhcnNlZElucHV0WzBdLCBwYXJzZWRJbnB1dFsxXSwgcGFyc2VkSW5wdXRbMl0pLmdldERheSgpO1xuICAgICAgICAgICAgaWYgKHdlZWtkYXlQcm92aWRlZCAhPT0gd2Vla2RheUFjdHVhbCkge1xuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLndlZWtkYXlNaXNtYXRjaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHZhciBvYnNPZmZzZXRzID0ge1xuICAgICAgICBVVDogMCxcbiAgICAgICAgR01UOiAwLFxuICAgICAgICBFRFQ6IC00ICogNjAsXG4gICAgICAgIEVTVDogLTUgKiA2MCxcbiAgICAgICAgQ0RUOiAtNSAqIDYwLFxuICAgICAgICBDU1Q6IC02ICogNjAsXG4gICAgICAgIE1EVDogLTYgKiA2MCxcbiAgICAgICAgTVNUOiAtNyAqIDYwLFxuICAgICAgICBQRFQ6IC03ICogNjAsXG4gICAgICAgIFBTVDogLTggKiA2MFxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBjYWxjdWxhdGVPZmZzZXQob2JzT2Zmc2V0LCBtaWxpdGFyeU9mZnNldCwgbnVtT2Zmc2V0KSB7XG4gICAgICAgIGlmIChvYnNPZmZzZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBvYnNPZmZzZXRzW29ic09mZnNldF07XG4gICAgICAgIH0gZWxzZSBpZiAobWlsaXRhcnlPZmZzZXQpIHtcbiAgICAgICAgICAgIC8vIHRoZSBvbmx5IGFsbG93ZWQgbWlsaXRhcnkgdHogaXMgWlxuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgaG0gPSBwYXJzZUludChudW1PZmZzZXQsIDEwKTtcbiAgICAgICAgICAgIHZhciBtID0gaG0gJSAxMDAsIGggPSAoaG0gLSBtKSAvIDEwMDtcbiAgICAgICAgICAgIHJldHVybiBoICogNjAgKyBtO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZGF0ZSBhbmQgdGltZSBmcm9tIHJlZiAyODIyIGZvcm1hdFxuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21SRkMyODIyKGNvbmZpZykge1xuICAgICAgICB2YXIgbWF0Y2ggPSByZmMyODIyLmV4ZWMocHJlcHJvY2Vzc1JGQzI4MjIoY29uZmlnLl9pKSk7XG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgdmFyIHBhcnNlZEFycmF5ID0gZXh0cmFjdEZyb21SRkMyODIyU3RyaW5ncyhtYXRjaFs0XSwgbWF0Y2hbM10sIG1hdGNoWzJdLCBtYXRjaFs1XSwgbWF0Y2hbNl0sIG1hdGNoWzddKTtcbiAgICAgICAgICAgIGlmICghY2hlY2tXZWVrZGF5KG1hdGNoWzFdLCBwYXJzZWRBcnJheSwgY29uZmlnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uZmlnLl9hID0gcGFyc2VkQXJyYXk7XG4gICAgICAgICAgICBjb25maWcuX3R6bSA9IGNhbGN1bGF0ZU9mZnNldChtYXRjaFs4XSwgbWF0Y2hbOV0sIG1hdGNoWzEwXSk7XG5cbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IGNyZWF0ZVVUQ0RhdGUuYXBwbHkobnVsbCwgY29uZmlnLl9hKTtcbiAgICAgICAgICAgIGNvbmZpZy5fZC5zZXRVVENNaW51dGVzKGNvbmZpZy5fZC5nZXRVVENNaW51dGVzKCkgLSBjb25maWcuX3R6bSk7XG5cbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnJmYzI4MjIgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBkYXRlIGZyb20gaXNvIGZvcm1hdCBvciBmYWxsYmFja1xuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21TdHJpbmcoY29uZmlnKSB7XG4gICAgICAgIHZhciBtYXRjaGVkID0gYXNwTmV0SnNvblJlZ2V4LmV4ZWMoY29uZmlnLl9pKTtcblxuICAgICAgICBpZiAobWF0Y2hlZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoK21hdGNoZWRbMV0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uZmlnRnJvbUlTTyhjb25maWcpO1xuICAgICAgICBpZiAoY29uZmlnLl9pc1ZhbGlkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgZGVsZXRlIGNvbmZpZy5faXNWYWxpZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbmZpZ0Zyb21SRkMyODIyKGNvbmZpZyk7XG4gICAgICAgIGlmIChjb25maWcuX2lzVmFsaWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBkZWxldGUgY29uZmlnLl9pc1ZhbGlkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRmluYWwgYXR0ZW1wdCwgdXNlIElucHV0IEZhbGxiYWNrXG4gICAgICAgIGhvb2tzLmNyZWF0ZUZyb21JbnB1dEZhbGxiYWNrKGNvbmZpZyk7XG4gICAgfVxuXG4gICAgaG9va3MuY3JlYXRlRnJvbUlucHV0RmFsbGJhY2sgPSBkZXByZWNhdGUoXG4gICAgICAgICd2YWx1ZSBwcm92aWRlZCBpcyBub3QgaW4gYSByZWNvZ25pemVkIFJGQzI4MjIgb3IgSVNPIGZvcm1hdC4gbW9tZW50IGNvbnN0cnVjdGlvbiBmYWxscyBiYWNrIHRvIGpzIERhdGUoKSwgJyArXG4gICAgICAgICd3aGljaCBpcyBub3QgcmVsaWFibGUgYWNyb3NzIGFsbCBicm93c2VycyBhbmQgdmVyc2lvbnMuIE5vbiBSRkMyODIyL0lTTyBkYXRlIGZvcm1hdHMgYXJlICcgK1xuICAgICAgICAnZGlzY291cmFnZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiBhbiB1cGNvbWluZyBtYWpvciByZWxlYXNlLiBQbGVhc2UgcmVmZXIgdG8gJyArXG4gICAgICAgICdodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL2pzLWRhdGUvIGZvciBtb3JlIGluZm8uJyxcbiAgICAgICAgZnVuY3Rpb24gKGNvbmZpZykge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoY29uZmlnLl9pICsgKGNvbmZpZy5fdXNlVVRDID8gJyBVVEMnIDogJycpKTtcbiAgICAgICAgfVxuICAgICk7XG5cbiAgICAvLyBjb25zdGFudCB0aGF0IHJlZmVycyB0byB0aGUgSVNPIHN0YW5kYXJkXG4gICAgaG9va3MuSVNPXzg2MDEgPSBmdW5jdGlvbiAoKSB7fTtcblxuICAgIC8vIGNvbnN0YW50IHRoYXQgcmVmZXJzIHRvIHRoZSBSRkMgMjgyMiBmb3JtXG4gICAgaG9va3MuUkZDXzI4MjIgPSBmdW5jdGlvbiAoKSB7fTtcblxuICAgIC8vIGRhdGUgZnJvbSBzdHJpbmcgYW5kIGZvcm1hdCBzdHJpbmdcbiAgICBmdW5jdGlvbiBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZykge1xuICAgICAgICAvLyBUT0RPOiBNb3ZlIHRoaXMgdG8gYW5vdGhlciBwYXJ0IG9mIHRoZSBjcmVhdGlvbiBmbG93IHRvIHByZXZlbnQgY2lyY3VsYXIgZGVwc1xuICAgICAgICBpZiAoY29uZmlnLl9mID09PSBob29rcy5JU09fODYwMSkge1xuICAgICAgICAgICAgY29uZmlnRnJvbUlTTyhjb25maWcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb25maWcuX2YgPT09IGhvb2tzLlJGQ18yODIyKSB7XG4gICAgICAgICAgICBjb25maWdGcm9tUkZDMjgyMihjb25maWcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbmZpZy5fYSA9IFtdO1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5lbXB0eSA9IHRydWU7XG5cbiAgICAgICAgLy8gVGhpcyBhcnJheSBpcyB1c2VkIHRvIG1ha2UgYSBEYXRlLCBlaXRoZXIgd2l0aCBgbmV3IERhdGVgIG9yIGBEYXRlLlVUQ2BcbiAgICAgICAgdmFyIHN0cmluZyA9ICcnICsgY29uZmlnLl9pLFxuICAgICAgICAgICAgaSwgcGFyc2VkSW5wdXQsIHRva2VucywgdG9rZW4sIHNraXBwZWQsXG4gICAgICAgICAgICBzdHJpbmdMZW5ndGggPSBzdHJpbmcubGVuZ3RoLFxuICAgICAgICAgICAgdG90YWxQYXJzZWRJbnB1dExlbmd0aCA9IDA7XG5cbiAgICAgICAgdG9rZW5zID0gZXhwYW5kRm9ybWF0KGNvbmZpZy5fZiwgY29uZmlnLl9sb2NhbGUpLm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpIHx8IFtdO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRva2VuID0gdG9rZW5zW2ldO1xuICAgICAgICAgICAgcGFyc2VkSW5wdXQgPSAoc3RyaW5nLm1hdGNoKGdldFBhcnNlUmVnZXhGb3JUb2tlbih0b2tlbiwgY29uZmlnKSkgfHwgW10pWzBdO1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ3Rva2VuJywgdG9rZW4sICdwYXJzZWRJbnB1dCcsIHBhcnNlZElucHV0LFxuICAgICAgICAgICAgLy8gICAgICAgICAncmVnZXgnLCBnZXRQYXJzZVJlZ2V4Rm9yVG9rZW4odG9rZW4sIGNvbmZpZykpO1xuICAgICAgICAgICAgaWYgKHBhcnNlZElucHV0KSB7XG4gICAgICAgICAgICAgICAgc2tpcHBlZCA9IHN0cmluZy5zdWJzdHIoMCwgc3RyaW5nLmluZGV4T2YocGFyc2VkSW5wdXQpKTtcbiAgICAgICAgICAgICAgICBpZiAoc2tpcHBlZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZElucHV0LnB1c2goc2tpcHBlZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN0cmluZyA9IHN0cmluZy5zbGljZShzdHJpbmcuaW5kZXhPZihwYXJzZWRJbnB1dCkgKyBwYXJzZWRJbnB1dC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIHRvdGFsUGFyc2VkSW5wdXRMZW5ndGggKz0gcGFyc2VkSW5wdXQubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZG9uJ3QgcGFyc2UgaWYgaXQncyBub3QgYSBrbm93biB0b2tlblxuICAgICAgICAgICAgaWYgKGZvcm1hdFRva2VuRnVuY3Rpb25zW3Rva2VuXSkge1xuICAgICAgICAgICAgICAgIGlmIChwYXJzZWRJbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5lbXB0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykudW51c2VkVG9rZW5zLnB1c2godG9rZW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhZGRUaW1lVG9BcnJheUZyb21Ub2tlbih0b2tlbiwgcGFyc2VkSW5wdXQsIGNvbmZpZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjb25maWcuX3N0cmljdCAmJiAhcGFyc2VkSW5wdXQpIHtcbiAgICAgICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS51bnVzZWRUb2tlbnMucHVzaCh0b2tlbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGQgcmVtYWluaW5nIHVucGFyc2VkIGlucHV0IGxlbmd0aCB0byB0aGUgc3RyaW5nXG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmNoYXJzTGVmdE92ZXIgPSBzdHJpbmdMZW5ndGggLSB0b3RhbFBhcnNlZElucHV0TGVuZ3RoO1xuICAgICAgICBpZiAoc3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZElucHV0LnB1c2goc3RyaW5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNsZWFyIF8xMmggZmxhZyBpZiBob3VyIGlzIDw9IDEyXG4gICAgICAgIGlmIChjb25maWcuX2FbSE9VUl0gPD0gMTIgJiZcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmJpZ0hvdXIgPT09IHRydWUgJiZcbiAgICAgICAgICAgIGNvbmZpZy5fYVtIT1VSXSA+IDApIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmJpZ0hvdXIgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5wYXJzZWREYXRlUGFydHMgPSBjb25maWcuX2Euc2xpY2UoMCk7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLm1lcmlkaWVtID0gY29uZmlnLl9tZXJpZGllbTtcbiAgICAgICAgLy8gaGFuZGxlIG1lcmlkaWVtXG4gICAgICAgIGNvbmZpZy5fYVtIT1VSXSA9IG1lcmlkaWVtRml4V3JhcChjb25maWcuX2xvY2FsZSwgY29uZmlnLl9hW0hPVVJdLCBjb25maWcuX21lcmlkaWVtKTtcblxuICAgICAgICBjb25maWdGcm9tQXJyYXkoY29uZmlnKTtcbiAgICAgICAgY2hlY2tPdmVyZmxvdyhjb25maWcpO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gbWVyaWRpZW1GaXhXcmFwIChsb2NhbGUsIGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIHZhciBpc1BtO1xuXG4gICAgICAgIGlmIChtZXJpZGllbSA9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBub3RoaW5nIHRvIGRvXG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobG9jYWxlLm1lcmlkaWVtSG91ciAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxlLm1lcmlkaWVtSG91cihob3VyLCBtZXJpZGllbSk7XG4gICAgICAgIH0gZWxzZSBpZiAobG9jYWxlLmlzUE0gIT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gRmFsbGJhY2tcbiAgICAgICAgICAgIGlzUG0gPSBsb2NhbGUuaXNQTShtZXJpZGllbSk7XG4gICAgICAgICAgICBpZiAoaXNQbSAmJiBob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyICs9IDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc1BtICYmIGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgbm90IHN1cHBvc2VkIHRvIGhhcHBlblxuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBkYXRlIGZyb20gc3RyaW5nIGFuZCBhcnJheSBvZiBmb3JtYXQgc3RyaW5nc1xuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21TdHJpbmdBbmRBcnJheShjb25maWcpIHtcbiAgICAgICAgdmFyIHRlbXBDb25maWcsXG4gICAgICAgICAgICBiZXN0TW9tZW50LFxuXG4gICAgICAgICAgICBzY29yZVRvQmVhdCxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICBjdXJyZW50U2NvcmU7XG5cbiAgICAgICAgaWYgKGNvbmZpZy5fZi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmludmFsaWRGb3JtYXQgPSB0cnVlO1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoTmFOKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb25maWcuX2YubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGN1cnJlbnRTY29yZSA9IDA7XG4gICAgICAgICAgICB0ZW1wQ29uZmlnID0gY29weUNvbmZpZyh7fSwgY29uZmlnKTtcbiAgICAgICAgICAgIGlmIChjb25maWcuX3VzZVVUQyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGVtcENvbmZpZy5fdXNlVVRDID0gY29uZmlnLl91c2VVVEM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0ZW1wQ29uZmlnLl9mID0gY29uZmlnLl9mW2ldO1xuICAgICAgICAgICAgY29uZmlnRnJvbVN0cmluZ0FuZEZvcm1hdCh0ZW1wQ29uZmlnKTtcblxuICAgICAgICAgICAgaWYgKCFpc1ZhbGlkKHRlbXBDb25maWcpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGlmIHRoZXJlIGlzIGFueSBpbnB1dCB0aGF0IHdhcyBub3QgcGFyc2VkIGFkZCBhIHBlbmFsdHkgZm9yIHRoYXQgZm9ybWF0XG4gICAgICAgICAgICBjdXJyZW50U2NvcmUgKz0gZ2V0UGFyc2luZ0ZsYWdzKHRlbXBDb25maWcpLmNoYXJzTGVmdE92ZXI7XG5cbiAgICAgICAgICAgIC8vb3IgdG9rZW5zXG4gICAgICAgICAgICBjdXJyZW50U2NvcmUgKz0gZ2V0UGFyc2luZ0ZsYWdzKHRlbXBDb25maWcpLnVudXNlZFRva2Vucy5sZW5ndGggKiAxMDtcblxuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKHRlbXBDb25maWcpLnNjb3JlID0gY3VycmVudFNjb3JlO1xuXG4gICAgICAgICAgICBpZiAoc2NvcmVUb0JlYXQgPT0gbnVsbCB8fCBjdXJyZW50U2NvcmUgPCBzY29yZVRvQmVhdCkge1xuICAgICAgICAgICAgICAgIHNjb3JlVG9CZWF0ID0gY3VycmVudFNjb3JlO1xuICAgICAgICAgICAgICAgIGJlc3RNb21lbnQgPSB0ZW1wQ29uZmlnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZXh0ZW5kKGNvbmZpZywgYmVzdE1vbWVudCB8fCB0ZW1wQ29uZmlnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb25maWdGcm9tT2JqZWN0KGNvbmZpZykge1xuICAgICAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaSA9IG5vcm1hbGl6ZU9iamVjdFVuaXRzKGNvbmZpZy5faSk7XG4gICAgICAgIGNvbmZpZy5fYSA9IG1hcChbaS55ZWFyLCBpLm1vbnRoLCBpLmRheSB8fCBpLmRhdGUsIGkuaG91ciwgaS5taW51dGUsIGkuc2Vjb25kLCBpLm1pbGxpc2Vjb25kXSwgZnVuY3Rpb24gKG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iaiAmJiBwYXJzZUludChvYmosIDEwKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uZmlnRnJvbUFycmF5KGNvbmZpZyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnJvbUNvbmZpZyAoY29uZmlnKSB7XG4gICAgICAgIHZhciByZXMgPSBuZXcgTW9tZW50KGNoZWNrT3ZlcmZsb3cocHJlcGFyZUNvbmZpZyhjb25maWcpKSk7XG4gICAgICAgIGlmIChyZXMuX25leHREYXkpIHtcbiAgICAgICAgICAgIC8vIEFkZGluZyBpcyBzbWFydCBlbm91Z2ggYXJvdW5kIERTVFxuICAgICAgICAgICAgcmVzLmFkZCgxLCAnZCcpO1xuICAgICAgICAgICAgcmVzLl9uZXh0RGF5ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcmVwYXJlQ29uZmlnIChjb25maWcpIHtcbiAgICAgICAgdmFyIGlucHV0ID0gY29uZmlnLl9pLFxuICAgICAgICAgICAgZm9ybWF0ID0gY29uZmlnLl9mO1xuXG4gICAgICAgIGNvbmZpZy5fbG9jYWxlID0gY29uZmlnLl9sb2NhbGUgfHwgZ2V0TG9jYWxlKGNvbmZpZy5fbCk7XG5cbiAgICAgICAgaWYgKGlucHV0ID09PSBudWxsIHx8IChmb3JtYXQgPT09IHVuZGVmaW5lZCAmJiBpbnB1dCA9PT0gJycpKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlSW52YWxpZCh7bnVsbElucHV0OiB0cnVlfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uZmlnLl9pID0gaW5wdXQgPSBjb25maWcuX2xvY2FsZS5wcmVwYXJzZShpbnB1dCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNNb21lbnQoaW5wdXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1vbWVudChjaGVja092ZXJmbG93KGlucHV0KSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNEYXRlKGlucHV0KSkge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gaW5wdXQ7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShmb3JtYXQpKSB7XG4gICAgICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kQXJyYXkoY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQpIHtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21TdHJpbmdBbmRGb3JtYXQoY29uZmlnKTtcbiAgICAgICAgfSAgZWxzZSB7XG4gICAgICAgICAgICBjb25maWdGcm9tSW5wdXQoY29uZmlnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNWYWxpZChjb25maWcpKSB7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb25maWdGcm9tSW5wdXQoY29uZmlnKSB7XG4gICAgICAgIHZhciBpbnB1dCA9IGNvbmZpZy5faTtcbiAgICAgICAgaWYgKGlzVW5kZWZpbmVkKGlucHV0KSkge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoaG9va3Mubm93KCkpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzRGF0ZShpbnB1dCkpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKGlucHV0LnZhbHVlT2YoKSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uZmlnRnJvbVN0cmluZyhjb25maWcpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgICAgICBjb25maWcuX2EgPSBtYXAoaW5wdXQuc2xpY2UoMCksIGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQob2JqLCAxMCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21BcnJheShjb25maWcpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGlucHV0KSkge1xuICAgICAgICAgICAgY29uZmlnRnJvbU9iamVjdChjb25maWcpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzTnVtYmVyKGlucHV0KSkge1xuICAgICAgICAgICAgLy8gZnJvbSBtaWxsaXNlY29uZHNcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKGlucHV0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhvb2tzLmNyZWF0ZUZyb21JbnB1dEZhbGxiYWNrKGNvbmZpZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVMb2NhbE9yVVRDIChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCwgaXNVVEMpIHtcbiAgICAgICAgdmFyIGMgPSB7fTtcblxuICAgICAgICBpZiAobG9jYWxlID09PSB0cnVlIHx8IGxvY2FsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHN0cmljdCA9IGxvY2FsZTtcbiAgICAgICAgICAgIGxvY2FsZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgoaXNPYmplY3QoaW5wdXQpICYmIGlzT2JqZWN0RW1wdHkoaW5wdXQpKSB8fFxuICAgICAgICAgICAgICAgIChpc0FycmF5KGlucHV0KSAmJiBpbnB1dC5sZW5ndGggPT09IDApKSB7XG4gICAgICAgICAgICBpbnB1dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBvYmplY3QgY29uc3RydWN0aW9uIG11c3QgYmUgZG9uZSB0aGlzIHdheS5cbiAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzE0MjNcbiAgICAgICAgYy5faXNBTW9tZW50T2JqZWN0ID0gdHJ1ZTtcbiAgICAgICAgYy5fdXNlVVRDID0gYy5faXNVVEMgPSBpc1VUQztcbiAgICAgICAgYy5fbCA9IGxvY2FsZTtcbiAgICAgICAgYy5faSA9IGlucHV0O1xuICAgICAgICBjLl9mID0gZm9ybWF0O1xuICAgICAgICBjLl9zdHJpY3QgPSBzdHJpY3Q7XG5cbiAgICAgICAgcmV0dXJuIGNyZWF0ZUZyb21Db25maWcoYyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlTG9jYWwgKGlucHV0LCBmb3JtYXQsIGxvY2FsZSwgc3RyaWN0KSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVMb2NhbE9yVVRDKGlucHV0LCBmb3JtYXQsIGxvY2FsZSwgc3RyaWN0LCBmYWxzZSk7XG4gICAgfVxuXG4gICAgdmFyIHByb3RvdHlwZU1pbiA9IGRlcHJlY2F0ZShcbiAgICAgICAgJ21vbWVudCgpLm1pbiBpcyBkZXByZWNhdGVkLCB1c2UgbW9tZW50Lm1heCBpbnN0ZWFkLiBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL21pbi1tYXgvJyxcbiAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG90aGVyID0gY3JlYXRlTG9jYWwuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVmFsaWQoKSAmJiBvdGhlci5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3RoZXIgPCB0aGlzID8gdGhpcyA6IG90aGVyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlSW52YWxpZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgKTtcblxuICAgIHZhciBwcm90b3R5cGVNYXggPSBkZXByZWNhdGUoXG4gICAgICAgICdtb21lbnQoKS5tYXggaXMgZGVwcmVjYXRlZCwgdXNlIG1vbWVudC5taW4gaW5zdGVhZC4gaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9taW4tbWF4LycsXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBvdGhlciA9IGNyZWF0ZUxvY2FsLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1ZhbGlkKCkgJiYgb3RoZXIuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG90aGVyID4gdGhpcyA/IHRoaXMgOiBvdGhlcjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUludmFsaWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICk7XG5cbiAgICAvLyBQaWNrIGEgbW9tZW50IG0gZnJvbSBtb21lbnRzIHNvIHRoYXQgbVtmbl0ob3RoZXIpIGlzIHRydWUgZm9yIGFsbFxuICAgIC8vIG90aGVyLiBUaGlzIHJlbGllcyBvbiB0aGUgZnVuY3Rpb24gZm4gdG8gYmUgdHJhbnNpdGl2ZS5cbiAgICAvL1xuICAgIC8vIG1vbWVudHMgc2hvdWxkIGVpdGhlciBiZSBhbiBhcnJheSBvZiBtb21lbnQgb2JqZWN0cyBvciBhbiBhcnJheSwgd2hvc2VcbiAgICAvLyBmaXJzdCBlbGVtZW50IGlzIGFuIGFycmF5IG9mIG1vbWVudCBvYmplY3RzLlxuICAgIGZ1bmN0aW9uIHBpY2tCeShmbiwgbW9tZW50cykge1xuICAgICAgICB2YXIgcmVzLCBpO1xuICAgICAgICBpZiAobW9tZW50cy5sZW5ndGggPT09IDEgJiYgaXNBcnJheShtb21lbnRzWzBdKSkge1xuICAgICAgICAgICAgbW9tZW50cyA9IG1vbWVudHNbMF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFtb21lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzID0gbW9tZW50c1swXTtcbiAgICAgICAgZm9yIChpID0gMTsgaSA8IG1vbWVudHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIGlmICghbW9tZW50c1tpXS5pc1ZhbGlkKCkgfHwgbW9tZW50c1tpXVtmbl0ocmVzKSkge1xuICAgICAgICAgICAgICAgIHJlcyA9IG1vbWVudHNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBVc2UgW10uc29ydCBpbnN0ZWFkP1xuICAgIGZ1bmN0aW9uIG1pbiAoKSB7XG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuXG4gICAgICAgIHJldHVybiBwaWNrQnkoJ2lzQmVmb3JlJywgYXJncyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWF4ICgpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCk7XG5cbiAgICAgICAgcmV0dXJuIHBpY2tCeSgnaXNBZnRlcicsIGFyZ3MpO1xuICAgIH1cblxuICAgIHZhciBub3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBEYXRlLm5vdyA/IERhdGUubm93KCkgOiArKG5ldyBEYXRlKCkpO1xuICAgIH07XG5cbiAgICB2YXIgb3JkZXJpbmcgPSBbJ3llYXInLCAncXVhcnRlcicsICdtb250aCcsICd3ZWVrJywgJ2RheScsICdob3VyJywgJ21pbnV0ZScsICdzZWNvbmQnLCAnbWlsbGlzZWNvbmQnXTtcblxuICAgIGZ1bmN0aW9uIGlzRHVyYXRpb25WYWxpZChtKSB7XG4gICAgICAgIGZvciAodmFyIGtleSBpbiBtKSB7XG4gICAgICAgICAgICBpZiAoIShpbmRleE9mLmNhbGwob3JkZXJpbmcsIGtleSkgIT09IC0xICYmIChtW2tleV0gPT0gbnVsbCB8fCAhaXNOYU4obVtrZXldKSkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHVuaXRIYXNEZWNpbWFsID0gZmFsc2U7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3JkZXJpbmcubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIGlmIChtW29yZGVyaW5nW2ldXSkge1xuICAgICAgICAgICAgICAgIGlmICh1bml0SGFzRGVjaW1hbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7IC8vIG9ubHkgYWxsb3cgbm9uLWludGVnZXJzIGZvciBzbWFsbGVzdCB1bml0XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwYXJzZUZsb2F0KG1bb3JkZXJpbmdbaV1dKSAhPT0gdG9JbnQobVtvcmRlcmluZ1tpXV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHVuaXRIYXNEZWNpbWFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkJDEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1ZhbGlkO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUludmFsaWQkMSgpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKE5hTik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gRHVyYXRpb24gKGR1cmF0aW9uKSB7XG4gICAgICAgIHZhciBub3JtYWxpemVkSW5wdXQgPSBub3JtYWxpemVPYmplY3RVbml0cyhkdXJhdGlvbiksXG4gICAgICAgICAgICB5ZWFycyA9IG5vcm1hbGl6ZWRJbnB1dC55ZWFyIHx8IDAsXG4gICAgICAgICAgICBxdWFydGVycyA9IG5vcm1hbGl6ZWRJbnB1dC5xdWFydGVyIHx8IDAsXG4gICAgICAgICAgICBtb250aHMgPSBub3JtYWxpemVkSW5wdXQubW9udGggfHwgMCxcbiAgICAgICAgICAgIHdlZWtzID0gbm9ybWFsaXplZElucHV0LndlZWsgfHwgbm9ybWFsaXplZElucHV0Lmlzb1dlZWsgfHwgMCxcbiAgICAgICAgICAgIGRheXMgPSBub3JtYWxpemVkSW5wdXQuZGF5IHx8IDAsXG4gICAgICAgICAgICBob3VycyA9IG5vcm1hbGl6ZWRJbnB1dC5ob3VyIHx8IDAsXG4gICAgICAgICAgICBtaW51dGVzID0gbm9ybWFsaXplZElucHV0Lm1pbnV0ZSB8fCAwLFxuICAgICAgICAgICAgc2Vjb25kcyA9IG5vcm1hbGl6ZWRJbnB1dC5zZWNvbmQgfHwgMCxcbiAgICAgICAgICAgIG1pbGxpc2Vjb25kcyA9IG5vcm1hbGl6ZWRJbnB1dC5taWxsaXNlY29uZCB8fCAwO1xuXG4gICAgICAgIHRoaXMuX2lzVmFsaWQgPSBpc0R1cmF0aW9uVmFsaWQobm9ybWFsaXplZElucHV0KTtcblxuICAgICAgICAvLyByZXByZXNlbnRhdGlvbiBmb3IgZGF0ZUFkZFJlbW92ZVxuICAgICAgICB0aGlzLl9taWxsaXNlY29uZHMgPSArbWlsbGlzZWNvbmRzICtcbiAgICAgICAgICAgIHNlY29uZHMgKiAxZTMgKyAvLyAxMDAwXG4gICAgICAgICAgICBtaW51dGVzICogNmU0ICsgLy8gMTAwMCAqIDYwXG4gICAgICAgICAgICBob3VycyAqIDEwMDAgKiA2MCAqIDYwOyAvL3VzaW5nIDEwMDAgKiA2MCAqIDYwIGluc3RlYWQgb2YgMzZlNSB0byBhdm9pZCBmbG9hdGluZyBwb2ludCByb3VuZGluZyBlcnJvcnMgaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzI5NzhcbiAgICAgICAgLy8gQmVjYXVzZSBvZiBkYXRlQWRkUmVtb3ZlIHRyZWF0cyAyNCBob3VycyBhcyBkaWZmZXJlbnQgZnJvbSBhXG4gICAgICAgIC8vIGRheSB3aGVuIHdvcmtpbmcgYXJvdW5kIERTVCwgd2UgbmVlZCB0byBzdG9yZSB0aGVtIHNlcGFyYXRlbHlcbiAgICAgICAgdGhpcy5fZGF5cyA9ICtkYXlzICtcbiAgICAgICAgICAgIHdlZWtzICogNztcbiAgICAgICAgLy8gSXQgaXMgaW1wb3NzaWJsZSB0byB0cmFuc2xhdGUgbW9udGhzIGludG8gZGF5cyB3aXRob3V0IGtub3dpbmdcbiAgICAgICAgLy8gd2hpY2ggbW9udGhzIHlvdSBhcmUgYXJlIHRhbGtpbmcgYWJvdXQsIHNvIHdlIGhhdmUgdG8gc3RvcmVcbiAgICAgICAgLy8gaXQgc2VwYXJhdGVseS5cbiAgICAgICAgdGhpcy5fbW9udGhzID0gK21vbnRocyArXG4gICAgICAgICAgICBxdWFydGVycyAqIDMgK1xuICAgICAgICAgICAgeWVhcnMgKiAxMjtcblxuICAgICAgICB0aGlzLl9kYXRhID0ge307XG5cbiAgICAgICAgdGhpcy5fbG9jYWxlID0gZ2V0TG9jYWxlKCk7XG5cbiAgICAgICAgdGhpcy5fYnViYmxlKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNEdXJhdGlvbiAob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogaW5zdGFuY2VvZiBEdXJhdGlvbjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhYnNSb3VuZCAobnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5yb3VuZCgtMSAqIG51bWJlcikgKiAtMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLnJvdW5kKG51bWJlcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBmdW5jdGlvbiBvZmZzZXQgKHRva2VuLCBzZXBhcmF0b3IpIHtcbiAgICAgICAgYWRkRm9ybWF0VG9rZW4odG9rZW4sIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSB0aGlzLnV0Y09mZnNldCgpO1xuICAgICAgICAgICAgdmFyIHNpZ24gPSAnKyc7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCkge1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IC1vZmZzZXQ7XG4gICAgICAgICAgICAgICAgc2lnbiA9ICctJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzaWduICsgemVyb0ZpbGwofn4ob2Zmc2V0IC8gNjApLCAyKSArIHNlcGFyYXRvciArIHplcm9GaWxsKH5+KG9mZnNldCkgJSA2MCwgMik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG9mZnNldCgnWicsICc6Jyk7XG4gICAgb2Zmc2V0KCdaWicsICcnKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ1onLCAgbWF0Y2hTaG9ydE9mZnNldCk7XG4gICAgYWRkUmVnZXhUb2tlbignWlonLCBtYXRjaFNob3J0T2Zmc2V0KTtcbiAgICBhZGRQYXJzZVRva2VuKFsnWicsICdaWiddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgY29uZmlnLl91c2VVVEMgPSB0cnVlO1xuICAgICAgICBjb25maWcuX3R6bSA9IG9mZnNldEZyb21TdHJpbmcobWF0Y2hTaG9ydE9mZnNldCwgaW5wdXQpO1xuICAgIH0pO1xuXG4gICAgLy8gSEVMUEVSU1xuXG4gICAgLy8gdGltZXpvbmUgY2h1bmtlclxuICAgIC8vICcrMTA6MDAnID4gWycxMCcsICAnMDAnXVxuICAgIC8vICctMTUzMCcgID4gWyctMTUnLCAnMzAnXVxuICAgIHZhciBjaHVua09mZnNldCA9IC8oW1xcK1xcLV18XFxkXFxkKS9naTtcblxuICAgIGZ1bmN0aW9uIG9mZnNldEZyb21TdHJpbmcobWF0Y2hlciwgc3RyaW5nKSB7XG4gICAgICAgIHZhciBtYXRjaGVzID0gKHN0cmluZyB8fCAnJykubWF0Y2gobWF0Y2hlcik7XG5cbiAgICAgICAgaWYgKG1hdGNoZXMgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNodW5rICAgPSBtYXRjaGVzW21hdGNoZXMubGVuZ3RoIC0gMV0gfHwgW107XG4gICAgICAgIHZhciBwYXJ0cyAgID0gKGNodW5rICsgJycpLm1hdGNoKGNodW5rT2Zmc2V0KSB8fCBbJy0nLCAwLCAwXTtcbiAgICAgICAgdmFyIG1pbnV0ZXMgPSArKHBhcnRzWzFdICogNjApICsgdG9JbnQocGFydHNbMl0pO1xuXG4gICAgICAgIHJldHVybiBtaW51dGVzID09PSAwID9cbiAgICAgICAgICAwIDpcbiAgICAgICAgICBwYXJ0c1swXSA9PT0gJysnID8gbWludXRlcyA6IC1taW51dGVzO1xuICAgIH1cblxuICAgIC8vIFJldHVybiBhIG1vbWVudCBmcm9tIGlucHV0LCB0aGF0IGlzIGxvY2FsL3V0Yy96b25lIGVxdWl2YWxlbnQgdG8gbW9kZWwuXG4gICAgZnVuY3Rpb24gY2xvbmVXaXRoT2Zmc2V0KGlucHV0LCBtb2RlbCkge1xuICAgICAgICB2YXIgcmVzLCBkaWZmO1xuICAgICAgICBpZiAobW9kZWwuX2lzVVRDKSB7XG4gICAgICAgICAgICByZXMgPSBtb2RlbC5jbG9uZSgpO1xuICAgICAgICAgICAgZGlmZiA9IChpc01vbWVudChpbnB1dCkgfHwgaXNEYXRlKGlucHV0KSA/IGlucHV0LnZhbHVlT2YoKSA6IGNyZWF0ZUxvY2FsKGlucHV0KS52YWx1ZU9mKCkpIC0gcmVzLnZhbHVlT2YoKTtcbiAgICAgICAgICAgIC8vIFVzZSBsb3ctbGV2ZWwgYXBpLCBiZWNhdXNlIHRoaXMgZm4gaXMgbG93LWxldmVsIGFwaS5cbiAgICAgICAgICAgIHJlcy5fZC5zZXRUaW1lKHJlcy5fZC52YWx1ZU9mKCkgKyBkaWZmKTtcbiAgICAgICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldChyZXMsIGZhbHNlKTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlTG9jYWwoaW5wdXQpLmxvY2FsKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXREYXRlT2Zmc2V0IChtKSB7XG4gICAgICAgIC8vIE9uIEZpcmVmb3guMjQgRGF0ZSNnZXRUaW1lem9uZU9mZnNldCByZXR1cm5zIGEgZmxvYXRpbmcgcG9pbnQuXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L3B1bGwvMTg3MVxuICAgICAgICByZXR1cm4gLU1hdGgucm91bmQobS5fZC5nZXRUaW1lem9uZU9mZnNldCgpIC8gMTUpICogMTU7XG4gICAgfVxuXG4gICAgLy8gSE9PS1NcblxuICAgIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgd2hlbmV2ZXIgYSBtb21lbnQgaXMgbXV0YXRlZC5cbiAgICAvLyBJdCBpcyBpbnRlbmRlZCB0byBrZWVwIHRoZSBvZmZzZXQgaW4gc3luYyB3aXRoIHRoZSB0aW1lem9uZS5cbiAgICBob29rcy51cGRhdGVPZmZzZXQgPSBmdW5jdGlvbiAoKSB7fTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIC8vIGtlZXBMb2NhbFRpbWUgPSB0cnVlIG1lYW5zIG9ubHkgY2hhbmdlIHRoZSB0aW1lem9uZSwgd2l0aG91dFxuICAgIC8vIGFmZmVjdGluZyB0aGUgbG9jYWwgaG91ci4gU28gNTozMToyNiArMDMwMCAtLVt1dGNPZmZzZXQoMiwgdHJ1ZSldLS0+XG4gICAgLy8gNTozMToyNiArMDIwMCBJdCBpcyBwb3NzaWJsZSB0aGF0IDU6MzE6MjYgZG9lc24ndCBleGlzdCB3aXRoIG9mZnNldFxuICAgIC8vICswMjAwLCBzbyB3ZSBhZGp1c3QgdGhlIHRpbWUgYXMgbmVlZGVkLCB0byBiZSB2YWxpZC5cbiAgICAvL1xuICAgIC8vIEtlZXBpbmcgdGhlIHRpbWUgYWN0dWFsbHkgYWRkcy9zdWJ0cmFjdHMgKG9uZSBob3VyKVxuICAgIC8vIGZyb20gdGhlIGFjdHVhbCByZXByZXNlbnRlZCB0aW1lLiBUaGF0IGlzIHdoeSB3ZSBjYWxsIHVwZGF0ZU9mZnNldFxuICAgIC8vIGEgc2Vjb25kIHRpbWUuIEluIGNhc2UgaXQgd2FudHMgdXMgdG8gY2hhbmdlIHRoZSBvZmZzZXQgYWdhaW5cbiAgICAvLyBfY2hhbmdlSW5Qcm9ncmVzcyA9PSB0cnVlIGNhc2UsIHRoZW4gd2UgaGF2ZSB0byBhZGp1c3QsIGJlY2F1c2VcbiAgICAvLyB0aGVyZSBpcyBubyBzdWNoIHRpbWUgaW4gdGhlIGdpdmVuIHRpbWV6b25lLlxuICAgIGZ1bmN0aW9uIGdldFNldE9mZnNldCAoaW5wdXQsIGtlZXBMb2NhbFRpbWUsIGtlZXBNaW51dGVzKSB7XG4gICAgICAgIHZhciBvZmZzZXQgPSB0aGlzLl9vZmZzZXQgfHwgMCxcbiAgICAgICAgICAgIGxvY2FsQWRqdXN0O1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQgIT0gbnVsbCA/IHRoaXMgOiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaW5wdXQgPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoU2hvcnRPZmZzZXQsIGlucHV0KTtcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChNYXRoLmFicyhpbnB1dCkgPCAxNiAmJiAha2VlcE1pbnV0ZXMpIHtcbiAgICAgICAgICAgICAgICBpbnB1dCA9IGlucHV0ICogNjA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzVVRDICYmIGtlZXBMb2NhbFRpbWUpIHtcbiAgICAgICAgICAgICAgICBsb2NhbEFkanVzdCA9IGdldERhdGVPZmZzZXQodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vZmZzZXQgPSBpbnB1dDtcbiAgICAgICAgICAgIHRoaXMuX2lzVVRDID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChsb2NhbEFkanVzdCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGQobG9jYWxBZGp1c3QsICdtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2Zmc2V0ICE9PSBpbnB1dCkge1xuICAgICAgICAgICAgICAgIGlmICgha2VlcExvY2FsVGltZSB8fCB0aGlzLl9jaGFuZ2VJblByb2dyZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZFN1YnRyYWN0KHRoaXMsIGNyZWF0ZUR1cmF0aW9uKGlucHV0IC0gb2Zmc2V0LCAnbScpLCAxLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5fY2hhbmdlSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jaGFuZ2VJblByb2dyZXNzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KHRoaXMsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jaGFuZ2VJblByb2dyZXNzID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc1VUQyA/IG9mZnNldCA6IGdldERhdGVPZmZzZXQodGhpcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTZXRab25lIChpbnB1dCwga2VlcExvY2FsVGltZSkge1xuICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpbnB1dCA9IC1pbnB1dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQoaW5wdXQsIGtlZXBMb2NhbFRpbWUpO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAtdGhpcy51dGNPZmZzZXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldE9mZnNldFRvVVRDIChrZWVwTG9jYWxUaW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnV0Y09mZnNldCgwLCBrZWVwTG9jYWxUaW1lKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRPZmZzZXRUb0xvY2FsIChrZWVwTG9jYWxUaW1lKSB7XG4gICAgICAgIGlmICh0aGlzLl9pc1VUQykge1xuICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQoMCwga2VlcExvY2FsVGltZSk7XG4gICAgICAgICAgICB0aGlzLl9pc1VUQyA9IGZhbHNlO1xuXG4gICAgICAgICAgICBpZiAoa2VlcExvY2FsVGltZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3VidHJhY3QoZ2V0RGF0ZU9mZnNldCh0aGlzKSwgJ20nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRPZmZzZXRUb1BhcnNlZE9mZnNldCAoKSB7XG4gICAgICAgIGlmICh0aGlzLl90em0gIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQodGhpcy5fdHptLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMuX2kgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB2YXIgdFpvbmUgPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoT2Zmc2V0LCB0aGlzLl9pKTtcbiAgICAgICAgICAgIGlmICh0Wm9uZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQodFpvbmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQoMCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGFzQWxpZ25lZEhvdXJPZmZzZXQgKGlucHV0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpbnB1dCA9IGlucHV0ID8gY3JlYXRlTG9jYWwoaW5wdXQpLnV0Y09mZnNldCgpIDogMDtcblxuICAgICAgICByZXR1cm4gKHRoaXMudXRjT2Zmc2V0KCkgLSBpbnB1dCkgJSA2MCA9PT0gMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0RheWxpZ2h0U2F2aW5nVGltZSAoKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLnV0Y09mZnNldCgpID4gdGhpcy5jbG9uZSgpLm1vbnRoKDApLnV0Y09mZnNldCgpIHx8XG4gICAgICAgICAgICB0aGlzLnV0Y09mZnNldCgpID4gdGhpcy5jbG9uZSgpLm1vbnRoKDUpLnV0Y09mZnNldCgpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNEYXlsaWdodFNhdmluZ1RpbWVTaGlmdGVkICgpIHtcbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZCh0aGlzLl9pc0RTVFNoaWZ0ZWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNEU1RTaGlmdGVkO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGMgPSB7fTtcblxuICAgICAgICBjb3B5Q29uZmlnKGMsIHRoaXMpO1xuICAgICAgICBjID0gcHJlcGFyZUNvbmZpZyhjKTtcblxuICAgICAgICBpZiAoYy5fYSkge1xuICAgICAgICAgICAgdmFyIG90aGVyID0gYy5faXNVVEMgPyBjcmVhdGVVVEMoYy5fYSkgOiBjcmVhdGVMb2NhbChjLl9hKTtcbiAgICAgICAgICAgIHRoaXMuX2lzRFNUU2hpZnRlZCA9IHRoaXMuaXNWYWxpZCgpICYmXG4gICAgICAgICAgICAgICAgY29tcGFyZUFycmF5cyhjLl9hLCBvdGhlci50b0FycmF5KCkpID4gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2lzRFNUU2hpZnRlZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzRFNUU2hpZnRlZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0xvY2FsICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gIXRoaXMuX2lzVVRDIDogZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNVdGNPZmZzZXQgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyB0aGlzLl9pc1VUQyA6IGZhbHNlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzVXRjICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gdGhpcy5faXNVVEMgJiYgdGhpcy5fb2Zmc2V0ID09PSAwIDogZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gQVNQLk5FVCBqc29uIGRhdGUgZm9ybWF0IHJlZ2V4XG4gICAgdmFyIGFzcE5ldFJlZ2V4ID0gL14oXFwtfFxcKyk/KD86KFxcZCopWy4gXSk/KFxcZCspXFw6KFxcZCspKD86XFw6KFxcZCspKFxcLlxcZCopPyk/JC87XG5cbiAgICAvLyBmcm9tIGh0dHA6Ly9kb2NzLmNsb3N1cmUtbGlicmFyeS5nb29nbGVjb2RlLmNvbS9naXQvY2xvc3VyZV9nb29nX2RhdGVfZGF0ZS5qcy5zb3VyY2UuaHRtbFxuICAgIC8vIHNvbWV3aGF0IG1vcmUgaW4gbGluZSB3aXRoIDQuNC4zLjIgMjAwNCBzcGVjLCBidXQgYWxsb3dzIGRlY2ltYWwgYW55d2hlcmVcbiAgICAvLyBhbmQgZnVydGhlciBtb2RpZmllZCB0byBhbGxvdyBmb3Igc3RyaW5ncyBjb250YWluaW5nIGJvdGggd2VlayBhbmQgZGF5XG4gICAgdmFyIGlzb1JlZ2V4ID0gL14oLXxcXCspP1AoPzooWy0rXT9bMC05LC5dKilZKT8oPzooWy0rXT9bMC05LC5dKilNKT8oPzooWy0rXT9bMC05LC5dKilXKT8oPzooWy0rXT9bMC05LC5dKilEKT8oPzpUKD86KFstK10/WzAtOSwuXSopSCk/KD86KFstK10/WzAtOSwuXSopTSk/KD86KFstK10/WzAtOSwuXSopUyk/KT8kLztcblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUR1cmF0aW9uIChpbnB1dCwga2V5KSB7XG4gICAgICAgIHZhciBkdXJhdGlvbiA9IGlucHV0LFxuICAgICAgICAgICAgLy8gbWF0Y2hpbmcgYWdhaW5zdCByZWdleHAgaXMgZXhwZW5zaXZlLCBkbyBpdCBvbiBkZW1hbmRcbiAgICAgICAgICAgIG1hdGNoID0gbnVsbCxcbiAgICAgICAgICAgIHNpZ24sXG4gICAgICAgICAgICByZXQsXG4gICAgICAgICAgICBkaWZmUmVzO1xuXG4gICAgICAgIGlmIChpc0R1cmF0aW9uKGlucHV0KSkge1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgbXMgOiBpbnB1dC5fbWlsbGlzZWNvbmRzLFxuICAgICAgICAgICAgICAgIGQgIDogaW5wdXQuX2RheXMsXG4gICAgICAgICAgICAgICAgTSAgOiBpbnB1dC5fbW9udGhzXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2UgaWYgKGlzTnVtYmVyKGlucHV0KSkge1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7fTtcbiAgICAgICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbltrZXldID0gaW5wdXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uLm1pbGxpc2Vjb25kcyA9IGlucHV0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCEhKG1hdGNoID0gYXNwTmV0UmVnZXguZXhlYyhpbnB1dCkpKSB7XG4gICAgICAgICAgICBzaWduID0gKG1hdGNoWzFdID09PSAnLScpID8gLTEgOiAxO1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgeSAgOiAwLFxuICAgICAgICAgICAgICAgIGQgIDogdG9JbnQobWF0Y2hbREFURV0pICAgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgICAgICBoICA6IHRvSW50KG1hdGNoW0hPVVJdKSAgICAgICAgICAgICAgICAgICAgICAgICAqIHNpZ24sXG4gICAgICAgICAgICAgICAgbSAgOiB0b0ludChtYXRjaFtNSU5VVEVdKSAgICAgICAgICAgICAgICAgICAgICAgKiBzaWduLFxuICAgICAgICAgICAgICAgIHMgIDogdG9JbnQobWF0Y2hbU0VDT05EXSkgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgICAgICBtcyA6IHRvSW50KGFic1JvdW5kKG1hdGNoW01JTExJU0VDT05EXSAqIDEwMDApKSAqIHNpZ24gLy8gdGhlIG1pbGxpc2Vjb25kIGRlY2ltYWwgcG9pbnQgaXMgaW5jbHVkZWQgaW4gdGhlIG1hdGNoXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2UgaWYgKCEhKG1hdGNoID0gaXNvUmVnZXguZXhlYyhpbnB1dCkpKSB7XG4gICAgICAgICAgICBzaWduID0gKG1hdGNoWzFdID09PSAnLScpID8gLTEgOiAxO1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgeSA6IHBhcnNlSXNvKG1hdGNoWzJdLCBzaWduKSxcbiAgICAgICAgICAgICAgICBNIDogcGFyc2VJc28obWF0Y2hbM10sIHNpZ24pLFxuICAgICAgICAgICAgICAgIHcgOiBwYXJzZUlzbyhtYXRjaFs0XSwgc2lnbiksXG4gICAgICAgICAgICAgICAgZCA6IHBhcnNlSXNvKG1hdGNoWzVdLCBzaWduKSxcbiAgICAgICAgICAgICAgICBoIDogcGFyc2VJc28obWF0Y2hbNl0sIHNpZ24pLFxuICAgICAgICAgICAgICAgIG0gOiBwYXJzZUlzbyhtYXRjaFs3XSwgc2lnbiksXG4gICAgICAgICAgICAgICAgcyA6IHBhcnNlSXNvKG1hdGNoWzhdLCBzaWduKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmIChkdXJhdGlvbiA9PSBudWxsKSB7Ly8gY2hlY2tzIGZvciBudWxsIG9yIHVuZGVmaW5lZFxuICAgICAgICAgICAgZHVyYXRpb24gPSB7fTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZHVyYXRpb24gPT09ICdvYmplY3QnICYmICgnZnJvbScgaW4gZHVyYXRpb24gfHwgJ3RvJyBpbiBkdXJhdGlvbikpIHtcbiAgICAgICAgICAgIGRpZmZSZXMgPSBtb21lbnRzRGlmZmVyZW5jZShjcmVhdGVMb2NhbChkdXJhdGlvbi5mcm9tKSwgY3JlYXRlTG9jYWwoZHVyYXRpb24udG8pKTtcblxuICAgICAgICAgICAgZHVyYXRpb24gPSB7fTtcbiAgICAgICAgICAgIGR1cmF0aW9uLm1zID0gZGlmZlJlcy5taWxsaXNlY29uZHM7XG4gICAgICAgICAgICBkdXJhdGlvbi5NID0gZGlmZlJlcy5tb250aHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXQgPSBuZXcgRHVyYXRpb24oZHVyYXRpb24pO1xuXG4gICAgICAgIGlmIChpc0R1cmF0aW9uKGlucHV0KSAmJiBoYXNPd25Qcm9wKGlucHV0LCAnX2xvY2FsZScpKSB7XG4gICAgICAgICAgICByZXQuX2xvY2FsZSA9IGlucHV0Ll9sb2NhbGU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGNyZWF0ZUR1cmF0aW9uLmZuID0gRHVyYXRpb24ucHJvdG90eXBlO1xuICAgIGNyZWF0ZUR1cmF0aW9uLmludmFsaWQgPSBjcmVhdGVJbnZhbGlkJDE7XG5cbiAgICBmdW5jdGlvbiBwYXJzZUlzbyAoaW5wLCBzaWduKSB7XG4gICAgICAgIC8vIFdlJ2Qgbm9ybWFsbHkgdXNlIH5+aW5wIGZvciB0aGlzLCBidXQgdW5mb3J0dW5hdGVseSBpdCBhbHNvXG4gICAgICAgIC8vIGNvbnZlcnRzIGZsb2F0cyB0byBpbnRzLlxuICAgICAgICAvLyBpbnAgbWF5IGJlIHVuZGVmaW5lZCwgc28gY2FyZWZ1bCBjYWxsaW5nIHJlcGxhY2Ugb24gaXQuXG4gICAgICAgIHZhciByZXMgPSBpbnAgJiYgcGFyc2VGbG9hdChpbnAucmVwbGFjZSgnLCcsICcuJykpO1xuICAgICAgICAvLyBhcHBseSBzaWduIHdoaWxlIHdlJ3JlIGF0IGl0XG4gICAgICAgIHJldHVybiAoaXNOYU4ocmVzKSA/IDAgOiByZXMpICogc2lnbjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwb3NpdGl2ZU1vbWVudHNEaWZmZXJlbmNlKGJhc2UsIG90aGVyKSB7XG4gICAgICAgIHZhciByZXMgPSB7fTtcblxuICAgICAgICByZXMubW9udGhzID0gb3RoZXIubW9udGgoKSAtIGJhc2UubW9udGgoKSArXG4gICAgICAgICAgICAob3RoZXIueWVhcigpIC0gYmFzZS55ZWFyKCkpICogMTI7XG4gICAgICAgIGlmIChiYXNlLmNsb25lKCkuYWRkKHJlcy5tb250aHMsICdNJykuaXNBZnRlcihvdGhlcikpIHtcbiAgICAgICAgICAgIC0tcmVzLm1vbnRocztcbiAgICAgICAgfVxuXG4gICAgICAgIHJlcy5taWxsaXNlY29uZHMgPSArb3RoZXIgLSArKGJhc2UuY2xvbmUoKS5hZGQocmVzLm1vbnRocywgJ00nKSk7XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb21lbnRzRGlmZmVyZW5jZShiYXNlLCBvdGhlcikge1xuICAgICAgICB2YXIgcmVzO1xuICAgICAgICBpZiAoIShiYXNlLmlzVmFsaWQoKSAmJiBvdGhlci5pc1ZhbGlkKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4ge21pbGxpc2Vjb25kczogMCwgbW9udGhzOiAwfTtcbiAgICAgICAgfVxuXG4gICAgICAgIG90aGVyID0gY2xvbmVXaXRoT2Zmc2V0KG90aGVyLCBiYXNlKTtcbiAgICAgICAgaWYgKGJhc2UuaXNCZWZvcmUob3RoZXIpKSB7XG4gICAgICAgICAgICByZXMgPSBwb3NpdGl2ZU1vbWVudHNEaWZmZXJlbmNlKGJhc2UsIG90aGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcyA9IHBvc2l0aXZlTW9tZW50c0RpZmZlcmVuY2Uob3RoZXIsIGJhc2UpO1xuICAgICAgICAgICAgcmVzLm1pbGxpc2Vjb25kcyA9IC1yZXMubWlsbGlzZWNvbmRzO1xuICAgICAgICAgICAgcmVzLm1vbnRocyA9IC1yZXMubW9udGhzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvLyBUT0RPOiByZW1vdmUgJ25hbWUnIGFyZyBhZnRlciBkZXByZWNhdGlvbiBpcyByZW1vdmVkXG4gICAgZnVuY3Rpb24gY3JlYXRlQWRkZXIoZGlyZWN0aW9uLCBuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAodmFsLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHZhciBkdXIsIHRtcDtcbiAgICAgICAgICAgIC8vaW52ZXJ0IHRoZSBhcmd1bWVudHMsIGJ1dCBjb21wbGFpbiBhYm91dCBpdFxuICAgICAgICAgICAgaWYgKHBlcmlvZCAhPT0gbnVsbCAmJiAhaXNOYU4oK3BlcmlvZCkpIHtcbiAgICAgICAgICAgICAgICBkZXByZWNhdGVTaW1wbGUobmFtZSwgJ21vbWVudCgpLicgKyBuYW1lICArICcocGVyaW9kLCBudW1iZXIpIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgbW9tZW50KCkuJyArIG5hbWUgKyAnKG51bWJlciwgcGVyaW9kKS4gJyArXG4gICAgICAgICAgICAgICAgJ1NlZSBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL2FkZC1pbnZlcnRlZC1wYXJhbS8gZm9yIG1vcmUgaW5mby4nKTtcbiAgICAgICAgICAgICAgICB0bXAgPSB2YWw7IHZhbCA9IHBlcmlvZDsgcGVyaW9kID0gdG1wO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YWwgPSB0eXBlb2YgdmFsID09PSAnc3RyaW5nJyA/ICt2YWwgOiB2YWw7XG4gICAgICAgICAgICBkdXIgPSBjcmVhdGVEdXJhdGlvbih2YWwsIHBlcmlvZCk7XG4gICAgICAgICAgICBhZGRTdWJ0cmFjdCh0aGlzLCBkdXIsIGRpcmVjdGlvbik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhZGRTdWJ0cmFjdCAobW9tLCBkdXJhdGlvbiwgaXNBZGRpbmcsIHVwZGF0ZU9mZnNldCkge1xuICAgICAgICB2YXIgbWlsbGlzZWNvbmRzID0gZHVyYXRpb24uX21pbGxpc2Vjb25kcyxcbiAgICAgICAgICAgIGRheXMgPSBhYnNSb3VuZChkdXJhdGlvbi5fZGF5cyksXG4gICAgICAgICAgICBtb250aHMgPSBhYnNSb3VuZChkdXJhdGlvbi5fbW9udGhzKTtcblxuICAgICAgICBpZiAoIW1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIC8vIE5vIG9wXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB1cGRhdGVPZmZzZXQgPSB1cGRhdGVPZmZzZXQgPT0gbnVsbCA/IHRydWUgOiB1cGRhdGVPZmZzZXQ7XG5cbiAgICAgICAgaWYgKG1vbnRocykge1xuICAgICAgICAgICAgc2V0TW9udGgobW9tLCBnZXQobW9tLCAnTW9udGgnKSArIG1vbnRocyAqIGlzQWRkaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF5cykge1xuICAgICAgICAgICAgc2V0JDEobW9tLCAnRGF0ZScsIGdldChtb20sICdEYXRlJykgKyBkYXlzICogaXNBZGRpbmcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtaWxsaXNlY29uZHMpIHtcbiAgICAgICAgICAgIG1vbS5fZC5zZXRUaW1lKG1vbS5fZC52YWx1ZU9mKCkgKyBtaWxsaXNlY29uZHMgKiBpc0FkZGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVwZGF0ZU9mZnNldCkge1xuICAgICAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KG1vbSwgZGF5cyB8fCBtb250aHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGFkZCAgICAgID0gY3JlYXRlQWRkZXIoMSwgJ2FkZCcpO1xuICAgIHZhciBzdWJ0cmFjdCA9IGNyZWF0ZUFkZGVyKC0xLCAnc3VidHJhY3QnKTtcblxuICAgIGZ1bmN0aW9uIGdldENhbGVuZGFyRm9ybWF0KG15TW9tZW50LCBub3cpIHtcbiAgICAgICAgdmFyIGRpZmYgPSBteU1vbWVudC5kaWZmKG5vdywgJ2RheXMnLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIGRpZmYgPCAtNiA/ICdzYW1lRWxzZScgOlxuICAgICAgICAgICAgICAgIGRpZmYgPCAtMSA/ICdsYXN0V2VlaycgOlxuICAgICAgICAgICAgICAgIGRpZmYgPCAwID8gJ2xhc3REYXknIDpcbiAgICAgICAgICAgICAgICBkaWZmIDwgMSA/ICdzYW1lRGF5JyA6XG4gICAgICAgICAgICAgICAgZGlmZiA8IDIgPyAnbmV4dERheScgOlxuICAgICAgICAgICAgICAgIGRpZmYgPCA3ID8gJ25leHRXZWVrJyA6ICdzYW1lRWxzZSc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2FsZW5kYXIkMSAodGltZSwgZm9ybWF0cykge1xuICAgICAgICAvLyBXZSB3YW50IHRvIGNvbXBhcmUgdGhlIHN0YXJ0IG9mIHRvZGF5LCB2cyB0aGlzLlxuICAgICAgICAvLyBHZXR0aW5nIHN0YXJ0LW9mLXRvZGF5IGRlcGVuZHMgb24gd2hldGhlciB3ZSdyZSBsb2NhbC91dGMvb2Zmc2V0IG9yIG5vdC5cbiAgICAgICAgdmFyIG5vdyA9IHRpbWUgfHwgY3JlYXRlTG9jYWwoKSxcbiAgICAgICAgICAgIHNvZCA9IGNsb25lV2l0aE9mZnNldChub3csIHRoaXMpLnN0YXJ0T2YoJ2RheScpLFxuICAgICAgICAgICAgZm9ybWF0ID0gaG9va3MuY2FsZW5kYXJGb3JtYXQodGhpcywgc29kKSB8fCAnc2FtZUVsc2UnO1xuXG4gICAgICAgIHZhciBvdXRwdXQgPSBmb3JtYXRzICYmIChpc0Z1bmN0aW9uKGZvcm1hdHNbZm9ybWF0XSkgPyBmb3JtYXRzW2Zvcm1hdF0uY2FsbCh0aGlzLCBub3cpIDogZm9ybWF0c1tmb3JtYXRdKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXQob3V0cHV0IHx8IHRoaXMubG9jYWxlRGF0YSgpLmNhbGVuZGFyKGZvcm1hdCwgdGhpcywgY3JlYXRlTG9jYWwobm93KSkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNsb25lICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNb21lbnQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNBZnRlciAoaW5wdXQsIHVuaXRzKSB7XG4gICAgICAgIHZhciBsb2NhbElucHV0ID0gaXNNb21lbnQoaW5wdXQpID8gaW5wdXQgOiBjcmVhdGVMb2NhbChpbnB1dCk7XG4gICAgICAgIGlmICghKHRoaXMuaXNWYWxpZCgpICYmIGxvY2FsSW5wdXQuaXNWYWxpZCgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpIHx8ICdtaWxsaXNlY29uZCc7XG4gICAgICAgIGlmICh1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVPZigpID4gbG9jYWxJbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxJbnB1dC52YWx1ZU9mKCkgPCB0aGlzLmNsb25lKCkuc3RhcnRPZih1bml0cykudmFsdWVPZigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNCZWZvcmUgKGlucHV0LCB1bml0cykge1xuICAgICAgICB2YXIgbG9jYWxJbnB1dCA9IGlzTW9tZW50KGlucHV0KSA/IGlucHV0IDogY3JlYXRlTG9jYWwoaW5wdXQpO1xuICAgICAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbElucHV0LmlzVmFsaWQoKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKSB8fCAnbWlsbGlzZWNvbmQnO1xuICAgICAgICBpZiAodW5pdHMgPT09ICdtaWxsaXNlY29uZCcpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlT2YoKSA8IGxvY2FsSW5wdXQudmFsdWVPZigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5lbmRPZih1bml0cykudmFsdWVPZigpIDwgbG9jYWxJbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0JldHdlZW4gKGZyb20sIHRvLCB1bml0cywgaW5jbHVzaXZpdHkpIHtcbiAgICAgICAgdmFyIGxvY2FsRnJvbSA9IGlzTW9tZW50KGZyb20pID8gZnJvbSA6IGNyZWF0ZUxvY2FsKGZyb20pLFxuICAgICAgICAgICAgbG9jYWxUbyA9IGlzTW9tZW50KHRvKSA/IHRvIDogY3JlYXRlTG9jYWwodG8pO1xuICAgICAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbEZyb20uaXNWYWxpZCgpICYmIGxvY2FsVG8uaXNWYWxpZCgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGluY2x1c2l2aXR5ID0gaW5jbHVzaXZpdHkgfHwgJygpJztcbiAgICAgICAgcmV0dXJuIChpbmNsdXNpdml0eVswXSA9PT0gJygnID8gdGhpcy5pc0FmdGVyKGxvY2FsRnJvbSwgdW5pdHMpIDogIXRoaXMuaXNCZWZvcmUobG9jYWxGcm9tLCB1bml0cykpICYmXG4gICAgICAgICAgICAoaW5jbHVzaXZpdHlbMV0gPT09ICcpJyA/IHRoaXMuaXNCZWZvcmUobG9jYWxUbywgdW5pdHMpIDogIXRoaXMuaXNBZnRlcihsb2NhbFRvLCB1bml0cykpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzU2FtZSAoaW5wdXQsIHVuaXRzKSB7XG4gICAgICAgIHZhciBsb2NhbElucHV0ID0gaXNNb21lbnQoaW5wdXQpID8gaW5wdXQgOiBjcmVhdGVMb2NhbChpbnB1dCksXG4gICAgICAgICAgICBpbnB1dE1zO1xuICAgICAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbElucHV0LmlzVmFsaWQoKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKSB8fCAnbWlsbGlzZWNvbmQnO1xuICAgICAgICBpZiAodW5pdHMgPT09ICdtaWxsaXNlY29uZCcpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlT2YoKSA9PT0gbG9jYWxJbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbnB1dE1zID0gbG9jYWxJbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpLnN0YXJ0T2YodW5pdHMpLnZhbHVlT2YoKSA8PSBpbnB1dE1zICYmIGlucHV0TXMgPD0gdGhpcy5jbG9uZSgpLmVuZE9mKHVuaXRzKS52YWx1ZU9mKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1NhbWVPckFmdGVyIChpbnB1dCwgdW5pdHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNTYW1lKGlucHV0LCB1bml0cykgfHwgdGhpcy5pc0FmdGVyKGlucHV0LCB1bml0cyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNTYW1lT3JCZWZvcmUgKGlucHV0LCB1bml0cykge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1NhbWUoaW5wdXQsIHVuaXRzKSB8fCB0aGlzLmlzQmVmb3JlKGlucHV0LCB1bml0cyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGlmZiAoaW5wdXQsIHVuaXRzLCBhc0Zsb2F0KSB7XG4gICAgICAgIHZhciB0aGF0LFxuICAgICAgICAgICAgem9uZURlbHRhLFxuICAgICAgICAgICAgb3V0cHV0O1xuXG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cblxuICAgICAgICB0aGF0ID0gY2xvbmVXaXRoT2Zmc2V0KGlucHV0LCB0aGlzKTtcblxuICAgICAgICBpZiAoIXRoYXQuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG5cbiAgICAgICAgem9uZURlbHRhID0gKHRoYXQudXRjT2Zmc2V0KCkgLSB0aGlzLnV0Y09mZnNldCgpKSAqIDZlNDtcblxuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcblxuICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgICAgICBjYXNlICd5ZWFyJzogb3V0cHV0ID0gbW9udGhEaWZmKHRoaXMsIHRoYXQpIC8gMTI7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbW9udGgnOiBvdXRwdXQgPSBtb250aERpZmYodGhpcywgdGhhdCk7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncXVhcnRlcic6IG91dHB1dCA9IG1vbnRoRGlmZih0aGlzLCB0aGF0KSAvIDM7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2Vjb25kJzogb3V0cHV0ID0gKHRoaXMgLSB0aGF0KSAvIDFlMzsgYnJlYWs7IC8vIDEwMDBcbiAgICAgICAgICAgIGNhc2UgJ21pbnV0ZSc6IG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyA2ZTQ7IGJyZWFrOyAvLyAxMDAwICogNjBcbiAgICAgICAgICAgIGNhc2UgJ2hvdXInOiBvdXRwdXQgPSAodGhpcyAtIHRoYXQpIC8gMzZlNTsgYnJlYWs7IC8vIDEwMDAgKiA2MCAqIDYwXG4gICAgICAgICAgICBjYXNlICdkYXknOiBvdXRwdXQgPSAodGhpcyAtIHRoYXQgLSB6b25lRGVsdGEpIC8gODY0ZTU7IGJyZWFrOyAvLyAxMDAwICogNjAgKiA2MCAqIDI0LCBuZWdhdGUgZHN0XG4gICAgICAgICAgICBjYXNlICd3ZWVrJzogb3V0cHV0ID0gKHRoaXMgLSB0aGF0IC0gem9uZURlbHRhKSAvIDYwNDhlNTsgYnJlYWs7IC8vIDEwMDAgKiA2MCAqIDYwICogMjQgKiA3LCBuZWdhdGUgZHN0XG4gICAgICAgICAgICBkZWZhdWx0OiBvdXRwdXQgPSB0aGlzIC0gdGhhdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhc0Zsb2F0ID8gb3V0cHV0IDogYWJzRmxvb3Iob3V0cHV0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb250aERpZmYgKGEsIGIpIHtcbiAgICAgICAgLy8gZGlmZmVyZW5jZSBpbiBtb250aHNcbiAgICAgICAgdmFyIHdob2xlTW9udGhEaWZmID0gKChiLnllYXIoKSAtIGEueWVhcigpKSAqIDEyKSArIChiLm1vbnRoKCkgLSBhLm1vbnRoKCkpLFxuICAgICAgICAgICAgLy8gYiBpcyBpbiAoYW5jaG9yIC0gMSBtb250aCwgYW5jaG9yICsgMSBtb250aClcbiAgICAgICAgICAgIGFuY2hvciA9IGEuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYsICdtb250aHMnKSxcbiAgICAgICAgICAgIGFuY2hvcjIsIGFkanVzdDtcblxuICAgICAgICBpZiAoYiAtIGFuY2hvciA8IDApIHtcbiAgICAgICAgICAgIGFuY2hvcjIgPSBhLmNsb25lKCkuYWRkKHdob2xlTW9udGhEaWZmIC0gMSwgJ21vbnRocycpO1xuICAgICAgICAgICAgLy8gbGluZWFyIGFjcm9zcyB0aGUgbW9udGhcbiAgICAgICAgICAgIGFkanVzdCA9IChiIC0gYW5jaG9yKSAvIChhbmNob3IgLSBhbmNob3IyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFuY2hvcjIgPSBhLmNsb25lKCkuYWRkKHdob2xlTW9udGhEaWZmICsgMSwgJ21vbnRocycpO1xuICAgICAgICAgICAgLy8gbGluZWFyIGFjcm9zcyB0aGUgbW9udGhcbiAgICAgICAgICAgIGFkanVzdCA9IChiIC0gYW5jaG9yKSAvIChhbmNob3IyIC0gYW5jaG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vY2hlY2sgZm9yIG5lZ2F0aXZlIHplcm8sIHJldHVybiB6ZXJvIGlmIG5lZ2F0aXZlIHplcm9cbiAgICAgICAgcmV0dXJuIC0od2hvbGVNb250aERpZmYgKyBhZGp1c3QpIHx8IDA7XG4gICAgfVxuXG4gICAgaG9va3MuZGVmYXVsdEZvcm1hdCA9ICdZWVlZLU1NLUREVEhIOm1tOnNzWic7XG4gICAgaG9va3MuZGVmYXVsdEZvcm1hdFV0YyA9ICdZWVlZLU1NLUREVEhIOm1tOnNzW1pdJztcblxuICAgIGZ1bmN0aW9uIHRvU3RyaW5nICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5sb2NhbGUoJ2VuJykuZm9ybWF0KCdkZGQgTU1NIEREIFlZWVkgSEg6bW06c3MgW0dNVF1aWicpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvSVNPU3RyaW5nKGtlZXBPZmZzZXQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHV0YyA9IGtlZXBPZmZzZXQgIT09IHRydWU7XG4gICAgICAgIHZhciBtID0gdXRjID8gdGhpcy5jbG9uZSgpLnV0YygpIDogdGhpcztcbiAgICAgICAgaWYgKG0ueWVhcigpIDwgMCB8fCBtLnllYXIoKSA+IDk5OTkpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXRNb21lbnQobSwgdXRjID8gJ1lZWVlZWS1NTS1ERFtUXUhIOm1tOnNzLlNTU1taXScgOiAnWVlZWVlZLU1NLUREW1RdSEg6bW06c3MuU1NTWicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0Z1bmN0aW9uKERhdGUucHJvdG90eXBlLnRvSVNPU3RyaW5nKSkge1xuICAgICAgICAgICAgLy8gbmF0aXZlIGltcGxlbWVudGF0aW9uIGlzIH41MHggZmFzdGVyLCB1c2UgaXQgd2hlbiB3ZSBjYW5cbiAgICAgICAgICAgIGlmICh1dGMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50b0RhdGUoKS50b0lTT1N0cmluZygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERhdGUodGhpcy52YWx1ZU9mKCkgKyB0aGlzLnV0Y09mZnNldCgpICogNjAgKiAxMDAwKS50b0lTT1N0cmluZygpLnJlcGxhY2UoJ1onLCBmb3JtYXRNb21lbnQobSwgJ1onKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZvcm1hdE1vbWVudChtLCB1dGMgPyAnWVlZWS1NTS1ERFtUXUhIOm1tOnNzLlNTU1taXScgOiAnWVlZWS1NTS1ERFtUXUhIOm1tOnNzLlNTU1onKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBodW1hbiByZWFkYWJsZSByZXByZXNlbnRhdGlvbiBvZiBhIG1vbWVudCB0aGF0IGNhblxuICAgICAqIGFsc28gYmUgZXZhbHVhdGVkIHRvIGdldCBhIG5ldyBtb21lbnQgd2hpY2ggaXMgdGhlIHNhbWVcbiAgICAgKlxuICAgICAqIEBsaW5rIGh0dHBzOi8vbm9kZWpzLm9yZy9kaXN0L2xhdGVzdC9kb2NzL2FwaS91dGlsLmh0bWwjdXRpbF9jdXN0b21faW5zcGVjdF9mdW5jdGlvbl9vbl9vYmplY3RzXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5zcGVjdCAoKSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiAnbW9tZW50LmludmFsaWQoLyogJyArIHRoaXMuX2kgKyAnICovKSc7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZ1bmMgPSAnbW9tZW50JztcbiAgICAgICAgdmFyIHpvbmUgPSAnJztcbiAgICAgICAgaWYgKCF0aGlzLmlzTG9jYWwoKSkge1xuICAgICAgICAgICAgZnVuYyA9IHRoaXMudXRjT2Zmc2V0KCkgPT09IDAgPyAnbW9tZW50LnV0YycgOiAnbW9tZW50LnBhcnNlWm9uZSc7XG4gICAgICAgICAgICB6b25lID0gJ1onO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwcmVmaXggPSAnWycgKyBmdW5jICsgJyhcIl0nO1xuICAgICAgICB2YXIgeWVhciA9ICgwIDw9IHRoaXMueWVhcigpICYmIHRoaXMueWVhcigpIDw9IDk5OTkpID8gJ1lZWVknIDogJ1lZWVlZWSc7XG4gICAgICAgIHZhciBkYXRldGltZSA9ICctTU0tRERbVF1ISDptbTpzcy5TU1MnO1xuICAgICAgICB2YXIgc3VmZml4ID0gem9uZSArICdbXCIpXSc7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0KHByZWZpeCArIHllYXIgKyBkYXRldGltZSArIHN1ZmZpeCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0IChpbnB1dFN0cmluZykge1xuICAgICAgICBpZiAoIWlucHV0U3RyaW5nKSB7XG4gICAgICAgICAgICBpbnB1dFN0cmluZyA9IHRoaXMuaXNVdGMoKSA/IGhvb2tzLmRlZmF1bHRGb3JtYXRVdGMgOiBob29rcy5kZWZhdWx0Rm9ybWF0O1xuICAgICAgICB9XG4gICAgICAgIHZhciBvdXRwdXQgPSBmb3JtYXRNb21lbnQodGhpcywgaW5wdXRTdHJpbmcpO1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkucG9zdGZvcm1hdChvdXRwdXQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZyb20gKHRpbWUsIHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNWYWxpZCgpICYmXG4gICAgICAgICAgICAgICAgKChpc01vbWVudCh0aW1lKSAmJiB0aW1lLmlzVmFsaWQoKSkgfHxcbiAgICAgICAgICAgICAgICAgY3JlYXRlTG9jYWwodGltZSkuaXNWYWxpZCgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHt0bzogdGhpcywgZnJvbTogdGltZX0pLmxvY2FsZSh0aGlzLmxvY2FsZSgpKS5odW1hbml6ZSghd2l0aG91dFN1ZmZpeCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkuaW52YWxpZERhdGUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZyb21Ob3cgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnJvbShjcmVhdGVMb2NhbCgpLCB3aXRob3V0U3VmZml4KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0byAodGltZSwgd2l0aG91dFN1ZmZpeCkge1xuICAgICAgICBpZiAodGhpcy5pc1ZhbGlkKCkgJiZcbiAgICAgICAgICAgICAgICAoKGlzTW9tZW50KHRpbWUpICYmIHRpbWUuaXNWYWxpZCgpKSB8fFxuICAgICAgICAgICAgICAgICBjcmVhdGVMb2NhbCh0aW1lKS5pc1ZhbGlkKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oe2Zyb206IHRoaXMsIHRvOiB0aW1lfSkubG9jYWxlKHRoaXMubG9jYWxlKCkpLmh1bWFuaXplKCF3aXRob3V0U3VmZml4KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5pbnZhbGlkRGF0ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdG9Ob3cgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudG8oY3JlYXRlTG9jYWwoKSwgd2l0aG91dFN1ZmZpeCk7XG4gICAgfVxuXG4gICAgLy8gSWYgcGFzc2VkIGEgbG9jYWxlIGtleSwgaXQgd2lsbCBzZXQgdGhlIGxvY2FsZSBmb3IgdGhpc1xuICAgIC8vIGluc3RhbmNlLiAgT3RoZXJ3aXNlLCBpdCB3aWxsIHJldHVybiB0aGUgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbiAgICAvLyB2YXJpYWJsZXMgZm9yIHRoaXMgaW5zdGFuY2UuXG4gICAgZnVuY3Rpb24gbG9jYWxlIChrZXkpIHtcbiAgICAgICAgdmFyIG5ld0xvY2FsZURhdGE7XG5cbiAgICAgICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbG9jYWxlLl9hYmJyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3TG9jYWxlRGF0YSA9IGdldExvY2FsZShrZXkpO1xuICAgICAgICAgICAgaWYgKG5ld0xvY2FsZURhdGEgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2xvY2FsZSA9IG5ld0xvY2FsZURhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsYW5nID0gZGVwcmVjYXRlKFxuICAgICAgICAnbW9tZW50KCkubGFuZygpIGlzIGRlcHJlY2F0ZWQuIEluc3RlYWQsIHVzZSBtb21lbnQoKS5sb2NhbGVEYXRhKCkgdG8gZ2V0IHRoZSBsYW5ndWFnZSBjb25maWd1cmF0aW9uLiBVc2UgbW9tZW50KCkubG9jYWxlKCkgdG8gY2hhbmdlIGxhbmd1YWdlcy4nLFxuICAgICAgICBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICBpZiAoa2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgKTtcblxuICAgIGZ1bmN0aW9uIGxvY2FsZURhdGEgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbG9jYWxlO1xuICAgIH1cblxuICAgIHZhciBNU19QRVJfU0VDT05EID0gMTAwMDtcbiAgICB2YXIgTVNfUEVSX01JTlVURSA9IDYwICogTVNfUEVSX1NFQ09ORDtcbiAgICB2YXIgTVNfUEVSX0hPVVIgPSA2MCAqIE1TX1BFUl9NSU5VVEU7XG4gICAgdmFyIE1TX1BFUl80MDBfWUVBUlMgPSAoMzY1ICogNDAwICsgOTcpICogMjQgKiBNU19QRVJfSE9VUjtcblxuICAgIC8vIGFjdHVhbCBtb2R1bG8gLSBoYW5kbGVzIG5lZ2F0aXZlIG51bWJlcnMgKGZvciBkYXRlcyBiZWZvcmUgMTk3MCk6XG4gICAgZnVuY3Rpb24gbW9kJDEoZGl2aWRlbmQsIGRpdmlzb3IpIHtcbiAgICAgICAgcmV0dXJuIChkaXZpZGVuZCAlIGRpdmlzb3IgKyBkaXZpc29yKSAlIGRpdmlzb3I7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9jYWxTdGFydE9mRGF0ZSh5LCBtLCBkKSB7XG4gICAgICAgIC8vIHRoZSBkYXRlIGNvbnN0cnVjdG9yIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgICAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDApIHtcbiAgICAgICAgICAgIC8vIHByZXNlcnZlIGxlYXAgeWVhcnMgdXNpbmcgYSBmdWxsIDQwMCB5ZWFyIGN5Y2xlLCB0aGVuIHJlc2V0XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUoeSArIDQwMCwgbSwgZCkgLSBNU19QRVJfNDAwX1lFQVJTO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHksIG0sIGQpLnZhbHVlT2YoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHV0Y1N0YXJ0T2ZEYXRlKHksIG0sIGQpIHtcbiAgICAgICAgLy8gRGF0ZS5VVEMgcmVtYXBzIHllYXJzIDAtOTkgdG8gMTkwMC0xOTk5XG4gICAgICAgIGlmICh5IDwgMTAwICYmIHkgPj0gMCkge1xuICAgICAgICAgICAgLy8gcHJlc2VydmUgbGVhcCB5ZWFycyB1c2luZyBhIGZ1bGwgNDAwIHllYXIgY3ljbGUsIHRoZW4gcmVzZXRcbiAgICAgICAgICAgIHJldHVybiBEYXRlLlVUQyh5ICsgNDAwLCBtLCBkKSAtIE1TX1BFUl80MDBfWUVBUlM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gRGF0ZS5VVEMoeSwgbSwgZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdGFydE9mICh1bml0cykge1xuICAgICAgICB2YXIgdGltZTtcbiAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG4gICAgICAgIGlmICh1bml0cyA9PT0gdW5kZWZpbmVkIHx8IHVuaXRzID09PSAnbWlsbGlzZWNvbmQnIHx8ICF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc3RhcnRPZkRhdGUgPSB0aGlzLl9pc1VUQyA/IHV0Y1N0YXJ0T2ZEYXRlIDogbG9jYWxTdGFydE9mRGF0ZTtcblxuICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgICAgICBjYXNlICd5ZWFyJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIDAsIDEpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncXVhcnRlcic6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpLCB0aGlzLm1vbnRoKCkgLSB0aGlzLm1vbnRoKCkgJSAzLCAxKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSwgMSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd3ZWVrJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSwgdGhpcy5kYXRlKCkgLSB0aGlzLndlZWtkYXkoKSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdpc29XZWVrJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSwgdGhpcy5kYXRlKCkgLSAodGhpcy5pc29XZWVrZGF5KCkgLSAxKSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkYXknOlxuICAgICAgICAgICAgY2FzZSAnZGF0ZSc6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpLCB0aGlzLm1vbnRoKCksIHRoaXMuZGF0ZSgpKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2hvdXInOlxuICAgICAgICAgICAgICAgIHRpbWUgPSB0aGlzLl9kLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICB0aW1lIC09IG1vZCQxKHRpbWUgKyAodGhpcy5faXNVVEMgPyAwIDogdGhpcy51dGNPZmZzZXQoKSAqIE1TX1BFUl9NSU5VVEUpLCBNU19QRVJfSE9VUik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtaW51dGUnOlxuICAgICAgICAgICAgICAgIHRpbWUgPSB0aGlzLl9kLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICB0aW1lIC09IG1vZCQxKHRpbWUsIE1TX1BFUl9NSU5VVEUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2Vjb25kJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gdGhpcy5fZC52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgdGltZSAtPSBtb2QkMSh0aW1lLCBNU19QRVJfU0VDT05EKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2Quc2V0VGltZSh0aW1lKTtcbiAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KHRoaXMsIHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbmRPZiAodW5pdHMpIHtcbiAgICAgICAgdmFyIHRpbWU7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICBpZiAodW5pdHMgPT09IHVuZGVmaW5lZCB8fCB1bml0cyA9PT0gJ21pbGxpc2Vjb25kJyB8fCAhdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0YXJ0T2ZEYXRlID0gdGhpcy5faXNVVEMgPyB1dGNTdGFydE9mRGF0ZSA6IGxvY2FsU3RhcnRPZkRhdGU7XG5cbiAgICAgICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICAgICAgY2FzZSAneWVhcic6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpICsgMSwgMCwgMSkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncXVhcnRlcic6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpLCB0aGlzLm1vbnRoKCkgLSB0aGlzLm1vbnRoKCkgJSAzICsgMywgMSkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbW9udGgnOlxuICAgICAgICAgICAgICAgIHRpbWUgPSBzdGFydE9mRGF0ZSh0aGlzLnllYXIoKSwgdGhpcy5tb250aCgpICsgMSwgMSkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnd2Vlayc6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpLCB0aGlzLm1vbnRoKCksIHRoaXMuZGF0ZSgpIC0gdGhpcy53ZWVrZGF5KCkgKyA3KSAtIDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdpc29XZWVrJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSwgdGhpcy5kYXRlKCkgLSAodGhpcy5pc29XZWVrZGF5KCkgLSAxKSArIDcpIC0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2RheSc6XG4gICAgICAgICAgICBjYXNlICdkYXRlJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSwgdGhpcy5kYXRlKCkgKyAxKSAtIDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdob3VyJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gdGhpcy5fZC52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgdGltZSArPSBNU19QRVJfSE9VUiAtIG1vZCQxKHRpbWUgKyAodGhpcy5faXNVVEMgPyAwIDogdGhpcy51dGNPZmZzZXQoKSAqIE1TX1BFUl9NSU5VVEUpLCBNU19QRVJfSE9VUikgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbWludXRlJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gdGhpcy5fZC52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgdGltZSArPSBNU19QRVJfTUlOVVRFIC0gbW9kJDEodGltZSwgTVNfUEVSX01JTlVURSkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2Vjb25kJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gdGhpcy5fZC52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgdGltZSArPSBNU19QRVJfU0VDT05EIC0gbW9kJDEodGltZSwgTVNfUEVSX1NFQ09ORCkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZC5zZXRUaW1lKHRpbWUpO1xuICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywgdHJ1ZSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZhbHVlT2YgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZC52YWx1ZU9mKCkgLSAoKHRoaXMuX29mZnNldCB8fCAwKSAqIDYwMDAwKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1bml4ICgpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IodGhpcy52YWx1ZU9mKCkgLyAxMDAwKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b0RhdGUgKCkge1xuICAgICAgICByZXR1cm4gbmV3IERhdGUodGhpcy52YWx1ZU9mKCkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvQXJyYXkgKCkge1xuICAgICAgICB2YXIgbSA9IHRoaXM7XG4gICAgICAgIHJldHVybiBbbS55ZWFyKCksIG0ubW9udGgoKSwgbS5kYXRlKCksIG0uaG91cigpLCBtLm1pbnV0ZSgpLCBtLnNlY29uZCgpLCBtLm1pbGxpc2Vjb25kKCldO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvT2JqZWN0ICgpIHtcbiAgICAgICAgdmFyIG0gPSB0aGlzO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeWVhcnM6IG0ueWVhcigpLFxuICAgICAgICAgICAgbW9udGhzOiBtLm1vbnRoKCksXG4gICAgICAgICAgICBkYXRlOiBtLmRhdGUoKSxcbiAgICAgICAgICAgIGhvdXJzOiBtLmhvdXJzKCksXG4gICAgICAgICAgICBtaW51dGVzOiBtLm1pbnV0ZXMoKSxcbiAgICAgICAgICAgIHNlY29uZHM6IG0uc2Vjb25kcygpLFxuICAgICAgICAgICAgbWlsbGlzZWNvbmRzOiBtLm1pbGxpc2Vjb25kcygpXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdG9KU09OICgpIHtcbiAgICAgICAgLy8gbmV3IERhdGUoTmFOKS50b0pTT04oKSA9PT0gbnVsbFxuICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyB0aGlzLnRvSVNPU3RyaW5nKCkgOiBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzVmFsaWQkMiAoKSB7XG4gICAgICAgIHJldHVybiBpc1ZhbGlkKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhcnNpbmdGbGFncyAoKSB7XG4gICAgICAgIHJldHVybiBleHRlbmQoe30sIGdldFBhcnNpbmdGbGFncyh0aGlzKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW52YWxpZEF0ICgpIHtcbiAgICAgICAgcmV0dXJuIGdldFBhcnNpbmdGbGFncyh0aGlzKS5vdmVyZmxvdztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGlvbkRhdGEoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpbnB1dDogdGhpcy5faSxcbiAgICAgICAgICAgIGZvcm1hdDogdGhpcy5fZixcbiAgICAgICAgICAgIGxvY2FsZTogdGhpcy5fbG9jYWxlLFxuICAgICAgICAgICAgaXNVVEM6IHRoaXMuX2lzVVRDLFxuICAgICAgICAgICAgc3RyaWN0OiB0aGlzLl9zdHJpY3RcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ2dnJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2Vla1llYXIoKSAlIDEwMDtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnR0cnLCAyXSwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc29XZWVrWWVhcigpICUgMTAwO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gYWRkV2Vla1llYXJGb3JtYXRUb2tlbiAodG9rZW4sIGdldHRlcikge1xuICAgICAgICBhZGRGb3JtYXRUb2tlbigwLCBbdG9rZW4sIHRva2VuLmxlbmd0aF0sIDAsIGdldHRlcik7XG4gICAgfVxuXG4gICAgYWRkV2Vla1llYXJGb3JtYXRUb2tlbignZ2dnZycsICAgICAnd2Vla1llYXInKTtcbiAgICBhZGRXZWVrWWVhckZvcm1hdFRva2VuKCdnZ2dnZycsICAgICd3ZWVrWWVhcicpO1xuICAgIGFkZFdlZWtZZWFyRm9ybWF0VG9rZW4oJ0dHR0cnLCAgJ2lzb1dlZWtZZWFyJyk7XG4gICAgYWRkV2Vla1llYXJGb3JtYXRUb2tlbignR0dHR0cnLCAnaXNvV2Vla1llYXInKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnd2Vla1llYXInLCAnZ2cnKTtcbiAgICBhZGRVbml0QWxpYXMoJ2lzb1dlZWtZZWFyJywgJ0dHJyk7XG5cbiAgICAvLyBQUklPUklUWVxuXG4gICAgYWRkVW5pdFByaW9yaXR5KCd3ZWVrWWVhcicsIDEpO1xuICAgIGFkZFVuaXRQcmlvcml0eSgnaXNvV2Vla1llYXInLCAxKTtcblxuXG4gICAgLy8gUEFSU0lOR1xuXG4gICAgYWRkUmVnZXhUb2tlbignRycsICAgICAgbWF0Y2hTaWduZWQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2cnLCAgICAgIG1hdGNoU2lnbmVkKTtcbiAgICBhZGRSZWdleFRva2VuKCdHRycsICAgICBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbignZ2cnLCAgICAgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0dHR0cnLCAgIG1hdGNoMXRvNCwgbWF0Y2g0KTtcbiAgICBhZGRSZWdleFRva2VuKCdnZ2dnJywgICBtYXRjaDF0bzQsIG1hdGNoNCk7XG4gICAgYWRkUmVnZXhUb2tlbignR0dHR0cnLCAgbWF0Y2gxdG82LCBtYXRjaDYpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2dnZ2dnJywgIG1hdGNoMXRvNiwgbWF0Y2g2KTtcblxuICAgIGFkZFdlZWtQYXJzZVRva2VuKFsnZ2dnZycsICdnZ2dnZycsICdHR0dHJywgJ0dHR0dHJ10sIGZ1bmN0aW9uIChpbnB1dCwgd2VlaywgY29uZmlnLCB0b2tlbikge1xuICAgICAgICB3ZWVrW3Rva2VuLnN1YnN0cigwLCAyKV0gPSB0b0ludChpbnB1dCk7XG4gICAgfSk7XG5cbiAgICBhZGRXZWVrUGFyc2VUb2tlbihbJ2dnJywgJ0dHJ10sIGZ1bmN0aW9uIChpbnB1dCwgd2VlaywgY29uZmlnLCB0b2tlbikge1xuICAgICAgICB3ZWVrW3Rva2VuXSA9IGhvb2tzLnBhcnNlVHdvRGlnaXRZZWFyKGlucHV0KTtcbiAgICB9KTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIGZ1bmN0aW9uIGdldFNldFdlZWtZZWFyIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gZ2V0U2V0V2Vla1llYXJIZWxwZXIuY2FsbCh0aGlzLFxuICAgICAgICAgICAgICAgIGlucHV0LFxuICAgICAgICAgICAgICAgIHRoaXMud2VlaygpLFxuICAgICAgICAgICAgICAgIHRoaXMud2Vla2RheSgpLFxuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxlRGF0YSgpLl93ZWVrLmRvdyxcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsZURhdGEoKS5fd2Vlay5kb3kpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFNldElTT1dlZWtZZWFyIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gZ2V0U2V0V2Vla1llYXJIZWxwZXIuY2FsbCh0aGlzLFxuICAgICAgICAgICAgICAgIGlucHV0LCB0aGlzLmlzb1dlZWsoKSwgdGhpcy5pc29XZWVrZGF5KCksIDEsIDQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldElTT1dlZWtzSW5ZZWFyICgpIHtcbiAgICAgICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMueWVhcigpLCAxLCA0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRXZWVrc0luWWVhciAoKSB7XG4gICAgICAgIHZhciB3ZWVrSW5mbyA9IHRoaXMubG9jYWxlRGF0YSgpLl93ZWVrO1xuICAgICAgICByZXR1cm4gd2Vla3NJblllYXIodGhpcy55ZWFyKCksIHdlZWtJbmZvLmRvdywgd2Vla0luZm8uZG95KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTZXRXZWVrWWVhckhlbHBlcihpbnB1dCwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpIHtcbiAgICAgICAgdmFyIHdlZWtzVGFyZ2V0O1xuICAgICAgICBpZiAoaW5wdXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHdlZWtPZlllYXIodGhpcywgZG93LCBkb3kpLnllYXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3ZWVrc1RhcmdldCA9IHdlZWtzSW5ZZWFyKGlucHV0LCBkb3csIGRveSk7XG4gICAgICAgICAgICBpZiAod2VlayA+IHdlZWtzVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgd2VlayA9IHdlZWtzVGFyZ2V0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNldFdlZWtBbGwuY2FsbCh0aGlzLCBpbnB1dCwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0V2Vla0FsbCh3ZWVrWWVhciwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpIHtcbiAgICAgICAgdmFyIGRheU9mWWVhckRhdGEgPSBkYXlPZlllYXJGcm9tV2Vla3Mod2Vla1llYXIsIHdlZWssIHdlZWtkYXksIGRvdywgZG95KSxcbiAgICAgICAgICAgIGRhdGUgPSBjcmVhdGVVVENEYXRlKGRheU9mWWVhckRhdGEueWVhciwgMCwgZGF5T2ZZZWFyRGF0YS5kYXlPZlllYXIpO1xuXG4gICAgICAgIHRoaXMueWVhcihkYXRlLmdldFVUQ0Z1bGxZZWFyKCkpO1xuICAgICAgICB0aGlzLm1vbnRoKGRhdGUuZ2V0VVRDTW9udGgoKSk7XG4gICAgICAgIHRoaXMuZGF0ZShkYXRlLmdldFVUQ0RhdGUoKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdRJywgMCwgJ1FvJywgJ3F1YXJ0ZXInKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygncXVhcnRlcicsICdRJyk7XG5cbiAgICAvLyBQUklPUklUWVxuXG4gICAgYWRkVW5pdFByaW9yaXR5KCdxdWFydGVyJywgNyk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdRJywgbWF0Y2gxKTtcbiAgICBhZGRQYXJzZVRva2VuKCdRJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICBhcnJheVtNT05USF0gPSAodG9JbnQoaW5wdXQpIC0gMSkgKiAzO1xuICAgIH0pO1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gZ2V0U2V0UXVhcnRlciAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyBNYXRoLmNlaWwoKHRoaXMubW9udGgoKSArIDEpIC8gMykgOiB0aGlzLm1vbnRoKChpbnB1dCAtIDEpICogMyArIHRoaXMubW9udGgoKSAlIDMpO1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdEJywgWydERCcsIDJdLCAnRG8nLCAnZGF0ZScpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCdkYXRlJywgJ0QnKTtcblxuICAgIC8vIFBSSU9SSVRZXG4gICAgYWRkVW5pdFByaW9yaXR5KCdkYXRlJywgOSk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdEJywgIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignREQnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbignRG8nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICAvLyBUT0RPOiBSZW1vdmUgXCJvcmRpbmFsUGFyc2VcIiBmYWxsYmFjayBpbiBuZXh0IG1ham9yIHJlbGVhc2UuXG4gICAgICAgIHJldHVybiBpc1N0cmljdCA/XG4gICAgICAgICAgKGxvY2FsZS5fZGF5T2ZNb250aE9yZGluYWxQYXJzZSB8fCBsb2NhbGUuX29yZGluYWxQYXJzZSkgOlxuICAgICAgICAgIGxvY2FsZS5fZGF5T2ZNb250aE9yZGluYWxQYXJzZUxlbmllbnQ7XG4gICAgfSk7XG5cbiAgICBhZGRQYXJzZVRva2VuKFsnRCcsICdERCddLCBEQVRFKTtcbiAgICBhZGRQYXJzZVRva2VuKCdEbycsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgYXJyYXlbREFURV0gPSB0b0ludChpbnB1dC5tYXRjaChtYXRjaDF0bzIpWzBdKTtcbiAgICB9KTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIHZhciBnZXRTZXREYXlPZk1vbnRoID0gbWFrZUdldFNldCgnRGF0ZScsIHRydWUpO1xuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ0RERCcsIFsnRERERCcsIDNdLCAnREREbycsICdkYXlPZlllYXInKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnZGF5T2ZZZWFyJywgJ0RERCcpO1xuXG4gICAgLy8gUFJJT1JJVFlcbiAgICBhZGRVbml0UHJpb3JpdHkoJ2RheU9mWWVhcicsIDQpO1xuXG4gICAgLy8gUEFSU0lOR1xuXG4gICAgYWRkUmVnZXhUb2tlbignREREJywgIG1hdGNoMXRvMyk7XG4gICAgYWRkUmVnZXhUb2tlbignRERERCcsIG1hdGNoMyk7XG4gICAgYWRkUGFyc2VUb2tlbihbJ0RERCcsICdEREREJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICBjb25maWcuX2RheU9mWWVhciA9IHRvSW50KGlucHV0KTtcbiAgICB9KTtcblxuICAgIC8vIEhFTFBFUlNcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIGZ1bmN0aW9uIGdldFNldERheU9mWWVhciAoaW5wdXQpIHtcbiAgICAgICAgdmFyIGRheU9mWWVhciA9IE1hdGgucm91bmQoKHRoaXMuY2xvbmUoKS5zdGFydE9mKCdkYXknKSAtIHRoaXMuY2xvbmUoKS5zdGFydE9mKCd5ZWFyJykpIC8gODY0ZTUpICsgMTtcbiAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyBkYXlPZlllYXIgOiB0aGlzLmFkZCgoaW5wdXQgLSBkYXlPZlllYXIpLCAnZCcpO1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdtJywgWydtbScsIDJdLCAwLCAnbWludXRlJyk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ21pbnV0ZScsICdtJyk7XG5cbiAgICAvLyBQUklPUklUWVxuXG4gICAgYWRkVW5pdFByaW9yaXR5KCdtaW51dGUnLCAxNCk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdtJywgIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignbW0nLCBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUGFyc2VUb2tlbihbJ20nLCAnbW0nXSwgTUlOVVRFKTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIHZhciBnZXRTZXRNaW51dGUgPSBtYWtlR2V0U2V0KCdNaW51dGVzJywgZmFsc2UpO1xuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ3MnLCBbJ3NzJywgMl0sIDAsICdzZWNvbmQnKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnc2Vjb25kJywgJ3MnKTtcblxuICAgIC8vIFBSSU9SSVRZXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ3NlY29uZCcsIDE1KTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ3MnLCAgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdzcycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbiAgICBhZGRQYXJzZVRva2VuKFsncycsICdzcyddLCBTRUNPTkQpO1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgdmFyIGdldFNldFNlY29uZCA9IG1ha2VHZXRTZXQoJ1NlY29uZHMnLCBmYWxzZSk7XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbignUycsIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIH5+KHRoaXMubWlsbGlzZWNvbmQoKSAvIDEwMCk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIH5+KHRoaXMubWlsbGlzZWNvbmQoKSAvIDEwKTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTJywgM10sIDAsICdtaWxsaXNlY29uZCcpO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTUycsIDRdLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDtcbiAgICB9KTtcbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTU1NTJywgNV0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWlsbGlzZWNvbmQoKSAqIDEwMDtcbiAgICB9KTtcbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTU1NTUycsIDZdLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDAwO1xuICAgIH0pO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTUycsIDddLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDAwMDtcbiAgICB9KTtcbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTU1NTU1NTJywgOF0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWlsbGlzZWNvbmQoKSAqIDEwMDAwMDtcbiAgICB9KTtcbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1NTU1NTU1NTUycsIDldLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDAwMDAwO1xuICAgIH0pO1xuXG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ21pbGxpc2Vjb25kJywgJ21zJyk7XG5cbiAgICAvLyBQUklPUklUWVxuXG4gICAgYWRkVW5pdFByaW9yaXR5KCdtaWxsaXNlY29uZCcsIDE2KTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ1MnLCAgICBtYXRjaDF0bzMsIG1hdGNoMSk7XG4gICAgYWRkUmVnZXhUb2tlbignU1MnLCAgIG1hdGNoMXRvMywgbWF0Y2gyKTtcbiAgICBhZGRSZWdleFRva2VuKCdTU1MnLCAgbWF0Y2gxdG8zLCBtYXRjaDMpO1xuXG4gICAgdmFyIHRva2VuO1xuICAgIGZvciAodG9rZW4gPSAnU1NTUyc7IHRva2VuLmxlbmd0aCA8PSA5OyB0b2tlbiArPSAnUycpIHtcbiAgICAgICAgYWRkUmVnZXhUb2tlbih0b2tlbiwgbWF0Y2hVbnNpZ25lZCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VNcyhpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgYXJyYXlbTUlMTElTRUNPTkRdID0gdG9JbnQoKCcwLicgKyBpbnB1dCkgKiAxMDAwKTtcbiAgICB9XG5cbiAgICBmb3IgKHRva2VuID0gJ1MnOyB0b2tlbi5sZW5ndGggPD0gOTsgdG9rZW4gKz0gJ1MnKSB7XG4gICAgICAgIGFkZFBhcnNlVG9rZW4odG9rZW4sIHBhcnNlTXMpO1xuICAgIH1cbiAgICAvLyBNT01FTlRTXG5cbiAgICB2YXIgZ2V0U2V0TWlsbGlzZWNvbmQgPSBtYWtlR2V0U2V0KCdNaWxsaXNlY29uZHMnLCBmYWxzZSk7XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbigneicsICAwLCAwLCAnem9uZUFiYnInKTtcbiAgICBhZGRGb3JtYXRUb2tlbignenonLCAwLCAwLCAnem9uZU5hbWUnKTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIGZ1bmN0aW9uIGdldFpvbmVBYmJyICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzVVRDID8gJ1VUQycgOiAnJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRab25lTmFtZSAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1VUQyA/ICdDb29yZGluYXRlZCBVbml2ZXJzYWwgVGltZScgOiAnJztcbiAgICB9XG5cbiAgICB2YXIgcHJvdG8gPSBNb21lbnQucHJvdG90eXBlO1xuXG4gICAgcHJvdG8uYWRkICAgICAgICAgICAgICAgPSBhZGQ7XG4gICAgcHJvdG8uY2FsZW5kYXIgICAgICAgICAgPSBjYWxlbmRhciQxO1xuICAgIHByb3RvLmNsb25lICAgICAgICAgICAgID0gY2xvbmU7XG4gICAgcHJvdG8uZGlmZiAgICAgICAgICAgICAgPSBkaWZmO1xuICAgIHByb3RvLmVuZE9mICAgICAgICAgICAgID0gZW5kT2Y7XG4gICAgcHJvdG8uZm9ybWF0ICAgICAgICAgICAgPSBmb3JtYXQ7XG4gICAgcHJvdG8uZnJvbSAgICAgICAgICAgICAgPSBmcm9tO1xuICAgIHByb3RvLmZyb21Ob3cgICAgICAgICAgID0gZnJvbU5vdztcbiAgICBwcm90by50byAgICAgICAgICAgICAgICA9IHRvO1xuICAgIHByb3RvLnRvTm93ICAgICAgICAgICAgID0gdG9Ob3c7XG4gICAgcHJvdG8uZ2V0ICAgICAgICAgICAgICAgPSBzdHJpbmdHZXQ7XG4gICAgcHJvdG8uaW52YWxpZEF0ICAgICAgICAgPSBpbnZhbGlkQXQ7XG4gICAgcHJvdG8uaXNBZnRlciAgICAgICAgICAgPSBpc0FmdGVyO1xuICAgIHByb3RvLmlzQmVmb3JlICAgICAgICAgID0gaXNCZWZvcmU7XG4gICAgcHJvdG8uaXNCZXR3ZWVuICAgICAgICAgPSBpc0JldHdlZW47XG4gICAgcHJvdG8uaXNTYW1lICAgICAgICAgICAgPSBpc1NhbWU7XG4gICAgcHJvdG8uaXNTYW1lT3JBZnRlciAgICAgPSBpc1NhbWVPckFmdGVyO1xuICAgIHByb3RvLmlzU2FtZU9yQmVmb3JlICAgID0gaXNTYW1lT3JCZWZvcmU7XG4gICAgcHJvdG8uaXNWYWxpZCAgICAgICAgICAgPSBpc1ZhbGlkJDI7XG4gICAgcHJvdG8ubGFuZyAgICAgICAgICAgICAgPSBsYW5nO1xuICAgIHByb3RvLmxvY2FsZSAgICAgICAgICAgID0gbG9jYWxlO1xuICAgIHByb3RvLmxvY2FsZURhdGEgICAgICAgID0gbG9jYWxlRGF0YTtcbiAgICBwcm90by5tYXggICAgICAgICAgICAgICA9IHByb3RvdHlwZU1heDtcbiAgICBwcm90by5taW4gICAgICAgICAgICAgICA9IHByb3RvdHlwZU1pbjtcbiAgICBwcm90by5wYXJzaW5nRmxhZ3MgICAgICA9IHBhcnNpbmdGbGFncztcbiAgICBwcm90by5zZXQgICAgICAgICAgICAgICA9IHN0cmluZ1NldDtcbiAgICBwcm90by5zdGFydE9mICAgICAgICAgICA9IHN0YXJ0T2Y7XG4gICAgcHJvdG8uc3VidHJhY3QgICAgICAgICAgPSBzdWJ0cmFjdDtcbiAgICBwcm90by50b0FycmF5ICAgICAgICAgICA9IHRvQXJyYXk7XG4gICAgcHJvdG8udG9PYmplY3QgICAgICAgICAgPSB0b09iamVjdDtcbiAgICBwcm90by50b0RhdGUgICAgICAgICAgICA9IHRvRGF0ZTtcbiAgICBwcm90by50b0lTT1N0cmluZyAgICAgICA9IHRvSVNPU3RyaW5nO1xuICAgIHByb3RvLmluc3BlY3QgICAgICAgICAgID0gaW5zcGVjdDtcbiAgICBwcm90by50b0pTT04gICAgICAgICAgICA9IHRvSlNPTjtcbiAgICBwcm90by50b1N0cmluZyAgICAgICAgICA9IHRvU3RyaW5nO1xuICAgIHByb3RvLnVuaXggICAgICAgICAgICAgID0gdW5peDtcbiAgICBwcm90by52YWx1ZU9mICAgICAgICAgICA9IHZhbHVlT2Y7XG4gICAgcHJvdG8uY3JlYXRpb25EYXRhICAgICAgPSBjcmVhdGlvbkRhdGE7XG4gICAgcHJvdG8ueWVhciAgICAgICA9IGdldFNldFllYXI7XG4gICAgcHJvdG8uaXNMZWFwWWVhciA9IGdldElzTGVhcFllYXI7XG4gICAgcHJvdG8ud2Vla1llYXIgICAgPSBnZXRTZXRXZWVrWWVhcjtcbiAgICBwcm90by5pc29XZWVrWWVhciA9IGdldFNldElTT1dlZWtZZWFyO1xuICAgIHByb3RvLnF1YXJ0ZXIgPSBwcm90by5xdWFydGVycyA9IGdldFNldFF1YXJ0ZXI7XG4gICAgcHJvdG8ubW9udGggICAgICAgPSBnZXRTZXRNb250aDtcbiAgICBwcm90by5kYXlzSW5Nb250aCA9IGdldERheXNJbk1vbnRoO1xuICAgIHByb3RvLndlZWsgICAgICAgICAgID0gcHJvdG8ud2Vla3MgICAgICAgID0gZ2V0U2V0V2VlaztcbiAgICBwcm90by5pc29XZWVrICAgICAgICA9IHByb3RvLmlzb1dlZWtzICAgICA9IGdldFNldElTT1dlZWs7XG4gICAgcHJvdG8ud2Vla3NJblllYXIgICAgPSBnZXRXZWVrc0luWWVhcjtcbiAgICBwcm90by5pc29XZWVrc0luWWVhciA9IGdldElTT1dlZWtzSW5ZZWFyO1xuICAgIHByb3RvLmRhdGUgICAgICAgPSBnZXRTZXREYXlPZk1vbnRoO1xuICAgIHByb3RvLmRheSAgICAgICAgPSBwcm90by5kYXlzICAgICAgICAgICAgID0gZ2V0U2V0RGF5T2ZXZWVrO1xuICAgIHByb3RvLndlZWtkYXkgICAgPSBnZXRTZXRMb2NhbGVEYXlPZldlZWs7XG4gICAgcHJvdG8uaXNvV2Vla2RheSA9IGdldFNldElTT0RheU9mV2VlaztcbiAgICBwcm90by5kYXlPZlllYXIgID0gZ2V0U2V0RGF5T2ZZZWFyO1xuICAgIHByb3RvLmhvdXIgPSBwcm90by5ob3VycyA9IGdldFNldEhvdXI7XG4gICAgcHJvdG8ubWludXRlID0gcHJvdG8ubWludXRlcyA9IGdldFNldE1pbnV0ZTtcbiAgICBwcm90by5zZWNvbmQgPSBwcm90by5zZWNvbmRzID0gZ2V0U2V0U2Vjb25kO1xuICAgIHByb3RvLm1pbGxpc2Vjb25kID0gcHJvdG8ubWlsbGlzZWNvbmRzID0gZ2V0U2V0TWlsbGlzZWNvbmQ7XG4gICAgcHJvdG8udXRjT2Zmc2V0ICAgICAgICAgICAgPSBnZXRTZXRPZmZzZXQ7XG4gICAgcHJvdG8udXRjICAgICAgICAgICAgICAgICAgPSBzZXRPZmZzZXRUb1VUQztcbiAgICBwcm90by5sb2NhbCAgICAgICAgICAgICAgICA9IHNldE9mZnNldFRvTG9jYWw7XG4gICAgcHJvdG8ucGFyc2Vab25lICAgICAgICAgICAgPSBzZXRPZmZzZXRUb1BhcnNlZE9mZnNldDtcbiAgICBwcm90by5oYXNBbGlnbmVkSG91ck9mZnNldCA9IGhhc0FsaWduZWRIb3VyT2Zmc2V0O1xuICAgIHByb3RvLmlzRFNUICAgICAgICAgICAgICAgID0gaXNEYXlsaWdodFNhdmluZ1RpbWU7XG4gICAgcHJvdG8uaXNMb2NhbCAgICAgICAgICAgICAgPSBpc0xvY2FsO1xuICAgIHByb3RvLmlzVXRjT2Zmc2V0ICAgICAgICAgID0gaXNVdGNPZmZzZXQ7XG4gICAgcHJvdG8uaXNVdGMgICAgICAgICAgICAgICAgPSBpc1V0YztcbiAgICBwcm90by5pc1VUQyAgICAgICAgICAgICAgICA9IGlzVXRjO1xuICAgIHByb3RvLnpvbmVBYmJyID0gZ2V0Wm9uZUFiYnI7XG4gICAgcHJvdG8uem9uZU5hbWUgPSBnZXRab25lTmFtZTtcbiAgICBwcm90by5kYXRlcyAgPSBkZXByZWNhdGUoJ2RhdGVzIGFjY2Vzc29yIGlzIGRlcHJlY2F0ZWQuIFVzZSBkYXRlIGluc3RlYWQuJywgZ2V0U2V0RGF5T2ZNb250aCk7XG4gICAgcHJvdG8ubW9udGhzID0gZGVwcmVjYXRlKCdtb250aHMgYWNjZXNzb3IgaXMgZGVwcmVjYXRlZC4gVXNlIG1vbnRoIGluc3RlYWQnLCBnZXRTZXRNb250aCk7XG4gICAgcHJvdG8ueWVhcnMgID0gZGVwcmVjYXRlKCd5ZWFycyBhY2Nlc3NvciBpcyBkZXByZWNhdGVkLiBVc2UgeWVhciBpbnN0ZWFkJywgZ2V0U2V0WWVhcik7XG4gICAgcHJvdG8uem9uZSAgID0gZGVwcmVjYXRlKCdtb21lbnQoKS56b25lIGlzIGRlcHJlY2F0ZWQsIHVzZSBtb21lbnQoKS51dGNPZmZzZXQgaW5zdGVhZC4gaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy96b25lLycsIGdldFNldFpvbmUpO1xuICAgIHByb3RvLmlzRFNUU2hpZnRlZCA9IGRlcHJlY2F0ZSgnaXNEU1RTaGlmdGVkIGlzIGRlcHJlY2F0ZWQuIFNlZSBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL2RzdC1zaGlmdGVkLyBmb3IgbW9yZSBpbmZvcm1hdGlvbicsIGlzRGF5bGlnaHRTYXZpbmdUaW1lU2hpZnRlZCk7XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVVbml4IChpbnB1dCkge1xuICAgICAgICByZXR1cm4gY3JlYXRlTG9jYWwoaW5wdXQgKiAxMDAwKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVJblpvbmUgKCkge1xuICAgICAgICByZXR1cm4gY3JlYXRlTG9jYWwuYXBwbHkobnVsbCwgYXJndW1lbnRzKS5wYXJzZVpvbmUoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcmVQYXJzZVBvc3RGb3JtYXQgKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgIH1cblxuICAgIHZhciBwcm90byQxID0gTG9jYWxlLnByb3RvdHlwZTtcblxuICAgIHByb3RvJDEuY2FsZW5kYXIgICAgICAgID0gY2FsZW5kYXI7XG4gICAgcHJvdG8kMS5sb25nRGF0ZUZvcm1hdCAgPSBsb25nRGF0ZUZvcm1hdDtcbiAgICBwcm90byQxLmludmFsaWREYXRlICAgICA9IGludmFsaWREYXRlO1xuICAgIHByb3RvJDEub3JkaW5hbCAgICAgICAgID0gb3JkaW5hbDtcbiAgICBwcm90byQxLnByZXBhcnNlICAgICAgICA9IHByZVBhcnNlUG9zdEZvcm1hdDtcbiAgICBwcm90byQxLnBvc3Rmb3JtYXQgICAgICA9IHByZVBhcnNlUG9zdEZvcm1hdDtcbiAgICBwcm90byQxLnJlbGF0aXZlVGltZSAgICA9IHJlbGF0aXZlVGltZTtcbiAgICBwcm90byQxLnBhc3RGdXR1cmUgICAgICA9IHBhc3RGdXR1cmU7XG4gICAgcHJvdG8kMS5zZXQgICAgICAgICAgICAgPSBzZXQ7XG5cbiAgICBwcm90byQxLm1vbnRocyAgICAgICAgICAgID0gICAgICAgIGxvY2FsZU1vbnRocztcbiAgICBwcm90byQxLm1vbnRoc1Nob3J0ICAgICAgID0gICAgICAgIGxvY2FsZU1vbnRoc1Nob3J0O1xuICAgIHByb3RvJDEubW9udGhzUGFyc2UgICAgICAgPSAgICAgICAgbG9jYWxlTW9udGhzUGFyc2U7XG4gICAgcHJvdG8kMS5tb250aHNSZWdleCAgICAgICA9IG1vbnRoc1JlZ2V4O1xuICAgIHByb3RvJDEubW9udGhzU2hvcnRSZWdleCAgPSBtb250aHNTaG9ydFJlZ2V4O1xuICAgIHByb3RvJDEud2VlayA9IGxvY2FsZVdlZWs7XG4gICAgcHJvdG8kMS5maXJzdERheU9mWWVhciA9IGxvY2FsZUZpcnN0RGF5T2ZZZWFyO1xuICAgIHByb3RvJDEuZmlyc3REYXlPZldlZWsgPSBsb2NhbGVGaXJzdERheU9mV2VlaztcblxuICAgIHByb3RvJDEud2Vla2RheXMgICAgICAgPSAgICAgICAgbG9jYWxlV2Vla2RheXM7XG4gICAgcHJvdG8kMS53ZWVrZGF5c01pbiAgICA9ICAgICAgICBsb2NhbGVXZWVrZGF5c01pbjtcbiAgICBwcm90byQxLndlZWtkYXlzU2hvcnQgID0gICAgICAgIGxvY2FsZVdlZWtkYXlzU2hvcnQ7XG4gICAgcHJvdG8kMS53ZWVrZGF5c1BhcnNlICA9ICAgICAgICBsb2NhbGVXZWVrZGF5c1BhcnNlO1xuXG4gICAgcHJvdG8kMS53ZWVrZGF5c1JlZ2V4ICAgICAgID0gICAgICAgIHdlZWtkYXlzUmVnZXg7XG4gICAgcHJvdG8kMS53ZWVrZGF5c1Nob3J0UmVnZXggID0gICAgICAgIHdlZWtkYXlzU2hvcnRSZWdleDtcbiAgICBwcm90byQxLndlZWtkYXlzTWluUmVnZXggICAgPSAgICAgICAgd2Vla2RheXNNaW5SZWdleDtcblxuICAgIHByb3RvJDEuaXNQTSA9IGxvY2FsZUlzUE07XG4gICAgcHJvdG8kMS5tZXJpZGllbSA9IGxvY2FsZU1lcmlkaWVtO1xuXG4gICAgZnVuY3Rpb24gZ2V0JDEgKGZvcm1hdCwgaW5kZXgsIGZpZWxkLCBzZXR0ZXIpIHtcbiAgICAgICAgdmFyIGxvY2FsZSA9IGdldExvY2FsZSgpO1xuICAgICAgICB2YXIgdXRjID0gY3JlYXRlVVRDKCkuc2V0KHNldHRlciwgaW5kZXgpO1xuICAgICAgICByZXR1cm4gbG9jYWxlW2ZpZWxkXSh1dGMsIGZvcm1hdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdE1vbnRoc0ltcGwgKGZvcm1hdCwgaW5kZXgsIGZpZWxkKSB7XG4gICAgICAgIGlmIChpc051bWJlcihmb3JtYXQpKSB7XG4gICAgICAgICAgICBpbmRleCA9IGZvcm1hdDtcbiAgICAgICAgICAgIGZvcm1hdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdCB8fCAnJztcblxuICAgICAgICBpZiAoaW5kZXggIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGdldCQxKGZvcm1hdCwgaW5kZXgsIGZpZWxkLCAnbW9udGgnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgb3V0ID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgICAgICBvdXRbaV0gPSBnZXQkMShmb3JtYXQsIGksIGZpZWxkLCAnbW9udGgnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIC8vICgpXG4gICAgLy8gKDUpXG4gICAgLy8gKGZtdCwgNSlcbiAgICAvLyAoZm10KVxuICAgIC8vICh0cnVlKVxuICAgIC8vICh0cnVlLCA1KVxuICAgIC8vICh0cnVlLCBmbXQsIDUpXG4gICAgLy8gKHRydWUsIGZtdClcbiAgICBmdW5jdGlvbiBsaXN0V2Vla2RheXNJbXBsIChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgsIGZpZWxkKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbG9jYWxlU29ydGVkID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIGlmIChpc051bWJlcihmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBmb3JtYXQ7XG4gICAgICAgICAgICAgICAgZm9ybWF0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3JtYXQgPSBmb3JtYXQgfHwgJyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3JtYXQgPSBsb2NhbGVTb3J0ZWQ7XG4gICAgICAgICAgICBpbmRleCA9IGZvcm1hdDtcbiAgICAgICAgICAgIGxvY2FsZVNvcnRlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBpZiAoaXNOdW1iZXIoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gZm9ybWF0O1xuICAgICAgICAgICAgICAgIGZvcm1hdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9ybWF0ID0gZm9ybWF0IHx8ICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxvY2FsZSA9IGdldExvY2FsZSgpLFxuICAgICAgICAgICAgc2hpZnQgPSBsb2NhbGVTb3J0ZWQgPyBsb2NhbGUuX3dlZWsuZG93IDogMDtcblxuICAgICAgICBpZiAoaW5kZXggIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGdldCQxKGZvcm1hdCwgKGluZGV4ICsgc2hpZnQpICUgNywgZmllbGQsICdkYXknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgb3V0ID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgIG91dFtpXSA9IGdldCQxKGZvcm1hdCwgKGkgKyBzaGlmdCkgJSA3LCBmaWVsZCwgJ2RheScpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdE1vbnRocyAoZm9ybWF0LCBpbmRleCkge1xuICAgICAgICByZXR1cm4gbGlzdE1vbnRoc0ltcGwoZm9ybWF0LCBpbmRleCwgJ21vbnRocycpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpc3RNb250aHNTaG9ydCAoZm9ybWF0LCBpbmRleCkge1xuICAgICAgICByZXR1cm4gbGlzdE1vbnRoc0ltcGwoZm9ybWF0LCBpbmRleCwgJ21vbnRoc1Nob3J0Jyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdFdlZWtkYXlzIChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIGxpc3RXZWVrZGF5c0ltcGwobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4LCAnd2Vla2RheXMnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaXN0V2Vla2RheXNTaG9ydCAobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4KSB7XG4gICAgICAgIHJldHVybiBsaXN0V2Vla2RheXNJbXBsKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCwgJ3dlZWtkYXlzU2hvcnQnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaXN0V2Vla2RheXNNaW4gKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCkge1xuICAgICAgICByZXR1cm4gbGlzdFdlZWtkYXlzSW1wbChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgsICd3ZWVrZGF5c01pbicpO1xuICAgIH1cblxuICAgIGdldFNldEdsb2JhbExvY2FsZSgnZW4nLCB7XG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSh0aHxzdHxuZHxyZCkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAodG9JbnQobnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAxKSA/ICdzdCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gU2lkZSBlZmZlY3QgaW1wb3J0c1xuXG4gICAgaG9va3MubGFuZyA9IGRlcHJlY2F0ZSgnbW9tZW50LmxhbmcgaXMgZGVwcmVjYXRlZC4gVXNlIG1vbWVudC5sb2NhbGUgaW5zdGVhZC4nLCBnZXRTZXRHbG9iYWxMb2NhbGUpO1xuICAgIGhvb2tzLmxhbmdEYXRhID0gZGVwcmVjYXRlKCdtb21lbnQubGFuZ0RhdGEgaXMgZGVwcmVjYXRlZC4gVXNlIG1vbWVudC5sb2NhbGVEYXRhIGluc3RlYWQuJywgZ2V0TG9jYWxlKTtcblxuICAgIHZhciBtYXRoQWJzID0gTWF0aC5hYnM7XG5cbiAgICBmdW5jdGlvbiBhYnMgKCkge1xuICAgICAgICB2YXIgZGF0YSAgICAgICAgICAgPSB0aGlzLl9kYXRhO1xuXG4gICAgICAgIHRoaXMuX21pbGxpc2Vjb25kcyA9IG1hdGhBYnModGhpcy5fbWlsbGlzZWNvbmRzKTtcbiAgICAgICAgdGhpcy5fZGF5cyAgICAgICAgID0gbWF0aEFicyh0aGlzLl9kYXlzKTtcbiAgICAgICAgdGhpcy5fbW9udGhzICAgICAgID0gbWF0aEFicyh0aGlzLl9tb250aHMpO1xuXG4gICAgICAgIGRhdGEubWlsbGlzZWNvbmRzICA9IG1hdGhBYnMoZGF0YS5taWxsaXNlY29uZHMpO1xuICAgICAgICBkYXRhLnNlY29uZHMgICAgICAgPSBtYXRoQWJzKGRhdGEuc2Vjb25kcyk7XG4gICAgICAgIGRhdGEubWludXRlcyAgICAgICA9IG1hdGhBYnMoZGF0YS5taW51dGVzKTtcbiAgICAgICAgZGF0YS5ob3VycyAgICAgICAgID0gbWF0aEFicyhkYXRhLmhvdXJzKTtcbiAgICAgICAgZGF0YS5tb250aHMgICAgICAgID0gbWF0aEFicyhkYXRhLm1vbnRocyk7XG4gICAgICAgIGRhdGEueWVhcnMgICAgICAgICA9IG1hdGhBYnMoZGF0YS55ZWFycyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkU3VidHJhY3QkMSAoZHVyYXRpb24sIGlucHV0LCB2YWx1ZSwgZGlyZWN0aW9uKSB7XG4gICAgICAgIHZhciBvdGhlciA9IGNyZWF0ZUR1cmF0aW9uKGlucHV0LCB2YWx1ZSk7XG5cbiAgICAgICAgZHVyYXRpb24uX21pbGxpc2Vjb25kcyArPSBkaXJlY3Rpb24gKiBvdGhlci5fbWlsbGlzZWNvbmRzO1xuICAgICAgICBkdXJhdGlvbi5fZGF5cyAgICAgICAgICs9IGRpcmVjdGlvbiAqIG90aGVyLl9kYXlzO1xuICAgICAgICBkdXJhdGlvbi5fbW9udGhzICAgICAgICs9IGRpcmVjdGlvbiAqIG90aGVyLl9tb250aHM7XG5cbiAgICAgICAgcmV0dXJuIGR1cmF0aW9uLl9idWJibGUoKTtcbiAgICB9XG5cbiAgICAvLyBzdXBwb3J0cyBvbmx5IDIuMC1zdHlsZSBhZGQoMSwgJ3MnKSBvciBhZGQoZHVyYXRpb24pXG4gICAgZnVuY3Rpb24gYWRkJDEgKGlucHV0LCB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gYWRkU3VidHJhY3QkMSh0aGlzLCBpbnB1dCwgdmFsdWUsIDEpO1xuICAgIH1cblxuICAgIC8vIHN1cHBvcnRzIG9ubHkgMi4wLXN0eWxlIHN1YnRyYWN0KDEsICdzJykgb3Igc3VidHJhY3QoZHVyYXRpb24pXG4gICAgZnVuY3Rpb24gc3VidHJhY3QkMSAoaW5wdXQsIHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBhZGRTdWJ0cmFjdCQxKHRoaXMsIGlucHV0LCB2YWx1ZSwgLTEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFic0NlaWwgKG51bWJlcikge1xuICAgICAgICBpZiAobnVtYmVyIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IobnVtYmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmNlaWwobnVtYmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1YmJsZSAoKSB7XG4gICAgICAgIHZhciBtaWxsaXNlY29uZHMgPSB0aGlzLl9taWxsaXNlY29uZHM7XG4gICAgICAgIHZhciBkYXlzICAgICAgICAgPSB0aGlzLl9kYXlzO1xuICAgICAgICB2YXIgbW9udGhzICAgICAgID0gdGhpcy5fbW9udGhzO1xuICAgICAgICB2YXIgZGF0YSAgICAgICAgID0gdGhpcy5fZGF0YTtcbiAgICAgICAgdmFyIHNlY29uZHMsIG1pbnV0ZXMsIGhvdXJzLCB5ZWFycywgbW9udGhzRnJvbURheXM7XG5cbiAgICAgICAgLy8gaWYgd2UgaGF2ZSBhIG1peCBvZiBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWVzLCBidWJibGUgZG93biBmaXJzdFxuICAgICAgICAvLyBjaGVjazogaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzIxNjZcbiAgICAgICAgaWYgKCEoKG1pbGxpc2Vjb25kcyA+PSAwICYmIGRheXMgPj0gMCAmJiBtb250aHMgPj0gMCkgfHxcbiAgICAgICAgICAgICAgICAobWlsbGlzZWNvbmRzIDw9IDAgJiYgZGF5cyA8PSAwICYmIG1vbnRocyA8PSAwKSkpIHtcbiAgICAgICAgICAgIG1pbGxpc2Vjb25kcyArPSBhYnNDZWlsKG1vbnRoc1RvRGF5cyhtb250aHMpICsgZGF5cykgKiA4NjRlNTtcbiAgICAgICAgICAgIGRheXMgPSAwO1xuICAgICAgICAgICAgbW9udGhzID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoZSBmb2xsb3dpbmcgY29kZSBidWJibGVzIHVwIHZhbHVlcywgc2VlIHRoZSB0ZXN0cyBmb3JcbiAgICAgICAgLy8gZXhhbXBsZXMgb2Ygd2hhdCB0aGF0IG1lYW5zLlxuICAgICAgICBkYXRhLm1pbGxpc2Vjb25kcyA9IG1pbGxpc2Vjb25kcyAlIDEwMDA7XG5cbiAgICAgICAgc2Vjb25kcyAgICAgICAgICAgPSBhYnNGbG9vcihtaWxsaXNlY29uZHMgLyAxMDAwKTtcbiAgICAgICAgZGF0YS5zZWNvbmRzICAgICAgPSBzZWNvbmRzICUgNjA7XG5cbiAgICAgICAgbWludXRlcyAgICAgICAgICAgPSBhYnNGbG9vcihzZWNvbmRzIC8gNjApO1xuICAgICAgICBkYXRhLm1pbnV0ZXMgICAgICA9IG1pbnV0ZXMgJSA2MDtcblxuICAgICAgICBob3VycyAgICAgICAgICAgICA9IGFic0Zsb29yKG1pbnV0ZXMgLyA2MCk7XG4gICAgICAgIGRhdGEuaG91cnMgICAgICAgID0gaG91cnMgJSAyNDtcblxuICAgICAgICBkYXlzICs9IGFic0Zsb29yKGhvdXJzIC8gMjQpO1xuXG4gICAgICAgIC8vIGNvbnZlcnQgZGF5cyB0byBtb250aHNcbiAgICAgICAgbW9udGhzRnJvbURheXMgPSBhYnNGbG9vcihkYXlzVG9Nb250aHMoZGF5cykpO1xuICAgICAgICBtb250aHMgKz0gbW9udGhzRnJvbURheXM7XG4gICAgICAgIGRheXMgLT0gYWJzQ2VpbChtb250aHNUb0RheXMobW9udGhzRnJvbURheXMpKTtcblxuICAgICAgICAvLyAxMiBtb250aHMgLT4gMSB5ZWFyXG4gICAgICAgIHllYXJzID0gYWJzRmxvb3IobW9udGhzIC8gMTIpO1xuICAgICAgICBtb250aHMgJT0gMTI7XG5cbiAgICAgICAgZGF0YS5kYXlzICAgPSBkYXlzO1xuICAgICAgICBkYXRhLm1vbnRocyA9IG1vbnRocztcbiAgICAgICAgZGF0YS55ZWFycyAgPSB5ZWFycztcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkYXlzVG9Nb250aHMgKGRheXMpIHtcbiAgICAgICAgLy8gNDAwIHllYXJzIGhhdmUgMTQ2MDk3IGRheXMgKHRha2luZyBpbnRvIGFjY291bnQgbGVhcCB5ZWFyIHJ1bGVzKVxuICAgICAgICAvLyA0MDAgeWVhcnMgaGF2ZSAxMiBtb250aHMgPT09IDQ4MDBcbiAgICAgICAgcmV0dXJuIGRheXMgKiA0ODAwIC8gMTQ2MDk3O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vbnRoc1RvRGF5cyAobW9udGhzKSB7XG4gICAgICAgIC8vIHRoZSByZXZlcnNlIG9mIGRheXNUb01vbnRoc1xuICAgICAgICByZXR1cm4gbW9udGhzICogMTQ2MDk3IC8gNDgwMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcyAodW5pdHMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF5cztcbiAgICAgICAgdmFyIG1vbnRocztcbiAgICAgICAgdmFyIG1pbGxpc2Vjb25kcyA9IHRoaXMuX21pbGxpc2Vjb25kcztcblxuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcblxuICAgICAgICBpZiAodW5pdHMgPT09ICdtb250aCcgfHwgdW5pdHMgPT09ICdxdWFydGVyJyB8fCB1bml0cyA9PT0gJ3llYXInKSB7XG4gICAgICAgICAgICBkYXlzID0gdGhpcy5fZGF5cyArIG1pbGxpc2Vjb25kcyAvIDg2NGU1O1xuICAgICAgICAgICAgbW9udGhzID0gdGhpcy5fbW9udGhzICsgZGF5c1RvTW9udGhzKGRheXMpO1xuICAgICAgICAgICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICAgICAgICAgIGNhc2UgJ21vbnRoJzogICByZXR1cm4gbW9udGhzO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3F1YXJ0ZXInOiByZXR1cm4gbW9udGhzIC8gMztcbiAgICAgICAgICAgICAgICBjYXNlICd5ZWFyJzogICAgcmV0dXJuIG1vbnRocyAvIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gaGFuZGxlIG1pbGxpc2Vjb25kcyBzZXBhcmF0ZWx5IGJlY2F1c2Ugb2YgZmxvYXRpbmcgcG9pbnQgbWF0aCBlcnJvcnMgKGlzc3VlICMxODY3KVxuICAgICAgICAgICAgZGF5cyA9IHRoaXMuX2RheXMgKyBNYXRoLnJvdW5kKG1vbnRoc1RvRGF5cyh0aGlzLl9tb250aHMpKTtcbiAgICAgICAgICAgIHN3aXRjaCAodW5pdHMpIHtcbiAgICAgICAgICAgICAgICBjYXNlICd3ZWVrJyAgIDogcmV0dXJuIGRheXMgLyA3ICAgICArIG1pbGxpc2Vjb25kcyAvIDYwNDhlNTtcbiAgICAgICAgICAgICAgICBjYXNlICdkYXknICAgIDogcmV0dXJuIGRheXMgICAgICAgICArIG1pbGxpc2Vjb25kcyAvIDg2NGU1O1xuICAgICAgICAgICAgICAgIGNhc2UgJ2hvdXInICAgOiByZXR1cm4gZGF5cyAqIDI0ICAgICsgbWlsbGlzZWNvbmRzIC8gMzZlNTtcbiAgICAgICAgICAgICAgICBjYXNlICdtaW51dGUnIDogcmV0dXJuIGRheXMgKiAxNDQwICArIG1pbGxpc2Vjb25kcyAvIDZlNDtcbiAgICAgICAgICAgICAgICBjYXNlICdzZWNvbmQnIDogcmV0dXJuIGRheXMgKiA4NjQwMCArIG1pbGxpc2Vjb25kcyAvIDEwMDA7XG4gICAgICAgICAgICAgICAgLy8gTWF0aC5mbG9vciBwcmV2ZW50cyBmbG9hdGluZyBwb2ludCBtYXRoIGVycm9ycyBoZXJlXG4gICAgICAgICAgICAgICAgY2FzZSAnbWlsbGlzZWNvbmQnOiByZXR1cm4gTWF0aC5mbG9vcihkYXlzICogODY0ZTUpICsgbWlsbGlzZWNvbmRzO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHRocm93IG5ldyBFcnJvcignVW5rbm93biB1bml0ICcgKyB1bml0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUT0RPOiBVc2UgdGhpcy5hcygnbXMnKT9cbiAgICBmdW5jdGlvbiB2YWx1ZU9mJDEgKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLl9taWxsaXNlY29uZHMgK1xuICAgICAgICAgICAgdGhpcy5fZGF5cyAqIDg2NGU1ICtcbiAgICAgICAgICAgICh0aGlzLl9tb250aHMgJSAxMikgKiAyNTkyZTYgK1xuICAgICAgICAgICAgdG9JbnQodGhpcy5fbW9udGhzIC8gMTIpICogMzE1MzZlNlxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VBcyAoYWxpYXMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFzKGFsaWFzKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgYXNNaWxsaXNlY29uZHMgPSBtYWtlQXMoJ21zJyk7XG4gICAgdmFyIGFzU2Vjb25kcyAgICAgID0gbWFrZUFzKCdzJyk7XG4gICAgdmFyIGFzTWludXRlcyAgICAgID0gbWFrZUFzKCdtJyk7XG4gICAgdmFyIGFzSG91cnMgICAgICAgID0gbWFrZUFzKCdoJyk7XG4gICAgdmFyIGFzRGF5cyAgICAgICAgID0gbWFrZUFzKCdkJyk7XG4gICAgdmFyIGFzV2Vla3MgICAgICAgID0gbWFrZUFzKCd3Jyk7XG4gICAgdmFyIGFzTW9udGhzICAgICAgID0gbWFrZUFzKCdNJyk7XG4gICAgdmFyIGFzUXVhcnRlcnMgICAgID0gbWFrZUFzKCdRJyk7XG4gICAgdmFyIGFzWWVhcnMgICAgICAgID0gbWFrZUFzKCd5Jyk7XG5cbiAgICBmdW5jdGlvbiBjbG9uZSQxICgpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldCQyICh1bml0cykge1xuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gdGhpc1t1bml0cyArICdzJ10oKSA6IE5hTjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlR2V0dGVyKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMuX2RhdGFbbmFtZV0gOiBOYU47XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIG1pbGxpc2Vjb25kcyA9IG1ha2VHZXR0ZXIoJ21pbGxpc2Vjb25kcycpO1xuICAgIHZhciBzZWNvbmRzICAgICAgPSBtYWtlR2V0dGVyKCdzZWNvbmRzJyk7XG4gICAgdmFyIG1pbnV0ZXMgICAgICA9IG1ha2VHZXR0ZXIoJ21pbnV0ZXMnKTtcbiAgICB2YXIgaG91cnMgICAgICAgID0gbWFrZUdldHRlcignaG91cnMnKTtcbiAgICB2YXIgZGF5cyAgICAgICAgID0gbWFrZUdldHRlcignZGF5cycpO1xuICAgIHZhciBtb250aHMgICAgICAgPSBtYWtlR2V0dGVyKCdtb250aHMnKTtcbiAgICB2YXIgeWVhcnMgICAgICAgID0gbWFrZUdldHRlcigneWVhcnMnKTtcblxuICAgIGZ1bmN0aW9uIHdlZWtzICgpIHtcbiAgICAgICAgcmV0dXJuIGFic0Zsb29yKHRoaXMuZGF5cygpIC8gNyk7XG4gICAgfVxuXG4gICAgdmFyIHJvdW5kID0gTWF0aC5yb3VuZDtcbiAgICB2YXIgdGhyZXNob2xkcyA9IHtcbiAgICAgICAgc3M6IDQ0LCAgICAgICAgIC8vIGEgZmV3IHNlY29uZHMgdG8gc2Vjb25kc1xuICAgICAgICBzIDogNDUsICAgICAgICAgLy8gc2Vjb25kcyB0byBtaW51dGVcbiAgICAgICAgbSA6IDQ1LCAgICAgICAgIC8vIG1pbnV0ZXMgdG8gaG91clxuICAgICAgICBoIDogMjIsICAgICAgICAgLy8gaG91cnMgdG8gZGF5XG4gICAgICAgIGQgOiAyNiwgICAgICAgICAvLyBkYXlzIHRvIG1vbnRoXG4gICAgICAgIE0gOiAxMSAgICAgICAgICAvLyBtb250aHMgdG8geWVhclxuICAgIH07XG5cbiAgICAvLyBoZWxwZXIgZnVuY3Rpb24gZm9yIG1vbWVudC5mbi5mcm9tLCBtb21lbnQuZm4uZnJvbU5vdywgYW5kIG1vbWVudC5kdXJhdGlvbi5mbi5odW1hbml6ZVxuICAgIGZ1bmN0aW9uIHN1YnN0aXR1dGVUaW1lQWdvKHN0cmluZywgbnVtYmVyLCB3aXRob3V0U3VmZml4LCBpc0Z1dHVyZSwgbG9jYWxlKSB7XG4gICAgICAgIHJldHVybiBsb2NhbGUucmVsYXRpdmVUaW1lKG51bWJlciB8fCAxLCAhIXdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbGF0aXZlVGltZSQxIChwb3NOZWdEdXJhdGlvbiwgd2l0aG91dFN1ZmZpeCwgbG9jYWxlKSB7XG4gICAgICAgIHZhciBkdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uKHBvc05lZ0R1cmF0aW9uKS5hYnMoKTtcbiAgICAgICAgdmFyIHNlY29uZHMgID0gcm91bmQoZHVyYXRpb24uYXMoJ3MnKSk7XG4gICAgICAgIHZhciBtaW51dGVzICA9IHJvdW5kKGR1cmF0aW9uLmFzKCdtJykpO1xuICAgICAgICB2YXIgaG91cnMgICAgPSByb3VuZChkdXJhdGlvbi5hcygnaCcpKTtcbiAgICAgICAgdmFyIGRheXMgICAgID0gcm91bmQoZHVyYXRpb24uYXMoJ2QnKSk7XG4gICAgICAgIHZhciBtb250aHMgICA9IHJvdW5kKGR1cmF0aW9uLmFzKCdNJykpO1xuICAgICAgICB2YXIgeWVhcnMgICAgPSByb3VuZChkdXJhdGlvbi5hcygneScpKTtcblxuICAgICAgICB2YXIgYSA9IHNlY29uZHMgPD0gdGhyZXNob2xkcy5zcyAmJiBbJ3MnLCBzZWNvbmRzXSAgfHxcbiAgICAgICAgICAgICAgICBzZWNvbmRzIDwgdGhyZXNob2xkcy5zICAgJiYgWydzcycsIHNlY29uZHNdIHx8XG4gICAgICAgICAgICAgICAgbWludXRlcyA8PSAxICAgICAgICAgICAgICYmIFsnbSddICAgICAgICAgICB8fFxuICAgICAgICAgICAgICAgIG1pbnV0ZXMgPCB0aHJlc2hvbGRzLm0gICAmJiBbJ21tJywgbWludXRlc10gfHxcbiAgICAgICAgICAgICAgICBob3VycyAgIDw9IDEgICAgICAgICAgICAgJiYgWydoJ10gICAgICAgICAgIHx8XG4gICAgICAgICAgICAgICAgaG91cnMgICA8IHRocmVzaG9sZHMuaCAgICYmIFsnaGgnLCBob3Vyc10gICB8fFxuICAgICAgICAgICAgICAgIGRheXMgICAgPD0gMSAgICAgICAgICAgICAmJiBbJ2QnXSAgICAgICAgICAgfHxcbiAgICAgICAgICAgICAgICBkYXlzICAgIDwgdGhyZXNob2xkcy5kICAgJiYgWydkZCcsIGRheXNdICAgIHx8XG4gICAgICAgICAgICAgICAgbW9udGhzICA8PSAxICAgICAgICAgICAgICYmIFsnTSddICAgICAgICAgICB8fFxuICAgICAgICAgICAgICAgIG1vbnRocyAgPCB0aHJlc2hvbGRzLk0gICAmJiBbJ01NJywgbW9udGhzXSAgfHxcbiAgICAgICAgICAgICAgICB5ZWFycyAgIDw9IDEgICAgICAgICAgICAgJiYgWyd5J10gICAgICAgICAgIHx8IFsneXknLCB5ZWFyc107XG5cbiAgICAgICAgYVsyXSA9IHdpdGhvdXRTdWZmaXg7XG4gICAgICAgIGFbM10gPSArcG9zTmVnRHVyYXRpb24gPiAwO1xuICAgICAgICBhWzRdID0gbG9jYWxlO1xuICAgICAgICByZXR1cm4gc3Vic3RpdHV0ZVRpbWVBZ28uYXBwbHkobnVsbCwgYSk7XG4gICAgfVxuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBhbGxvd3MgeW91IHRvIHNldCB0aGUgcm91bmRpbmcgZnVuY3Rpb24gZm9yIHJlbGF0aXZlIHRpbWUgc3RyaW5nc1xuICAgIGZ1bmN0aW9uIGdldFNldFJlbGF0aXZlVGltZVJvdW5kaW5nIChyb3VuZGluZ0Z1bmN0aW9uKSB7XG4gICAgICAgIGlmIChyb3VuZGluZ0Z1bmN0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiByb3VuZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mKHJvdW5kaW5nRnVuY3Rpb24pID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByb3VuZCA9IHJvdW5kaW5nRnVuY3Rpb247XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBhbGxvd3MgeW91IHRvIHNldCBhIHRocmVzaG9sZCBmb3IgcmVsYXRpdmUgdGltZSBzdHJpbmdzXG4gICAgZnVuY3Rpb24gZ2V0U2V0UmVsYXRpdmVUaW1lVGhyZXNob2xkICh0aHJlc2hvbGQsIGxpbWl0KSB7XG4gICAgICAgIGlmICh0aHJlc2hvbGRzW3RocmVzaG9sZF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsaW1pdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhyZXNob2xkc1t0aHJlc2hvbGRdO1xuICAgICAgICB9XG4gICAgICAgIHRocmVzaG9sZHNbdGhyZXNob2xkXSA9IGxpbWl0O1xuICAgICAgICBpZiAodGhyZXNob2xkID09PSAncycpIHtcbiAgICAgICAgICAgIHRocmVzaG9sZHMuc3MgPSBsaW1pdCAtIDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaHVtYW5pemUgKHdpdGhTdWZmaXgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbG9jYWxlID0gdGhpcy5sb2NhbGVEYXRhKCk7XG4gICAgICAgIHZhciBvdXRwdXQgPSByZWxhdGl2ZVRpbWUkMSh0aGlzLCAhd2l0aFN1ZmZpeCwgbG9jYWxlKTtcblxuICAgICAgICBpZiAod2l0aFN1ZmZpeCkge1xuICAgICAgICAgICAgb3V0cHV0ID0gbG9jYWxlLnBhc3RGdXR1cmUoK3RoaXMsIG91dHB1dCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbG9jYWxlLnBvc3Rmb3JtYXQob3V0cHV0KTtcbiAgICB9XG5cbiAgICB2YXIgYWJzJDEgPSBNYXRoLmFicztcblxuICAgIGZ1bmN0aW9uIHNpZ24oeCkge1xuICAgICAgICByZXR1cm4gKCh4ID4gMCkgLSAoeCA8IDApKSB8fCAreDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b0lTT1N0cmluZyQxKCkge1xuICAgICAgICAvLyBmb3IgSVNPIHN0cmluZ3Mgd2UgZG8gbm90IHVzZSB0aGUgbm9ybWFsIGJ1YmJsaW5nIHJ1bGVzOlxuICAgICAgICAvLyAgKiBtaWxsaXNlY29uZHMgYnViYmxlIHVwIHVudGlsIHRoZXkgYmVjb21lIGhvdXJzXG4gICAgICAgIC8vICAqIGRheXMgZG8gbm90IGJ1YmJsZSBhdCBhbGxcbiAgICAgICAgLy8gICogbW9udGhzIGJ1YmJsZSB1cCB1bnRpbCB0aGV5IGJlY29tZSB5ZWFyc1xuICAgICAgICAvLyBUaGlzIGlzIGJlY2F1c2UgdGhlcmUgaXMgbm8gY29udGV4dC1mcmVlIGNvbnZlcnNpb24gYmV0d2VlbiBob3VycyBhbmQgZGF5c1xuICAgICAgICAvLyAodGhpbmsgb2YgY2xvY2sgY2hhbmdlcylcbiAgICAgICAgLy8gYW5kIGFsc28gbm90IGJldHdlZW4gZGF5cyBhbmQgbW9udGhzICgyOC0zMSBkYXlzIHBlciBtb250aClcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2Vjb25kcyA9IGFicyQxKHRoaXMuX21pbGxpc2Vjb25kcykgLyAxMDAwO1xuICAgICAgICB2YXIgZGF5cyAgICAgICAgID0gYWJzJDEodGhpcy5fZGF5cyk7XG4gICAgICAgIHZhciBtb250aHMgICAgICAgPSBhYnMkMSh0aGlzLl9tb250aHMpO1xuICAgICAgICB2YXIgbWludXRlcywgaG91cnMsIHllYXJzO1xuXG4gICAgICAgIC8vIDM2MDAgc2Vjb25kcyAtPiA2MCBtaW51dGVzIC0+IDEgaG91clxuICAgICAgICBtaW51dGVzICAgICAgICAgICA9IGFic0Zsb29yKHNlY29uZHMgLyA2MCk7XG4gICAgICAgIGhvdXJzICAgICAgICAgICAgID0gYWJzRmxvb3IobWludXRlcyAvIDYwKTtcbiAgICAgICAgc2Vjb25kcyAlPSA2MDtcbiAgICAgICAgbWludXRlcyAlPSA2MDtcblxuICAgICAgICAvLyAxMiBtb250aHMgLT4gMSB5ZWFyXG4gICAgICAgIHllYXJzICA9IGFic0Zsb29yKG1vbnRocyAvIDEyKTtcbiAgICAgICAgbW9udGhzICU9IDEyO1xuXG5cbiAgICAgICAgLy8gaW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL2RvcmRpbGxlL21vbWVudC1pc29kdXJhdGlvbi9ibG9iL21hc3Rlci9tb21lbnQuaXNvZHVyYXRpb24uanNcbiAgICAgICAgdmFyIFkgPSB5ZWFycztcbiAgICAgICAgdmFyIE0gPSBtb250aHM7XG4gICAgICAgIHZhciBEID0gZGF5cztcbiAgICAgICAgdmFyIGggPSBob3VycztcbiAgICAgICAgdmFyIG0gPSBtaW51dGVzO1xuICAgICAgICB2YXIgcyA9IHNlY29uZHMgPyBzZWNvbmRzLnRvRml4ZWQoMykucmVwbGFjZSgvXFwuPzArJC8sICcnKSA6ICcnO1xuICAgICAgICB2YXIgdG90YWwgPSB0aGlzLmFzU2Vjb25kcygpO1xuXG4gICAgICAgIGlmICghdG90YWwpIHtcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHNhbWUgYXMgQyMncyAoTm9kYSkgYW5kIHB5dGhvbiAoaXNvZGF0ZSkuLi5cbiAgICAgICAgICAgIC8vIGJ1dCBub3Qgb3RoZXIgSlMgKGdvb2cuZGF0ZSlcbiAgICAgICAgICAgIHJldHVybiAnUDBEJztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0b3RhbFNpZ24gPSB0b3RhbCA8IDAgPyAnLScgOiAnJztcbiAgICAgICAgdmFyIHltU2lnbiA9IHNpZ24odGhpcy5fbW9udGhzKSAhPT0gc2lnbih0b3RhbCkgPyAnLScgOiAnJztcbiAgICAgICAgdmFyIGRheXNTaWduID0gc2lnbih0aGlzLl9kYXlzKSAhPT0gc2lnbih0b3RhbCkgPyAnLScgOiAnJztcbiAgICAgICAgdmFyIGhtc1NpZ24gPSBzaWduKHRoaXMuX21pbGxpc2Vjb25kcykgIT09IHNpZ24odG90YWwpID8gJy0nIDogJyc7XG5cbiAgICAgICAgcmV0dXJuIHRvdGFsU2lnbiArICdQJyArXG4gICAgICAgICAgICAoWSA/IHltU2lnbiArIFkgKyAnWScgOiAnJykgK1xuICAgICAgICAgICAgKE0gPyB5bVNpZ24gKyBNICsgJ00nIDogJycpICtcbiAgICAgICAgICAgIChEID8gZGF5c1NpZ24gKyBEICsgJ0QnIDogJycpICtcbiAgICAgICAgICAgICgoaCB8fCBtIHx8IHMpID8gJ1QnIDogJycpICtcbiAgICAgICAgICAgIChoID8gaG1zU2lnbiArIGggKyAnSCcgOiAnJykgK1xuICAgICAgICAgICAgKG0gPyBobXNTaWduICsgbSArICdNJyA6ICcnKSArXG4gICAgICAgICAgICAocyA/IGhtc1NpZ24gKyBzICsgJ1MnIDogJycpO1xuICAgIH1cblxuICAgIHZhciBwcm90byQyID0gRHVyYXRpb24ucHJvdG90eXBlO1xuXG4gICAgcHJvdG8kMi5pc1ZhbGlkICAgICAgICA9IGlzVmFsaWQkMTtcbiAgICBwcm90byQyLmFicyAgICAgICAgICAgID0gYWJzO1xuICAgIHByb3RvJDIuYWRkICAgICAgICAgICAgPSBhZGQkMTtcbiAgICBwcm90byQyLnN1YnRyYWN0ICAgICAgID0gc3VidHJhY3QkMTtcbiAgICBwcm90byQyLmFzICAgICAgICAgICAgID0gYXM7XG4gICAgcHJvdG8kMi5hc01pbGxpc2Vjb25kcyA9IGFzTWlsbGlzZWNvbmRzO1xuICAgIHByb3RvJDIuYXNTZWNvbmRzICAgICAgPSBhc1NlY29uZHM7XG4gICAgcHJvdG8kMi5hc01pbnV0ZXMgICAgICA9IGFzTWludXRlcztcbiAgICBwcm90byQyLmFzSG91cnMgICAgICAgID0gYXNIb3VycztcbiAgICBwcm90byQyLmFzRGF5cyAgICAgICAgID0gYXNEYXlzO1xuICAgIHByb3RvJDIuYXNXZWVrcyAgICAgICAgPSBhc1dlZWtzO1xuICAgIHByb3RvJDIuYXNNb250aHMgICAgICAgPSBhc01vbnRocztcbiAgICBwcm90byQyLmFzUXVhcnRlcnMgICAgID0gYXNRdWFydGVycztcbiAgICBwcm90byQyLmFzWWVhcnMgICAgICAgID0gYXNZZWFycztcbiAgICBwcm90byQyLnZhbHVlT2YgICAgICAgID0gdmFsdWVPZiQxO1xuICAgIHByb3RvJDIuX2J1YmJsZSAgICAgICAgPSBidWJibGU7XG4gICAgcHJvdG8kMi5jbG9uZSAgICAgICAgICA9IGNsb25lJDE7XG4gICAgcHJvdG8kMi5nZXQgICAgICAgICAgICA9IGdldCQyO1xuICAgIHByb3RvJDIubWlsbGlzZWNvbmRzICAgPSBtaWxsaXNlY29uZHM7XG4gICAgcHJvdG8kMi5zZWNvbmRzICAgICAgICA9IHNlY29uZHM7XG4gICAgcHJvdG8kMi5taW51dGVzICAgICAgICA9IG1pbnV0ZXM7XG4gICAgcHJvdG8kMi5ob3VycyAgICAgICAgICA9IGhvdXJzO1xuICAgIHByb3RvJDIuZGF5cyAgICAgICAgICAgPSBkYXlzO1xuICAgIHByb3RvJDIud2Vla3MgICAgICAgICAgPSB3ZWVrcztcbiAgICBwcm90byQyLm1vbnRocyAgICAgICAgID0gbW9udGhzO1xuICAgIHByb3RvJDIueWVhcnMgICAgICAgICAgPSB5ZWFycztcbiAgICBwcm90byQyLmh1bWFuaXplICAgICAgID0gaHVtYW5pemU7XG4gICAgcHJvdG8kMi50b0lTT1N0cmluZyAgICA9IHRvSVNPU3RyaW5nJDE7XG4gICAgcHJvdG8kMi50b1N0cmluZyAgICAgICA9IHRvSVNPU3RyaW5nJDE7XG4gICAgcHJvdG8kMi50b0pTT04gICAgICAgICA9IHRvSVNPU3RyaW5nJDE7XG4gICAgcHJvdG8kMi5sb2NhbGUgICAgICAgICA9IGxvY2FsZTtcbiAgICBwcm90byQyLmxvY2FsZURhdGEgICAgID0gbG9jYWxlRGF0YTtcblxuICAgIHByb3RvJDIudG9Jc29TdHJpbmcgPSBkZXByZWNhdGUoJ3RvSXNvU3RyaW5nKCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSB0b0lTT1N0cmluZygpIGluc3RlYWQgKG5vdGljZSB0aGUgY2FwaXRhbHMpJywgdG9JU09TdHJpbmckMSk7XG4gICAgcHJvdG8kMi5sYW5nID0gbGFuZztcblxuICAgIC8vIFNpZGUgZWZmZWN0IGltcG9ydHNcblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdYJywgMCwgMCwgJ3VuaXgnKTtcbiAgICBhZGRGb3JtYXRUb2tlbigneCcsIDAsIDAsICd2YWx1ZU9mJyk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCd4JywgbWF0Y2hTaWduZWQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1gnLCBtYXRjaFRpbWVzdGFtcCk7XG4gICAgYWRkUGFyc2VUb2tlbignWCcsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShwYXJzZUZsb2F0KGlucHV0LCAxMCkgKiAxMDAwKTtcbiAgICB9KTtcbiAgICBhZGRQYXJzZVRva2VuKCd4JywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKHRvSW50KGlucHV0KSk7XG4gICAgfSk7XG5cbiAgICAvLyBTaWRlIGVmZmVjdCBpbXBvcnRzXG5cbiAgICAvLyEgbW9tZW50LmpzXG5cbiAgICBob29rcy52ZXJzaW9uID0gJzIuMjQuMCc7XG5cbiAgICBzZXRIb29rQ2FsbGJhY2soY3JlYXRlTG9jYWwpO1xuXG4gICAgaG9va3MuZm4gICAgICAgICAgICAgICAgICAgID0gcHJvdG87XG4gICAgaG9va3MubWluICAgICAgICAgICAgICAgICAgID0gbWluO1xuICAgIGhvb2tzLm1heCAgICAgICAgICAgICAgICAgICA9IG1heDtcbiAgICBob29rcy5ub3cgICAgICAgICAgICAgICAgICAgPSBub3c7XG4gICAgaG9va3MudXRjICAgICAgICAgICAgICAgICAgID0gY3JlYXRlVVRDO1xuICAgIGhvb2tzLnVuaXggICAgICAgICAgICAgICAgICA9IGNyZWF0ZVVuaXg7XG4gICAgaG9va3MubW9udGhzICAgICAgICAgICAgICAgID0gbGlzdE1vbnRocztcbiAgICBob29rcy5pc0RhdGUgICAgICAgICAgICAgICAgPSBpc0RhdGU7XG4gICAgaG9va3MubG9jYWxlICAgICAgICAgICAgICAgID0gZ2V0U2V0R2xvYmFsTG9jYWxlO1xuICAgIGhvb2tzLmludmFsaWQgICAgICAgICAgICAgICA9IGNyZWF0ZUludmFsaWQ7XG4gICAgaG9va3MuZHVyYXRpb24gICAgICAgICAgICAgID0gY3JlYXRlRHVyYXRpb247XG4gICAgaG9va3MuaXNNb21lbnQgICAgICAgICAgICAgID0gaXNNb21lbnQ7XG4gICAgaG9va3Mud2Vla2RheXMgICAgICAgICAgICAgID0gbGlzdFdlZWtkYXlzO1xuICAgIGhvb2tzLnBhcnNlWm9uZSAgICAgICAgICAgICA9IGNyZWF0ZUluWm9uZTtcbiAgICBob29rcy5sb2NhbGVEYXRhICAgICAgICAgICAgPSBnZXRMb2NhbGU7XG4gICAgaG9va3MuaXNEdXJhdGlvbiAgICAgICAgICAgID0gaXNEdXJhdGlvbjtcbiAgICBob29rcy5tb250aHNTaG9ydCAgICAgICAgICAgPSBsaXN0TW9udGhzU2hvcnQ7XG4gICAgaG9va3Mud2Vla2RheXNNaW4gICAgICAgICAgID0gbGlzdFdlZWtkYXlzTWluO1xuICAgIGhvb2tzLmRlZmluZUxvY2FsZSAgICAgICAgICA9IGRlZmluZUxvY2FsZTtcbiAgICBob29rcy51cGRhdGVMb2NhbGUgICAgICAgICAgPSB1cGRhdGVMb2NhbGU7XG4gICAgaG9va3MubG9jYWxlcyAgICAgICAgICAgICAgID0gbGlzdExvY2FsZXM7XG4gICAgaG9va3Mud2Vla2RheXNTaG9ydCAgICAgICAgID0gbGlzdFdlZWtkYXlzU2hvcnQ7XG4gICAgaG9va3Mubm9ybWFsaXplVW5pdHMgICAgICAgID0gbm9ybWFsaXplVW5pdHM7XG4gICAgaG9va3MucmVsYXRpdmVUaW1lUm91bmRpbmcgID0gZ2V0U2V0UmVsYXRpdmVUaW1lUm91bmRpbmc7XG4gICAgaG9va3MucmVsYXRpdmVUaW1lVGhyZXNob2xkID0gZ2V0U2V0UmVsYXRpdmVUaW1lVGhyZXNob2xkO1xuICAgIGhvb2tzLmNhbGVuZGFyRm9ybWF0ICAgICAgICA9IGdldENhbGVuZGFyRm9ybWF0O1xuICAgIGhvb2tzLnByb3RvdHlwZSAgICAgICAgICAgICA9IHByb3RvO1xuXG4gICAgLy8gY3VycmVudGx5IEhUTUw1IGlucHV0IHR5cGUgb25seSBzdXBwb3J0cyAyNC1ob3VyIGZvcm1hdHNcbiAgICBob29rcy5IVE1MNV9GTVQgPSB7XG4gICAgICAgIERBVEVUSU1FX0xPQ0FMOiAnWVlZWS1NTS1ERFRISDptbScsICAgICAgICAgICAgIC8vIDxpbnB1dCB0eXBlPVwiZGF0ZXRpbWUtbG9jYWxcIiAvPlxuICAgICAgICBEQVRFVElNRV9MT0NBTF9TRUNPTkRTOiAnWVlZWS1NTS1ERFRISDptbTpzcycsICAvLyA8aW5wdXQgdHlwZT1cImRhdGV0aW1lLWxvY2FsXCIgc3RlcD1cIjFcIiAvPlxuICAgICAgICBEQVRFVElNRV9MT0NBTF9NUzogJ1lZWVktTU0tRERUSEg6bW06c3MuU1NTJywgICAvLyA8aW5wdXQgdHlwZT1cImRhdGV0aW1lLWxvY2FsXCIgc3RlcD1cIjAuMDAxXCIgLz5cbiAgICAgICAgREFURTogJ1lZWVktTU0tREQnLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJkYXRlXCIgLz5cbiAgICAgICAgVElNRTogJ0hIOm1tJywgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJ0aW1lXCIgLz5cbiAgICAgICAgVElNRV9TRUNPTkRTOiAnSEg6bW06c3MnLCAgICAgICAgICAgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJ0aW1lXCIgc3RlcD1cIjFcIiAvPlxuICAgICAgICBUSU1FX01TOiAnSEg6bW06c3MuU1NTJywgICAgICAgICAgICAgICAgICAgICAgICAvLyA8aW5wdXQgdHlwZT1cInRpbWVcIiBzdGVwPVwiMC4wMDFcIiAvPlxuICAgICAgICBXRUVLOiAnR0dHRy1bV11XVycsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8aW5wdXQgdHlwZT1cIndlZWtcIiAvPlxuICAgICAgICBNT05USDogJ1lZWVktTU0nICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8aW5wdXQgdHlwZT1cIm1vbnRoXCIgLz5cbiAgICB9O1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdhZicsIHtcbiAgICAgICAgbW9udGhzIDogJ0phbnVhcmllX0ZlYnJ1YXJpZV9NYWFydF9BcHJpbF9NZWlfSnVuaWVfSnVsaWVfQXVndXN0dXNfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGVzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTXJ0X0Fwcl9NZWlfSnVuX0p1bF9BdWdfU2VwX09rdF9Ob3ZfRGVzJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdTb25kYWdfTWFhbmRhZ19EaW5zZGFnX1dvZW5zZGFnX0RvbmRlcmRhZ19WcnlkYWdfU2F0ZXJkYWcnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnU29uX01hYV9EaW5fV29lX0Rvbl9WcnlfU2F0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdTb19NYV9EaV9Xb19Eb19Wcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL3ZtfG5tL2ksXG4gICAgICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiAvXm5tJC9pLnRlc3QoaW5wdXQpO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXJzIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICd2bScgOiAnVk0nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdubScgOiAnTk0nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbVmFuZGFnIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1tNw7RyZSBvbV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbb21dIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW0dpc3RlciBvbV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW0xhYXNdIGRkZGQgW29tXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnb29yICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgZ2VsZWRlJyxcbiAgICAgICAgICAgIHMgOiAnXFwnbiBwYWFyIHNla29uZGVzJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNla29uZGVzJyxcbiAgICAgICAgICAgIG0gOiAnXFwnbiBtaW51dXQnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXRlJyxcbiAgICAgICAgICAgIGggOiAnXFwnbiB1dXInLFxuICAgICAgICAgICAgaGggOiAnJWQgdXJlJyxcbiAgICAgICAgICAgIGQgOiAnXFwnbiBkYWcnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGFlJyxcbiAgICAgICAgICAgIE0gOiAnXFwnbiBtYWFuZCcsXG4gICAgICAgICAgICBNTSA6ICclZCBtYWFuZGUnLFxuICAgICAgICAgICAgeSA6ICdcXCduIGphYXInLFxuICAgICAgICAgICAgeXkgOiAnJWQgamFhcidcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICgobnVtYmVyID09PSAxIHx8IG51bWJlciA9PT0gOCB8fCBudW1iZXIgPj0gMjApID8gJ3N0ZScgOiAnZGUnKTsgLy8gVGhhbmtzIHRvIEpvcmlzIFLDtmxpbmcgOiBodHRwczovL2dpdGh1Yi5jb20vamp1cGl0ZXJcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1hYW5kYWcgaXMgZGllIGVlcnN0ZSBkYWcgdmFuIGRpZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gRGllIHdlZWsgd2F0IGRpZSA0ZGUgSmFudWFyaWUgYmV2YXQgaXMgZGllIGVlcnN0ZSB3ZWVrIHZhbiBkaWUgamFhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdhci1keicsIHtcbiAgICAgICAgbW9udGhzIDogJ9is2KfZhtmB2Ypf2YHZitmB2LHZil/Zhdin2LHYs1/Yo9mB2LHZitmEX9mF2KfZil/YrNmI2KfZhl/YrNmI2YrZhNmK2Klf2KPZiNiqX9iz2KjYqtmF2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmB2YXYqNixX9iv2YrYs9mF2KjYsScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn2KzYp9mG2YHZil/ZgdmK2YHYsdmKX9mF2KfYsdizX9ij2YHYsdmK2YRf2YXYp9mKX9is2YjYp9mGX9is2YjZitmE2YrYqV/Yo9mI2Kpf2LPYqNiq2YXYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YHZhdio2LFf2K/Zitiz2YXYqNixJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfYp9mE2KPYrdivX9in2YTYpdir2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn2KfYrdivX9in2KvZhtmK2YZf2KvZhNin2KvYp9ihX9in2LHYqNi52KfYoV/YrtmF2YrYs1/YrNmF2LnYqV/Ys9io2KonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ9ij2K1f2KXYq1/Yq9mE2Kdf2KPYsV/YrtmFX9is2YVf2LPYqCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfZgdmKICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAn2YXZhtiwICVzJyxcbiAgICAgICAgICAgIHMgOiAn2KvZiNin2YYnLFxuICAgICAgICAgICAgc3MgOiAnJWQg2KvYp9mG2YrYqScsXG4gICAgICAgICAgICBtIDogJ9iv2YLZitmC2KknLFxuICAgICAgICAgICAgbW0gOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgICAgICBoIDogJ9iz2KfYudipJyxcbiAgICAgICAgICAgIGhoIDogJyVkINiz2KfYudin2KonLFxuICAgICAgICAgICAgZCA6ICfZitmI2YUnLFxuICAgICAgICAgICAgZGQgOiAnJWQg2KPZitin2YUnLFxuICAgICAgICAgICAgTSA6ICfYtNmH2LEnLFxuICAgICAgICAgICAgTU0gOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICAgICAgeSA6ICfYs9mG2KknLFxuICAgICAgICAgICAgeXkgOiAnJWQg2LPZhtmI2KfYqidcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2FyLWt3Jywge1xuICAgICAgICBtb250aHMgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2Ypf2YrZiNmG2YrZiF/ZitmI2YTZitmI2LJf2LrYtNiqX9i02KrZhtio2LFf2KPZg9iq2YjYqNixX9mG2YjZhtio2LFf2K/YrNmG2KjYsScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2Ypf2YrZiNmG2YrZiF/ZitmI2YTZitmI2LJf2LrYtNiqX9i02KrZhtio2LFf2KPZg9iq2YjYqNixX9mG2YjZhtio2LFf2K/YrNmG2KjYsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAn2KfZhNij2K3Yr1/Yp9mE2KXYqtmG2YrZhl/Yp9mE2KvZhNin2KvYp9ihX9in2YTYo9ix2KjYudin2KFf2KfZhNiu2YXZitizX9in2YTYrNmF2LnYqV/Yp9mE2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ9in2K3Yr1/Yp9iq2YbZitmGX9ir2YTYp9ir2KfYoV/Yp9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfZgdmKICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAn2YXZhtiwICVzJyxcbiAgICAgICAgICAgIHMgOiAn2KvZiNin2YYnLFxuICAgICAgICAgICAgc3MgOiAnJWQg2KvYp9mG2YrYqScsXG4gICAgICAgICAgICBtIDogJ9iv2YLZitmC2KknLFxuICAgICAgICAgICAgbW0gOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgICAgICBoIDogJ9iz2KfYudipJyxcbiAgICAgICAgICAgIGhoIDogJyVkINiz2KfYudin2KonLFxuICAgICAgICAgICAgZCA6ICfZitmI2YUnLFxuICAgICAgICAgICAgZGQgOiAnJWQg2KPZitin2YUnLFxuICAgICAgICAgICAgTSA6ICfYtNmH2LEnLFxuICAgICAgICAgICAgTU0gOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICAgICAgeSA6ICfYs9mG2KknLFxuICAgICAgICAgICAgeXkgOiAnJWQg2LPZhtmI2KfYqidcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDEydGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAgPSB7XG4gICAgICAgICcxJzogJzEnLFxuICAgICAgICAnMic6ICcyJyxcbiAgICAgICAgJzMnOiAnMycsXG4gICAgICAgICc0JzogJzQnLFxuICAgICAgICAnNSc6ICc1JyxcbiAgICAgICAgJzYnOiAnNicsXG4gICAgICAgICc3JzogJzcnLFxuICAgICAgICAnOCc6ICc4JyxcbiAgICAgICAgJzknOiAnOScsXG4gICAgICAgICcwJzogJzAnXG4gICAgfSwgcGx1cmFsRm9ybSA9IGZ1bmN0aW9uIChuKSB7XG4gICAgICAgIHJldHVybiBuID09PSAwID8gMCA6IG4gPT09IDEgPyAxIDogbiA9PT0gMiA/IDIgOiBuICUgMTAwID49IDMgJiYgbiAlIDEwMCA8PSAxMCA/IDMgOiBuICUgMTAwID49IDExID8gNCA6IDU7XG4gICAgfSwgcGx1cmFscyA9IHtcbiAgICAgICAgcyA6IFsn2KPZgtmEINmF2YYg2KvYp9mG2YrYqScsICfYq9in2YbZitipINmI2KfYrdiv2KknLCBbJ9ir2KfZhtmK2KrYp9mGJywgJ9ir2KfZhtmK2KrZitmGJ10sICclZCDYq9mI2KfZhicsICclZCDYq9in2YbZitipJywgJyVkINir2KfZhtmK2KknXSxcbiAgICAgICAgbSA6IFsn2KPZgtmEINmF2YYg2K/ZgtmK2YLYqScsICfYr9mC2YrZgtipINmI2KfYrdiv2KknLCBbJ9iv2YLZitmC2KrYp9mGJywgJ9iv2YLZitmC2KrZitmGJ10sICclZCDYr9mC2KfYptmCJywgJyVkINiv2YLZitmC2KknLCAnJWQg2K/ZgtmK2YLYqSddLFxuICAgICAgICBoIDogWyfYo9mC2YQg2YXZhiDYs9in2LnYqScsICfYs9in2LnYqSDZiNin2K3Yr9ipJywgWyfYs9in2LnYqtin2YYnLCAn2LPYp9i52KrZitmGJ10sICclZCDYs9in2LnYp9iqJywgJyVkINiz2KfYudipJywgJyVkINiz2KfYudipJ10sXG4gICAgICAgIGQgOiBbJ9ij2YLZhCDZhdmGINmK2YjZhScsICfZitmI2YUg2YjYp9it2K8nLCBbJ9mK2YjZhdin2YYnLCAn2YrZiNmF2YrZhiddLCAnJWQg2KPZitin2YUnLCAnJWQg2YrZiNmF2YvYpycsICclZCDZitmI2YUnXSxcbiAgICAgICAgTSA6IFsn2KPZgtmEINmF2YYg2LTZh9ixJywgJ9i02YfYsSDZiNin2K3YrycsIFsn2LTZh9ix2KfZhicsICfYtNmH2LHZitmGJ10sICclZCDYo9i02YfYsScsICclZCDYtNmH2LHYpycsICclZCDYtNmH2LEnXSxcbiAgICAgICAgeSA6IFsn2KPZgtmEINmF2YYg2LnYp9mFJywgJ9i52KfZhSDZiNin2K3YrycsIFsn2LnYp9mF2KfZhicsICfYudin2YXZitmGJ10sICclZCDYo9i52YjYp9mFJywgJyVkINi52KfZhdmL2KcnLCAnJWQg2LnYp9mFJ11cbiAgICB9LCBwbHVyYWxpemUgPSBmdW5jdGlvbiAodSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgdmFyIGYgPSBwbHVyYWxGb3JtKG51bWJlciksXG4gICAgICAgICAgICAgICAgc3RyID0gcGx1cmFsc1t1XVtwbHVyYWxGb3JtKG51bWJlcildO1xuICAgICAgICAgICAgaWYgKGYgPT09IDIpIHtcbiAgICAgICAgICAgICAgICBzdHIgPSBzdHJbd2l0aG91dFN1ZmZpeCA/IDAgOiAxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdHIucmVwbGFjZSgvJWQvaSwgbnVtYmVyKTtcbiAgICAgICAgfTtcbiAgICB9LCBtb250aHMkMSA9IFtcbiAgICAgICAgJ9mK2YbYp9mK2LEnLFxuICAgICAgICAn2YHYqNix2KfZitixJyxcbiAgICAgICAgJ9mF2KfYsdizJyxcbiAgICAgICAgJ9ij2KjYsdmK2YQnLFxuICAgICAgICAn2YXYp9mK2YgnLFxuICAgICAgICAn2YrZiNmG2YrZiCcsXG4gICAgICAgICfZitmI2YTZitmIJyxcbiAgICAgICAgJ9ij2LrYs9i32LMnLFxuICAgICAgICAn2LPYqNiq2YXYqNixJyxcbiAgICAgICAgJ9ij2YPYqtmI2KjYsScsXG4gICAgICAgICfZhtmI2YHZhdio2LEnLFxuICAgICAgICAn2K/Zitiz2YXYqNixJ1xuICAgIF07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2FyLWx5Jywge1xuICAgICAgICBtb250aHMgOiBtb250aHMkMSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiBtb250aHMkMSxcbiAgICAgICAgd2Vla2RheXMgOiAn2KfZhNij2K3Yr1/Yp9mE2KXYq9mG2YrZhl/Yp9mE2KvZhNin2KvYp9ihX9in2YTYo9ix2KjYudin2KFf2KfZhNiu2YXZitizX9in2YTYrNmF2LnYqV/Yp9mE2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ9ij2K3Yr1/Ypdir2YbZitmGX9ir2YTYp9ir2KfYoV/Yo9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdEL1xcdTIwMEZNL1xcdTIwMEZZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/YtXzZhS8sXG4gICAgICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiAn2YUnID09PSBpbnB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfYtSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2YUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9i62K/Zi9inINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfYqNi52K8gJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICfZhdmG2LAgJXMnLFxuICAgICAgICAgICAgcyA6IHBsdXJhbGl6ZSgncycpLFxuICAgICAgICAgICAgc3MgOiBwbHVyYWxpemUoJ3MnKSxcbiAgICAgICAgICAgIG0gOiBwbHVyYWxpemUoJ20nKSxcbiAgICAgICAgICAgIG1tIDogcGx1cmFsaXplKCdtJyksXG4gICAgICAgICAgICBoIDogcGx1cmFsaXplKCdoJyksXG4gICAgICAgICAgICBoaCA6IHBsdXJhbGl6ZSgnaCcpLFxuICAgICAgICAgICAgZCA6IHBsdXJhbGl6ZSgnZCcpLFxuICAgICAgICAgICAgZGQgOiBwbHVyYWxpemUoJ2QnKSxcbiAgICAgICAgICAgIE0gOiBwbHVyYWxpemUoJ00nKSxcbiAgICAgICAgICAgIE1NIDogcGx1cmFsaXplKCdNJyksXG4gICAgICAgICAgICB5IDogcGx1cmFsaXplKCd5JyksXG4gICAgICAgICAgICB5eSA6IHBsdXJhbGl6ZSgneScpXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXBbbWF0Y2hdO1xuICAgICAgICAgICAgfSkucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiAxMiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMTJ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdhci1tYScsIHtcbiAgICAgICAgbW9udGhzIDogJ9mK2YbYp9mK2LFf2YHYqNix2KfZitixX9mF2KfYsdizX9ij2KjYsdmK2YRf2YXYp9mKX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiNiyX9i62LTYql/YtNiq2YbYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YbYqNixX9iv2KzZhtio2LEnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ9mK2YbYp9mK2LFf2YHYqNix2KfZitixX9mF2KfYsdizX9ij2KjYsdmK2YRf2YXYp9mKX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiNiyX9i62LTYql/YtNiq2YbYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YbYqNixX9iv2KzZhtio2LEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ9in2YTYo9it2K9f2KfZhNil2KrZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfYp9it2K9f2KfYqtmG2YrZhl/Yq9mE2KfYq9in2KFf2KfYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn2K1f2YZf2Ktf2LFf2K5f2Kxf2LMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9i62K/YpyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW9i52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAn2YHZiiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgICAgICBzIDogJ9ir2YjYp9mGJyxcbiAgICAgICAgICAgIHNzIDogJyVkINir2KfZhtmK2KknLFxuICAgICAgICAgICAgbSA6ICfYr9mC2YrZgtipJyxcbiAgICAgICAgICAgIG1tIDogJyVkINiv2YLYp9im2YInLFxuICAgICAgICAgICAgaCA6ICfYs9in2LnYqScsXG4gICAgICAgICAgICBoaCA6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgICAgIGQgOiAn2YrZiNmFJyxcbiAgICAgICAgICAgIGRkIDogJyVkINij2YrYp9mFJyxcbiAgICAgICAgICAgIE0gOiAn2LTZh9ixJyxcbiAgICAgICAgICAgIE1NIDogJyVkINij2LTZh9ixJyxcbiAgICAgICAgICAgIHkgOiAn2LPZhtipJyxcbiAgICAgICAgICAgIHl5IDogJyVkINiz2YbZiNin2KonXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiA2LCAvLyBTYXR1cmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDEydGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkMSA9IHtcbiAgICAgICAgJzEnOiAn2aEnLFxuICAgICAgICAnMic6ICfZoicsXG4gICAgICAgICczJzogJ9mjJyxcbiAgICAgICAgJzQnOiAn2aQnLFxuICAgICAgICAnNSc6ICfZpScsXG4gICAgICAgICc2JzogJ9mmJyxcbiAgICAgICAgJzcnOiAn2acnLFxuICAgICAgICAnOCc6ICfZqCcsXG4gICAgICAgICc5JzogJ9mpJyxcbiAgICAgICAgJzAnOiAn2aAnXG4gICAgfSwgbnVtYmVyTWFwID0ge1xuICAgICAgICAn2aEnOiAnMScsXG4gICAgICAgICfZoic6ICcyJyxcbiAgICAgICAgJ9mjJzogJzMnLFxuICAgICAgICAn2aQnOiAnNCcsXG4gICAgICAgICfZpSc6ICc1JyxcbiAgICAgICAgJ9mmJzogJzYnLFxuICAgICAgICAn2acnOiAnNycsXG4gICAgICAgICfZqCc6ICc4JyxcbiAgICAgICAgJ9mpJzogJzknLFxuICAgICAgICAn2aAnOiAnMCdcbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdhci1zYScsIHtcbiAgICAgICAgbW9udGhzIDogJ9mK2YbYp9mK2LFf2YHYqNix2KfZitixX9mF2KfYsdizX9ij2KjYsdmK2YRf2YXYp9mK2Yhf2YrZiNmG2YrZiF/ZitmI2YTZitmIX9ij2LrYs9i32LNf2LPYqNiq2YXYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YHZhdio2LFf2K/Zitiz2YXYqNixJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICfZitmG2KfZitixX9mB2KjYsdin2YrYsV/Zhdin2LHYs1/Yo9io2LHZitmEX9mF2KfZitmIX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiF/Yo9i62LPYt9izX9iz2KjYqtmF2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmB2YXYqNixX9iv2YrYs9mF2KjYsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAn2KfZhNij2K3Yr1/Yp9mE2KXYq9mG2YrZhl/Yp9mE2KvZhNin2KvYp9ihX9in2YTYo9ix2KjYudin2KFf2KfZhNiu2YXZitizX9in2YTYrNmF2LnYqV/Yp9mE2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ9ij2K3Yr1/Ypdir2YbZitmGX9ir2YTYp9ir2KfYoV/Yo9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/YtXzZhS8sXG4gICAgICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiAn2YUnID09PSBpbnB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfYtSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2YUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9i62K/YpyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW9i52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAn2YHZiiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgICAgICBzIDogJ9ir2YjYp9mGJyxcbiAgICAgICAgICAgIHNzIDogJyVkINir2KfZhtmK2KknLFxuICAgICAgICAgICAgbSA6ICfYr9mC2YrZgtipJyxcbiAgICAgICAgICAgIG1tIDogJyVkINiv2YLYp9im2YInLFxuICAgICAgICAgICAgaCA6ICfYs9in2LnYqScsXG4gICAgICAgICAgICBoaCA6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgICAgIGQgOiAn2YrZiNmFJyxcbiAgICAgICAgICAgIGRkIDogJyVkINij2YrYp9mFJyxcbiAgICAgICAgICAgIE0gOiAn2LTZh9ixJyxcbiAgICAgICAgICAgIE1NIDogJyVkINij2LTZh9ixJyxcbiAgICAgICAgICAgIHkgOiAn2LPZhtipJyxcbiAgICAgICAgICAgIHl5IDogJyVkINiz2YbZiNin2KonXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vZodmi2aPZpNml2abZp9mo2anZoF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcFttYXRjaF07XG4gICAgICAgICAgICB9KS5yZXBsYWNlKC/YjC9nLCAnLCcpO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDFbbWF0Y2hdO1xuICAgICAgICAgICAgfSkucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2FyLXRuJywge1xuICAgICAgICBtb250aHM6ICfYrNin2YbZgdmKX9mB2YrZgdix2Ypf2YXYp9ix2LNf2KPZgdix2YrZhF/Zhdin2Ypf2KzZiNin2YZf2KzZiNmK2YTZitipX9ij2YjYql/Ys9io2KrZhdio2LFf2KPZg9iq2YjYqNixX9mG2YjZgdmF2KjYsV/Yr9mK2LPZhdio2LEnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn2KzYp9mG2YHZil/ZgdmK2YHYsdmKX9mF2KfYsdizX9ij2YHYsdmK2YRf2YXYp9mKX9is2YjYp9mGX9is2YjZitmE2YrYqV/Yo9mI2Kpf2LPYqNiq2YXYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YHZhdio2LFf2K/Zitiz2YXYqNixJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ9in2YTYo9it2K9f2KfZhNil2KvZhtmK2YZf2KfZhNir2YTYp9ir2KfYoV/Yp9mE2KPYsdio2LnYp9ihX9in2YTYrtmF2YrYs1/Yp9mE2KzZhdi52Klf2KfZhNiz2KjYqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ9ij2K3Yr1/Ypdir2YbZitmGX9ir2YTYp9ir2KfYoV/Yo9ix2KjYudin2KFf2K7ZhdmK2LNf2KzZhdi52Klf2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAn2YHZiiAlcycsXG4gICAgICAgICAgICBwYXN0OiAn2YXZhtiwICVzJyxcbiAgICAgICAgICAgIHM6ICfYq9mI2KfZhicsXG4gICAgICAgICAgICBzcyA6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgICAgIG06ICfYr9mC2YrZgtipJyxcbiAgICAgICAgICAgIG1tOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgICAgICBoOiAn2LPYp9i52KknLFxuICAgICAgICAgICAgaGg6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgICAgIGQ6ICfZitmI2YUnLFxuICAgICAgICAgICAgZGQ6ICclZCDYo9mK2KfZhScsXG4gICAgICAgICAgICBNOiAn2LTZh9ixJyxcbiAgICAgICAgICAgIE1NOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICAgICAgeTogJ9iz2YbYqScsXG4gICAgICAgICAgICB5eTogJyVkINiz2YbZiNin2KonXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJDIgPSB7XG4gICAgICAgICcxJzogJ9mhJyxcbiAgICAgICAgJzInOiAn2aInLFxuICAgICAgICAnMyc6ICfZoycsXG4gICAgICAgICc0JzogJ9mkJyxcbiAgICAgICAgJzUnOiAn2aUnLFxuICAgICAgICAnNic6ICfZpicsXG4gICAgICAgICc3JzogJ9mnJyxcbiAgICAgICAgJzgnOiAn2agnLFxuICAgICAgICAnOSc6ICfZqScsXG4gICAgICAgICcwJzogJ9mgJ1xuICAgIH0sIG51bWJlck1hcCQxID0ge1xuICAgICAgICAn2aEnOiAnMScsXG4gICAgICAgICfZoic6ICcyJyxcbiAgICAgICAgJ9mjJzogJzMnLFxuICAgICAgICAn2aQnOiAnNCcsXG4gICAgICAgICfZpSc6ICc1JyxcbiAgICAgICAgJ9mmJzogJzYnLFxuICAgICAgICAn2acnOiAnNycsXG4gICAgICAgICfZqCc6ICc4JyxcbiAgICAgICAgJ9mpJzogJzknLFxuICAgICAgICAn2aAnOiAnMCdcbiAgICB9LCBwbHVyYWxGb3JtJDEgPSBmdW5jdGlvbiAobikge1xuICAgICAgICByZXR1cm4gbiA9PT0gMCA/IDAgOiBuID09PSAxID8gMSA6IG4gPT09IDIgPyAyIDogbiAlIDEwMCA+PSAzICYmIG4gJSAxMDAgPD0gMTAgPyAzIDogbiAlIDEwMCA+PSAxMSA/IDQgOiA1O1xuICAgIH0sIHBsdXJhbHMkMSA9IHtcbiAgICAgICAgcyA6IFsn2KPZgtmEINmF2YYg2KvYp9mG2YrYqScsICfYq9in2YbZitipINmI2KfYrdiv2KknLCBbJ9ir2KfZhtmK2KrYp9mGJywgJ9ir2KfZhtmK2KrZitmGJ10sICclZCDYq9mI2KfZhicsICclZCDYq9in2YbZitipJywgJyVkINir2KfZhtmK2KknXSxcbiAgICAgICAgbSA6IFsn2KPZgtmEINmF2YYg2K/ZgtmK2YLYqScsICfYr9mC2YrZgtipINmI2KfYrdiv2KknLCBbJ9iv2YLZitmC2KrYp9mGJywgJ9iv2YLZitmC2KrZitmGJ10sICclZCDYr9mC2KfYptmCJywgJyVkINiv2YLZitmC2KknLCAnJWQg2K/ZgtmK2YLYqSddLFxuICAgICAgICBoIDogWyfYo9mC2YQg2YXZhiDYs9in2LnYqScsICfYs9in2LnYqSDZiNin2K3Yr9ipJywgWyfYs9in2LnYqtin2YYnLCAn2LPYp9i52KrZitmGJ10sICclZCDYs9in2LnYp9iqJywgJyVkINiz2KfYudipJywgJyVkINiz2KfYudipJ10sXG4gICAgICAgIGQgOiBbJ9ij2YLZhCDZhdmGINmK2YjZhScsICfZitmI2YUg2YjYp9it2K8nLCBbJ9mK2YjZhdin2YYnLCAn2YrZiNmF2YrZhiddLCAnJWQg2KPZitin2YUnLCAnJWQg2YrZiNmF2YvYpycsICclZCDZitmI2YUnXSxcbiAgICAgICAgTSA6IFsn2KPZgtmEINmF2YYg2LTZh9ixJywgJ9i02YfYsSDZiNin2K3YrycsIFsn2LTZh9ix2KfZhicsICfYtNmH2LHZitmGJ10sICclZCDYo9i02YfYsScsICclZCDYtNmH2LHYpycsICclZCDYtNmH2LEnXSxcbiAgICAgICAgeSA6IFsn2KPZgtmEINmF2YYg2LnYp9mFJywgJ9i52KfZhSDZiNin2K3YrycsIFsn2LnYp9mF2KfZhicsICfYudin2YXZitmGJ10sICclZCDYo9i52YjYp9mFJywgJyVkINi52KfZhdmL2KcnLCAnJWQg2LnYp9mFJ11cbiAgICB9LCBwbHVyYWxpemUkMSA9IGZ1bmN0aW9uICh1KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAobnVtYmVyLCB3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKSB7XG4gICAgICAgICAgICB2YXIgZiA9IHBsdXJhbEZvcm0kMShudW1iZXIpLFxuICAgICAgICAgICAgICAgIHN0ciA9IHBsdXJhbHMkMVt1XVtwbHVyYWxGb3JtJDEobnVtYmVyKV07XG4gICAgICAgICAgICBpZiAoZiA9PT0gMikge1xuICAgICAgICAgICAgICAgIHN0ciA9IHN0clt3aXRob3V0U3VmZml4ID8gMCA6IDFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8lZC9pLCBudW1iZXIpO1xuICAgICAgICB9O1xuICAgIH0sIG1vbnRocyQyID0gW1xuICAgICAgICAn2YrZhtin2YrYsScsXG4gICAgICAgICfZgdio2LHYp9mK2LEnLFxuICAgICAgICAn2YXYp9ix2LMnLFxuICAgICAgICAn2KPYqNix2YrZhCcsXG4gICAgICAgICfZhdin2YrZiCcsXG4gICAgICAgICfZitmI2YbZitmIJyxcbiAgICAgICAgJ9mK2YjZhNmK2YgnLFxuICAgICAgICAn2KPYutiz2LfYsycsXG4gICAgICAgICfYs9io2KrZhdio2LEnLFxuICAgICAgICAn2KPZg9iq2YjYqNixJyxcbiAgICAgICAgJ9mG2YjZgdmF2KjYsScsXG4gICAgICAgICfYr9mK2LPZhdio2LEnXG4gICAgXTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYXInLCB7XG4gICAgICAgIG1vbnRocyA6IG1vbnRocyQyLFxuICAgICAgICBtb250aHNTaG9ydCA6IG1vbnRocyQyLFxuICAgICAgICB3ZWVrZGF5cyA6ICfYp9mE2KPYrdivX9in2YTYpdir2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn2KPYrdivX9il2KvZhtmK2YZf2KvZhNin2KvYp9ihX9ij2LHYqNi52KfYoV/YrtmF2YrYs1/YrNmF2LnYqV/Ys9io2KonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0QvXFx1MjAwRk0vXFx1MjAwRllZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9i1fNmFLyxcbiAgICAgICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuICfZhScgPT09IGlucHV0O1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9i1JztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfZhSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb2LrYr9mL2Kcg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9ij2YXYsyDYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW9i52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ9io2LnYryAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgICAgICBzIDogcGx1cmFsaXplJDEoJ3MnKSxcbiAgICAgICAgICAgIHNzIDogcGx1cmFsaXplJDEoJ3MnKSxcbiAgICAgICAgICAgIG0gOiBwbHVyYWxpemUkMSgnbScpLFxuICAgICAgICAgICAgbW0gOiBwbHVyYWxpemUkMSgnbScpLFxuICAgICAgICAgICAgaCA6IHBsdXJhbGl6ZSQxKCdoJyksXG4gICAgICAgICAgICBoaCA6IHBsdXJhbGl6ZSQxKCdoJyksXG4gICAgICAgICAgICBkIDogcGx1cmFsaXplJDEoJ2QnKSxcbiAgICAgICAgICAgIGRkIDogcGx1cmFsaXplJDEoJ2QnKSxcbiAgICAgICAgICAgIE0gOiBwbHVyYWxpemUkMSgnTScpLFxuICAgICAgICAgICAgTU0gOiBwbHVyYWxpemUkMSgnTScpLFxuICAgICAgICAgICAgeSA6IHBsdXJhbGl6ZSQxKCd5JyksXG4gICAgICAgICAgICB5eSA6IHBsdXJhbGl6ZSQxKCd5JylcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW9mh2aLZo9mk2aXZptmn2ajZqdmgXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDFbbWF0Y2hdO1xuICAgICAgICAgICAgfSkucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQyW21hdGNoXTtcbiAgICAgICAgICAgIH0pLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiA2LCAvLyBTYXR1cmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDEydGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzdWZmaXhlcyA9IHtcbiAgICAgICAgMTogJy1pbmNpJyxcbiAgICAgICAgNTogJy1pbmNpJyxcbiAgICAgICAgODogJy1pbmNpJyxcbiAgICAgICAgNzA6ICctaW5jaScsXG4gICAgICAgIDgwOiAnLWluY2knLFxuICAgICAgICAyOiAnLW5jaScsXG4gICAgICAgIDc6ICctbmNpJyxcbiAgICAgICAgMjA6ICctbmNpJyxcbiAgICAgICAgNTA6ICctbmNpJyxcbiAgICAgICAgMzogJy3DvG5jw7wnLFxuICAgICAgICA0OiAnLcO8bmPDvCcsXG4gICAgICAgIDEwMDogJy3DvG5jw7wnLFxuICAgICAgICA2OiAnLW5jxLEnLFxuICAgICAgICA5OiAnLXVuY3UnLFxuICAgICAgICAxMDogJy11bmN1JyxcbiAgICAgICAgMzA6ICctdW5jdScsXG4gICAgICAgIDYwOiAnLcSxbmPEsScsXG4gICAgICAgIDkwOiAnLcSxbmPEsSdcbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdheicsIHtcbiAgICAgICAgbW9udGhzIDogJ3lhbnZhcl9mZXZyYWxfbWFydF9hcHJlbF9tYXlfaXl1bl9peXVsX2F2cXVzdF9zZW50eWFicl9va3R5YWJyX25veWFicl9kZWthYnInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ3lhbl9mZXZfbWFyX2Fwcl9tYXlfaXluX2l5bF9hdnFfc2VuX29rdF9ub3lfZGVrJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdCYXphcl9CYXphciBlcnTJmXNpX8OHyZlyxZ/JmW5iyZkgYXjFn2FtxLFfw4fJmXLFn8mZbmLJmV9Dw7xtyZkgYXjFn2FtxLFfQ8O8bcmZX8WeyZluYsmZJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ0Jhel9CekVfw4dBeF/Dh8mZcl9DQXhfQ8O8bV/FnsmZbicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnQnpfQkVfw4dBX8OHyZlfQ0FfQ8O8X8WeyZknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tidWfDvG4gc2FhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbc2FiYWggc2FhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnW2fJmWzJmW4gaMmZZnTJmV0gZGRkZCBbc2FhdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbZMO8bsmZbl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW2tlw6fJmW4gaMmZZnTJmV0gZGRkZCBbc2FhdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVzIHNvbnJhJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgyZl2dsmZbCcsXG4gICAgICAgICAgICBzIDogJ2Jpcm5lw6fJmSBzYW5pecmZJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNhbml5yZknLFxuICAgICAgICAgICAgbSA6ICdiaXIgZMmZcWlxyZknLFxuICAgICAgICAgICAgbW0gOiAnJWQgZMmZcWlxyZknLFxuICAgICAgICAgICAgaCA6ICdiaXIgc2FhdCcsXG4gICAgICAgICAgICBoaCA6ICclZCBzYWF0JyxcbiAgICAgICAgICAgIGQgOiAnYmlyIGfDvG4nLFxuICAgICAgICAgICAgZGQgOiAnJWQgZ8O8bicsXG4gICAgICAgICAgICBNIDogJ2JpciBheScsXG4gICAgICAgICAgICBNTSA6ICclZCBheScsXG4gICAgICAgICAgICB5IDogJ2JpciBpbCcsXG4gICAgICAgICAgICB5eSA6ICclZCBpbCdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL2dlY8mZfHPJmWjJmXJ8Z8O8bmTDvHp8YXjFn2FtLyxcbiAgICAgICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIC9eKGfDvG5kw7x6fGF4xZ9hbSkkLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2dlY8mZJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdzyZloyZlyJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdnw7xuZMO8eic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAnYXjFn2FtJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjEsW5jxLF8aW5jaXxuY2l8w7xuY8O8fG5jxLF8dW5jdSkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMCkgeyAgLy8gc3BlY2lhbCBjYXNlIGZvciB6ZXJvXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICctxLFuY8SxJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgYiA9IG51bWJlciAlIDEwMCAtIGEsXG4gICAgICAgICAgICAgICAgYyA9IG51bWJlciA+PSAxMDAgPyAxMDAgOiBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChzdWZmaXhlc1thXSB8fCBzdWZmaXhlc1tiXSB8fCBzdWZmaXhlc1tjXSk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcGx1cmFsKHdvcmQsIG51bSkge1xuICAgICAgICB2YXIgZm9ybXMgPSB3b3JkLnNwbGl0KCdfJyk7XG4gICAgICAgIHJldHVybiBudW0gJSAxMCA9PT0gMSAmJiBudW0gJSAxMDAgIT09IDExID8gZm9ybXNbMF0gOiAobnVtICUgMTAgPj0gMiAmJiBudW0gJSAxMCA8PSA0ICYmIChudW0gJSAxMDAgPCAxMCB8fCBudW0gJSAxMDAgPj0gMjApID8gZm9ybXNbMV0gOiBmb3Jtc1syXSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlbGF0aXZlVGltZVdpdGhQbHVyYWwobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgICAgICdzcyc6IHdpdGhvdXRTdWZmaXggPyAn0YHQtdC60YPQvdC00LBf0YHQtdC60YPQvdC00Ytf0YHQtdC60YPQvdC0JyA6ICfRgdC10LrRg9C90LTRg1/RgdC10LrRg9C90LTRi1/RgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgJ21tJzogd2l0aG91dFN1ZmZpeCA/ICfRhdCy0ZbQu9GW0L3QsF/RhdCy0ZbQu9GW0L3Ri1/RhdCy0ZbQu9GW0L0nIDogJ9GF0LLRltC70ZbQvdGDX9GF0LLRltC70ZbQvdGLX9GF0LLRltC70ZbQvScsXG4gICAgICAgICAgICAnaGgnOiB3aXRob3V0U3VmZml4ID8gJ9Cz0LDQtNC30ZbQvdCwX9Cz0LDQtNC30ZbQvdGLX9Cz0LDQtNC30ZbQvScgOiAn0LPQsNC00LfRltC90YNf0LPQsNC00LfRltC90Ytf0LPQsNC00LfRltC9JyxcbiAgICAgICAgICAgICdkZCc6ICfQtNC30LXQvdGMX9C00L3Rll/QtNC30ZHQvScsXG4gICAgICAgICAgICAnTU0nOiAn0LzQtdGB0Y/Rhl/QvNC10YHRj9GG0Ytf0LzQtdGB0Y/RhtCw0Z4nLFxuICAgICAgICAgICAgJ3l5JzogJ9Cz0L7QtF/Qs9Cw0LTRi1/Qs9Cw0LTQvtGeJ1xuICAgICAgICB9O1xuICAgICAgICBpZiAoa2V5ID09PSAnbScpIHtcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9GF0LLRltC70ZbQvdCwJyA6ICfRhdCy0ZbQu9GW0L3Rgyc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoa2V5ID09PSAnaCcpIHtcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9Cz0LDQtNC30ZbQvdCwJyA6ICfQs9Cw0LTQt9GW0L3Rgyc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgcGx1cmFsKGZvcm1hdFtrZXldLCArbnVtYmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYmUnLCB7XG4gICAgICAgIG1vbnRocyA6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ9GB0YLRg9C00LfQtdC90Y9f0LvRjtGC0LDQs9CwX9GB0LDQutCw0LLRltC60LBf0LrRgNCw0YHQsNCy0ZbQutCwX9GC0YDQsNGe0L3Rj1/Rh9GN0YDQstC10L3Rj1/Qu9GW0L/QtdC90Y9f0LbQvdGW0Z7QvdGPX9Cy0LXRgNCw0YHQvdGPX9C60LDRgdGC0YDRi9GH0L3RltC60LBf0LvRltGB0YLQsNC/0LDQtNCwX9GB0L3QtdC20L3Rjycuc3BsaXQoJ18nKSxcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICfRgdGC0YPQtNC30LXQvdGMX9C70Y7RgtGLX9GB0LDQutCw0LLRltC6X9C60YDQsNGB0LDQstGW0Lpf0YLRgNCw0LLQtdC90Yxf0YfRjdGA0LLQtdC90Yxf0LvRltC/0LXQvdGMX9C20L3RltCy0LXQvdGMX9Cy0LXRgNCw0YHQtdC90Yxf0LrQsNGB0YLRgNGL0YfQvdGW0Lpf0LvRltGB0YLQsNC/0LDQtF/RgdC90LXQttCw0L3RjCcuc3BsaXQoJ18nKVxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydCA6ICfRgdGC0YPQtF/Qu9GO0YJf0YHQsNC6X9C60YDQsNGBX9GC0YDQsNCyX9GH0Y3RgNCyX9C70ZbQv1/QttC90ZbQsl/QstC10YBf0LrQsNGB0YJf0LvRltGB0YJf0YHQvdC10LYnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDoge1xuICAgICAgICAgICAgZm9ybWF0OiAn0L3Rj9C00LfQtdC70Y5f0L/QsNC90Y/QtNC30LXQu9Cw0Lpf0LDRntGC0L7RgNCw0Lpf0YHQtdGA0LDQtNGDX9GH0LDRhtCy0LXRgF/Qv9GP0YLQvdGW0YbRg1/RgdGD0LHQvtGC0YMnLnNwbGl0KCdfJyksXG4gICAgICAgICAgICBzdGFuZGFsb25lOiAn0L3Rj9C00LfQtdC70Y9f0L/QsNC90Y/QtNC30LXQu9Cw0Lpf0LDRntGC0L7RgNCw0Lpf0YHQtdGA0LDQtNCwX9GH0LDRhtCy0LXRgF/Qv9GP0YLQvdGW0YbQsF/RgdGD0LHQvtGC0LAnLnNwbGl0KCdfJyksXG4gICAgICAgICAgICBpc0Zvcm1hdDogL1xcWyA/W9Cj0YPRnl0gPyg/OtC80ZbQvdGD0LvRg9GOfNC90LDRgdGC0YPQv9C90YPRjik/ID9cXF0gP2RkZGQvXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn0L3QtF/Qv9C9X9Cw0YJf0YHRgF/Rh9GGX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn0L3QtF/Qv9C9X9Cw0YJf0YHRgF/Rh9GGX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZINCzLicsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkg0LMuLCBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZINCzLiwgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vQodGR0L3QvdGPINGeXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9CX0LDRntGC0YDQsCDRnl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vQo9GH0L7RgNCwINGeXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW9CjXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CjINC80ZbQvdGD0LvRg9GOXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0KMg0LzRltC90YPQu9GLXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfQv9GA0LDQtyAlcycsXG4gICAgICAgICAgICBwYXN0IDogJyVzINGC0LDQvNGDJyxcbiAgICAgICAgICAgIHMgOiAn0L3QtdC60LDQu9GM0LrRliDRgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgbSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgICAgICBtbSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgICAgICBoIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgICAgIGhoIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgICAgIGQgOiAn0LTQt9C10L3RjCcsXG4gICAgICAgICAgICBkZCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgICAgICBNIDogJ9C80LXRgdGP0YYnLFxuICAgICAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICAgICAgeSA6ICfQs9C+0LQnLFxuICAgICAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/QvdC+0YfRi3zRgNCw0L3RltGG0Yt80LTQvdGPfNCy0LXRh9Cw0YDQsC8sXG4gICAgICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiAvXijQtNC90Y980LLQtdGH0LDRgNCwKSQvLnRlc3QoaW5wdXQpO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0L3QvtGH0YsnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9GA0LDQvdGW0YbRiyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0LTQvdGPJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfQstC10YfQsNGA0LAnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNGWfNGLfNCz0LApLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAobnVtYmVyICUgMTAgPT09IDIgfHwgbnVtYmVyICUgMTAgPT09IDMpICYmIChudW1iZXIgJSAxMDAgIT09IDEyICYmIG51bWJlciAlIDEwMCAhPT0gMTMpID8gbnVtYmVyICsgJy3RlicgOiBudW1iZXIgKyAnLdGLJztcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LPQsCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2JnJywge1xuICAgICAgICBtb250aHMgOiAn0Y/QvdGD0LDRgNC4X9GE0LXQstGA0YPQsNGA0Lhf0LzQsNGA0YJf0LDQv9GA0LjQu1/QvNCw0Llf0Y7QvdC4X9GO0LvQuF/QsNCy0LPRg9GB0YJf0YHQtdC/0YLQtdC80LLRgNC4X9C+0LrRgtC+0LzQstGA0Lhf0L3QvtC10LzQstGA0Lhf0LTQtdC60LXQvNCy0YDQuCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn0Y/QvdGAX9GE0LXQsl/QvNCw0YBf0LDQv9GAX9C80LDQuV/RjtC90Lhf0Y7Qu9C4X9Cw0LLQs1/RgdC10L9f0L7QutGCX9C90L7QtV/QtNC10LonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ9C90LXQtNC10LvRj1/Qv9C+0L3QtdC00LXQu9C90LjQul/QstGC0L7RgNC90LjQul/RgdGA0Y/QtNCwX9GH0LXRgtCy0YrRgNGC0YrQul/Qv9C10YLRitC6X9GB0YrQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfQvdC10LRf0L/QvtC9X9Cy0YLQvl/RgdGA0Y9f0YfQtdGCX9C/0LXRgl/RgdGK0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ9C90LRf0L/QvV/QstGCX9GB0YBf0YfRgl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0QuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb0JTQvdC10YEg0LJdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW9Cj0YLRgNC1INCyXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvQsl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb0JLRh9C10YDQsCDQsl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDQuNC30LzQuNC90LDQu9Cw0YLQsF0gZGRkZCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JIg0LjQt9C80LjQvdCw0LvQuNGPXSBkZGRkIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAn0YHQu9C10LQgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICfQv9GA0LXQtNC4ICVzJyxcbiAgICAgICAgICAgIHMgOiAn0L3Rj9C60L7Qu9C60L4g0YHQtdC60YPQvdC00LgnLFxuICAgICAgICAgICAgc3MgOiAnJWQg0YHQtdC60YPQvdC00LgnLFxuICAgICAgICAgICAgbSA6ICfQvNC40L3Rg9GC0LAnLFxuICAgICAgICAgICAgbW0gOiAnJWQg0LzQuNC90YPRgtC4JyxcbiAgICAgICAgICAgIGggOiAn0YfQsNGBJyxcbiAgICAgICAgICAgIGhoIDogJyVkINGH0LDRgdCwJyxcbiAgICAgICAgICAgIGQgOiAn0LTQtdC9JyxcbiAgICAgICAgICAgIGRkIDogJyVkINC00L3QuCcsXG4gICAgICAgICAgICBNIDogJ9C80LXRgdC10YYnLFxuICAgICAgICAgICAgTU0gOiAnJWQg0LzQtdGB0LXRhtCwJyxcbiAgICAgICAgICAgIHkgOiAn0LPQvtC00LjQvdCwJyxcbiAgICAgICAgICAgIHl5IDogJyVkINCz0L7QtNC40L3QuCdcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjQtdCyfNC10L180YLQuHzQstC4fNGA0Lh80LzQuCkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGxhc3REaWdpdCA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIGxhc3QyRGlnaXRzID0gbnVtYmVyICUgMTAwO1xuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC10LInO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0MkRpZ2l0cyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC10L0nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0MkRpZ2l0cyA+IDEwICYmIGxhc3QyRGlnaXRzIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3RgtC4JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGFzdERpZ2l0ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LLQuCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxhc3REaWdpdCA9PT0gMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGA0LgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0RGlnaXQgPT09IDcgfHwgbGFzdERpZ2l0ID09PSA4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LzQuCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYm0nLCB7XG4gICAgICAgIG1vbnRocyA6ICdaYW53dXlla2Fsb19GZXd1cnV5ZWthbG9fTWFyaXNpa2Fsb19Bd2lyaWxpa2Fsb19NyZtrYWxvX1p1d8mbbmthbG9fWnVsdXlla2Fsb19VdGlrYWxvX1PJm3RhbmJ1cnVrYWxvX8mUa3V0yZRidXJ1a2Fsb19Ob3dhbmJ1cnVrYWxvX0Rlc2FuYnVydWthbG8nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ1phbl9GZXdfTWFyX0F3aV9NyZtfWnV3X1p1bF9VdGlfU8mbdF/JlGt1X05vd19EZXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ0thcmlfTnTJm27Jm25fVGFyYXRhX0FyYWJhX0FsYW1pc2FfSnVtYV9TaWJpcmknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnS2FyX050yZtfVGFyX0FyYV9BbGFfSnVtX1NpYicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnS2FfTnRfVGFfQXJfQWxfSnVfU2knLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdNTU1NIFt0aWxlXSBEIFtzYW5dIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ01NTU0gW3RpbGVdIEQgW3Nhbl0gWVlZWSBbbMmbcsmbXSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgTU1NTSBbdGlsZV0gRCBbc2FuXSBZWVlZIFtsyZtyyZtdIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW0JpIGzJm3LJm10gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbU2luaSBsyZtyyZtdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2RvbiBsyZtyyZtdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW0t1bnUgbMmbcsmbXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFt0yZttyZtuZW4gbMmbcsmbXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnJXMga8mUbsmUJyxcbiAgICAgICAgICAgIHBhc3QgOiAnYSBiyZsgJXMgYsmUJyxcbiAgICAgICAgICAgIHMgOiAnc2FuZ2EgZGFtYSBkYW1hJyxcbiAgICAgICAgICAgIHNzIDogJ3Nla29uZGkgJWQnLFxuICAgICAgICAgICAgbSA6ICdtaW5pdGkga2VsZW4nLFxuICAgICAgICAgICAgbW0gOiAnbWluaXRpICVkJyxcbiAgICAgICAgICAgIGggOiAnbMmbcsmbIGtlbGVuJyxcbiAgICAgICAgICAgIGhoIDogJ2zJm3LJmyAlZCcsXG4gICAgICAgICAgICBkIDogJ3RpbGUga2VsZW4nLFxuICAgICAgICAgICAgZGQgOiAndGlsZSAlZCcsXG4gICAgICAgICAgICBNIDogJ2thbG8ga2VsZW4nLFxuICAgICAgICAgICAgTU0gOiAna2FsbyAlZCcsXG4gICAgICAgICAgICB5IDogJ3NhbiBrZWxlbicsXG4gICAgICAgICAgICB5eSA6ICdzYW4gJWQnXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCQzID0ge1xuICAgICAgICAnMSc6ICfgp6cnLFxuICAgICAgICAnMic6ICfgp6gnLFxuICAgICAgICAnMyc6ICfgp6knLFxuICAgICAgICAnNCc6ICfgp6onLFxuICAgICAgICAnNSc6ICfgp6snLFxuICAgICAgICAnNic6ICfgp6wnLFxuICAgICAgICAnNyc6ICfgp60nLFxuICAgICAgICAnOCc6ICfgp64nLFxuICAgICAgICAnOSc6ICfgp68nLFxuICAgICAgICAnMCc6ICfgp6YnXG4gICAgfSxcbiAgICBudW1iZXJNYXAkMiA9IHtcbiAgICAgICAgJ+Cnpyc6ICcxJyxcbiAgICAgICAgJ+CnqCc6ICcyJyxcbiAgICAgICAgJ+CnqSc6ICczJyxcbiAgICAgICAgJ+Cnqic6ICc0JyxcbiAgICAgICAgJ+Cnqyc6ICc1JyxcbiAgICAgICAgJ+CnrCc6ICc2JyxcbiAgICAgICAgJ+CnrSc6ICc3JyxcbiAgICAgICAgJ+Cnric6ICc4JyxcbiAgICAgICAgJ+Cnryc6ICc5JyxcbiAgICAgICAgJ+Cnpic6ICcwJ1xuICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2JuJywge1xuICAgICAgICBtb250aHMgOiAn4Kac4Ka+4Kao4KeB4Kef4Ka+4Kaw4KeAX+Cmq+Cnh+CmrOCnjeCmsOCngeCnn+CmvuCmsOCmv1/gpq7gpr7gprDgp43gpppf4KaP4Kaq4KeN4Kaw4Ka/4KayX+CmruCnh1/gppzgp4Hgpqhf4Kac4KeB4Kay4Ka+4KaHX+CmhuCml+CmuOCnjeCmn1/gprjgp4fgpqrgp43gpp/gp4fgpq7gp43gpqzgprBf4KaF4KaV4KeN4Kaf4KeL4Kas4KawX+CmqOCmreCnh+CmruCnjeCmrOCmsF/gpqHgpr/gprjgp4fgpq7gp43gpqzgprAnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ+CmnOCmvuCmqOCngV/gpqvgp4fgpqxf4Kau4Ka+4Kaw4KeN4KaaX+Cmj+CmquCnjeCmsF/gpq7gp4df4Kac4KeB4KaoX+CmnOCngeCmsl/gpobgppdf4Ka44KeH4Kaq4KeN4KafX+CmheCmleCnjeCmn+Cni1/gpqjgpq3gp4df4Kah4Ka/4Ka44KeHJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfgprDgpqzgpr/gpqzgpr7gprBf4Ka44KeL4Kau4Kas4Ka+4KawX+CmruCmmeCnjeCml+CmsuCmrOCmvuCmsF/gpqzgp4Hgpqfgpqzgpr7gprBf4Kas4KeD4Ka54Ka44KeN4Kaq4Kak4Ka/4Kas4Ka+4KawX+CmtuCngeCmleCnjeCmsOCmrOCmvuCmsF/gprbgpqjgpr/gpqzgpr7gprAnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn4Kaw4Kas4Ka/X+CmuOCni+Cmrl/gpq7gppngp43gppfgprJf4Kas4KeB4KanX+CmrOCng+CmueCmuOCnjeCmquCmpOCmv1/gprbgp4HgppXgp43gprBf4Ka24Kao4Ka/Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfgprDgpqzgpr9f4Ka44KeL4KauX+CmruCmmeCnjeCml1/gpqzgp4Hgpqdf4Kas4KeD4Ka54KaDX+CmtuCngeCmleCnjeCmsF/gprbgpqjgpr8nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnQSBoOm1tIOCmuOCmruCnnycsXG4gICAgICAgICAgICBMVFMgOiAnQSBoOm1tOnNzIOCmuOCmruCnnycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0g4Ka44Kau4KefJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgprjgpq7gp58nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb4KaG4KacXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vgpobgppfgpr7gpq7gp4DgppXgpr7gprJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW+Cml+CmpOCmleCmvuCmsl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW+Cml+CmpF0gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVzIOCmquCmsOCnhycsXG4gICAgICAgICAgICBwYXN0IDogJyVzIOCmhuCml+CnhycsXG4gICAgICAgICAgICBzIDogJ+CmleCnn+Cnh+CmlSDgprjgp4fgppXgp4fgpqjgp43gpqEnLFxuICAgICAgICAgICAgc3MgOiAnJWQg4Ka44KeH4KaV4KeH4Kao4KeN4KahJyxcbiAgICAgICAgICAgIG0gOiAn4KaP4KaVIOCmruCmv+CmqOCmv+CmnycsXG4gICAgICAgICAgICBtbSA6ICclZCDgpq7gpr/gpqjgpr/gpp8nLFxuICAgICAgICAgICAgaCA6ICfgpo/gppUg4KaY4Kao4KeN4Kaf4Ka+JyxcbiAgICAgICAgICAgIGhoIDogJyVkIOCmmOCmqOCnjeCmn+CmvicsXG4gICAgICAgICAgICBkIDogJ+Cmj+CmlSDgpqbgpr/gpqgnLFxuICAgICAgICAgICAgZGQgOiAnJWQg4Kam4Ka/4KaoJyxcbiAgICAgICAgICAgIE0gOiAn4KaP4KaVIOCmruCmvuCmuCcsXG4gICAgICAgICAgICBNTSA6ICclZCDgpq7gpr7gprgnLFxuICAgICAgICAgICAgeSA6ICfgpo/gppUg4Kas4Kab4KawJyxcbiAgICAgICAgICAgIHl5IDogJyVkIOCmrOCmm+CmsCdcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Cnp+CnqOCnqeCnquCnq+CnrOCnreCnruCnr+Cnpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCQyW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDNbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gprDgpr7gpqR84Ka44KaV4Ka+4KayfOCmpuCngeCmquCngeCmsHzgpqzgpr/gppXgpr7gprJ84Kaw4Ka+4KakLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgobWVyaWRpZW0gPT09ICfgprDgpr7gpqQnICYmIGhvdXIgPj0gNCkgfHxcbiAgICAgICAgICAgICAgICAgICAgKG1lcmlkaWVtID09PSAn4Kam4KeB4Kaq4KeB4KawJyAmJiBob3VyIDwgNSkgfHxcbiAgICAgICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfgpqzgpr/gppXgpr7gprInKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgprDgpr7gpqQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CmuOCmleCmvuCmsic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kam4KeB4Kaq4KeB4KawJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpqzgpr/gppXgpr7gprInO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CmsOCmvuCmpCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCQ0ID0ge1xuICAgICAgICAnMSc6ICfgvKEnLFxuICAgICAgICAnMic6ICfgvKInLFxuICAgICAgICAnMyc6ICfgvKMnLFxuICAgICAgICAnNCc6ICfgvKQnLFxuICAgICAgICAnNSc6ICfgvKUnLFxuICAgICAgICAnNic6ICfgvKYnLFxuICAgICAgICAnNyc6ICfgvKcnLFxuICAgICAgICAnOCc6ICfgvKgnLFxuICAgICAgICAnOSc6ICfgvKknLFxuICAgICAgICAnMCc6ICfgvKAnXG4gICAgfSxcbiAgICBudW1iZXJNYXAkMyA9IHtcbiAgICAgICAgJ+C8oSc6ICcxJyxcbiAgICAgICAgJ+C8oic6ICcyJyxcbiAgICAgICAgJ+C8oyc6ICczJyxcbiAgICAgICAgJ+C8pCc6ICc0JyxcbiAgICAgICAgJ+C8pSc6ICc1JyxcbiAgICAgICAgJ+C8pic6ICc2JyxcbiAgICAgICAgJ+C8pyc6ICc3JyxcbiAgICAgICAgJ+C8qCc6ICc4JyxcbiAgICAgICAgJ+C8qSc6ICc5JyxcbiAgICAgICAgJ+C8oCc6ICcwJ1xuICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2JvJywge1xuICAgICAgICBtb250aHMgOiAn4L2f4L6z4LyL4L2W4LyL4L2R4L2E4LyL4L2U4L28X+C9n+C+s+C8i+C9luC8i+C9guC9ieC9suC9puC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvYLgvabgvbTgvZjgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2e4L2y4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9o+C+lOC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZHgvrLgvbTgvYLgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2R4L204L2T4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9luC9ouC+kuC+seC9keC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZHgvYLgvbTgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2F4L204LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9luC9heC9tOC8i+C9guC9heC9suC9guC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvYXgvbTgvIvgvYLgvYngvbLgvabgvIvgvZQnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ+C9n+C+s+C8i+C9luC8i+C9keC9hOC8i+C9lOC9vF/gvZ/gvrPgvIvgvZbgvIvgvYLgvYngvbLgvabgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2C4L2m4L204L2Y4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9luC9nuC9suC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvaPgvpTgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2R4L6y4L204L2C4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9luC9keC9tOC9k+C8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvaLgvpLgvrHgvZHgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2R4L2C4L204LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9luC9heC9tOC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvYXgvbTgvIvgvYLgvYXgvbLgvYLgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2F4L204LyL4L2C4L2J4L2y4L2m4LyL4L2UJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfgvYLgvZ/gvaDgvIvgvYngvbLgvIvgvZjgvItf4L2C4L2f4L2g4LyL4L2f4L6z4LyL4L2W4LyLX+C9guC9n+C9oOC8i+C9mOC9suC9guC8i+C9keC9mOC9ouC8i1/gvYLgvZ/gvaDgvIvgvaPgvrfgvYLgvIvgvZTgvItf4L2C4L2f4L2g4LyL4L2V4L204L2i4LyL4L2W4L20X+C9guC9n+C9oOC8i+C9lOC8i+C9puC9hOC9puC8i1/gvYLgvZ/gvaDgvIvgvabgvqTgvbrgvZPgvIvgvZTgvIsnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn4L2J4L2y4LyL4L2Y4LyLX+C9n+C+s+C8i+C9luC8i1/gvZjgvbLgvYLgvIvgvZHgvZjgvaLgvItf4L2j4L634L2C4LyL4L2U4LyLX+C9leC9tOC9ouC8i+C9luC9tF/gvZTgvIvgvabgvYTgvabgvItf4L2m4L6k4L264L2T4LyL4L2U4LyLJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfgvYngvbLgvIvgvZjgvItf4L2f4L6z4LyL4L2W4LyLX+C9mOC9suC9guC8i+C9keC9mOC9ouC8i1/gvaPgvrfgvYLgvIvgvZTgvItf4L2V4L204L2i4LyL4L2W4L20X+C9lOC8i+C9puC9hOC9puC8i1/gvabgvqTgvbrgvZPgvIvgvZTgvIsnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnQSBoOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdBIGg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1vgvZHgvbLgvIvgvaLgvbLgvYRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW+C9puC9hOC8i+C9ieC9suC9k10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnW+C9luC9keC9tOC9k+C8i+C9leC+suC9guC8i+C9ouC+l+C9uuC9puC8i+C9mF0sIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW+C9geC8i+C9puC9hF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW+C9luC9keC9tOC9k+C8i+C9leC+suC9guC8i+C9mOC9kOC9oOC8i+C9mF0gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVzIOC9o+C8iycsXG4gICAgICAgICAgICBwYXN0IDogJyVzIOC9puC+lOC9k+C8i+C9oycsXG4gICAgICAgICAgICBzIDogJ+C9o+C9mOC8i+C9puC9hCcsXG4gICAgICAgICAgICBzcyA6ICclZCDgvabgvpDgvaLgvIvgvYbgvI0nLFxuICAgICAgICAgICAgbSA6ICfgvabgvpDgvaLgvIvgvZjgvIvgvYLgvYXgvbLgvYInLFxuICAgICAgICAgICAgbW0gOiAnJWQg4L2m4L6Q4L2i4LyL4L2YJyxcbiAgICAgICAgICAgIGggOiAn4L2G4L204LyL4L2a4L284L2R4LyL4L2C4L2F4L2y4L2CJyxcbiAgICAgICAgICAgIGhoIDogJyVkIOC9huC9tOC8i+C9muC9vOC9kScsXG4gICAgICAgICAgICBkIDogJ+C9ieC9suC9k+C8i+C9guC9heC9suC9gicsXG4gICAgICAgICAgICBkZCA6ICclZCDgvYngvbLgvZPgvIsnLFxuICAgICAgICAgICAgTSA6ICfgvZ/gvrPgvIvgvZbgvIvgvYLgvYXgvbLgvYInLFxuICAgICAgICAgICAgTU0gOiAnJWQg4L2f4L6z4LyL4L2WJyxcbiAgICAgICAgICAgIHkgOiAn4L2j4L284LyL4L2C4L2F4L2y4L2CJyxcbiAgICAgICAgICAgIHl5IDogJyVkIOC9o+C9vCdcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+C8oeC8ouC8o+C8pOC8peC8puC8p+C8qOC8qeC8oF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCQzW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDRbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gvZjgvZrgvZPgvIvgvZjgvbx84L2e4L284L2C4L2m4LyL4L2A4L2mfOC9ieC9suC9k+C8i+C9guC9tOC9hHzgvZHgvYLgvbzgvYTgvIvgvZHgvYJ84L2Y4L2a4L2T4LyL4L2Y4L28LyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgobWVyaWRpZW0gPT09ICfgvZjgvZrgvZPgvIvgvZjgvbwnICYmIGhvdXIgPj0gNCkgfHxcbiAgICAgICAgICAgICAgICAgICAgKG1lcmlkaWVtID09PSAn4L2J4L2y4L2T4LyL4L2C4L204L2EJyAmJiBob3VyIDwgNSkgfHxcbiAgICAgICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfgvZHgvYLgvbzgvYTgvIvgvZHgvYInKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgvZjgvZrgvZPgvIvgvZjgvbwnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C9nuC9vOC9guC9puC8i+C9gOC9pic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4L2J4L2y4L2T4LyL4L2C4L204L2EJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgvZHgvYLgvbzgvYTgvIvgvZHgvYInO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C9mOC9muC9k+C8i+C9mOC9vCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aE11dGF0aW9uKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICAnbW0nOiAnbXVudXRlbm4nLFxuICAgICAgICAgICAgJ01NJzogJ21peicsXG4gICAgICAgICAgICAnZGQnOiAnZGV2ZXpoJ1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgbXV0YXRpb24oZm9ybWF0W2tleV0sIG51bWJlcik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNwZWNpYWxNdXRhdGlvbkZvclllYXJzKG51bWJlcikge1xuICAgICAgICBzd2l0Y2ggKGxhc3ROdW1iZXIobnVtYmVyKSkge1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgY2FzZSA5OlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnIGJsb2F6JztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgdmxvYXonO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGxhc3ROdW1iZXIobnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPiA5KSB7XG4gICAgICAgICAgICByZXR1cm4gbGFzdE51bWJlcihudW1iZXIgJSAxMCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gbXV0YXRpb24odGV4dCwgbnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgIHJldHVybiBzb2Z0TXV0YXRpb24odGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNvZnRNdXRhdGlvbih0ZXh0KSB7XG4gICAgICAgIHZhciBtdXRhdGlvblRhYmxlID0ge1xuICAgICAgICAgICAgJ20nOiAndicsXG4gICAgICAgICAgICAnYic6ICd2JyxcbiAgICAgICAgICAgICdkJzogJ3onXG4gICAgICAgIH07XG4gICAgICAgIGlmIChtdXRhdGlvblRhYmxlW3RleHQuY2hhckF0KDApXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbXV0YXRpb25UYWJsZVt0ZXh0LmNoYXJBdCgwKV0gKyB0ZXh0LnN1YnN0cmluZygxKTtcbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2JyJywge1xuICAgICAgICBtb250aHMgOiAnR2VudmVyX0NcXCdod2V2cmVyX01ldXJ6aF9FYnJlbF9NYWVfTWV6aGV2ZW5fR291ZXJlX0Vvc3RfR3dlbmdvbG9fSGVyZV9EdV9LZXJ6dScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnR2VuX0NcXCdod2VfTWV1X0Vicl9NYWVfRXZlX0dvdV9Fb3NfR3dlX0hlcl9EdV9LZXInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ1N1bF9MdW5fTWV1cnpoX01lcmNcXCdoZXJfWWFvdV9Hd2VuZXJfU2Fkb3JuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ1N1bF9MdW5fTWV1X01lcl9ZYW9fR3dlX1NhZCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnU3VfTHVfTWVfTWVyX1lhX0d3X1NhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ2hbZV1tbSBBJyxcbiAgICAgICAgICAgIExUUyA6ICdoW2VdbW06c3MgQScsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBbYSB2aXpdIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBbYSB2aXpdIE1NTU0gWVlZWSBoW2VdbW0gQScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgW2Egdml6XSBNTU1NIFlZWVkgaFtlXW1tIEEnXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbSGl6aXYgZGFdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW1dhcmNcXCdob2F6aCBkYV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbZGFdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW0RlY1xcJ2ggZGFdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW3Bhc2V0IGRhXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnYS1iZW5uICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgXFwnem8nLFxuICAgICAgICAgICAgcyA6ICd1biBuZWJldWQgc2Vnb25kZW5ub8O5JyxcbiAgICAgICAgICAgIHNzIDogJyVkIGVpbGVubicsXG4gICAgICAgICAgICBtIDogJ3VyIHZ1bnV0ZW5uJyxcbiAgICAgICAgICAgIG1tIDogcmVsYXRpdmVUaW1lV2l0aE11dGF0aW9uLFxuICAgICAgICAgICAgaCA6ICd1biBldXInLFxuICAgICAgICAgICAgaGggOiAnJWQgZXVyJyxcbiAgICAgICAgICAgIGQgOiAndW4gZGV2ZXpoJyxcbiAgICAgICAgICAgIGRkIDogcmVsYXRpdmVUaW1lV2l0aE11dGF0aW9uLFxuICAgICAgICAgICAgTSA6ICd1ciBtaXonLFxuICAgICAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoTXV0YXRpb24sXG4gICAgICAgICAgICB5IDogJ3VyIGJsb2F6JyxcbiAgICAgICAgICAgIHl5IDogc3BlY2lhbE11dGF0aW9uRm9yWWVhcnNcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGHDsXx2ZXQpLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSAobnVtYmVyID09PSAxKSA/ICdhw7EnIDogJ3ZldCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmRhJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kZSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmRpJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2plZG5hIG1pbnV0YScgOiAnamVkbmUgbWludXRlJztcbiAgICAgICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRhJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRlJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21pbnV0YSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdqZWRhbiBzYXQnIDogJ2plZG5vZyBzYXRhJztcbiAgICAgICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2F0JztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2F0YSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXRpJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZGFuJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2RhbmEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWMnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWNhJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21qZXNlY2knO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmUnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZ29kaW5hJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnYnMnLCB7XG4gICAgICAgIG1vbnRocyA6ICdqYW51YXJfZmVicnVhcl9tYXJ0X2FwcmlsX21hal9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJhcl9va3RvYmFyX25vdmVtYmFyX2RlY2VtYmFyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdqYW4uX2ZlYi5fbWFyLl9hcHIuX21hai5fanVuLl9qdWwuX2F1Zy5fc2VwLl9va3QuX25vdi5fZGVjLicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXMgOiAnbmVkamVsamFfcG9uZWRqZWxqYWtfdXRvcmFrX3NyaWplZGFfxI1ldHZydGFrX3BldGFrX3N1Ym90YScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICduZWQuX3Bvbi5fdXRvLl9zcmkuX8SNZXQuX3BldC5fc3ViLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnbmVfcG9fdXRfc3JfxI1lX3BlX3N1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5ICA6ICdbZGFuYXMgdV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSAgOiAnW3N1dHJhIHVdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbbmVkamVsanVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzcmlqZWR1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbc3Vib3R1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXkgIDogJ1tqdcSNZXIgdV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsdV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcm/FoWxlXSBbc3Vib3RlXSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcm/FoWxpXSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICd6YSAlcycsXG4gICAgICAgICAgICBwYXN0ICAgOiAncHJpamUgJXMnLFxuICAgICAgICAgICAgcyAgICAgIDogJ3BhciBzZWt1bmRpJyxcbiAgICAgICAgICAgIHNzICAgICA6IHRyYW5zbGF0ZSxcbiAgICAgICAgICAgIG0gICAgICA6IHRyYW5zbGF0ZSxcbiAgICAgICAgICAgIG1tICAgICA6IHRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGggICAgICA6IHRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGhoICAgICA6IHRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGQgICAgICA6ICdkYW4nLFxuICAgICAgICAgICAgZGQgICAgIDogdHJhbnNsYXRlLFxuICAgICAgICAgICAgTSAgICAgIDogJ21qZXNlYycsXG4gICAgICAgICAgICBNTSAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgICAgICB5ICAgICAgOiAnZ29kaW51JyxcbiAgICAgICAgICAgIHl5ICAgICA6IHRyYW5zbGF0ZVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdjYScsIHtcbiAgICAgICAgbW9udGhzIDoge1xuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ2dlbmVyX2ZlYnJlcl9tYXLDp19hYnJpbF9tYWlnX2p1bnlfanVsaW9sX2Fnb3N0X3NldGVtYnJlX29jdHVicmVfbm92ZW1icmVfZGVzZW1icmUnLnNwbGl0KCdfJyksXG4gICAgICAgICAgICBmb3JtYXQ6ICdkZSBnZW5lcl9kZSBmZWJyZXJfZGUgbWFyw6dfZFxcJ2FicmlsX2RlIG1haWdfZGUganVueV9kZSBqdWxpb2xfZFxcJ2Fnb3N0X2RlIHNldGVtYnJlX2RcXCdvY3R1YnJlX2RlIG5vdmVtYnJlX2RlIGRlc2VtYnJlJy5zcGxpdCgnXycpLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IC9EW29EXT8oXFxzKStNTU1NL1xuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydCA6ICdnZW4uX2ZlYnIuX21hcsOnX2Fici5fbWFpZ19qdW55X2p1bC5fYWcuX3NldC5fb2N0Ll9ub3YuX2Rlcy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdkaXVtZW5nZV9kaWxsdW5zX2RpbWFydHNfZGltZWNyZXNfZGlqb3VzX2RpdmVuZHJlc19kaXNzYWJ0ZScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdkZy5fZGwuX2R0Ll9kYy5fZGouX2R2Ll9kcy4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ2RnX2RsX2R0X2RjX2RqX2R2X2RzJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBbZGVdIFlZWVknLFxuICAgICAgICAgICAgbGwgOiAnRCBNTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFtkZV0gWVlZWSBbYSBsZXNdIEg6bW0nLFxuICAgICAgICAgICAgbGxsIDogJ0QgTU1NIFlZWVksIEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBbZGVdIFlZWVkgW2EgbGVzXSBIOm1tJyxcbiAgICAgICAgICAgIGxsbGwgOiAnZGRkIEQgTU1NIFlZWVksIEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1thdnVpIGEgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdsZXMnIDogJ2xhJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dERheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1tkZW3DoCBhICcgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAnbGVzJyA6ICdsYScpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZGRkZCBbYSAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ2xlcycgOiAnbGEnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2FoaXIgYSAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ2xlcycgOiAnbGEnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1tlbF0gZGRkZCBbcGFzc2F0IGEgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdsZXMnIDogJ2xhJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2RcXCdhcXXDrSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ2ZhICVzJyxcbiAgICAgICAgICAgIHMgOiAndW5zIHNlZ29ucycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWdvbnMnLFxuICAgICAgICAgICAgbSA6ICd1biBtaW51dCcsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dHMnLFxuICAgICAgICAgICAgaCA6ICd1bmEgaG9yYScsXG4gICAgICAgICAgICBoaCA6ICclZCBob3JlcycsXG4gICAgICAgICAgICBkIDogJ3VuIGRpYScsXG4gICAgICAgICAgICBkZCA6ICclZCBkaWVzJyxcbiAgICAgICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG1lc29zJyxcbiAgICAgICAgICAgIHkgOiAndW4gYW55JyxcbiAgICAgICAgICAgIHl5IDogJyVkIGFueXMnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShyfG58dHzDqHxhKS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSAobnVtYmVyID09PSAxKSA/ICdyJyA6XG4gICAgICAgICAgICAgICAgKG51bWJlciA9PT0gMikgPyAnbicgOlxuICAgICAgICAgICAgICAgIChudW1iZXIgPT09IDMpID8gJ3InIDpcbiAgICAgICAgICAgICAgICAobnVtYmVyID09PSA0KSA/ICd0JyA6ICfDqCc7XG4gICAgICAgICAgICBpZiAocGVyaW9kID09PSAndycgfHwgcGVyaW9kID09PSAnVycpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAnYSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBtb250aHMkMyA9ICdsZWRlbl/Dum5vcl9ixZllemVuX2R1YmVuX2t2xJt0ZW5fxI1lcnZlbl/EjWVydmVuZWNfc3JwZW5fesOhxZnDrV/FmcOtamVuX2xpc3RvcGFkX3Byb3NpbmVjJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA9ICdsZWRfw7pub19ixZllX2R1Yl9rdsSbX8SNdm5fxI12Y19zcnBfesOhxZlfxZnDrWpfbGlzX3Bybycuc3BsaXQoJ18nKTtcblxuICAgIHZhciBtb250aHNQYXJzZSA9IFsvXmxlZC9pLCAvXsO6bm8vaSwgL15ixZllL2ksIC9eZHViL2ksIC9ea3bEmy9pLCAvXijEjXZufMSNZXJ2ZW4kfMSNZXJ2bmEpL2ksIC9eKMSNdmN8xI1lcnZlbmVjfMSNZXJ2ZW5jZSkvaSwgL15zcnAvaSwgL156w6HFmS9pLCAvXsWZw61qL2ksIC9ebGlzL2ksIC9ecHJvL2ldO1xuICAgIC8vIE5PVEU6ICfEjWVydmVuJyBpcyBzdWJzdHJpbmcgb2YgJ8SNZXJ2ZW5lYyc7IHRoZXJlZm9yZSAnxI1lcnZlbmVjJyBtdXN0IHByZWNlZGUgJ8SNZXJ2ZW4nIGluIHRoZSByZWdleCB0byBiZSBmdWxseSBtYXRjaGVkLlxuICAgIC8vIE90aGVyd2lzZSBwYXJzZXIgbWF0Y2hlcyAnMS4gxI1lcnZlbmVjJyBhcyAnMS4gxI1lcnZlbicgKyAnZWMnLlxuICAgIHZhciBtb250aHNSZWdleCQxID0gL14obGVkZW58w7pub3J8YsWZZXplbnxkdWJlbnxrdsSbdGVufMSNZXJ2ZW5lY3zEjWVydmVuY2V8xI1lcnZlbnzEjWVydm5hfHNycGVufHrDocWZw618xZnDrWplbnxsaXN0b3BhZHxwcm9zaW5lY3xsZWR8w7pub3xixZllfGR1YnxrdsSbfMSNdm58xI12Y3xzcnB8esOhxZl8xZnDrWp8bGlzfHBybykvaTtcblxuICAgIGZ1bmN0aW9uIHBsdXJhbCQxKG4pIHtcbiAgICAgICAgcmV0dXJuIChuID4gMSkgJiYgKG4gPCA1KSAmJiAofn4obiAvIDEwKSAhPT0gMSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZSQxKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAncyc6ICAvLyBhIGZldyBzZWNvbmRzIC8gaW4gYSBmZXcgc2Vjb25kcyAvIGEgZmV3IHNlY29uZHMgYWdvXG4gICAgICAgICAgICAgICAgcmV0dXJuICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSA/ICdww6FyIHNla3VuZCcgOiAncMOhciBzZWt1bmRhbWknO1xuICAgICAgICAgICAgY2FzZSAnc3MnOiAvLyA5IHNlY29uZHMgLyBpbiA5IHNlY29uZHMgLyA5IHNlY29uZHMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ3Nla3VuZHknIDogJ3Nla3VuZCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnc2VrdW5kYW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtJzogIC8vIGEgbWludXRlIC8gaW4gYSBtaW51dGUgLyBhIG1pbnV0ZSBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdtaW51dGEnIDogKGlzRnV0dXJlID8gJ21pbnV0dScgOiAnbWludXRvdScpO1xuICAgICAgICAgICAgY2FzZSAnbW0nOiAvLyA5IG1pbnV0ZXMgLyBpbiA5IG1pbnV0ZXMgLyA5IG1pbnV0ZXMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ21pbnV0eScgOiAnbWludXQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ21pbnV0YW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdoJzogIC8vIGFuIGhvdXIgLyBpbiBhbiBob3VyIC8gYW4gaG91ciBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdob2RpbmEnIDogKGlzRnV0dXJlID8gJ2hvZGludScgOiAnaG9kaW5vdScpO1xuICAgICAgICAgICAgY2FzZSAnaGgnOiAvLyA5IGhvdXJzIC8gaW4gOSBob3VycyAvIDkgaG91cnMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMShudW1iZXIpID8gJ2hvZGlueScgOiAnaG9kaW4nKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2hvZGluYW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkJzogIC8vIGEgZGF5IC8gaW4gYSBkYXkgLyBhIGRheSBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpID8gJ2RlbicgOiAnZG5lbSc7XG4gICAgICAgICAgICBjYXNlICdkZCc6IC8vIDkgZGF5cyAvIGluIDkgZGF5cyAvIDkgZGF5cyBhZ29cbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQxKG51bWJlcikgPyAnZG55JyA6ICdkbsOtJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdkbnknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ00nOiAgLy8gYSBtb250aCAvIGluIGEgbW9udGggLyBhIG1vbnRoIGFnb1xuICAgICAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAnbcSbc8OtYycgOiAnbcSbc8OtY2VtJztcbiAgICAgICAgICAgIGNhc2UgJ01NJzogLy8gOSBtb250aHMgLyBpbiA5IG1vbnRocyAvIDkgbW9udGhzIGFnb1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDEobnVtYmVyKSA/ICdtxJtzw61jZScgOiAnbcSbc8OtY8WvJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdtxJtzw61jaSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAneSc6ICAvLyBhIHllYXIgLyBpbiBhIHllYXIgLyBhIHllYXIgYWdvXG4gICAgICAgICAgICAgICAgcmV0dXJuICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSA/ICdyb2snIDogJ3Jva2VtJztcbiAgICAgICAgICAgIGNhc2UgJ3l5JzogLy8gOSB5ZWFycyAvIGluIDkgeWVhcnMgLyA5IHllYXJzIGFnb1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDEobnVtYmVyKSA/ICdyb2t5JyA6ICdsZXQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2xldHknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnY3MnLCB7XG4gICAgICAgIG1vbnRocyA6IG1vbnRocyQzLFxuICAgICAgICBtb250aHNTaG9ydCA6IG1vbnRoc1Nob3J0LFxuICAgICAgICBtb250aHNSZWdleCA6IG1vbnRoc1JlZ2V4JDEsXG4gICAgICAgIG1vbnRoc1Nob3J0UmVnZXggOiBtb250aHNSZWdleCQxLFxuICAgICAgICAvLyBOT1RFOiAnxI1lcnZlbicgaXMgc3Vic3RyaW5nIG9mICfEjWVydmVuZWMnOyB0aGVyZWZvcmUgJ8SNZXJ2ZW5lYycgbXVzdCBwcmVjZWRlICfEjWVydmVuJyBpbiB0aGUgcmVnZXggdG8gYmUgZnVsbHkgbWF0Y2hlZC5cbiAgICAgICAgLy8gT3RoZXJ3aXNlIHBhcnNlciBtYXRjaGVzICcxLiDEjWVydmVuZWMnIGFzICcxLiDEjWVydmVuJyArICdlYycuXG4gICAgICAgIG1vbnRoc1N0cmljdFJlZ2V4IDogL14obGVkZW58bGVkbmF8w7pub3JhfMO6bm9yfGLFmWV6ZW58YsWZZXpuYXxkdWJlbnxkdWJuYXxrdsSbdGVufGt2xJt0bmF8xI1lcnZlbmVjfMSNZXJ2ZW5jZXzEjWVydmVufMSNZXJ2bmF8c3JwZW58c3JwbmF8esOhxZnDrXzFmcOtamVufMWZw61qbmF8bGlzdG9wYWR1fGxpc3RvcGFkfHByb3NpbmVjfHByb3NpbmNlKS9pLFxuICAgICAgICBtb250aHNTaG9ydFN0cmljdFJlZ2V4IDogL14obGVkfMO6bm98YsWZZXxkdWJ8a3bEm3zEjXZufMSNdmN8c3JwfHrDocWZfMWZw61qfGxpc3xwcm8pL2ksXG4gICAgICAgIG1vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UsXG4gICAgICAgIGxvbmdNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlLFxuICAgICAgICBzaG9ydE1vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UsXG4gICAgICAgIHdlZWtkYXlzIDogJ25lZMSbbGVfcG9uZMSbbMOtX8O6dGVyw71fc3TFmWVkYV/EjXR2cnRla19ww6F0ZWtfc29ib3RhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ25lX3BvX8O6dF9zdF/EjXRfcMOhX3NvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICduZV9wb1/DunRfc3RfxI10X3DDoV9zbycuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIEQuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIGwgOiAnRC4gTS4gWVlZWSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2RuZXMgdl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1t6w610cmEgdl0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBuZWTEm2xpIHZdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBkZGRkIFt2XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZlIHN0xZllZHUgdl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2ZSDEjXR2cnRlayB2XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3YgcMOhdGVrIHZdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBzb2JvdHUgdl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5OiAnW3bEjWVyYSB2XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bG91IG5lZMSbbGkgdl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw6ldIGRkZGQgW3ZdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWxvdSBzdMWZZWR1IHZdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO9XSBkZGRkIFt2XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsb3Ugc29ib3R1IHZdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnemEgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICdwxZllZCAlcycsXG4gICAgICAgICAgICBzIDogdHJhbnNsYXRlJDEsXG4gICAgICAgICAgICBzcyA6IHRyYW5zbGF0ZSQxLFxuICAgICAgICAgICAgbSA6IHRyYW5zbGF0ZSQxLFxuICAgICAgICAgICAgbW0gOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgICAgIGggOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgICAgIGhoIDogdHJhbnNsYXRlJDEsXG4gICAgICAgICAgICBkIDogdHJhbnNsYXRlJDEsXG4gICAgICAgICAgICBkZCA6IHRyYW5zbGF0ZSQxLFxuICAgICAgICAgICAgTSA6IHRyYW5zbGF0ZSQxLFxuICAgICAgICAgICAgTU0gOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgICAgIHkgOiB0cmFuc2xhdGUkMSxcbiAgICAgICAgICAgIHl5IDogdHJhbnNsYXRlJDFcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2N2Jywge1xuICAgICAgICBtb250aHMgOiAn0LrTkdGA0LvQsNGHX9C90LDRgNOR0YFf0L/Rg9GIX9Cw0LrQsF/QvNCw0Llf0qvTl9GA0YLQvNC1X9GD0YLTkV/Sq9GD0YDQu9CwX9Cw0LLTkdC9X9GO0L/QsF/Rh9Oz0Lpf0YDQsNGI0YLQsNCyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICfQutOR0YBf0L3QsNGAX9C/0YPRiF/QsNC60LBf0LzQsNC5X9Kr05fRgF/Rg9GC05Ff0qvRg9GAX9Cw0LLQvV/RjtC/0LBf0YfTs9C6X9GA0LDRiCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAn0LLRi9GA0YHQsNGA0L3QuNC60YPQvV/RgtGD0L3RgtC40LrRg9C9X9GL0YLQu9Cw0YDQuNC60YPQvV/RjtC90LrRg9C9X9C605fSq9C90LXRgNC90LjQutGD0L1f0Y3RgNC90LXQutGD0L1f0YjTkdC80LDRgtC60YPQvScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfQstGL0YBf0YLRg9C9X9GL0YLQu1/RjtC9X9C605fSq1/RjdGA0L1f0YjTkdC8Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfQstGAX9GC0L1f0YvRgl/RjtC9X9C60qtf0Y3RgF/RiNC8Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELU1NLVlZWVknLFxuICAgICAgICAgICAgTEwgOiAnWVlZWSBb0qvRg9C70YXQuF0gTU1NTSBb0YPQudOR0YXTl9C9XSBEWy3QvNOX0YjTl10nLFxuICAgICAgICAgICAgTExMIDogJ1lZWVkgW9Kr0YPQu9GF0LhdIE1NTU0gW9GD0LnTkdGF05fQvV0gRFst0LzTl9GI05ddLCBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIFlZWVkgW9Kr0YPQu9GF0LhdIE1NTU0gW9GD0LnTkdGF05fQvV0gRFst0LzTl9GI05ddLCBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9Cf0LDRj9C9XSBMVCBb0YHQtdGF0LXRgtGA0LVdJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb0KvRgNCw0L1dIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1vTltC90LXRgF0gTFQgW9GB0LXRhdC10YLRgNC1XScsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1vSqtC40YLQtdGBXSBkZGRkIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdb0JjRgNGC0L3Tl10gZGRkZCBMVCBb0YHQtdGF0LXRgtGA0LVdJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogZnVuY3Rpb24gKG91dHB1dCkge1xuICAgICAgICAgICAgICAgIHZhciBhZmZpeCA9IC/RgdC10YXQtdGCJC9pLmV4ZWMob3V0cHV0KSA/ICfRgNC10L0nIDogL9Kr0YPQuyQvaS5leGVjKG91dHB1dCkgPyAn0YLQsNC9JyA6ICfRgNCw0L0nO1xuICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQgKyBhZmZpeDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYXN0IDogJyVzINC60LDRj9C70LvQsCcsXG4gICAgICAgICAgICBzIDogJ9C/05fRgC3QuNC6INKr0LXQutC60YPQvdGCJyxcbiAgICAgICAgICAgIHNzIDogJyVkINKr0LXQutC60YPQvdGCJyxcbiAgICAgICAgICAgIG0gOiAn0L/Tl9GAINC80LjQvdGD0YInLFxuICAgICAgICAgICAgbW0gOiAnJWQg0LzQuNC90YPRgicsXG4gICAgICAgICAgICBoIDogJ9C/05fRgCDRgdC10YXQtdGCJyxcbiAgICAgICAgICAgIGhoIDogJyVkINGB0LXRhdC10YInLFxuICAgICAgICAgICAgZCA6ICfQv9OX0YAg0LrRg9C9JyxcbiAgICAgICAgICAgIGRkIDogJyVkINC60YPQvScsXG4gICAgICAgICAgICBNIDogJ9C/05fRgCDRg9C505HRhScsXG4gICAgICAgICAgICBNTSA6ICclZCDRg9C505HRhScsXG4gICAgICAgICAgICB5IDogJ9C/05fRgCDSq9GD0LsnLFxuICAgICAgICAgICAgeXkgOiAnJWQg0qvRg9C7J1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0t0LzTl9GILyxcbiAgICAgICAgb3JkaW5hbCA6ICclZC3QvNOX0YgnLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnY3knLCB7XG4gICAgICAgIG1vbnRoczogJ0lvbmF3cl9DaHdlZnJvcl9NYXdydGhfRWJyaWxsX01haV9NZWhlZmluX0dvcmZmZW5uYWZfQXdzdF9NZWRpX0h5ZHJlZl9UYWNod2VkZF9SaGFnZnlyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydDogJ0lvbl9DaHdlX01hd19FYnJfTWFpX01laF9Hb3JfQXdzX01lZF9IeWRfVGFjaF9SaGFnJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ0R5ZGQgU3VsX0R5ZGQgTGx1bl9EeWRkIE1hd3J0aF9EeWRkIE1lcmNoZXJfRHlkZCBJYXVfRHlkZCBHd2VuZXJfRHlkZCBTYWR3cm4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICdTdWxfTGx1bl9NYXdfTWVyX0lhdV9Hd2VfU2FkJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1N1X0xsX01hX01lX0lhX0d3X1NhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICAvLyB0aW1lIGZvcm1hdHMgYXJlIHRoZSBzYW1lIGFzIGVuLWdiXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSGVkZGl3IGFtXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW1lmb3J5IGFtXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2FtXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0Rkb2UgYW1dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnZGRkZCBbZGl3ZXRoYWYgYW1dIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICdtZXduICVzJyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyB5biDDtGwnLFxuICAgICAgICAgICAgczogJ3ljaHlkaWcgZWlsaWFkYXUnLFxuICAgICAgICAgICAgc3M6ICclZCBlaWxpYWQnLFxuICAgICAgICAgICAgbTogJ211bnVkJyxcbiAgICAgICAgICAgIG1tOiAnJWQgbXVudWQnLFxuICAgICAgICAgICAgaDogJ2F3cicsXG4gICAgICAgICAgICBoaDogJyVkIGF3cicsXG4gICAgICAgICAgICBkOiAnZGl3cm5vZCcsXG4gICAgICAgICAgICBkZDogJyVkIGRpd3Jub2QnLFxuICAgICAgICAgICAgTTogJ21pcycsXG4gICAgICAgICAgICBNTTogJyVkIG1pcycsXG4gICAgICAgICAgICB5OiAnYmx3eWRkeW4nLFxuICAgICAgICAgICAgeXk6ICclZCBmbHluZWRkJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZmVkfGFpbnxhZnxpbHx5ZGR8ZWR8ZWcpLyxcbiAgICAgICAgLy8gdHJhZGl0aW9uYWwgb3JkaW5hbCBudW1iZXJzIGFib3ZlIDMxIGFyZSBub3QgY29tbW9ubHkgdXNlZCBpbiBjb2xsb3F1aWFsIFdlbHNoXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyLFxuICAgICAgICAgICAgICAgIG91dHB1dCA9ICcnLFxuICAgICAgICAgICAgICAgIGxvb2t1cCA9IFtcbiAgICAgICAgICAgICAgICAgICAgJycsICdhZicsICdpbCcsICd5ZGQnLCAneWRkJywgJ2VkJywgJ2VkJywgJ2VkJywgJ2ZlZCcsICdmZWQnLCAnZmVkJywgLy8gMWFmIHRvIDEwZmVkXG4gICAgICAgICAgICAgICAgICAgICdlZycsICdmZWQnLCAnZWcnLCAnZWcnLCAnZmVkJywgJ2VnJywgJ2VnJywgJ2ZlZCcsICdlZycsICdmZWQnIC8vIDExZWcgdG8gMjBmZWRcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgaWYgKGIgPiAyMCkge1xuICAgICAgICAgICAgICAgIGlmIChiID09PSA0MCB8fCBiID09PSA1MCB8fCBiID09PSA2MCB8fCBiID09PSA4MCB8fCBiID09PSAxMDApIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gJ2ZlZCc7IC8vIG5vdCAzMGFpbiwgNzBhaW4gb3IgOTBhaW5cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgPSAnYWluJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGIgPiAwKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gbG9va3VwW2JdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2RhJywge1xuICAgICAgICBtb250aHMgOiAnamFudWFyX2ZlYnJ1YXJfbWFydHNfYXByaWxfbWFqX2p1bmlfanVsaV9hdWd1c3Rfc2VwdGVtYmVyX29rdG9iZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYWpfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdzw7huZGFnX21hbmRhZ190aXJzZGFnX29uc2RhZ190b3JzZGFnX2ZyZWRhZ19sw7hyZGFnJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ3PDuG5fbWFuX3Rpcl9vbnNfdG9yX2ZyZV9sw7hyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdzw7hfbWFfdGlfb25fdG9fZnJfbMO4Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIFtkLl0gRC4gTU1NTSBZWVlZIFtrbC5dIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW2kgZGFnIGtsLl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbaSBtb3JnZW4ga2wuXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdww6UgZGRkZCBba2wuXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tpIGfDpXIga2wuXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbaV0gZGRkZFtzIGtsLl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ29tICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgc2lkZW4nLFxuICAgICAgICAgICAgcyA6ICdmw6Ugc2VrdW5kZXInLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2VrdW5kZXInLFxuICAgICAgICAgICAgbSA6ICdldCBtaW51dCcsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dHRlcicsXG4gICAgICAgICAgICBoIDogJ2VuIHRpbWUnLFxuICAgICAgICAgICAgaGggOiAnJWQgdGltZXInLFxuICAgICAgICAgICAgZCA6ICdlbiBkYWcnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGFnZScsXG4gICAgICAgICAgICBNIDogJ2VuIG3DpW5lZCcsXG4gICAgICAgICAgICBNTSA6ICclZCBtw6VuZWRlcicsXG4gICAgICAgICAgICB5IDogJ2V0IMOlcicsXG4gICAgICAgICAgICB5eSA6ICclZCDDpXInXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgJ20nOiBbJ2VpbmUgTWludXRlJywgJ2VpbmVyIE1pbnV0ZSddLFxuICAgICAgICAgICAgJ2gnOiBbJ2VpbmUgU3R1bmRlJywgJ2VpbmVyIFN0dW5kZSddLFxuICAgICAgICAgICAgJ2QnOiBbJ2VpbiBUYWcnLCAnZWluZW0gVGFnJ10sXG4gICAgICAgICAgICAnZGQnOiBbbnVtYmVyICsgJyBUYWdlJywgbnVtYmVyICsgJyBUYWdlbiddLFxuICAgICAgICAgICAgJ00nOiBbJ2VpbiBNb25hdCcsICdlaW5lbSBNb25hdCddLFxuICAgICAgICAgICAgJ01NJzogW251bWJlciArICcgTW9uYXRlJywgbnVtYmVyICsgJyBNb25hdGVuJ10sXG4gICAgICAgICAgICAneSc6IFsnZWluIEphaHInLCAnZWluZW0gSmFociddLFxuICAgICAgICAgICAgJ3l5JzogW251bWJlciArICcgSmFocmUnLCBudW1iZXIgKyAnIEphaHJlbiddXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gZm9ybWF0W2tleV1bMF0gOiBmb3JtYXRba2V5XVsxXTtcbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2RlLWF0Jywge1xuICAgICAgICBtb250aHMgOiAnSsOkbm5lcl9GZWJydWFyX03DpHJ6X0FwcmlsX01haV9KdW5pX0p1bGlfQXVndXN0X1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0RlemVtYmVyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKw6RuLl9GZWIuX03DpHJ6X0Fwci5fTWFpX0p1bmlfSnVsaV9BdWcuX1NlcC5fT2t0Ll9Ob3YuX0Rlei4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdTb25udGFnX01vbnRhZ19EaWVuc3RhZ19NaXR0d29jaF9Eb25uZXJzdGFnX0ZyZWl0YWdfU2Ftc3RhZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTby5fTW8uX0RpLl9NaS5fRG8uX0ZyLl9TYS4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1NvX01vX0RpX01pX0RvX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbaGV1dGUgdW1dIExUIFtVaHJdJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1tnZXN0ZXJuIHVtXSBMVCBbVWhyXScsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tsZXR6dGVuXSBkZGRkIFt1bV0gTFQgW1Vocl0nXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ3ZvciAlcycsXG4gICAgICAgICAgICBzIDogJ2VpbiBwYWFyIFNla3VuZGVuJyxcbiAgICAgICAgICAgIHNzIDogJyVkIFNla3VuZGVuJyxcbiAgICAgICAgICAgIG0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICAgICAgbW0gOiAnJWQgTWludXRlbicsXG4gICAgICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgICAgIGhoIDogJyVkIFN0dW5kZW4nLFxuICAgICAgICAgICAgZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgICAgICBkZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgICAgICBNIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgICAgIE1NIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICAgICAgeXkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lJDEobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICAnbSc6IFsnZWluZSBNaW51dGUnLCAnZWluZXIgTWludXRlJ10sXG4gICAgICAgICAgICAnaCc6IFsnZWluZSBTdHVuZGUnLCAnZWluZXIgU3R1bmRlJ10sXG4gICAgICAgICAgICAnZCc6IFsnZWluIFRhZycsICdlaW5lbSBUYWcnXSxcbiAgICAgICAgICAgICdkZCc6IFtudW1iZXIgKyAnIFRhZ2UnLCBudW1iZXIgKyAnIFRhZ2VuJ10sXG4gICAgICAgICAgICAnTSc6IFsnZWluIE1vbmF0JywgJ2VpbmVtIE1vbmF0J10sXG4gICAgICAgICAgICAnTU0nOiBbbnVtYmVyICsgJyBNb25hdGUnLCBudW1iZXIgKyAnIE1vbmF0ZW4nXSxcbiAgICAgICAgICAgICd5JzogWydlaW4gSmFocicsICdlaW5lbSBKYWhyJ10sXG4gICAgICAgICAgICAneXknOiBbbnVtYmVyICsgJyBKYWhyZScsIG51bWJlciArICcgSmFocmVuJ11cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZGUtY2gnLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW51YXJfRmVicnVhcl9Nw6Ryel9BcHJpbF9NYWlfSnVuaV9KdWxpX0F1Z3VzdF9TZXB0ZW1iZXJfT2t0b2Jlcl9Ob3ZlbWJlcl9EZXplbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnSmFuLl9GZWIuX03DpHJ6X0Fwci5fTWFpX0p1bmlfSnVsaV9BdWcuX1NlcC5fT2t0Ll9Ob3YuX0Rlei4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdTb25udGFnX01vbnRhZ19EaWVuc3RhZ19NaXR0d29jaF9Eb25uZXJzdGFnX0ZyZWl0YWdfU2Ftc3RhZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTb19Nb19EaV9NaV9Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnU29fTW9fRGlfTWlfRG9fRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBELiBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1toZXV0ZSB1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbbW9yZ2VuIHVtXSBMVCBbVWhyXScsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3VtXSBMVCBbVWhyXScsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW2dlc3Rlcm4gdW1dIExUIFtVaHJdJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW2xldHp0ZW5dIGRkZGQgW3VtXSBMVCBbVWhyXSdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAndm9yICVzJyxcbiAgICAgICAgICAgIHMgOiAnZWluIHBhYXIgU2VrdW5kZW4nLFxuICAgICAgICAgICAgc3MgOiAnJWQgU2VrdW5kZW4nLFxuICAgICAgICAgICAgbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIG1tIDogJyVkIE1pbnV0ZW4nLFxuICAgICAgICAgICAgaCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIGhoIDogJyVkIFN0dW5kZW4nLFxuICAgICAgICAgICAgZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIGRkIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQxLFxuICAgICAgICAgICAgTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIE1NIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQxLFxuICAgICAgICAgICAgeSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMSxcbiAgICAgICAgICAgIHl5IDogcHJvY2Vzc1JlbGF0aXZlVGltZSQxXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICAnbSc6IFsnZWluZSBNaW51dGUnLCAnZWluZXIgTWludXRlJ10sXG4gICAgICAgICAgICAnaCc6IFsnZWluZSBTdHVuZGUnLCAnZWluZXIgU3R1bmRlJ10sXG4gICAgICAgICAgICAnZCc6IFsnZWluIFRhZycsICdlaW5lbSBUYWcnXSxcbiAgICAgICAgICAgICdkZCc6IFtudW1iZXIgKyAnIFRhZ2UnLCBudW1iZXIgKyAnIFRhZ2VuJ10sXG4gICAgICAgICAgICAnTSc6IFsnZWluIE1vbmF0JywgJ2VpbmVtIE1vbmF0J10sXG4gICAgICAgICAgICAnTU0nOiBbbnVtYmVyICsgJyBNb25hdGUnLCBudW1iZXIgKyAnIE1vbmF0ZW4nXSxcbiAgICAgICAgICAgICd5JzogWydlaW4gSmFocicsICdlaW5lbSBKYWhyJ10sXG4gICAgICAgICAgICAneXknOiBbbnVtYmVyICsgJyBKYWhyZScsIG51bWJlciArICcgSmFocmVuJ11cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZGUnLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW51YXJfRmVicnVhcl9Nw6Ryel9BcHJpbF9NYWlfSnVuaV9KdWxpX0F1Z3VzdF9TZXB0ZW1iZXJfT2t0b2Jlcl9Ob3ZlbWJlcl9EZXplbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnSmFuLl9GZWIuX03DpHJ6X0Fwci5fTWFpX0p1bmlfSnVsaV9BdWcuX1NlcC5fT2t0Ll9Ob3YuX0Rlei4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdTb25udGFnX01vbnRhZ19EaWVuc3RhZ19NaXR0d29jaF9Eb25uZXJzdGFnX0ZyZWl0YWdfU2Ftc3RhZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTby5fTW8uX0RpLl9NaS5fRG8uX0ZyLl9TYS4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1NvX01vX0RpX01pX0RvX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbaGV1dGUgdW1dIExUIFtVaHJdJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt1bV0gTFQgW1Vocl0nLFxuICAgICAgICAgICAgbGFzdERheTogJ1tnZXN0ZXJuIHVtXSBMVCBbVWhyXScsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tsZXR6dGVuXSBkZGRkIFt1bV0gTFQgW1Vocl0nXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ3ZvciAlcycsXG4gICAgICAgICAgICBzIDogJ2VpbiBwYWFyIFNla3VuZGVuJyxcbiAgICAgICAgICAgIHNzIDogJyVkIFNla3VuZGVuJyxcbiAgICAgICAgICAgIG0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIsXG4gICAgICAgICAgICBtbSA6ICclZCBNaW51dGVuJyxcbiAgICAgICAgICAgIGggOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIsXG4gICAgICAgICAgICBoaCA6ICclZCBTdHVuZGVuJyxcbiAgICAgICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIsXG4gICAgICAgICAgICBkZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMixcbiAgICAgICAgICAgIE0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIsXG4gICAgICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMixcbiAgICAgICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDIsXG4gICAgICAgICAgICB5eSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMlxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRocyQ0ID0gW1xuICAgICAgICAn3pberN6C3qreh96m3oPeqScsXG4gICAgICAgICfeit6s3oTesN6D3qreh96m3oPeqScsXG4gICAgICAgICfeid6n3oPeqN6X3qonLFxuICAgICAgICAn3oferd6V3rDeg96p3o3eqicsXG4gICAgICAgICfeid6tJyxcbiAgICAgICAgJ96W3qvegt6wJyxcbiAgICAgICAgJ96W3qrejd6m3ofeqCcsXG4gICAgICAgICfeh96v3o7ept6Q3rDek96qJyxcbiAgICAgICAgJ96Q3qzeld6w3pPerN6J3rDehN6m3oPeqicsXG4gICAgICAgICfeh96u3obesN6T3q/ehN6m3oPeqicsXG4gICAgICAgICfegt6u3ojerN6J3rDehN6m3oPeqicsXG4gICAgICAgICfekd6o3pDerN6J3rDehN6m3oPeqidcbiAgICBdLCB3ZWVrZGF5cyA9IFtcbiAgICAgICAgJ96H3qfei96o3ofesN6M3qYnLFxuICAgICAgICAn3oDer96J3qYnLFxuICAgICAgICAn3ofept6C3rDejt6n3oPepicsXG4gICAgICAgICfehN6q3ovepicsXG4gICAgICAgICfehN6q3oPep96Q3rDeit6m3ozeqCcsXG4gICAgICAgICfegN6q3obeqt6D3qonLFxuICAgICAgICAn3oDert6C3qjegN6o3oPeqidcbiAgICBdO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdkdicsIHtcbiAgICAgICAgbW9udGhzIDogbW9udGhzJDQsXG4gICAgICAgIG1vbnRoc1Nob3J0IDogbW9udGhzJDQsXG4gICAgICAgIHdlZWtkYXlzIDogd2Vla2RheXMsXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiB3ZWVrZGF5cyxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn3ofep96L3qhf3oDer96J3qZf3ofept6C3rBf3oTeqt6L3qZf3oTeqt6D3qdf3oDeqt6G3qpf3oDert6C3qgnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuXG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdEL00vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv3onehnzeid6KLyxcbiAgICAgICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuICfeid6KJyA9PT0gaW5wdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn3onehic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn3oneiic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb3oneqN6H3qbei96qXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1veid6n3ovept6J3qddIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb3ofeqN6H3rDelN6sXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdb3orep96H3qjejN6q3ojeqF0gZGRkZCBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAn3ozerN6D3q3ejt6m3ofeqCAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ96G3qreg96o3oLesCAlcycsXG4gICAgICAgICAgICBzIDogJ96Q3qjeht6q3oLesN6M3qreht6u3oXerN6H3rAnLFxuICAgICAgICAgICAgc3MgOiAnZCUg3pDeqN6G3qregt6w3ozeqicsXG4gICAgICAgICAgICBtIDogJ96J3qjegt6o3pPerN6H3rAnLFxuICAgICAgICAgICAgbW0gOiAn3oneqN6C3qjek96qICVkJyxcbiAgICAgICAgICAgIGggOiAn3o7ept6R3qjeh96o3oPerN6H3rAnLFxuICAgICAgICAgICAgaGggOiAn3o7ept6R3qjeh96o3oPeqiAlZCcsXG4gICAgICAgICAgICBkIDogJ96L3qreiN6m3oDerN6H3rAnLFxuICAgICAgICAgICAgZGQgOiAn3oveqt6I3qbekN6wICVkJyxcbiAgICAgICAgICAgIE0gOiAn3onept6A3qzeh96wJyxcbiAgICAgICAgICAgIE1NIDogJ96J3qbekN6wICVkJyxcbiAgICAgICAgICAgIHkgOiAn3ofept6A3qbeg96s3ofesCcsXG4gICAgICAgICAgICB5eSA6ICfeh96m3oDept6D3qogJWQnXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDcsICAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDEyICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxMnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2VsJywge1xuICAgICAgICBtb250aHNOb21pbmF0aXZlRWwgOiAnzpnOsc69zr/Phc6sz4HOuc6/z4JfzqbOtc6yz4HOv8+FzqzPgc65zr/Pgl/OnM6sz4HPhM65zr/Pgl/Okc+Az4HOr867zrnOv8+CX86czqzOuc6/z4JfzpnOv8+Nzr3Ouc6/z4JfzpnOv8+NzrvOuc6/z4JfzpHPjc6zzr/Phc+Dz4TOv8+CX86jzrXPgM+Ezq3OvM6yz4HOuc6/z4Jfzp/Ous+Ez47Oss+BzrnOv8+CX86dzr/Orc68zrLPgc65zr/Pgl/OlM61zrrOrc68zrLPgc65zr/Pgicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzR2VuaXRpdmVFbCA6ICfOmc6xzr3Ov8+FzrHPgc6vzr/PhV/Ops61zrLPgc6/z4XOsc+Bzq/Ov8+FX86czrHPgc+Ezq/Ov8+FX86Rz4DPgc65zrvOr86/z4VfzpzOsc6Qzr/PhV/Omc6/z4XOvc6vzr/PhV/Omc6/z4XOu86vzr/PhV/Okc+FzrPOv8+Nz4PPhM6/z4VfzqPOtc+Az4TOtc68zrLPgc6vzr/PhV/On866z4TPic6yz4HOr86/z4Vfzp3Ov861zrzOss+Bzq/Ov8+FX86UzrXOus61zrzOss+Bzq/Ov8+FJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHMgOiBmdW5jdGlvbiAobW9tZW50VG9Gb3JtYXQsIGZvcm1hdCkge1xuICAgICAgICAgICAgaWYgKCFtb21lbnRUb0Zvcm1hdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNOb21pbmF0aXZlRWw7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmb3JtYXQgPT09ICdzdHJpbmcnICYmIC9ELy50ZXN0KGZvcm1hdC5zdWJzdHJpbmcoMCwgZm9ybWF0LmluZGV4T2YoJ01NTU0nKSkpKSB7IC8vIGlmIHRoZXJlIGlzIGEgZGF5IG51bWJlciBiZWZvcmUgJ01NTU0nXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21vbnRoc0dlbml0aXZlRWxbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNOb21pbmF0aXZlRWxbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ86ZzrHOvV/Ops61zrJfzpzOsc+BX86Rz4DPgV/OnM6xz4pfzpnOv8+Fzr1fzpnOv8+FzrtfzpHPhc6zX86jzrXPgF/On866z4Rfzp3Ov861X86UzrXOuicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnzprPhc+BzrnOsc66zq5fzpTOtc+Fz4TOrc+BzrFfzqTPgc6vz4TOt1/OpM61z4TOrM+Bz4TOt1/OoM6tzrzPgM+EzrdfzqDOsc+BzrHPg866zrXPhc6uX86jzqzOss6yzrHPhM6/Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ86az4XPgV/OlM61z4VfzqTPgc65X86kzrXPhF/OoM61zrxfzqDOsc+BX86jzrHOsicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnzprPhV/OlM61X86kz4FfzqTOtV/OoM61X86gzrFfzqPOsScuc3BsaXQoJ18nKSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VycyA+IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnzrzOvCcgOiAnzpzOnCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ8+AzrwnIDogJ86gzpwnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gKChpbnB1dCArICcnKS50b0xvd2VyQ2FzZSgpWzBdID09PSAnzrwnKTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZSA6IC9bzqDOnF1cXC4/zpw/XFwuPy9pLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ2g6bW0gQScsXG4gICAgICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhckVsIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbzqPOrs68zrXPgc6xIHt9XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vOkc+Nz4HOuc6/IHt9XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFt7fV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbzqfOuM61z4Ige31dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vPhM6/IM+Az4HOv863zrPOv8+NzrzOtc69zr9dIGRkZGQgW3t9XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vPhM63zr0gz4DPgc6/zrfOs86/z43OvM61zr3Ot10gZGRkZCBbe31dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiBmdW5jdGlvbiAoa2V5LCBtb20pIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSB0aGlzLl9jYWxlbmRhckVsW2tleV0sXG4gICAgICAgICAgICAgICAgaG91cnMgPSBtb20gJiYgbW9tLmhvdXJzKCk7XG4gICAgICAgICAgICBpZiAoaXNGdW5jdGlvbihvdXRwdXQpKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gb3V0cHV0LmFwcGx5KG1vbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0cHV0LnJlcGxhY2UoJ3t9JywgKGhvdXJzICUgMTIgPT09IDEgPyAnz4PPhM63JyA6ICfPg8+EzrnPgicpKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ8+DzrUgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyDPgM+BzrnOvScsXG4gICAgICAgICAgICBzIDogJ867zq/Os86xIM60zrXPhc+EzrXPgc+MzrvOtc+Az4TOsScsXG4gICAgICAgICAgICBzcyA6ICclZCDOtM61z4XPhM61z4HPjM67zrXPgM+EzrEnLFxuICAgICAgICAgICAgbSA6ICfOrc69zrEgzrvOtc+Az4TPjCcsXG4gICAgICAgICAgICBtbSA6ICclZCDOu861z4DPhM6sJyxcbiAgICAgICAgICAgIGggOiAnzrzOr86xIM+Oz4HOsScsXG4gICAgICAgICAgICBoaCA6ICclZCDPjs+BzrXPgicsXG4gICAgICAgICAgICBkIDogJ868zq/OsSDOvM6tz4HOsScsXG4gICAgICAgICAgICBkZCA6ICclZCDOvM6tz4HOtc+CJyxcbiAgICAgICAgICAgIE0gOiAnzq3Ovc6xz4IgzrzOrs69zrHPgicsXG4gICAgICAgICAgICBNTSA6ICclZCDOvM6uzr3Otc+CJyxcbiAgICAgICAgICAgIHkgOiAnzq3Ovc6xz4Igz4fPgc+Mzr3Ov8+CJyxcbiAgICAgICAgICAgIHl5IDogJyVkIM+Hz4HPjM69zrnOsSdcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9zrcvLFxuICAgICAgICBvcmRpbmFsOiAnJWTOtycsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDRzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlbi1TRycsIHtcbiAgICAgICAgbW9udGhzIDogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW1RvbW9ycm93IGF0XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbTGFzdF0gZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgICAgICBzIDogJ2EgZmV3IHNlY29uZHMnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2Vjb25kcycsXG4gICAgICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaCA6ICdhbiBob3VyJyxcbiAgICAgICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgICAgIGQgOiAnYSBkYXknLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGF5cycsXG4gICAgICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbW9udGhzJyxcbiAgICAgICAgICAgIHkgOiAnYSB5ZWFyJyxcbiAgICAgICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAndGgnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMykgPyAncmQnIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlbi1hdScsIHtcbiAgICAgICAgbW9udGhzIDogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ2g6bW0gQScsXG4gICAgICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW1RvZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1tUb21vcnJvdyBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW1llc3RlcmRheSBhdF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW0xhc3RdIGRkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyBhZ28nLFxuICAgICAgICAgICAgcyA6ICdhIGZldyBzZWNvbmRzJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNlY29uZHMnLFxuICAgICAgICAgICAgbSA6ICdhIG1pbnV0ZScsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dGVzJyxcbiAgICAgICAgICAgIGggOiAnYW4gaG91cicsXG4gICAgICAgICAgICBoaCA6ICclZCBob3VycycsXG4gICAgICAgICAgICBkIDogJ2EgZGF5JyxcbiAgICAgICAgICAgIGRkIDogJyVkIGRheXMnLFxuICAgICAgICAgICAgTSA6ICdhIG1vbnRoJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG1vbnRocycsXG4gICAgICAgICAgICB5IDogJ2EgeWVhcicsXG4gICAgICAgICAgICB5eSA6ICclZCB5ZWFycydcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAgICAgKGIgPT09IDEpID8gJ3N0JyA6XG4gICAgICAgICAgICAgICAgKGIgPT09IDIpID8gJ25kJyA6XG4gICAgICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZW4tY2EnLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdTdV9Nb19UdV9XZV9UaF9Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgICAgICBMIDogJ1lZWVktTU0tREQnLFxuICAgICAgICAgICAgTEwgOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdNTU1NIEQsIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgTU1NTSBELCBZWVlZIGg6bW0gQSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgYWdvJyxcbiAgICAgICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWNvbmRzJyxcbiAgICAgICAgICAgIG0gOiAnYSBtaW51dGUnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgICAgICBoIDogJ2FuIGhvdXInLFxuICAgICAgICAgICAgaGggOiAnJWQgaG91cnMnLFxuICAgICAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgICAgICBkZCA6ICclZCBkYXlzJyxcbiAgICAgICAgICAgIE0gOiAnYSBtb250aCcsXG4gICAgICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICAgICAgeSA6ICdhIHllYXInLFxuICAgICAgICAgICAgeXkgOiAnJWQgeWVhcnMnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdHxuZHxyZHx0aCkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAofn4obnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAxKSA/ICdzdCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlbi1nYicsIHtcbiAgICAgICAgbW9udGhzIDogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW1RvbW9ycm93IGF0XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbTGFzdF0gZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgICAgICBzIDogJ2EgZmV3IHNlY29uZHMnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2Vjb25kcycsXG4gICAgICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaCA6ICdhbiBob3VyJyxcbiAgICAgICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgICAgIGQgOiAnYSBkYXknLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGF5cycsXG4gICAgICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbW9udGhzJyxcbiAgICAgICAgICAgIHkgOiAnYSB5ZWFyJyxcbiAgICAgICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAndGgnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMykgPyAncmQnIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdlbi1pZScsIHtcbiAgICAgICAgbW9udGhzIDogJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgYWdvJyxcbiAgICAgICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWNvbmRzJyxcbiAgICAgICAgICAgIG0gOiAnYSBtaW51dGUnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgICAgICBoIDogJ2FuIGhvdXInLFxuICAgICAgICAgICAgaGggOiAnJWQgaG91cnMnLFxuICAgICAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgICAgICBkZCA6ICclZCBkYXlzJyxcbiAgICAgICAgICAgIE0gOiAnYSBtb250aCcsXG4gICAgICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICAgICAgeSA6ICdhIHllYXInLFxuICAgICAgICAgICAgeXkgOiAnJWQgeWVhcnMnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdHxuZHxyZHx0aCkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAofn4obnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAxKSA/ICdzdCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2VuLWlsJywge1xuICAgICAgICBtb250aHMgOiAnSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgYWdvJyxcbiAgICAgICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaCA6ICdhbiBob3VyJyxcbiAgICAgICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgICAgIGQgOiAnYSBkYXknLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGF5cycsXG4gICAgICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbW9udGhzJyxcbiAgICAgICAgICAgIHkgOiAnYSB5ZWFyJyxcbiAgICAgICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAndGgnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMykgPyAncmQnIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZW4tbnonLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdTdV9Nb19UdV9XZV9UaF9Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIGg6bW0gQSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2F0XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgYWdvJyxcbiAgICAgICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWNvbmRzJyxcbiAgICAgICAgICAgIG0gOiAnYSBtaW51dGUnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgICAgICBoIDogJ2FuIGhvdXInLFxuICAgICAgICAgICAgaGggOiAnJWQgaG91cnMnLFxuICAgICAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgICAgICBkZCA6ICclZCBkYXlzJyxcbiAgICAgICAgICAgIE0gOiAnYSBtb250aCcsXG4gICAgICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICAgICAgeSA6ICdhIHllYXInLFxuICAgICAgICAgICAgeXkgOiAnJWQgeWVhcnMnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdHxuZHxyZHx0aCkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAofn4obnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAxKSA/ICdzdCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2VvJywge1xuICAgICAgICBtb250aHMgOiAnamFudWFyb19mZWJydWFyb19tYXJ0b19hcHJpbG9fbWFqb19qdW5pb19qdWxpb19hxa1ndXN0b19zZXB0ZW1icm9fb2t0b2Jyb19ub3ZlbWJyb19kZWNlbWJybycuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnamFuX2ZlYl9tYXJfYXByX21hal9qdW5fanVsX2HFrWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdkaW1hbsSJb19sdW5kb19tYXJkb19tZXJrcmVkb1/EtWHFrWRvX3ZlbmRyZWRvX3NhYmF0bycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdkaW1fbHVuX21hcmRfbWVya1/EtWHFrV92ZW5fc2FiJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdkaV9sdV9tYV9tZV/EtWFfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgICAgICBMTCA6ICdEWy1hIGRlXSBNTU1NLCBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEWy1hIGRlXSBNTU1NLCBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgW2xhXSBEWy1hIGRlXSBNTU1NLCBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAvW2FwXVxcLnRcXC5tL2ksXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0LmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpID09PSAncCc7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ3AudC5tLicgOiAnUC5ULk0uJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnYS50Lm0uJyA6ICdBLlQuTS4nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW0hvZGlhxa0gamVdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW01vcmdhxa0gamVdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2plXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tIaWVyYcWtIGplXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbcGFzaW50YV0gZGRkZCBbamVdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdwb3N0ICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnYW50YcWtICVzJyxcbiAgICAgICAgICAgIHMgOiAnc2VrdW5kb2onLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2VrdW5kb2onLFxuICAgICAgICAgICAgbSA6ICdtaW51dG8nLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXRvaicsXG4gICAgICAgICAgICBoIDogJ2hvcm8nLFxuICAgICAgICAgICAgaGggOiAnJWQgaG9yb2onLFxuICAgICAgICAgICAgZCA6ICd0YWdvJywvL25lICdkaXVybm8nLCDEiWFyIGVzdGFzIHV6aXRhIHBvciBwcm9rc2ltdW1vXG4gICAgICAgICAgICBkZCA6ICclZCB0YWdvaicsXG4gICAgICAgICAgICBNIDogJ21vbmF0bycsXG4gICAgICAgICAgICBNTSA6ICclZCBtb25hdG9qJyxcbiAgICAgICAgICAgIHkgOiAnamFybycsXG4gICAgICAgICAgICB5eSA6ICclZCBqYXJvaidcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9YS8sXG4gICAgICAgIG9yZGluYWwgOiAnJWRhJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzU2hvcnREb3QgPSAnZW5lLl9mZWIuX21hci5fYWJyLl9tYXkuX2p1bi5fanVsLl9hZ28uX3NlcC5fb2N0Ll9ub3YuX2RpYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0JDEgPSAnZW5lX2ZlYl9tYXJfYWJyX21heV9qdW5fanVsX2Fnb19zZXBfb2N0X25vdl9kaWMnLnNwbGl0KCdfJyk7XG5cbiAgICB2YXIgbW9udGhzUGFyc2UkMSA9IFsvXmVuZS9pLCAvXmZlYi9pLCAvXm1hci9pLCAvXmFici9pLCAvXm1heS9pLCAvXmp1bi9pLCAvXmp1bC9pLCAvXmFnby9pLCAvXnNlcC9pLCAvXm9jdC9pLCAvXm5vdi9pLCAvXmRpYy9pXTtcbiAgICB2YXIgbW9udGhzUmVnZXgkMiA9IC9eKGVuZXJvfGZlYnJlcm98bWFyem98YWJyaWx8bWF5b3xqdW5pb3xqdWxpb3xhZ29zdG98c2VwdGllbWJyZXxvY3R1YnJlfG5vdmllbWJyZXxkaWNpZW1icmV8ZW5lXFwuP3xmZWJcXC4/fG1hclxcLj98YWJyXFwuP3xtYXlcXC4/fGp1blxcLj98anVsXFwuP3xhZ29cXC4/fHNlcFxcLj98b2N0XFwuP3xub3ZcXC4/fGRpY1xcLj8pL2k7XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2VzLWRvJywge1xuICAgICAgICBtb250aHMgOiAnZW5lcm9fZmVicmVyb19tYXJ6b19hYnJpbF9tYXlvX2p1bmlvX2p1bGlvX2Fnb3N0b19zZXB0aWVtYnJlX29jdHVicmVfbm92aWVtYnJlX2RpY2llbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiBmdW5jdGlvbiAobSwgZm9ybWF0KSB7XG4gICAgICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnREb3Q7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKC8tTU1NLS8udGVzdChmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0JDFbbS5tb250aCgpXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0RG90W20ubW9udGgoKV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1JlZ2V4OiBtb250aHNSZWdleCQyLFxuICAgICAgICBtb250aHNTaG9ydFJlZ2V4OiBtb250aHNSZWdleCQyLFxuICAgICAgICBtb250aHNTdHJpY3RSZWdleDogL14oZW5lcm98ZmVicmVyb3xtYXJ6b3xhYnJpbHxtYXlvfGp1bmlvfGp1bGlvfGFnb3N0b3xzZXB0aWVtYnJlfG9jdHVicmV8bm92aWVtYnJlfGRpY2llbWJyZSkvaSxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14oZW5lXFwuP3xmZWJcXC4/fG1hclxcLj98YWJyXFwuP3xtYXlcXC4/fGp1blxcLj98anVsXFwuP3xhZ29cXC4/fHNlcFxcLj98b2N0XFwuP3xub3ZcXC4/fGRpY1xcLj8pL2ksXG4gICAgICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQxLFxuICAgICAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDEsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDEsXG4gICAgICAgIHdlZWtkYXlzIDogJ2RvbWluZ29fbHVuZXNfbWFydGVzX21pw6lyY29sZXNfanVldmVzX3ZpZXJuZXNfc8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdkb20uX2x1bi5fbWFyLl9tacOpLl9qdWUuX3ZpZS5fc8OhYi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ2RvX2x1X21hX21pX2p1X3ZpX3PDoScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIGg6bW0gQSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2hveSBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXh0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW21hw7FhbmEgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdkZGRkIFthIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2F5ZXIgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbZWxdIGRkZGQgW3Bhc2FkbyBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnZW4gJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICdoYWNlICVzJyxcbiAgICAgICAgICAgIHMgOiAndW5vcyBzZWd1bmRvcycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgICAgICBtIDogJ3VuIG1pbnV0bycsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dG9zJyxcbiAgICAgICAgICAgIGggOiAndW5hIGhvcmEnLFxuICAgICAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICAgICAgZCA6ICd1biBkw61hJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGTDrWFzJyxcbiAgICAgICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG1lc2VzJyxcbiAgICAgICAgICAgIHkgOiAndW4gYcOxbycsXG4gICAgICAgICAgICB5eSA6ICclZCBhw7FvcydcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbCA6ICclZMK6JyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzU2hvcnREb3QkMSA9ICdlbmUuX2ZlYi5fbWFyLl9hYnIuX21heS5fanVuLl9qdWwuX2Fnby5fc2VwLl9vY3QuX25vdi5fZGljLicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQkMiA9ICdlbmVfZmViX21hcl9hYnJfbWF5X2p1bl9qdWxfYWdvX3NlcF9vY3Rfbm92X2RpYycuc3BsaXQoJ18nKTtcblxuICAgIHZhciBtb250aHNQYXJzZSQyID0gWy9eZW5lL2ksIC9eZmViL2ksIC9ebWFyL2ksIC9eYWJyL2ksIC9ebWF5L2ksIC9eanVuL2ksIC9eanVsL2ksIC9eYWdvL2ksIC9ec2VwL2ksIC9eb2N0L2ksIC9ebm92L2ksIC9eZGljL2ldO1xuICAgIHZhciBtb250aHNSZWdleCQzID0gL14oZW5lcm98ZmVicmVyb3xtYXJ6b3xhYnJpbHxtYXlvfGp1bmlvfGp1bGlvfGFnb3N0b3xzZXB0aWVtYnJlfG9jdHVicmV8bm92aWVtYnJlfGRpY2llbWJyZXxlbmVcXC4/fGZlYlxcLj98bWFyXFwuP3xhYnJcXC4/fG1heVxcLj98anVuXFwuP3xqdWxcXC4/fGFnb1xcLj98c2VwXFwuP3xvY3RcXC4/fG5vdlxcLj98ZGljXFwuPykvaTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZXMtdXMnLCB7XG4gICAgICAgIG1vbnRocyA6ICdlbmVyb19mZWJyZXJvX21hcnpvX2FicmlsX21heW9fanVuaW9fanVsaW9fYWdvc3RvX3NlcHRpZW1icmVfb2N0dWJyZV9ub3ZpZW1icmVfZGljaWVtYnJlJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6IGZ1bmN0aW9uIChtLCBmb3JtYXQpIHtcbiAgICAgICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdCQxO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydCQyW20ubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdCQxW20ubW9udGgoKV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1JlZ2V4OiBtb250aHNSZWdleCQzLFxuICAgICAgICBtb250aHNTaG9ydFJlZ2V4OiBtb250aHNSZWdleCQzLFxuICAgICAgICBtb250aHNTdHJpY3RSZWdleDogL14oZW5lcm98ZmVicmVyb3xtYXJ6b3xhYnJpbHxtYXlvfGp1bmlvfGp1bGlvfGFnb3N0b3xzZXB0aWVtYnJlfG9jdHVicmV8bm92aWVtYnJlfGRpY2llbWJyZSkvaSxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14oZW5lXFwuP3xmZWJcXC4/fG1hclxcLj98YWJyXFwuP3xtYXlcXC4/fGp1blxcLj98anVsXFwuP3xhZ29cXC4/fHNlcFxcLj98b2N0XFwuP3xub3ZcXC4/fGRpY1xcLj8pL2ksXG4gICAgICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSQyLFxuICAgICAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDIsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlJDIsXG4gICAgICAgIHdlZWtkYXlzIDogJ2RvbWluZ29fbHVuZXNfbWFydGVzX21pw6lyY29sZXNfanVldmVzX3ZpZXJuZXNfc8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdkb20uX2x1bi5fbWFyLl9tacOpLl9qdWUuX3ZpZS5fc8OhYi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ2RvX2x1X21hX21pX2p1X3ZpX3PDoScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgICAgICBMIDogJ01NL0REL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIGg6bW0gQSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2hveSBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXh0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW21hw7FhbmEgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdkZGRkIFthIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW2F5ZXIgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbZWxdIGRkZGQgW3Bhc2FkbyBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnZW4gJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICdoYWNlICVzJyxcbiAgICAgICAgICAgIHMgOiAndW5vcyBzZWd1bmRvcycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgICAgICBtIDogJ3VuIG1pbnV0bycsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dG9zJyxcbiAgICAgICAgICAgIGggOiAndW5hIGhvcmEnLFxuICAgICAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICAgICAgZCA6ICd1biBkw61hJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGTDrWFzJyxcbiAgICAgICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG1lc2VzJyxcbiAgICAgICAgICAgIHkgOiAndW4gYcOxbycsXG4gICAgICAgICAgICB5eSA6ICclZCBhw7FvcydcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbCA6ICclZMK6JyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzU2hvcnREb3QkMiA9ICdlbmUuX2ZlYi5fbWFyLl9hYnIuX21heS5fanVuLl9qdWwuX2Fnby5fc2VwLl9vY3QuX25vdi5fZGljLicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQkMyA9ICdlbmVfZmViX21hcl9hYnJfbWF5X2p1bl9qdWxfYWdvX3NlcF9vY3Rfbm92X2RpYycuc3BsaXQoJ18nKTtcblxuICAgIHZhciBtb250aHNQYXJzZSQzID0gWy9eZW5lL2ksIC9eZmViL2ksIC9ebWFyL2ksIC9eYWJyL2ksIC9ebWF5L2ksIC9eanVuL2ksIC9eanVsL2ksIC9eYWdvL2ksIC9ec2VwL2ksIC9eb2N0L2ksIC9ebm92L2ksIC9eZGljL2ldO1xuICAgIHZhciBtb250aHNSZWdleCQ0ID0gL14oZW5lcm98ZmVicmVyb3xtYXJ6b3xhYnJpbHxtYXlvfGp1bmlvfGp1bGlvfGFnb3N0b3xzZXB0aWVtYnJlfG9jdHVicmV8bm92aWVtYnJlfGRpY2llbWJyZXxlbmVcXC4/fGZlYlxcLj98bWFyXFwuP3xhYnJcXC4/fG1heVxcLj98anVuXFwuP3xqdWxcXC4/fGFnb1xcLj98c2VwXFwuP3xvY3RcXC4/fG5vdlxcLj98ZGljXFwuPykvaTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZXMnLCB7XG4gICAgICAgIG1vbnRocyA6ICdlbmVyb19mZWJyZXJvX21hcnpvX2FicmlsX21heW9fanVuaW9fanVsaW9fYWdvc3RvX3NlcHRpZW1icmVfb2N0dWJyZV9ub3ZpZW1icmVfZGljaWVtYnJlJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6IGZ1bmN0aW9uIChtLCBmb3JtYXQpIHtcbiAgICAgICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdCQyO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydCQzW20ubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdCQyW20ubW9udGgoKV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1JlZ2V4IDogbW9udGhzUmVnZXgkNCxcbiAgICAgICAgbW9udGhzU2hvcnRSZWdleCA6IG1vbnRoc1JlZ2V4JDQsXG4gICAgICAgIG1vbnRoc1N0cmljdFJlZ2V4IDogL14oZW5lcm98ZmVicmVyb3xtYXJ6b3xhYnJpbHxtYXlvfGp1bmlvfGp1bGlvfGFnb3N0b3xzZXB0aWVtYnJlfG9jdHVicmV8bm92aWVtYnJlfGRpY2llbWJyZSkvaSxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleCA6IC9eKGVuZVxcLj98ZmViXFwuP3xtYXJcXC4/fGFiclxcLj98bWF5XFwuP3xqdW5cXC4/fGp1bFxcLj98YWdvXFwuP3xzZXBcXC4/fG9jdFxcLj98bm92XFwuP3xkaWNcXC4/KS9pLFxuICAgICAgICBtb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDMsXG4gICAgICAgIGxvbmdNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDMsXG4gICAgICAgIHNob3J0TW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSQzLFxuICAgICAgICB3ZWVrZGF5cyA6ICdkb21pbmdvX2x1bmVzX21hcnRlc19tacOpcmNvbGVzX2p1ZXZlc192aWVybmVzX3PDoWJhZG8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnZG9tLl9sdW4uX21hci5fbWnDqS5fanVlLl92aWUuX3PDoWIuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdkb19sdV9tYV9taV9qdV92aV9zw6EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgW2RlXSBNTU1NIFtkZV0gWVlZWSBIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbaG95IGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5leHREYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbbWHDsWFuYSBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBuZXh0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2RkZGQgW2EgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbYXllciBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1tlbF0gZGRkZCBbcGFzYWRvIGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdlbiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ2hhY2UgJXMnLFxuICAgICAgICAgICAgcyA6ICd1bm9zIHNlZ3VuZG9zJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNlZ3VuZG9zJyxcbiAgICAgICAgICAgIG0gOiAndW4gbWludXRvJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0b3MnLFxuICAgICAgICAgICAgaCA6ICd1bmEgaG9yYScsXG4gICAgICAgICAgICBoaCA6ICclZCBob3JhcycsXG4gICAgICAgICAgICBkIDogJ3VuIGTDrWEnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZMOtYXMnLFxuICAgICAgICAgICAgTSA6ICd1biBtZXMnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbWVzZXMnLFxuICAgICAgICAgICAgeSA6ICd1biBhw7FvJyxcbiAgICAgICAgICAgIHl5IDogJyVkIGHDsW9zJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9wrovLFxuICAgICAgICBvcmRpbmFsIDogJyVkwronLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyhudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgICAgICdzJyA6IFsnbcO1bmUgc2VrdW5kaScsICdtw7VuaSBzZWt1bmQnLCAncGFhciBzZWt1bmRpdCddLFxuICAgICAgICAgICAgJ3NzJzogW251bWJlciArICdzZWt1bmRpJywgbnVtYmVyICsgJ3Nla3VuZGl0J10sXG4gICAgICAgICAgICAnbScgOiBbJ8O8aGUgbWludXRpJywgJ8O8a3MgbWludXQnXSxcbiAgICAgICAgICAgICdtbSc6IFtudW1iZXIgKyAnIG1pbnV0aScsIG51bWJlciArICcgbWludXRpdCddLFxuICAgICAgICAgICAgJ2gnIDogWyfDvGhlIHR1bm5pJywgJ3R1bmQgYWVnYScsICfDvGtzIHR1bmQnXSxcbiAgICAgICAgICAgICdoaCc6IFtudW1iZXIgKyAnIHR1bm5pJywgbnVtYmVyICsgJyB0dW5kaSddLFxuICAgICAgICAgICAgJ2QnIDogWyfDvGhlIHDDpGV2YScsICfDvGtzIHDDpGV2J10sXG4gICAgICAgICAgICAnTScgOiBbJ2t1dSBhamEnLCAna3V1IGFlZ2EnLCAnw7xrcyBrdXUnXSxcbiAgICAgICAgICAgICdNTSc6IFtudW1iZXIgKyAnIGt1dScsIG51bWJlciArICcga3V1ZCddLFxuICAgICAgICAgICAgJ3knIDogWyfDvGhlIGFhc3RhJywgJ2Fhc3RhJywgJ8O8a3MgYWFzdGEnXSxcbiAgICAgICAgICAgICd5eSc6IFtudW1iZXIgKyAnIGFhc3RhJywgbnVtYmVyICsgJyBhYXN0YXQnXVxuICAgICAgICB9O1xuICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdFtrZXldWzJdID8gZm9ybWF0W2tleV1bMl0gOiBmb3JtYXRba2V5XVsxXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZXQnLCB7XG4gICAgICAgIG1vbnRocyAgICAgICAgOiAnamFhbnVhcl92ZWVicnVhcl9tw6RydHNfYXByaWxsX21haV9qdXVuaV9qdXVsaV9hdWd1c3Rfc2VwdGVtYmVyX29rdG9vYmVyX25vdmVtYmVyX2RldHNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgICA6ICdqYWFuX3ZlZWJyX23DpHJ0c19hcHJfbWFpX2p1dW5pX2p1dWxpX2F1Z19zZXB0X29rdF9ub3ZfZGV0cycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgICAgICA6ICdww7xoYXDDpGV2X2VzbWFzcMOkZXZfdGVpc2lww6Rldl9rb2xtYXDDpGV2X25lbGphcMOkZXZfcmVlZGVfbGF1cMOkZXYnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnUF9FX1RfS19OX1JfTCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gICA6ICdQX0VfVF9LX05fUl9MJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUICAgOiAnSDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMICAgIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgICA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMICA6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgIDogJ1tUw6RuYSxdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgIDogJ1tIb21tZSxdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ1tKw6RyZ21pbmVdIGRkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheSAgOiAnW0VpbGUsXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbRWVsbWluZV0gZGRkZCBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnJXMgcMOkcmFzdCcsXG4gICAgICAgICAgICBwYXN0ICAgOiAnJXMgdGFnYXNpJyxcbiAgICAgICAgICAgIHMgICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIHNzICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIG0gICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIG1tICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIGggICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIGhoICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIGQgICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkMyxcbiAgICAgICAgICAgIGRkICAgICA6ICclZCBww6RldmEnLFxuICAgICAgICAgICAgTSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICAgICAgTU0gICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICAgICAgeSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQzLFxuICAgICAgICAgICAgeXkgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQzXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2V1Jywge1xuICAgICAgICBtb250aHMgOiAndXJ0YXJyaWxhX290c2FpbGFfbWFydHhvYV9hcGlyaWxhX21haWF0emFfZWthaW5hX3V6dGFpbGFfYWJ1enR1YV9pcmFpbGFfdXJyaWFfYXphcm9hX2FiZW5kdWEnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ3VydC5fb3RzLl9tYXIuX2FwaS5fbWFpLl9la2EuX3V6dC5fYWJ1Ll9pcmEuX3Vyci5fYXphLl9hYmUuJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXMgOiAnaWdhbmRlYV9hc3RlbGVoZW5hX2FzdGVhcnRlYV9hc3RlYXprZW5hX29zdGVndW5hX29zdGlyYWxhX2xhcnVuYmF0YScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdpZy5fYWwuX2FyLl9hei5fb2cuX29sLl9sci4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ2lnX2FsX2FyX2F6X29nX29sX2xyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ1lZWVktTU0tREQnLFxuICAgICAgICAgICAgTEwgOiAnWVlZWVtrb10gTU1NTVtyZW5dIERbYV0nLFxuICAgICAgICAgICAgTExMIDogJ1lZWVlba29dIE1NTU1bcmVuXSBEW2FdIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgWVlZWVtrb10gTU1NTVtyZW5dIERbYV0gSEg6bW0nLFxuICAgICAgICAgICAgbCA6ICdZWVlZLU0tRCcsXG4gICAgICAgICAgICBsbCA6ICdZWVlZW2tvXSBNTU0gRFthXScsXG4gICAgICAgICAgICBsbGwgOiAnWVlZWVtrb10gTU1NIERbYV0gSEg6bW0nLFxuICAgICAgICAgICAgbGxsbCA6ICdkZGQsIFlZWVlba29dIE1NTSBEW2FdIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW2dhdXJdIExUW2V0YW5dJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW2JpaGFyXSBMVFtldGFuXScsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIExUW2V0YW5dJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW2F0em9dIExUW2V0YW5dJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1thdXJyZWtvXSBkZGRkIExUW2V0YW5dJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyBiYXJydScsXG4gICAgICAgICAgICBwYXN0IDogJ2R1ZWxhICVzJyxcbiAgICAgICAgICAgIHMgOiAnc2VndW5kbyBiYXR6dWsnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2VndW5kbycsXG4gICAgICAgICAgICBtIDogJ21pbnV0dSBiYXQnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXR1JyxcbiAgICAgICAgICAgIGggOiAnb3JkdSBiYXQnLFxuICAgICAgICAgICAgaGggOiAnJWQgb3JkdScsXG4gICAgICAgICAgICBkIDogJ2VndW4gYmF0JyxcbiAgICAgICAgICAgIGRkIDogJyVkIGVndW4nLFxuICAgICAgICAgICAgTSA6ICdoaWxhYmV0ZSBiYXQnLFxuICAgICAgICAgICAgTU0gOiAnJWQgaGlsYWJldGUnLFxuICAgICAgICAgICAgeSA6ICd1cnRlIGJhdCcsXG4gICAgICAgICAgICB5eSA6ICclZCB1cnRlJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCQ1ID0ge1xuICAgICAgICAnMSc6ICfbsScsXG4gICAgICAgICcyJzogJ9uyJyxcbiAgICAgICAgJzMnOiAn27MnLFxuICAgICAgICAnNCc6ICfbtCcsXG4gICAgICAgICc1JzogJ9u1JyxcbiAgICAgICAgJzYnOiAn27YnLFxuICAgICAgICAnNyc6ICfbtycsXG4gICAgICAgICc4JzogJ9u4JyxcbiAgICAgICAgJzknOiAn27knLFxuICAgICAgICAnMCc6ICfbsCdcbiAgICB9LCBudW1iZXJNYXAkNCA9IHtcbiAgICAgICAgJ9uxJzogJzEnLFxuICAgICAgICAn27InOiAnMicsXG4gICAgICAgICfbsyc6ICczJyxcbiAgICAgICAgJ9u0JzogJzQnLFxuICAgICAgICAn27UnOiAnNScsXG4gICAgICAgICfbtic6ICc2JyxcbiAgICAgICAgJ9u3JzogJzcnLFxuICAgICAgICAn27gnOiAnOCcsXG4gICAgICAgICfbuSc6ICc5JyxcbiAgICAgICAgJ9uwJzogJzAnXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZmEnLCB7XG4gICAgICAgIG1vbnRocyA6ICfamNin2YbZiNuM2Ydf2YHZiNix24zZh1/Zhdin2LHYs1/YotmI2LHbjNmEX9mF2Ydf2pjZiNim2YZf2pjZiNim24zZh1/Yp9mI2Kpf2LPZvtiq2KfZhdio2LFf2Kfaqdiq2KjYsV/ZhtmI2KfZhdio2LFf2K/Ys9in2YXYqNixJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICfamNin2YbZiNuM2Ydf2YHZiNix24zZh1/Zhdin2LHYs1/YotmI2LHbjNmEX9mF2Ydf2pjZiNim2YZf2pjZiNim24zZh1/Yp9mI2Kpf2LPZvtiq2KfZhdio2LFf2Kfaqdiq2KjYsV/ZhtmI2KfZhdio2LFf2K/Ys9in2YXYqNixJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfbjNqpXFx1MjAwY9i02YbYqNmHX9iv2YjYtNmG2KjZh1/Ys9mHXFx1MjAwY9i02YbYqNmHX9qG2YfYp9ix2LTZhtio2Ydf2b7ZhtisXFx1MjAwY9i02YbYqNmHX9is2YXYudmHX9i02YbYqNmHJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ9uM2qlcXHUyMDBj2LTZhtio2Ydf2K/ZiNi02YbYqNmHX9iz2YdcXHUyMDBj2LTZhtio2Ydf2obZh9in2LHYtNmG2KjZh1/ZvtmG2KxcXHUyMDBj2LTZhtio2Ydf2KzZhdi52Ydf2LTZhtio2YcnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ9uMX9ivX9izX9qGX9m+X9isX9i0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/Zgtio2YQg2KfYsiDYuNmH2LF82KjYudivINin2LIg2LjZh9ixLyxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gL9io2LnYryDYp9iyINi42YfYsS8udGVzdChpbnB1dCk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2YLYqNmEINin2LIg2LjZh9ixJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfYqNi52K8g2KfYsiDYuNmH2LEnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW9in2YXYsdmI2LIg2LPYp9i52KpdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW9mB2LHYr9inINiz2KfYudiqXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvYs9in2LnYql0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb2K/bjNix2YjYsiDYs9in2LnYql0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBb2b7bjNi0XSBb2LPYp9i52KpdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfYr9ixICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMg2b7bjNi0JyxcbiAgICAgICAgICAgIHMgOiAn2obZhtivINir2KfZhtuM2YcnLFxuICAgICAgICAgICAgc3MgOiAn2KvYp9mG24zZhyBkJScsXG4gICAgICAgICAgICBtIDogJ9uM2qkg2K/ZgtuM2YLZhycsXG4gICAgICAgICAgICBtbSA6ICclZCDYr9mC24zZgtmHJyxcbiAgICAgICAgICAgIGggOiAn24zaqSDYs9in2LnYqicsXG4gICAgICAgICAgICBoaCA6ICclZCDYs9in2LnYqicsXG4gICAgICAgICAgICBkIDogJ9uM2qkg2LHZiNiyJyxcbiAgICAgICAgICAgIGRkIDogJyVkINix2YjYsicsXG4gICAgICAgICAgICBNIDogJ9uM2qkg2YXYp9mHJyxcbiAgICAgICAgICAgIE1NIDogJyVkINmF2KfZhycsXG4gICAgICAgICAgICB5IDogJ9uM2qkg2LPYp9mEJyxcbiAgICAgICAgICAgIHl5IDogJyVkINiz2KfZhCdcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW9uwLdu5XS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJDRbbWF0Y2hdO1xuICAgICAgICAgICAgfSkucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQ1W21hdGNoXTtcbiAgICAgICAgICAgIH0pLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfdmFLyxcbiAgICAgICAgb3JkaW5hbCA6ICclZNmFJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiAxMiAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxMnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbnVtYmVyc1Bhc3QgPSAnbm9sbGEgeWtzaSBrYWtzaSBrb2xtZSBuZWxqw6Qgdmlpc2kga3V1c2kgc2VpdHNlbcOkbiBrYWhkZWtzYW4geWhkZWtzw6RuJy5zcGxpdCgnICcpLFxuICAgICAgICBudW1iZXJzRnV0dXJlID0gW1xuICAgICAgICAgICAgJ25vbGxhJywgJ3loZGVuJywgJ2thaGRlbicsICdrb2xtZW4nLCAnbmVsasOkbicsICd2aWlkZW4nLCAna3V1ZGVuJyxcbiAgICAgICAgICAgIG51bWJlcnNQYXN0WzddLCBudW1iZXJzUGFzdFs4XSwgbnVtYmVyc1Bhc3RbOV1cbiAgICAgICAgXTtcbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkMihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9ICcnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ211dXRhbWFuIHNla3VubmluJyA6ICdtdXV0YW1hIHNla3VudGknO1xuICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdzZWt1bm5pbicgOiAnc2VrdW50aWEnO1xuICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ21pbnV1dGluJyA6ICdtaW51dXR0aSc7XG4gICAgICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gaXNGdXR1cmUgPyAnbWludXV0aW4nIDogJ21pbnV1dHRpYSc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAndHVubmluJyA6ICd0dW50aSc7XG4gICAgICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gaXNGdXR1cmUgPyAndHVubmluJyA6ICd0dW50aWEnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ3DDpGl2w6RuJyA6ICdww6RpdsOkJztcbiAgICAgICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICdww6RpdsOkbicgOiAncMOkaXbDpMOkJztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdrdXVrYXVkZW4nIDogJ2t1dWthdXNpJztcbiAgICAgICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICdrdXVrYXVkZW4nIDogJ2t1dWthdXR0YSc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd5JzpcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAndnVvZGVuJyA6ICd2dW9zaSc7XG4gICAgICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gaXNGdXR1cmUgPyAndnVvZGVuJyA6ICd2dW90dGEnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdCA9IHZlcmJhbE51bWJlcihudW1iZXIsIGlzRnV0dXJlKSArICcgJyArIHJlc3VsdDtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgZnVuY3Rpb24gdmVyYmFsTnVtYmVyKG51bWJlciwgaXNGdXR1cmUpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciA8IDEwID8gKGlzRnV0dXJlID8gbnVtYmVyc0Z1dHVyZVtudW1iZXJdIDogbnVtYmVyc1Bhc3RbbnVtYmVyXSkgOiBudW1iZXI7XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdmaScsIHtcbiAgICAgICAgbW9udGhzIDogJ3RhbW1pa3V1X2hlbG1pa3V1X21hYWxpc2t1dV9odWh0aWt1dV90b3Vrb2t1dV9rZXPDpGt1dV9oZWluw6RrdXVfZWxva3V1X3N5eXNrdXVfbG9rYWt1dV9tYXJyYXNrdXVfam91bHVrdXUnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ3RhbW1pX2hlbG1pX21hYWxpc19odWh0aV90b3Vrb19rZXPDpF9oZWluw6RfZWxvX3N5eXNfbG9rYV9tYXJyYXNfam91bHUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ3N1bm51bnRhaV9tYWFuYW50YWlfdGlpc3RhaV9rZXNraXZpaWtrb190b3JzdGFpX3BlcmphbnRhaV9sYXVhbnRhaScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdzdV9tYV90aV9rZV90b19wZV9sYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnc3VfbWFfdGlfa2VfdG9fcGVfbGEnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEgubW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hILm1tLnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEbyBNTU1NW3RhXSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEbyBNTU1NW3RhXSBZWVlZLCBba2xvXSBISC5tbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIERvIE1NTU1bdGFdIFlZWVksIFtrbG9dIEhILm1tJyxcbiAgICAgICAgICAgIGwgOiAnRC5NLllZWVknLFxuICAgICAgICAgICAgbGwgOiAnRG8gTU1NIFlZWVknLFxuICAgICAgICAgICAgbGxsIDogJ0RvIE1NTSBZWVlZLCBba2xvXSBISC5tbScsXG4gICAgICAgICAgICBsbGxsIDogJ2RkZCwgRG8gTU1NIFlZWVksIFtrbG9dIEhILm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW3TDpG7DpMOkbl0gW2tsb10gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbaHVvbWVubmFdIFtrbG9dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2tsb10gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbZWlsZW5dIFtrbG9dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1t2aWltZV0gZGRkZFtuYV0gW2tsb10gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVzIHDDpMOkc3TDpCcsXG4gICAgICAgICAgICBwYXN0IDogJyVzIHNpdHRlbicsXG4gICAgICAgICAgICBzIDogdHJhbnNsYXRlJDIsXG4gICAgICAgICAgICBzcyA6IHRyYW5zbGF0ZSQyLFxuICAgICAgICAgICAgbSA6IHRyYW5zbGF0ZSQyLFxuICAgICAgICAgICAgbW0gOiB0cmFuc2xhdGUkMixcbiAgICAgICAgICAgIGggOiB0cmFuc2xhdGUkMixcbiAgICAgICAgICAgIGhoIDogdHJhbnNsYXRlJDIsXG4gICAgICAgICAgICBkIDogdHJhbnNsYXRlJDIsXG4gICAgICAgICAgICBkZCA6IHRyYW5zbGF0ZSQyLFxuICAgICAgICAgICAgTSA6IHRyYW5zbGF0ZSQyLFxuICAgICAgICAgICAgTU0gOiB0cmFuc2xhdGUkMixcbiAgICAgICAgICAgIHkgOiB0cmFuc2xhdGUkMixcbiAgICAgICAgICAgIHl5IDogdHJhbnNsYXRlJDJcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbCA6ICclZC4nLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZm8nLCB7XG4gICAgICAgIG1vbnRocyA6ICdqYW51YXJfZmVicnVhcl9tYXJzX2FwcsOtbF9tYWlfanVuaV9qdWxpX2F1Z3VzdF9zZXB0ZW1iZXJfb2t0b2Jlcl9ub3ZlbWJlcl9kZXNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnamFuX2ZlYl9tYXJfYXByX21haV9qdW5fanVsX2F1Z19zZXBfb2t0X25vdl9kZXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ3N1bm51ZGFndXJfbcOhbmFkYWd1cl90w71zZGFndXJfbWlrdWRhZ3VyX2jDs3NkYWd1cl9mcsOtZ2dqYWRhZ3VyX2xleWdhcmRhZ3VyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ3N1bl9tw6FuX3TDvXNfbWlrX2jDs3NfZnLDrV9sZXknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ3N1X23DoV90w71fbWlfaMOzX2ZyX2xlJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBELiBNTU1NLCBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW8ONIGRhZyBrbC5dIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW8ONIG1vcmdpbiBrbC5dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2tsLl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbw40gZ2rDoXIga2wuXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbc8Otw7BzdHVdIGRkZGQgW2tsXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAndW0gJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyBzw63DsGFuaScsXG4gICAgICAgICAgICBzIDogJ2bDoSBzZWt1bmQnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2VrdW5kaXInLFxuICAgICAgICAgICAgbSA6ICdlaW4gbWludXR0dXInLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXR0aXInLFxuICAgICAgICAgICAgaCA6ICdlaW4gdMOtbWknLFxuICAgICAgICAgICAgaGggOiAnJWQgdMOtbWFyJyxcbiAgICAgICAgICAgIGQgOiAnZWluIGRhZ3VyJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGRhZ2FyJyxcbiAgICAgICAgICAgIE0gOiAnZWluIG3DoW5hw7B1cicsXG4gICAgICAgICAgICBNTSA6ICclZCBtw6FuYcOwaXInLFxuICAgICAgICAgICAgeSA6ICdlaXR0IMOhcicsXG4gICAgICAgICAgICB5eSA6ICclZCDDoXInXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2ZyLWNhJywge1xuICAgICAgICBtb250aHMgOiAnamFudmllcl9mw6l2cmllcl9tYXJzX2F2cmlsX21haV9qdWluX2p1aWxsZXRfYW/Du3Rfc2VwdGVtYnJlX29jdG9icmVfbm92ZW1icmVfZMOpY2VtYnJlJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdqYW52Ll9mw6l2ci5fbWFyc19hdnIuX21haV9qdWluX2p1aWwuX2Fvw7t0X3NlcHQuX29jdC5fbm92Ll9kw6ljLicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogJ2RpbWFuY2hlX2x1bmRpX21hcmRpX21lcmNyZWRpX2pldWRpX3ZlbmRyZWRpX3NhbWVkaScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdkaW0uX2x1bi5fbWFyLl9tZXIuX2pldS5fdmVuLl9zYW0uJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdkaV9sdV9tYV9tZV9qZV92ZV9zYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbQXVqb3VyZOKAmWh1aSDDoF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbRGVtYWluIMOgXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvDoF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbSGllciDDoF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbZGVybmllciDDoF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2RhbnMgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICdpbCB5IGEgJXMnLFxuICAgICAgICAgICAgcyA6ICdxdWVscXVlcyBzZWNvbmRlcycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWNvbmRlcycsXG4gICAgICAgICAgICBtIDogJ3VuZSBtaW51dGUnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgICAgICBoIDogJ3VuZSBoZXVyZScsXG4gICAgICAgICAgICBoaCA6ICclZCBoZXVyZXMnLFxuICAgICAgICAgICAgZCA6ICd1biBqb3VyJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGpvdXJzJyxcbiAgICAgICAgICAgIE0gOiAndW4gbW9pcycsXG4gICAgICAgICAgICBNTSA6ICclZCBtb2lzJyxcbiAgICAgICAgICAgIHkgOiAndW4gYW4nLFxuICAgICAgICAgICAgeXkgOiAnJWQgYW5zJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZXJ8ZSkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggbWFzY3VsaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogbW9pcywgdHJpbWVzdHJlLCBqb3VyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICBjYXNlICdRJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdlcicgOiAnZScpO1xuXG4gICAgICAgICAgICAgICAgLy8gV29yZHMgd2l0aCBmZW1pbmluZSBncmFtbWF0aWNhbCBnZW5kZXI6IHNlbWFpbmVcbiAgICAgICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChudW1iZXIgPT09IDEgPyAncmUnIDogJ2UnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdmci1jaCcsIHtcbiAgICAgICAgbW9udGhzIDogJ2phbnZpZXJfZsOpdnJpZXJfbWFyc19hdnJpbF9tYWlfanVpbl9qdWlsbGV0X2Fvw7t0X3NlcHRlbWJyZV9vY3RvYnJlX25vdmVtYnJlX2TDqWNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnamFudi5fZsOpdnIuX21hcnNfYXZyLl9tYWlfanVpbl9qdWlsLl9hb8O7dF9zZXB0Ll9vY3QuX25vdi5fZMOpYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdkaW1hbmNoZV9sdW5kaV9tYXJkaV9tZXJjcmVkaV9qZXVkaV92ZW5kcmVkaV9zYW1lZGknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnZGltLl9sdW4uX21hci5fbWVyLl9qZXUuX3Zlbi5fc2FtLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnZGlfbHVfbWFfbWVfamVfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW0F1am91cmTigJlodWkgw6BdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW0RlbWFpbiDDoF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbw6BdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW0hpZXIgw6BdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW2Rlcm5pZXIgw6BdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdkYW5zICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnaWwgeSBhICVzJyxcbiAgICAgICAgICAgIHMgOiAncXVlbHF1ZXMgc2Vjb25kZXMnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2Vjb25kZXMnLFxuICAgICAgICAgICAgbSA6ICd1bmUgbWludXRlJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaCA6ICd1bmUgaGV1cmUnLFxuICAgICAgICAgICAgaGggOiAnJWQgaGV1cmVzJyxcbiAgICAgICAgICAgIGQgOiAndW4gam91cicsXG4gICAgICAgICAgICBkZCA6ICclZCBqb3VycycsXG4gICAgICAgICAgICBNIDogJ3VuIG1vaXMnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbW9pcycsXG4gICAgICAgICAgICB5IDogJ3VuIGFuJyxcbiAgICAgICAgICAgIHl5IDogJyVkIGFucydcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGVyfGUpLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgICAgICAvLyBXb3JkcyB3aXRoIG1hc2N1bGluZSBncmFtbWF0aWNhbCBnZW5kZXI6IG1vaXMsIHRyaW1lc3RyZSwgam91clxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgY2FzZSAnUSc6XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChudW1iZXIgPT09IDEgPyAnZXInIDogJ2UnKTtcblxuICAgICAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggZmVtaW5pbmUgZ3JhbW1hdGljYWwgZ2VuZGVyOiBzZW1haW5lXG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ3JlJyA6ICdlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdmcicsIHtcbiAgICAgICAgbW9udGhzIDogJ2phbnZpZXJfZsOpdnJpZXJfbWFyc19hdnJpbF9tYWlfanVpbl9qdWlsbGV0X2Fvw7t0X3NlcHRlbWJyZV9vY3RvYnJlX25vdmVtYnJlX2TDqWNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnamFudi5fZsOpdnIuX21hcnNfYXZyLl9tYWlfanVpbl9qdWlsLl9hb8O7dF9zZXB0Ll9vY3QuX25vdi5fZMOpYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdkaW1hbmNoZV9sdW5kaV9tYXJkaV9tZXJjcmVkaV9qZXVkaV92ZW5kcmVkaV9zYW1lZGknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnZGltLl9sdW4uX21hci5fbWVyLl9qZXUuX3Zlbi5fc2FtLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnZGlfbHVfbWFfbWVfamVfdmVfc2EnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW0F1am91cmTigJlodWkgw6BdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW0RlbWFpbiDDoF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbw6BdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW0hpZXIgw6BdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW2Rlcm5pZXIgw6BdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdkYW5zICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnaWwgeSBhICVzJyxcbiAgICAgICAgICAgIHMgOiAncXVlbHF1ZXMgc2Vjb25kZXMnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2Vjb25kZXMnLFxuICAgICAgICAgICAgbSA6ICd1bmUgbWludXRlJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0ZXMnLFxuICAgICAgICAgICAgaCA6ICd1bmUgaGV1cmUnLFxuICAgICAgICAgICAgaGggOiAnJWQgaGV1cmVzJyxcbiAgICAgICAgICAgIGQgOiAndW4gam91cicsXG4gICAgICAgICAgICBkZCA6ICclZCBqb3VycycsXG4gICAgICAgICAgICBNIDogJ3VuIG1vaXMnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbW9pcycsXG4gICAgICAgICAgICB5IDogJ3VuIGFuJyxcbiAgICAgICAgICAgIHl5IDogJyVkIGFucydcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGVyfCkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IFJldHVybiAnZScgd2hlbiBkYXkgb2YgbW9udGggPiAxLiBNb3ZlIHRoaXMgY2FzZSBpbnNpZGVcbiAgICAgICAgICAgICAgICAvLyBibG9jayBmb3IgbWFzY3VsaW5lIHdvcmRzIGJlbG93LlxuICAgICAgICAgICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vbW9tZW50L21vbWVudC9pc3N1ZXMvMzM3NVxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdlcicgOiAnJyk7XG5cbiAgICAgICAgICAgICAgICAvLyBXb3JkcyB3aXRoIG1hc2N1bGluZSBncmFtbWF0aWNhbCBnZW5kZXI6IG1vaXMsIHRyaW1lc3RyZSwgam91clxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgY2FzZSAnUSc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChudW1iZXIgPT09IDEgPyAnZXInIDogJ2UnKTtcblxuICAgICAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggZmVtaW5pbmUgZ3JhbW1hdGljYWwgZ2VuZGVyOiBzZW1haW5lXG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAobnVtYmVyID09PSAxID8gJ3JlJyA6ICdlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRoc1Nob3J0V2l0aERvdHMgPSAnamFuLl9mZWIuX21ydC5fYXByLl9tYWlfanVuLl9qdWwuX2F1Zy5fc2VwLl9va3QuX25vdi5fZGVzLicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnRXaXRob3V0RG90cyA9ICdqYW5fZmViX21ydF9hcHJfbWFpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2Rlcycuc3BsaXQoJ18nKTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZnknLCB7XG4gICAgICAgIG1vbnRocyA6ICdqYW5uZXdhcmlzX2ZlYnJld2FyaXNfbWFhcnRfYXByaWxfbWFhaWVfanVueV9qdWx5X2F1Z3VzdHVzX3NlcHRpbWJlcl9va3RvYmVyX25vdmltYmVyX2Rlc2ltYmVyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6IGZ1bmN0aW9uIChtLCBmb3JtYXQpIHtcbiAgICAgICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhvdXREb3RzW20ubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzW20ubW9udGgoKV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdzbmVpbl9tb2FuZGVpX3RpaXNkZWlfd29hbnNkZWlfdG9uZ2Vyc2RlaV9mcmVlZF9zbmVvbicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdzaS5fbW8uX3RpLl93by5fdG8uX2ZyLl9zby4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1NpX01vX1RpX1dvX1RvX0ZyX1NvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELU1NLVlZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2hqb2VkIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW21vYXJuIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW29tXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW2p1c3RlciBvbV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbw7RmcsO7bmVdIGRkZGQgW29tXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdvZXIgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyBseW4nLFxuICAgICAgICAgICAgcyA6ICdpbiBwZWFyIHNla29uZGVuJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNla29uZGVuJyxcbiAgICAgICAgICAgIG0gOiAnaWVuIG1pbsO6dCcsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dGVuJyxcbiAgICAgICAgICAgIGggOiAnaWVuIG9lcmUnLFxuICAgICAgICAgICAgaGggOiAnJWQgb2VyZW4nLFxuICAgICAgICAgICAgZCA6ICdpZW4gZGVpJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGRhZ2VuJyxcbiAgICAgICAgICAgIE0gOiAnaWVuIG1vYW5uZScsXG4gICAgICAgICAgICBNTSA6ICclZCBtb2FubmVuJyxcbiAgICAgICAgICAgIHkgOiAnaWVuIGppZXInLFxuICAgICAgICAgICAgeXkgOiAnJWQgamllcnJlbidcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICgobnVtYmVyID09PSAxIHx8IG51bWJlciA9PT0gOCB8fCBudW1iZXIgPj0gMjApID8gJ3N0ZScgOiAnZGUnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cblxuICAgIHZhciBtb250aHMkNSA9IFtcbiAgICAgICAgJ0VhbsOhaXInLCAnRmVhYmhyYScsICdNw6FydGEnLCAnQWlicmXDoW4nLCAnQmVhbHRhaW5lJywgJ03DqWl0aGVhbWgnLCAnScO6aWwnLCAnTMO6bmFzYScsICdNZcOhbiBGw7NtaGFpcicsICdEZWFpcmVhZGggRsOzbWhhaXInLCAnU2FtaGFpbicsICdOb2xsYWlnJ1xuICAgIF07XG5cbiAgICB2YXIgbW9udGhzU2hvcnQkNCA9IFsnRWFuw6EnLCAnRmVhYicsICdNw6FydCcsICdBaWJyJywgJ0JlYWwnLCAnTcOpaXQnLCAnScO6aWwnLCAnTMO6bmEnLCAnTWXDoW4nLCAnRGVhaScsICdTYW1oJywgJ05vbGwnXTtcblxuICAgIHZhciB3ZWVrZGF5cyQxID0gWydEw6kgRG9taG5haWdoJywgJ0TDqSBMdWFpbicsICdEw6kgTcOhaXJ0JywgJ0TDqSBDw6lhZGFvaW4nLCAnRMOpYXJkYW9pbicsICdEw6kgaEFvaW5lJywgJ0TDqSBTYXRoYXJuJ107XG5cbiAgICB2YXIgd2Vla2RheXNTaG9ydCA9IFsnRG9tJywgJ0x1YScsICdNw6FpJywgJ0PDqWEnLCAnRMOpYScsICdoQW8nLCAnU2F0J107XG5cbiAgICB2YXIgd2Vla2RheXNNaW4gPSBbJ0RvJywgJ0x1JywgJ03DoScsICdDZScsICdEw6knLCAnaEEnLCAnU2EnXTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZ2EnLCB7XG4gICAgICAgIG1vbnRoczogbW9udGhzJDUsXG4gICAgICAgIG1vbnRoc1Nob3J0OiBtb250aHNTaG9ydCQ0LFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogd2Vla2RheXMkMSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogd2Vla2RheXNTaG9ydCxcbiAgICAgICAgd2Vla2RheXNNaW46IHdlZWtkYXlzTWluLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSW5uaXUgYWddIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbQW3DoXJhY2ggYWddIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYWddIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbSW5uw6kgYWlnXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW3NlbyBjYWl0ZV0gW2FnXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnaSAlcycsXG4gICAgICAgICAgICBwYXN0OiAnJXMgw7Mgc2hpbicsXG4gICAgICAgICAgICBzOiAnY8O6cGxhIHNvaWNpbmQnLFxuICAgICAgICAgICAgc3M6ICclZCBzb2ljaW5kJyxcbiAgICAgICAgICAgIG06ICduw7NpbcOpYWQnLFxuICAgICAgICAgICAgbW06ICclZCBuw7NpbcOpYWQnLFxuICAgICAgICAgICAgaDogJ3VhaXIgYW4gY2hsb2lnJyxcbiAgICAgICAgICAgIGhoOiAnJWQgdWFpciBhbiBjaGxvaWcnLFxuICAgICAgICAgICAgZDogJ2zDoScsXG4gICAgICAgICAgICBkZDogJyVkIGzDoScsXG4gICAgICAgICAgICBNOiAnbcOtJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbcOtJyxcbiAgICAgICAgICAgIHk6ICdibGlhaW4nLFxuICAgICAgICAgICAgeXk6ICclZCBibGlhaW4nXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShkfG5hfG1oKS8sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSBudW1iZXIgPT09IDEgPyAnZCcgOiBudW1iZXIgJSAxMCA9PT0gMiA/ICduYScgOiAnbWgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzJDYgPSBbXG4gICAgICAgICdBbSBGYW9pbGxlYWNoJywgJ0FuIEdlYXJyYW4nLCAnQW0gTcOgcnQnLCAnQW4gR2libGVhbicsICdBbiBDw6hpdGVhbicsICdBbiB0LcOSZ21oaW9zJywgJ0FuIHQtSXVjaGFyJywgJ0FuIEzDuW5hc3RhbCcsICdBbiB0LVN1bHRhaW4nLCAnQW4gRMOgbWhhaXInLCAnQW4gdC1TYW1oYWluJywgJ0FuIETDuWJobGFjaGQnXG4gICAgXTtcblxuICAgIHZhciBtb250aHNTaG9ydCQ1ID0gWydGYW9pJywgJ0dlYXInLCAnTcOgcnQnLCAnR2libCcsICdDw6hpdCcsICfDkmdtaCcsICdJdWNoJywgJ0zDuW4nLCAnU3VsdCcsICdEw6BtaCcsICdTYW1oJywgJ0TDuWJoJ107XG5cbiAgICB2YXIgd2Vla2RheXMkMiA9IFsnRGlkw7JtaG5haWNoJywgJ0RpbHVhaW4nLCAnRGltw6BpcnQnLCAnRGljaWFkYWluJywgJ0RpYXJkYW9pbicsICdEaWhhb2luZScsICdEaXNhdGhhaXJuZSddO1xuXG4gICAgdmFyIHdlZWtkYXlzU2hvcnQkMSA9IFsnRGlkJywgJ0RpbCcsICdEaW0nLCAnRGljJywgJ0RpYScsICdEaWgnLCAnRGlzJ107XG5cbiAgICB2YXIgd2Vla2RheXNNaW4kMSA9IFsnRMOyJywgJ0x1JywgJ03DoCcsICdDaScsICdBcicsICdIYScsICdTYSddO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdnZCcsIHtcbiAgICAgICAgbW9udGhzIDogbW9udGhzJDYsXG4gICAgICAgIG1vbnRoc1Nob3J0IDogbW9udGhzU2hvcnQkNSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogd2Vla2RheXMkMixcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6IHdlZWtkYXlzU2hvcnQkMSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiB3ZWVrZGF5c01pbiQxLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbQW4tZGl1Z2ggYWlnXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1tBLW3DoGlyZWFjaCBhaWddIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2FpZ10gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbQW4tZMOoIGFpZ10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbc2VvIGNoYWlkaF0gW2FpZ10gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2FubiBhbiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ2JobyBjaGlvbm4gJXMnLFxuICAgICAgICAgICAgcyA6ICdiZWFnYW4gZGlvZ2FuJyxcbiAgICAgICAgICAgIHNzIDogJyVkIGRpb2dhbicsXG4gICAgICAgICAgICBtIDogJ21pb25haWQnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWlvbmFpZGVhbicsXG4gICAgICAgICAgICBoIDogJ3VhaXInLFxuICAgICAgICAgICAgaGggOiAnJWQgdWFpcmVhbicsXG4gICAgICAgICAgICBkIDogJ2xhdGhhJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGxhdGhhJyxcbiAgICAgICAgICAgIE0gOiAnbcOsb3MnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbcOsb3NhbicsXG4gICAgICAgICAgICB5IDogJ2JsaWFkaG5hJyxcbiAgICAgICAgICAgIHl5IDogJyVkIGJsaWFkaG5hJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9KGR8bmF8bWgpLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSBudW1iZXIgPT09IDEgPyAnZCcgOiBudW1iZXIgJSAxMCA9PT0gMiA/ICduYScgOiAnbWgnO1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2dsJywge1xuICAgICAgICBtb250aHMgOiAneGFuZWlyb19mZWJyZWlyb19tYXJ6b19hYnJpbF9tYWlvX3h1w7FvX3h1bGxvX2Fnb3N0b19zZXRlbWJyb19vdXR1YnJvX25vdmVtYnJvX2RlY2VtYnJvJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICd4YW4uX2ZlYi5fbWFyLl9hYnIuX21haS5feHXDsS5feHVsLl9hZ28uX3NldC5fb3V0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogJ2RvbWluZ29fbHVuc19tYXJ0ZXNfbcOpcmNvcmVzX3hvdmVzX3ZlbnJlc19zw6FiYWRvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ2RvbS5fbHVuLl9tYXIuX23DqXIuX3hvdi5fdmVuLl9zw6FiLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnZG9fbHVfbWFfbcOpX3hvX3ZlX3PDoScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1tob3hlICcgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAnw6FzJyA6ICfDoScpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5leHREYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdbbWHDscOhICcgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAnw6FzJyA6ICfDoScpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZGRkZCBbJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICfDoXMnIDogJ2EnKSArICddIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW29udGUgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICfDoScgOiAnYScpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnW29dIGRkZGQgW3Bhc2FkbyAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ8OhcycgOiAnYScpICsgJ10gTFQnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RyLmluZGV4T2YoJ3VuJykgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICduJyArIHN0cjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuICdlbiAnICsgc3RyO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhc3QgOiAnaGFpICVzJyxcbiAgICAgICAgICAgIHMgOiAndW5zIHNlZ3VuZG9zJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNlZ3VuZG9zJyxcbiAgICAgICAgICAgIG0gOiAndW4gbWludXRvJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0b3MnLFxuICAgICAgICAgICAgaCA6ICd1bmhhIGhvcmEnLFxuICAgICAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICAgICAgZCA6ICd1biBkw61hJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGTDrWFzJyxcbiAgICAgICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG1lc2VzJyxcbiAgICAgICAgICAgIHkgOiAndW4gYW5vJyxcbiAgICAgICAgICAgIHl5IDogJyVkIGFub3MnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn3Cui8sXG4gICAgICAgIG9yZGluYWwgOiAnJWTCuicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQ0KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgJ3MnOiBbJ3Rob2RkZSBzZWNvbmRhbmltJywgJ3Rob2RkZSBzZWNvbmQnXSxcbiAgICAgICAgICAgICdzcyc6IFtudW1iZXIgKyAnIHNlY29uZGFuaW0nLCBudW1iZXIgKyAnIHNlY29uZCddLFxuICAgICAgICAgICAgJ20nOiBbJ2VrYSBtaW50YW4nLCAnZWsgbWludXRlJ10sXG4gICAgICAgICAgICAnbW0nOiBbbnVtYmVyICsgJyBtaW50YW5pbScsIG51bWJlciArICcgbWludGFtJ10sXG4gICAgICAgICAgICAnaCc6IFsnZWthIHZvcmFuJywgJ2VrIHZvciddLFxuICAgICAgICAgICAgJ2hoJzogW251bWJlciArICcgdm9yYW5pbScsIG51bWJlciArICcgdm9yYW0nXSxcbiAgICAgICAgICAgICdkJzogWydla2EgZGlzYW4nLCAnZWsgZGlzJ10sXG4gICAgICAgICAgICAnZGQnOiBbbnVtYmVyICsgJyBkaXNhbmltJywgbnVtYmVyICsgJyBkaXMnXSxcbiAgICAgICAgICAgICdNJzogWydla2EgbWhvaW5lYW4nLCAnZWsgbWhvaW5vJ10sXG4gICAgICAgICAgICAnTU0nOiBbbnVtYmVyICsgJyBtaG9pbmVhbmltJywgbnVtYmVyICsgJyBtaG9pbmUnXSxcbiAgICAgICAgICAgICd5JzogWydla2Egdm9yc2FuJywgJ2VrIHZvcm9zJ10sXG4gICAgICAgICAgICAneXknOiBbbnVtYmVyICsgJyB2b3JzYW5pbScsIG51bWJlciArICcgdm9yc2FtJ11cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZ29tLWxhdG4nLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW5lcl9GZWJyZXJfTWFyc19BYnJpbF9NYWlfSnVuX0p1bGFpX0Fnb3N0X1NldGVtYnJfT3R1YnJfTm92ZW1icl9EZXplbWJyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKYW4uX0ZlYi5fTWFyc19BYnIuX01haV9KdW5fSnVsLl9BZ28uX1NldC5fT3R1Ll9Ob3YuX0Rlei4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdBaXRhcl9Tb21hcl9Nb25nbGxhcl9CdWR2YXJfQnJlc3Rhcl9TdWtyYXJfU29uXFwndmFyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ0FpdC5fU29tLl9Nb24uX0J1ZC5fQnJlLl9TdWsuX1Nvbi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ0FpX1NtX01vX0J1X0JyX1N1X1NuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0EgaDptbSBbdmF6dGFdJyxcbiAgICAgICAgICAgIExUUyA6ICdBIGg6bW06c3MgW3ZhenRhXScsXG4gICAgICAgICAgICBMIDogJ0RELU1NLVlZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEEgaDptbSBbdmF6dGFdJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgTU1NTVthY2hlYV0gRG8sIFlZWVksIEEgaDptbSBbdmF6dGFdJyxcbiAgICAgICAgICAgIGxsbGw6ICdkZGQsIEQgTU1NIFlZWVksIEEgaDptbSBbdmF6dGFdJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbQWl6XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0ZhbGVhbV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdbSWV0YSB0b10gZGRkZFssXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0thbF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbRmF0bG9dIGRkZGRbLF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyBhZGltJyxcbiAgICAgICAgICAgIHMgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICBzcyA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIG0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICBtbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIGggOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICBoaCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICBkZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIE0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNCxcbiAgICAgICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDQsXG4gICAgICAgICAgICB5eSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNFxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9KGVyKS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgLy8gdGhlIG9yZGluYWwgJ2VyJyBvbmx5IGFwcGxpZXMgdG8gZGF5IG9mIHRoZSBtb250aFxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ2VyJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1EnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL3JhdGl8c29rYWxsaXxkb25wYXJhbXxzYW5qZS8sXG4gICAgICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICdyYXRpJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc29rYWxsaScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdkb25wYXJhbScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+IDEyID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzYW5qZScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAncmF0aSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAnc29rYWxsaSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNikge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZG9ucGFyYW0nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3NhbmplJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdyYXRpJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCQ2ID0ge1xuICAgICAgICAgICAgJzEnOiAn4KunJyxcbiAgICAgICAgICAgICcyJzogJ+CrqCcsXG4gICAgICAgICAgICAnMyc6ICfgq6knLFxuICAgICAgICAgICAgJzQnOiAn4KuqJyxcbiAgICAgICAgICAgICc1JzogJ+CrqycsXG4gICAgICAgICAgICAnNic6ICfgq6wnLFxuICAgICAgICAgICAgJzcnOiAn4KutJyxcbiAgICAgICAgICAgICc4JzogJ+CrricsXG4gICAgICAgICAgICAnOSc6ICfgq68nLFxuICAgICAgICAgICAgJzAnOiAn4KumJ1xuICAgICAgICB9LFxuICAgICAgICBudW1iZXJNYXAkNSA9IHtcbiAgICAgICAgICAgICfgq6cnOiAnMScsXG4gICAgICAgICAgICAn4KuoJzogJzInLFxuICAgICAgICAgICAgJ+CrqSc6ICczJyxcbiAgICAgICAgICAgICfgq6onOiAnNCcsXG4gICAgICAgICAgICAn4KurJzogJzUnLFxuICAgICAgICAgICAgJ+CrrCc6ICc2JyxcbiAgICAgICAgICAgICfgq60nOiAnNycsXG4gICAgICAgICAgICAn4KuuJzogJzgnLFxuICAgICAgICAgICAgJ+Crryc6ICc5JyxcbiAgICAgICAgICAgICfgq6YnOiAnMCdcbiAgICAgICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnZ3UnLCB7XG4gICAgICAgIG1vbnRoczogJ+CqnOCqvuCqqOCrjeCqr+CrgeCqhuCqsOCrgF/gqqvgq4fgqqzgq43gqrDgq4HgqobgqrDgq4Bf4Kqu4Kq+4Kqw4KuN4KqaX+Cqj+CqquCrjeCqsOCqv+Cqsl/gqq7gq4df4Kqc4KuC4KqoX+CqnOCrgeCqsuCqvuCqiF/gqpHgqpfgqrjgq43gqp9f4Kq44Kqq4KuN4Kqf4KuH4Kqu4KuN4Kqs4KqwX+CqkeCqleCrjeCqn+CrjeCqrOCqsF/gqqjgqrXgq4fgqq7gq43gqqzgqrBf4Kqh4Kq/4Kq44KuH4Kqu4KuN4Kqs4KqwJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydDogJ+CqnOCqvuCqqOCrjeCqr+CrgS5f4Kqr4KuH4Kqs4KuN4Kqw4KuBLl/gqq7gqr7gqrDgq43gqppf4KqP4Kqq4KuN4Kqw4Kq/Ll/gqq7gq4df4Kqc4KuC4KqoX+CqnOCrgeCqsuCqvi5f4KqR4KqXLl/gqrjgqqrgq43gqp/gq4cuX+CqkeCqleCrjeCqn+CrjS5f4Kqo4Kq14KuHLl/gqqHgqr/gqrjgq4cuJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ+CqsOCqteCqv+CqteCqvuCqsF/gqrjgq4vgqq7gqrXgqr7gqrBf4Kqu4KqC4KqX4Kqz4Kq14Kq+4KqwX+CqrOCrgeCqp+CrjeCqteCqvuCqsF/gqpfgq4HgqrDgq4HgqrXgqr7gqrBf4Kq24KuB4KqV4KuN4Kqw4Kq14Kq+4KqwX+CqtuCqqOCqv+CqteCqvuCqsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+CqsOCqteCqv1/gqrjgq4vgqq5f4Kqu4KqC4KqX4KqzX+CqrOCrgeCqp+CrjV/gqpfgq4HgqrDgq4Ff4Kq24KuB4KqV4KuN4KqwX+CqtuCqqOCqvycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfgqrBf4Kq44KuLX+CqruCqgl/gqqzgq4Ff4KqX4KuBX+CqtuCrgV/gqrYnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0EgaDptbSDgqrXgqr7gqpfgq43gqq/gq4cnLFxuICAgICAgICAgICAgTFRTOiAnQSBoOm1tOnNzIOCqteCqvuCql+CrjeCqr+CrhycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0g4Kq14Kq+4KqX4KuN4Kqv4KuHJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tIOCqteCqvuCql+CrjeCqr+CrhydcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb4KqG4KqcXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW+CqleCqvuCqsuCrh10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkLCBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW+Cql+Cqh+CqleCqvuCqsuCrh10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdb4Kqq4Kq+4Kqb4Kqy4Kq+XSBkZGRkLCBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnJXMg4Kqu4Kq+JyxcbiAgICAgICAgICAgIHBhc3Q6ICclcyDgqqrgq4fgqrngqrLgqr4nLFxuICAgICAgICAgICAgczogJ+CqheCqruCrgeCqlSDgqqrgqrPgq4snLFxuICAgICAgICAgICAgc3M6ICclZCDgqrjgq4fgqpXgqoLgqqEnLFxuICAgICAgICAgICAgbTogJ+Cqj+CqlSDgqq7gqr/gqqjgqr/gqp8nLFxuICAgICAgICAgICAgbW06ICclZCDgqq7gqr/gqqjgqr/gqp8nLFxuICAgICAgICAgICAgaDogJ+Cqj+CqlSDgqpXgqrLgqr7gqpUnLFxuICAgICAgICAgICAgaGg6ICclZCDgqpXgqrLgqr7gqpUnLFxuICAgICAgICAgICAgZDogJ+Cqj+CqlSDgqqbgqr/gqrXgqrgnLFxuICAgICAgICAgICAgZGQ6ICclZCDgqqbgqr/gqrXgqrgnLFxuICAgICAgICAgICAgTTogJ+Cqj+CqlSDgqq7gqrngqr/gqqjgq4snLFxuICAgICAgICAgICAgTU06ICclZCDgqq7gqrngqr/gqqjgq4snLFxuICAgICAgICAgICAgeTogJ+Cqj+CqlSDgqrXgqrDgq43gqrcnLFxuICAgICAgICAgICAgeXk6ICclZCDgqrXgqrDgq43gqrcnXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgq6fgq6jgq6ngq6rgq6vgq6zgq63gq67gq6/gq6ZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkNVttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQ2W21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICAvLyBHdWphcmF0aSBub3RhdGlvbiBmb3IgbWVyaWRpZW1zIGFyZSBxdWl0ZSBmdXp6eSBpbiBwcmFjdGljZS4gV2hpbGUgdGhlcmUgZXhpc3RzXG4gICAgICAgIC8vIGEgcmlnaWQgbm90aW9uIG9mIGEgJ1BhaGFyJyBpdCBpcyBub3QgdXNlZCBhcyByaWdpZGx5IGluIG1vZGVybiBHdWphcmF0aS5cbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+CqsOCqvuCqpHzgqqzgqqrgq4vgqrB84Kq44Kq14Kq+4KqwfOCquOCqvuCqguCqnC8sXG4gICAgICAgIG1lcmlkaWVtSG91cjogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+CqsOCqvuCqpCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA8IDQgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CquOCqteCqvuCqsCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqqzgqqrgq4vgqrAnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CquOCqvuCqguCqnCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgqrDgqr7gqqQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CquOCqteCqvuCqsCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kqs4Kqq4KuL4KqwJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgqrjgqr7gqoLgqpwnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CqsOCqvuCqpCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDYgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2hlJywge1xuICAgICAgICBtb250aHMgOiAn15nXoNeV15DXqF/XpNeR16jXldeQ16hf157XqNelX9eQ16TXqNeZ15xf157XkNeZX9eZ15XXoNeZX9eZ15XXnNeZX9eQ15XXkteV16HXmF/Xodek15jXnteR16hf15DXlden15jXldeR16hf16DXldeR157XkdeoX9eT16bXnteR16gnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ9eZ16DXldezX9ek15HXqNezX9ee16jXpV/XkNek16jXs1/XnteQ15lf15nXldeg15lf15nXldec15lf15DXldeS17Nf16HXpNeY17Nf15DXlden17Nf16DXldeR17Nf15PXptee17MnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ9eo15DXqdeV159f16nXoNeZX9ep15zXmdep15lf16jXkdeZ16LXmV/Xl9ee15nXqdeZX9ep15nXqdeZX9ep15HXqicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfXkNezX9eR17Nf15LXs1/Xk9ezX9eU17Nf15XXs1/XqdezJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfXkF/XkV/Xkl/Xk1/XlF/XlV/XqScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgW9eRXU1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBb15FdTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBb15FdTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIGwgOiAnRC9NL1lZWVknLFxuICAgICAgICAgICAgbGwgOiAnRCBNTU0gWVlZWScsXG4gICAgICAgICAgICBsbGwgOiAnRCBNTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBsbGxsIDogJ2RkZCwgRCBNTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1vXlNeZ15XXnSDXkda+XUxUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW9ee15fXqCDXkda+XUxUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW9eR16nXoteUXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1vXkNeq157XldecINeR1r5dTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW9eR15nXldedXSBkZGRkIFvXlNeQ15fXqNeV158g15HXqdei15RdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfXkdei15XXkyAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ9ec16TXoNeZICVzJyxcbiAgICAgICAgICAgIHMgOiAn157Xodek16gg16nXoNeZ15XXqicsXG4gICAgICAgICAgICBzcyA6ICclZCDXqdeg15nXldeqJyxcbiAgICAgICAgICAgIG0gOiAn15PXp9eUJyxcbiAgICAgICAgICAgIG1tIDogJyVkINeT16fXldeqJyxcbiAgICAgICAgICAgIGggOiAn16nXoteUJyxcbiAgICAgICAgICAgIGhoIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICfXqdei16rXmdeZ150nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXqdei15XXqic7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZCA6ICfXmdeV150nLFxuICAgICAgICAgICAgZGQgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ9eZ15XXnteZ15nXnSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnINeZ157XmdedJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBNIDogJ9eX15XXk9epJyxcbiAgICAgICAgICAgIE1NIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICfXl9eV15PXqdeZ15nXnSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnINeX15XXk9ep15nXnSc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeSA6ICfXqdeg15QnLFxuICAgICAgICAgICAgeXkgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ9ep16DXqteZ15nXnSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgJSAxMCA9PT0gMCAmJiBudW1iZXIgIT09IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnINep16DXlCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnINep16DXmdedJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9eQ15fXlFwi16Z815zXpNeg15RcItemfNeQ15fXqNeZINeU16bXlNeo15nXmdedfNec16TXoNeZINeU16bXlNeo15nXmdedfNec16TXoNeV16og15HXlden16h815HXkdeV16fXqHzXkdei16jXkS9pLFxuICAgICAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gL14o15DXl9eUXCLXpnzXkNeX16jXmSDXlNem15TXqNeZ15nXnXzXkdei16jXkSkkLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9ec16TXoNeV16og15HXlden16gnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9eR15HXlden16gnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfXnNek16DXlFwi16YnIDogJ9ec16TXoNeZINeU16bXlNeo15nXmdedJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAn15DXl9eUXCLXpicgOiAn15DXl9eo15kg15TXpteU16jXmdeZ150nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9eR16LXqNeRJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCQ3ID0ge1xuICAgICAgICAnMSc6ICfgpacnLFxuICAgICAgICAnMic6ICfgpagnLFxuICAgICAgICAnMyc6ICfgpaknLFxuICAgICAgICAnNCc6ICfgpaonLFxuICAgICAgICAnNSc6ICfgpasnLFxuICAgICAgICAnNic6ICfgpawnLFxuICAgICAgICAnNyc6ICfgpa0nLFxuICAgICAgICAnOCc6ICfgpa4nLFxuICAgICAgICAnOSc6ICfgpa8nLFxuICAgICAgICAnMCc6ICfgpaYnXG4gICAgfSxcbiAgICBudW1iZXJNYXAkNiA9IHtcbiAgICAgICAgJ+Clpyc6ICcxJyxcbiAgICAgICAgJ+ClqCc6ICcyJyxcbiAgICAgICAgJ+ClqSc6ICczJyxcbiAgICAgICAgJ+Clqic6ICc0JyxcbiAgICAgICAgJ+Clqyc6ICc1JyxcbiAgICAgICAgJ+ClrCc6ICc2JyxcbiAgICAgICAgJ+ClrSc6ICc3JyxcbiAgICAgICAgJ+Clric6ICc4JyxcbiAgICAgICAgJ+Clryc6ICc5JyxcbiAgICAgICAgJ+Clpic6ICcwJ1xuICAgIH07XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2hpJywge1xuICAgICAgICBtb250aHMgOiAn4KSc4KSo4KS14KSw4KWAX+Ckq+CkvOCksOCkteCksOClgF/gpK7gpL7gpLDgpY3gpJpf4KSF4KSq4KWN4KSw4KWI4KSyX+CkruCkiF/gpJzgpYLgpKhf4KSc4KWB4KSy4KS+4KSIX+CkheCkl+CkuOCljeCkpF/gpLjgpL/gpKTgpK7gpY3gpKzgpLBf4KSF4KSV4KWN4KSf4KWC4KSs4KSwX+CkqOCkteCkruCljeCkrOCksF/gpKbgpL/gpLjgpK7gpY3gpKzgpLAnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ+CknOCkqC5f4KSr4KS84KSwLl/gpK7gpL7gpLDgpY3gpJpf4KSF4KSq4KWN4KSw4KWILl/gpK7gpIhf4KSc4KWC4KSoX+CknOClgeCksi5f4KSF4KSXLl/gpLjgpL/gpKQuX+CkheCkleCljeCkn+Clgi5f4KSo4KS1Ll/gpKbgpL/gpLguJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICfgpLDgpLXgpL/gpLXgpL7gpLBf4KS44KWL4KSu4KS14KS+4KSwX+CkruCkguCkl+CksuCkteCkvuCksF/gpKzgpYHgpKfgpLXgpL7gpLBf4KSX4KWB4KSw4KWC4KS14KS+4KSwX+CktuClgeCkleCljeCksOCkteCkvuCksF/gpLbgpKjgpL/gpLXgpL7gpLAnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn4KSw4KS14KS/X+CkuOCli+Ckrl/gpK7gpILgpJfgpLJf4KSs4KWB4KSnX+Ckl+ClgeCksOClgl/gpLbgpYHgpJXgpY3gpLBf4KS24KSo4KS/Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfgpLBf4KS44KWLX+CkruCkgl/gpKzgpYFf4KSX4KWBX+CktuClgV/gpLYnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnQSBoOm1tIOCkrOCknOClhycsXG4gICAgICAgICAgICBMVFMgOiAnQSBoOm1tOnNzIOCkrOCknOClhycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0g4KSs4KSc4KWHJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgpKzgpJzgpYcnXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb4KSG4KScXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vgpJXgpLJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW+CkleCksl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW+CkquCkv+Ckm+CksuClh10gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVzIOCkruClh+CkgicsXG4gICAgICAgICAgICBwYXN0IDogJyVzIOCkquCkueCksuClhycsXG4gICAgICAgICAgICBzIDogJ+CkleClgeCkmyDgpLngpYAg4KSV4KWN4KS34KSjJyxcbiAgICAgICAgICAgIHNzIDogJyVkIOCkuOClh+CkleCkguCkoScsXG4gICAgICAgICAgICBtIDogJ+Ckj+CklSDgpK7gpL/gpKjgpJ8nLFxuICAgICAgICAgICAgbW0gOiAnJWQg4KSu4KS/4KSo4KSfJyxcbiAgICAgICAgICAgIGggOiAn4KSP4KSVIOCkmOCkguCkn+CkvicsXG4gICAgICAgICAgICBoaCA6ICclZCDgpJjgpILgpJ/gpYcnLFxuICAgICAgICAgICAgZCA6ICfgpI/gpJUg4KSm4KS/4KSoJyxcbiAgICAgICAgICAgIGRkIDogJyVkIOCkpuCkv+CkqCcsXG4gICAgICAgICAgICBNIDogJ+Ckj+CklSDgpK7gpLngpYDgpKjgpYcnLFxuICAgICAgICAgICAgTU0gOiAnJWQg4KSu4KS54KWA4KSo4KWHJyxcbiAgICAgICAgICAgIHkgOiAn4KSP4KSVIOCkteCksOCljeCktycsXG4gICAgICAgICAgICB5eSA6ICclZCDgpLXgpLDgpY3gpLcnXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgpafgpajgpangpargpavgpazgpa3gpa7gpa/gpaZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkNlttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQ3W21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICAvLyBIaW5kaSBub3RhdGlvbiBmb3IgbWVyaWRpZW1zIGFyZSBxdWl0ZSBmdXp6eSBpbiBwcmFjdGljZS4gV2hpbGUgdGhlcmUgZXhpc3RzXG4gICAgICAgIC8vIGEgcmlnaWQgbm90aW9uIG9mIGEgJ1BhaGFyJyBpdCBpcyBub3QgdXNlZCBhcyByaWdpZGx5IGluIG1vZGVybiBIaW5kaS5cbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+CksOCkvuCkpHzgpLjgpYHgpKzgpLl84KSm4KWL4KSq4KS54KSwfOCktuCkvuCkri8sXG4gICAgICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgpLDgpL7gpKQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgpLjgpYHgpKzgpLknKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KSm4KWL4KSq4KS54KSwJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgpLbgpL7gpK4nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CksOCkvuCkpCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KS44KWB4KSs4KS5JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpKbgpYvgpKrgpLngpLAnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CktuCkvuCkric7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSkJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkMyhudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmRhJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kZSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmRpJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2plZG5hIG1pbnV0YScgOiAnamVkbmUgbWludXRlJztcbiAgICAgICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRhJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRlJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21pbnV0YSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdqZWRhbiBzYXQnIDogJ2plZG5vZyBzYXRhJztcbiAgICAgICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2F0JztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2F0YSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXRpJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZGFuJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2RhbmEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWMnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWNhJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21qZXNlY2knO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmUnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZ29kaW5hJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnaHInLCB7XG4gICAgICAgIG1vbnRocyA6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ3NpamXEjW5qYV92ZWxqYcSNZV9vxb51amthX3RyYXZuamFfc3ZpYm5qYV9saXBuamFfc3JwbmphX2tvbG92b3phX3J1am5hX2xpc3RvcGFkYV9zdHVkZW5vZ2FfcHJvc2luY2EnLnNwbGl0KCdfJyksXG4gICAgICAgICAgICBzdGFuZGFsb25lOiAnc2lqZcSNYW5qX3ZlbGphxI1hX2/FvnVqYWtfdHJhdmFual9zdmliYW5qX2xpcGFual9zcnBhbmpfa29sb3Zvel9ydWphbl9saXN0b3BhZF9zdHVkZW5pX3Byb3NpbmFjJy5zcGxpdCgnXycpXG4gICAgICAgIH0sXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ3Npai5fdmVsai5fb8W+dS5fdHJhLl9zdmkuX2xpcC5fc3JwLl9rb2wuX3J1ai5fbGlzLl9zdHUuX3Byby4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogJ25lZGplbGphX3BvbmVkamVsamFrX3V0b3Jha19zcmlqZWRhX8SNZXR2cnRha19wZXRha19zdWJvdGEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnbmVkLl9wb24uX3V0by5fc3JpLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ25lX3BvX3V0X3NyX8SNZV9wZV9zdScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSAgOiAnW2RhbmFzIHVdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgIDogJ1tzdXRyYSB1XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW25lZGplbGp1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbc3JpamVkdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3N1Ym90dV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5ICA6ICdbanXEjWVyIHVdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbHVdIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsZV0gW3N1Ym90ZV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsaV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnemEgJXMnLFxuICAgICAgICAgICAgcGFzdCAgIDogJ3ByaWplICVzJyxcbiAgICAgICAgICAgIHMgICAgICA6ICdwYXIgc2VrdW5kaScsXG4gICAgICAgICAgICBzcyAgICAgOiB0cmFuc2xhdGUkMyxcbiAgICAgICAgICAgIG0gICAgICA6IHRyYW5zbGF0ZSQzLFxuICAgICAgICAgICAgbW0gICAgIDogdHJhbnNsYXRlJDMsXG4gICAgICAgICAgICBoICAgICAgOiB0cmFuc2xhdGUkMyxcbiAgICAgICAgICAgIGhoICAgICA6IHRyYW5zbGF0ZSQzLFxuICAgICAgICAgICAgZCAgICAgIDogJ2RhbicsXG4gICAgICAgICAgICBkZCAgICAgOiB0cmFuc2xhdGUkMyxcbiAgICAgICAgICAgIE0gICAgICA6ICdtamVzZWMnLFxuICAgICAgICAgICAgTU0gICAgIDogdHJhbnNsYXRlJDMsXG4gICAgICAgICAgICB5ICAgICAgOiAnZ29kaW51JyxcbiAgICAgICAgICAgIHl5ICAgICA6IHRyYW5zbGF0ZSQzXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgd2Vla0VuZGluZ3MgPSAndmFzw6FybmFwIGjDqXRmxZFuIGtlZGRlbiBzemVyZMOhbiBjc8O8dMO2cnTDtmvDtm4gcMOpbnRla2VuIHN6b21iYXRvbicuc3BsaXQoJyAnKTtcbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkNChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIG51bSA9IG51bWJlcjtcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCkgPyAnbsOpaMOhbnkgbcOhc29kcGVyYycgOiAnbsOpaMOhbnkgbcOhc29kcGVyY2UnO1xuICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCkgPyAnIG3DoXNvZHBlcmMnIDogJyBtw6Fzb2RwZXJjZSc7XG4gICAgICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2VneScgKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgcGVyYycgOiAnIHBlcmNlJyk7XG4gICAgICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBwZXJjJyA6ICcgcGVyY2UnKTtcbiAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyDDs3JhJyA6ICcgw7Nyw6FqYScpO1xuICAgICAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgw7NyYScgOiAnIMOzcsOhamEnKTtcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBuYXAnIDogJyBuYXBqYScpO1xuICAgICAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgbmFwJyA6ICcgbmFwamEnKTtcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBow7NuYXAnIDogJyBow7NuYXBqYScpO1xuICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgaMOzbmFwJyA6ICcgaMOzbmFwamEnKTtcbiAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyDDqXYnIDogJyDDqXZlJyk7XG4gICAgICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyDDqXYnIDogJyDDqXZlJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICBmdW5jdGlvbiB3ZWVrKGlzRnV0dXJlKSB7XG4gICAgICAgIHJldHVybiAoaXNGdXR1cmUgPyAnJyA6ICdbbcO6bHRdICcpICsgJ1snICsgd2Vla0VuZGluZ3NbdGhpcy5kYXkoKV0gKyAnXSBMVFsta29yXSc7XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdodScsIHtcbiAgICAgICAgbW9udGhzIDogJ2phbnXDoXJfZmVicnXDoXJfbcOhcmNpdXNfw6FwcmlsaXNfbcOhanVzX2rDum5pdXNfasO6bGl1c19hdWd1c3p0dXNfc3plcHRlbWJlcl9va3TDs2Jlcl9ub3ZlbWJlcl9kZWNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnamFuX2ZlYl9tw6FyY1/DoXByX23DoWpfasO6bl9qw7psX2F1Z19zemVwdF9va3Rfbm92X2RlYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAndmFzw6FybmFwX2jDqXRmxZFfa2VkZF9zemVyZGFfY3PDvHTDtnJ0w7ZrX3DDqW50ZWtfc3pvbWJhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICd2YXNfaMOpdF9rZWRkX3N6ZV9jc8O8dF9ww6luX3N6bycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAndl9oX2tfc3plX2NzX3Bfc3pvJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdZWVlZLk1NLkRELicsXG4gICAgICAgICAgICBMTCA6ICdZWVlZLiBNTU1NIEQuJyxcbiAgICAgICAgICAgIExMTCA6ICdZWVlZLiBNTU1NIEQuIEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdZWVlZLiBNTU1NIEQuLCBkZGRkIEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9kZXxkdS9pLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dC5jaGFyQXQoMSkudG9Mb3dlckNhc2UoKSA9PT0gJ3UnO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXJzIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA9PT0gdHJ1ZSA/ICdkZScgOiAnREUnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA9PT0gdHJ1ZSA/ICdkdScgOiAnRFUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW21hXSBMVFsta29yXScsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1tob2xuYXBdIExUWy1rb3JdJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ZWVrLmNhbGwodGhpcywgdHJ1ZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheSA6ICdbdGVnbmFwXSBMVFsta29yXScsXG4gICAgICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd2Vlay5jYWxsKHRoaXMsIGZhbHNlKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnJXMgbcO6bHZhJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMnLFxuICAgICAgICAgICAgcyA6IHRyYW5zbGF0ZSQ0LFxuICAgICAgICAgICAgc3MgOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgICAgIG0gOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgICAgIG1tIDogdHJhbnNsYXRlJDQsXG4gICAgICAgICAgICBoIDogdHJhbnNsYXRlJDQsXG4gICAgICAgICAgICBoaCA6IHRyYW5zbGF0ZSQ0LFxuICAgICAgICAgICAgZCA6IHRyYW5zbGF0ZSQ0LFxuICAgICAgICAgICAgZGQgOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgICAgIE0gOiB0cmFuc2xhdGUkNCxcbiAgICAgICAgICAgIE1NIDogdHJhbnNsYXRlJDQsXG4gICAgICAgICAgICB5IDogdHJhbnNsYXRlJDQsXG4gICAgICAgICAgICB5eSA6IHRyYW5zbGF0ZSQ0XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2h5LWFtJywge1xuICAgICAgICBtb250aHMgOiB7XG4gICAgICAgICAgICBmb3JtYXQ6ICfVsNW41oLVttW+1aHWgNWrX9aD1aXVv9aA1b7VodaA1atf1bTVodaA1b/Vq1/VodW61oDVq9Ws1atf1bTVodW11avVvdWrX9Ww1bjWgtW21avVvdWrX9Ww1bjWgtWs1avVvdWrX9aF1aPVuNW91b/VuNW91atf1b3VpdW61b/VpdW01aLVpdaA1atf1bDVuNWv1b/VpdW01aLVpdaA1atf1bbVuNW11aXVtNWi1aXWgNWrX9Wk1aXVr9W/1aXVtNWi1aXWgNWrJy5zcGxpdCgnXycpLFxuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ9Ww1bjWgtW21b7VodaAX9aD1aXVv9aA1b7VodaAX9W01aHWgNW/X9Wh1brWgNWr1axf1bTVodW11avVvV/VsNW41oLVttWr1b1f1bDVuNaC1azVq9W9X9aF1aPVuNW91b/VuNW9X9W91aXVutW/1aXVtNWi1aXWgF/VsNW41a/Vv9Wl1bTVotWl1oBf1bbVuNW11aXVtNWi1aXWgF/VpNWl1a/Vv9Wl1bTVotWl1oAnLnNwbGl0KCdfJylcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn1bDVttW+X9aD1b/WgF/VtNaA1b9f1aHVutaAX9W01bXVvV/VsNW21b1f1bDVrNW9X9aF1aPVvV/VvdW61b9f1bDVr9W/X9W21bTVol/VpNWv1b8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ9Wv1avWgNWh1a/Vq1/VpdaA1a/VuNaC1bfVodWi1anVq1/VpdaA1aXWhNW31aHVotWp1atf1bnVuNaA1aXWhNW31aHVotWp1atf1bDVq9W21aPVt9Wh1aLVqdWrX9W41oLWgNWi1aHVqV/Vt9Wh1aLVodWpJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ9Wv1oDVr1/VpdaA1a9f1aXWgNaEX9W51oDWhF/VsNW21aNf1bjWgtaA1aJf1bfVotWpJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfVr9aA1a9f1aXWgNWvX9Wl1oDWhF/VudaA1oRf1bDVttWjX9W41oLWgNWiX9W31aLVqScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZINWpLicsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkg1akuLCBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZINWpLiwgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1vVodW11b3WhdaAXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW9W+1aHVstWoXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9Wl1oDVpdWvXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZGRkZCBb1oXWgNWoINWq1aHVtNWoXSBMVCc7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1vVodW21oHVodWuXSBkZGRkIFvWhdaA1agg1arVodW01ahdIExUJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyDVsNWl1b/VuCcsXG4gICAgICAgICAgICBwYXN0IDogJyVzINWh1bzVodW7JyxcbiAgICAgICAgICAgIHMgOiAn1bTVqyDWhNWh1bbVqyDVvtWh1bXWgNWv1bXVodW2JyxcbiAgICAgICAgICAgIHNzIDogJyVkINW+1aHVtdaA1a/VtdWh1bYnLFxuICAgICAgICAgICAgbSA6ICfWgNW41brVpScsXG4gICAgICAgICAgICBtbSA6ICclZCDWgNW41brVpScsXG4gICAgICAgICAgICBoIDogJ9Wq1aHVtCcsXG4gICAgICAgICAgICBoaCA6ICclZCDVqtWh1bQnLFxuICAgICAgICAgICAgZCA6ICfWhdaAJyxcbiAgICAgICAgICAgIGRkIDogJyVkINaF1oAnLFxuICAgICAgICAgICAgTSA6ICfVodW01avVvScsXG4gICAgICAgICAgICBNTSA6ICclZCDVodW01avVvScsXG4gICAgICAgICAgICB5IDogJ9W/1aHWgNWrJyxcbiAgICAgICAgICAgIHl5IDogJyVkINW/1aHWgNWrJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv1aPVq9W31aXWgNW+1aF81aHVvNWh1b7VuNW/1b7VoXzWgdWl1oDVpdWv1b7VoXzVpdaA1aXVr9W41bXVodW2LyxcbiAgICAgICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gL14o1oHVpdaA1aXVr9W+1aF81aXWgNWl1a/VuNW11aHVtikkLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfVo9Wr1bfVpdaA1b7VoSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn1aHVvNWh1b7VuNW/1b7VoSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn1oHVpdaA1aXVr9W+1aEnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9Wl1oDVpdWv1bjVtdWh1bYnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn18XFxkezEsMn0tKNWr1bZ81oDVpCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICBjYXNlICdERERvJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct1avVtic7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct1oDVpCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2lkJywge1xuICAgICAgICBtb250aHMgOiAnSmFudWFyaV9GZWJydWFyaV9NYXJldF9BcHJpbF9NZWlfSnVuaV9KdWxpX0FndXN0dXNfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGVzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NZWlfSnVuX0p1bF9BZ3RfU2VwX09rdF9Ob3ZfRGVzJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdNaW5nZ3VfU2VuaW5fU2VsYXNhX1JhYnVfS2FtaXNfSnVtYXRfU2FidHUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnTWluX1Nlbl9TZWxfUmFiX0thbV9KdW1fU2FiJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdNZ19Tbl9TbF9SYl9LbV9KbV9TYicuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISC5tbScsXG4gICAgICAgICAgICBMVFMgOiAnSEgubW0uc3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbSdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL3BhZ2l8c2lhbmd8c29yZXxtYWxhbS8sXG4gICAgICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICdwYWdpJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3NpYW5nJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzb3JlJyB8fCBtZXJpZGllbSA9PT0gJ21hbGFtJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPCAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAncGFnaSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3NpYW5nJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnc29yZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAnbWFsYW0nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW0hhcmkgaW5pIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1tCZXNvayBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW0tlbWFyaW4gcHVrdWxdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW2xhbHUgcHVrdWxdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdkYWxhbSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJyVzIHlhbmcgbGFsdScsXG4gICAgICAgICAgICBzIDogJ2JlYmVyYXBhIGRldGlrJyxcbiAgICAgICAgICAgIHNzIDogJyVkIGRldGlrJyxcbiAgICAgICAgICAgIG0gOiAnc2VtZW5pdCcsXG4gICAgICAgICAgICBtbSA6ICclZCBtZW5pdCcsXG4gICAgICAgICAgICBoIDogJ3NlamFtJyxcbiAgICAgICAgICAgIGhoIDogJyVkIGphbScsXG4gICAgICAgICAgICBkIDogJ3NlaGFyaScsXG4gICAgICAgICAgICBkZCA6ICclZCBoYXJpJyxcbiAgICAgICAgICAgIE0gOiAnc2VidWxhbicsXG4gICAgICAgICAgICBNTSA6ICclZCBidWxhbicsXG4gICAgICAgICAgICB5IDogJ3NldGFodW4nLFxuICAgICAgICAgICAgeXkgOiAnJWQgdGFodW4nXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcGx1cmFsJDIobikge1xuICAgICAgICBpZiAobiAlIDEwMCA9PT0gMTEpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGVsc2UgaWYgKG4gJSAxMCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkNShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ25va2tyYXIgc2Vrw7puZHVyJyA6ICdub2trcnVtIHNla8O6bmR1bSc7XG4gICAgICAgICAgICBjYXNlICdzcyc6XG4gICAgICAgICAgICAgICAgaWYgKHBsdXJhbCQyKG51bWJlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ3Nla8O6bmR1cicgOiAnc2Vrw7puZHVtJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnc2Vrw7puZGEnO1xuICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnbcOtbsO6dGEnIDogJ23DrW7DunR1JztcbiAgICAgICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgICAgICBpZiAocGx1cmFsJDIobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbcOtbsO6dHVyJyA6ICdtw61uw7p0dW0nKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdtw61uw7p0YSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbcOtbsO6dHUnO1xuICAgICAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgICAgIGlmIChwbHVyYWwkMihudW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdrbHVra3VzdHVuZGlyJyA6ICdrbHVra3VzdHVuZHVtJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAna2x1a2t1c3R1bmQnO1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdkYWd1cic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdkYWcnIDogJ2RlZ2knO1xuICAgICAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgICAgIGlmIChwbHVyYWwkMihudW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2RhZ2FyJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKGlzRnV0dXJlID8gJ2RhZ2EnIDogJ2TDtmd1bScpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2RhZ3VyJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChpc0Z1dHVyZSA/ICdkYWcnIDogJ2RlZ2knKTtcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnbcOhbnXDsHVyJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ23DoW51w7AnIDogJ23DoW51w7BpJztcbiAgICAgICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgICAgICBpZiAocGx1cmFsJDIobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdtw6FudcOwaXInO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoaXNGdXR1cmUgPyAnbcOhbnXDsGknIDogJ23DoW51w7B1bScpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ23DoW51w7B1cic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoaXNGdXR1cmUgPyAnbcOhbnXDsCcgOiAnbcOhbnXDsGknKTtcbiAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ8OhcicgOiAnw6FyaSc7XG4gICAgICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICAgICAgaWYgKHBsdXJhbCQyKG51bWJlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ8OhcicgOiAnw6FydW0nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ8OhcicgOiAnw6FyaScpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdpcycsIHtcbiAgICAgICAgbW9udGhzIDogJ2phbsO6YXJfZmVicsO6YXJfbWFyc19hcHLDrWxfbWHDrV9qw7puw61fasO6bMOtX8OhZ8O6c3Rfc2VwdGVtYmVyX29rdMOzYmVyX27Ds3ZlbWJlcl9kZXNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnamFuX2ZlYl9tYXJfYXByX21hw61fasO6bl9qw7psX8OhZ8O6X3NlcF9va3RfbsOzdl9kZXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ3N1bm51ZGFndXJfbcOhbnVkYWd1cl/DvnJpw7BqdWRhZ3VyX21pw7B2aWt1ZGFndXJfZmltbXR1ZGFndXJfZsO2c3R1ZGFndXJfbGF1Z2FyZGFndXInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnc3VuX23DoW5fw75yaV9tacOwX2ZpbV9mw7ZzX2xhdScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnU3VfTcOhX8Oecl9NaV9GaV9Gw7ZfTGEnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgW2tsLl0gSDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBba2wuXSBIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW8OtIGRhZyBrbC5dIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW8OhIG1vcmd1biBrbC5dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2tsLl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbw60gZ8OmciBrbC5dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1tzw63DsGFzdGFdIGRkZGQgW2tsLl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2VmdGlyICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnZnlyaXIgJXMgc8Otw7BhbicsXG4gICAgICAgICAgICBzIDogdHJhbnNsYXRlJDUsXG4gICAgICAgICAgICBzcyA6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICAgICAgbSA6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICAgICAgbW0gOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgICAgIGggOiAna2x1a2t1c3R1bmQnLFxuICAgICAgICAgICAgaGggOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgICAgIGQgOiB0cmFuc2xhdGUkNSxcbiAgICAgICAgICAgIGRkIDogdHJhbnNsYXRlJDUsXG4gICAgICAgICAgICBNIDogdHJhbnNsYXRlJDUsXG4gICAgICAgICAgICBNTSA6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICAgICAgeSA6IHRyYW5zbGF0ZSQ1LFxuICAgICAgICAgICAgeXkgOiB0cmFuc2xhdGUkNVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdpdC1jaCcsIHtcbiAgICAgICAgbW9udGhzIDogJ2dlbm5haW9fZmViYnJhaW9fbWFyem9fYXByaWxlX21hZ2dpb19naXVnbm9fbHVnbGlvX2Fnb3N0b19zZXR0ZW1icmVfb3R0b2JyZV9ub3ZlbWJyZV9kaWNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnZ2VuX2ZlYl9tYXJfYXByX21hZ19naXVfbHVnX2Fnb19zZXRfb3R0X25vdl9kaWMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ2RvbWVuaWNhX2x1bmVkw6xfbWFydGVkw6xfbWVyY29sZWTDrF9naW92ZWTDrF92ZW5lcmTDrF9zYWJhdG8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnZG9tX2x1bl9tYXJfbWVyX2dpb192ZW5fc2FiJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdkb19sdV9tYV9tZV9naV92ZV9zYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tPZ2dpIGFsbGVdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbRG9tYW5pIGFsbGVdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYWxsZV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tJZXJpIGFsbGVdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW2xhIHNjb3JzYV0gZGRkZCBbYWxsZV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbG8gc2NvcnNvXSBkZGRkIFthbGxlXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKCgvXlswLTldLiskLykudGVzdChzKSA/ICd0cmEnIDogJ2luJykgKyAnICcgKyBzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgZmEnLFxuICAgICAgICAgICAgcyA6ICdhbGN1bmkgc2Vjb25kaScsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWNvbmRpJyxcbiAgICAgICAgICAgIG0gOiAndW4gbWludXRvJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0aScsXG4gICAgICAgICAgICBoIDogJ3VuXFwnb3JhJyxcbiAgICAgICAgICAgIGhoIDogJyVkIG9yZScsXG4gICAgICAgICAgICBkIDogJ3VuIGdpb3JubycsXG4gICAgICAgICAgICBkZCA6ICclZCBnaW9ybmknLFxuICAgICAgICAgICAgTSA6ICd1biBtZXNlJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG1lc2knLFxuICAgICAgICAgICAgeSA6ICd1biBhbm5vJyxcbiAgICAgICAgICAgIHl5IDogJyVkIGFubmknXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn3Cui8sXG4gICAgICAgIG9yZGluYWw6ICclZMK6JyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2l0Jywge1xuICAgICAgICBtb250aHMgOiAnZ2VubmFpb19mZWJicmFpb19tYXJ6b19hcHJpbGVfbWFnZ2lvX2dpdWdub19sdWdsaW9fYWdvc3RvX3NldHRlbWJyZV9vdHRvYnJlX25vdmVtYnJlX2RpY2VtYnJlJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdnZW5fZmViX21hcl9hcHJfbWFnX2dpdV9sdWdfYWdvX3NldF9vdHRfbm92X2RpYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnZG9tZW5pY2FfbHVuZWTDrF9tYXJ0ZWTDrF9tZXJjb2xlZMOsX2dpb3ZlZMOsX3ZlbmVyZMOsX3NhYmF0bycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdkb21fbHVuX21hcl9tZXJfZ2lvX3Zlbl9zYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ2RvX2x1X21hX21lX2dpX3ZlX3NhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW09nZ2kgYWxsZV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tEb21hbmkgYWxsZV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFthbGxlXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW0llcmkgYWxsZV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbGEgc2NvcnNhXSBkZGRkIFthbGxlXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tsbyBzY29yc29dIGRkZGQgW2FsbGVdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiBmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgIHJldHVybiAoKC9eWzAtOV0uKyQvKS50ZXN0KHMpID8gJ3RyYScgOiAnaW4nKSArICcgJyArIHM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFzdCA6ICclcyBmYScsXG4gICAgICAgICAgICBzIDogJ2FsY3VuaSBzZWNvbmRpJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNlY29uZGknLFxuICAgICAgICAgICAgbSA6ICd1biBtaW51dG8nLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXRpJyxcbiAgICAgICAgICAgIGggOiAndW5cXCdvcmEnLFxuICAgICAgICAgICAgaGggOiAnJWQgb3JlJyxcbiAgICAgICAgICAgIGQgOiAndW4gZ2lvcm5vJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGdpb3JuaScsXG4gICAgICAgICAgICBNIDogJ3VuIG1lc2UnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbWVzaScsXG4gICAgICAgICAgICB5IDogJ3VuIGFubm8nLFxuICAgICAgICAgICAgeXkgOiAnJWQgYW5uaSdcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbDogJyVkwronLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnamEnLCB7XG4gICAgICAgIG1vbnRocyA6ICfkuIDmnIhf5LqM5pyIX+S4ieaciF/lm5vmnIhf5LqU5pyIX+WFreaciF/kuIPmnIhf5YWr5pyIX+S5neaciF/ljYHmnIhf5Y2B5LiA5pyIX+WNgeS6jOaciCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnMeaciF8y5pyIXzPmnIhfNOaciF815pyIXzbmnIhfN+aciF845pyIXznmnIhfMTDmnIhfMTHmnIhfMTLmnIgnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ+aXpeabnOaXpV/mnIjmm5zml6Vf54Gr5puc5pelX+awtOabnOaXpV/mnKjmm5zml6Vf6YeR5puc5pelX+Wcn+abnOaXpScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfml6Vf5pyIX+eBq1/msLRf5pyoX+mHkV/lnJ8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ+aXpV/mnIhf54GrX+awtF/mnKhf6YeRX+Wcnycuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdZWVlZL01NL0REJyxcbiAgICAgICAgICAgIExMIDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgICAgICBMTEwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnWVlZWeW5tE3mnIhE5pelIGRkZGQgSEg6bW0nLFxuICAgICAgICAgICAgbCA6ICdZWVlZL01NL0REJyxcbiAgICAgICAgICAgIGxsIDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgICAgICBsbGwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGwgOiAnWVlZWeW5tE3mnIhE5pelKGRkZCkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/ljYjliY185Y2I5b6ML2ksXG4gICAgICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PT0gJ+WNiOW+jCc7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5Y2I5YmNJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfljYjlvownO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW+S7iuaXpV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb5piO5pelXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6IGZ1bmN0aW9uIChub3cpIHtcbiAgICAgICAgICAgICAgICBpZiAobm93LndlZWsoKSA8IHRoaXMud2VlaygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW+adpemAsV1kZGRkIExUJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ2RkZGQgTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1vmmKjml6VdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKG5vdykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndlZWsoKSA8IG5vdy53ZWVrKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb5YWI6YCxXWRkZGQgTFQnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnZGRkZCBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn3ml6UvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5pelJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnJXPlvownLFxuICAgICAgICAgICAgcGFzdCA6ICclc+WJjScsXG4gICAgICAgICAgICBzIDogJ+aVsOenkicsXG4gICAgICAgICAgICBzcyA6ICclZOenkicsXG4gICAgICAgICAgICBtIDogJzHliIYnLFxuICAgICAgICAgICAgbW0gOiAnJWTliIYnLFxuICAgICAgICAgICAgaCA6ICcx5pmC6ZaTJyxcbiAgICAgICAgICAgIGhoIDogJyVk5pmC6ZaTJyxcbiAgICAgICAgICAgIGQgOiAnMeaXpScsXG4gICAgICAgICAgICBkZCA6ICclZOaXpScsXG4gICAgICAgICAgICBNIDogJzHjg7bmnIgnLFxuICAgICAgICAgICAgTU0gOiAnJWTjg7bmnIgnLFxuICAgICAgICAgICAgeSA6ICcx5bm0JyxcbiAgICAgICAgICAgIHl5IDogJyVk5bm0J1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2p2Jywge1xuICAgICAgICBtb250aHMgOiAnSmFudWFyaV9GZWJydWFyaV9NYXJldF9BcHJpbF9NZWlfSnVuaV9KdWxpX0FndXN0dXNfU2VwdGVtYmVyX09rdG9iZXJfTm9wZW1iZXJfRGVzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NZWlfSnVuX0p1bF9BZ3NfU2VwX09rdF9Ob3BfRGVzJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdNaW5nZ3VfU2VuZW5fU2Vsb3NvX1JlYnVfS2VtaXNfSmVtdXdhaF9TZXB0dScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdNaW5fU2VuX1NlbF9SZWJfS2VtX0plbV9TZXAnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ01nX1NuX1NsX1JiX0ttX0ptX1NwJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hILm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISC5tbS5zcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAvZW5qaW5nfHNpeWFuZ3xzb250ZW58bmRhbHUvLFxuICAgICAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAnZW5qaW5nJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3NpeWFuZycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc29udGVuJyB8fCBtZXJpZGllbSA9PT0gJ25kYWx1Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPCAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZW5qaW5nJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnc2l5YW5nJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnc29udGVuJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICduZGFsdSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbRGludGVuIHB1bmlrbyBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbTWJlbmphbmcgcHVrdWxdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW3B1a3VsXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tLYWxhIHdpbmdpIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtrZXBlbmdrZXIgcHVrdWxdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICd3b250ZW4gaW5nICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgaW5na2FuZyBrZXBlbmdrZXInLFxuICAgICAgICAgICAgcyA6ICdzYXdldGF3aXMgZGV0aWsnLFxuICAgICAgICAgICAgc3MgOiAnJWQgZGV0aWsnLFxuICAgICAgICAgICAgbSA6ICdzZXR1bmdnYWwgbWVuaXQnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWVuaXQnLFxuICAgICAgICAgICAgaCA6ICdzZXR1bmdnYWwgamFtJyxcbiAgICAgICAgICAgIGhoIDogJyVkIGphbScsXG4gICAgICAgICAgICBkIDogJ3NlZGludGVuJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGRpbnRlbicsXG4gICAgICAgICAgICBNIDogJ3Nld3VsYW4nLFxuICAgICAgICAgICAgTU0gOiAnJWQgd3VsYW4nLFxuICAgICAgICAgICAgeSA6ICdzZXRhdW4nLFxuICAgICAgICAgICAgeXkgOiAnJWQgdGF1bidcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2thJywge1xuICAgICAgICBtb250aHMgOiB7XG4gICAgICAgICAgICBzdGFuZGFsb25lOiAn4YOY4YOQ4YOc4YOV4YOQ4YOg4YOYX+GDl+GDlOGDkeGDlOGDoOGDleGDkOGDmuGDmF/hg5vhg5Dhg6Dhg6Lhg5hf4YOQ4YOe4YOg4YOY4YOa4YOYX+GDm+GDkOGDmOGDoeGDmF/hg5jhg5Xhg5zhg5jhg6Hhg5hf4YOY4YOV4YOa4YOY4YOh4YOYX+GDkOGDkuGDleGDmOGDoeGDouGDnV/hg6Hhg5Thg6Xhg6Lhg5Thg5vhg5Hhg5Thg6Dhg5hf4YOd4YOl4YOi4YOd4YOb4YOR4YOU4YOg4YOYX+GDnOGDneGDlOGDm+GDkeGDlOGDoOGDmF/hg5Phg5Thg5nhg5Thg5vhg5Hhg5Thg6Dhg5gnLnNwbGl0KCdfJyksXG4gICAgICAgICAgICBmb3JtYXQ6ICfhg5jhg5Dhg5zhg5Xhg5Dhg6Dhg6Ff4YOX4YOU4YOR4YOU4YOg4YOV4YOQ4YOa4YOhX+GDm+GDkOGDoOGDouGDoV/hg5Dhg57hg6Dhg5jhg5rhg5jhg6Ff4YOb4YOQ4YOY4YOh4YOhX+GDmOGDleGDnOGDmOGDoeGDoV/hg5jhg5Xhg5rhg5jhg6Hhg6Ff4YOQ4YOS4YOV4YOY4YOh4YOi4YOhX+GDoeGDlOGDpeGDouGDlOGDm+GDkeGDlOGDoOGDoV/hg53hg6Xhg6Lhg53hg5vhg5Hhg5Thg6Dhg6Ff4YOc4YOd4YOU4YOb4YOR4YOU4YOg4YOhX+GDk+GDlOGDmeGDlOGDm+GDkeGDlOGDoOGDoScuc3BsaXQoJ18nKVxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydCA6ICfhg5jhg5Dhg5xf4YOX4YOU4YORX+GDm+GDkOGDoF/hg5Dhg57hg6Bf4YOb4YOQ4YOYX+GDmOGDleGDnF/hg5jhg5Xhg5pf4YOQ4YOS4YOVX+GDoeGDlOGDpV/hg53hg6Xhg6Jf4YOc4YOd4YOUX+GDk+GDlOGDmScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiB7XG4gICAgICAgICAgICBzdGFuZGFsb25lOiAn4YOZ4YOV4YOY4YOg4YOQX+GDneGDoOGDqOGDkOGDkeGDkOGDl+GDmF/hg6Hhg5Dhg5vhg6jhg5Dhg5Hhg5Dhg5fhg5hf4YOd4YOX4YOu4YOo4YOQ4YOR4YOQ4YOX4YOYX+GDruGDo+GDl+GDqOGDkOGDkeGDkOGDl+GDmF/hg57hg5Dhg6Dhg5Dhg6Hhg5nhg5Thg5Xhg5hf4YOo4YOQ4YOR4YOQ4YOX4YOYJy5zcGxpdCgnXycpLFxuICAgICAgICAgICAgZm9ybWF0OiAn4YOZ4YOV4YOY4YOg4YOQ4YOhX+GDneGDoOGDqOGDkOGDkeGDkOGDl+GDoV/hg6Hhg5Dhg5vhg6jhg5Dhg5Hhg5Dhg5fhg6Ff4YOd4YOX4YOu4YOo4YOQ4YOR4YOQ4YOX4YOhX+GDruGDo+GDl+GDqOGDkOGDkeGDkOGDl+GDoV/hg57hg5Dhg6Dhg5Dhg6Hhg5nhg5Thg5Xhg6Ff4YOo4YOQ4YOR4YOQ4YOX4YOhJy5zcGxpdCgnXycpLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IC8o4YOs4YOY4YOc4YOQfOGDqOGDlOGDm+GDk+GDlOGDkikvXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn4YOZ4YOV4YOYX+GDneGDoOGDqF/hg6Hhg5Dhg5tf4YOd4YOX4YOuX+GDruGDo+GDl1/hg57hg5Dhg6Bf4YOo4YOQ4YORJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfhg5nhg5Vf4YOd4YOgX+GDoeGDkF/hg53hg5df4YOu4YOjX+GDnuGDkF/hg6jhg5AnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgICAgIExUUyA6ICdoOm1tOnNzIEEnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBoOm1tIEEnLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb4YOT4YOm4YOU4YOhXSBMVFst4YOW4YOUXScsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vhg67hg5Xhg5Dhg5pdIExUWy3hg5bhg5RdJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW+GDkuGDo+GDqOGDmOGDnF0gTFRbLeGDluGDlF0nLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnW+GDqOGDlOGDm+GDk+GDlOGDkl0gZGRkZCBMVFst4YOW4YOUXScsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdb4YOs4YOY4YOc4YOQXSBkZGRkIExULeGDluGDlCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiBmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgIHJldHVybiAoLyjhg6zhg5Dhg5vhg5h84YOs4YOj4YOX4YOYfOGDoeGDkOGDkOGDl+GDmHzhg6zhg5Thg5rhg5gpLykudGVzdChzKSA/XG4gICAgICAgICAgICAgICAgICAgIHMucmVwbGFjZSgv4YOYJC8sICfhg6jhg5gnKSA6XG4gICAgICAgICAgICAgICAgICAgIHMgKyAn4YOo4YOYJztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYXN0IDogZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoKC8o4YOs4YOQ4YOb4YOYfOGDrOGDo+GDl+GDmHzhg6Hhg5Dhg5Dhg5fhg5h84YOT4YOm4YOUfOGDl+GDleGDlCkvKS50ZXN0KHMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzLnJlcGxhY2UoLyjhg5h84YOUKSQvLCAn4YOY4YOhIOGDrOGDmOGDnCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoKC/hg6zhg5Thg5rhg5gvKS50ZXN0KHMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzLnJlcGxhY2UoL+GDrOGDlOGDmuGDmCQvLCAn4YOs4YOa4YOY4YOhIOGDrOGDmOGDnCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzIDogJ+GDoOGDkOGDm+GDk+GDlOGDnOGDmOGDm+GDlCDhg6zhg5Dhg5vhg5gnLFxuICAgICAgICAgICAgc3MgOiAnJWQg4YOs4YOQ4YOb4YOYJyxcbiAgICAgICAgICAgIG0gOiAn4YOs4YOj4YOX4YOYJyxcbiAgICAgICAgICAgIG1tIDogJyVkIOGDrOGDo+GDl+GDmCcsXG4gICAgICAgICAgICBoIDogJ+GDoeGDkOGDkOGDl+GDmCcsXG4gICAgICAgICAgICBoaCA6ICclZCDhg6Hhg5Dhg5Dhg5fhg5gnLFxuICAgICAgICAgICAgZCA6ICfhg5Phg6bhg5QnLFxuICAgICAgICAgICAgZGQgOiAnJWQg4YOT4YOm4YOUJyxcbiAgICAgICAgICAgIE0gOiAn4YOX4YOV4YOUJyxcbiAgICAgICAgICAgIE1NIDogJyVkIOGDl+GDleGDlCcsXG4gICAgICAgICAgICB5IDogJ+GDrOGDlOGDmuGDmCcsXG4gICAgICAgICAgICB5eSA6ICclZCDhg6zhg5Thg5rhg5gnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC8wfDEt4YOa4YOYfOGDm+GDlC1cXGR7MSwyfXxcXGR7MSwyfS3hg5QvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct4YOa4YOYJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgobnVtYmVyIDwgMjApIHx8IChudW1iZXIgPD0gMTAwICYmIChudW1iZXIgJSAyMCA9PT0gMCkpIHx8IChudW1iZXIgJSAxMDAgPT09IDApKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfhg5vhg5QtJyArIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLeGDlCc7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLFxuICAgICAgICAgICAgZG95IDogN1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3VmZml4ZXMkMSA9IHtcbiAgICAgICAgMDogJy3RiNGWJyxcbiAgICAgICAgMTogJy3RiNGWJyxcbiAgICAgICAgMjogJy3RiNGWJyxcbiAgICAgICAgMzogJy3RiNGWJyxcbiAgICAgICAgNDogJy3RiNGWJyxcbiAgICAgICAgNTogJy3RiNGWJyxcbiAgICAgICAgNjogJy3RiNGLJyxcbiAgICAgICAgNzogJy3RiNGWJyxcbiAgICAgICAgODogJy3RiNGWJyxcbiAgICAgICAgOTogJy3RiNGLJyxcbiAgICAgICAgMTA6ICct0YjRiycsXG4gICAgICAgIDIwOiAnLdGI0YsnLFxuICAgICAgICAzMDogJy3RiNGLJyxcbiAgICAgICAgNDA6ICct0YjRiycsXG4gICAgICAgIDUwOiAnLdGI0ZYnLFxuICAgICAgICA2MDogJy3RiNGLJyxcbiAgICAgICAgNzA6ICct0YjRlicsXG4gICAgICAgIDgwOiAnLdGI0ZYnLFxuICAgICAgICA5MDogJy3RiNGLJyxcbiAgICAgICAgMTAwOiAnLdGI0ZYnXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgna2snLCB7XG4gICAgICAgIG1vbnRocyA6ICfSm9Cw0qPRgtCw0YBf0LDSm9C/0LDQvV/QvdCw0YPRgNGL0Ldf0YHTmdGD0ZbRgF/QvNCw0LzRi9GAX9C80LDRg9GB0YvQvF/RiNGW0LvQtNC1X9GC0LDQvNGL0Ldf0pvRi9GA0LrSr9C50LXQul/Sm9Cw0LfQsNC9X9Kb0LDRgNCw0YjQsF/QttC10LvRgtC+0pvRgdCw0L0nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ9Kb0LDSo1/QsNKb0L9f0L3QsNGDX9GB05nRg1/QvNCw0Lxf0LzQsNGDX9GI0ZbQu1/RgtCw0Lxf0pvRi9GAX9Kb0LDQt1/Sm9Cw0YBf0LbQtdC7Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfQttC10LrRgdC10L3QsdGWX9C00q/QudGB0LXQvdCx0ZZf0YHQtdC50YHQtdC90LHRll/RgdOZ0YDRgdC10L3QsdGWX9Cx0LXQudGB0LXQvdCx0ZZf0LbSsdC80LBf0YHQtdC90LHRlicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfQttC10Lpf0LTSr9C5X9GB0LXQuV/RgdOZ0YBf0LHQtdC5X9C20rHQvF/RgdC10L0nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ9C20Lpf0LTQuV/RgdC5X9GB0YBf0LHQuV/QttC8X9GB0L0nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1vQkdKv0LPRltC9INGB0LDSk9Cw0YJdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW9CV0YDRgtC10qMg0YHQsNKT0LDRgl0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb0YHQsNKT0LDRgl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb0JrQtdGI0LUg0YHQsNKT0LDRgl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW9Oo0YLQutC10L0g0LDQv9GC0LDQvdGL0qNdIGRkZGQgW9GB0LDSk9Cw0YJdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyDRltGI0ZbQvdC00LUnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyDQsdKx0YDRi9C9JyxcbiAgICAgICAgICAgIHMgOiAn0LHRltGA0L3QtdGI0LUg0YHQtdC60YPQvdC0JyxcbiAgICAgICAgICAgIHNzIDogJyVkINGB0LXQutGD0L3QtCcsXG4gICAgICAgICAgICBtIDogJ9Cx0ZbRgCDQvNC40L3Rg9GCJyxcbiAgICAgICAgICAgIG1tIDogJyVkINC80LjQvdGD0YInLFxuICAgICAgICAgICAgaCA6ICfQsdGW0YAg0YHQsNKT0LDRgicsXG4gICAgICAgICAgICBoaCA6ICclZCDRgdCw0pPQsNGCJyxcbiAgICAgICAgICAgIGQgOiAn0LHRltGAINC60q/QvScsXG4gICAgICAgICAgICBkZCA6ICclZCDQutKv0L0nLFxuICAgICAgICAgICAgTSA6ICfQsdGW0YAg0LDQuScsXG4gICAgICAgICAgICBNTSA6ICclZCDQsNC5JyxcbiAgICAgICAgICAgIHkgOiAn0LHRltGAINC20YvQuycsXG4gICAgICAgICAgICB5eSA6ICclZCDQttGL0LsnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0YjRlnzRiNGLKS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIGIgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAoc3VmZml4ZXMkMVtudW1iZXJdIHx8IHN1ZmZpeGVzJDFbYV0gfHwgc3VmZml4ZXMkMVtiXSk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCQ4ID0ge1xuICAgICAgICAnMSc6ICfhn6EnLFxuICAgICAgICAnMic6ICfhn6InLFxuICAgICAgICAnMyc6ICfhn6MnLFxuICAgICAgICAnNCc6ICfhn6QnLFxuICAgICAgICAnNSc6ICfhn6UnLFxuICAgICAgICAnNic6ICfhn6YnLFxuICAgICAgICAnNyc6ICfhn6cnLFxuICAgICAgICAnOCc6ICfhn6gnLFxuICAgICAgICAnOSc6ICfhn6knLFxuICAgICAgICAnMCc6ICfhn6AnXG4gICAgfSwgbnVtYmVyTWFwJDcgPSB7XG4gICAgICAgICfhn6EnOiAnMScsXG4gICAgICAgICfhn6InOiAnMicsXG4gICAgICAgICfhn6MnOiAnMycsXG4gICAgICAgICfhn6QnOiAnNCcsXG4gICAgICAgICfhn6UnOiAnNScsXG4gICAgICAgICfhn6YnOiAnNicsXG4gICAgICAgICfhn6cnOiAnNycsXG4gICAgICAgICfhn6gnOiAnOCcsXG4gICAgICAgICfhn6knOiAnOScsXG4gICAgICAgICfhn6AnOiAnMCdcbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdrbScsIHtcbiAgICAgICAgbW9udGhzOiAn4Z6Y4Z6A4Z6a4Z62X+GegOGeu+GemOGfkuGel+GfiF/hnpjhnrjhnpPhnrZf4Z6Y4Z+B4Z6f4Z62X+Gep+Gen+Gel+Getl/hnpjhnrfhnpDhnrvhnpPhnrZf4Z6A4Z6A4Z+S4Z6A4Z6K4Z62X+Gen+GeuOGeoOGetl/hnoDhnonhn5LhnonhnrZf4Z6P4Z674Z6b4Z62X+GenOGet+GeheGfkuGehuGet+GegOGetl/hnpLhn5LhnpPhnrwnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn4Z6Y4Z6A4Z6a4Z62X+GegOGeu+GemOGfkuGel+GfiF/hnpjhnrjhnpPhnrZf4Z6Y4Z+B4Z6f4Z62X+Gep+Gen+Gel+Getl/hnpjhnrfhnpDhnrvhnpPhnrZf4Z6A4Z6A4Z+S4Z6A4Z6K4Z62X+Gen+GeuOGeoOGetl/hnoDhnonhn5LhnonhnrZf4Z6P4Z674Z6b4Z62X+GenOGet+GeheGfkuGehuGet+GegOGetl/hnpLhn5LhnpPhnrwnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzOiAn4Z6i4Z624Z6R4Z634Z6P4Z+S4Z6ZX+GeheGfkOGek+GfkuGekV/hnqLhnoThn5LhnoLhnrbhnppf4Z6W4Z674Z6SX+GeluGfkuGemuGeoOGen+GfkuGelOGej+Get+GfjV/hnp/hnrvhnoDhn5Lhnppf4Z6f4Z+F4Z6a4Z+NJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn4Z6i4Z62X+GehV/hnqJf4Z6WX+GeluGfkuGeml/hnp/hnrtf4Z6fJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ+GeouGetl/hnoVf4Z6iX+Gell/hnpbhn5Lhnppf4Z6f4Z67X+Genycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+GeluGfkuGemuGeueGegHzhnpvhn5LhnoThnrbhnoUvLFxuICAgICAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PT0gJ+Gem+GfkuGehOGetuGehSc7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfhnpbhn5LhnprhnrnhnoAnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+Gem+GfkuGehOGetuGehSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+GekOGfkuGehOGfg+Gek+GfgeGfhyDhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4Z6f4Z+S4Z6i4Z+C4Z6AIOGemOGfieGfhOGehF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4Z6Y4Z+S4Z6f4Z634Z6b4Z6Y4Z634Z6JIOGemOGfieGfhOGehF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvhnp/hnpThn5Lhno/hnrbhnqDhn43hnpjhnrvhnpNdIFvhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgICAgICBmdXR1cmU6ICclc+GekeGfgOGejycsXG4gICAgICAgICAgICBwYXN0OiAnJXPhnpjhnrvhnpMnLFxuICAgICAgICAgICAgczogJ+GelOGfieGeu+Gek+GfkuGemOGetuGek+GenOGet+Gek+GetuGekeGeuCcsXG4gICAgICAgICAgICBzczogJyVkIOGenOGet+Gek+GetuGekeGeuCcsXG4gICAgICAgICAgICBtOiAn4Z6Y4Z694Z6Z4Z6T4Z624Z6R4Z64JyxcbiAgICAgICAgICAgIG1tOiAnJWQg4Z6T4Z624Z6R4Z64JyxcbiAgICAgICAgICAgIGg6ICfhnpjhnr3hnpnhnpjhn4nhn4ThnoQnLFxuICAgICAgICAgICAgaGg6ICclZCDhnpjhn4nhn4ThnoQnLFxuICAgICAgICAgICAgZDogJ+GemOGeveGemeGekOGfkuGehOGfgycsXG4gICAgICAgICAgICBkZDogJyVkIOGekOGfkuGehOGfgycsXG4gICAgICAgICAgICBNOiAn4Z6Y4Z694Z6Z4Z6B4Z+CJyxcbiAgICAgICAgICAgIE1NOiAnJWQg4Z6B4Z+CJyxcbiAgICAgICAgICAgIHk6ICfhnpjhnr3hnpnhnobhn5LhnpPhnrbhn4YnLFxuICAgICAgICAgICAgeXk6ICclZCDhnobhn5LhnpPhnrbhn4YnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAv4Z6R4Z64XFxkezEsMn0vLFxuICAgICAgICBvcmRpbmFsIDogJ+GekeGeuCVkJyxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+GfoeGfouGfo+GfpOGfpeGfpuGfp+GfqOGfqeGfoF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCQ3W21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJDhbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWs6IHtcbiAgICAgICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3k6IDQgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJDkgPSB7XG4gICAgICAgICcxJzogJ+CzpycsXG4gICAgICAgICcyJzogJ+CzqCcsXG4gICAgICAgICczJzogJ+CzqScsXG4gICAgICAgICc0JzogJ+CzqicsXG4gICAgICAgICc1JzogJ+CzqycsXG4gICAgICAgICc2JzogJ+CzrCcsXG4gICAgICAgICc3JzogJ+CzrScsXG4gICAgICAgICc4JzogJ+CzricsXG4gICAgICAgICc5JzogJ+CzrycsXG4gICAgICAgICcwJzogJ+CzpidcbiAgICB9LFxuICAgIG51bWJlck1hcCQ4ID0ge1xuICAgICAgICAn4LOnJzogJzEnLFxuICAgICAgICAn4LOoJzogJzInLFxuICAgICAgICAn4LOpJzogJzMnLFxuICAgICAgICAn4LOqJzogJzQnLFxuICAgICAgICAn4LOrJzogJzUnLFxuICAgICAgICAn4LOsJzogJzYnLFxuICAgICAgICAn4LOtJzogJzcnLFxuICAgICAgICAn4LOuJzogJzgnLFxuICAgICAgICAn4LOvJzogJzknLFxuICAgICAgICAn4LOmJzogJzAnXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgna24nLCB7XG4gICAgICAgIG1vbnRocyA6ICfgspzgsqjgsrXgsrDgsr9f4LKr4LOG4LKs4LON4LKw4LK14LKw4LK/X+CyruCyvuCysOCzjeCymuCzjV/gso/gsqrgs43gsrDgsr/gsrLgs41f4LKu4LOG4LOVX+CynOCzguCyqOCzjV/gspzgs4HgsrLgs4bgs5Zf4LKG4LKX4LK44LON4LKf4LONX+CyuOCzhuCyquCzjeCyn+CzhuCyguCyrOCysOCzjV/gsoXgspXgs43gsp/gs4bgs4Lgs5XgsqzgsrDgs41f4LKo4LK14LOG4LKC4LKs4LKw4LONX+CyoeCyv+CyuOCzhuCyguCyrOCysOCzjScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn4LKc4LKoX+Cyq+CzhuCyrOCzjeCysF/gsq7gsr7gsrDgs43gsprgs41f4LKP4LKq4LON4LKw4LK/4LKy4LONX+CyruCzhuCzlV/gspzgs4Lgsqjgs41f4LKc4LOB4LKy4LOG4LOWX+CyhuCyl+CyuOCzjeCyn+CzjV/gsrjgs4bgsqrgs43gsp/gs4bgsoJf4LKF4LKV4LON4LKf4LOG4LOC4LOVX+CyqOCyteCzhuCygl/gsqHgsr/gsrjgs4bgsoInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogJ+CyreCyvuCyqOCzgeCyteCyvuCysF/gsrjgs4bgs4Lgs5Xgsq7gsrXgsr7gsrBf4LKu4LKC4LKX4LKz4LK14LK+4LKwX+CyrOCzgeCyp+CyteCyvuCysF/gspfgs4HgsrDgs4HgsrXgsr7gsrBf4LK24LOB4LKV4LON4LKw4LK14LK+4LKwX+CytuCyqOCyv+CyteCyvuCysCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfgsq3gsr7gsqjgs4Ff4LK44LOG4LOC4LOV4LKuX+CyruCyguCyl+Cys1/gsqzgs4Hgsqdf4LKX4LOB4LKw4LOBX+CytuCzgeCyleCzjeCysF/gsrbgsqjgsr8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ+CyreCyvl/gsrjgs4bgs4Lgs5Vf4LKu4LKCX+CyrOCzgV/gspfgs4Ff4LK24LOBX+Cyticuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdBIGg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0EgaDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZLCBBIGg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW+Cyh+CyguCypuCzgV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb4LKo4LK+4LKz4LOGXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkLCBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1vgsqjgsr/gsqjgs43gsqjgs4ZdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1vgspXgs4bgs4Lgsqjgs4bgsq9dIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyDgsqjgsoLgsqTgsrAnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyDgsrngsr/gsoLgsqbgs4YnLFxuICAgICAgICAgICAgcyA6ICfgspXgs4bgsrLgsrXgs4Eg4LKV4LON4LK34LKj4LKX4LKz4LOBJyxcbiAgICAgICAgICAgIHNzIDogJyVkIOCyuOCzhuCyleCzhuCyguCyoeCzgeCyl+Cys+CzgScsXG4gICAgICAgICAgICBtIDogJ+CykuCyguCypuCzgSDgsqjgsr/gsq7gsr/gsrcnLFxuICAgICAgICAgICAgbW0gOiAnJWQg4LKo4LK/4LKu4LK/4LK3JyxcbiAgICAgICAgICAgIGggOiAn4LKS4LKC4LKm4LOBIOCyl+CyguCyn+CzhicsXG4gICAgICAgICAgICBoaCA6ICclZCDgspfgsoLgsp/gs4YnLFxuICAgICAgICAgICAgZCA6ICfgspLgsoLgsqbgs4Eg4LKm4LK/4LKoJyxcbiAgICAgICAgICAgIGRkIDogJyVkIOCypuCyv+CyqCcsXG4gICAgICAgICAgICBNIDogJ+CykuCyguCypuCzgSDgsqTgsr/gsoLgspfgsrPgs4EnLFxuICAgICAgICAgICAgTU0gOiAnJWQg4LKk4LK/4LKC4LKX4LKz4LOBJyxcbiAgICAgICAgICAgIHkgOiAn4LKS4LKC4LKm4LOBIOCyteCysOCzjeCytycsXG4gICAgICAgICAgICB5eSA6ICclZCDgsrXgsrDgs43gsrcnXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgs6fgs6jgs6ngs6rgs6vgs6zgs63gs67gs6/gs6ZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkOFttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCQ5W21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4LKw4LK+4LKk4LON4LKw4LK/fOCyrOCzhuCys+Cyv+Cyl+CzjeCyl+Czhnzgsq7gsqfgs43gsq/gsr7gsrngs43gsqh84LK44LKC4LKc4LOGLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+CysOCyvuCypOCzjeCysOCyvycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA8IDQgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CyrOCzhuCys+Cyv+Cyl+CzjeCyl+CzhicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgsq7gsqfgs43gsq/gsr7gsrngs43gsqgnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CyuOCyguCynOCzhicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LKw4LK+4LKk4LON4LKw4LK/JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgsqzgs4bgsrPgsr/gspfgs43gspfgs4YnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CyruCyp+CzjeCyr+CyvuCyueCzjeCyqCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LK44LKC4LKc4LOGJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgsrDgsr7gsqTgs43gsrDgsr8nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0o4LKo4LOG4LOVKS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+CyqOCzhuCzlSc7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdrbycsIHtcbiAgICAgICAgbW9udGhzIDogJzHsm5RfMuyblF8z7JuUXzTsm5RfNeyblF827JuUXzfsm5RfOOyblF857JuUXzEw7JuUXzEx7JuUXzEy7JuUJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICcx7JuUXzLsm5RfM+yblF807JuUXzXsm5RfNuyblF837JuUXzjsm5RfOeyblF8xMOyblF8xMeyblF8xMuyblCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAn7J287JqU7J28X+yblOyalOydvF/tmZTsmpTsnbxf7IiY7JqU7J28X+uqqeyalOydvF/quIjsmpTsnbxf7Yag7JqU7J28Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ+ydvF/sm5Rf7ZmUX+yImF/rqqlf6riIX+2GoCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn7J28X+yblF/tmZRf7IiYX+uqqV/quIhf7YagJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0EgaDptbScsXG4gICAgICAgICAgICBMVFMgOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnWVlZWS5NTS5ERC4nLFxuICAgICAgICAgICAgTEwgOiAnWVlZWeuFhCBNTU1NIETsnbwnLFxuICAgICAgICAgICAgTExMIDogJ1lZWVnrhYQgTU1NTSBE7J28IEEgaDptbScsXG4gICAgICAgICAgICBMTExMIDogJ1lZWVnrhYQgTU1NTSBE7J28IGRkZGQgQSBoOm1tJyxcbiAgICAgICAgICAgIGwgOiAnWVlZWS5NTS5ERC4nLFxuICAgICAgICAgICAgbGwgOiAnWVlZWeuFhCBNTU1NIETsnbwnLFxuICAgICAgICAgICAgbGxsIDogJ1lZWVnrhYQgTU1NTSBE7J28IEEgaDptbScsXG4gICAgICAgICAgICBsbGxsIDogJ1lZWVnrhYQgTU1NTSBE7J28IGRkZGQgQSBoOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAn7Jik64qYIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAn64K07J28IExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICfslrTsoJwgTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAn7KeA64Kc7KO8IGRkZGQgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVzIO2bhCcsXG4gICAgICAgICAgICBwYXN0IDogJyVzIOyghCcsXG4gICAgICAgICAgICBzIDogJ+uqhyDstIgnLFxuICAgICAgICAgICAgc3MgOiAnJWTstIgnLFxuICAgICAgICAgICAgbSA6ICcx67aEJyxcbiAgICAgICAgICAgIG1tIDogJyVk67aEJyxcbiAgICAgICAgICAgIGggOiAn7ZWcIOyLnOqwhCcsXG4gICAgICAgICAgICBoaCA6ICclZOyLnOqwhCcsXG4gICAgICAgICAgICBkIDogJ+2VmOujqCcsXG4gICAgICAgICAgICBkZCA6ICclZOydvCcsXG4gICAgICAgICAgICBNIDogJ+2VnCDri6wnLFxuICAgICAgICAgICAgTU0gOiAnJWTri6wnLFxuICAgICAgICAgICAgeSA6ICfsnbwg64WEJyxcbiAgICAgICAgICAgIHl5IDogJyVk64WEJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9KOydvHzsm5R87KO8KS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfsnbwnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+yblCc7XG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn7KO8JztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlIDogL+yYpOyghHzsmKTtm4QvLFxuICAgICAgICBpc1BNIDogZnVuY3Rpb24gKHRva2VuKSB7XG4gICAgICAgICAgICByZXR1cm4gdG9rZW4gPT09ICfsmKTtm4QnO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzVXBwZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyIDwgMTIgPyAn7Jik7KCEJyA6ICfsmKTtm4QnO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJGEgPSB7XG4gICAgICAgICcxJzogJ9mhJyxcbiAgICAgICAgJzInOiAn2aInLFxuICAgICAgICAnMyc6ICfZoycsXG4gICAgICAgICc0JzogJ9mkJyxcbiAgICAgICAgJzUnOiAn2aUnLFxuICAgICAgICAnNic6ICfZpicsXG4gICAgICAgICc3JzogJ9mnJyxcbiAgICAgICAgJzgnOiAn2agnLFxuICAgICAgICAnOSc6ICfZqScsXG4gICAgICAgICcwJzogJ9mgJ1xuICAgIH0sIG51bWJlck1hcCQ5ID0ge1xuICAgICAgICAn2aEnOiAnMScsXG4gICAgICAgICfZoic6ICcyJyxcbiAgICAgICAgJ9mjJzogJzMnLFxuICAgICAgICAn2aQnOiAnNCcsXG4gICAgICAgICfZpSc6ICc1JyxcbiAgICAgICAgJ9mmJzogJzYnLFxuICAgICAgICAn2acnOiAnNycsXG4gICAgICAgICfZqCc6ICc4JyxcbiAgICAgICAgJ9mpJzogJzknLFxuICAgICAgICAn2aAnOiAnMCdcbiAgICB9LFxuICAgIG1vbnRocyQ3ID0gW1xuICAgICAgICAn2qnYp9mG2YjZhtuMINiv2YjZiNuV2YUnLFxuICAgICAgICAn2LTZiNio2KfYqicsXG4gICAgICAgICfYptin2LLYp9ixJyxcbiAgICAgICAgJ9mG24zYs9in2YYnLFxuICAgICAgICAn2KbYp9uM2KfYsScsXG4gICAgICAgICfYrdmI2LLblduM2LHYp9mGJyxcbiAgICAgICAgJ9iq25XZhdmF2YjYsicsXG4gICAgICAgICfYptin2KgnLFxuICAgICAgICAn2KbblduM2YTZiNmI2YQnLFxuICAgICAgICAn2KrYtNix24zZhtuMINuM25XZg9uV2YUnLFxuICAgICAgICAn2KrYtNix24zZhtuMINiv2YjZiNuV2YUnLFxuICAgICAgICAn2YPYp9mG2YjZhtuMINuM25XaqduV2YUnXG4gICAgXTtcblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdrdScsIHtcbiAgICAgICAgbW9udGhzIDogbW9udGhzJDcsXG4gICAgICAgIG1vbnRoc1Nob3J0IDogbW9udGhzJDcsXG4gICAgICAgIHdlZWtkYXlzIDogJ9uM2YfigIzZg9i02YfigIzZhdmF2YfigIxf2K/ZiNmI2LTZh+KAjNmF2YXZh+KAjF/Ys9uO2LTZh+KAjNmF2YXZh+KAjF/ahtmI2KfYsdi02YfigIzZhdmF2YfigIxf2b7bjtmG2KzYtNmH4oCM2YXZhdmH4oCMX9mH2YfigIzbjNmG24xf2LTZh+KAjNmF2YXZh+KAjCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfbjNmH4oCM2YPYtNmH4oCM2YVf2K/ZiNmI2LTZh+KAjNmFX9iz247YtNmH4oCM2YVf2obZiNin2LHYtNmH4oCM2YVf2b7bjtmG2KzYtNmH4oCM2YVf2YfZh+KAjNuM2YbbjF/YtNmH4oCM2YXZhdmH4oCMJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfbjF/Yr1/Ys1/ahl/Zvl/Zh1/YtCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv2KbbjtmI2KfYsdmH4oCMfNio2YfigIzbjNin2YbbjC8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIC/YptuO2YjYp9ix2YfigIwvLnRlc3QoaW5wdXQpO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9io2YfigIzbjNin2YbbjCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2KbbjtmI2KfYsdmH4oCMJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1vYptmH4oCM2YXYsduGINmD2KfYqtqY2YXbjtixXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vYqNmH4oCM24zYp9mG24wg2YPYp9iq2pjZhduO2LFdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW9mD2KfYqtqY2YXbjtixXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1vYr9mI247ZhtuOINmD2KfYqtqY2YXbjtixXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFvZg9in2KramNmF247YsV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ9mE2YfigIwgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcycsXG4gICAgICAgICAgICBzIDogJ9qG2YfigIzZhtivINqG2LHZg9mH4oCM24zZh+KAjNmDJyxcbiAgICAgICAgICAgIHNzIDogJ9qG2LHZg9mH4oCMICVkJyxcbiAgICAgICAgICAgIG0gOiAn24zZh+KAjNmDINiu2YjZhNmH4oCM2YMnLFxuICAgICAgICAgICAgbW0gOiAnJWQg2K7ZiNmE2YfigIzZgycsXG4gICAgICAgICAgICBoIDogJ9uM2YfigIzZgyDZg9in2KramNmF247YsScsXG4gICAgICAgICAgICBoaCA6ICclZCDZg9in2KramNmF247YsScsXG4gICAgICAgICAgICBkIDogJ9uM2YfigIzZgyDalduG2pgnLFxuICAgICAgICAgICAgZGQgOiAnJWQg2pXbhtqYJyxcbiAgICAgICAgICAgIE0gOiAn24zZh+KAjNmDINmF2KfZhtqvJyxcbiAgICAgICAgICAgIE1NIDogJyVkINmF2KfZhtqvJyxcbiAgICAgICAgICAgIHkgOiAn24zZh+KAjNmDINiz2KfatScsXG4gICAgICAgICAgICB5eSA6ICclZCDYs9in2rUnXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vZodmi2aPZpNml2abZp9mo2anZoF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCQ5W21hdGNoXTtcbiAgICAgICAgICAgIH0pLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXAkYVttYXRjaF07XG4gICAgICAgICAgICB9KS5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogNiwgLy8gU2F0dXJkYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDEyIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDEydGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzdWZmaXhlcyQyID0ge1xuICAgICAgICAwOiAnLdGH0q8nLFxuICAgICAgICAxOiAnLdGH0LgnLFxuICAgICAgICAyOiAnLdGH0LgnLFxuICAgICAgICAzOiAnLdGH0q8nLFxuICAgICAgICA0OiAnLdGH0q8nLFxuICAgICAgICA1OiAnLdGH0LgnLFxuICAgICAgICA2OiAnLdGH0YsnLFxuICAgICAgICA3OiAnLdGH0LgnLFxuICAgICAgICA4OiAnLdGH0LgnLFxuICAgICAgICA5OiAnLdGH0YMnLFxuICAgICAgICAxMDogJy3Rh9GDJyxcbiAgICAgICAgMjA6ICct0YfRiycsXG4gICAgICAgIDMwOiAnLdGH0YMnLFxuICAgICAgICA0MDogJy3Rh9GLJyxcbiAgICAgICAgNTA6ICct0YfSrycsXG4gICAgICAgIDYwOiAnLdGH0YsnLFxuICAgICAgICA3MDogJy3Rh9C4JyxcbiAgICAgICAgODA6ICct0YfQuCcsXG4gICAgICAgIDkwOiAnLdGH0YMnLFxuICAgICAgICAxMDA6ICct0YfSrydcbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdreScsIHtcbiAgICAgICAgbW9udGhzIDogJ9GP0L3QstCw0YDRjF/RhNC10LLRgNCw0LvRjF/QvNCw0YDRgl/QsNC/0YDQtdC70Yxf0LzQsNC5X9C40Y7QvdGMX9C40Y7Qu9GMX9Cw0LLQs9GD0YHRgl/RgdC10L3RgtGP0LHRgNGMX9C+0LrRgtGP0LHRgNGMX9C90L7Rj9Cx0YDRjF/QtNC10LrQsNCx0YDRjCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn0Y/QvdCyX9GE0LXQsl/QvNCw0YDRgl/QsNC/0YBf0LzQsNC5X9C40Y7QvdGMX9C40Y7Qu9GMX9Cw0LLQs1/RgdC10L1f0L7QutGCX9C90L7Rj1/QtNC10LonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ9CW0LXQutGI0LXQvNCx0Lhf0JTSr9C50YjTqdC80LHSr1/QqNC10LnRiNC10LzQsdC4X9Co0LDRgNGI0LXQvNCx0Lhf0JHQtdC50YjQtdC80LHQuF/QltGD0LzQsF/QmNGI0LXQvNCx0LgnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn0JbQtdC6X9CU0q/QuV/QqNC10Llf0KjQsNGAX9CR0LXQuV/QltGD0Lxf0JjRiNC1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfQltC6X9CU0Llf0KjQuV/QqNGAX9CR0Llf0JbQvF/QmNGIJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb0JHSr9Cz0q/QvSDRgdCw0LDRgl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb0K3RgNGC0LXSoyDRgdCw0LDRgl0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb0YHQsNCw0YJdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW9Ca0LXRh9GN0Y0g0YHQsNCw0YJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1vTqNGC0LrTqdC9INCw0L/RgtCw0L3Ri9C9XSBkZGRkIFvQutKv0L3Sr10gW9GB0LDQsNGCXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnJXMg0LjRh9C40L3QtNC1JyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMg0LzRg9GA0YPQvScsXG4gICAgICAgICAgICBzIDogJ9Cx0LjRgNC90LXRh9C1INGB0LXQutGD0L3QtCcsXG4gICAgICAgICAgICBzcyA6ICclZCDRgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgbSA6ICfQsdC40YAg0LzSr9C906nRgicsXG4gICAgICAgICAgICBtbSA6ICclZCDQvNKv0L3TqdGCJyxcbiAgICAgICAgICAgIGggOiAn0LHQuNGAINGB0LDQsNGCJyxcbiAgICAgICAgICAgIGhoIDogJyVkINGB0LDQsNGCJyxcbiAgICAgICAgICAgIGQgOiAn0LHQuNGAINC60q/QvScsXG4gICAgICAgICAgICBkZCA6ICclZCDQutKv0L0nLFxuICAgICAgICAgICAgTSA6ICfQsdC40YAg0LDQuScsXG4gICAgICAgICAgICBNTSA6ICclZCDQsNC5JyxcbiAgICAgICAgICAgIHkgOiAn0LHQuNGAINC20YvQuycsXG4gICAgICAgICAgICB5eSA6ICclZCDQttGL0LsnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0YfQuHzRh9GLfNGH0q980YfRgykvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGEgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBiID0gbnVtYmVyID49IDEwMCA/IDEwMCA6IG51bGw7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKHN1ZmZpeGVzJDJbbnVtYmVyXSB8fCBzdWZmaXhlcyQyW2FdIHx8IHN1ZmZpeGVzJDJbYl0pO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUkNShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgICAgICdtJzogWydlbmcgTWludXR0JywgJ2VuZ2VyIE1pbnV0dCddLFxuICAgICAgICAgICAgJ2gnOiBbJ2VuZyBTdG9ubicsICdlbmdlciBTdG9ubiddLFxuICAgICAgICAgICAgJ2QnOiBbJ2VlbiBEYWcnLCAnZW5nZW0gRGFnJ10sXG4gICAgICAgICAgICAnTSc6IFsnZWUgTW91bnQnLCAnZW5nZW0gTW91bnQnXSxcbiAgICAgICAgICAgICd5JzogWydlZSBKb2VyJywgJ2VuZ2VtIEpvZXInXVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHByb2Nlc3NGdXR1cmVUaW1lKHN0cmluZykge1xuICAgICAgICB2YXIgbnVtYmVyID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZignICcpKTtcbiAgICAgICAgaWYgKGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihudW1iZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gJ2EgJyArIHN0cmluZztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJ2FuICcgKyBzdHJpbmc7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHByb2Nlc3NQYXN0VGltZShzdHJpbmcpIHtcbiAgICAgICAgdmFyIG51bWJlciA9IHN0cmluZy5zdWJzdHIoMCwgc3RyaW5nLmluZGV4T2YoJyAnKSk7XG4gICAgICAgIGlmIChlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIobnVtYmVyKSkge1xuICAgICAgICAgICAgcmV0dXJuICd2aXJ1ICcgKyBzdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICd2aXJ1biAnICsgc3RyaW5nO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdvcmQgYmVmb3JlIHRoZSBnaXZlbiBudW1iZXIgbG9zZXMgdGhlICctbicgZW5kaW5nLlxuICAgICAqIGUuZy4gJ2FuIDEwIERlZWcnIGJ1dCAnYSA1IERlZWcnXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbnVtYmVyIHtpbnRlZ2VyfVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihudW1iZXIpIHtcbiAgICAgICAgbnVtYmVyID0gcGFyc2VJbnQobnVtYmVyLCAxMCk7XG4gICAgICAgIGlmIChpc05hTihudW1iZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgICAgICAgIC8vIE5lZ2F0aXZlIE51bWJlciAtLT4gYWx3YXlzIHRydWVcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDEwKSB7XG4gICAgICAgICAgICAvLyBPbmx5IDEgZGlnaXRcbiAgICAgICAgICAgIGlmICg0IDw9IG51bWJlciAmJiBudW1iZXIgPD0gNykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDEwMCkge1xuICAgICAgICAgICAgLy8gMiBkaWdpdHNcbiAgICAgICAgICAgIHZhciBsYXN0RGlnaXQgPSBudW1iZXIgJSAxMCwgZmlyc3REaWdpdCA9IG51bWJlciAvIDEwO1xuICAgICAgICAgICAgaWYgKGxhc3REaWdpdCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIoZmlyc3REaWdpdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKGxhc3REaWdpdCk7XG4gICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgMTAwMDApIHtcbiAgICAgICAgICAgIC8vIDMgb3IgNCBkaWdpdHMgLS0+IHJlY3Vyc2l2ZWx5IGNoZWNrIGZpcnN0IGRpZ2l0XG4gICAgICAgICAgICB3aGlsZSAobnVtYmVyID49IDEwKSB7XG4gICAgICAgICAgICAgICAgbnVtYmVyID0gbnVtYmVyIC8gMTA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKG51bWJlcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBBbnl0aGluZyBsYXJnZXIgdGhhbiA0IGRpZ2l0czogcmVjdXJzaXZlbHkgY2hlY2sgZmlyc3Qgbi0zIGRpZ2l0c1xuICAgICAgICAgICAgbnVtYmVyID0gbnVtYmVyIC8gMTAwMDtcbiAgICAgICAgICAgIHJldHVybiBlaWZlbGVyUmVnZWxBcHBsaWVzVG9OdW1iZXIobnVtYmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbGInLCB7XG4gICAgICAgIG1vbnRoczogJ0phbnVhcl9GZWJydWFyX03DpGVyel9BYnLDq2xsX01lZV9KdW5pX0p1bGlfQXVndXN0X1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0RlemVtYmVyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydDogJ0phbi5fRmVici5fTXJ6Ll9BYnIuX01lZV9KdW4uX0p1bC5fQXVnLl9TZXB0Ll9Pa3QuX05vdi5fRGV6Licuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnU29ubmRlZ19Nw6lpbmRlZ19Ew6tuc2NoZGVnX03Dq3R0d29jaF9Eb25uZXNjaGRlZ19GcmVpZGVnX1NhbXNjaGRlZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ1NvLl9Nw6kuX0TDqy5fTcOrLl9Eby5fRnIuX1NhLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICdTb19Nw6lfRMOrX03Dq19Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSDptbSBbQXVlcl0nLFxuICAgICAgICAgICAgTFRTOiAnSDptbTpzcyBbQXVlcl0nLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRC4gTU1NTSBZWVlZIEg6bW0gW0F1ZXJdJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSBbQXVlcl0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0hhdXQgdW1dIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW011ZXIgdW1dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbdW1dIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbR8Orc2NodGVyIHVtXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIC8vIERpZmZlcmVudCBkYXRlIHN0cmluZyBmb3IgJ0TDq25zY2hkZWcnIChUdWVzZGF5KSBhbmQgJ0Rvbm5lc2NoZGVnJyAoVGh1cnNkYXkpIGR1ZSB0byBwaG9ub2xvZ2ljYWwgcnVsZVxuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW0xlc2NodGVuXSBkZGRkIFt1bV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbTGVzY2h0ZV0gZGRkZCBbdW1dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6IHByb2Nlc3NGdXR1cmVUaW1lLFxuICAgICAgICAgICAgcGFzdCA6IHByb2Nlc3NQYXN0VGltZSxcbiAgICAgICAgICAgIHMgOiAnZSBwdWVyIFNla29ubmVuJyxcbiAgICAgICAgICAgIHNzIDogJyVkIFNla29ubmVuJyxcbiAgICAgICAgICAgIG0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDUsXG4gICAgICAgICAgICBtbSA6ICclZCBNaW51dHRlbicsXG4gICAgICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ1LFxuICAgICAgICAgICAgaGggOiAnJWQgU3Rvbm5lbicsXG4gICAgICAgICAgICBkIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ1LFxuICAgICAgICAgICAgZGQgOiAnJWQgRGVlZycsXG4gICAgICAgICAgICBNIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ1LFxuICAgICAgICAgICAgTU0gOiAnJWQgTcOpaW50JyxcbiAgICAgICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lJDUsXG4gICAgICAgICAgICB5eSA6ICclZCBKb2VyJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ2xvJywge1xuICAgICAgICBtb250aHMgOiAn4Lqh4Lqx4LqH4LqB4Lqt4LqZX+C6geC6uOC6oeC6nuC6sl/guqHgurXgupngurJf4LuA4Lqh4Lqq4LqyX+C6nuC6tuC6lOC6quC6sOC6nuC6sl/guqHgurTgupbgurjgupngurJf4LqB4LuN4Lql4Lqw4LqB4Lq74LqUX+C6quC6tOC6h+C6q+C6sl/guoHgurHgupnguo3gurJf4LqV4Lq44Lql4LqyX+C6nuC6sOC6iOC6tOC6gV/gupfgurHgupnguqfgurInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ+C6oeC6seC6h+C6geC6reC6mV/guoHgurjguqHgup7gurJf4Lqh4Lq14LqZ4LqyX+C7gOC6oeC6quC6sl/gup7gurbgupTguqrgurDgup7gurJf4Lqh4Lq04LqW4Lq44LqZ4LqyX+C6geC7jeC6peC6sOC6geC6u+C6lF/guqrgurTguofguqvgurJf4LqB4Lqx4LqZ4LqN4LqyX+C6leC6uOC6peC6sl/gup7gurDguojgurTguoFf4LqX4Lqx4LqZ4Lqn4LqyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfguq3gurLgupfgurTgupRf4LqI4Lqx4LqZX+C6reC6seC6h+C6hOC6suC6mV/gup7gurjgupRf4Lqe4Lqw4Lqr4Lqx4LqUX+C6quC6uOC6gV/gu4DguqrgurvgurInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn4LqX4Lq04LqUX+C6iOC6seC6mV/guq3gurHguofguoTgurLguplf4Lqe4Lq44LqUX+C6nuC6sOC6q+C6seC6lF/guqrgurjguoFf4LuA4Lqq4Lq74LqyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfgupdf4LqIX+C6reC6hF/gup5f4Lqe4LqrX+C6quC6gV/guqonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICfguqfgurHguplkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4LqV4Lqt4LqZ4LuA4LqK4Lq74LuJ4LqyfOC6leC6reC6meC7geC6peC6hy8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn4LqV4Lqt4LqZ4LuB4Lql4LqHJztcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgupXguq3gupngu4Dguorgurvgu4ngurInO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C6leC6reC6meC7geC6peC6hyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb4Lqh4Lq34LuJ4LqZ4Lq14LuJ4LuA4Lqn4Lql4LqyXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vguqHgurfgu4nguq3gurfgu4jgupngu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ1vguqfgurHgupldZGRkZFvgu5zgu4ngurLgu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW+C6oeC6t+C7ieC6p+C6suC6meC6meC6teC7ieC7gOC6p+C6peC6sl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW+C6p+C6seC6mV1kZGRkW+C7geC6peC7ieC6p+C6meC6teC7ieC7gOC6p+C6peC6sl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ+C6reC6teC6gSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJyVz4Lqc4LuI4Lqy4LqZ4Lqh4LqyJyxcbiAgICAgICAgICAgIHMgOiAn4Lqa4LuN4LuI4LuA4LqX4Lq74LuI4Lqy4LuD4LqU4Lqn4Lq04LqZ4Lqy4LqX4Lq1JyxcbiAgICAgICAgICAgIHNzIDogJyVkIOC6p+C6tOC6meC6suC6l+C6tScgLFxuICAgICAgICAgICAgbSA6ICcxIOC6meC6suC6l+C6tScsXG4gICAgICAgICAgICBtbSA6ICclZCDgupngurLgupfgurUnLFxuICAgICAgICAgICAgaCA6ICcxIOC6iuC6u+C7iOC6p+C7guC6oeC6hycsXG4gICAgICAgICAgICBoaCA6ICclZCDguorgurvgu4jguqfgu4LguqHguocnLFxuICAgICAgICAgICAgZCA6ICcxIOC6oeC6t+C7iScsXG4gICAgICAgICAgICBkZCA6ICclZCDguqHgurfgu4knLFxuICAgICAgICAgICAgTSA6ICcxIOC7gOC6lOC6t+C6reC6mScsXG4gICAgICAgICAgICBNTSA6ICclZCDgu4DgupTgurfguq3gupknLFxuICAgICAgICAgICAgeSA6ICcxIOC6m+C6tScsXG4gICAgICAgICAgICB5eSA6ICclZCDgupvgurUnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC8o4LqX4Lq14LuIKVxcZHsxLDJ9LyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiAn4LqX4Lq14LuIJyArIG51bWJlcjtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHVuaXRzID0ge1xuICAgICAgICAnc3MnIDogJ3Nla3VuZMSXX3Nla3VuZMW+acWzX3Nla3VuZGVzJyxcbiAgICAgICAgJ20nIDogJ21pbnV0xJdfbWludXTEl3NfbWludXTEmScsXG4gICAgICAgICdtbSc6ICdtaW51dMSXc19taW51xI1pxbNfbWludXRlcycsXG4gICAgICAgICdoJyA6ICd2YWxhbmRhX3ZhbGFuZG9zX3ZhbGFuZMSFJyxcbiAgICAgICAgJ2hoJzogJ3ZhbGFuZG9zX3ZhbGFuZMWzX3ZhbGFuZGFzJyxcbiAgICAgICAgJ2QnIDogJ2RpZW5hX2RpZW5vc19kaWVuxIUnLFxuICAgICAgICAnZGQnOiAnZGllbm9zX2RpZW7Fs19kaWVuYXMnLFxuICAgICAgICAnTScgOiAnbcSXbnVvX23El25lc2lvX23El25lc8SvJyxcbiAgICAgICAgJ01NJzogJ23El25lc2lhaV9txJduZXNpxbNfbcSXbmVzaXVzJyxcbiAgICAgICAgJ3knIDogJ21ldGFpX21ldMWzX21ldHVzJyxcbiAgICAgICAgJ3l5JzogJ21ldGFpX21ldMWzX21ldHVzJ1xuICAgIH07XG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlU2Vjb25kcyhudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgIHJldHVybiAna2VsaW9zIHNla3VuZMSXcyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAna2VsacWzIHNla3VuZMW+acWzJyA6ICdrZWxpYXMgc2VrdW5kZXMnO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZVNpbmd1bGFyKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IGZvcm1zKGtleSlbMF0gOiAoaXNGdXR1cmUgPyBmb3JtcyhrZXkpWzFdIDogZm9ybXMoa2V5KVsyXSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNwZWNpYWwobnVtYmVyKSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgJSAxMCA9PT0gMCB8fCAobnVtYmVyID4gMTAgJiYgbnVtYmVyIDwgMjApO1xuICAgIH1cbiAgICBmdW5jdGlvbiBmb3JtcyhrZXkpIHtcbiAgICAgICAgcmV0dXJuIHVuaXRzW2tleV0uc3BsaXQoJ18nKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlJDYobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyB0cmFuc2xhdGVTaW5ndWxhcihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleVswXSwgaXNGdXR1cmUpO1xuICAgICAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoc3BlY2lhbChudW1iZXIpID8gZm9ybXMoa2V5KVsxXSA6IGZvcm1zKGtleSlbMF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIGZvcm1zKGtleSlbMV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoc3BlY2lhbChudW1iZXIpID8gZm9ybXMoa2V5KVsxXSA6IGZvcm1zKGtleSlbMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbHQnLCB7XG4gICAgICAgIG1vbnRocyA6IHtcbiAgICAgICAgICAgIGZvcm1hdDogJ3NhdXNpb192YXNhcmlvX2tvdm9fYmFsYW5kxb5pb19nZWd1xb7El3NfYmlyxb5lbGlvX2xpZXBvc19ydWdwasWrxI1pb19ydWdzxJdqb19zcGFsaW9fbGFwa3JpxI1pb19ncnVvZMW+aW8nLnNwbGl0KCdfJyksXG4gICAgICAgICAgICBzdGFuZGFsb25lOiAnc2F1c2lzX3Zhc2FyaXNfa292YXNfYmFsYW5kaXNfZ2VndcW+xJdfYmlyxb5lbGlzX2xpZXBhX3J1Z3Bqxat0aXNfcnVnc8SXamlzX3NwYWxpc19sYXBrcml0aXNfZ3J1b2Rpcycuc3BsaXQoJ18nKSxcbiAgICAgICAgICAgIGlzRm9ybWF0OiAvRFtvRF0/KFxcW1teXFxbXFxdXSpcXF18XFxzKStNTU1NP3xNTU1NPyhcXFtbXlxcW1xcXV0qXFxdfFxccykrRFtvRF0/L1xuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydCA6ICdzYXVfdmFzX2tvdl9iYWxfZ2VnX2Jpcl9saWVfcmdwX3Jnc19zcGFfbGFwX2dyZCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiB7XG4gICAgICAgICAgICBmb3JtYXQ6ICdzZWttYWRpZW7Er19waXJtYWRpZW7Er19hbnRyYWRpZW7Er190cmXEjWlhZGllbsSvX2tldHZpcnRhZGllbsSvX3Blbmt0YWRpZW7Er1/FoWXFoXRhZGllbsSvJy5zcGxpdCgnXycpLFxuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ3Nla21hZGllbmlzX3Bpcm1hZGllbmlzX2FudHJhZGllbmlzX3RyZcSNaWFkaWVuaXNfa2V0dmlydGFkaWVuaXNfcGVua3RhZGllbmlzX8WhZcWhdGFkaWVuaXMnLnNwbGl0KCdfJyksXG4gICAgICAgICAgICBpc0Zvcm1hdDogL2RkZGQgSEg6bW0vXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnU2VrX1Bpcl9BbnRfVHJlX0tldF9QZW5fxaBlxaEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1NfUF9BX1RfS19Qbl/FoCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgICAgIExMIDogJ1lZWVkgW20uXSBNTU1NIEQgW2QuXScsXG4gICAgICAgICAgICBMTEwgOiAnWVlZWSBbbS5dIE1NTU0gRCBbZC5dLCBISDptbSBbdmFsLl0nLFxuICAgICAgICAgICAgTExMTCA6ICdZWVlZIFttLl0gTU1NTSBEIFtkLl0sIGRkZGQsIEhIOm1tIFt2YWwuXScsXG4gICAgICAgICAgICBsIDogJ1lZWVktTU0tREQnLFxuICAgICAgICAgICAgbGwgOiAnWVlZWSBbbS5dIE1NTU0gRCBbZC5dJyxcbiAgICAgICAgICAgIGxsbCA6ICdZWVlZIFttLl0gTU1NTSBEIFtkLl0sIEhIOm1tIFt2YWwuXScsXG4gICAgICAgICAgICBsbGxsIDogJ1lZWVkgW20uXSBNTU1NIEQgW2QuXSwgZGRkLCBISDptbSBbdmFsLl0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbxaBpYW5kaWVuXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1tSeXRval0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tWYWthcl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW1ByYcSXanVzxK9dIGRkZGQgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ3BvICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAncHJpZcWhICVzJyxcbiAgICAgICAgICAgIHMgOiB0cmFuc2xhdGVTZWNvbmRzLFxuICAgICAgICAgICAgc3MgOiB0cmFuc2xhdGUkNixcbiAgICAgICAgICAgIG0gOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgICAgIG1tIDogdHJhbnNsYXRlJDYsXG4gICAgICAgICAgICBoIDogdHJhbnNsYXRlU2luZ3VsYXIsXG4gICAgICAgICAgICBoaCA6IHRyYW5zbGF0ZSQ2LFxuICAgICAgICAgICAgZCA6IHRyYW5zbGF0ZVNpbmd1bGFyLFxuICAgICAgICAgICAgZGQgOiB0cmFuc2xhdGUkNixcbiAgICAgICAgICAgIE0gOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgICAgIE1NIDogdHJhbnNsYXRlJDYsXG4gICAgICAgICAgICB5IDogdHJhbnNsYXRlU2luZ3VsYXIsXG4gICAgICAgICAgICB5eSA6IHRyYW5zbGF0ZSQ2XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS1vamkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICctb2ppJztcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgdW5pdHMkMSA9IHtcbiAgICAgICAgJ3NzJzogJ3Nla3VuZGVzX3Nla3VuZMSTbV9zZWt1bmRlX3Nla3VuZGVzJy5zcGxpdCgnXycpLFxuICAgICAgICAnbSc6ICdtaW7Fq3Rlc19taW7Fq3TEk21fbWluxat0ZV9taW7Fq3Rlcycuc3BsaXQoJ18nKSxcbiAgICAgICAgJ21tJzogJ21pbsWrdGVzX21pbsWrdMSTbV9taW7Fq3RlX21pbsWrdGVzJy5zcGxpdCgnXycpLFxuICAgICAgICAnaCc6ICdzdHVuZGFzX3N0dW5kxIFtX3N0dW5kYV9zdHVuZGFzJy5zcGxpdCgnXycpLFxuICAgICAgICAnaGgnOiAnc3R1bmRhc19zdHVuZMSBbV9zdHVuZGFfc3R1bmRhcycuc3BsaXQoJ18nKSxcbiAgICAgICAgJ2QnOiAnZGllbmFzX2RpZW7EgW1fZGllbmFfZGllbmFzJy5zcGxpdCgnXycpLFxuICAgICAgICAnZGQnOiAnZGllbmFzX2RpZW7EgW1fZGllbmFfZGllbmFzJy5zcGxpdCgnXycpLFxuICAgICAgICAnTSc6ICdtxJNuZcWhYV9txJNuZcWhaWVtX23Ek25lc2lzX23Ek25lxaFpJy5zcGxpdCgnXycpLFxuICAgICAgICAnTU0nOiAnbcSTbmXFoWFfbcSTbmXFoWllbV9txJNuZXNpc19txJNuZcWhaScuc3BsaXQoJ18nKSxcbiAgICAgICAgJ3knOiAnZ2FkYV9nYWRpZW1fZ2Fkc19nYWRpJy5zcGxpdCgnXycpLFxuICAgICAgICAneXknOiAnZ2FkYV9nYWRpZW1fZ2Fkc19nYWRpJy5zcGxpdCgnXycpXG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gd2l0aG91dFN1ZmZpeCBib29sZWFuIHRydWUgPSBhIGxlbmd0aCBvZiB0aW1lOyBmYWxzZSA9IGJlZm9yZS9hZnRlciBhIHBlcmlvZCBvZiB0aW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZvcm1hdCQxKGZvcm1zLCBudW1iZXIsIHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgIC8vIEUuZy4gXCIyMSBtaW7Fq3RlXCIsIFwiMyBtaW7Fq3Rlc1wiLlxuICAgICAgICAgICAgcmV0dXJuIG51bWJlciAlIDEwID09PSAxICYmIG51bWJlciAlIDEwMCAhPT0gMTEgPyBmb3Jtc1syXSA6IGZvcm1zWzNdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gRS5nLiBcIjIxIG1pbsWrdGVzXCIgYXMgaW4gXCJwxJNjIDIxIG1pbsWrdGVzXCIuXG4gICAgICAgICAgICAvLyBFLmcuIFwiMyBtaW7Fq3TEk21cIiBhcyBpbiBcInDEk2MgMyBtaW7Fq3TEk21cIi5cbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgJSAxMCA9PT0gMSAmJiBudW1iZXIgJSAxMDAgIT09IDExID8gZm9ybXNbMF0gOiBmb3Jtc1sxXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciArICcgJyArIGZvcm1hdCQxKHVuaXRzJDFba2V5XSwgbnVtYmVyLCB3aXRob3V0U3VmZml4KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgIHJldHVybiBmb3JtYXQkMSh1bml0cyQxW2tleV0sIG51bWJlciwgd2l0aG91dFN1ZmZpeCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlbGF0aXZlU2Vjb25kcyhudW1iZXIsIHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnZGHFvmFzIHNla3VuZGVzJyA6ICdkYcW+xIFtIHNla3VuZMSTbSc7XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdsdicsIHtcbiAgICAgICAgbW9udGhzIDogJ2phbnbEgXJpc19mZWJydcSBcmlzX21hcnRzX2FwcsSrbGlzX21haWpzX2rFq25panNfasWrbGlqc19hdWd1c3RzX3NlcHRlbWJyaXNfb2t0b2JyaXNfbm92ZW1icmlzX2RlY2VtYnJpcycuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnamFuX2ZlYl9tYXJfYXByX21haV9qxatuX2rFq2xfYXVnX3NlcF9va3Rfbm92X2RlYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnc3bEk3RkaWVuYV9waXJtZGllbmFfb3RyZGllbmFfdHJlxaFkaWVuYV9jZXR1cnRkaWVuYV9waWVrdGRpZW5hX3Nlc3RkaWVuYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTdl9QX09fVF9DX1BrX1MnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1N2X1BfT19UX0NfUGtfUycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZLicsXG4gICAgICAgICAgICBMTCA6ICdZWVlZLiBbZ2FkYV0gRC4gTU1NTScsXG4gICAgICAgICAgICBMTEwgOiAnWVlZWS4gW2dhZGFdIEQuIE1NTU0sIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnWVlZWS4gW2dhZGFdIEQuIE1NTU0sIGRkZGQsIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW8Wgb2RpZW4gcHVsa3N0ZW5dIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW1LEq3QgcHVsa3N0ZW5dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW3B1bGtzdGVuXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tWYWthciBwdWxrc3Rlbl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW1BhZ8SBanXFocSBXSBkZGRkIFtwdWxrc3Rlbl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ3DEk2MgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICdwaXJtcyAlcycsXG4gICAgICAgICAgICBzIDogcmVsYXRpdmVTZWNvbmRzLFxuICAgICAgICAgICAgc3MgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEsXG4gICAgICAgICAgICBtIDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICAgICAgbW0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEsXG4gICAgICAgICAgICBoIDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICAgICAgaGggOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEsXG4gICAgICAgICAgICBkIDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICAgICAgZGQgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEsXG4gICAgICAgICAgICBNIDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDEsXG4gICAgICAgICAgICB5IDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDFcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbCA6ICclZC4nLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciB0cmFuc2xhdG9yID0ge1xuICAgICAgICB3b3JkczogeyAvL0RpZmZlcmVudCBncmFtbWF0aWNhbCBjYXNlc1xuICAgICAgICAgICAgc3M6IFsnc2VrdW5kJywgJ3Nla3VuZGEnLCAnc2VrdW5kaSddLFxuICAgICAgICAgICAgbTogWydqZWRhbiBtaW51dCcsICdqZWRub2cgbWludXRhJ10sXG4gICAgICAgICAgICBtbTogWydtaW51dCcsICdtaW51dGEnLCAnbWludXRhJ10sXG4gICAgICAgICAgICBoOiBbJ2plZGFuIHNhdCcsICdqZWRub2cgc2F0YSddLFxuICAgICAgICAgICAgaGg6IFsnc2F0JywgJ3NhdGEnLCAnc2F0aSddLFxuICAgICAgICAgICAgZGQ6IFsnZGFuJywgJ2RhbmEnLCAnZGFuYSddLFxuICAgICAgICAgICAgTU06IFsnbWplc2VjJywgJ21qZXNlY2EnLCAnbWplc2VjaSddLFxuICAgICAgICAgICAgeXk6IFsnZ29kaW5hJywgJ2dvZGluZScsICdnb2RpbmEnXVxuICAgICAgICB9LFxuICAgICAgICBjb3JyZWN0R3JhbW1hdGljYWxDYXNlOiBmdW5jdGlvbiAobnVtYmVyLCB3b3JkS2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyID09PSAxID8gd29yZEtleVswXSA6IChudW1iZXIgPj0gMiAmJiBudW1iZXIgPD0gNCA/IHdvcmRLZXlbMV0gOiB3b3JkS2V5WzJdKTtcbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNsYXRlOiBmdW5jdGlvbiAobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgICAgIHZhciB3b3JkS2V5ID0gdHJhbnNsYXRvci53b3Jkc1trZXldO1xuICAgICAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IHdvcmRLZXlbMF0gOiB3b3JkS2V5WzFdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgdHJhbnNsYXRvci5jb3JyZWN0R3JhbW1hdGljYWxDYXNlKG51bWJlciwgd29yZEtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdtZScsIHtcbiAgICAgICAgbW9udGhzOiAnamFudWFyX2ZlYnJ1YXJfbWFydF9hcHJpbF9tYWpfanVuX2p1bF9hdmd1c3Rfc2VwdGVtYmFyX29rdG9iYXJfbm92ZW1iYXJfZGVjZW1iYXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnamFuLl9mZWIuX21hci5fYXByLl9tYWpfanVuX2p1bF9hdmcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5czogJ25lZGplbGphX3BvbmVkamVsamFrX3V0b3Jha19zcmlqZWRhX8SNZXR2cnRha19wZXRha19zdWJvdGEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQ6ICduZWQuX3Bvbi5fdXRvLl9zcmkuX8SNZXQuX3BldC5fc3ViLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICduZV9wb191dF9zcl/EjWVfcGVfc3UnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhcjoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tkYW5hcyB1XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW3NqdXRyYSB1XSBMVCcsXG5cbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtuZWRqZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3NyaWplZHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzdWJvdHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheSAgOiAnW2p1xI1lIHVdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBsYXN0V2Vla0RheXMgPSBbXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsZV0gW25lZGplbGplXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICAgICAnW3Byb8WhbG9nXSBbcG9uZWRqZWxqa2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFt1dG9ya2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsZV0gW3NyaWplZGVdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFvEjWV0dnJ0a2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFtwZXRrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3Vib3RlXSBbdV0gTFQnXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFzdFdlZWtEYXlzW3RoaXMuZGF5KCldO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICd6YSAlcycsXG4gICAgICAgICAgICBwYXN0ICAgOiAncHJpamUgJXMnLFxuICAgICAgICAgICAgcyAgICAgIDogJ25la29saWtvIHNla3VuZGknLFxuICAgICAgICAgICAgc3MgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgICAgICBtICAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIG1tICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICAgICAgaCAgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgICAgICBoaCAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGQgICAgICA6ICdkYW4nLFxuICAgICAgICAgICAgZGQgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgICAgICBNICAgICAgOiAnbWplc2VjJyxcbiAgICAgICAgICAgIE1NICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICAgICAgeSAgICAgIDogJ2dvZGludScsXG4gICAgICAgICAgICB5eSAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdtaScsIHtcbiAgICAgICAgbW9udGhzOiAnS29oaS10xIF0ZV9IdWktdGFuZ3VydV9Qb3V0xastdGUtcmFuZ2lfUGFlbmdhLXdoxIF3aMSBX0hhcmF0dWFfUGlwaXJpX0jFjW5nb2luZ29pX0hlcmUtdHVyaS1rxY1rxIFfTWFodXJ1X1doaXJpbmdhLcSBLW51a3VfV2hpcmluZ2EtxIEtcmFuZ2lfSGFraWhlYScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICdLb2hpX0h1aV9Qb3VfUGFlX0hhcmFfUGlwaV9IxY1uZ29pX0hlcmVfTWFodV9XaGktbnVfV2hpLXJhX0hha2knLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1JlZ2V4OiAvKD86WydhLXpcXHUwMTAxXFx1MDE0RFxcdTAxNkJdK1xcLT8pezEsM30vaSxcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC8oPzpbJ2EtelxcdTAxMDFcXHUwMTREXFx1MDE2Ql0rXFwtPyl7MSwzfS9pLFxuICAgICAgICBtb250aHNTaG9ydFJlZ2V4OiAvKD86WydhLXpcXHUwMTAxXFx1MDE0RFxcdTAxNkJdK1xcLT8pezEsM30vaSxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogLyg/OlsnYS16XFx1MDEwMVxcdTAxNERcXHUwMTZCXStcXC0/KXsxLDJ9L2ksXG4gICAgICAgIHdlZWtkYXlzOiAnUsSBdGFwdV9NYW5lX1TFq3JlaV9XZW5lcmVpX1TEgWl0ZV9QYXJhaXJlX0jEgXRhcmVpJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnVGFfTWFfVMWrX1dlX1TEgWlfUGFfSMSBJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbjogJ1RhX01hX1TFq19XZV9UxIFpX1BhX0jEgScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBbaV0gSEg6bW0nLFxuICAgICAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIFtpXSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbaSB0ZWllIG1haGFuYSwgaV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1thcG9wbyBpXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2ldIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbaW5hbmFoaSBpXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW3doYWthbXV0dW5nYSBpXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAnaSByb3RvIGkgJXMnLFxuICAgICAgICAgICAgcGFzdDogJyVzIGkgbXVhJyxcbiAgICAgICAgICAgIHM6ICd0ZSBoxJNrb25hIHJ1YXJ1YScsXG4gICAgICAgICAgICBzczogJyVkIGjEk2tvbmEnLFxuICAgICAgICAgICAgbTogJ2hlIG1lbmV0aScsXG4gICAgICAgICAgICBtbTogJyVkIG1lbmV0aScsXG4gICAgICAgICAgICBoOiAndGUgaGFvcmEnLFxuICAgICAgICAgICAgaGg6ICclZCBoYW9yYScsXG4gICAgICAgICAgICBkOiAnaGUgcmEnLFxuICAgICAgICAgICAgZGQ6ICclZCByYScsXG4gICAgICAgICAgICBNOiAnaGUgbWFyYW1hJyxcbiAgICAgICAgICAgIE1NOiAnJWQgbWFyYW1hJyxcbiAgICAgICAgICAgIHk6ICdoZSB0YXUnLFxuICAgICAgICAgICAgeXk6ICclZCB0YXUnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbDogJyVkwronLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbWsnLCB7XG4gICAgICAgIG1vbnRocyA6ICfRmNCw0L3Rg9Cw0YDQuF/RhNC10LLRgNGD0LDRgNC4X9C80LDRgNGCX9Cw0L/RgNC40Ltf0LzQsNGYX9GY0YPQvdC4X9GY0YPQu9C4X9Cw0LLQs9GD0YHRgl/RgdC10L/RgtC10LzQstGA0Lhf0L7QutGC0L7QvNCy0YDQuF/QvdC+0LXQvNCy0YDQuF/QtNC10LrQtdC80LLRgNC4Jy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICfRmNCw0L1f0YTQtdCyX9C80LDRgF/QsNC/0YBf0LzQsNGYX9GY0YPQvV/RmNGD0Ltf0LDQstCzX9GB0LXQv1/QvtC60YJf0L3QvtC1X9C00LXQuicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAn0L3QtdC00LXQu9CwX9C/0L7QvdC10LTQtdC70L3QuNC6X9Cy0YLQvtGA0L3QuNC6X9GB0YDQtdC00LBf0YfQtdGC0LLRgNGC0L7Qul/Qv9C10YLQvtC6X9GB0LDQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfQvdC10LRf0L/QvtC9X9Cy0YLQvl/RgdGA0LVf0YfQtdGCX9C/0LXRgl/RgdCw0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ9C9ZV/Qv29f0LLRgl/RgdGAX9GH0LVf0L/QtV/RgWEnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0QuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb0JTQtdC90LXRgSDQstC+XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vQo9GC0YDQtSDQstC+XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdb0JLQvl0gZGRkZCBb0LLQvl0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb0JLRh9C10YDQsCDQstC+XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CY0LfQvNC40L3QsNGC0LDRgtCwXSBkZGRkIFvQstC+XSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CY0LfQvNC40L3QsNGC0LjQvtGCXSBkZGRkIFvQstC+XSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfQv9C+0YHQu9C1ICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAn0L/RgNC10LQgJXMnLFxuICAgICAgICAgICAgcyA6ICfQvdC10LrQvtC70LrRgyDRgdC10LrRg9C90LTQuCcsXG4gICAgICAgICAgICBzcyA6ICclZCDRgdC10LrRg9C90LTQuCcsXG4gICAgICAgICAgICBtIDogJ9C80LjQvdGD0YLQsCcsXG4gICAgICAgICAgICBtbSA6ICclZCDQvNC40L3Rg9GC0LgnLFxuICAgICAgICAgICAgaCA6ICfRh9Cw0YEnLFxuICAgICAgICAgICAgaGggOiAnJWQg0YfQsNGB0LAnLFxuICAgICAgICAgICAgZCA6ICfQtNC10L0nLFxuICAgICAgICAgICAgZGQgOiAnJWQg0LTQtdC90LAnLFxuICAgICAgICAgICAgTSA6ICfQvNC10YHQtdGGJyxcbiAgICAgICAgICAgIE1NIDogJyVkINC80LXRgdC10YbQuCcsXG4gICAgICAgICAgICB5IDogJ9Cz0L7QtNC40L3QsCcsXG4gICAgICAgICAgICB5eSA6ICclZCDQs9C+0LTQuNC90LgnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS0o0LXQsnzQtdC9fNGC0Lh80LLQuHzRgNC4fNC80LgpLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBsYXN0RGlnaXQgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBsYXN0MkRpZ2l0cyA9IG51bWJlciAlIDEwMDtcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QtdCyJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGFzdDJEaWdpdHMgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QtdC9JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGFzdDJEaWdpdHMgPiAxMCAmJiBsYXN0MkRpZ2l0cyA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0YLQuCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxhc3REaWdpdCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdCy0LgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0RGlnaXQgPT09IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3RgNC4JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGFzdERpZ2l0ID09PSA3IHx8IGxhc3REaWdpdCA9PT0gOCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC80LgnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3RgtC4JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ21sJywge1xuICAgICAgICBtb250aHMgOiAn4LSc4LSo4LWB4LS14LSw4LS/X+C0q+C1huC0rOC1jeC0sOC1geC0teC0sOC0v1/gtK7gtL7gtbzgtJrgtY3gtJrgtY1f4LSP4LSq4LWN4LSw4LS/4LW9X+C0ruC1h+C0r+C1jV/gtJzgtYLgtbpf4LSc4LWC4LSy4LWIX+C0k+C0l+C0uOC1jeC0seC1jeC0seC1jV/gtLjgtYbgtKrgtY3gtLHgtY3gtLHgtILgtKzgtbxf4LSS4LSV4LWN4LSf4LWL4LSs4LW8X+C0qOC0teC0guC0rOC1vF/gtKHgtL/gtLjgtILgtKzgtbwnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ+C0nOC0qOC1gS5f4LSr4LWG4LSs4LWN4LSw4LWBLl/gtK7gtL7gtbwuX+C0j+C0quC1jeC0sOC0vy5f4LSu4LWH4LSv4LWNX+C0nOC1guC1ul/gtJzgtYLgtLLgtYguX+C0k+C0ly5f4LS44LWG4LSq4LWN4LSx4LWN4LSxLl/gtJLgtJXgtY3gtJ/gtYsuX+C0qOC0teC0gi5f4LSh4LS/4LS44LSCLicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogJ+C0nuC0vuC0r+C0seC0vuC0tOC1jeC0ml/gtKTgtL/gtJngtY3gtJXgtLPgtL7gtLTgtY3gtJpf4LSa4LWK4LS14LWN4LS14LS+4LS04LWN4LSaX+C0rOC1geC0p+C0qOC0vuC0tOC1jeC0ml/gtLXgtY3gtK/gtL7gtLTgtL7gtLTgtY3gtJpf4LS14LWG4LSz4LWN4LSz4LS/4LSv4LS+4LS04LWN4LSaX+C0tuC0qOC0v+C0r+C0vuC0tOC1jeC0micuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfgtJ7gtL7gtK/gtbxf4LSk4LS/4LSZ4LWN4LSV4LW+X+C0muC1iuC0teC1jeC0tV/gtKzgtYHgtKfgtbtf4LS14LWN4LSv4LS+4LS04LSCX+C0teC1huC0s+C1jeC0s+C0v1/gtLbgtKjgtL8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ+C0nuC0vl/gtKTgtL9f4LSa4LWKX+C0rOC1gV/gtLXgtY3gtK/gtL5f4LS14LWGX+C0ticuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdBIGg6bW0gLeC0qOC1gScsXG4gICAgICAgICAgICBMVFMgOiAnQSBoOm1tOnNzIC3gtKjgtYEnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIC3gtKjgtYEnLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tIC3gtKjgtYEnXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb4LSH4LSo4LWN4LSo4LWNXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vgtKjgtL7gtLPgtYZdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW+C0h+C0qOC1jeC0qOC0suC1hl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW+C0leC0tOC0v+C0nuC1jeC0nl0gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVzIOC0leC0tOC0v+C0nuC1jeC0nuC1jScsXG4gICAgICAgICAgICBwYXN0IDogJyVzIOC0ruC1geC1u+C0quC1jScsXG4gICAgICAgICAgICBzIDogJ+C0heC1veC0qiDgtKjgtL/gtK7gtL/gtLfgtJngtY3gtJngtb4nLFxuICAgICAgICAgICAgc3MgOiAnJWQg4LS44LWG4LSV4LWN4LSV4LW74LSh4LWNJyxcbiAgICAgICAgICAgIG0gOiAn4LSS4LSw4LWBIOC0ruC0v+C0qOC0v+C0seC1jeC0seC1jScsXG4gICAgICAgICAgICBtbSA6ICclZCDgtK7gtL/gtKjgtL/gtLHgtY3gtLHgtY0nLFxuICAgICAgICAgICAgaCA6ICfgtJLgtLDgtYEg4LSu4LSj4LS/4LSV4LWN4LSV4LWC4LW8JyxcbiAgICAgICAgICAgIGhoIDogJyVkIOC0ruC0o+C0v+C0leC1jeC0leC1guC1vCcsXG4gICAgICAgICAgICBkIDogJ+C0kuC0sOC1gSDgtKbgtL/gtLXgtLjgtIInLFxuICAgICAgICAgICAgZGQgOiAnJWQg4LSm4LS/4LS14LS44LSCJyxcbiAgICAgICAgICAgIE0gOiAn4LSS4LSw4LWBIOC0ruC0vuC0uOC0gicsXG4gICAgICAgICAgICBNTSA6ICclZCDgtK7gtL7gtLjgtIInLFxuICAgICAgICAgICAgeSA6ICfgtJLgtLDgtYEg4LS14LW84LS34LSCJyxcbiAgICAgICAgICAgIHl5IDogJyVkIOC0teC1vOC0t+C0gidcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+C0sOC0vuC0pOC1jeC0sOC0v3zgtLDgtL7gtLXgtL/gtLLgtYZ84LSJ4LSa4LWN4LSaIOC0leC0tOC0v+C0nuC1jeC0nuC1jXzgtLXgtYjgtJXgtYHgtKjgtY3gtKjgtYfgtLDgtIJ84LSw4LS+4LSk4LWN4LSw4LS/L2ksXG4gICAgICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoKG1lcmlkaWVtID09PSAn4LSw4LS+4LSk4LWN4LSw4LS/JyAmJiBob3VyID49IDQpIHx8XG4gICAgICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn4LSJ4LSa4LWN4LSaIOC0leC0tOC0v+C0nuC1jeC0nuC1jScgfHxcbiAgICAgICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfgtLXgtYjgtJXgtYHgtKjgtY3gtKjgtYfgtLDgtIInKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgtLDgtL7gtKTgtY3gtLDgtL8nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C0sOC0vuC0teC0v+C0suC1hic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LSJ4LSa4LWN4LSaIOC0leC0tOC0v+C0nuC1jeC0nuC1jSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LS14LWI4LSV4LWB4LSo4LWN4LSo4LWH4LSw4LSCJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgtLDgtL7gtKTgtY3gtLDgtL8nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkNyhudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9GF0Y3QtNGF0Y3QvSDRgdC10LrRg9C90LQnIDogJ9GF0Y3QtNGF0Y3QvSDRgdC10LrRg9C90LTRi9C9JztcbiAgICAgICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKHdpdGhvdXRTdWZmaXggPyAnINGB0LXQutGD0L3QtCcgOiAnINGB0LXQutGD0L3QtNGL0L0nKTtcbiAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAod2l0aG91dFN1ZmZpeCA/ICcg0LzQuNC90YPRgicgOiAnINC80LjQvdGD0YLRi9C9Jyk7XG4gICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKHdpdGhvdXRTdWZmaXggPyAnINGG0LDQsycgOiAnINGG0LDQs9C40LnQvScpO1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICh3aXRob3V0U3VmZml4ID8gJyDTqdC006nRgCcgOiAnINOp0LTRgNC40LnQvScpO1xuICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICh3aXRob3V0U3VmZml4ID8gJyDRgdCw0YAnIDogJyDRgdCw0YDRi9C9Jyk7XG4gICAgICAgICAgICBjYXNlICd5JzpcbiAgICAgICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKHdpdGhvdXRTdWZmaXggPyAnINC20LjQuycgOiAnINC20LjQu9C40LnQvScpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdtbicsIHtcbiAgICAgICAgbW9udGhzIDogJ9Cd0Y3Qs9C00q/Qs9GN0Y3RgCDRgdCw0YBf0KXQvtGR0YDQtNGD0LPQsNCw0YAg0YHQsNGAX9CT0YPRgNCw0LLQtNGD0LPQsNCw0YAg0YHQsNGAX9CU06nRgNOp0LLQtNKv0LPRjdGN0YAg0YHQsNGAX9Ci0LDQstC00YPQs9Cw0LDRgCDRgdCw0YBf0JfRg9GA0LPQsNC00YPQs9Cw0LDRgCDRgdCw0YBf0JTQvtC70LTRg9Cz0LDQsNGAINGB0LDRgF/QndCw0LnQvNC00YPQs9Cw0LDRgCDRgdCw0YBf0JXRgdC00q/Qs9GN0Y3RgCDRgdCw0YBf0JDRgNCw0LLQtNGD0LPQsNCw0YAg0YHQsNGAX9CQ0YDQstCw0L0g0L3RjdCz0LTSr9Cz0Y3RjdGAINGB0LDRgF/QkNGA0LLQsNC9INGF0L7RkdGA0LTRg9Cz0LDQsNGAINGB0LDRgCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnMSDRgdCw0YBfMiDRgdCw0YBfMyDRgdCw0YBfNCDRgdCw0YBfNSDRgdCw0YBfNiDRgdCw0YBfNyDRgdCw0YBfOCDRgdCw0YBfOSDRgdCw0YBfMTAg0YHQsNGAXzExINGB0LDRgF8xMiDRgdCw0YAnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICfQndGP0Lxf0JTQsNCy0LDQsF/QnNGP0LPQvNCw0YBf0JvRhdCw0LPQstCwX9Cf0q/RgNGN0LJf0JHQsNCw0YHQsNC9X9CR0Y/QvNCx0LAnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn0J3Rj9C8X9CU0LDQsl/QnNGP0LNf0JvRhdCwX9Cf0q/RgF/QkdCw0LBf0JHRj9C8Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfQndGPX9CU0LBf0JzRj1/Qm9GFX9Cf0q9f0JHQsF/QkdGPJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ1lZWVktTU0tREQnLFxuICAgICAgICAgICAgTEwgOiAnWVlZWSDQvtC90YsgTU1NTdGL0L0gRCcsXG4gICAgICAgICAgICBMTEwgOiAnWVlZWSDQvtC90YsgTU1NTdGL0L0gRCBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIFlZWVkg0L7QvdGLIE1NTU3Ri9C9IEQgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/SrtOofNKu0KUvaSxcbiAgICAgICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn0q7QpSc7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0q7TqCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0q7QpSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb06jQvdOp06nQtNOp0YBdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW9Cc0LDRgNCz0LDQsNGIXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdb0JjRgNGN0YVdIGRkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb06jRh9C40LPQtNOp0YBdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1vTqNC90LPTqdGA0YHTqdC9XSBkZGRkIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyDQtNCw0YDQsNCwJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMg06nQvNC906knLFxuICAgICAgICAgICAgcyA6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICAgICAgc3MgOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgICAgIG0gOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgICAgIG1tIDogdHJhbnNsYXRlJDcsXG4gICAgICAgICAgICBoIDogdHJhbnNsYXRlJDcsXG4gICAgICAgICAgICBoaCA6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICAgICAgZCA6IHRyYW5zbGF0ZSQ3LFxuICAgICAgICAgICAgZGQgOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgICAgIE0gOiB0cmFuc2xhdGUkNyxcbiAgICAgICAgICAgIE1NIDogdHJhbnNsYXRlJDcsXG4gICAgICAgICAgICB5IDogdHJhbnNsYXRlJDcsXG4gICAgICAgICAgICB5eSA6IHRyYW5zbGF0ZSQ3XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSDTqdC006nRgC8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcg06nQtNOp0YAnO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkYiA9IHtcbiAgICAgICAgJzEnOiAn4KWnJyxcbiAgICAgICAgJzInOiAn4KWoJyxcbiAgICAgICAgJzMnOiAn4KWpJyxcbiAgICAgICAgJzQnOiAn4KWqJyxcbiAgICAgICAgJzUnOiAn4KWrJyxcbiAgICAgICAgJzYnOiAn4KWsJyxcbiAgICAgICAgJzcnOiAn4KWtJyxcbiAgICAgICAgJzgnOiAn4KWuJyxcbiAgICAgICAgJzknOiAn4KWvJyxcbiAgICAgICAgJzAnOiAn4KWmJ1xuICAgIH0sXG4gICAgbnVtYmVyTWFwJGEgPSB7XG4gICAgICAgICfgpacnOiAnMScsXG4gICAgICAgICfgpagnOiAnMicsXG4gICAgICAgICfgpaknOiAnMycsXG4gICAgICAgICfgpaonOiAnNCcsXG4gICAgICAgICfgpasnOiAnNScsXG4gICAgICAgICfgpawnOiAnNicsXG4gICAgICAgICfgpa0nOiAnNycsXG4gICAgICAgICfgpa4nOiAnOCcsXG4gICAgICAgICfgpa8nOiAnOScsXG4gICAgICAgICfgpaYnOiAnMCdcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lTXIobnVtYmVyLCB3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKVxuICAgIHtcbiAgICAgICAgdmFyIG91dHB1dCA9ICcnO1xuICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgc3dpdGNoIChzdHJpbmcpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdzJzogb3V0cHV0ID0gJ+CkleCkvuCkueClgCDgpLjgpYfgpJXgpILgpKYnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzcyc6IG91dHB1dCA9ICclZCDgpLjgpYfgpJXgpILgpKYnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdtJzogb3V0cHV0ID0gJ+Ckj+CklSDgpK7gpL/gpKjgpL/gpJ8nOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdtbSc6IG91dHB1dCA9ICclZCDgpK7gpL/gpKjgpL/gpJ/gpYcnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdoJzogb3V0cHV0ID0gJ+Ckj+CklSDgpKTgpL7gpLgnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdoaCc6IG91dHB1dCA9ICclZCDgpKTgpL7gpLgnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdkJzogb3V0cHV0ID0gJ+Ckj+CklSDgpKbgpL/gpLXgpLgnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdkZCc6IG91dHB1dCA9ICclZCDgpKbgpL/gpLXgpLgnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdNJzogb3V0cHV0ID0gJ+Ckj+CklSDgpK7gpLngpL/gpKjgpL4nOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdNTSc6IG91dHB1dCA9ICclZCDgpK7gpLngpL/gpKjgpYcnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd5Jzogb3V0cHV0ID0gJ+Ckj+CklSDgpLXgpLDgpY3gpLcnOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd5eSc6IG91dHB1dCA9ICclZCDgpLXgpLDgpY3gpLfgpYcnOyBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHN3aXRjaCAoc3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAncyc6IG91dHB1dCA9ICfgpJXgpL7gpLngpYAg4KS44KWH4KSV4KSC4KSm4KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3MnOiBvdXRwdXQgPSAnJWQg4KS44KWH4KSV4KSC4KSm4KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnbSc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KSu4KS/4KSo4KS/4KSf4KS+JzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnbW0nOiBvdXRwdXQgPSAnJWQg4KSu4KS/4KSo4KS/4KSf4KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnaCc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KSk4KS+4KS44KS+JzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnaGgnOiBvdXRwdXQgPSAnJWQg4KSk4KS+4KS44KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KSm4KS/4KS14KS44KS+JzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnZGQnOiBvdXRwdXQgPSAnJWQg4KSm4KS/4KS14KS44KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KSu4KS54KS/4KSo4KWN4KSv4KS+JzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnTU0nOiBvdXRwdXQgPSAnJWQg4KSu4KS54KS/4KSo4KWN4KSv4KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAneSc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KS14KSw4KWN4KS34KS+JzsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAneXknOiBvdXRwdXQgPSAnJWQg4KS14KSw4KWN4KS34KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dHB1dC5yZXBsYWNlKC8lZC9pLCBudW1iZXIpO1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbXInLCB7XG4gICAgICAgIG1vbnRocyA6ICfgpJzgpL7gpKjgpYfgpLXgpL7gpLDgpYBf4KSr4KWH4KSs4KWN4KSw4KWB4KS14KS+4KSw4KWAX+CkruCkvuCksOCljeCkml/gpI/gpKrgpY3gpLDgpL/gpLJf4KSu4KWHX+CknOClguCkqF/gpJzgpYHgpLLgpYhf4KSR4KSX4KS44KWN4KSfX+CkuOCkquCljeCkn+Clh+CkguCkrOCksF/gpJHgpJXgpY3gpJ/gpYvgpKzgpLBf4KSo4KWL4KS14KWN4KS54KWH4KSC4KSs4KSwX+CkoeCkv+CkuOClh+CkguCkrOCksCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQ6ICfgpJzgpL7gpKjgpYcuX+Ckq+Clh+CkrOCljeCksOClgS5f4KSu4KS+4KSw4KWN4KSaLl/gpI/gpKrgpY3gpLDgpL8uX+CkruClhy5f4KSc4KWC4KSoLl/gpJzgpYHgpLLgpYguX+CkkeCkly5f4KS44KSq4KWN4KSf4KWH4KSCLl/gpJHgpJXgpY3gpJ/gpYsuX+CkqOCli+CkteCljeCkueClh+Ckgi5f4KSh4KS/4KS44KWH4KSCLicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogJ+CksOCkteCkv+CkteCkvuCksF/gpLjgpYvgpK7gpLXgpL7gpLBf4KSu4KSC4KSX4KSz4KS14KS+4KSwX+CkrOClgeCkp+CkteCkvuCksF/gpJfgpYHgpLDgpYLgpLXgpL7gpLBf4KS24KWB4KSV4KWN4KSw4KS14KS+4KSwX+CktuCkqOCkv+CkteCkvuCksCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfgpLDgpLXgpL9f4KS44KWL4KSuX+CkruCkguCkl+Cks1/gpKzgpYHgpKdf4KSX4KWB4KSw4KWCX+CktuClgeCkleCljeCksF/gpLbgpKjgpL8nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ+CksF/gpLjgpYtf4KSu4KSCX+CkrOClgV/gpJfgpYFf4KS24KWBX+Ckticuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdBIGg6bW0g4KS14KS+4KSc4KSk4KS+JyxcbiAgICAgICAgICAgIExUUyA6ICdBIGg6bW06c3Mg4KS14KS+4KSc4KSk4KS+JyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEEgaDptbSDgpLXgpL7gpJzgpKTgpL4nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tIOCkteCkvuCknOCkpOCkvidcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1vgpIbgpJxdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW+CkieCkpuCljeCkr+Ckvl0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCwgTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb4KSV4KS+4KSyXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1vgpK7gpL7gpJfgpYDgpLJdIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJyVz4KSu4KSn4KWN4KSv4KWHJyxcbiAgICAgICAgICAgIHBhc3Q6ICclc+CkquClguCksOCljeCkteClgCcsXG4gICAgICAgICAgICBzOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgICAgIHNzOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgICAgIG06IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICAgICAgbW06IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICAgICAgaDogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgICAgICBoaDogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgICAgICBkOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgICAgIGRkOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgICAgIE06IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICAgICAgTU06IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICAgICAgeTogcmVsYXRpdmVUaW1lTXIsXG4gICAgICAgICAgICB5eTogcmVsYXRpdmVUaW1lTXJcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Clp+ClqOClqeClquClq+ClrOClreClruClr+Clpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCRhW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJGJbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gpLDgpL7gpKTgpY3gpLDgpYB84KS44KSV4KS+4KSz4KWAfOCkpuClgeCkquCkvuCksOClgHzgpLjgpL7gpK/gpILgpJXgpL7gpLPgpYAvLFxuICAgICAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSw4KS+4KSk4KWN4KSw4KWAJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS44KSV4KS+4KSz4KWAJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkpuClgeCkquCkvuCksOClgCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS44KS+4KSv4KSC4KSV4KS+4KSz4KWAJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CksOCkvuCkpOCljeCksOClgCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KS44KSV4KS+4KSz4KWAJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpKbgpYHgpKrgpL7gpLDgpYAnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CkuOCkvuCkr+CkguCkleCkvuCks+ClgCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSk4KWN4KSw4KWAJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ21zLW15Jywge1xuICAgICAgICBtb250aHMgOiAnSmFudWFyaV9GZWJydWFyaV9NYWNfQXByaWxfTWVpX0p1bl9KdWxhaV9PZ29zX1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0Rpc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hY19BcHJfTWVpX0p1bl9KdWxfT2dzX1NlcF9Pa3RfTm92X0Rpcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnQWhhZF9Jc25pbl9TZWxhc2FfUmFidV9LaGFtaXNfSnVtYWF0X1NhYnR1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ0FoZF9Jc25fU2VsX1JhYl9LaGFfSnVtX1NhYicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnQWhfSXNfU2xfUmJfS21fSm1fU2InLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEgubW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hILm1tLnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9wYWdpfHRlbmdhaGFyaXxwZXRhbmd8bWFsYW0vLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICdwYWdpJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3RlbmdhaGFyaScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAncGV0YW5nJyB8fCBtZXJpZGllbSA9PT0gJ21hbGFtJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPCAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAncGFnaSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3RlbmdhaGFyaSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3BldGFuZyc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAnbWFsYW0nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW0hhcmkgaW5pIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1tFc29rIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbS2VsbWFyaW4gcHVrdWxdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW2xlcGFzIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnZGFsYW0gJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyB5YW5nIGxlcGFzJyxcbiAgICAgICAgICAgIHMgOiAnYmViZXJhcGEgc2FhdCcsXG4gICAgICAgICAgICBzcyA6ICclZCBzYWF0JyxcbiAgICAgICAgICAgIG0gOiAnc2VtaW5pdCcsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW5pdCcsXG4gICAgICAgICAgICBoIDogJ3NlamFtJyxcbiAgICAgICAgICAgIGhoIDogJyVkIGphbScsXG4gICAgICAgICAgICBkIDogJ3NlaGFyaScsXG4gICAgICAgICAgICBkZCA6ICclZCBoYXJpJyxcbiAgICAgICAgICAgIE0gOiAnc2VidWxhbicsXG4gICAgICAgICAgICBNTSA6ICclZCBidWxhbicsXG4gICAgICAgICAgICB5IDogJ3NldGFodW4nLFxuICAgICAgICAgICAgeXkgOiAnJWQgdGFodW4nXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdtcycsIHtcbiAgICAgICAgbW9udGhzIDogJ0phbnVhcmlfRmVicnVhcmlfTWFjX0FwcmlsX01laV9KdW5fSnVsYWlfT2dvc19TZXB0ZW1iZXJfT2t0b2Jlcl9Ob3ZlbWJlcl9EaXNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnSmFuX0ZlYl9NYWNfQXByX01laV9KdW5fSnVsX09nc19TZXBfT2t0X05vdl9EaXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ0FoYWRfSXNuaW5fU2VsYXNhX1JhYnVfS2hhbWlzX0p1bWFhdF9TYWJ0dScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdBaGRfSXNuX1NlbF9SYWJfS2hhX0p1bV9TYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ0FoX0lzX1NsX1JiX0ttX0ptX1NiJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hILm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISC5tbS5zcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAvcGFnaXx0ZW5nYWhhcml8cGV0YW5nfG1hbGFtLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAncGFnaScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICd0ZW5nYWhhcmknKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3BldGFuZycgfHwgbWVyaWRpZW0gPT09ICdtYWxhbScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXJzIDwgMTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3BhZ2knO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE1KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICd0ZW5nYWhhcmknO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdwZXRhbmcnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ21hbGFtJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tIYXJpIGluaSBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbRXNvayBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW0tlbG1hcmluIHB1a3VsXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtsZXBhcyBwdWt1bF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2RhbGFtICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgeWFuZyBsZXBhcycsXG4gICAgICAgICAgICBzIDogJ2JlYmVyYXBhIHNhYXQnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2FhdCcsXG4gICAgICAgICAgICBtIDogJ3NlbWluaXQnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWluaXQnLFxuICAgICAgICAgICAgaCA6ICdzZWphbScsXG4gICAgICAgICAgICBoaCA6ICclZCBqYW0nLFxuICAgICAgICAgICAgZCA6ICdzZWhhcmknLFxuICAgICAgICAgICAgZGQgOiAnJWQgaGFyaScsXG4gICAgICAgICAgICBNIDogJ3NlYnVsYW4nLFxuICAgICAgICAgICAgTU0gOiAnJWQgYnVsYW4nLFxuICAgICAgICAgICAgeSA6ICdzZXRhaHVuJyxcbiAgICAgICAgICAgIHl5IDogJyVkIHRhaHVuJ1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbXQnLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW5uYXJfRnJhcl9NYXJ6dV9BcHJpbF9NZWpqdV/EoHVuanVfTHVsanVfQXd3aXNzdV9TZXR0ZW1icnVfT3R0dWJydV9Ob3ZlbWJydV9EacSLZW1icnUnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GcmFfTWFyX0Fwcl9NZWpfxKB1bl9MdWxfQXd3X1NldF9PdHRfTm92X0RpxIsnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ0lsLcSmYWRkX0l0LVRuZWpuX0l0LVRsaWV0YV9MLUVyYmfEp2FfSWwtxKZhbWlzX0lsLcSgaW1nxKdhX0lzLVNpYnQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnxKZhZF9UbmVfVGxpX0VyYl/EpmFtX8SgaW1fU2liJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfEpmFfVG5fVGxfRXJfxKZhX8SgaV9TaScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW0lsbHVtIGZpbC1dTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbR8SnYWRhIGZpbC1dTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbZmlsLV1MVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tJbC1iaWVyYcSnIGZpbC1dTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbbGkgZ8SnYWRkYV0gW2ZpbC1dTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ2bigJkgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyBpbHUnLFxuICAgICAgICAgICAgcyA6ICdmdGl0IHNla29uZGknLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2Vrb25kaScsXG4gICAgICAgICAgICBtIDogJ21pbnV0YScsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dGknLFxuICAgICAgICAgICAgaCA6ICdzaWVnxKdhJyxcbiAgICAgICAgICAgIGhoIDogJyVkIHNpZWfEp2F0JyxcbiAgICAgICAgICAgIGQgOiAnxKF1cm5hdGEnLFxuICAgICAgICAgICAgZGQgOiAnJWQgxKFyYW5ldCcsXG4gICAgICAgICAgICBNIDogJ3hhaGFyJyxcbiAgICAgICAgICAgIE1NIDogJyVkIHhodXInLFxuICAgICAgICAgICAgeSA6ICdzZW5hJyxcbiAgICAgICAgICAgIHl5IDogJyVkIHNuaSdcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfcK6LyxcbiAgICAgICAgb3JkaW5hbDogJyVkwronLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBzeW1ib2xNYXAkYyA9IHtcbiAgICAgICAgJzEnOiAn4YGBJyxcbiAgICAgICAgJzInOiAn4YGCJyxcbiAgICAgICAgJzMnOiAn4YGDJyxcbiAgICAgICAgJzQnOiAn4YGEJyxcbiAgICAgICAgJzUnOiAn4YGFJyxcbiAgICAgICAgJzYnOiAn4YGGJyxcbiAgICAgICAgJzcnOiAn4YGHJyxcbiAgICAgICAgJzgnOiAn4YGIJyxcbiAgICAgICAgJzknOiAn4YGJJyxcbiAgICAgICAgJzAnOiAn4YGAJ1xuICAgIH0sIG51bWJlck1hcCRiID0ge1xuICAgICAgICAn4YGBJzogJzEnLFxuICAgICAgICAn4YGCJzogJzInLFxuICAgICAgICAn4YGDJzogJzMnLFxuICAgICAgICAn4YGEJzogJzQnLFxuICAgICAgICAn4YGFJzogJzUnLFxuICAgICAgICAn4YGGJzogJzYnLFxuICAgICAgICAn4YGHJzogJzcnLFxuICAgICAgICAn4YGIJzogJzgnLFxuICAgICAgICAn4YGJJzogJzknLFxuICAgICAgICAn4YGAJzogJzAnXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbXknLCB7XG4gICAgICAgIG1vbnRoczogJ+GAh+GAlOGAuuGAlOGAneGAq+GAm+GArl/hgJbhgLHhgJbhgLHhgKzhgLrhgJ3hgKvhgJvhgK5f4YCZ4YCQ4YC6X+GAp+GAleGAvOGArl/hgJnhgLFf4YCH4YC94YCU4YC6X+GAh+GAsOGAnOGAreGAr+GAhOGAul/hgJ7hgLzhgILhgK/hgJDhgLpf4YCF4YCA4YC64YCQ4YCE4YC64YCY4YCsX+GAoeGAseGArOGAgOGAuuGAkOGAreGAr+GAmOGArF/hgJThgK3hgK/hgJ3hgIThgLrhgJjhgKxf4YCS4YCu4YCH4YCE4YC64YCY4YCsJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydDogJ+GAh+GAlOGAul/hgJbhgLFf4YCZ4YCQ4YC6X+GAleGAvOGArl/hgJnhgLFf4YCH4YC94YCU4YC6X+GAnOGAreGAr+GAhOGAul/hgJ7hgLxf4YCF4YCA4YC6X+GAoeGAseGArOGAgOGAul/hgJThgK3hgK9f4YCS4YCuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5czogJ+GAkOGAlOGAhOGAuuGAueGAguGAlOGAveGAsV/hgJDhgJThgIThgLrhgLnhgJzhgKxf4YCh4YCE4YC64YC54YCC4YCrX+GAl+GAr+GAkuGAueGAk+GAn+GAsOGAuF/hgIDhgLzhgKzhgJ7hgJXhgJDhgLHhgLhf4YCe4YCx4YCs4YCA4YC84YCsX+GAheGAlOGAsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydDogJ+GAlOGAveGAsV/hgJzhgKxf4YCC4YCrX+GAn+GAsOGAuF/hgIDhgLzhgKxf4YCe4YCx4YCsX+GAlOGAsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfhgJThgL3hgLFf4YCc4YCsX+GAguGAq1/hgJ/hgLDhgLhf4YCA4YC84YCsX+GAnuGAseGArF/hgJThgLEnLnNwbGl0KCdfJyksXG5cbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb4YCa4YCU4YCxLl0gTFQgW+GAmeGAvuGArF0nLFxuICAgICAgICAgICAgbmV4dERheTogJ1vhgJnhgJThgIDhgLrhgJbhgLzhgJThgLpdIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBMVCBb4YCZ4YC+4YCsXScsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW+GAmeGAlOGAsS7hgIBdIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiAnW+GAleGAvOGAruGAuOGAgeGAsuGAt+GAnuGAseGArF0gZGRkZCBMVCBb4YCZ4YC+4YCsXScsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICAgICAgZnV0dXJlOiAn4YCc4YCs4YCZ4YCK4YC64YC3ICVzIOGAmeGAvuGArCcsXG4gICAgICAgICAgICBwYXN0OiAn4YCc4YC94YCU4YC64YCB4YCy4YC34YCe4YCx4YCsICVzIOGAgCcsXG4gICAgICAgICAgICBzOiAn4YCF4YCA4YC54YCA4YCU4YC6LuGAoeGAlOGAiuGAuuGAuOGAhOGAmuGAuicsXG4gICAgICAgICAgICBzcyA6ICclZCDhgIXhgIDhgLnhgIDhgJThgLfhgLonLFxuICAgICAgICAgICAgbTogJ+GAkOGAheGAuuGAmeGAreGAlOGAheGAuicsXG4gICAgICAgICAgICBtbTogJyVkIOGAmeGAreGAlOGAheGAuicsXG4gICAgICAgICAgICBoOiAn4YCQ4YCF4YC64YCU4YCs4YCb4YCuJyxcbiAgICAgICAgICAgIGhoOiAnJWQg4YCU4YCs4YCb4YCuJyxcbiAgICAgICAgICAgIGQ6ICfhgJDhgIXhgLrhgJvhgIDhgLonLFxuICAgICAgICAgICAgZGQ6ICclZCDhgJvhgIDhgLonLFxuICAgICAgICAgICAgTTogJ+GAkOGAheGAuuGAnCcsXG4gICAgICAgICAgICBNTTogJyVkIOGAnCcsXG4gICAgICAgICAgICB5OiAn4YCQ4YCF4YC64YCU4YC+4YCF4YC6JyxcbiAgICAgICAgICAgIHl5OiAnJWQg4YCU4YC+4YCF4YC6J1xuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4YGB4YGC4YGD4YGE4YGF4YGG4YGH4YGI4YGJ4YGAXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwJGJbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXAkY1ttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgd2Vlazoge1xuICAgICAgICAgICAgZG93OiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveTogNCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbmInLCB7XG4gICAgICAgIG1vbnRocyA6ICdqYW51YXJfZmVicnVhcl9tYXJzX2FwcmlsX21haV9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdqYW4uX2ZlYi5fbWFyc19hcHJpbF9tYWlfanVuaV9qdWxpX2F1Zy5fc2VwLl9va3QuX25vdi5fZGVzLicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogJ3PDuG5kYWdfbWFuZGFnX3RpcnNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2zDuHJkYWcnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnc8O4Ll9tYS5fdGkuX29uLl90by5fZnIuX2zDuC4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ3PDuF9tYV90aV9vbl90b19mcl9sw7gnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBba2wuXSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgRC4gTU1NTSBZWVlZIFtrbC5dIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbaSBkYWcga2wuXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW2kgbW9yZ2VuIGtsLl0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtrbC5dIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbaSBnw6VyIGtsLl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbZm9ycmlnZV0gZGRkZCBba2wuXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdvbSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJyVzIHNpZGVuJyxcbiAgICAgICAgICAgIHMgOiAnbm9lbiBzZWt1bmRlcicsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWt1bmRlcicsXG4gICAgICAgICAgICBtIDogJ2V0dCBtaW51dHQnLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXR0ZXInLFxuICAgICAgICAgICAgaCA6ICdlbiB0aW1lJyxcbiAgICAgICAgICAgIGhoIDogJyVkIHRpbWVyJyxcbiAgICAgICAgICAgIGQgOiAnZW4gZGFnJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGRhZ2VyJyxcbiAgICAgICAgICAgIE0gOiAnZW4gbcOlbmVkJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG3DpW5lZGVyJyxcbiAgICAgICAgICAgIHkgOiAnZXR0IMOlcicsXG4gICAgICAgICAgICB5eSA6ICclZCDDpXInXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJGQgPSB7XG4gICAgICAgICcxJzogJ+ClpycsXG4gICAgICAgICcyJzogJ+ClqCcsXG4gICAgICAgICczJzogJ+ClqScsXG4gICAgICAgICc0JzogJ+ClqicsXG4gICAgICAgICc1JzogJ+ClqycsXG4gICAgICAgICc2JzogJ+ClrCcsXG4gICAgICAgICc3JzogJ+ClrScsXG4gICAgICAgICc4JzogJ+ClricsXG4gICAgICAgICc5JzogJ+ClrycsXG4gICAgICAgICcwJzogJ+ClpidcbiAgICB9LFxuICAgIG51bWJlck1hcCRjID0ge1xuICAgICAgICAn4KWnJzogJzEnLFxuICAgICAgICAn4KWoJzogJzInLFxuICAgICAgICAn4KWpJzogJzMnLFxuICAgICAgICAn4KWqJzogJzQnLFxuICAgICAgICAn4KWrJzogJzUnLFxuICAgICAgICAn4KWsJzogJzYnLFxuICAgICAgICAn4KWtJzogJzcnLFxuICAgICAgICAn4KWuJzogJzgnLFxuICAgICAgICAn4KWvJzogJzknLFxuICAgICAgICAn4KWmJzogJzAnXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbmUnLCB7XG4gICAgICAgIG1vbnRocyA6ICfgpJzgpKjgpLXgpLDgpYBf4KSr4KWH4KSs4KWN4KSw4KWB4KS14KSw4KWAX+CkruCkvuCksOCljeCkml/gpIXgpKrgpY3gpLDgpL/gpLJf4KSu4KSIX+CknOClgeCkqF/gpJzgpYHgpLLgpL7gpIhf4KSF4KSX4KS34KWN4KSfX+CkuOClh+CkquCljeCkn+Clh+CkruCljeCkrOCksF/gpIXgpJXgpY3gpJ/gpYvgpKzgpLBf4KSo4KWL4KSt4KWH4KSu4KWN4KSs4KSwX+CkoeCkv+CkuOClh+CkruCljeCkrOCksCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn4KSc4KSoLl/gpKvgpYfgpKzgpY3gpLDgpYEuX+CkruCkvuCksOCljeCkml/gpIXgpKrgpY3gpLDgpL8uX+CkruCkiF/gpJzgpYHgpKhf4KSc4KWB4KSy4KS+4KSILl/gpIXgpJcuX+CkuOClh+CkquCljeCkny5f4KSF4KSV4KWN4KSf4KWLLl/gpKjgpYvgpK3gpYcuX+CkoeCkv+CkuOClhy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICfgpIbgpIfgpKTgpKzgpL7gpLBf4KS44KWL4KSu4KSs4KS+4KSwX+CkruCkmeCljeCkl+CksuCkrOCkvuCksF/gpKzgpYHgpKfgpKzgpL7gpLBf4KSs4KS/4KS54KS/4KSs4KS+4KSwX+CktuClgeCkleCljeCksOCkrOCkvuCksF/gpLbgpKjgpL/gpKzgpL7gpLAnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn4KSG4KSH4KSkLl/gpLjgpYvgpK4uX+CkruCkmeCljeCkl+Cksi5f4KSs4KWB4KSnLl/gpKzgpL/gpLngpL8uX+CktuClgeCkleCljeCksC5f4KS24KSo4KS/Licuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn4KSGLl/gpLjgpYsuX+CkruCkgi5f4KSs4KWBLl/gpKzgpL8uX+CktuClgS5f4KS2Licuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdB4KSV4KWLIGg6bW0g4KSs4KSc4KWHJyxcbiAgICAgICAgICAgIExUUyA6ICdB4KSV4KWLIGg6bW06c3Mg4KSs4KSc4KWHJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEHgpJXgpYsgaDptbSDgpKzgpJzgpYcnLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQeCkleCliyBoOm1tIOCkrOCknOClhydcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Clp+ClqOClqeClquClq+ClrOClreClruClr+Clpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCRjW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJGRbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gpLDgpL7gpKTgpL984KSs4KS/4KS54KS+4KSofOCkpuCkv+CkieCkgeCkuOCli3zgpLjgpL7gpIHgpJ0vLFxuICAgICAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4KSw4KS+4KSk4KS/Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KSs4KS/4KS54KS+4KSoJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkpuCkv+CkieCkgeCkuOCliycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4KS44KS+4KSB4KSdJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCAzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpLDgpL7gpKTgpL8nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CkrOCkv+CkueCkvuCkqCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4KSm4KS/4KSJ4KSB4KS44KWLJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgpLjgpL7gpIHgpJ0nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CksOCkvuCkpOCkvyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb4KSG4KScXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vgpK3gpYvgpLLgpL9dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ1vgpIbgpIngpIHgpKbgpYtdIGRkZGRbLF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb4KS54KS/4KSc4KWLXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdb4KSX4KSP4KSV4KWLXSBkZGRkWyxdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclc+CkruCkvicsXG4gICAgICAgICAgICBwYXN0IDogJyVzIOCkheCkl+CkvuCkoeCkvycsXG4gICAgICAgICAgICBzIDogJ+CkleClh+CkueClgCDgpJXgpY3gpLfgpKMnLFxuICAgICAgICAgICAgc3MgOiAnJWQg4KS44KWH4KSV4KWH4KSj4KWN4KShJyxcbiAgICAgICAgICAgIG0gOiAn4KSP4KSVIOCkruCkv+CkqOClh+CknycsXG4gICAgICAgICAgICBtbSA6ICclZCDgpK7gpL/gpKjgpYfgpJ8nLFxuICAgICAgICAgICAgaCA6ICfgpI/gpJUg4KSY4KSj4KWN4KSf4KS+JyxcbiAgICAgICAgICAgIGhoIDogJyVkIOCkmOCko+CljeCkn+CkvicsXG4gICAgICAgICAgICBkIDogJ+Ckj+CklSDgpKbgpL/gpKgnLFxuICAgICAgICAgICAgZGQgOiAnJWQg4KSm4KS/4KSoJyxcbiAgICAgICAgICAgIE0gOiAn4KSP4KSVIOCkruCkueCkv+CkqOCkvicsXG4gICAgICAgICAgICBNTSA6ICclZCDgpK7gpLngpL/gpKjgpL4nLFxuICAgICAgICAgICAgeSA6ICfgpI/gpJUg4KSs4KSw4KWN4KS3JyxcbiAgICAgICAgICAgIHl5IDogJyVkIOCkrOCksOCljeCktydcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzU2hvcnRXaXRoRG90cyQxID0gJ2phbi5fZmViLl9tcnQuX2Fwci5fbWVpX2p1bi5fanVsLl9hdWcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0V2l0aG91dERvdHMkMSA9ICdqYW5fZmViX21ydF9hcHJfbWVpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2RlYycuc3BsaXQoJ18nKTtcblxuICAgIHZhciBtb250aHNQYXJzZSQ0ID0gWy9eamFuL2ksIC9eZmViL2ksIC9ebWFhcnR8bXJ0Lj8kL2ksIC9eYXByL2ksIC9ebWVpJC9pLCAvXmp1bltpLl0/JC9pLCAvXmp1bFtpLl0/JC9pLCAvXmF1Zy9pLCAvXnNlcC9pLCAvXm9rdC9pLCAvXm5vdi9pLCAvXmRlYy9pXTtcbiAgICB2YXIgbW9udGhzUmVnZXgkNSA9IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXJ8amFuXFwuP3xmZWJcXC4/fG1ydFxcLj98YXByXFwuP3xqdVtubF1cXC4/fGF1Z1xcLj98c2VwXFwuP3xva3RcXC4/fG5vdlxcLj98ZGVjXFwuPykvaTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbmwtYmUnLCB7XG4gICAgICAgIG1vbnRocyA6ICdqYW51YXJpX2ZlYnJ1YXJpX21hYXJ0X2FwcmlsX21laV9qdW5pX2p1bGlfYXVndXN0dXNfc2VwdGVtYmVyX29rdG9iZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHMkMTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRob3V0RG90cyQxW20ubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzJDFbbS5tb250aCgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBtb250aHNSZWdleDogbW9udGhzUmVnZXgkNSxcbiAgICAgICAgbW9udGhzU2hvcnRSZWdleDogbW9udGhzUmVnZXgkNSxcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXIpL2ksXG4gICAgICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKGphblxcLj98ZmViXFwuP3xtcnRcXC4/fGFwclxcLj98bWVpfGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pLFxuXG4gICAgICAgIG1vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UkNCxcbiAgICAgICAgbG9uZ01vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UkNCxcbiAgICAgICAgc2hvcnRNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDQsXG5cbiAgICAgICAgd2Vla2RheXMgOiAnem9uZGFnX21hYW5kYWdfZGluc2RhZ193b2Vuc2RhZ19kb25kZXJkYWdfdnJpamRhZ196YXRlcmRhZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICd6by5fbWEuX2RpLl93by5fZG8uX3ZyLl96YS4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ3pvX21hX2RpX3dvX2RvX3ZyX3phJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW3ZhbmRhYWcgb21dIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbbW9yZ2VuIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW29tXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW2dpc3RlcmVuIG9tXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1thZmdlbG9wZW5dIGRkZGQgW29tXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdvdmVyICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgZ2VsZWRlbicsXG4gICAgICAgICAgICBzIDogJ2VlbiBwYWFyIHNlY29uZGVuJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNlY29uZGVuJyxcbiAgICAgICAgICAgIG0gOiAnw6nDqW4gbWludXV0JyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0ZW4nLFxuICAgICAgICAgICAgaCA6ICfDqcOpbiB1dXInLFxuICAgICAgICAgICAgaGggOiAnJWQgdXVyJyxcbiAgICAgICAgICAgIGQgOiAnw6nDqW4gZGFnJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGRhZ2VuJyxcbiAgICAgICAgICAgIE0gOiAnw6nDqW4gbWFhbmQnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbWFhbmRlbicsXG4gICAgICAgICAgICB5IDogJ8Opw6luIGphYXInLFxuICAgICAgICAgICAgeXkgOiAnJWQgamFhcidcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICgobnVtYmVyID09PSAxIHx8IG51bWJlciA9PT0gOCB8fCBudW1iZXIgPj0gMjApID8gJ3N0ZScgOiAnZGUnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzU2hvcnRXaXRoRG90cyQyID0gJ2phbi5fZmViLl9tcnQuX2Fwci5fbWVpX2p1bi5fanVsLl9hdWcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0V2l0aG91dERvdHMkMiA9ICdqYW5fZmViX21ydF9hcHJfbWVpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2RlYycuc3BsaXQoJ18nKTtcblxuICAgIHZhciBtb250aHNQYXJzZSQ1ID0gWy9eamFuL2ksIC9eZmViL2ksIC9ebWFhcnR8bXJ0Lj8kL2ksIC9eYXByL2ksIC9ebWVpJC9pLCAvXmp1bltpLl0/JC9pLCAvXmp1bFtpLl0/JC9pLCAvXmF1Zy9pLCAvXnNlcC9pLCAvXm9rdC9pLCAvXm5vdi9pLCAvXmRlYy9pXTtcbiAgICB2YXIgbW9udGhzUmVnZXgkNiA9IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXJ8amFuXFwuP3xmZWJcXC4/fG1ydFxcLj98YXByXFwuP3xqdVtubF1cXC4/fGF1Z1xcLj98c2VwXFwuP3xva3RcXC4/fG5vdlxcLj98ZGVjXFwuPykvaTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnbmwnLCB7XG4gICAgICAgIG1vbnRocyA6ICdqYW51YXJpX2ZlYnJ1YXJpX21hYXJ0X2FwcmlsX21laV9qdW5pX2p1bGlfYXVndXN0dXNfc2VwdGVtYmVyX29rdG9iZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHMkMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRob3V0RG90cyQyW20ubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzJDJbbS5tb250aCgpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBtb250aHNSZWdleDogbW9udGhzUmVnZXgkNixcbiAgICAgICAgbW9udGhzU2hvcnRSZWdleDogbW9udGhzUmVnZXgkNixcbiAgICAgICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXIpL2ksXG4gICAgICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKGphblxcLj98ZmViXFwuP3xtcnRcXC4/fGFwclxcLj98bWVpfGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pLFxuXG4gICAgICAgIG1vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UkNSxcbiAgICAgICAgbG9uZ01vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UkNSxcbiAgICAgICAgc2hvcnRNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlJDUsXG5cbiAgICAgICAgd2Vla2RheXMgOiAnem9uZGFnX21hYW5kYWdfZGluc2RhZ193b2Vuc2RhZ19kb25kZXJkYWdfdnJpamRhZ196YXRlcmRhZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICd6by5fbWEuX2RpLl93by5fZG8uX3ZyLl96YS4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ3pvX21hX2RpX3dvX2RvX3ZyX3phJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELU1NLVlZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW3ZhbmRhYWcgb21dIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbbW9yZ2VuIG9tXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ2RkZGQgW29tXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW2dpc3RlcmVuIG9tXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1thZmdlbG9wZW5dIGRkZGQgW29tXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdvdmVyICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgZ2VsZWRlbicsXG4gICAgICAgICAgICBzIDogJ2VlbiBwYWFyIHNlY29uZGVuJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNlY29uZGVuJyxcbiAgICAgICAgICAgIG0gOiAnw6nDqW4gbWludXV0JyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0ZW4nLFxuICAgICAgICAgICAgaCA6ICfDqcOpbiB1dXInLFxuICAgICAgICAgICAgaGggOiAnJWQgdXVyJyxcbiAgICAgICAgICAgIGQgOiAnw6nDqW4gZGFnJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGRhZ2VuJyxcbiAgICAgICAgICAgIE0gOiAnw6nDqW4gbWFhbmQnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbWFhbmRlbicsXG4gICAgICAgICAgICB5IDogJ8Opw6luIGphYXInLFxuICAgICAgICAgICAgeXkgOiAnJWQgamFhcidcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICgobnVtYmVyID09PSAxIHx8IG51bWJlciA9PT0gOCB8fCBudW1iZXIgPj0gMjApID8gJ3N0ZScgOiAnZGUnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ25uJywge1xuICAgICAgICBtb250aHMgOiAnamFudWFyX2ZlYnJ1YXJfbWFyc19hcHJpbF9tYWlfanVuaV9qdWxpX2F1Z3VzdF9zZXB0ZW1iZXJfb2t0b2Jlcl9ub3ZlbWJlcl9kZXNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnamFuX2ZlYl9tYXJfYXByX21haV9qdW5fanVsX2F1Z19zZXBfb2t0X25vdl9kZXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ3N1bmRhZ19tw6VuZGFnX3R5c2RhZ19vbnNkYWdfdG9yc2RhZ19mcmVkYWdfbGF1cmRhZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdzdW5fbcOlbl90eXNfb25zX3Rvcl9mcmVfbGF1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdzdV9tw6VfdHlfb25fdG9fZnJfbMO4Jy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgW2tsLl0gSDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQgRC4gTU1NTSBZWVlZIFtrbC5dIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSSBkYWcga2xva2thXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0kgbW9yZ29uIGtsb2trYV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtrbG9ra2FdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbSSBnw6VyIGtsb2trYV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbRsO4cmVnw6VhbmRlXSBkZGRkIFtrbG9ra2FdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ29tICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgc2lkYW4nLFxuICAgICAgICAgICAgcyA6ICdub2tyZSBzZWt1bmQnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2VrdW5kJyxcbiAgICAgICAgICAgIG0gOiAnZWl0IG1pbnV0dCcsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dHQnLFxuICAgICAgICAgICAgaCA6ICdlaW4gdGltZScsXG4gICAgICAgICAgICBoaCA6ICclZCB0aW1hcicsXG4gICAgICAgICAgICBkIDogJ2VpbiBkYWcnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGFnYXInLFxuICAgICAgICAgICAgTSA6ICdlaW4gbcOlbmFkJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG3DpW5hZGVyJyxcbiAgICAgICAgICAgIHkgOiAnZWl0IMOlcicsXG4gICAgICAgICAgICB5eSA6ICclZCDDpXInXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgc3ltYm9sTWFwJGUgPSB7XG4gICAgICAgICcxJzogJ+CppycsXG4gICAgICAgICcyJzogJ+CpqCcsXG4gICAgICAgICczJzogJ+CpqScsXG4gICAgICAgICc0JzogJ+CpqicsXG4gICAgICAgICc1JzogJ+CpqycsXG4gICAgICAgICc2JzogJ+CprCcsXG4gICAgICAgICc3JzogJ+CprScsXG4gICAgICAgICc4JzogJ+CpricsXG4gICAgICAgICc5JzogJ+CprycsXG4gICAgICAgICcwJzogJ+CppidcbiAgICB9LFxuICAgIG51bWJlck1hcCRkID0ge1xuICAgICAgICAn4KmnJzogJzEnLFxuICAgICAgICAn4KmoJzogJzInLFxuICAgICAgICAn4KmpJzogJzMnLFxuICAgICAgICAn4KmqJzogJzQnLFxuICAgICAgICAn4KmrJzogJzUnLFxuICAgICAgICAn4KmsJzogJzYnLFxuICAgICAgICAn4KmtJzogJzcnLFxuICAgICAgICAn4KmuJzogJzgnLFxuICAgICAgICAn4KmvJzogJzknLFxuICAgICAgICAn4KmmJzogJzAnXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgncGEtaW4nLCB7XG4gICAgICAgIC8vIFRoZXJlIGFyZSBtb250aHMgbmFtZSBhcyBwZXIgTmFuYWtzaGFoaSBDYWxlbmRhciBidXQgdGhleSBhcmUgbm90IHVzZWQgYXMgcmlnaWRseSBpbiBtb2Rlcm4gUHVuamFiaS5cbiAgICAgICAgbW9udGhzIDogJ+ConOCoqOCoteCosOCpgF/gqKvgqLzgqLDgqLXgqLDgqYBf4Kiu4Ki+4Kiw4KiaX+CoheCoquCpjeCosOCpiOCosl/gqK7gqIhf4Kic4KmC4KioX+ConOCpgeCosuCovuCoiF/gqIXgqJfgqLjgqKRf4Ki44Kik4Kmw4Kis4KiwX+CoheColeCopOCpguCorOCosF/gqKjgqLXgqbDgqKzgqLBf4Kim4Ki44Kmw4Kis4KiwJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICfgqJzgqKjgqLXgqLDgqYBf4Kir4Ki84Kiw4Ki14Kiw4KmAX+CoruCovuCosOComl/gqIXgqKrgqY3gqLDgqYjgqLJf4Kiu4KiIX+ConOCpguCoqF/gqJzgqYHgqLLgqL7gqIhf4KiF4KiX4Ki44KikX+CouOCopOCpsOCorOCosF/gqIXgqJXgqKTgqYLgqKzgqLBf4Kio4Ki14Kmw4Kis4KiwX+CopuCouOCpsOCorOCosCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAn4KiQ4Kik4Ki14Ki+4KiwX+CouOCpi+CoruCoteCovuCosF/gqK7gqbDgqJfgqLLgqLXgqL7gqLBf4Kis4KmB4Kin4Ki14Ki+4KiwX+CoteCpgOCosOCoteCovuCosF/gqLjgqLzgqYHgqbHgqJXgqLDgqLXgqL7gqLBf4Ki44Ki84Kio4KmA4Kia4Kiw4Ki14Ki+4KiwJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ+CokOCopF/gqLjgqYvgqK5f4Kiu4Kmw4KiX4KiyX+CorOCpgeCop1/gqLXgqYDgqLBf4Ki44Ki84KmB4KiV4KiwX+CouOCovOCoqOCpgCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn4KiQ4KikX+CouOCpi+Corl/gqK7gqbDgqJfgqLJf4Kis4KmB4KinX+CoteCpgOCosF/gqLjgqLzgqYHgqJXgqLBf4Ki44Ki84Kio4KmAJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0EgaDptbSDgqLXgqJzgqYcnLFxuICAgICAgICAgICAgTFRTIDogJ0EgaDptbTpzcyDgqLXgqJzgqYcnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCoteConOCphycsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0g4Ki14Kic4KmHJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW+CoheConF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb4KiV4KiyXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdb4KiF4KiX4Kiy4Ki+XSBkZGRkLCBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1vgqJXgqLJdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1vgqKrgqL/gqJvgqLLgqYddIGRkZGQsIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyDgqLXgqL/gqbHgqJonLFxuICAgICAgICAgICAgcGFzdCA6ICclcyDgqKrgqL/gqJvgqLLgqYcnLFxuICAgICAgICAgICAgcyA6ICfgqJXgqYHgqJ0g4Ki44KiV4Ki/4Kmw4KifJyxcbiAgICAgICAgICAgIHNzIDogJyVkIOCouOColeCov+CpsOConycsXG4gICAgICAgICAgICBtIDogJ+Coh+ColSDgqK7gqL/gqbDgqJ8nLFxuICAgICAgICAgICAgbW0gOiAnJWQg4Kiu4Ki/4Kmw4KifJyxcbiAgICAgICAgICAgIGggOiAn4KiH4Kmx4KiVIOComOCpsOCon+CovicsXG4gICAgICAgICAgICBoaCA6ICclZCDgqJjgqbDgqJ/gqYcnLFxuICAgICAgICAgICAgZCA6ICfgqIfgqbHgqJUg4Kim4Ki/4KioJyxcbiAgICAgICAgICAgIGRkIDogJyVkIOCopuCov+CoqCcsXG4gICAgICAgICAgICBNIDogJ+Coh+CpseColSDgqK7gqLngqYDgqKjgqL4nLFxuICAgICAgICAgICAgTU0gOiAnJWQg4Kiu4Ki54KmA4Kio4KmHJyxcbiAgICAgICAgICAgIHkgOiAn4KiH4Kmx4KiVIOCouOCovuCosicsXG4gICAgICAgICAgICB5eSA6ICclZCDgqLjgqL7gqLInXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgqafgqajgqangqargqavgqazgqa3gqa7gqa/gqaZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXAkZFttYXRjaF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcCRlW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICAvLyBQdW5qYWJpIG5vdGF0aW9uIGZvciBtZXJpZGllbXMgYXJlIHF1aXRlIGZ1enp5IGluIHByYWN0aWNlLiBXaGlsZSB0aGVyZSBleGlzdHNcbiAgICAgICAgLy8gYSByaWdpZCBub3Rpb24gb2YgYSAnUGFoYXInIGl0IGlzIG5vdCB1c2VkIGFzIHJpZ2lkbHkgaW4gbW9kZXJuIFB1bmphYmkuXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gqLDgqL7gqKR84Ki44Ki14KmH4KiwfOCopuCpgeCoquCoueCov+CosHzgqLjgqLzgqL7gqK4vLFxuICAgICAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4Kiw4Ki+4KikJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Ki44Ki14KmH4KiwJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CopuCpgeCoquCoueCov+CosCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Ki44Ki84Ki+4KiuJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgqLDgqL7gqKQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CouOCoteCph+CosCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4Kim4KmB4Kiq4Ki54Ki/4KiwJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgqLjgqLzgqL7gqK4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CosOCovuCopCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRoc05vbWluYXRpdmUgPSAnc3R5Y3plxYRfbHV0eV9tYXJ6ZWNfa3dpZWNpZcWEX21hal9jemVyd2llY19saXBpZWNfc2llcnBpZcWEX3dyemVzaWXFhF9wYcW6ZHppZXJuaWtfbGlzdG9wYWRfZ3J1ZHppZcWEJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTdWJqZWN0aXZlID0gJ3N0eWN6bmlhX2x1dGVnb19tYXJjYV9rd2lldG5pYV9tYWphX2N6ZXJ3Y2FfbGlwY2Ffc2llcnBuaWFfd3J6ZcWbbmlhX3Bhxbpkemllcm5pa2FfbGlzdG9wYWRhX2dydWRuaWEnLnNwbGl0KCdfJyk7XG4gICAgZnVuY3Rpb24gcGx1cmFsJDMobikge1xuICAgICAgICByZXR1cm4gKG4gJSAxMCA8IDUpICYmIChuICUgMTAgPiAxKSAmJiAoKH5+KG4gLyAxMCkgJSAxMCkgIT09IDEpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkOChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDMobnVtYmVyKSA/ICdzZWt1bmR5JyA6ICdzZWt1bmQnKTtcbiAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ21pbnV0YScgOiAnbWludXTEmSc7XG4gICAgICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkMyhudW1iZXIpID8gJ21pbnV0eScgOiAnbWludXQnKTtcbiAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ICA/ICdnb2R6aW5hJyAgOiAnZ29kemluxJknO1xuICAgICAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsJDMobnVtYmVyKSA/ICdnb2R6aW55JyA6ICdnb2R6aW4nKTtcbiAgICAgICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQzKG51bWJlcikgPyAnbWllc2nEhWNlJyA6ICdtaWVzacSZY3knKTtcbiAgICAgICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQzKG51bWJlcikgPyAnbGF0YScgOiAnbGF0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3BsJywge1xuICAgICAgICBtb250aHMgOiBmdW5jdGlvbiAobW9tZW50VG9Gb3JtYXQsIGZvcm1hdCkge1xuICAgICAgICAgICAgaWYgKCFtb21lbnRUb0Zvcm1hdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNOb21pbmF0aXZlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgLy8gSGFjazogaWYgZm9ybWF0IGVtcHR5IHdlIGtub3cgdGhpcyBpcyB1c2VkIHRvIGdlbmVyYXRlXG4gICAgICAgICAgICAgICAgLy8gUmVnRXhwIGJ5IG1vbWVudC4gR2l2ZSB0aGVuIGJhY2sgYm90aCB2YWxpZCBmb3JtcyBvZiBtb250aHNcbiAgICAgICAgICAgICAgICAvLyBpbiBSZWdFeHAgcmVhZHkgZm9ybWF0LlxuICAgICAgICAgICAgICAgIHJldHVybiAnKCcgKyBtb250aHNTdWJqZWN0aXZlW21vbWVudFRvRm9ybWF0Lm1vbnRoKCldICsgJ3wnICsgbW9udGhzTm9taW5hdGl2ZVttb21lbnRUb0Zvcm1hdC5tb250aCgpXSArICcpJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoL0QgTU1NTS8udGVzdChmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1N1YmplY3RpdmVbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aHNOb21pbmF0aXZlW21vbWVudFRvRm9ybWF0Lm1vbnRoKCldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydCA6ICdzdHlfbHV0X21hcl9rd2lfbWFqX2N6ZV9saXBfc2llX3dyel9wYcW6X2xpc19ncnUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ25pZWR6aWVsYV9wb25pZWR6aWHFgmVrX3d0b3Jla1/Fm3JvZGFfY3p3YXJ0ZWtfcGnEhXRla19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnbmR6X3Bvbl93dF/Fm3JfY3p3X3B0X3NvYicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnTmRfUG5fV3RfxZpyX0N6X1B0X1NvJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tEemnFmyBvXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0p1dHJvIG9dIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1cgbmllZHppZWzEmSBvXSBMVCc7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbV2Ugd3RvcmVrIG9dIExUJztcblxuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIMWbcm9kxJkgb10gTFQnO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1cgc29ib3TEmSBvXSBMVCc7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1ddIGRkZGQgW29dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogJ1tXY3pvcmFqIG9dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1cgemVzesWCxIUgbmllZHppZWzEmSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1cgemVzesWCxIUgxZtyb2TEmSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1cgemVzesWCxIUgc29ib3TEmSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIHplc3rFgnldIGRkZGQgW29dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnemEgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyB0ZW11JyxcbiAgICAgICAgICAgIHMgOiAna2lsa2Egc2VrdW5kJyxcbiAgICAgICAgICAgIHNzIDogdHJhbnNsYXRlJDgsXG4gICAgICAgICAgICBtIDogdHJhbnNsYXRlJDgsXG4gICAgICAgICAgICBtbSA6IHRyYW5zbGF0ZSQ4LFxuICAgICAgICAgICAgaCA6IHRyYW5zbGF0ZSQ4LFxuICAgICAgICAgICAgaGggOiB0cmFuc2xhdGUkOCxcbiAgICAgICAgICAgIGQgOiAnMSBkemllxYQnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZG5pJyxcbiAgICAgICAgICAgIE0gOiAnbWllc2nEhWMnLFxuICAgICAgICAgICAgTU0gOiB0cmFuc2xhdGUkOCxcbiAgICAgICAgICAgIHkgOiAncm9rJyxcbiAgICAgICAgICAgIHl5IDogdHJhbnNsYXRlJDhcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbCA6ICclZC4nLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgncHQtYnInLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW5laXJvX0ZldmVyZWlyb19NYXLDp29fQWJyaWxfTWFpb19KdW5ob19KdWxob19BZ29zdG9fU2V0ZW1icm9fT3V0dWJyb19Ob3ZlbWJyb19EZXplbWJybycuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnSmFuX0Zldl9NYXJfQWJyX01haV9KdW5fSnVsX0Fnb19TZXRfT3V0X05vdl9EZXonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ0RvbWluZ29fU2VndW5kYS1mZWlyYV9UZXLDp2EtZmVpcmFfUXVhcnRhLWZlaXJhX1F1aW50YS1mZWlyYV9TZXh0YS1mZWlyYV9Tw6FiYWRvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ0RvbV9TZWdfVGVyX1F1YV9RdWlfU2V4X1PDoWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ0RvXzLCql8zwqpfNMKqXzXCql82wqpfU8OhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgW8Ogc10gSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIFtkZV0gTU1NTSBbZGVdIFlZWVkgW8Ogc10gSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tIb2plIMOgc10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tBbWFuaMOjIMOgc10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvDoHNdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbT250ZW0gw6BzXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAodGhpcy5kYXkoKSA9PT0gMCB8fCB0aGlzLmRheSgpID09PSA2KSA/XG4gICAgICAgICAgICAgICAgICAgICdbw5psdGltb10gZGRkZCBbw6BzXSBMVCcgOiAvLyBTYXR1cmRheSArIFN1bmRheVxuICAgICAgICAgICAgICAgICAgICAnW8OabHRpbWFdIGRkZGQgW8Ogc10gTFQnOyAvLyBNb25kYXkgLSBGcmlkYXlcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdlbSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ2jDoSAlcycsXG4gICAgICAgICAgICBzIDogJ3BvdWNvcyBzZWd1bmRvcycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgICAgICBtIDogJ3VtIG1pbnV0bycsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dG9zJyxcbiAgICAgICAgICAgIGggOiAndW1hIGhvcmEnLFxuICAgICAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICAgICAgZCA6ICd1bSBkaWEnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGlhcycsXG4gICAgICAgICAgICBNIDogJ3VtIG3DqnMnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbWVzZXMnLFxuICAgICAgICAgICAgeSA6ICd1bSBhbm8nLFxuICAgICAgICAgICAgeXkgOiAnJWQgYW5vcydcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9wrovLFxuICAgICAgICBvcmRpbmFsIDogJyVkwronXG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3B0Jywge1xuICAgICAgICBtb250aHMgOiAnSmFuZWlyb19GZXZlcmVpcm9fTWFyw6dvX0FicmlsX01haW9fSnVuaG9fSnVsaG9fQWdvc3RvX1NldGVtYnJvX091dHVicm9fTm92ZW1icm9fRGV6ZW1icm8nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZXZfTWFyX0Ficl9NYWlfSnVuX0p1bF9BZ29fU2V0X091dF9Ob3ZfRGV6Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdEb21pbmdvX1NlZ3VuZGEtZmVpcmFfVGVyw6dhLWZlaXJhX1F1YXJ0YS1mZWlyYV9RdWludGEtZmVpcmFfU2V4dGEtZmVpcmFfU8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdEb21fU2VnX1Rlcl9RdWFfUXVpX1NleF9Tw6FiJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdEb18ywqpfM8KqXzTCql81wqpfNsKqX1PDoScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSG9qZSDDoHNdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdbQW1hbmjDoyDDoHNdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbw6BzXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW09udGVtIMOgc10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHRoaXMuZGF5KCkgPT09IDAgfHwgdGhpcy5kYXkoKSA9PT0gNikgP1xuICAgICAgICAgICAgICAgICAgICAnW8OabHRpbW9dIGRkZGQgW8Ogc10gTFQnIDogLy8gU2F0dXJkYXkgKyBTdW5kYXlcbiAgICAgICAgICAgICAgICAgICAgJ1vDmmx0aW1hXSBkZGRkIFvDoHNdIExUJzsgLy8gTW9uZGF5IC0gRnJpZGF5XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnZW0gJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICdow6EgJXMnLFxuICAgICAgICAgICAgcyA6ICdzZWd1bmRvcycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgICAgICBtIDogJ3VtIG1pbnV0bycsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51dG9zJyxcbiAgICAgICAgICAgIGggOiAndW1hIGhvcmEnLFxuICAgICAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICAgICAgZCA6ICd1bSBkaWEnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGlhcycsXG4gICAgICAgICAgICBNIDogJ3VtIG3DqnMnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbWVzZXMnLFxuICAgICAgICAgICAgeSA6ICd1bSBhbm8nLFxuICAgICAgICAgICAgeXkgOiAnJWQgYW5vcydcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9wrovLFxuICAgICAgICBvcmRpbmFsIDogJyVkwronLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGZ1bmN0aW9uIHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgICAgICdzcyc6ICdzZWN1bmRlJyxcbiAgICAgICAgICAgICAgICAnbW0nOiAnbWludXRlJyxcbiAgICAgICAgICAgICAgICAnaGgnOiAnb3JlJyxcbiAgICAgICAgICAgICAgICAnZGQnOiAnemlsZScsXG4gICAgICAgICAgICAgICAgJ01NJzogJ2x1bmknLFxuICAgICAgICAgICAgICAgICd5eSc6ICdhbmknXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2VwYXJhdG9yID0gJyAnO1xuICAgICAgICBpZiAobnVtYmVyICUgMTAwID49IDIwIHx8IChudW1iZXIgPj0gMTAwICYmIG51bWJlciAlIDEwMCA9PT0gMCkpIHtcbiAgICAgICAgICAgIHNlcGFyYXRvciA9ICcgZGUgJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVtYmVyICsgc2VwYXJhdG9yICsgZm9ybWF0W2tleV07XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdybycsIHtcbiAgICAgICAgbW9udGhzIDogJ2lhbnVhcmllX2ZlYnJ1YXJpZV9tYXJ0aWVfYXByaWxpZV9tYWlfaXVuaWVfaXVsaWVfYXVndXN0X3NlcHRlbWJyaWVfb2N0b21icmllX25vaWVtYnJpZV9kZWNlbWJyaWUnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ2lhbi5fZmVici5fbWFydC5fYXByLl9tYWlfaXVuLl9pdWwuX2F1Zy5fc2VwdC5fb2N0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzIDogJ2R1bWluaWPEg19sdW5pX21hcsibaV9taWVyY3VyaV9qb2lfdmluZXJpX3PDom1ixIN0xIMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnRHVtX0x1bl9NYXJfTWllX0pvaV9WaW5fU8OibScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnRHVfTHVfTWFfTWlfSm9fVmlfU8OiJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2F6aSBsYV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1ttw6JpbmUgbGFdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbbGFdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbaWVyaSBsYV0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdbZm9zdGFdIGRkZGQgW2xhXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdwZXN0ZSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJyVzIMOubiB1cm3EgycsXG4gICAgICAgICAgICBzIDogJ2PDonRldmEgc2VjdW5kZScsXG4gICAgICAgICAgICBzcyA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMixcbiAgICAgICAgICAgIG0gOiAndW4gbWludXQnLFxuICAgICAgICAgICAgbW0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDIsXG4gICAgICAgICAgICBoIDogJ28gb3LEgycsXG4gICAgICAgICAgICBoaCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMixcbiAgICAgICAgICAgIGQgOiAnbyB6aScsXG4gICAgICAgICAgICBkZCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMixcbiAgICAgICAgICAgIE0gOiAnbyBsdW7EgycsXG4gICAgICAgICAgICBNTSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMixcbiAgICAgICAgICAgIHkgOiAndW4gYW4nLFxuICAgICAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDJcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBmdW5jdGlvbiBwbHVyYWwkNCh3b3JkLCBudW0pIHtcbiAgICAgICAgdmFyIGZvcm1zID0gd29yZC5zcGxpdCgnXycpO1xuICAgICAgICByZXR1cm4gbnVtICUgMTAgPT09IDEgJiYgbnVtICUgMTAwICE9PSAxMSA/IGZvcm1zWzBdIDogKG51bSAlIDEwID49IDIgJiYgbnVtICUgMTAgPD0gNCAmJiAobnVtICUgMTAwIDwgMTAgfHwgbnVtICUgMTAwID49IDIwKSA/IGZvcm1zWzFdIDogZm9ybXNbMl0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDMobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgICAgICdzcyc6IHdpdGhvdXRTdWZmaXggPyAn0YHQtdC60YPQvdC00LBf0YHQtdC60YPQvdC00Ytf0YHQtdC60YPQvdC0JyA6ICfRgdC10LrRg9C90LTRg1/RgdC10LrRg9C90LTRi1/RgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgJ21tJzogd2l0aG91dFN1ZmZpeCA/ICfQvNC40L3Rg9GC0LBf0LzQuNC90YPRgtGLX9C80LjQvdGD0YInIDogJ9C80LjQvdGD0YLRg1/QvNC40L3Rg9GC0Ytf0LzQuNC90YPRgicsXG4gICAgICAgICAgICAnaGgnOiAn0YfQsNGBX9GH0LDRgdCwX9GH0LDRgdC+0LInLFxuICAgICAgICAgICAgJ2RkJzogJ9C00LXQvdGMX9C00L3Rj1/QtNC90LXQuScsXG4gICAgICAgICAgICAnTU0nOiAn0LzQtdGB0Y/Rhl/QvNC10YHRj9GG0LBf0LzQtdGB0Y/RhtC10LInLFxuICAgICAgICAgICAgJ3l5JzogJ9Cz0L7QtF/Qs9C+0LTQsF/Qu9C10YInXG4gICAgICAgIH07XG4gICAgICAgIGlmIChrZXkgPT09ICdtJykge1xuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAn0LzQuNC90YPRgtCwJyA6ICfQvNC40L3Rg9GC0YMnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgJyArIHBsdXJhbCQ0KGZvcm1hdFtrZXldLCArbnVtYmVyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB2YXIgbW9udGhzUGFyc2UkNiA9IFsvXtGP0L3Qsi9pLCAvXtGE0LXQsi9pLCAvXtC80LDRgC9pLCAvXtCw0L/RgC9pLCAvXtC80LBb0LnRj10vaSwgL17QuNGO0L0vaSwgL17QuNGO0LsvaSwgL17QsNCy0LMvaSwgL17RgdC10L0vaSwgL17QvtC60YIvaSwgL17QvdC+0Y8vaSwgL17QtNC10LovaV07XG5cbiAgICAvLyBodHRwOi8vbmV3LmdyYW1vdGEucnUvc3ByYXZrYS9ydWxlcy8xMzktcHJvcCA6IMKnIDEwM1xuICAgIC8vINCh0L7QutGA0LDRidC10L3QuNGPINC80LXRgdGP0YbQtdCyOiBodHRwOi8vbmV3LmdyYW1vdGEucnUvc3ByYXZrYS9idXJvL3NlYXJjaC1hbnN3ZXI/cz0yNDI2MzdcbiAgICAvLyBDTERSIGRhdGE6ICAgICAgICAgIGh0dHA6Ly93d3cudW5pY29kZS5vcmcvY2xkci9jaGFydHMvMjgvc3VtbWFyeS9ydS5odG1sIzE3NTNcbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3J1Jywge1xuICAgICAgICBtb250aHMgOiB7XG4gICAgICAgICAgICBmb3JtYXQ6ICfRj9C90LLQsNGA0Y9f0YTQtdCy0YDQsNC70Y9f0LzQsNGA0YLQsF/QsNC/0YDQtdC70Y9f0LzQsNGPX9C40Y7QvdGPX9C40Y7Qu9GPX9Cw0LLQs9GD0YHRgtCwX9GB0LXQvdGC0Y/QsdGA0Y9f0L7QutGC0Y/QsdGA0Y9f0L3QvtGP0LHRgNGPX9C00LXQutCw0LHRgNGPJy5zcGxpdCgnXycpLFxuICAgICAgICAgICAgc3RhbmRhbG9uZTogJ9GP0L3QstCw0YDRjF/RhNC10LLRgNCw0LvRjF/QvNCw0YDRgl/QsNC/0YDQtdC70Yxf0LzQsNC5X9C40Y7QvdGMX9C40Y7Qu9GMX9Cw0LLQs9GD0YHRgl/RgdC10L3RgtGP0LHRgNGMX9C+0LrRgtGP0LHRgNGMX9C90L7Rj9Cx0YDRjF/QtNC10LrQsNCx0YDRjCcuc3BsaXQoJ18nKVxuICAgICAgICB9LFxuICAgICAgICBtb250aHNTaG9ydCA6IHtcbiAgICAgICAgICAgIC8vINC/0L4gQ0xEUiDQuNC80LXQvdC90L4gXCLQuNGO0LsuXCIg0LggXCLQuNGO0L0uXCIsINC90L4g0LrQsNC60L7QuSDRgdC80YvRgdC7INC80LXQvdGP0YLRjCDQsdGD0LrQstGDINC90LAg0YLQvtGH0LrRgyA/XG4gICAgICAgICAgICBmb3JtYXQ6ICfRj9C90LIuX9GE0LXQstGALl/QvNCw0YAuX9Cw0L/RgC5f0LzQsNGPX9C40Y7QvdGPX9C40Y7Qu9GPX9Cw0LLQsy5f0YHQtdC90YIuX9C+0LrRgi5f0L3QvtGP0LEuX9C00LXQui4nLnNwbGl0KCdfJyksXG4gICAgICAgICAgICBzdGFuZGFsb25lOiAn0Y/QvdCyLl/RhNC10LLRgC5f0LzQsNGA0YJf0LDQv9GALl/QvNCw0Llf0LjRjtC90Yxf0LjRjtC70Yxf0LDQstCzLl/RgdC10L3Rgi5f0L7QutGCLl/QvdC+0Y/QsS5f0LTQtdC6Licuc3BsaXQoJ18nKVxuICAgICAgICB9LFxuICAgICAgICB3ZWVrZGF5cyA6IHtcbiAgICAgICAgICAgIHN0YW5kYWxvbmU6ICfQstC+0YHQutGA0LXRgdC10L3RjNC1X9C/0L7QvdC10LTQtdC70YzQvdC40Lpf0LLRgtC+0YDQvdC40Lpf0YHRgNC10LTQsF/Rh9C10YLQstC10YDQs1/Qv9GP0YLQvdC40YbQsF/RgdGD0LHQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgICAgIGZvcm1hdDogJ9Cy0L7RgdC60YDQtdGB0LXQvdGM0LVf0L/QvtC90LXQtNC10LvRjNC90LjQul/QstGC0L7RgNC90LjQul/RgdGA0LXQtNGDX9GH0LXRgtCy0LXRgNCzX9C/0Y/RgtC90LjRhtGDX9GB0YPQsdCx0L7RgtGDJy5zcGxpdCgnXycpLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IC9cXFsgP1vQktCyXSA/KD860L/RgNC+0YjQu9GD0Y580YHQu9C10LTRg9GO0YnRg9GOfNGN0YLRgyk/ID9cXF0gP2RkZGQvXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn0LLRgV/Qv9C9X9Cy0YJf0YHRgF/Rh9GCX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn0LLRgV/Qv9C9X9Cy0YJf0YHRgF/Rh9GCX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSQ2LFxuICAgICAgICBsb25nTW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSQ2LFxuICAgICAgICBzaG9ydE1vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UkNixcblxuICAgICAgICAvLyDQv9C+0LvQvdGL0LUg0L3QsNC30LLQsNC90LjRjyDRgSDQv9Cw0LTQtdC20LDQvNC4LCDQv9C+INGC0YDQuCDQsdGD0LrQstGLLCDQtNC70Y8g0L3QtdC60L7RgtC+0YDRi9GFLCDQv9C+IDQg0LHRg9C60LLRiywg0YHQvtC60YDQsNGJ0LXQvdC40Y8g0YEg0YLQvtGH0LrQvtC5INC4INCx0LXQtyDRgtC+0YfQutC4XG4gICAgICAgIG1vbnRoc1JlZ2V4OiAvXijRj9C90LLQsNGAW9GM0Y9dfNGP0L3QslxcLj980YTQtdCy0YDQsNC7W9GM0Y9dfNGE0LXQstGAP1xcLj980LzQsNGA0YLQsD980LzQsNGAXFwuP3zQsNC/0YDQtdC7W9GM0Y9dfNCw0L/RgFxcLj980LzQsFvQudGPXXzQuNGO0L1b0YzRj1180LjRjtC9XFwuP3zQuNGO0Ltb0YzRj1180LjRjtC7XFwuP3zQsNCy0LPRg9GB0YLQsD980LDQstCzXFwuP3zRgdC10L3RgtGP0LHRgFvRjNGPXXzRgdC10L3Rgj9cXC4/fNC+0LrRgtGP0LHRgFvRjNGPXXzQvtC60YJcXC4/fNC90L7Rj9Cx0YBb0YzRj1180L3QvtGP0LE/XFwuP3zQtNC10LrQsNCx0YBb0YzRj1180LTQtdC6XFwuPykvaSxcblxuICAgICAgICAvLyDQutC+0L/QuNGPINC/0YDQtdC00YvQtNGD0YnQtdCz0L5cbiAgICAgICAgbW9udGhzU2hvcnRSZWdleDogL14o0Y/QvdCy0LDRgFvRjNGPXXzRj9C90LJcXC4/fNGE0LXQstGA0LDQu1vRjNGPXXzRhNC10LLRgD9cXC4/fNC80LDRgNGC0LA/fNC80LDRgFxcLj980LDQv9GA0LXQu1vRjNGPXXzQsNC/0YBcXC4/fNC80LBb0LnRj1180LjRjtC9W9GM0Y9dfNC40Y7QvVxcLj980LjRjtC7W9GM0Y9dfNC40Y7Qu1xcLj980LDQstCz0YPRgdGC0LA/fNCw0LLQs1xcLj980YHQtdC90YLRj9Cx0YBb0YzRj1180YHQtdC90YI/XFwuP3zQvtC60YLRj9Cx0YBb0YzRj1180L7QutGCXFwuP3zQvdC+0Y/QsdGAW9GM0Y9dfNC90L7Rj9CxP1xcLj980LTQtdC60LDQsdGAW9GM0Y9dfNC00LXQulxcLj8pL2ksXG5cbiAgICAgICAgLy8g0L/QvtC70L3Ri9C1INC90LDQt9Cy0LDQvdC40Y8g0YEg0L/QsNC00LXQttCw0LzQuFxuICAgICAgICBtb250aHNTdHJpY3RSZWdleDogL14o0Y/QvdCy0LDRgFvRj9GMXXzRhNC10LLRgNCw0Ltb0Y/RjF180LzQsNGA0YLQsD980LDQv9GA0LXQu1vRj9GMXXzQvNCwW9GP0LldfNC40Y7QvVvRj9GMXXzQuNGO0Ltb0Y/RjF180LDQstCz0YPRgdGC0LA/fNGB0LXQvdGC0Y/QsdGAW9GP0YxdfNC+0LrRgtGP0LHRgFvRj9GMXXzQvdC+0Y/QsdGAW9GP0YxdfNC00LXQutCw0LHRgFvRj9GMXSkvaSxcblxuICAgICAgICAvLyDQktGL0YDQsNC20LXQvdC40LUsINC60L7RgtC+0YDQvtC1INGB0L7QvtGC0LLQtdGB0YLQstGD0LXRgiDRgtC+0LvRjNC60L4g0YHQvtC60YDQsNGJ0ZHQvdC90YvQvCDRhNC+0YDQvNCw0LxcbiAgICAgICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14o0Y/QvdCyXFwufNGE0LXQstGAP1xcLnzQvNCw0YBb0YIuXXzQsNC/0YBcXC580LzQsFvRj9C5XXzQuNGO0L1b0YzRjy5dfNC40Y7Qu1vRjNGPLl180LDQstCzXFwufNGB0LXQvdGCP1xcLnzQvtC60YJcXC580L3QvtGP0LE/XFwufNC00LXQulxcLikvaSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWSDQsy4nLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZINCzLiwgSDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZINCzLiwgSDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9Ch0LXQs9C+0LTQvdGPLCDQsl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vQl9Cw0LLRgtGA0LAsINCyXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5OiAnW9CS0YfQtdGA0LAsINCyXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKG5vdykge1xuICAgICAgICAgICAgICAgIGlmIChub3cud2VlaygpICE9PSB0aGlzLndlZWsoKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDRgdC70LXQtNGD0Y7RidC10LVdIGRkZGQsIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINGB0LvQtdC00YPRjtGJ0LjQuV0gZGRkZCwgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JIg0YHQu9C10LTRg9GO0YnRg9GOXSBkZGRkLCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRheSgpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQktC+XSBkZGRkLCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSXSBkZGRkLCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKG5vdykge1xuICAgICAgICAgICAgICAgIGlmIChub3cud2VlaygpICE9PSB0aGlzLndlZWsoKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDQv9GA0L7RiNC70L7QtV0gZGRkZCwgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JIg0L/RgNC+0YjQu9GL0LldIGRkZGQsIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINC/0YDQvtGI0LvRg9GOXSBkZGRkLCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRheSgpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQktC+XSBkZGRkLCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSXSBkZGRkLCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfRh9C10YDQtdC3ICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMg0L3QsNC30LDQtCcsXG4gICAgICAgICAgICBzIDogJ9C90LXRgdC60L7Qu9GM0LrQviDRgdC10LrRg9C90LQnLFxuICAgICAgICAgICAgc3MgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDMsXG4gICAgICAgICAgICBtIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQzLFxuICAgICAgICAgICAgbW0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDMsXG4gICAgICAgICAgICBoIDogJ9GH0LDRgScsXG4gICAgICAgICAgICBoaCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkMyxcbiAgICAgICAgICAgIGQgOiAn0LTQtdC90YwnLFxuICAgICAgICAgICAgZGQgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDMsXG4gICAgICAgICAgICBNIDogJ9C80LXRgdGP0YYnLFxuICAgICAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDMsXG4gICAgICAgICAgICB5IDogJ9Cz0L7QtCcsXG4gICAgICAgICAgICB5eSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkM1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv0L3QvtGH0Lh80YPRgtGA0LB80LTQvdGPfNCy0LXRh9C10YDQsC9pLFxuICAgICAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gL14o0LTQvdGPfNCy0LXRh9C10YDQsCkkLy50ZXN0KGlucHV0KTtcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9C90L7Rh9C4JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfRg9GC0YDQsCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0LTQvdGPJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfQstC10YfQtdGA0LAnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNC5fNCz0L580Y8pLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC5JztcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LPQvic7XG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGPJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciBtb250aHMkOCA9IFtcbiAgICAgICAgJ9is2YbZiNix2YonLFxuICAgICAgICAn2YHZitio2LHZiNix2YonLFxuICAgICAgICAn2YXYp9ix2oYnLFxuICAgICAgICAn2KfZvtix2YrZhCcsXG4gICAgICAgICfZhdim2YonLFxuICAgICAgICAn2KzZiNmGJyxcbiAgICAgICAgJ9is2YjZhNin2KHZkCcsXG4gICAgICAgICfYotqv2LPZvScsXG4gICAgICAgICfYs9mK2b7ZvdmF2KjYsScsXG4gICAgICAgICfYotqq2b3ZiNio2LEnLFxuICAgICAgICAn2YbZiNmF2KjYsScsXG4gICAgICAgICfaitiz2YXYqNixJ1xuICAgIF07XG4gICAgdmFyIGRheXMkMSA9IFtcbiAgICAgICAgJ9ii2obYsScsXG4gICAgICAgICfYs9mI2YXYsScsXG4gICAgICAgICfYp9qx2KfYsdmIJyxcbiAgICAgICAgJ9in2LHYqNi5JyxcbiAgICAgICAgJ9iu2YXZitizJyxcbiAgICAgICAgJ9is2YXYuScsXG4gICAgICAgICfah9mG2ofYsSdcbiAgICBdO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzZCcsIHtcbiAgICAgICAgbW9udGhzIDogbW9udGhzJDgsXG4gICAgICAgIG1vbnRoc1Nob3J0IDogbW9udGhzJDgsXG4gICAgICAgIHdlZWtkYXlzIDogZGF5cyQxLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogZGF5cyQxLFxuICAgICAgICB3ZWVrZGF5c01pbiA6IGRheXMkMSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGTYjCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9i12KjYrXzYtNin2YUvLFxuICAgICAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9i02KfZhScgPT09IGlucHV0O1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9i12KjYrSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJ9i02KfZhSc7XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb2KfahF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb2LPagNin2rvZil0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb2Kfas9mK2YYg2YfZgdiq2Yog2KrZil0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb2qrYp9mE2YfZh10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW9qv2LLYsdmK2YQg2YfZgdiq2YpdIGRkZGQgW9iq2YpdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyDZvtmI2KEnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyDYp9qzJyxcbiAgICAgICAgICAgIHMgOiAn2obZhtivINiz2YraqtmG2oonLFxuICAgICAgICAgICAgc3MgOiAnJWQg2LPZitqq2YbaiicsXG4gICAgICAgICAgICBtIDogJ9mH2qog2YXZhtm9JyxcbiAgICAgICAgICAgIG1tIDogJyVkINmF2YbZvScsXG4gICAgICAgICAgICBoIDogJ9mH2qog2qrZhNin2qonLFxuICAgICAgICAgICAgaGggOiAnJWQg2qrZhNin2qonLFxuICAgICAgICAgICAgZCA6ICfZh9qqINqP2YrZhtmH2YYnLFxuICAgICAgICAgICAgZGQgOiAnJWQg2o/ZitmG2YfZhicsXG4gICAgICAgICAgICBNIDogJ9mH2qog2YXZh9mK2YbZiCcsXG4gICAgICAgICAgICBNTSA6ICclZCDZhdmH2YrZhtinJyxcbiAgICAgICAgICAgIHkgOiAn2YfaqiDYs9in2YQnLFxuICAgICAgICAgICAgeXkgOiAnJWQg2LPYp9mEJ1xuICAgICAgICB9LFxuICAgICAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC/YjC9nLCAnLCcpO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzZScsIHtcbiAgICAgICAgbW9udGhzIDogJ2/EkcSRYWphZ2Vtw6FubnVfZ3VvdnZhbcOhbm51X25qdWvEjWFtw6FubnVfY3VvxYtvbcOhbm51X21pZXNzZW3DoW5udV9nZWFzc2Vtw6FubnVfc3VvaWRuZW3DoW5udV9ib3JnZW3DoW5udV/EjWFrxI1hbcOhbm51X2dvbGdnb3Rtw6FubnVfc2vDoWJtYW3DoW5udV9qdW92bGFtw6FubnUnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ2/EkcSRal9ndW92X25qdWtfY3VvX21pZXNfZ2Vhc19zdW9pX2JvcmdfxI1ha8SNX2dvbGdfc2vDoWJfanVvdicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnc290bmFiZWFpdmlfdnVvc3PDoXJnYV9tYcWLxYtlYsOhcmdhX2dhc2thdmFoa2t1X2R1b3Jhc3RhdF9iZWFyamFkYXRfbMOhdnZhcmRhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdzb3RuX3Z1b3NfbWHFi19nYXNrX2R1b3JfYmVhcl9sw6F2Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdzX3ZfbV9nX2RfYl9MJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgOiAnTU1NTSBELiBbYi5dIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ01NTU0gRC4gW2IuXSBZWVlZIFt0aS5dIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgTU1NTSBELiBbYi5dIFlZWVkgW3RpLl0gSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tvdG5lIHRpXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW2lodHRpbiB0aV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt0aV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tpa3RlIHRpXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tvdmRkaXRdIGRkZGQgW3RpXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyBnZWHFvmVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnbWHFi2l0ICVzJyxcbiAgICAgICAgICAgIHMgOiAnbW9hZGRlIHNla3VuZGRhdCcsXG4gICAgICAgICAgICBzczogJyVkIHNla3VuZGRhdCcsXG4gICAgICAgICAgICBtIDogJ29rdGEgbWludWh0YScsXG4gICAgICAgICAgICBtbSA6ICclZCBtaW51aHRhdCcsXG4gICAgICAgICAgICBoIDogJ29rdGEgZGlpbW11JyxcbiAgICAgICAgICAgIGhoIDogJyVkIGRpaW1tdXQnLFxuICAgICAgICAgICAgZCA6ICdva3RhIGJlYWl2aScsXG4gICAgICAgICAgICBkZCA6ICclZCBiZWFpdnZpdCcsXG4gICAgICAgICAgICBNIDogJ29rdGEgbcOhbm51JyxcbiAgICAgICAgICAgIE1NIDogJyVkIG3DoW51dCcsXG4gICAgICAgICAgICB5IDogJ29rdGEgamFoa2knLFxuICAgICAgICAgICAgeXkgOiAnJWQgamFnaXQnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICAvKmpzaGludCAtVzEwMCovXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzaScsIHtcbiAgICAgICAgbW9udGhzIDogJ+C2ouC2seC3gOC3j+C2u+C3kl/gtrTgt5ngtrbgtrvgt4Dgt4/gtrvgt5Jf4La44LeP4La74LeK4Lat4LeUX+C2heC2tOC3iuKAjeC2u+C3muC2veC3il/gtrjgt5Dgtrrgt5Jf4Lai4LeW4Lax4LeSX+C2ouC3luC2veC3kl/gtoXgtpzgt53gt4Pgt4rgtq3gt5Rf4LeD4LeQ4La04LeK4Lat4LeQ4La44LeK4La24La74LeKX+C2lOC2muC3iuC2reC3neC2tuC2u+C3il/gtrHgt5zgt4Dgt5Dgtrjgt4rgtrbgtrvgt4pf4Lav4LeZ4LeD4LeQ4La44LeK4La24La74LeKJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICfgtqLgtrFf4La04LeZ4La2X+C2uOC3j+C2u+C3il/gtoXgtrTgt4pf4La44LeQ4La64LeSX+C2ouC3luC2seC3kl/gtqLgt5bgtr3gt5Jf4LaF4Lac4LedX+C3g+C3kOC2tOC3il/gtpTgtprgt4pf4Lax4Lec4LeA4LeQX+C2r+C3meC3g+C3kCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAn4LaJ4La74LeS4Lav4LePX+C3g+C2s+C3lOC2r+C3j1/gtoXgtp/gt4Tgtrvgt5Tgt4Dgt4/gtq/gt49f4La24Lav4LeP4Lav4LePX+C2tuC3iuKAjeC2u+C3hOC3g+C3iuC2tOC2reC3kuC2seC3iuC2r+C3j1/gt4Pgt5Lgtprgt5Tgtrvgt4/gtq/gt49f4LeD4LeZ4Lax4LeD4LeU4La74LeP4Lav4LePJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ+C2ieC2u+C3kl/gt4PgtrPgt5Rf4LaF4LafX+C2tuC2r+C3j1/gtrbgt4rigI3gtrvgt4Rf4LeD4LeS4Laa4LeUX+C3g+C3meC2sScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn4LaJX+C3g1/gtoVf4La2X+C2tuC3iuKAjeC2u1/gt4Pgt5Jf4LeD4LeZJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ2EgaDptbScsXG4gICAgICAgICAgICBMVFMgOiAnYSBoOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnWVlZWS9NTS9ERCcsXG4gICAgICAgICAgICBMTCA6ICdZWVlZIE1NTU0gRCcsXG4gICAgICAgICAgICBMTEwgOiAnWVlZWSBNTU1NIEQsIGEgaDptbScsXG4gICAgICAgICAgICBMTExMIDogJ1lZWVkgTU1NTSBEIFvgt4Dgt5DgtrHgt5JdIGRkZGQsIGEgaDptbTpzcydcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1vgtoXgtq9dIExUW+C2p10nLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb4LeE4LeZ4LanXSBMVFvgtqddJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgTFRb4LanXScsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1vgtorgtrrgt5pdIExUW+C2p10nLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW+C2tOC3g+C3lOC2nOC3kuC2ul0gZGRkZCBMVFvgtqddJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclc+C2muC3kuC2seC3iicsXG4gICAgICAgICAgICBwYXN0IDogJyVz4Laa4LanIOC2tOC3meC2uycsXG4gICAgICAgICAgICBzIDogJ+C2reC2reC3iuC2tOC2uyDgtprgt5Lgt4Tgt5LgtrTgtronLFxuICAgICAgICAgICAgc3MgOiAn4Lat4Lat4LeK4La04La7ICVkJyxcbiAgICAgICAgICAgIG0gOiAn4La44LeS4Lax4LeS4Lat4LeK4Lat4LeU4LeAJyxcbiAgICAgICAgICAgIG1tIDogJ+C2uOC3kuC2seC3kuC2reC3iuC2reC3lCAlZCcsXG4gICAgICAgICAgICBoIDogJ+C2tOC3kOC2uicsXG4gICAgICAgICAgICBoaCA6ICfgtrTgt5DgtrogJWQnLFxuICAgICAgICAgICAgZCA6ICfgtq/gt5LgtrHgtronLFxuICAgICAgICAgICAgZGQgOiAn4Lav4LeS4LaxICVkJyxcbiAgICAgICAgICAgIE0gOiAn4La44LeP4LeD4La6JyxcbiAgICAgICAgICAgIE1NIDogJ+C2uOC3j+C3gyAlZCcsXG4gICAgICAgICAgICB5IDogJ+C3gOC3g+C2uycsXG4gICAgICAgICAgICB5eSA6ICfgt4Dgt4PgtrsgJWQnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSDgt4Dgt5DgtrHgt5IvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcg4LeA4LeQ4Lax4LeSJztcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZSA6IC/gtrTgt5ngtrsg4LeA4La74LeUfOC2tOC3g+C3iiDgt4Dgtrvgt5R84La04LeZLuC3gHzgtrQu4LeALi8sXG4gICAgICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PT0gJ+C2tC7gt4AuJyB8fCBpbnB1dCA9PT0gJ+C2tOC3g+C3iiDgt4Dgtrvgt5QnO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXJzID4gMTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfgtrQu4LeALicgOiAn4La04LeD4LeKIOC3gOC2u+C3lCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ+C2tOC3mS7gt4AuJyA6ICfgtrTgt5ngtrsg4LeA4La74LeUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIG1vbnRocyQ5ID0gJ2phbnXDoXJfZmVicnXDoXJfbWFyZWNfYXByw61sX23DoWpfasO6bl9qw7psX2F1Z3VzdF9zZXB0ZW1iZXJfb2t0w7NiZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0JDYgPSAnamFuX2ZlYl9tYXJfYXByX23DoWpfasO6bl9qw7psX2F1Z19zZXBfb2t0X25vdl9kZWMnLnNwbGl0KCdfJyk7XG4gICAgZnVuY3Rpb24gcGx1cmFsJDUobikge1xuICAgICAgICByZXR1cm4gKG4gPiAxKSAmJiAobiA8IDUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkOShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgJ3MnOiAgLy8gYSBmZXcgc2Vjb25kcyAvIGluIGEgZmV3IHNlY29uZHMgLyBhIGZldyBzZWNvbmRzIGFnb1xuICAgICAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAncMOhciBzZWvDum5kJyA6ICdww6FyIHNla3VuZGFtaSc7XG4gICAgICAgICAgICBjYXNlICdzcyc6IC8vIDkgc2Vjb25kcyAvIGluIDkgc2Vjb25kcyAvIDkgc2Vjb25kcyBhZ29cbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAnc2VrdW5keScgOiAnc2Vrw7puZCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnc2VrdW5kYW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtJzogIC8vIGEgbWludXRlIC8gaW4gYSBtaW51dGUgLyBhIG1pbnV0ZSBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdtaW7DunRhJyA6IChpc0Z1dHVyZSA/ICdtaW7DunR1JyA6ICdtaW7DunRvdScpO1xuICAgICAgICAgICAgY2FzZSAnbW0nOiAvLyA5IG1pbnV0ZXMgLyBpbiA5IG1pbnV0ZXMgLyA5IG1pbnV0ZXMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkNShudW1iZXIpID8gJ21pbsO6dHknIDogJ21pbsO6dCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbWluw7p0YW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdoJzogIC8vIGFuIGhvdXIgLyBpbiBhbiBob3VyIC8gYW4gaG91ciBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdob2RpbmEnIDogKGlzRnV0dXJlID8gJ2hvZGludScgOiAnaG9kaW5vdScpO1xuICAgICAgICAgICAgY2FzZSAnaGgnOiAvLyA5IGhvdXJzIC8gaW4gOSBob3VycyAvIDkgaG91cnMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkNShudW1iZXIpID8gJ2hvZGlueScgOiAnaG9kw61uJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdob2RpbmFtaSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZCc6ICAvLyBhIGRheSAvIGluIGEgZGF5IC8gYSBkYXkgYWdvXG4gICAgICAgICAgICAgICAgcmV0dXJuICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSA/ICdkZcWIJyA6ICdkxYhvbSc7XG4gICAgICAgICAgICBjYXNlICdkZCc6IC8vIDkgZGF5cyAvIGluIDkgZGF5cyAvIDkgZGF5cyBhZ29cbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAnZG5pJyA6ICdkbsOtJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdkxYhhbWknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ00nOiAgLy8gYSBtb250aCAvIGluIGEgbW9udGggLyBhIG1vbnRoIGFnb1xuICAgICAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAnbWVzaWFjJyA6ICdtZXNpYWNvbSc7XG4gICAgICAgICAgICBjYXNlICdNTSc6IC8vIDkgbW9udGhzIC8gaW4gOSBtb250aHMgLyA5IG1vbnRocyBhZ29cbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbCQ1KG51bWJlcikgPyAnbWVzaWFjZScgOiAnbWVzaWFjb3YnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ21lc2lhY21pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd5JzogIC8vIGEgeWVhciAvIGluIGEgeWVhciAvIGEgeWVhciBhZ29cbiAgICAgICAgICAgICAgICByZXR1cm4gKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpID8gJ3JvaycgOiAncm9rb20nO1xuICAgICAgICAgICAgY2FzZSAneXknOiAvLyA5IHllYXJzIC8gaW4gOSB5ZWFycyAvIDkgeWVhcnMgYWdvXG4gICAgICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwkNShudW1iZXIpID8gJ3Jva3knIDogJ3Jva292Jyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdyb2ttaSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzaycsIHtcbiAgICAgICAgbW9udGhzIDogbW9udGhzJDksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogbW9udGhzU2hvcnQkNixcbiAgICAgICAgd2Vla2RheXMgOiAnbmVkZcS+YV9wb25kZWxva191dG9yb2tfc3RyZWRhX8WhdHZydG9rX3BpYXRva19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnbmVfcG9fdXRfc3RfxaF0X3BpX3NvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICduZV9wb191dF9zdF/FoXRfcGlfc28nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW2RuZXMgb10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1t6YWp0cmEgb10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBuZWRlxL51IG9dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Ygc3RyZWR1IG9dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdm8gxaF0dnJ0b2sgb10gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IHBpYXRvayBvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Ygc29ib3R1IG9dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGFzdERheTogJ1t2xI1lcmEgb10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDuiBuZWRlxL51IG9dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO9XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw7ogc3RyZWR1IG9dIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO9XSBkZGRkIFtvXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw7ogc29ib3R1IG9dIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnemEgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICdwcmVkICVzJyxcbiAgICAgICAgICAgIHMgOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgICAgIHNzIDogdHJhbnNsYXRlJDksXG4gICAgICAgICAgICBtIDogdHJhbnNsYXRlJDksXG4gICAgICAgICAgICBtbSA6IHRyYW5zbGF0ZSQ5LFxuICAgICAgICAgICAgaCA6IHRyYW5zbGF0ZSQ5LFxuICAgICAgICAgICAgaGggOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgICAgIGQgOiB0cmFuc2xhdGUkOSxcbiAgICAgICAgICAgIGRkIDogdHJhbnNsYXRlJDksXG4gICAgICAgICAgICBNIDogdHJhbnNsYXRlJDksXG4gICAgICAgICAgICBNTSA6IHRyYW5zbGF0ZSQ5LFxuICAgICAgICAgICAgeSA6IHRyYW5zbGF0ZSQ5LFxuICAgICAgICAgICAgeXkgOiB0cmFuc2xhdGUkOVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZSQ2KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbmVrYWogc2VrdW5kJyA6ICduZWthaiBzZWt1bmRhbWknO1xuICAgICAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggPyAnc2VrdW5kbycgOiAnc2VrdW5kaSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnc2VrdW5kaScgOiAnc2VrdW5kYWgnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgNSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdzZWt1bmRlJyA6ICdzZWt1bmRhaCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnZW5hIG1pbnV0YScgOiAnZW5vIG1pbnV0byc7XG4gICAgICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCA/ICdtaW51dGEnIDogJ21pbnV0byc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWludXRpJyA6ICdtaW51dGFtYSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPCA1KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ21pbnV0ZScgOiAnbWludXRhbWknO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ21pbnV0JyA6ICdtaW51dGFtaSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdlbmEgdXJhJyA6ICdlbm8gdXJvJztcbiAgICAgICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4ID8gJ3VyYScgOiAndXJvJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICd1cmknIDogJ3VyYW1hJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAndXJlJyA6ICd1cmFtaSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAndXInIDogJ3VyYW1pJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2VuIGRhbicgOiAnZW5pbSBkbmVtJztcbiAgICAgICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2RhbicgOiAnZG5lbSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnZG5pJyA6ICdkbmV2b21hJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdkbmknIDogJ2RuZXZpJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2VuIG1lc2VjJyA6ICdlbmltIG1lc2VjZW0nO1xuICAgICAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWVzZWMnIDogJ21lc2VjZW0nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ21lc2VjYScgOiAnbWVzZWNlbWEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgNSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtZXNlY2UnIDogJ21lc2VjaSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWVzZWNldicgOiAnbWVzZWNpJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2VubyBsZXRvJyA6ICdlbmltIGxldG9tJztcbiAgICAgICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2xldG8nIDogJ2xldG9tJztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdsZXRpJyA6ICdsZXRvbWEnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgNSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdsZXRhJyA6ICdsZXRpJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdsZXQnIDogJ2xldGknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzbCcsIHtcbiAgICAgICAgbW9udGhzIDogJ2phbnVhcl9mZWJydWFyX21hcmVjX2FwcmlsX21hal9qdW5pal9qdWxpal9hdmd1c3Rfc2VwdGVtYmVyX29rdG9iZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ2phbi5fZmViLl9tYXIuX2Fwci5fbWFqLl9qdW4uX2p1bC5fYXZnLl9zZXAuX29rdC5fbm92Ll9kZWMuJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICduZWRlbGphX3BvbmVkZWxqZWtfdG9yZWtfc3JlZGFfxI1ldHJ0ZWtfcGV0ZWtfc29ib3RhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ25lZC5fcG9uLl90b3IuX3NyZS5fxI1ldC5fcGV0Ll9zb2IuJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICduZV9wb190b19zcl/EjWVfcGVfc28nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgIDogJ1tkYW5lcyBvYl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSAgOiAnW2p1dHJpIG9iXSBMVCcsXG5cbiAgICAgICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBbbmVkZWxqb10gW29iXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIFtzcmVkb10gW29iXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIFtzb2JvdG9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2XSBkZGRkIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXN0RGF5ICA6ICdbdsSNZXJhaiBvYl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ByZWrFoW5qb10gW25lZGVsam9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1twcmVqxaFuam9dIFtzcmVkb10gW29iXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ByZWrFoW5qb10gW3NvYm90b10gW29iXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ByZWrFoW5qaV0gZGRkZCBbb2JdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ8SNZXogJXMnLFxuICAgICAgICAgICAgcGFzdCAgIDogJ3ByZWQgJXMnLFxuICAgICAgICAgICAgcyAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgc3MgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgbSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgbW0gICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgaCAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgaGggICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgZCAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgZGQgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgTSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgTU0gICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgeSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2LFxuICAgICAgICAgICAgeXkgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ2XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3NxJywge1xuICAgICAgICBtb250aHMgOiAnSmFuYXJfU2hrdXJ0X01hcnNfUHJpbGxfTWFqX1FlcnNob3JfS29ycmlrX0d1c2h0X1NodGF0b3JfVGV0b3JfTsOrbnRvcl9EaGpldG9yJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKYW5fU2hrX01hcl9QcmlfTWFqX1Flcl9Lb3JfR3VzX1NodF9UZXRfTsOrbl9EaGonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ0UgRGllbF9FIEjDq27Dq19FIE1hcnTDq19FIE3Dq3JrdXLDq19FIEVuanRlX0UgUHJlbXRlX0UgU2h0dW7Dqycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdEaWVfSMOrbl9NYXJfTcOrcl9FbmpfUHJlX1NodCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnRF9IX01hX03Dq19FX1BfU2gnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC9QRHxNRC8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0LmNoYXJBdCgwKSA9PT0gJ00nO1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXJzIDwgMTIgPyAnUEQnIDogJ01EJztcbiAgICAgICAgfSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW1NvdCBuw6tdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW05lc8OrciBuw6tdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW27Dq10gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbRGplIG7Dq10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbZSBrYWx1YXIgbsOrXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnbsOrICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgbcOrIHBhcsOrJyxcbiAgICAgICAgICAgIHMgOiAnZGlzYSBzZWtvbmRhJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNla29uZGEnLFxuICAgICAgICAgICAgbSA6ICduasOrIG1pbnV0w6snLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludXRhJyxcbiAgICAgICAgICAgIGggOiAnbmrDqyBvcsOrJyxcbiAgICAgICAgICAgIGhoIDogJyVkIG9yw6snLFxuICAgICAgICAgICAgZCA6ICduasOrIGRpdMOrJyxcbiAgICAgICAgICAgIGRkIDogJyVkIGRpdMOrJyxcbiAgICAgICAgICAgIE0gOiAnbmrDqyBtdWFqJyxcbiAgICAgICAgICAgIE1NIDogJyVkIG11YWonLFxuICAgICAgICAgICAgeSA6ICduasOrIHZpdCcsXG4gICAgICAgICAgICB5eSA6ICclZCB2aXRlJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHRyYW5zbGF0b3IkMSA9IHtcbiAgICAgICAgd29yZHM6IHsgLy9EaWZmZXJlbnQgZ3JhbW1hdGljYWwgY2FzZXNcbiAgICAgICAgICAgIHNzOiBbJ9GB0LXQutGD0L3QtNCwJywgJ9GB0LXQutGD0L3QtNC1JywgJ9GB0LXQutGD0L3QtNC4J10sXG4gICAgICAgICAgICBtOiBbJ9GY0LXQtNCw0L0g0LzQuNC90YPRgicsICfRmNC10LTQvdC1INC80LjQvdGD0YLQtSddLFxuICAgICAgICAgICAgbW06IFsn0LzQuNC90YPRgicsICfQvNC40L3Rg9GC0LUnLCAn0LzQuNC90YPRgtCwJ10sXG4gICAgICAgICAgICBoOiBbJ9GY0LXQtNCw0L0g0YHQsNGCJywgJ9GY0LXQtNC90L7QsyDRgdCw0YLQsCddLFxuICAgICAgICAgICAgaGg6IFsn0YHQsNGCJywgJ9GB0LDRgtCwJywgJ9GB0LDRgtC4J10sXG4gICAgICAgICAgICBkZDogWyfQtNCw0L0nLCAn0LTQsNC90LAnLCAn0LTQsNC90LAnXSxcbiAgICAgICAgICAgIE1NOiBbJ9C80LXRgdC10YYnLCAn0LzQtdGB0LXRhtCwJywgJ9C80LXRgdC10YbQuCddLFxuICAgICAgICAgICAgeXk6IFsn0LPQvtC00LjQvdCwJywgJ9Cz0L7QtNC40L3QtScsICfQs9C+0LTQuNC90LAnXVxuICAgICAgICB9LFxuICAgICAgICBjb3JyZWN0R3JhbW1hdGljYWxDYXNlOiBmdW5jdGlvbiAobnVtYmVyLCB3b3JkS2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyID09PSAxID8gd29yZEtleVswXSA6IChudW1iZXIgPj0gMiAmJiBudW1iZXIgPD0gNCA/IHdvcmRLZXlbMV0gOiB3b3JkS2V5WzJdKTtcbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNsYXRlOiBmdW5jdGlvbiAobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgICAgIHZhciB3b3JkS2V5ID0gdHJhbnNsYXRvciQxLndvcmRzW2tleV07XG4gICAgICAgICAgICBpZiAoa2V5Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gd29yZEtleVswXSA6IHdvcmRLZXlbMV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnICcgKyB0cmFuc2xhdG9yJDEuY29ycmVjdEdyYW1tYXRpY2FsQ2FzZShudW1iZXIsIHdvcmRLZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnc3ItY3lybCcsIHtcbiAgICAgICAgbW9udGhzOiAn0ZjQsNC90YPQsNGAX9GE0LXQsdGA0YPQsNGAX9C80LDRgNGCX9Cw0L/RgNC40Ltf0LzQsNGYX9GY0YPQvV/RmNGD0Ltf0LDQstCz0YPRgdGCX9GB0LXQv9GC0LXQvNCx0LDRgF/QvtC60YLQvtCx0LDRgF/QvdC+0LLQtdC80LHQsNGAX9C00LXRhtC10LzQsdCw0YAnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn0ZjQsNC9Ll/RhNC10LEuX9C80LDRgC5f0LDQv9GALl/QvNCw0Zhf0ZjRg9C9X9GY0YPQu1/QsNCy0LMuX9GB0LXQvy5f0L7QutGCLl/QvdC+0LIuX9C00LXRhi4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAn0L3QtdC00LXRmdCwX9C/0L7QvdC10LTQtdGZ0LDQul/Rg9GC0L7RgNCw0Lpf0YHRgNC10LTQsF/Rh9C10YLQstGA0YLQsNC6X9C/0LXRgtCw0Lpf0YHRg9Cx0L7RgtCwJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn0L3QtdC0Ll/Qv9C+0L0uX9GD0YLQvi5f0YHRgNC1Ll/Rh9C10YIuX9C/0LXRgi5f0YHRg9CxLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfQvdC1X9C/0L5f0YPRgl/RgdGAX9GH0LVf0L/QtV/RgdGDJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdb0LTQsNC90LDRgSDRg10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vRgdGD0YLRgNCwINGDXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vRg10gW9C90LXQtNC10ZnRg10gW9GDXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9GDXSBb0YHRgNC10LTRg10gW9GDXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9GDXSBb0YHRg9Cx0L7RgtGDXSBb0YNdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0YNdIGRkZGQgW9GDXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXkgIDogJ1vRmNGD0YfQtSDRg10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RXZWVrRGF5cyA9IFtcbiAgICAgICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70LVdIFvQvdC10LTQtdGZ0LVdIFvRg10gTFQnLFxuICAgICAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQvtCzXSBb0L/QvtC90LXQtNC10ZnQutCwXSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70L7Qs10gW9GD0YLQvtGA0LrQsF0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdb0L/RgNC+0YjQu9C1XSBb0YHRgNC10LTQtV0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdb0L/RgNC+0YjQu9C+0LNdIFvRh9C10YLQstGA0YLQutCwXSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70L7Qs10gW9C/0LXRgtC60LBdIFvRg10gTFQnLFxuICAgICAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQtV0gW9GB0YPQsdC+0YLQtV0gW9GDXSBMVCdcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgIHJldHVybiBsYXN0V2Vla0RheXNbdGhpcy5kYXkoKV07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ9C30LAgJXMnLFxuICAgICAgICAgICAgcGFzdCAgIDogJ9C/0YDQtSAlcycsXG4gICAgICAgICAgICBzICAgICAgOiAn0L3QtdC60L7Qu9C40LrQviDRgdC10LrRg9C90LTQuCcsXG4gICAgICAgICAgICBzcyAgICAgOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICAgICAgbSAgICAgIDogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIG1tICAgICA6IHRyYW5zbGF0b3IkMS50cmFuc2xhdGUsXG4gICAgICAgICAgICBoICAgICAgOiB0cmFuc2xhdG9yJDEudHJhbnNsYXRlLFxuICAgICAgICAgICAgaGggICAgIDogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGQgICAgICA6ICfQtNCw0L0nLFxuICAgICAgICAgICAgZGQgICAgIDogdHJhbnNsYXRvciQxLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIE0gICAgICA6ICfQvNC10YHQtdGGJyxcbiAgICAgICAgICAgIE1NICAgICA6IHRyYW5zbGF0b3IkMS50cmFuc2xhdGUsXG4gICAgICAgICAgICB5ICAgICAgOiAn0LPQvtC00LjQvdGDJyxcbiAgICAgICAgICAgIHl5ICAgICA6IHRyYW5zbGF0b3IkMS50cmFuc2xhdGVcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbCA6ICclZC4nLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIHZhciB0cmFuc2xhdG9yJDIgPSB7XG4gICAgICAgIHdvcmRzOiB7IC8vRGlmZmVyZW50IGdyYW1tYXRpY2FsIGNhc2VzXG4gICAgICAgICAgICBzczogWydzZWt1bmRhJywgJ3Nla3VuZGUnLCAnc2VrdW5kaSddLFxuICAgICAgICAgICAgbTogWydqZWRhbiBtaW51dCcsICdqZWRuZSBtaW51dGUnXSxcbiAgICAgICAgICAgIG1tOiBbJ21pbnV0JywgJ21pbnV0ZScsICdtaW51dGEnXSxcbiAgICAgICAgICAgIGg6IFsnamVkYW4gc2F0JywgJ2plZG5vZyBzYXRhJ10sXG4gICAgICAgICAgICBoaDogWydzYXQnLCAnc2F0YScsICdzYXRpJ10sXG4gICAgICAgICAgICBkZDogWydkYW4nLCAnZGFuYScsICdkYW5hJ10sXG4gICAgICAgICAgICBNTTogWydtZXNlYycsICdtZXNlY2EnLCAnbWVzZWNpJ10sXG4gICAgICAgICAgICB5eTogWydnb2RpbmEnLCAnZ29kaW5lJywgJ2dvZGluYSddXG4gICAgICAgIH0sXG4gICAgICAgIGNvcnJlY3RHcmFtbWF0aWNhbENhc2U6IGZ1bmN0aW9uIChudW1iZXIsIHdvcmRLZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgPT09IDEgPyB3b3JkS2V5WzBdIDogKG51bWJlciA+PSAyICYmIG51bWJlciA8PSA0ID8gd29yZEtleVsxXSA6IHdvcmRLZXlbMl0pO1xuICAgICAgICB9LFxuICAgICAgICB0cmFuc2xhdGU6IGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICAgICAgdmFyIHdvcmRLZXkgPSB0cmFuc2xhdG9yJDIud29yZHNba2V5XTtcbiAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyB3b3JkS2V5WzBdIDogd29yZEtleVsxXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgJyArIHRyYW5zbGF0b3IkMi5jb3JyZWN0R3JhbW1hdGljYWxDYXNlKG51bWJlciwgd29yZEtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzcicsIHtcbiAgICAgICAgbW9udGhzOiAnamFudWFyX2ZlYnJ1YXJfbWFydF9hcHJpbF9tYWpfanVuX2p1bF9hdmd1c3Rfc2VwdGVtYmFyX29rdG9iYXJfbm92ZW1iYXJfZGVjZW1iYXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAnamFuLl9mZWIuX21hci5fYXByLl9tYWpfanVuX2p1bF9hdmcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgICAgIHdlZWtkYXlzOiAnbmVkZWxqYV9wb25lZGVsamFrX3V0b3Jha19zcmVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAnbmVkLl9wb24uX3V0by5fc3JlLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluOiAnbmVfcG9fdXRfc3JfxI1lX3BlX3N1Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXI6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbZGFuYXMgdV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tzdXRyYSB1XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbbmVkZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3NyZWR1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbc3Vib3R1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhc3REYXkgIDogJ1tqdcSNZSB1XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGFzdFdlZWtEYXlzID0gW1xuICAgICAgICAgICAgICAgICAgICAnW3Byb8WhbGVdIFtuZWRlbGplXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICAgICAnW3Byb8WhbG9nXSBbcG9uZWRlbGprYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1twcm/FoWxvZ10gW3V0b3JrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3JlZGVdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFvEjWV0dnJ0a2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFtwZXRrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3Vib3RlXSBbdV0gTFQnXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFzdFdlZWtEYXlzW3RoaXMuZGF5KCldO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICd6YSAlcycsXG4gICAgICAgICAgICBwYXN0ICAgOiAncHJlICVzJyxcbiAgICAgICAgICAgIHMgICAgICA6ICduZWtvbGlrbyBzZWt1bmRpJyxcbiAgICAgICAgICAgIHNzICAgICA6IHRyYW5zbGF0b3IkMi50cmFuc2xhdGUsXG4gICAgICAgICAgICBtICAgICAgOiB0cmFuc2xhdG9yJDIudHJhbnNsYXRlLFxuICAgICAgICAgICAgbW0gICAgIDogdHJhbnNsYXRvciQyLnRyYW5zbGF0ZSxcbiAgICAgICAgICAgIGggICAgICA6IHRyYW5zbGF0b3IkMi50cmFuc2xhdGUsXG4gICAgICAgICAgICBoaCAgICAgOiB0cmFuc2xhdG9yJDIudHJhbnNsYXRlLFxuICAgICAgICAgICAgZCAgICAgIDogJ2RhbicsXG4gICAgICAgICAgICBkZCAgICAgOiB0cmFuc2xhdG9yJDIudHJhbnNsYXRlLFxuICAgICAgICAgICAgTSAgICAgIDogJ21lc2VjJyxcbiAgICAgICAgICAgIE1NICAgICA6IHRyYW5zbGF0b3IkMi50cmFuc2xhdGUsXG4gICAgICAgICAgICB5ICAgICAgOiAnZ29kaW51JyxcbiAgICAgICAgICAgIHl5ICAgICA6IHRyYW5zbGF0b3IkMi50cmFuc2xhdGVcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICAgICAgb3JkaW5hbCA6ICclZC4nLFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA3dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnc3MnLCB7XG4gICAgICAgIG1vbnRocyA6IFwiQmhpbWJpZHZ3YW5lX0luZGxvdmFuYV9JbmRsb3YnbGVua2h1bHVfTWFiYXNhX0lua2h3ZWtod2V0aV9JbmhsYWJhX0tob2x3YW5lX0luZ2NpX0lueW9uaV9JbXBoYWxhX0x3ZXRpX0luZ29uZ29uaVwiLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0JoaV9JbmFfSW51X01hYl9JbmtfSW5oX0tob19JZ2NfSW55X0ltcF9Md2VfSWdvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdMaXNvbnRmb19VbXNvbWJ1bHVrb19MZXNpYmlsaV9MZXNpdHNhdGZ1X0xlc2luZV9MZXNpaGxhbnVfVW1nY2liZWxvJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ0xpc19VbWJfTHNiX0xlc19Mc2lfTHNoX1VtZycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnTGlfVXNfTGJfTHRfTHNfTGhfVWcnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgICAgIExUUyA6ICdoOm1tOnNzIEEnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBoOm1tIEEnLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbTmFtdWhsYSBuZ2FdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW0t1c2FzYSBuZ2FdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW25nYV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbSXRvbG8gbmdhXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtsZWxpcGhlbGlsZV0gW25nYV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ25nYSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ3dlbnRla2EgbmdhICVzJyxcbiAgICAgICAgICAgIHMgOiAnZW1penV6d2FuYSBsb21jYW5lJyxcbiAgICAgICAgICAgIHNzIDogJyVkIG16dXp3YW5hJyxcbiAgICAgICAgICAgIG0gOiAndW16dXp1JyxcbiAgICAgICAgICAgIG1tIDogJyVkIGVtaXp1enUnLFxuICAgICAgICAgICAgaCA6ICdsaWhvcmEnLFxuICAgICAgICAgICAgaGggOiAnJWQgZW1haG9yYScsXG4gICAgICAgICAgICBkIDogJ2xpbGFuZ2EnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZW1hbGFuZ2EnLFxuICAgICAgICAgICAgTSA6ICdpbnlhbmdhJyxcbiAgICAgICAgICAgIE1NIDogJyVkIHRpbnlhbmdhJyxcbiAgICAgICAgICAgIHkgOiAndW1ueWFrYScsXG4gICAgICAgICAgICB5eSA6ICclZCBpbWlueWFrYSdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL2VrdXNlbml8ZW1pbml8ZW50c2FtYmFtYXxlYnVzdWt1LyxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VycyA8IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdla3VzZW5pJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnZW1pbmknO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdlbnRzYW1iYW1hJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdlYnVzdWt1JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ2VrdXNlbmknKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnZW1pbmknKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ2VudHNhbWJhbWEnIHx8IG1lcmlkaWVtID09PSAnZWJ1c3VrdScpIHtcbiAgICAgICAgICAgICAgICBpZiAoaG91ciA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LyxcbiAgICAgICAgb3JkaW5hbCA6ICclZCcsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzdicsIHtcbiAgICAgICAgbW9udGhzIDogJ2phbnVhcmlfZmVicnVhcmlfbWFyc19hcHJpbF9tYWpfanVuaV9qdWxpX2F1Z3VzdGlfc2VwdGVtYmVyX29rdG9iZXJfbm92ZW1iZXJfZGVjZW1iZXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYWpfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdzw7ZuZGFnX23DpW5kYWdfdGlzZGFnX29uc2RhZ190b3JzZGFnX2ZyZWRhZ19sw7ZyZGFnJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ3PDtm5fbcOlbl90aXNfb25zX3Rvcl9mcmVfbMO2cicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnc8O2X23DpV90aV9vbl90b19mcl9sw7YnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIFtrbC5dIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbCA6ICdEIE1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGwgOiAnZGRkIEQgTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tJZGFnXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0ltb3Jnb25dIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbSWfDpXJdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnW1DDpV0gZGRkZCBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ1tJXSBkZGRkW3NdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ29tICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnZsO2ciAlcyBzZWRhbicsXG4gICAgICAgICAgICBzIDogJ27DpWdyYSBzZWt1bmRlcicsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWt1bmRlcicsXG4gICAgICAgICAgICBtIDogJ2VuIG1pbnV0JyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0ZXInLFxuICAgICAgICAgICAgaCA6ICdlbiB0aW1tZScsXG4gICAgICAgICAgICBoaCA6ICclZCB0aW1tYXInLFxuICAgICAgICAgICAgZCA6ICdlbiBkYWcnLFxuICAgICAgICAgICAgZGQgOiAnJWQgZGFnYXInLFxuICAgICAgICAgICAgTSA6ICdlbiBtw6VuYWQnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbcOlbmFkZXInLFxuICAgICAgICAgICAgeSA6ICdldHQgw6VyJyxcbiAgICAgICAgICAgIHl5IDogJyVkIMOlcidcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGV8YSkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAofn4obnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICdlJyA6XG4gICAgICAgICAgICAgICAgKGIgPT09IDEpID8gJ2EnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMikgPyAnYScgOlxuICAgICAgICAgICAgICAgIChiID09PSAzKSA/ICdlJyA6ICdlJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCdzdycsIHtcbiAgICAgICAgbW9udGhzIDogJ0phbnVhcmlfRmVicnVhcmlfTWFjaGlfQXByaWxpX01laV9KdW5pX0p1bGFpX0Fnb3N0aV9TZXB0ZW1iYV9Pa3RvYmFfTm92ZW1iYV9EZXNlbWJhJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hY19BcHJfTWVpX0p1bl9KdWxfQWdvX1NlcF9Pa3RfTm92X0Rlcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnSnVtYXBpbGlfSnVtYXRhdHVfSnVtYW5uZV9KdW1hdGFub19BbGhhbWlzaV9JanVtYWFfSnVtYW1vc2knLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnSnBsX0p0YXRfSm5uZV9KdGFuX0FsaF9Jam1fSm1vcycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnSjJfSjNfSjRfSjVfQWxfSWpfSjEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tsZW8gc2FhXSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1trZXNobyBzYWFdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ1t3aWtpIGlqYXlvXSBkZGRkIFtzYWF0XSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tqYW5hXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbd2lraSBpbGl5b3BpdGFdIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyBiYWFkYXllJyxcbiAgICAgICAgICAgIHBhc3QgOiAndG9rZWEgJXMnLFxuICAgICAgICAgICAgcyA6ICdoaXZpIHB1bmRlJyxcbiAgICAgICAgICAgIHNzIDogJ3Nla3VuZGUgJWQnLFxuICAgICAgICAgICAgbSA6ICdkYWtpa2EgbW9qYScsXG4gICAgICAgICAgICBtbSA6ICdkYWtpa2EgJWQnLFxuICAgICAgICAgICAgaCA6ICdzYWEgbGltb2phJyxcbiAgICAgICAgICAgIGhoIDogJ21hc2FhICVkJyxcbiAgICAgICAgICAgIGQgOiAnc2lrdSBtb2phJyxcbiAgICAgICAgICAgIGRkIDogJ21hc2lrdSAlZCcsXG4gICAgICAgICAgICBNIDogJ213ZXppIG1tb2phJyxcbiAgICAgICAgICAgIE1NIDogJ21pZXppICVkJyxcbiAgICAgICAgICAgIHkgOiAnbXdha2EgbW1vamEnLFxuICAgICAgICAgICAgeXkgOiAnbWlha2EgJWQnXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN5bWJvbE1hcCRmID0ge1xuICAgICAgICAnMSc6ICfgr6cnLFxuICAgICAgICAnMic6ICfgr6gnLFxuICAgICAgICAnMyc6ICfgr6knLFxuICAgICAgICAnNCc6ICfgr6onLFxuICAgICAgICAnNSc6ICfgr6snLFxuICAgICAgICAnNic6ICfgr6wnLFxuICAgICAgICAnNyc6ICfgr60nLFxuICAgICAgICAnOCc6ICfgr64nLFxuICAgICAgICAnOSc6ICfgr68nLFxuICAgICAgICAnMCc6ICfgr6YnXG4gICAgfSwgbnVtYmVyTWFwJGUgPSB7XG4gICAgICAgICfgr6cnOiAnMScsXG4gICAgICAgICfgr6gnOiAnMicsXG4gICAgICAgICfgr6knOiAnMycsXG4gICAgICAgICfgr6onOiAnNCcsXG4gICAgICAgICfgr6snOiAnNScsXG4gICAgICAgICfgr6wnOiAnNicsXG4gICAgICAgICfgr60nOiAnNycsXG4gICAgICAgICfgr64nOiAnOCcsXG4gICAgICAgICfgr68nOiAnOScsXG4gICAgICAgICfgr6YnOiAnMCdcbiAgICB9O1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0YScsIHtcbiAgICAgICAgbW9udGhzIDogJ+CunOCuqeCuteCusOCuv1/grqrgrr/grqrgr43grrDgrrXgrrDgrr9f4K6u4K6+4K6w4K+N4K6a4K+NX+Cuj+CuquCvjeCusOCusuCvjV/grq7gr4df4K6c4K+C4K6p4K+NX+CunOCvguCusuCviF/grobgrpXgrrjgr43grp/gr41f4K6a4K+G4K6q4K+N4K6f4K+G4K6u4K+N4K6q4K6w4K+NX+CuheCuleCvjeCun+Cvh+CuvuCuquCusOCvjV/grqjgrrXgrq7gr43grqrgrrDgr41f4K6f4K6/4K6a4K6u4K+N4K6q4K6w4K+NJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICfgrpzgrqngrrXgrrDgrr9f4K6q4K6/4K6q4K+N4K6w4K614K6w4K6/X+CuruCuvuCusOCvjeCumuCvjV/gro/grqrgr43grrDgrrLgr41f4K6u4K+HX+CunOCvguCuqeCvjV/grpzgr4LgrrLgr4hf4K6G4K6V4K644K+N4K6f4K+NX+CumuCvhuCuquCvjeCun+CvhuCuruCvjeCuquCusOCvjV/groXgrpXgr43grp/gr4fgrr7grqrgrrDgr41f4K6o4K614K6u4K+N4K6q4K6w4K+NX+Cun+Cuv+CumuCuruCvjeCuquCusOCvjScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAn4K6e4K6+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+IJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ+CunuCuvuCur+Cuv+CuseCvgV/grqTgrr/grpngr43grpXgrrPgr41f4K6a4K+G4K614K+N4K614K6+4K6v4K+NX+CuquCvgeCupOCuqeCvjV/grrXgrr/grq/grr7grrTgrqngr41f4K614K+G4K6z4K+N4K6z4K6/X+CumuCuqeCuvycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn4K6e4K6+X+CupOCuv1/grprgr4Zf4K6q4K+BX+CuteCuv1/grrXgr4Zf4K6aJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZLCBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1vgrofgrqngr43grrHgr4FdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW+CuqOCuvuCus+CviF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCwgTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb4K6o4K+H4K6x4K+N4K6x4K+BXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdb4K6V4K6f4K6o4K+N4K6kIOCuteCuvuCusOCuruCvjV0gZGRkZCwgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVzIOCuh+CusuCvjScsXG4gICAgICAgICAgICBwYXN0IDogJyVzIOCuruCvgeCuqeCvjScsXG4gICAgICAgICAgICBzIDogJ+CukuCusOCvgSDgrprgrr/grrIg4K614K6/4K6o4K6+4K6f4K6/4K6V4K6z4K+NJyxcbiAgICAgICAgICAgIHNzIDogJyVkIOCuteCuv+CuqOCuvuCun+Cuv+CuleCus+CvjScsXG4gICAgICAgICAgICBtIDogJ+CukuCusOCvgSDgrqjgrr/grq7grr/grp/grq7gr40nLFxuICAgICAgICAgICAgbW0gOiAnJWQg4K6o4K6/4K6u4K6/4K6f4K6Z4K+N4K6V4K6z4K+NJyxcbiAgICAgICAgICAgIGggOiAn4K6S4K6w4K+BIOCuruCuo+CuvyDgrqjgr4fgrrDgrq7gr40nLFxuICAgICAgICAgICAgaGggOiAnJWQg4K6u4K6j4K6/IOCuqOCvh+CusOCuruCvjScsXG4gICAgICAgICAgICBkIDogJ+CukuCusOCvgSDgrqjgrr7grrPgr40nLFxuICAgICAgICAgICAgZGQgOiAnJWQg4K6o4K6+4K6f4K+N4K6V4K6z4K+NJyxcbiAgICAgICAgICAgIE0gOiAn4K6S4K6w4K+BIOCuruCuvuCupOCuruCvjScsXG4gICAgICAgICAgICBNTSA6ICclZCDgrq7grr7grqTgrpngr43grpXgrrPgr40nLFxuICAgICAgICAgICAgeSA6ICfgrpLgrrDgr4Eg4K614K6w4K+B4K6f4K6u4K+NJyxcbiAgICAgICAgICAgIHl5IDogJyVkIOCuhuCuo+CvjeCun+CvgeCuleCus+CvjSdcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ94K614K6k4K+BLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn4K614K6k4K+BJztcbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Cvp+CvqOCvqeCvquCvq+CvrOCvreCvruCvr+Cvpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcCRlW21hdGNoXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwJGZbbWF0Y2hdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIC8vIHJlZmVyIGh0dHA6Ly90YS53aWtpcGVkaWEub3JnL3MvMWVyMVxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4K6v4K6+4K6u4K6u4K+NfOCuteCviOCuleCuseCviHzgrpXgrr7grrLgr4h84K6o4K6j4K+N4K6q4K6V4K6y4K+NfOCujuCuseCvjeCuquCuvuCun+CvgXzgrq7grr7grrLgr4gvLFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAnIOCur+CuvuCuruCuruCvjSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCA2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcg4K614K+I4K6V4K6x4K+IJzsgIC8vIOCuteCviOCuleCuseCviFxuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyDgrpXgrr7grrLgr4gnOyAvLyDgrpXgrr7grrLgr4hcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcg4K6o4K6j4K+N4K6q4K6V4K6y4K+NJzsgLy8g4K6o4K6j4K+N4K6q4K6V4K6y4K+NXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxOCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnIOCujuCuseCvjeCuquCuvuCun+CvgSc7IC8vIOCujuCuseCvjeCuquCuvuCun+CvgVxuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyDgrq7grr7grrLgr4gnOyAvLyDgrq7grr7grrLgr4hcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcg4K6v4K6+4K6u4K6u4K+NJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+Cur+CuvuCuruCuruCvjScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA8IDIgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CuteCviOCuleCuseCviCcgfHwgbWVyaWRpZW0gPT09ICfgrpXgrr7grrLgr4gnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4K6o4K6j4K+N4K6q4K6V4K6y4K+NJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNnRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3RlJywge1xuICAgICAgICBtb250aHMgOiAn4LCc4LCo4LC14LCw4LC/X+Cwq+Cwv+CwrOCxjeCwsOCwteCwsOCwv1/gsK7gsL7gsLDgsY3gsJrgsL9f4LCP4LCq4LGN4LCw4LC/4LCy4LGNX+CwruCxh1/gsJzgsYLgsKjgsY1f4LCc4LGB4LCy4LGIX+CwhuCwl+CwuOCxjeCwn+CxgV/gsLjgsYbgsKrgsY3gsJ/gsYbgsILgsKzgsLDgsY1f4LCF4LCV4LGN4LCf4LGL4LCs4LCw4LGNX+CwqOCwteCwguCwrOCwsOCxjV/gsKHgsL/gsLjgsYbgsILgsKzgsLDgsY0nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ+CwnOCwqC5f4LCr4LC/4LCs4LGN4LCwLl/gsK7gsL7gsLDgsY3gsJrgsL9f4LCP4LCq4LGN4LCw4LC/Ll/gsK7gsYdf4LCc4LGC4LCo4LGNX+CwnOCxgeCwsuCxiF/gsIbgsJcuX+CwuOCxhuCwquCxjS5f4LCF4LCV4LGN4LCf4LGLLl/gsKjgsLUuX+CwoeCwv+CwuOCxhi4nLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICfgsIbgsKbgsL/gsLXgsL7gsLDgsIJf4LC44LGL4LCu4LC14LC+4LCw4LCCX+CwruCwguCwl+Cws+CwteCwvuCwsOCwgl/gsKzgsYHgsKfgsLXgsL7gsLDgsIJf4LCX4LGB4LCw4LGB4LC14LC+4LCw4LCCX+CwtuCxgeCwleCxjeCwsOCwteCwvuCwsOCwgl/gsLbgsKjgsL/gsLXgsL7gsLDgsIInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn4LCG4LCm4LC/X+CwuOCxi+Cwrl/gsK7gsILgsJfgsLNf4LCs4LGB4LCnX+Cwl+CxgeCwsOCxgV/gsLbgsYHgsJXgsY3gsLBf4LC24LCo4LC/Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfgsIZf4LC44LGLX+CwruCwgl/gsKzgsYFf4LCX4LGBX+CwtuCxgV/gsLYnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnQSBoOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdBIGg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1vgsKjgsYfgsKHgsYFdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW+CwsOCxh+CwquCxgV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCwgTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb4LCo4LC/4LCo4LGN4LCoXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdb4LCX4LCkXSBkZGRkLCBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnJXMg4LCy4LGLJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMg4LCV4LGN4LCw4LC/4LCk4LCCJyxcbiAgICAgICAgICAgIHMgOiAn4LCV4LGK4LCo4LGN4LCo4LC/IOCwleCxjeCwt+Cwo+CwvuCwsuCxgScsXG4gICAgICAgICAgICBzcyA6ICclZCDgsLjgsYbgsJXgsKjgsY3gsLLgsYEnLFxuICAgICAgICAgICAgbSA6ICfgsJLgsJUg4LCo4LC/4LCu4LC/4LC34LCCJyxcbiAgICAgICAgICAgIG1tIDogJyVkIOCwqOCwv+CwruCwv+Cwt+CwvuCwsuCxgScsXG4gICAgICAgICAgICBoIDogJ+CwkuCwlSDgsJfgsILgsJ8nLFxuICAgICAgICAgICAgaGggOiAnJWQg4LCX4LCC4LCf4LCy4LGBJyxcbiAgICAgICAgICAgIGQgOiAn4LCS4LCVIOCwsOCxi+CwnOCxgScsXG4gICAgICAgICAgICBkZCA6ICclZCDgsLDgsYvgsJzgsYHgsLLgsYEnLFxuICAgICAgICAgICAgTSA6ICfgsJLgsJUg4LCo4LGG4LCyJyxcbiAgICAgICAgICAgIE1NIDogJyVkIOCwqOCxhuCwsuCwsuCxgScsXG4gICAgICAgICAgICB5IDogJ+CwkuCwlSDgsLjgsILgsLXgsKTgsY3gsLjgsLDgsIInLFxuICAgICAgICAgICAgeXkgOiAnJWQg4LC44LCC4LC14LCk4LGN4LC44LCw4LC+4LCy4LGBJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ94LC1LyxcbiAgICAgICAgb3JkaW5hbCA6ICclZOCwtScsXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/gsLDgsL7gsKTgsY3gsLDgsL984LCJ4LCm4LCv4LCCfOCwruCwp+CxjeCwr+CwvuCwueCxjeCwqOCwgnzgsLjgsL7gsK/gsILgsKTgsY3gsLDgsIIvLFxuICAgICAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4LCw4LC+4LCk4LGN4LCw4LC/Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LCJ4LCm4LCv4LCCJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CwruCwp+CxjeCwr+CwvuCwueCxjeCwqOCwgicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LC44LC+4LCv4LCC4LCk4LGN4LCw4LCCJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgsLDgsL7gsKTgsY3gsLDgsL8nO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CwieCwpuCwr+Cwgic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn4LCu4LCn4LGN4LCv4LC+4LC54LGN4LCo4LCCJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfgsLjgsL7gsK/gsILgsKTgsY3gsLDgsIInO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+CwsOCwvuCwpOCxjeCwsOCwvyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0ZXQnLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW5laXJ1X0ZldmVyZWlydV9NYXJzdV9BYnJpbF9NYWl1X0p1w7F1X0p1bGx1X0FndXN0dV9TZXRlbWJydV9PdXR1YnJ1X05vdmVtYnJ1X0RlemVtYnJ1Jy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKYW5fRmV2X01hcl9BYnJfTWFpX0p1bl9KdWxfQWdvX1NldF9PdXRfTm92X0Rleicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnRG9taW5ndV9TZWd1bmRhX1RlcnNhX0t1YXJ0YV9LaW50YV9TZXN0YV9TYWJhZHUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnRG9tX1NlZ19UZXJzX0t1YV9LaW50X1Nlc3RfU2FiJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdEb19TZWdfVGVfS3VfS2lfU2VzX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheTogJ1tPaGluIGloYV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tBYmFuIGloYV0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtpaGFdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdbSG9yaXNlaWsgaWhhXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW3NlbWFuYSBrb3R1a10gW2loYV0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnaWhhICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMgbGl1YmEnLFxuICAgICAgICAgICAgcyA6ICdtaW51dHUgYmFsdW4nLFxuICAgICAgICAgICAgc3MgOiAnbWludXR1ICVkJyxcbiAgICAgICAgICAgIG0gOiAnbWludXR1IGlkYScsXG4gICAgICAgICAgICBtbSA6ICdtaW51dHUgJWQnLFxuICAgICAgICAgICAgaCA6ICdvcmFzIGlkYScsXG4gICAgICAgICAgICBoaCA6ICdvcmFzICVkJyxcbiAgICAgICAgICAgIGQgOiAnbG9yb24gaWRhJyxcbiAgICAgICAgICAgIGRkIDogJ2xvcm9uICVkJyxcbiAgICAgICAgICAgIE0gOiAnZnVsYW4gaWRhJyxcbiAgICAgICAgICAgIE1NIDogJ2Z1bGFuICVkJyxcbiAgICAgICAgICAgIHkgOiAndGluYW4gaWRhJyxcbiAgICAgICAgICAgIHl5IDogJ3RpbmFuICVkJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAndGgnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMykgPyAncmQnIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgdmFyIHN1ZmZpeGVzJDMgPSB7XG4gICAgICAgIDA6ICct0YPQvCcsXG4gICAgICAgIDE6ICct0YPQvCcsXG4gICAgICAgIDI6ICct0Y7QvCcsXG4gICAgICAgIDM6ICct0Y7QvCcsXG4gICAgICAgIDQ6ICct0YPQvCcsXG4gICAgICAgIDU6ICct0YPQvCcsXG4gICAgICAgIDY6ICct0YPQvCcsXG4gICAgICAgIDc6ICct0YPQvCcsXG4gICAgICAgIDg6ICct0YPQvCcsXG4gICAgICAgIDk6ICct0YPQvCcsXG4gICAgICAgIDEwOiAnLdGD0LwnLFxuICAgICAgICAxMjogJy3Rg9C8JyxcbiAgICAgICAgMTM6ICct0YPQvCcsXG4gICAgICAgIDIwOiAnLdGD0LwnLFxuICAgICAgICAzMDogJy3RjtC8JyxcbiAgICAgICAgNDA6ICct0YPQvCcsXG4gICAgICAgIDUwOiAnLdGD0LwnLFxuICAgICAgICA2MDogJy3Rg9C8JyxcbiAgICAgICAgNzA6ICct0YPQvCcsXG4gICAgICAgIDgwOiAnLdGD0LwnLFxuICAgICAgICA5MDogJy3Rg9C8JyxcbiAgICAgICAgMTAwOiAnLdGD0LwnXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndGcnLCB7XG4gICAgICAgIG1vbnRocyA6ICfRj9C90LLQsNGAX9GE0LXQstGA0LDQu1/QvNCw0YDRgl/QsNC/0YDQtdC7X9C80LDQuV/QuNGO0L1f0LjRjtC7X9Cw0LLQs9GD0YHRgl/RgdC10L3RgtGP0LHRgF/QvtC60YLRj9Cx0YBf0L3QvtGP0LHRgF/QtNC10LrQsNCx0YAnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ9GP0L3Qsl/RhNC10LJf0LzQsNGAX9Cw0L/RgF/QvNCw0Llf0LjRjtC9X9C40Y7Qu1/QsNCy0LNf0YHQtdC9X9C+0LrRgl/QvdC+0Y9f0LTQtdC6Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfRj9C60YjQsNC90LHQtV/QtNGD0YjQsNC90LHQtV/RgdC10YjQsNC90LHQtV/Rh9C+0YDRiNCw0L3QsdC1X9C/0LDQvdK30YjQsNC90LHQtV/St9GD0LzRitCwX9GI0LDQvdCx0LUnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn0Y/RiNCxX9C00YjQsV/RgdGI0LFf0YfRiNCxX9C/0YjQsV/St9GD0Lxf0YjQvdCxJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfRj9GIX9C00Yhf0YHRiF/Rh9GIX9C/0Yhf0rfQvF/RiNCxJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb0JjQvNGA06/QtyDRgdC+0LDRgtC4XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vQn9Cw0LPQvtKzINGB0L7QsNGC0LhdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW9CU0LjRgNOv0Lcg0YHQvtCw0YLQuF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZFvQuF0gW9Kz0LDRhNGC0LDQuCDQvtGP0L3QtNCwINGB0L7QsNGC0LhdIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ2RkZGRb0LhdIFvSs9Cw0YTRgtCw0Lgg0LPRg9C30LDRiNGC0LAg0YHQvtCw0YLQuF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ9Cx0LDRitC00LggJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyDQv9C10YgnLFxuICAgICAgICAgICAgcyA6ICfRj9C60YfQsNC90LQg0YHQvtC90LjRjycsXG4gICAgICAgICAgICBtIDogJ9GP0Log0LTQsNKb0LjSm9CwJyxcbiAgICAgICAgICAgIG1tIDogJyVkINC00LDSm9C40pvQsCcsXG4gICAgICAgICAgICBoIDogJ9GP0Log0YHQvtCw0YInLFxuICAgICAgICAgICAgaGggOiAnJWQg0YHQvtCw0YInLFxuICAgICAgICAgICAgZCA6ICfRj9C6INGA06/QtycsXG4gICAgICAgICAgICBkZCA6ICclZCDRgNOv0LcnLFxuICAgICAgICAgICAgTSA6ICfRj9C6INC80L7SsycsXG4gICAgICAgICAgICBNTSA6ICclZCDQvNC+0rMnLFxuICAgICAgICAgICAgeSA6ICfRj9C6INGB0L7QuycsXG4gICAgICAgICAgICB5eSA6ICclZCDRgdC+0LsnXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/RiNCw0LF80YHRg9Cx0rN80YDTr9C3fNCx0LXQs9C+0rMvLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfRiNCw0LEnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfRgdGD0LHSsycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfRgNOv0LcnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ9Cx0LXQs9C+0rMnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0YjQsNCxJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfRgdGD0LHSsyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0YDTr9C3JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfQsdC10LPQvtKzJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfRiNCw0LEnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNGD0Lx80Y7QvCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIGIgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAoc3VmZml4ZXMkM1tudW1iZXJdIHx8IHN1ZmZpeGVzJDNbYV0gfHwgc3VmZml4ZXMkM1tiXSk7XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDF0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0aCcsIHtcbiAgICAgICAgbW9udGhzIDogJ+C4oeC4geC4o+C4suC4hOC4oV/guIHguLjguKHguKDguLLguJ7guLHguJnguJjguYxf4Lih4Li14LiZ4Liy4LiE4LihX+C5gOC4oeC4qeC4suC4ouC4mV/guJ7guKTguKnguKDguLLguITguKFf4Lih4Li04LiW4Li44LiZ4Liy4Lii4LiZX+C4geC4o+C4geC4juC4suC4hOC4oV/guKrguLTguIfguKvguLLguITguKFf4LiB4Lix4LiZ4Lii4Liy4Lii4LiZX+C4leC4uOC4peC4suC4hOC4oV/guJ7guKTguKjguIjguLTguIHguLLguKLguJlf4LiY4Lix4LiZ4Lin4Liy4LiE4LihJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICfguKEu4LiELl/guIEu4LieLl/guKHguLUu4LiELl/guYDguKEu4LiiLl/guJ4u4LiELl/guKHguLQu4LiiLl/guIEu4LiELl/guKou4LiELl/guIEu4LiiLl/guJUu4LiELl/guJ4u4LiiLl/guJgu4LiELicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXMgOiAn4Lit4Liy4LiX4Li04LiV4Lii4LmMX+C4iOC4seC4meC4l+C4o+C5jF/guK3guLHguIfguITguLLguKNf4Lie4Li44LiYX+C4nuC4pOC4q+C4seC4quC4muC4lOC4tV/guKjguLjguIHguKPguYxf4LmA4Liq4Liy4Lij4LmMJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ+C4reC4suC4l+C4tOC4leC4ouC5jF/guIjguLHguJnguJfguKPguYxf4Lit4Lix4LiH4LiE4Liy4LijX+C4nuC4uOC4mF/guJ7guKTguKvguLHguKpf4Lio4Li44LiB4Lij4LmMX+C5gOC4quC4suC4o+C5jCcuc3BsaXQoJ18nKSwgLy8geWVzLCB0aHJlZSBjaGFyYWN0ZXJzIGRpZmZlcmVuY2VcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn4Lit4LiyLl/guIguX+C4rS5f4LieLl/guJ7guKQuX+C4qC5f4LiqLicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkg4LmA4Lin4Lil4LiyIEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICfguKfguLHguJlkZGRk4LiX4Li14LmIIEQgTU1NTSBZWVlZIOC5gOC4p+C4peC4siBIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv4LiB4LmI4Lit4LiZ4LmA4LiX4Li14LmI4Lii4LiHfOC4q+C4peC4seC4h+C5gOC4l+C4teC5iOC4ouC4hy8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn4Lir4Lil4Lix4LiH4LmA4LiX4Li14LmI4Lii4LiHJztcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfguIHguYjguK3guJnguYDguJfguLXguYjguKLguIcnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+C4q+C4peC4seC4h+C5gOC4l+C4teC5iOC4ouC4hyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb4Lin4Lix4LiZ4LiZ4Li14LmJIOC5gOC4p+C4peC4sl0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb4Lie4Lij4Li44LmI4LiH4LiZ4Li14LmJIOC5gOC4p+C4peC4sl0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZFvguKvguJnguYnguLIg4LmA4Lin4Lil4LiyXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1vguYDguKHguLfguYjguK3guKfguLLguJnguJnguLXguYkg4LmA4Lin4Lil4LiyXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdb4Lin4Lix4LiZXWRkZGRb4LiX4Li14LmI4LmB4Lil4LmJ4LinIOC5gOC4p+C4peC4sl0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ+C4reC4teC4gSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJyVz4LiX4Li14LmI4LmB4Lil4LmJ4LinJyxcbiAgICAgICAgICAgIHMgOiAn4LmE4Lih4LmI4LiB4Li14LmI4Lin4Li04LiZ4Liy4LiX4Li1JyxcbiAgICAgICAgICAgIHNzIDogJyVkIOC4p+C4tOC4meC4suC4l+C4tScsXG4gICAgICAgICAgICBtIDogJzEg4LiZ4Liy4LiX4Li1JyxcbiAgICAgICAgICAgIG1tIDogJyVkIOC4meC4suC4l+C4tScsXG4gICAgICAgICAgICBoIDogJzEg4LiK4Lix4LmI4Lin4LmC4Lih4LiHJyxcbiAgICAgICAgICAgIGhoIDogJyVkIOC4iuC4seC5iOC4p+C5guC4oeC4hycsXG4gICAgICAgICAgICBkIDogJzEg4Lin4Lix4LiZJyxcbiAgICAgICAgICAgIGRkIDogJyVkIOC4p+C4seC4mScsXG4gICAgICAgICAgICBNIDogJzEg4LmA4LiU4Li34Lit4LiZJyxcbiAgICAgICAgICAgIE1NIDogJyVkIOC5gOC4lOC4t+C4reC4mScsXG4gICAgICAgICAgICB5IDogJzEg4Lib4Li1JyxcbiAgICAgICAgICAgIHl5IDogJyVkIOC4m+C4tSdcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0bC1waCcsIHtcbiAgICAgICAgbW9udGhzIDogJ0VuZXJvX1BlYnJlcm9fTWFyc29fQWJyaWxfTWF5b19IdW55b19IdWx5b19BZ29zdG9fU2V0eWVtYnJlX09rdHVicmVfTm9ieWVtYnJlX0Rpc3llbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnRW5lX1BlYl9NYXJfQWJyX01heV9IdW5fSHVsX0Fnb19TZXRfT2t0X05vYl9EaXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ0xpbmdnb19MdW5lc19NYXJ0ZXNfTWl5ZXJrdWxlc19IdXdlYmVzX0JpeWVybmVzX1NhYmFkbycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdMaW5fTHVuX01hcl9NaXlfSHV3X0JpeV9TYWInLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ0xpX0x1X01hX01pX0h1X0JpX1NhYicuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdNTS9EL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdNTU1NIEQsIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBNTU1NIERELCBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdMVCBbbmdheW9uZyBhcmF3XScsXG4gICAgICAgICAgICBuZXh0RGF5OiAnW0J1a2FzIG5nXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ0xUIFtzYSBzdXN1bm9kIG5hXSBkZGRkJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdMVCBba2FoYXBvbl0nLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdMVCBbbm9vbmcgbmFrYXJhYW5nXSBkZGRkJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ3NhIGxvb2IgbmcgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyBhbmcgbmFrYWxpcGFzJyxcbiAgICAgICAgICAgIHMgOiAnaWxhbmcgc2VndW5kbycsXG4gICAgICAgICAgICBzcyA6ICclZCBzZWd1bmRvJyxcbiAgICAgICAgICAgIG0gOiAnaXNhbmcgbWludXRvJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1pbnV0bycsXG4gICAgICAgICAgICBoIDogJ2lzYW5nIG9yYXMnLFxuICAgICAgICAgICAgaGggOiAnJWQgb3JhcycsXG4gICAgICAgICAgICBkIDogJ2lzYW5nIGFyYXcnLFxuICAgICAgICAgICAgZGQgOiAnJWQgYXJhdycsXG4gICAgICAgICAgICBNIDogJ2lzYW5nIGJ1d2FuJyxcbiAgICAgICAgICAgIE1NIDogJyVkIGJ1d2FuJyxcbiAgICAgICAgICAgIHkgOiAnaXNhbmcgdGFvbicsXG4gICAgICAgICAgICB5eSA6ICclZCB0YW9uJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0vLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbnVtYmVyc05vdW5zID0gJ3BhZ2hfd2HigJlfY2hh4oCZX3dlal9sb1NfdmFnaF9qYXZfU29jaF9jaG9yZ2hfSHV0Jy5zcGxpdCgnXycpO1xuXG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlRnV0dXJlKG91dHB1dCkge1xuICAgICAgICB2YXIgdGltZSA9IG91dHB1dDtcbiAgICAgICAgdGltZSA9IChvdXRwdXQuaW5kZXhPZignamFqJykgIT09IC0xKSA/XG4gICAgICAgIHRpbWUuc2xpY2UoMCwgLTMpICsgJ2xlUycgOlxuICAgICAgICAob3V0cHV0LmluZGV4T2YoJ2phcicpICE9PSAtMSkgP1xuICAgICAgICB0aW1lLnNsaWNlKDAsIC0zKSArICd3YVEnIDpcbiAgICAgICAgKG91dHB1dC5pbmRleE9mKCdESVMnKSAhPT0gLTEpID9cbiAgICAgICAgdGltZS5zbGljZSgwLCAtMykgKyAnbmVtJyA6XG4gICAgICAgIHRpbWUgKyAnIHBJcSc7XG4gICAgICAgIHJldHVybiB0aW1lO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZVBhc3Qob3V0cHV0KSB7XG4gICAgICAgIHZhciB0aW1lID0gb3V0cHV0O1xuICAgICAgICB0aW1lID0gKG91dHB1dC5pbmRleE9mKCdqYWonKSAhPT0gLTEpID9cbiAgICAgICAgdGltZS5zbGljZSgwLCAtMykgKyAnSHXigJknIDpcbiAgICAgICAgKG91dHB1dC5pbmRleE9mKCdqYXInKSAhPT0gLTEpID9cbiAgICAgICAgdGltZS5zbGljZSgwLCAtMykgKyAnd2VuJyA6XG4gICAgICAgIChvdXRwdXQuaW5kZXhPZignRElTJykgIT09IC0xKSA/XG4gICAgICAgIHRpbWUuc2xpY2UoMCwgLTMpICsgJ2JlbicgOlxuICAgICAgICB0aW1lICsgJyByZXQnO1xuICAgICAgICByZXR1cm4gdGltZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmFuc2xhdGUkYShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIG51bWJlck5vdW4gPSBudW1iZXJBc05vdW4obnVtYmVyKTtcbiAgICAgICAgc3dpdGNoIChzdHJpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgbHVwJztcbiAgICAgICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgdHVwJztcbiAgICAgICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgcmVwJztcbiAgICAgICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgamFqJztcbiAgICAgICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgamFyJztcbiAgICAgICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgRElTJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG51bWJlckFzTm91bihudW1iZXIpIHtcbiAgICAgICAgdmFyIGh1bmRyZWQgPSBNYXRoLmZsb29yKChudW1iZXIgJSAxMDAwKSAvIDEwMCksXG4gICAgICAgIHRlbiA9IE1hdGguZmxvb3IoKG51bWJlciAlIDEwMCkgLyAxMCksXG4gICAgICAgIG9uZSA9IG51bWJlciAlIDEwLFxuICAgICAgICB3b3JkID0gJyc7XG4gICAgICAgIGlmIChodW5kcmVkID4gMCkge1xuICAgICAgICAgICAgd29yZCArPSBudW1iZXJzTm91bnNbaHVuZHJlZF0gKyAndmF0bGgnO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0ZW4gPiAwKSB7XG4gICAgICAgICAgICB3b3JkICs9ICgod29yZCAhPT0gJycpID8gJyAnIDogJycpICsgbnVtYmVyc05vdW5zW3Rlbl0gKyAnbWFIJztcbiAgICAgICAgfVxuICAgICAgICBpZiAob25lID4gMCkge1xuICAgICAgICAgICAgd29yZCArPSAoKHdvcmQgIT09ICcnKSA/ICcgJyA6ICcnKSArIG51bWJlcnNOb3Vuc1tvbmVdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAod29yZCA9PT0gJycpID8gJ3BhZ2gnIDogd29yZDtcbiAgICB9XG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3RsaCcsIHtcbiAgICAgICAgbW9udGhzIDogJ3RlcmHigJkgamFyIHdh4oCZX3RlcmHigJkgamFyIGNoYeKAmV90ZXJh4oCZIGphciB3ZWpfdGVyYeKAmSBqYXIgbG9TX3RlcmHigJkgamFyIHZhZ2hfdGVyYeKAmSBqYXIgamF2X3RlcmHigJkgamFyIFNvY2hfdGVyYeKAmSBqYXIgY2hvcmdoX3RlcmHigJkgamFyIEh1dF90ZXJh4oCZIGphciB3YeKAmW1hSF90ZXJh4oCZIGphciB3YeKAmW1hSCB3YeKAmV90ZXJh4oCZIGphciB3YeKAmW1hSCBjaGHigJknLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ2phciB3YeKAmV9qYXIgY2hh4oCZX2phciB3ZWpfamFyIGxvU19qYXIgdmFnaF9qYXIgamF2X2phciBTb2NoX2phciBjaG9yZ2hfamFyIEh1dF9qYXIgd2HigJltYUhfamFyIHdh4oCZbWFIIHdh4oCZX2phciB3YeKAmW1hSCBjaGHigJknLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdsb2ptSXRqYWpfRGFTamFqX3Bvdmphal9naEl0bGhqYWpfbG9naGphal9idXFqYWpfZ2hJbmphaicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdsb2ptSXRqYWpfRGFTamFqX3Bvdmphal9naEl0bGhqYWpfbG9naGphal9idXFqYWpfZ2hJbmphaicuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnbG9qbUl0amFqX0RhU2phal9wb3ZqYWpfZ2hJdGxoamFqX2xvZ2hqYWpfYnVxamFqX2doSW5qYWonLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW0RhSGphal0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1t3YeKAmWxlU10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdMTEwnLFxuICAgICAgICAgICAgbGFzdERheTogJ1t3YeKAmUh14oCZXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ0xMTCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6IHRyYW5zbGF0ZUZ1dHVyZSxcbiAgICAgICAgICAgIHBhc3QgOiB0cmFuc2xhdGVQYXN0LFxuICAgICAgICAgICAgcyA6ICdwdVMgbHVwJyxcbiAgICAgICAgICAgIHNzIDogdHJhbnNsYXRlJGEsXG4gICAgICAgICAgICBtIDogJ3dh4oCZIHR1cCcsXG4gICAgICAgICAgICBtbSA6IHRyYW5zbGF0ZSRhLFxuICAgICAgICAgICAgaCA6ICd3YeKAmSByZXAnLFxuICAgICAgICAgICAgaGggOiB0cmFuc2xhdGUkYSxcbiAgICAgICAgICAgIGQgOiAnd2HigJkgamFqJyxcbiAgICAgICAgICAgIGRkIDogdHJhbnNsYXRlJGEsXG4gICAgICAgICAgICBNIDogJ3dh4oCZIGphcicsXG4gICAgICAgICAgICBNTSA6IHRyYW5zbGF0ZSRhLFxuICAgICAgICAgICAgeSA6ICd3YeKAmSBESVMnLFxuICAgICAgICAgICAgeXkgOiB0cmFuc2xhdGUkYVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgICAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIHN1ZmZpeGVzJDQgPSB7XG4gICAgICAgIDE6ICdcXCdpbmNpJyxcbiAgICAgICAgNTogJ1xcJ2luY2knLFxuICAgICAgICA4OiAnXFwnaW5jaScsXG4gICAgICAgIDcwOiAnXFwnaW5jaScsXG4gICAgICAgIDgwOiAnXFwnaW5jaScsXG4gICAgICAgIDI6ICdcXCduY2knLFxuICAgICAgICA3OiAnXFwnbmNpJyxcbiAgICAgICAgMjA6ICdcXCduY2knLFxuICAgICAgICA1MDogJ1xcJ25jaScsXG4gICAgICAgIDM6ICdcXCfDvG5jw7wnLFxuICAgICAgICA0OiAnXFwnw7xuY8O8JyxcbiAgICAgICAgMTAwOiAnXFwnw7xuY8O8JyxcbiAgICAgICAgNjogJ1xcJ25jxLEnLFxuICAgICAgICA5OiAnXFwndW5jdScsXG4gICAgICAgIDEwOiAnXFwndW5jdScsXG4gICAgICAgIDMwOiAnXFwndW5jdScsXG4gICAgICAgIDYwOiAnXFwnxLFuY8SxJyxcbiAgICAgICAgOTA6ICdcXCfEsW5jxLEnXG4gICAgfTtcblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndHInLCB7XG4gICAgICAgIG1vbnRocyA6ICdPY2FrX8WedWJhdF9NYXJ0X05pc2FuX01hecSxc19IYXppcmFuX1RlbW11el9BxJ91c3Rvc19FeWzDvGxfRWtpbV9LYXPEsW1fQXJhbMSxaycuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnT2NhX8WedWJfTWFyX05pc19NYXlfSGF6X1RlbV9BxJ91X0V5bF9Fa2lfS2FzX0FyYScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnUGF6YXJfUGF6YXJ0ZXNpX1NhbMSxX8OHYXLFn2FtYmFfUGVyxZ9lbWJlX0N1bWFfQ3VtYXJ0ZXNpJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ1Bhel9QdHNfU2FsX8OHYXJfUGVyX0N1bV9DdHMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1B6X1B0X1NhX8OHYV9QZV9DdV9DdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW2J1Z8O8biBzYWF0XSBMVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1t5YXLEsW4gc2FhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnW2dlbGVjZWtdIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW2TDvG5dIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1tnZcOnZW5dIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyBzb25yYScsXG4gICAgICAgICAgICBwYXN0IDogJyVzIMO2bmNlJyxcbiAgICAgICAgICAgIHMgOiAnYmlya2HDpyBzYW5peWUnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc2FuaXllJyxcbiAgICAgICAgICAgIG0gOiAnYmlyIGRha2lrYScsXG4gICAgICAgICAgICBtbSA6ICclZCBkYWtpa2EnLFxuICAgICAgICAgICAgaCA6ICdiaXIgc2FhdCcsXG4gICAgICAgICAgICBoaCA6ICclZCBzYWF0JyxcbiAgICAgICAgICAgIGQgOiAnYmlyIGfDvG4nLFxuICAgICAgICAgICAgZGQgOiAnJWQgZ8O8bicsXG4gICAgICAgICAgICBNIDogJ2JpciBheScsXG4gICAgICAgICAgICBNTSA6ICclZCBheScsXG4gICAgICAgICAgICB5IDogJ2JpciB5xLFsJyxcbiAgICAgICAgICAgIHl5IDogJyVkIHnEsWwnXG4gICAgICAgIH0sXG4gICAgICAgIG9yZGluYWw6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICBjYXNlICdEbyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnREQnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDApIHsgIC8vIHNwZWNpYWwgY2FzZSBmb3IgemVyb1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICdcXCfEsW5jxLEnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgICAgICAgICBiID0gbnVtYmVyICUgMTAwIC0gYSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChzdWZmaXhlcyQ0W2FdIHx8IHN1ZmZpeGVzJDRbYl0gfHwgc3VmZml4ZXMkNFtjXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgLy8gQWZ0ZXIgdGhlIHllYXIgdGhlcmUgc2hvdWxkIGJlIGEgc2xhc2ggYW5kIHRoZSBhbW91bnQgb2YgeWVhcnMgc2luY2UgRGVjZW1iZXIgMjYsIDE5NzkgaW4gUm9tYW4gbnVtZXJhbHMuXG4gICAgLy8gVGhpcyBpcyBjdXJyZW50bHkgdG9vIGRpZmZpY3VsdCAobWF5YmUgZXZlbiBpbXBvc3NpYmxlKSB0byBhZGQuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0emwnLCB7XG4gICAgICAgIG1vbnRocyA6ICdKYW51YXJfRmV2cmFnbGhfTWFyw6dfQXZyw691X01haV9Hw7xuX0p1bGlhX0d1c2NodF9TZXRlbXZhcl9MaXN0b3DDpHRzX05vZW12YXJfWmVjZW12YXInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZXZfTWFyX0F2cl9NYWlfR8O8bl9KdWxfR3VzX1NldF9MaXNfTm9lX1plYycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnU8O6bGFkaV9Mw7puZcOnaV9NYWl0emlfTcOhcmN1cmlfWGjDumFkaV9WacOpbmVyw6dpX1PDoXR1cmknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnU8O6bF9Mw7puX01haV9Nw6FyX1how7pfVmnDqV9Tw6F0Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdTw7pfTMO6X01hX03DoV9YaF9WaV9Tw6EnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEgubW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hILm1tLnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdELiBNTU1NIFtkYWxsYXNdIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QuIE1NTU0gW2RhbGxhc10gWVlZWSBISC5tbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIFtsaV0gRC4gTU1NTSBbZGFsbGFzXSBZWVlZIEhILm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAvZFxcJ298ZFxcJ2EvaSxcbiAgICAgICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuICdkXFwnbycgPT09IGlucHV0LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2RcXCdvJyA6ICdEXFwnTyc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2RcXCdhJyA6ICdEXFwnQSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbb3hoaSDDoF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbZGVtw6Agw6BdIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW8OgXSBMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tpZWlyaSDDoF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW3PDvHIgZWxdIGRkZGQgW2xhc3RldSDDoF0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ29zcHJlaSAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ2phJXMnLFxuICAgICAgICAgICAgcyA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIHNzIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIG1tIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgaCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIGhoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIGRkIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIE1NIDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3LFxuICAgICAgICAgICAgeSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUkNyxcbiAgICAgICAgICAgIHl5IDogcHJvY2Vzc1JlbGF0aXZlVGltZSQ3XG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lJDcobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICAncyc6IFsndmllbnNhcyBzZWN1bmRzJywgJ1xcJ2llbnNhcyBzZWN1bmRzJ10sXG4gICAgICAgICAgICAnc3MnOiBbbnVtYmVyICsgJyBzZWN1bmRzJywgJycgKyBudW1iZXIgKyAnIHNlY3VuZHMnXSxcbiAgICAgICAgICAgICdtJzogWydcXCduIG3DrXV0JywgJ1xcJ2llbnMgbcOtdXQnXSxcbiAgICAgICAgICAgICdtbSc6IFtudW1iZXIgKyAnIG3DrXV0cycsICcnICsgbnVtYmVyICsgJyBtw611dHMnXSxcbiAgICAgICAgICAgICdoJzogWydcXCduIMO+b3JhJywgJ1xcJ2llbnNhIMO+b3JhJ10sXG4gICAgICAgICAgICAnaGgnOiBbbnVtYmVyICsgJyDDvm9yYXMnLCAnJyArIG51bWJlciArICcgw75vcmFzJ10sXG4gICAgICAgICAgICAnZCc6IFsnXFwnbiB6aXVhJywgJ1xcJ2llbnNhIHppdWEnXSxcbiAgICAgICAgICAgICdkZCc6IFtudW1iZXIgKyAnIHppdWFzJywgJycgKyBudW1iZXIgKyAnIHppdWFzJ10sXG4gICAgICAgICAgICAnTSc6IFsnXFwnbiBtZXMnLCAnXFwnaWVucyBtZXMnXSxcbiAgICAgICAgICAgICdNTSc6IFtudW1iZXIgKyAnIG1lc2VuJywgJycgKyBudW1iZXIgKyAnIG1lc2VuJ10sXG4gICAgICAgICAgICAneSc6IFsnXFwnbiBhcicsICdcXCdpZW5zIGFyJ10sXG4gICAgICAgICAgICAneXknOiBbbnVtYmVyICsgJyBhcnMnLCAnJyArIG51bWJlciArICcgYXJzJ11cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gZm9ybWF0W2tleV1bMF0gOiAod2l0aG91dFN1ZmZpeCA/IGZvcm1hdFtrZXldWzBdIDogZm9ybWF0W2tleV1bMV0pO1xuICAgIH1cblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndHptLWxhdG4nLCB7XG4gICAgICAgIG1vbnRocyA6ICdpbm5heXJfYnLLpGF5csukX21hcsukc8ukX2licmlyX21heXl3X3l3bnl3X3l3bHl3el/Jo3fFoXRfxaF3dGFuYmlyX2t0y6R3YnLLpF9ud3dhbmJpcl9kd2puYmlyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdpbm5heXJfYnLLpGF5csukX21hcsukc8ukX2licmlyX21heXl3X3l3bnl3X3l3bHl3el/Jo3fFoXRfxaF3dGFuYmlyX2t0y6R3YnLLpF9ud3dhbmJpcl9kd2puYmlyJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdhc2FtYXNfYXluYXNfYXNpbmFzX2FrcmFzX2Frd2FzX2FzaW13YXNfYXNp4biNeWFzJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ2FzYW1hc19heW5hc19hc2luYXNfYWtyYXNfYWt3YXNfYXNpbXdhc19hc2nhuI15YXMnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ2FzYW1hc19heW5hc19hc2luYXNfYWtyYXNfYWt3YXNfYXNpbXdhc19hc2nhuI15YXMnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbYXNka2ggZ10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1thc2thIGddIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrOiAnZGRkZCBbZ10gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1thc3NhbnQgZ10gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFtnXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICdkYWRraCBzIHlhbiAlcycsXG4gICAgICAgICAgICBwYXN0IDogJ3lhbiAlcycsXG4gICAgICAgICAgICBzIDogJ2ltaWsnLFxuICAgICAgICAgICAgc3MgOiAnJWQgaW1paycsXG4gICAgICAgICAgICBtIDogJ21pbnXhuI0nLFxuICAgICAgICAgICAgbW0gOiAnJWQgbWludeG4jScsXG4gICAgICAgICAgICBoIDogJ3NhyZthJyxcbiAgICAgICAgICAgIGhoIDogJyVkIHRhc3NhyZtpbicsXG4gICAgICAgICAgICBkIDogJ2FzcycsXG4gICAgICAgICAgICBkZCA6ICclZCBvc3NhbicsXG4gICAgICAgICAgICBNIDogJ2F5b3dyJyxcbiAgICAgICAgICAgIE1NIDogJyVkIGl5eWlybicsXG4gICAgICAgICAgICB5IDogJ2FzZ2FzJyxcbiAgICAgICAgICAgIHl5IDogJyVkIGlzZ2FzbidcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiAxMiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMTJ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd0em0nLCB7XG4gICAgICAgIG1vbnRocyA6ICfitYnitY/itY/itLDitaLitZRf4rSx4rWV4rSw4rWi4rWVX+K1juK0sOK1leK1ml/itYnitLHitZTitYnitZRf4rWO4rSw4rWi4rWi4rWTX+K1ouK1k+K1j+K1ouK1k1/itaLitZPitY3itaLitZPitaNf4rWW4rWT4rWb4rWcX+K1m+K1k+K1nOK0sOK1j+K0seK1ieK1lF/itL3itZ/itZPitLHitZVf4rWP4rWT4rWh4rSw4rWP4rSx4rWJ4rWUX+K0t+K1k+K1iuK1j+K0seK1ieK1lCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn4rWJ4rWP4rWP4rSw4rWi4rWUX+K0seK1leK0sOK1ouK1lV/itY7itLDitZXitZpf4rWJ4rSx4rWU4rWJ4rWUX+K1juK0sOK1ouK1ouK1k1/itaLitZPitY/itaLitZNf4rWi4rWT4rWN4rWi4rWT4rWjX+K1luK1k+K1m+K1nF/itZvitZPitZzitLDitY/itLHitYnitZRf4rS94rWf4rWT4rSx4rWVX+K1j+K1k+K1oeK0sOK1j+K0seK1ieK1lF/itLfitZPitYritY/itLHitYnitZQnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ+K0sOK1meK0sOK1juK0sOK1mV/itLDitaLitY/itLDitZlf4rSw4rWZ4rWJ4rWP4rSw4rWZX+K0sOK0veK1lOK0sOK1mV/itLDitL3itaHitLDitZlf4rSw4rWZ4rWJ4rWO4rWh4rSw4rWZX+K0sOK1meK1ieK0ueK1ouK0sOK1mScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfitLDitZnitLDitY7itLDitZlf4rSw4rWi4rWP4rSw4rWZX+K0sOK1meK1ieK1j+K0sOK1mV/itLDitL3itZTitLDitZlf4rSw4rS94rWh4rSw4rWZX+K0sOK1meK1ieK1juK1oeK0sOK1mV/itLDitZnitYnitLnitaLitLDitZknLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ+K0sOK1meK0sOK1juK0sOK1mV/itLDitaLitY/itLDitZlf4rSw4rWZ4rWJ4rWP4rSw4rWZX+K0sOK0veK1lOK0sOK1mV/itLDitL3itaHitLDitZlf4rSw4rWZ4rWJ4rWO4rWh4rSw4rWZX+K0sOK1meK1ieK0ueK1ouK0sOK1mScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW+K0sOK1meK0t+K1hSDitLRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXk6ICdb4rSw4rWZ4rS94rSwIOK0tF0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvitLRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXk6ICdb4rSw4rWa4rSw4rWP4rWcIOK0tF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvitLRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ+K0t+K0sOK0t+K1hSDitZkg4rWi4rSw4rWPICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAn4rWi4rSw4rWPICVzJyxcbiAgICAgICAgICAgIHMgOiAn4rWJ4rWO4rWJ4rS9JyxcbiAgICAgICAgICAgIHNzIDogJyVkIOK1ieK1juK1ieK0vScsXG4gICAgICAgICAgICBtIDogJ+K1juK1ieK1j+K1k+K0uicsXG4gICAgICAgICAgICBtbSA6ICclZCDitY7itYnitY/itZPitLonLFxuICAgICAgICAgICAgaCA6ICfitZnitLDitYTitLAnLFxuICAgICAgICAgICAgaGggOiAnJWQg4rWc4rSw4rWZ4rWZ4rSw4rWE4rWJ4rWPJyxcbiAgICAgICAgICAgIGQgOiAn4rSw4rWZ4rWZJyxcbiAgICAgICAgICAgIGRkIDogJyVkIG/itZnitZnitLDitY8nLFxuICAgICAgICAgICAgTSA6ICfitLDitaJv4rWT4rWUJyxcbiAgICAgICAgICAgIE1NIDogJyVkIOK1ieK1ouK1ouK1ieK1lOK1jycsXG4gICAgICAgICAgICB5IDogJ+K0sOK1meK0s+K0sOK1mScsXG4gICAgICAgICAgICB5eSA6ICclZCDitYnitZnitLPitLDitZnitY8nXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiA2LCAvLyBTYXR1cmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDEydGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbGFuZ3VhZ2UgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd1Zy1jbicsIHtcbiAgICAgICAgbW9udGhzOiAn2YrYp9mG24vYp9ixX9mB25Dbi9ix2KfZhF/Zhdin2LHYql/Yptin2b7YsduQ2YRf2YXYp9mKX9im2YnZituH2YZf2KbZidmK24fZhF/Yptin24vYutuH2LPYql/Ys9uQ2YbYqtuV2KjZidixX9im24bZg9iq25XYqNmJ2LFf2YbZiNmK2KfYqNmJ2LFf2K/bkNmD2KfYqNmJ2LEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIG1vbnRoc1Nob3J0OiAn2YrYp9mG24vYp9ixX9mB25Dbi9ix2KfZhF/Zhdin2LHYql/Yptin2b7YsduQ2YRf2YXYp9mKX9im2YnZituH2YZf2KbZidmK24fZhF/Yptin24vYutuH2LPYql/Ys9uQ2YbYqtuV2KjZidixX9im24bZg9iq25XYqNmJ2LFf2YbZiNmK2KfYqNmJ2LFf2K/bkNmD2KfYqNmJ2LEnLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIHdlZWtkYXlzOiAn2YrbldmD2LTbldmG2KjblV/Yr9uI2LTbldmG2KjblV/Ys9uV2YrYtNuV2YbYqNuVX9qG2KfYsdi025XZhtio25Vf2b7bldmK2LTbldmG2KjblV/YrNuI2YXblV/YtNuV2YbYqNuVJy5zcGxpdChcbiAgICAgICAgICAgICdfJ1xuICAgICAgICApLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0OiAn2YrblV/Yr9uIX9iz25Vf2obYp1/ZvtuVX9is24hf2LTblScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW46ICfZituVX9iv24hf2LPblV/ahtinX9m+25Vf2KzbiF/YtNuVJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgICAgICBMOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgICAgICBMTDogJ1lZWVkt2YrZidmE2YlNLdim2KfZitmG2YnarUQt2YPbiNmG2YknLFxuICAgICAgICAgICAgTExMOiAnWVlZWS3ZitmJ2YTZiU0t2KbYp9mK2YbZidqtRC3Zg9uI2YbZidiMIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEw6ICdkZGRk2IwgWVlZWS3ZitmJ2YTZiU0t2KbYp9mK2YbZidqtRC3Zg9uI2YbZidiMIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAv2YrbkNix2YnZhSDZg9uQ2obblXzYs9uV2r7bldixfNqG24jYtNiq2YnZhiDYqNuH2LHbh9mGfNqG24jYtHzahtuI2LTYqtmJ2YYg2YPbkNmK2YnZhnzZg9uV2oYvLFxuICAgICAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfZituQ2LHZidmFINmD25DahtuVJyB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn2LPbldq+25XYsScgfHxcbiAgICAgICAgICAgICAgICBtZXJpZGllbSA9PT0gJ9qG24jYtNiq2YnZhiDYqNuH2LHbh9mGJ1xuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn2obbiNi02KrZidmGINmD25DZitmJ2YYnIHx8IG1lcmlkaWVtID09PSAn2YPbldqGJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW06IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIHZhciBobSA9IGhvdXIgKiAxMDAgKyBtaW51dGU7XG4gICAgICAgICAgICBpZiAoaG0gPCA2MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9mK25DYsdmJ2YUg2YPbkNqG25UnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2LPbldq+25XYsSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTEzMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2obbiNi02KrZidmGINio24fYsduH2YYnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDEyMzApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9qG24jYtCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTgwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn2obbiNi02KrZidmGINmD25DZitmJ2YYnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9mD25Xahic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyOiB7XG4gICAgICAgICAgICBzYW1lRGF5OiAnW9io24jar9uI2YYg2LPYp9im25XYql0gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1vYptuV2KrblSDYs9in2KbbldiqXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlazogJ1vZg9uQ2YTbldix2YPZiV0gZGRkZCBb2LPYp9im25XYql0gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1vYqtuG2YbbiNqv24jZhl0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWs6ICdb2KbYp9mE2K/ZidmG2YLZiV0gZGRkZCBb2LPYp9im25XYql0gTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgICAgIGZ1dHVyZTogJyVzINmD25DZitmJ2YYnLFxuICAgICAgICAgICAgcGFzdDogJyVzINio24fYsduH2YYnLFxuICAgICAgICAgICAgczogJ9mG25XahtqG25Ug2LPbkNmD2YjZhtiqJyxcbiAgICAgICAgICAgIHNzOiAnJWQg2LPbkNmD2YjZhtiqJyxcbiAgICAgICAgICAgIG06ICfYqNmJ2LEg2YXZidmG24fYqicsXG4gICAgICAgICAgICBtbTogJyVkINmF2YnZhtuH2KonLFxuICAgICAgICAgICAgaDogJ9io2YnYsSDYs9in2KbbldiqJyxcbiAgICAgICAgICAgIGhoOiAnJWQg2LPYp9im25XYqicsXG4gICAgICAgICAgICBkOiAn2KjZidixINmD24jZhicsXG4gICAgICAgICAgICBkZDogJyVkINmD24jZhicsXG4gICAgICAgICAgICBNOiAn2KjZidixINim2KfZiicsXG4gICAgICAgICAgICBNTTogJyVkINim2KfZiicsXG4gICAgICAgICAgICB5OiAn2KjZidixINmK2YnZhCcsXG4gICAgICAgICAgICB5eTogJyVkINmK2YnZhCdcbiAgICAgICAgfSxcblxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oLdmD24jZhtmJfC3Yptin2Yp8Ldq+25XZvtiq25UpLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdmD24jZhtmJJztcbiAgICAgICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct2r7bldm+2KrblSc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrOiB7XG4gICAgICAgICAgICAvLyBHQi9UIDc0MDgtMTk5NOOAiuaVsOaNruWFg+WSjOS6pOaNouagvOW8j8K35L+h5oGv5Lqk5o2iwrfml6XmnJ/lkozml7bpl7TooajnpLrms5XjgIvkuI5JU08gODYwMToxOTg4562J5pWIXG4gICAgICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95OiA3IC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgZnVuY3Rpb24gcGx1cmFsJDYod29yZCwgbnVtKSB7XG4gICAgICAgIHZhciBmb3JtcyA9IHdvcmQuc3BsaXQoJ18nKTtcbiAgICAgICAgcmV0dXJuIG51bSAlIDEwID09PSAxICYmIG51bSAlIDEwMCAhPT0gMTEgPyBmb3Jtc1swXSA6IChudW0gJSAxMCA+PSAyICYmIG51bSAlIDEwIDw9IDQgJiYgKG51bSAlIDEwMCA8IDEwIHx8IG51bSAlIDEwMCA+PSAyMCkgPyBmb3Jtc1sxXSA6IGZvcm1zWzJdKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0KG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICAgICAnc3MnOiB3aXRob3V0U3VmZml4ID8gJ9GB0LXQutGD0L3QtNCwX9GB0LXQutGD0L3QtNC4X9GB0LXQutGD0L3QtCcgOiAn0YHQtdC60YPQvdC00YNf0YHQtdC60YPQvdC00Lhf0YHQtdC60YPQvdC0JyxcbiAgICAgICAgICAgICdtbSc6IHdpdGhvdXRTdWZmaXggPyAn0YXQstC40LvQuNC90LBf0YXQstC40LvQuNC90Lhf0YXQstC40LvQuNC9JyA6ICfRhdCy0LjQu9C40L3Rg1/RhdCy0LjQu9C40L3QuF/RhdCy0LjQu9C40L0nLFxuICAgICAgICAgICAgJ2hoJzogd2l0aG91dFN1ZmZpeCA/ICfQs9C+0LTQuNC90LBf0LPQvtC00LjQvdC4X9Cz0L7QtNC40L0nIDogJ9Cz0L7QtNC40L3Rg1/Qs9C+0LTQuNC90Lhf0LPQvtC00LjQvScsXG4gICAgICAgICAgICAnZGQnOiAn0LTQtdC90Yxf0LTQvdGWX9C00L3RltCyJyxcbiAgICAgICAgICAgICdNTSc6ICfQvNGW0YHRj9GG0Yxf0LzRltGB0Y/RhtGWX9C80ZbRgdGP0YbRltCyJyxcbiAgICAgICAgICAgICd5eSc6ICfRgNGW0Lpf0YDQvtC60Lhf0YDQvtC60ZbQsidcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGtleSA9PT0gJ20nKSB7XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICfRhdCy0LjQu9C40L3QsCcgOiAn0YXQstC40LvQuNC90YMnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGtleSA9PT0gJ2gnKSB7XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICfQs9C+0LTQuNC90LAnIDogJ9Cz0L7QtNC40L3Rgyc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgcGx1cmFsJDYoZm9ybWF0W2tleV0sICtudW1iZXIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHdlZWtkYXlzQ2FzZVJlcGxhY2UobSwgZm9ybWF0KSB7XG4gICAgICAgIHZhciB3ZWVrZGF5cyA9IHtcbiAgICAgICAgICAgICdub21pbmF0aXZlJzogJ9C90LXQtNGW0LvRj1/Qv9C+0L3QtdC00ZbQu9C+0Lpf0LLRltCy0YLQvtGA0L7Qul/RgdC10YDQtdC00LBf0YfQtdGC0LLQtdGAX9C/4oCZ0Y/RgtC90LjRhtGPX9GB0YPQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgICAgICdhY2N1c2F0aXZlJzogJ9C90LXQtNGW0LvRjl/Qv9C+0L3QtdC00ZbQu9C+0Lpf0LLRltCy0YLQvtGA0L7Qul/RgdC10YDQtdC00YNf0YfQtdGC0LLQtdGAX9C/4oCZ0Y/RgtC90LjRhtGOX9GB0YPQsdC+0YLRgycuc3BsaXQoJ18nKSxcbiAgICAgICAgICAgICdnZW5pdGl2ZSc6ICfQvdC10LTRltC70ZZf0L/QvtC90LXQtNGW0LvQutCwX9Cy0ZbQstGC0L7RgNC60LBf0YHQtdGA0LXQtNC4X9GH0LXRgtCy0LXRgNCz0LBf0L/igJnRj9GC0L3QuNGG0ZZf0YHRg9Cx0L7RgtC4Jy5zcGxpdCgnXycpXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKG0gPT09IHRydWUpIHtcbiAgICAgICAgICAgIHJldHVybiB3ZWVrZGF5c1snbm9taW5hdGl2ZSddLnNsaWNlKDEsIDcpLmNvbmNhdCh3ZWVrZGF5c1snbm9taW5hdGl2ZSddLnNsaWNlKDAsIDEpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgIHJldHVybiB3ZWVrZGF5c1snbm9taW5hdGl2ZSddO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG5vdW5DYXNlID0gKC8oXFxbW9CS0LLQo9GDXVxcXSkgP2RkZGQvKS50ZXN0KGZvcm1hdCkgP1xuICAgICAgICAgICAgJ2FjY3VzYXRpdmUnIDpcbiAgICAgICAgICAgICgoL1xcWz8oPzrQvNC40L3Rg9C70L7Rl3zQvdCw0YHRgtGD0L/QvdC+0ZcpPyA/XFxdID9kZGRkLykudGVzdChmb3JtYXQpID9cbiAgICAgICAgICAgICAgICAnZ2VuaXRpdmUnIDpcbiAgICAgICAgICAgICAgICAnbm9taW5hdGl2ZScpO1xuICAgICAgICByZXR1cm4gd2Vla2RheXNbbm91bkNhc2VdW20uZGF5KCldO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwcm9jZXNzSG91cnNGdW5jdGlvbihzdHIpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHIgKyAn0L4nICsgKHRoaXMuaG91cnMoKSA9PT0gMTEgPyAn0LEnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndWsnLCB7XG4gICAgICAgIG1vbnRocyA6IHtcbiAgICAgICAgICAgICdmb3JtYXQnOiAn0YHRltGH0L3Rj1/Qu9GO0YLQvtCz0L5f0LHQtdGA0LXQt9C90Y9f0LrQstGW0YLQvdGPX9GC0YDQsNCy0L3Rj1/Rh9C10YDQstC90Y9f0LvQuNC/0L3Rj1/RgdC10YDQv9C90Y9f0LLQtdGA0LXRgdC90Y9f0LbQvtCy0YLQvdGPX9C70LjRgdGC0L7Qv9Cw0LTQsF/Qs9GA0YPQtNC90Y8nLnNwbGl0KCdfJyksXG4gICAgICAgICAgICAnc3RhbmRhbG9uZSc6ICfRgdGW0YfQtdC90Yxf0LvRjtGC0LjQuV/QsdC10YDQtdC30LXQvdGMX9C60LLRltGC0LXQvdGMX9GC0YDQsNCy0LXQvdGMX9GH0LXRgNCy0LXQvdGMX9C70LjQv9C10L3RjF/RgdC10YDQv9C10L3RjF/QstC10YDQtdGB0LXQvdGMX9C20L7QstGC0LXQvdGMX9C70LjRgdGC0L7Qv9Cw0LRf0LPRgNGD0LTQtdC90YwnLnNwbGl0KCdfJylcbiAgICAgICAgfSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn0YHRltGHX9C70Y7Rgl/QsdC10YBf0LrQstGW0YJf0YLRgNCw0LJf0YfQtdGA0LJf0LvQuNC/X9GB0LXRgNC/X9Cy0LXRgF/QttC+0LLRgl/Qu9C40YHRgl/Qs9GA0YPQtCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiB3ZWVrZGF5c0Nhc2VSZXBsYWNlLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ9C90LRf0L/QvV/QstGCX9GB0YBf0YfRgl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ9C90LRf0L/QvV/QstGCX9GB0YBf0YfRgl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWSDRgC4nLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZINGALiwgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSDRgC4sIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0KHRjNC+0LPQvtC00L3RliAnKSxcbiAgICAgICAgICAgIG5leHREYXk6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0JfQsNCy0YLRgNCwICcpLFxuICAgICAgICAgICAgbGFzdERheTogcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQktGH0L7RgNCwICcpLFxuICAgICAgICAgICAgbmV4dFdlZWs6IHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0KNdIGRkZGQgWycpLFxuICAgICAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NIb3Vyc0Z1bmN0aW9uKCdb0JzQuNC90YPQu9C+0ZddIGRkZGQgWycpLmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQnNC40L3Rg9C70L7Qs9C+XSBkZGRkIFsnKS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICfQt9CwICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMg0YLQvtC80YMnLFxuICAgICAgICAgICAgcyA6ICfQtNC10LrRltC70YzQutCwINGB0LXQutGD0L3QtCcsXG4gICAgICAgICAgICBzcyA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkNCxcbiAgICAgICAgICAgIG0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDQsXG4gICAgICAgICAgICBtbSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkNCxcbiAgICAgICAgICAgIGggOiAn0LPQvtC00LjQvdGDJyxcbiAgICAgICAgICAgIGhoIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICAgICAgZCA6ICfQtNC10L3RjCcsXG4gICAgICAgICAgICBkZCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwkNCxcbiAgICAgICAgICAgIE0gOiAn0LzRltGB0Y/RhtGMJyxcbiAgICAgICAgICAgIE1NIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCQ0LFxuICAgICAgICAgICAgeSA6ICfRgNGW0LonLFxuICAgICAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsJDRcbiAgICAgICAgfSxcbiAgICAgICAgLy8gTS4gRS46IHRob3NlIHR3byBhcmUgdmlydHVhbGx5IHVudXNlZCBidXQgYSB1c2VyIG1pZ2h0IHdhbnQgdG8gaW1wbGVtZW50IHRoZW0gZm9yIGhpcy9oZXIgd2Vic2l0ZSBmb3Igc29tZSByZWFzb25cbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9C90L7Rh9GWfNGA0LDQvdC60YN80LTQvdGPfNCy0LXRh9C+0YDQsC8sXG4gICAgICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIC9eKNC00L3Rj3zQstC10YfQvtGA0LApJC8udGVzdChpbnB1dCk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfQvdC+0YfRlic7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0YDQsNC90LrRgyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgICAgIHJldHVybiAn0LTQvdGPJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfQstC10YfQvtGA0LAnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNC5fNCz0L4pLyxcbiAgICAgICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC5JztcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LPQvic7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gN3RoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICB2YXIgbW9udGhzJGEgPSBbXG4gICAgICAgICfYrNmG2YjYsduMJyxcbiAgICAgICAgJ9mB2LHZiNix24wnLFxuICAgICAgICAn2YXYp9ix2oYnLFxuICAgICAgICAn2KfZvtix24zZhCcsXG4gICAgICAgICfZhdim24wnLFxuICAgICAgICAn2KzZiNmGJyxcbiAgICAgICAgJ9is2YjZhNin2KbbjCcsXG4gICAgICAgICfYp9qv2LPYqicsXG4gICAgICAgICfYs9iq2YXYqNixJyxcbiAgICAgICAgJ9in2qnYqtmI2KjYsScsXG4gICAgICAgICfZhtmI2YXYqNixJyxcbiAgICAgICAgJ9iv2LPZhdio2LEnXG4gICAgXTtcbiAgICB2YXIgZGF5cyQyID0gW1xuICAgICAgICAn2KfYqtmI2KfYsScsXG4gICAgICAgICfZvtuM2LEnLFxuICAgICAgICAn2YXZhtqv2YQnLFxuICAgICAgICAn2KjYr9q+JyxcbiAgICAgICAgJ9is2YXYudix2KfYqicsXG4gICAgICAgICfYrNmF2LnbgScsXG4gICAgICAgICfbgdmB2KrbgSdcbiAgICBdO1xuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd1cicsIHtcbiAgICAgICAgbW9udGhzIDogbW9udGhzJGEsXG4gICAgICAgIG1vbnRoc1Nob3J0IDogbW9udGhzJGEsXG4gICAgICAgIHdlZWtkYXlzIDogZGF5cyQyLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogZGF5cyQyLFxuICAgICAgICB3ZWVrZGF5c01pbiA6IGRheXMkMixcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGTYjCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL9i12KjYrXzYtNin2YUvLFxuICAgICAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9i02KfZhScgPT09IGlucHV0O1xuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9i12KjYrSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJ9i02KfZhSc7XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb2KLYrCDYqNmI2YLYql0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb2qnZhCDYqNmI2YLYql0gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb2KjZiNmC2KpdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW9qv2LDYtNiq24Eg2LHZiNiyINio2YjZgtiqXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdb2q/YsNi02KrbgV0gZGRkZCBb2KjZiNmC2KpdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyDYqNi52K8nLFxuICAgICAgICAgICAgcGFzdCA6ICclcyDZgtio2YQnLFxuICAgICAgICAgICAgcyA6ICfahtmG2K8g2LPbjNqp2YbaiCcsXG4gICAgICAgICAgICBzcyA6ICclZCDYs9uM2qnZhtqIJyxcbiAgICAgICAgICAgIG0gOiAn2KfbjNqpINmF2YbZuScsXG4gICAgICAgICAgICBtbSA6ICclZCDZhdmG2bknLFxuICAgICAgICAgICAgaCA6ICfYp9uM2qkg2q/avtmG2bnbgScsXG4gICAgICAgICAgICBoaCA6ICclZCDar9q+2YbZuduSJyxcbiAgICAgICAgICAgIGQgOiAn2KfbjNqpINiv2YYnLFxuICAgICAgICAgICAgZGQgOiAnJWQg2K/ZhicsXG4gICAgICAgICAgICBNIDogJ9in24zaqSDZhdin24EnLFxuICAgICAgICAgICAgTU0gOiAnJWQg2YXYp9uBJyxcbiAgICAgICAgICAgIHkgOiAn2KfbjNqpINiz2KfZhCcsXG4gICAgICAgICAgICB5eSA6ICclZCDYs9in2YQnXG4gICAgICAgIH0sXG4gICAgICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3V6LWxhdG4nLCB7XG4gICAgICAgIG1vbnRocyA6ICdZYW52YXJfRmV2cmFsX01hcnRfQXByZWxfTWF5X0l5dW5fSXl1bF9Bdmd1c3RfU2VudGFicl9Pa3RhYnJfTm95YWJyX0Rla2Ficicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnWWFuX0Zldl9NYXJfQXByX01heV9JeXVuX0l5dWxfQXZnX1Nlbl9Pa3RfTm95X0Rlaycuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXMgOiAnWWFrc2hhbmJhX0R1c2hhbmJhX1Nlc2hhbmJhX0Nob3JzaGFuYmFfUGF5c2hhbmJhX0p1bWFfU2hhbmJhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ1lha19EdXNoX1Nlc2hfQ2hvcl9QYXlfSnVtX1NoYW4nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ1lhX0R1X1NlX0Nob19QYV9KdV9TaGEnLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdEIE1NTU0gWVlZWSwgZGRkZCBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tCdWd1biBzb2F0XSBMVCBbZGFdJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW0VydGFnYV0gTFQgW2RhXScsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtrdW5pIHNvYXRdIExUIFtkYV0nLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbS2VjaGEgc29hdF0gTFQgW2RhXScsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbT1xcJ3RnYW5dIGRkZGQgW2t1bmkgc29hdF0gTFQgW2RhXScsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnWWFxaW4gJXMgaWNoaWRhJyxcbiAgICAgICAgICAgIHBhc3QgOiAnQmlyIG5lY2hhICVzIG9sZGluJyxcbiAgICAgICAgICAgIHMgOiAnc29uaXlhJyxcbiAgICAgICAgICAgIHNzIDogJyVkIHNvbml5YScsXG4gICAgICAgICAgICBtIDogJ2JpciBkYXFpcWEnLFxuICAgICAgICAgICAgbW0gOiAnJWQgZGFxaXFhJyxcbiAgICAgICAgICAgIGggOiAnYmlyIHNvYXQnLFxuICAgICAgICAgICAgaGggOiAnJWQgc29hdCcsXG4gICAgICAgICAgICBkIDogJ2JpciBrdW4nLFxuICAgICAgICAgICAgZGQgOiAnJWQga3VuJyxcbiAgICAgICAgICAgIE0gOiAnYmlyIG95JyxcbiAgICAgICAgICAgIE1NIDogJyVkIG95JyxcbiAgICAgICAgICAgIHkgOiAnYmlyIHlpbCcsXG4gICAgICAgICAgICB5eSA6ICclZCB5aWwnXG4gICAgICAgIH0sXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDd0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuXG4gICAgaG9va3MuZGVmaW5lTG9jYWxlKCd1eicsIHtcbiAgICAgICAgbW9udGhzIDogJ9GP0L3QstCw0YBf0YTQtdCy0YDQsNC7X9C80LDRgNGCX9Cw0L/RgNC10Ltf0LzQsNC5X9C40Y7QvV/QuNGO0Ltf0LDQstCz0YPRgdGCX9GB0LXQvdGC0Y/QsdGAX9C+0LrRgtGP0LHRgF/QvdC+0Y/QsdGAX9C00LXQutCw0LHRgCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAn0Y/QvdCyX9GE0LXQsl/QvNCw0YBf0LDQv9GAX9C80LDQuV/QuNGO0L1f0LjRjtC7X9Cw0LLQs1/RgdC10L1f0L7QutGCX9C90L7Rj1/QtNC10LonLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ9Cv0LrRiNCw0L3QsdCwX9CU0YPRiNCw0L3QsdCwX9Ch0LXRiNCw0L3QsdCwX9Cn0L7RgNGI0LDQvdCx0LBf0J/QsNC50YjQsNC90LHQsF/QltGD0LzQsF/QqNCw0L3QsdCwJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1Nob3J0IDogJ9Cv0LrRiF/QlNGD0Yhf0KHQtdGIX9Cn0L7RgF/Qn9Cw0Llf0JbRg9C8X9Co0LDQvScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAn0K/Qul/QlNGDX9Ch0LVf0KfQvl/Qn9CwX9CW0YNf0KjQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ0QgTU1NTSBZWVlZLCBkZGRkIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW9CR0YPQs9GD0L0g0YHQvtCw0YJdIExUIFvQtNCwXScsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vQrdGA0YLQsNCz0LBdIExUIFvQtNCwXScsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvQutGD0L3QuCDRgdC+0LDRgl0gTFQgW9C00LBdJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW9Ca0LXRh9CwINGB0L7QsNGCXSBMVCBb0LTQsF0nLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW9Cj0YLQs9Cw0L1dIGRkZGQgW9C60YPQvdC4INGB0L7QsNGCXSBMVCBb0LTQsF0nLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJ9Cv0LrQuNC9ICVzINC40YfQuNC00LAnLFxuICAgICAgICAgICAgcGFzdCA6ICfQkdC40YAg0L3QtdGH0LAgJXMg0L7Qu9C00LjQvScsXG4gICAgICAgICAgICBzIDogJ9GE0YPRgNGB0LDRgicsXG4gICAgICAgICAgICBzcyA6ICclZCDRhNGD0YDRgdCw0YInLFxuICAgICAgICAgICAgbSA6ICfQsdC40YAg0LTQsNC60LjQutCwJyxcbiAgICAgICAgICAgIG1tIDogJyVkINC00LDQutC40LrQsCcsXG4gICAgICAgICAgICBoIDogJ9Cx0LjRgCDRgdC+0LDRgicsXG4gICAgICAgICAgICBoaCA6ICclZCDRgdC+0LDRgicsXG4gICAgICAgICAgICBkIDogJ9Cx0LjRgCDQutGD0L0nLFxuICAgICAgICAgICAgZGQgOiAnJWQg0LrRg9C9JyxcbiAgICAgICAgICAgIE0gOiAn0LHQuNGAINC+0LknLFxuICAgICAgICAgICAgTU0gOiAnJWQg0L7QuScsXG4gICAgICAgICAgICB5IDogJ9Cx0LjRgCDQudC40LsnLFxuICAgICAgICAgICAgeXkgOiAnJWQg0LnQuNC7J1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgndmknLCB7XG4gICAgICAgIG1vbnRocyA6ICd0aMOhbmcgMV90aMOhbmcgMl90aMOhbmcgM190aMOhbmcgNF90aMOhbmcgNV90aMOhbmcgNl90aMOhbmcgN190aMOhbmcgOF90aMOhbmcgOV90aMOhbmcgMTBfdGjDoW5nIDExX3Row6FuZyAxMicuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnVGgwMV9UaDAyX1RoMDNfVGgwNF9UaDA1X1RoMDZfVGgwN19UaDA4X1RoMDlfVGgxMF9UaDExX1RoMTInLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICB3ZWVrZGF5cyA6ICdjaOG7pyBuaOG6rXRfdGjhu6kgaGFpX3Ro4bupIGJhX3Ro4bupIHTGsF90aOG7qSBuxINtX3Ro4bupIHPDoXVfdGjhu6kgYuG6o3knLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnQ05fVDJfVDNfVDRfVDVfVDZfVDcnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ0NOX1QyX1QzX1Q0X1Q1X1Q2X1Q3Jy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBtZXJpZGllbVBhcnNlOiAvc2F8Y2gvaSxcbiAgICAgICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIC9eY2gkL2kudGVzdChpbnB1dCk7XG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPCAxMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ3NhJyA6ICdTQSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2NoJyA6ICdDSCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gW27Eg21dIFlZWVknLFxuICAgICAgICAgICAgTExMIDogJ0QgTU1NTSBbbsSDbV0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBbbsSDbV0gWVlZWSBISDptbScsXG4gICAgICAgICAgICBsIDogJ0REL00vWVlZWScsXG4gICAgICAgICAgICBsbCA6ICdEIE1NTSBZWVlZJyxcbiAgICAgICAgICAgIGxsbCA6ICdEIE1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGwgOiAnZGRkLCBEIE1NTSBZWVlZIEhIOm1tJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXk6ICdbSMO0bSBuYXkgbMO6Y10gTFQnLFxuICAgICAgICAgICAgbmV4dERheTogJ1tOZ8OgeSBtYWkgbMO6Y10gTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt0deG6p24gdOG7m2kgbMO6Y10gTFQnLFxuICAgICAgICAgICAgbGFzdERheTogJ1tIw7RtIHF1YSBsw7pjXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlazogJ2RkZGQgW3R14bqnbiBy4buTaSBsw7pjXSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICclcyB04bubaScsXG4gICAgICAgICAgICBwYXN0IDogJyVzIHRyxrDhu5tjJyxcbiAgICAgICAgICAgIHMgOiAndsOgaSBnacOieScsXG4gICAgICAgICAgICBzcyA6ICclZCBnacOieScgLFxuICAgICAgICAgICAgbSA6ICdt4buZdCBwaMO6dCcsXG4gICAgICAgICAgICBtbSA6ICclZCBwaMO6dCcsXG4gICAgICAgICAgICBoIDogJ23hu5l0IGdp4budJyxcbiAgICAgICAgICAgIGhoIDogJyVkIGdp4budJyxcbiAgICAgICAgICAgIGQgOiAnbeG7mXQgbmfDoHknLFxuICAgICAgICAgICAgZGQgOiAnJWQgbmfDoHknLFxuICAgICAgICAgICAgTSA6ICdt4buZdCB0aMOhbmcnLFxuICAgICAgICAgICAgTU0gOiAnJWQgdGjDoW5nJyxcbiAgICAgICAgICAgIHkgOiAnbeG7mXQgbsSDbScsXG4gICAgICAgICAgICB5eSA6ICclZCBuxINtJ1xuICAgICAgICB9LFxuICAgICAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0vLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgfSxcbiAgICAgICAgd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3gtcHNldWRvJywge1xuICAgICAgICBtb250aHMgOiAnSn7DocOxw7rDoX5yw71fRn7DqWJyw7p+w6Fyw71ffk3DoXJjfmhfw4FwfnLDrWxffk3DocO9X35Kw7rDscOpfl9Kw7psfsO9X8OBw7p+Z8O6c3R+X1PDqXB+dMOpbWJ+w6lyX8OTfmN0w7NifsOpcl/DkX7Ds3bDqW1+YsOpcl9+RMOpY8Opfm1iw6lyJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNTaG9ydCA6ICdKfsOhw7FffkbDqWJffk3DoXJffsOBcHJffk3DocO9X35Kw7rDsV9+SsO6bF9+w4HDumdfflPDqXBffsOTY3RffsORw7N2X35Ew6ljJy5zcGxpdCgnXycpLFxuICAgICAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAgICAgd2Vla2RheXMgOiAnU37DusOxZMOhfsO9X03Ds37DsWTDocO9fl9Uw7rDqX5zZMOhw71+X1fDqWR+w7HDqXNkfsOhw71fVH5ow7pyc35kw6HDvV9+RnLDrWR+w6HDvV9TfsOhdMO6cn5kw6HDvScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICdTfsO6w7Fffk3Ds8OxX35Uw7rDqV9+V8OpZF9+VGjDul9+RnLDrV9+U8OhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNNaW4gOiAnU37Dul9Nw7N+X1TDul9+V8OpX1R+aF9Gcn5fU8OhJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgY2FsZW5kYXIgOiB7XG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tUfsOzZMOhfsO9IMOhdF0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdbVH7Ds23Ds35ycsOzfncgw6F0XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvDoXRdIExUJyxcbiAgICAgICAgICAgIGxhc3REYXkgOiAnW8OdfsOpc3R+w6lyZMOhfsO9IMOhdF0gTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW0x+w6FzdF0gZGRkZCBbw6F0XSBMVCcsXG4gICAgICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgICAgICBmdXR1cmUgOiAnw61+w7EgJXMnLFxuICAgICAgICAgICAgcGFzdCA6ICclcyDDoX5nw7MnLFxuICAgICAgICAgICAgcyA6ICfDoSB+ZsOpdyB+c8OpY8OzfsOxZHMnLFxuICAgICAgICAgICAgc3MgOiAnJWQgc37DqWPDs8OxfmRzJyxcbiAgICAgICAgICAgIG0gOiAnw6Egfm3DrcOxfsO6dMOpJyxcbiAgICAgICAgICAgIG1tIDogJyVkIG1+w63DscO6fnTDqXMnLFxuICAgICAgICAgICAgaCA6ICfDoX7DsSBow7N+w7pyJyxcbiAgICAgICAgICAgIGhoIDogJyVkIGh+w7PDunJzJyxcbiAgICAgICAgICAgIGQgOiAnw6EgfmTDocO9JyxcbiAgICAgICAgICAgIGRkIDogJyVkIGR+w6HDvXMnLFxuICAgICAgICAgICAgTSA6ICfDoSB+bcOzw7F+dGgnLFxuICAgICAgICAgICAgTU0gOiAnJWQgbX7Ds8OxdH5ocycsXG4gICAgICAgICAgICB5IDogJ8OhIH7DvcOpw6FyJyxcbiAgICAgICAgICAgIHl5IDogJyVkIMO9fsOpw6FycydcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHRofHN0fG5kfHJkKS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAgICAgKGIgPT09IDEpID8gJ3N0JyA6XG4gICAgICAgICAgICAgICAgKGIgPT09IDIpID8gJ25kJyA6XG4gICAgICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgneW8nLCB7XG4gICAgICAgIG1vbnRocyA6ICdT4bq5zIFy4bq5zIFfRcyAcmXMgGxlzIBf4bq4cuG6ucyAbmHMgF9JzIBnYmXMgV9FzIBiaWJpX0/MgGt1zIBkdV9BZ+G6uW1vX0/MgGd1zIFuX093ZXdlX+G7jMyAd2HMgHJhzIBfQmXMgWx1zIFf4buMzIBw4bq5zIDMgCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnU+G6ucyBcl9FzIBybF/hurhybl9JzIBnYl9FzIBiaV9PzIBrdcyAX0Fn4bq5X0/MgGd1zIFfT3dlX+G7jMyAd2HMgF9CZcyBbF/hu4zMgHDhurnMgMyAJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICdBzIBpzIBrdcyBX0FqZcyBX0nMgHPhurnMgWd1bl/hu4xq4buNzIFydcyBX+G7jGrhu43MgWLhu41f4bq4dGnMgF9BzIBiYcyBbeG6ucyBdGEnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAnQcyAacyAa19BamXMgV9JzIBz4bq5zIFf4buManJf4buMamJf4bq4dGnMgF9BzIBiYcyBJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICdBzIBpzIBfQWpfScyAc1/hu4xyX+G7jGJf4bq4dF9BzIBiJy5zcGxpdCgnXycpLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgICAgIExUIDogJ2g6bW0gQScsXG4gICAgICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJ1xuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW0/MgG5pzIAgbmldIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW+G7jMyAbGEgbmldIExUJyxcbiAgICAgICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW+G7jHPhurnMgCB0b8yBblxcJ2Lhu41dIFtuaV0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbQcyAbmEgbmldIExUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW+G7jHPhurnMgCB0b8yBbOG7jcyBXSBbbmldIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6ICduacyBICVzJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXMga+G7jWphzIEnLFxuICAgICAgICAgICAgcyA6ICdpzIBz4bq5anXMgSBhYXlhzIEgZGllJyxcbiAgICAgICAgICAgIHNzIDonYWF5YcyBICVkJyxcbiAgICAgICAgICAgIG0gOiAnacyAc+G6uWp1zIEga2FuJyxcbiAgICAgICAgICAgIG1tIDogJ2nMgHPhurlqdcyBICVkJyxcbiAgICAgICAgICAgIGggOiAnd2HMgWthdGkga2FuJyxcbiAgICAgICAgICAgIGhoIDogJ3dhzIFrYXRpICVkJyxcbiAgICAgICAgICAgIGQgOiAn4buNauG7jcyBIGthbicsXG4gICAgICAgICAgICBkZCA6ICfhu41q4buNzIEgJWQnLFxuICAgICAgICAgICAgTSA6ICdvc3XMgCBrYW4nLFxuICAgICAgICAgICAgTU0gOiAnb3N1zIAgJWQnLFxuICAgICAgICAgICAgeSA6ICfhu41kdcyBbiBrYW4nLFxuICAgICAgICAgICAgeXkgOiAn4buNZHXMgW4gJWQnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAv4buNauG7jcyBXFxzXFxkezEsMn0vLFxuICAgICAgICBvcmRpbmFsIDogJ+G7jWrhu43MgSAlZCcsXG4gICAgICAgIHdlZWsgOiB7XG4gICAgICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgICAgIGRveSA6IDQgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3poLWNuJywge1xuICAgICAgICBtb250aHMgOiAn5LiA5pyIX+S6jOaciF/kuInmnIhf5Zub5pyIX+S6lOaciF/lha3mnIhf5LiD5pyIX+WFq+aciF/kuZ3mnIhf5Y2B5pyIX+WNgeS4gOaciF/ljYHkuozmnIgnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfmmJ/mnJ/ml6Vf5pif5pyf5LiAX+aYn+acn+S6jF/mmJ/mnJ/kuIlf5pif5pyf5ZubX+aYn+acn+S6lF/mmJ/mnJ/lha0nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn5ZGo5pelX+WRqOS4gF/lkajkuoxf5ZGo5LiJX+WRqOWbm1/lkajkupRf5ZGo5YWtJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfml6Vf5LiAX+S6jF/kuIlf5ZubX+S6lF/lha0nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnWVlZWS9NTS9ERCcsXG4gICAgICAgICAgICBMTCA6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICAgICAgTExMIDogJ1lZWVnlubRN5pyIROaXpUFo54K5bW3liIYnLFxuICAgICAgICAgICAgTExMTCA6ICdZWVlZ5bm0TeaciETml6VkZGRkQWjngrltbeWIhicsXG4gICAgICAgICAgICBsIDogJ1lZWVkvTS9EJyxcbiAgICAgICAgICAgIGxsIDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgICAgICBsbGwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+WHjOaZqHzml6nkuIp85LiK5Y2IfOS4reWNiHzkuIvljYh85pma5LiKLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn5YeM5pmoJyB8fCBtZXJpZGllbSA9PT0gJ+aXqeS4iicgfHxcbiAgICAgICAgICAgICAgICAgICAgbWVyaWRpZW0gPT09ICfkuIrljYgnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn5LiL5Y2IJyB8fCBtZXJpZGllbSA9PT0gJ+aZmuS4iicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyAn5Lit5Y2IJ1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICB2YXIgaG0gPSBob3VyICogMTAwICsgbWludXRlO1xuICAgICAgICAgICAgaWYgKGhtIDwgNjAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICflh4zmmagnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5pep5LiKJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCAxMTMwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfkuIrljYgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDEyMzApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+S4reWNiCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTgwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5LiL5Y2IJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfmmZrkuIonO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW+S7iuWkqV1MVCcsXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1vmmI7lpKldTFQnLFxuICAgICAgICAgICAgbmV4dFdlZWsgOiAnW+S4i11kZGRkTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb5pio5aSpXUxUJyxcbiAgICAgICAgICAgIGxhc3RXZWVrIDogJ1vkuIpdZGRkZExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSjml6V85pyIfOWRqCkvLFxuICAgICAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5pelJztcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfmnIgnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+WRqCc7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVz5YaFJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXPliY0nLFxuICAgICAgICAgICAgcyA6ICflh6Dnp5InLFxuICAgICAgICAgICAgc3MgOiAnJWQg56eSJyxcbiAgICAgICAgICAgIG0gOiAnMSDliIbpkp8nLFxuICAgICAgICAgICAgbW0gOiAnJWQg5YiG6ZKfJyxcbiAgICAgICAgICAgIGggOiAnMSDlsI/ml7YnLFxuICAgICAgICAgICAgaGggOiAnJWQg5bCP5pe2JyxcbiAgICAgICAgICAgIGQgOiAnMSDlpKknLFxuICAgICAgICAgICAgZGQgOiAnJWQg5aSpJyxcbiAgICAgICAgICAgIE0gOiAnMSDkuKrmnIgnLFxuICAgICAgICAgICAgTU0gOiAnJWQg5Liq5pyIJyxcbiAgICAgICAgICAgIHkgOiAnMSDlubQnLFxuICAgICAgICAgICAgeXkgOiAnJWQg5bm0J1xuICAgICAgICB9LFxuICAgICAgICB3ZWVrIDoge1xuICAgICAgICAgICAgLy8gR0IvVCA3NDA4LTE5OTTjgIrmlbDmja7lhYPlkozkuqTmjaLmoLzlvI/Ct+S/oeaBr+S6pOaNosK35pel5pyf5ZKM5pe26Ze06KGo56S65rOV44CL5LiOSVNPIDg2MDE6MTk4OOetieaViFxuICAgICAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cblxuICAgIGhvb2tzLmRlZmluZUxvY2FsZSgnemgtaGsnLCB7XG4gICAgICAgIG1vbnRocyA6ICfkuIDmnIhf5LqM5pyIX+S4ieaciF/lm5vmnIhf5LqU5pyIX+WFreaciF/kuIPmnIhf5YWr5pyIX+S5neaciF/ljYHmnIhf5Y2B5LiA5pyIX+WNgeS6jOaciCcuc3BsaXQoJ18nKSxcbiAgICAgICAgbW9udGhzU2hvcnQgOiAnMeaciF8y5pyIXzPmnIhfNOaciF815pyIXzbmnIhfN+aciF845pyIXznmnIhfMTDmnIhfMTHmnIhfMTLmnIgnLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzIDogJ+aYn+acn+aXpV/mmJ/mnJ/kuIBf5pif5pyf5LqMX+aYn+acn+S4iV/mmJ/mnJ/lm5tf5pif5pyf5LqUX+aYn+acn+WFrScuc3BsaXQoJ18nKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6ICfpgLHml6Vf6YCx5LiAX+mAseS6jF/pgLHkuIlf6YCx5ZubX+mAseS6lF/pgLHlha0nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzTWluIDogJ+aXpV/kuIBf5LqMX+S4iV/lm5tf5LqUX+WFrScuc3BsaXQoJ18nKSxcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICAgICAgTCA6ICdZWVlZL01NL0REJyxcbiAgICAgICAgICAgIExMIDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgICAgICBMTEwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgICAgIExMTEwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbScsXG4gICAgICAgICAgICBsIDogJ1lZWVkvTS9EJyxcbiAgICAgICAgICAgIGxsIDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgICAgICBsbGwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgICAgIGxsbGwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbSdcbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW1QYXJzZTogL+WHjOaZqHzml6nkuIp85LiK5Y2IfOS4reWNiHzkuIvljYh85pma5LiKLyxcbiAgICAgICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+WHjOaZqCcgfHwgbWVyaWRpZW0gPT09ICfml6nkuIonIHx8IG1lcmlkaWVtID09PSAn5LiK5Y2IJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+S4reWNiCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn5LiL5Y2IJyB8fCBtZXJpZGllbSA9PT0gJ+aZmuS4iicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgICAgIHZhciBobSA9IGhvdXIgKiAxMDAgKyBtaW51dGU7XG4gICAgICAgICAgICBpZiAoaG0gPCA2MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+WHjOaZqCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgOTAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfml6nkuIonO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDExMzApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+S4iuWNiCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTIzMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5Lit5Y2IJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCAxODAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfkuIvljYgnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+aZmuS4iic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdb5LuK5aSpXUxUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW+aYjuWkqV1MVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdb5LiLXWRkZGRMVCcsXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1vmmKjlpKldTFQnLFxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW+S4il1kZGRkTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KOaXpXzmnIh86YCxKS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCcgOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnIDpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnIDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfml6UnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nIDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfmnIgnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3cnIDpcbiAgICAgICAgICAgICAgICBjYXNlICdXJyA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn6YCxJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVz5YWnJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXPliY0nLFxuICAgICAgICAgICAgcyA6ICflub7np5InLFxuICAgICAgICAgICAgc3MgOiAnJWQg56eSJyxcbiAgICAgICAgICAgIG0gOiAnMSDliIbpkJgnLFxuICAgICAgICAgICAgbW0gOiAnJWQg5YiG6ZCYJyxcbiAgICAgICAgICAgIGggOiAnMSDlsI/mmYInLFxuICAgICAgICAgICAgaGggOiAnJWQg5bCP5pmCJyxcbiAgICAgICAgICAgIGQgOiAnMSDlpKknLFxuICAgICAgICAgICAgZGQgOiAnJWQg5aSpJyxcbiAgICAgICAgICAgIE0gOiAnMSDlgIvmnIgnLFxuICAgICAgICAgICAgTU0gOiAnJWQg5YCL5pyIJyxcbiAgICAgICAgICAgIHkgOiAnMSDlubQnLFxuICAgICAgICAgICAgeXkgOiAnJWQg5bm0J1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG5cbiAgICBob29rcy5kZWZpbmVMb2NhbGUoJ3poLXR3Jywge1xuICAgICAgICBtb250aHMgOiAn5LiA5pyIX+S6jOaciF/kuInmnIhf5Zub5pyIX+S6lOaciF/lha3mnIhf5LiD5pyIX+WFq+aciF/kuZ3mnIhf5Y2B5pyIX+WNgeS4gOaciF/ljYHkuozmnIgnLnNwbGl0KCdfJyksXG4gICAgICAgIG1vbnRoc1Nob3J0IDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5cyA6ICfmmJ/mnJ/ml6Vf5pif5pyf5LiAX+aYn+acn+S6jF/mmJ/mnJ/kuIlf5pif5pyf5ZubX+aYn+acn+S6lF/mmJ/mnJ/lha0nLnNwbGl0KCdfJyksXG4gICAgICAgIHdlZWtkYXlzU2hvcnQgOiAn6YCx5pelX+mAseS4gF/pgLHkuoxf6YCx5LiJX+mAseWbm1/pgLHkupRf6YCx5YWtJy5zcGxpdCgnXycpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6ICfml6Vf5LiAX+S6jF/kuIlf5ZubX+S6lF/lha0nLnNwbGl0KCdfJyksXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgICAgIEwgOiAnWVlZWS9NTS9ERCcsXG4gICAgICAgICAgICBMTCA6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICAgICAgTExMIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgICAgICBMTExMIDogJ1lZWVnlubRN5pyIROaXpWRkZGQgSEg6bW0nLFxuICAgICAgICAgICAgbCA6ICdZWVlZL00vRCcsXG4gICAgICAgICAgICBsbCA6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICAgICAgbGxsIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgICAgICBsbGxsIDogJ1lZWVnlubRN5pyIROaXpWRkZGQgSEg6bW0nXG4gICAgICAgIH0sXG4gICAgICAgIG1lcmlkaWVtUGFyc2U6IC/lh4zmmah85pep5LiKfOS4iuWNiHzkuK3ljYh85LiL5Y2IfOaZmuS4ii8sXG4gICAgICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVyaWRpZW0gPT09ICflh4zmmagnIHx8IG1lcmlkaWVtID09PSAn5pep5LiKJyB8fCBtZXJpZGllbSA9PT0gJ+S4iuWNiCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfkuK3ljYgnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+S4i+WNiCcgfHwgbWVyaWRpZW0gPT09ICfmmZrkuIonKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICB2YXIgaG0gPSBob3VyICogMTAwICsgbWludXRlO1xuICAgICAgICAgICAgaWYgKGhtIDwgNjAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICflh4zmmagnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5pep5LiKJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaG0gPCAxMTMwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfkuIrljYgnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChobSA8IDEyMzApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ+S4reWNiCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTgwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAn5LiL5Y2IJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfmmZrkuIonO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgICAgIHNhbWVEYXkgOiAnW+S7iuWkqV0gTFQnLFxuICAgICAgICAgICAgbmV4dERheSA6ICdb5piO5aSpXSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdb5LiLXWRkZGQgTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdb5pio5aSpXSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdb5LiKXWRkZGQgTFQnLFxuICAgICAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICAgICAgfSxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KOaXpXzmnIh86YCxKS8sXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCcgOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0QnIDpcbiAgICAgICAgICAgICAgICBjYXNlICdEREQnIDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfml6UnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nIDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfmnIgnO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3cnIDpcbiAgICAgICAgICAgICAgICBjYXNlICdXJyA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn6YCxJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICAgICAgZnV0dXJlIDogJyVz5YWnJyxcbiAgICAgICAgICAgIHBhc3QgOiAnJXPliY0nLFxuICAgICAgICAgICAgcyA6ICflub7np5InLFxuICAgICAgICAgICAgc3MgOiAnJWQg56eSJyxcbiAgICAgICAgICAgIG0gOiAnMSDliIbpkJgnLFxuICAgICAgICAgICAgbW0gOiAnJWQg5YiG6ZCYJyxcbiAgICAgICAgICAgIGggOiAnMSDlsI/mmYInLFxuICAgICAgICAgICAgaGggOiAnJWQg5bCP5pmCJyxcbiAgICAgICAgICAgIGQgOiAnMSDlpKknLFxuICAgICAgICAgICAgZGQgOiAnJWQg5aSpJyxcbiAgICAgICAgICAgIE0gOiAnMSDlgIvmnIgnLFxuICAgICAgICAgICAgTU0gOiAnJWQg5YCL5pyIJyxcbiAgICAgICAgICAgIHkgOiAnMSDlubQnLFxuICAgICAgICAgICAgeXkgOiAnJWQg5bm0J1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBob29rcy5sb2NhbGUoJ2VuJyk7XG5cbiAgICByZXR1cm4gaG9va3M7XG5cbn0pKSk7XG4iLCIhZnVuY3Rpb24odCxlKXtcInVzZSBzdHJpY3RcIjtcIm9iamVjdFwiPT10eXBlb2YgbW9kdWxlJiZtb2R1bGUuZXhwb3J0cz9tb2R1bGUuZXhwb3J0cz1lKHJlcXVpcmUoXCJtb21lbnRcIikpOlwiZnVuY3Rpb25cIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoW1wibW9tZW50XCJdLGUpOmUodC5tb21lbnQpfSh0aGlzLGZ1bmN0aW9uKHMpe1widXNlIHN0cmljdFwiO3ZhciBlLGk9e30sZj17fSx1PXt9LGM9e307cyYmXCJzdHJpbmdcIj09dHlwZW9mIHMudmVyc2lvbnx8QShcIk1vbWVudCBUaW1lem9uZSByZXF1aXJlcyBNb21lbnQuanMuIFNlZSBodHRwczovL21vbWVudGpzLmNvbS90aW1lem9uZS9kb2NzLyMvdXNlLWl0L2Jyb3dzZXIvXCIpO3ZhciB0PXMudmVyc2lvbi5zcGxpdChcIi5cIiksbj0rdFswXSxvPSt0WzFdO2Z1bmN0aW9uIGEodCl7cmV0dXJuIDk2PHQ/dC04Nzo2NDx0P3QtMjk6dC00OH1mdW5jdGlvbiByKHQpe3ZhciBlPTAsbj10LnNwbGl0KFwiLlwiKSxvPW5bMF0scj1uWzFdfHxcIlwiLHM9MSxpPTAsZj0xO2Zvcig0NT09PXQuY2hhckNvZGVBdCgwKSYmKGY9LShlPTEpKTtlPG8ubGVuZ3RoO2UrKylpPTYwKmkrYShvLmNoYXJDb2RlQXQoZSkpO2ZvcihlPTA7ZTxyLmxlbmd0aDtlKyspcy89NjAsaSs9YShyLmNoYXJDb2RlQXQoZSkpKnM7cmV0dXJuIGkqZn1mdW5jdGlvbiBsKHQpe2Zvcih2YXIgZT0wO2U8dC5sZW5ndGg7ZSsrKXRbZV09cih0W2VdKX1mdW5jdGlvbiBoKHQsZSl7dmFyIG4sbz1bXTtmb3Iobj0wO248ZS5sZW5ndGg7bisrKW9bbl09dFtlW25dXTtyZXR1cm4gb31mdW5jdGlvbiBwKHQpe3ZhciBlPXQuc3BsaXQoXCJ8XCIpLG49ZVsyXS5zcGxpdChcIiBcIiksbz1lWzNdLnNwbGl0KFwiXCIpLHI9ZVs0XS5zcGxpdChcIiBcIik7cmV0dXJuIGwobiksbChvKSxsKHIpLGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciBuPTA7bjxlO24rKyl0W25dPU1hdGgucm91bmQoKHRbbi0xXXx8MCkrNmU0KnRbbl0pO3RbZS0xXT0xLzB9KHIsby5sZW5ndGgpLHtuYW1lOmVbMF0sYWJicnM6aChlWzFdLnNwbGl0KFwiIFwiKSxvKSxvZmZzZXRzOmgobixvKSx1bnRpbHM6cixwb3B1bGF0aW9uOjB8ZVs1XX19ZnVuY3Rpb24gbSh0KXt0JiZ0aGlzLl9zZXQocCh0KSl9ZnVuY3Rpb24gZCh0KXt2YXIgZT10LnRvVGltZVN0cmluZygpLG49ZS5tYXRjaCgvXFwoW2EteiBdK1xcKS9pKTtcIkdNVFwiPT09KG49biYmblswXT8obj1uWzBdLm1hdGNoKC9bQS1aXS9nKSk/bi5qb2luKFwiXCIpOnZvaWQgMDoobj1lLm1hdGNoKC9bQS1aXXszLDV9L2cpKT9uWzBdOnZvaWQgMCkmJihuPXZvaWQgMCksdGhpcy5hdD0rdCx0aGlzLmFiYnI9bix0aGlzLm9mZnNldD10LmdldFRpbWV6b25lT2Zmc2V0KCl9ZnVuY3Rpb24geih0KXt0aGlzLnpvbmU9dCx0aGlzLm9mZnNldFNjb3JlPTAsdGhpcy5hYmJyU2NvcmU9MH1mdW5jdGlvbiB2KHQsZSl7Zm9yKHZhciBuLG87bz02ZTQqKChlLmF0LXQuYXQpLzEyZTR8MCk7KShuPW5ldyBkKG5ldyBEYXRlKHQuYXQrbykpKS5vZmZzZXQ9PT10Lm9mZnNldD90PW46ZT1uO3JldHVybiB0fWZ1bmN0aW9uIGIodCxlKXtyZXR1cm4gdC5vZmZzZXRTY29yZSE9PWUub2Zmc2V0U2NvcmU/dC5vZmZzZXRTY29yZS1lLm9mZnNldFNjb3JlOnQuYWJiclNjb3JlIT09ZS5hYmJyU2NvcmU/dC5hYmJyU2NvcmUtZS5hYmJyU2NvcmU6dC56b25lLnBvcHVsYXRpb24hPT1lLnpvbmUucG9wdWxhdGlvbj9lLnpvbmUucG9wdWxhdGlvbi10LnpvbmUucG9wdWxhdGlvbjplLnpvbmUubmFtZS5sb2NhbGVDb21wYXJlKHQuem9uZS5uYW1lKX1mdW5jdGlvbiBnKHQsZSl7dmFyIG4sbztmb3IobChlKSxuPTA7bjxlLmxlbmd0aDtuKyspbz1lW25dLGNbb109Y1tvXXx8e30sY1tvXVt0XT0hMH1mdW5jdGlvbiBfKCl7dHJ5e3ZhciB0PUludGwuRGF0ZVRpbWVGb3JtYXQoKS5yZXNvbHZlZE9wdGlvbnMoKS50aW1lWm9uZTtpZih0JiYzPHQubGVuZ3RoKXt2YXIgZT11W3codCldO2lmKGUpcmV0dXJuIGU7QShcIk1vbWVudCBUaW1lem9uZSBmb3VuZCBcIit0K1wiIGZyb20gdGhlIEludGwgYXBpLCBidXQgZGlkIG5vdCBoYXZlIHRoYXQgZGF0YSBsb2FkZWQuXCIpfX1jYXRjaCh0KXt9dmFyIG4sbyxyLHM9ZnVuY3Rpb24oKXt2YXIgdCxlLG4sbz0obmV3IERhdGUpLmdldEZ1bGxZZWFyKCktMixyPW5ldyBkKG5ldyBEYXRlKG8sMCwxKSkscz1bcl07Zm9yKG49MTtuPDQ4O24rKykoZT1uZXcgZChuZXcgRGF0ZShvLG4sMSkpKS5vZmZzZXQhPT1yLm9mZnNldCYmKHQ9dihyLGUpLHMucHVzaCh0KSxzLnB1c2gobmV3IGQobmV3IERhdGUodC5hdCs2ZTQpKSkpLHI9ZTtmb3Iobj0wO248NDtuKyspcy5wdXNoKG5ldyBkKG5ldyBEYXRlKG8rbiwwLDEpKSkscy5wdXNoKG5ldyBkKG5ldyBEYXRlKG8rbiw2LDEpKSk7cmV0dXJuIHN9KCksaT1zLmxlbmd0aCxmPWZ1bmN0aW9uKHQpe3ZhciBlLG4sbyxyPXQubGVuZ3RoLHM9e30saT1bXTtmb3IoZT0wO2U8cjtlKyspZm9yKG4gaW4gbz1jW3RbZV0ub2Zmc2V0XXx8e30pby5oYXNPd25Qcm9wZXJ0eShuKSYmKHNbbl09ITApO2ZvcihlIGluIHMpcy5oYXNPd25Qcm9wZXJ0eShlKSYmaS5wdXNoKHVbZV0pO3JldHVybiBpfShzKSxhPVtdO2ZvcihvPTA7bzxmLmxlbmd0aDtvKyspe2ZvcihuPW5ldyB6KE8oZltvXSksaSkscj0wO3I8aTtyKyspbi5zY29yZU9mZnNldEF0KHNbcl0pO2EucHVzaChuKX1yZXR1cm4gYS5zb3J0KGIpLDA8YS5sZW5ndGg/YVswXS56b25lLm5hbWU6dm9pZCAwfWZ1bmN0aW9uIHcodCl7cmV0dXJuKHR8fFwiXCIpLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFwvL2csXCJfXCIpfWZ1bmN0aW9uIHkodCl7dmFyIGUsbixvLHI7Zm9yKFwic3RyaW5nXCI9PXR5cGVvZiB0JiYodD1bdF0pLGU9MDtlPHQubGVuZ3RoO2UrKylyPXcobj0obz10W2VdLnNwbGl0KFwifFwiKSlbMF0pLGlbcl09dFtlXSx1W3JdPW4sZyhyLG9bMl0uc3BsaXQoXCIgXCIpKX1mdW5jdGlvbiBPKHQsZSl7dD13KHQpO3ZhciBuLG89aVt0XTtyZXR1cm4gbyBpbnN0YW5jZW9mIG0/bzpcInN0cmluZ1wiPT10eXBlb2Ygbz8obz1uZXcgbShvKSxpW3RdPW8pOmZbdF0mJmUhPT1PJiYobj1PKGZbdF0sTykpPygobz1pW3RdPW5ldyBtKS5fc2V0KG4pLG8ubmFtZT11W3RdLG8pOm51bGx9ZnVuY3Rpb24gUyh0KXt2YXIgZSxuLG8scjtmb3IoXCJzdHJpbmdcIj09dHlwZW9mIHQmJih0PVt0XSksZT0wO2U8dC5sZW5ndGg7ZSsrKW89dygobj10W2VdLnNwbGl0KFwifFwiKSlbMF0pLHI9dyhuWzFdKSxmW29dPXIsdVtvXT1uWzBdLGZbcl09byx1W3JdPW5bMV19ZnVuY3Rpb24gTSh0KXt2YXIgZT1cIlhcIj09PXQuX2Z8fFwieFwiPT09dC5fZjtyZXR1cm4hKCF0Ll9hfHx2b2lkIDAhPT10Ll90em18fGUpfWZ1bmN0aW9uIEEodCl7XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGNvbnNvbGUmJlwiZnVuY3Rpb25cIj09dHlwZW9mIGNvbnNvbGUuZXJyb3ImJmNvbnNvbGUuZXJyb3IodCl9ZnVuY3Rpb24gaih0KXt2YXIgZT1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsMCwtMSksbj1hcmd1bWVudHNbYXJndW1lbnRzLmxlbmd0aC0xXSxvPU8obikscj1zLnV0Yy5hcHBseShudWxsLGUpO3JldHVybiBvJiYhcy5pc01vbWVudCh0KSYmTShyKSYmci5hZGQoby5wYXJzZShyKSxcIm1pbnV0ZXNcIiksci50eihuKSxyfShuPDJ8fDI9PW4mJm88NikmJkEoXCJNb21lbnQgVGltZXpvbmUgcmVxdWlyZXMgTW9tZW50LmpzID49IDIuNi4wLiBZb3UgYXJlIHVzaW5nIE1vbWVudC5qcyBcIitzLnZlcnNpb24rXCIuIFNlZSBtb21lbnRqcy5jb21cIiksbS5wcm90b3R5cGU9e19zZXQ6ZnVuY3Rpb24odCl7dGhpcy5uYW1lPXQubmFtZSx0aGlzLmFiYnJzPXQuYWJicnMsdGhpcy51bnRpbHM9dC51bnRpbHMsdGhpcy5vZmZzZXRzPXQub2Zmc2V0cyx0aGlzLnBvcHVsYXRpb249dC5wb3B1bGF0aW9ufSxfaW5kZXg6ZnVuY3Rpb24odCl7dmFyIGUsbj0rdCxvPXRoaXMudW50aWxzO2ZvcihlPTA7ZTxvLmxlbmd0aDtlKyspaWYobjxvW2VdKXJldHVybiBlfSxwYXJzZTpmdW5jdGlvbih0KXt2YXIgZSxuLG8scixzPSt0LGk9dGhpcy5vZmZzZXRzLGY9dGhpcy51bnRpbHMsYT1mLmxlbmd0aC0xO2ZvcihyPTA7cjxhO3IrKylpZihlPWlbcl0sbj1pW3IrMV0sbz1pW3I/ci0xOnJdLGU8biYmai5tb3ZlQW1iaWd1b3VzRm9yd2FyZD9lPW46bzxlJiZqLm1vdmVJbnZhbGlkRm9yd2FyZCYmKGU9byksczxmW3JdLTZlNCplKXJldHVybiBpW3JdO3JldHVybiBpW2FdfSxhYmJyOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmFiYnJzW3RoaXMuX2luZGV4KHQpXX0sb2Zmc2V0OmZ1bmN0aW9uKHQpe3JldHVybiBBKFwiem9uZS5vZmZzZXQgaGFzIGJlZW4gZGVwcmVjYXRlZCBpbiBmYXZvciBvZiB6b25lLnV0Y09mZnNldFwiKSx0aGlzLm9mZnNldHNbdGhpcy5faW5kZXgodCldfSx1dGNPZmZzZXQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMub2Zmc2V0c1t0aGlzLl9pbmRleCh0KV19fSx6LnByb3RvdHlwZS5zY29yZU9mZnNldEF0PWZ1bmN0aW9uKHQpe3RoaXMub2Zmc2V0U2NvcmUrPU1hdGguYWJzKHRoaXMuem9uZS51dGNPZmZzZXQodC5hdCktdC5vZmZzZXQpLHRoaXMuem9uZS5hYmJyKHQuYXQpLnJlcGxhY2UoL1teQS1aXS9nLFwiXCIpIT09dC5hYmJyJiZ0aGlzLmFiYnJTY29yZSsrfSxqLnZlcnNpb249XCIwLjUuMjdcIixqLmRhdGFWZXJzaW9uPVwiXCIsai5fem9uZXM9aSxqLl9saW5rcz1mLGouX25hbWVzPXUsai5hZGQ9eSxqLmxpbms9UyxqLmxvYWQ9ZnVuY3Rpb24odCl7eSh0LnpvbmVzKSxTKHQubGlua3MpLGouZGF0YVZlcnNpb249dC52ZXJzaW9ufSxqLnpvbmU9TyxqLnpvbmVFeGlzdHM9ZnVuY3Rpb24gdChlKXtyZXR1cm4gdC5kaWRTaG93RXJyb3J8fCh0LmRpZFNob3dFcnJvcj0hMCxBKFwibW9tZW50LnR6LnpvbmVFeGlzdHMoJ1wiK2UrXCInKSBoYXMgYmVlbiBkZXByZWNhdGVkIGluIGZhdm9yIG9mICFtb21lbnQudHouem9uZSgnXCIrZStcIicpXCIpKSwhIU8oZSl9LGouZ3Vlc3M9ZnVuY3Rpb24odCl7cmV0dXJuIGUmJiF0fHwoZT1fKCkpLGV9LGoubmFtZXM9ZnVuY3Rpb24oKXt2YXIgdCxlPVtdO2Zvcih0IGluIHUpdS5oYXNPd25Qcm9wZXJ0eSh0KSYmKGlbdF18fGlbZlt0XV0pJiZ1W3RdJiZlLnB1c2godVt0XSk7cmV0dXJuIGUuc29ydCgpfSxqLlpvbmU9bSxqLnVucGFjaz1wLGoudW5wYWNrQmFzZTYwPXIsai5uZWVkc09mZnNldD1NLGoubW92ZUludmFsaWRGb3J3YXJkPSEwLGoubW92ZUFtYmlndW91c0ZvcndhcmQ9ITE7dmFyIFQsRD1zLmZuO2Z1bmN0aW9uIHgodCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3o/dGhpcy5fei5hYmJyKHRoaXMpOnQuY2FsbCh0aGlzKX19ZnVuY3Rpb24gWih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fej1udWxsLHQuYXBwbHkodGhpcyxhcmd1bWVudHMpfX1zLnR6PWoscy5kZWZhdWx0Wm9uZT1udWxsLHMudXBkYXRlT2Zmc2V0PWZ1bmN0aW9uKHQsZSl7dmFyIG4sbz1zLmRlZmF1bHRab25lO2lmKHZvaWQgMD09PXQuX3omJihvJiZNKHQpJiYhdC5faXNVVEMmJih0Ll9kPXMudXRjKHQuX2EpLl9kLHQudXRjKCkuYWRkKG8ucGFyc2UodCksXCJtaW51dGVzXCIpKSx0Ll96PW8pLHQuX3opaWYobj10Ll96LnV0Y09mZnNldCh0KSxNYXRoLmFicyhuKTwxNiYmKG4vPTYwKSx2b2lkIDAhPT10LnV0Y09mZnNldCl7dmFyIHI9dC5fejt0LnV0Y09mZnNldCgtbixlKSx0Ll96PXJ9ZWxzZSB0LnpvbmUobixlKX0sRC50ej1mdW5jdGlvbih0LGUpe2lmKHQpe2lmKFwic3RyaW5nXCIhPXR5cGVvZiB0KXRocm93IG5ldyBFcnJvcihcIlRpbWUgem9uZSBuYW1lIG11c3QgYmUgYSBzdHJpbmcsIGdvdCBcIit0K1wiIFtcIit0eXBlb2YgdCtcIl1cIik7cmV0dXJuIHRoaXMuX3o9Tyh0KSx0aGlzLl96P3MudXBkYXRlT2Zmc2V0KHRoaXMsZSk6QShcIk1vbWVudCBUaW1lem9uZSBoYXMgbm8gZGF0YSBmb3IgXCIrdCtcIi4gU2VlIGh0dHA6Ly9tb21lbnRqcy5jb20vdGltZXpvbmUvZG9jcy8jL2RhdGEtbG9hZGluZy8uXCIpLHRoaXN9aWYodGhpcy5feilyZXR1cm4gdGhpcy5fei5uYW1lfSxELnpvbmVOYW1lPXgoRC56b25lTmFtZSksRC56b25lQWJicj14KEQuem9uZUFiYnIpLEQudXRjPVooRC51dGMpLEQubG9jYWw9WihELmxvY2FsKSxELnV0Y09mZnNldD0oVD1ELnV0Y09mZnNldCxmdW5jdGlvbigpe3JldHVybiAwPGFyZ3VtZW50cy5sZW5ndGgmJih0aGlzLl96PW51bGwpLFQuYXBwbHkodGhpcyxhcmd1bWVudHMpfSkscy50ei5zZXREZWZhdWx0PWZ1bmN0aW9uKHQpe3JldHVybihuPDJ8fDI9PW4mJm88OSkmJkEoXCJNb21lbnQgVGltZXpvbmUgc2V0RGVmYXVsdCgpIHJlcXVpcmVzIE1vbWVudC5qcyA+PSAyLjkuMC4gWW91IGFyZSB1c2luZyBNb21lbnQuanMgXCIrcy52ZXJzaW9uK1wiLlwiKSxzLmRlZmF1bHRab25lPXQ/Tyh0KTpudWxsLHN9O3ZhciBDPXMubW9tZW50UHJvcGVydGllcztyZXR1cm5cIltvYmplY3QgQXJyYXldXCI9PT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoQyk/KEMucHVzaChcIl96XCIpLEMucHVzaChcIl9hXCIpKTpDJiYoQy5fej1udWxsKSxzfSk7IiwidmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBJbmNvbnNpc3RlbnROYW1pbmdcbnZhciBEYXRlVGltZVBpY2tlciA9IGZ1bmN0aW9uICgkLCBtb21lbnQpIHtcbiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBJbmNvbnNpc3RlbnROYW1pbmdcbiAgICB2YXIgTkFNRSA9ICdkYXRldGltZXBpY2tlcicsXG4gICAgICAgIERBVEFfS0VZID0gJycgKyBOQU1FLFxuICAgICAgICBFVkVOVF9LRVkgPSAnLicgKyBEQVRBX0tFWSxcbiAgICAgICAgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaScsXG4gICAgICAgIFNlbGVjdG9yID0ge1xuICAgICAgICBEQVRBX1RPR0dMRTogJ1tkYXRhLXRvZ2dsZT1cIicgKyBEQVRBX0tFWSArICdcIl0nXG4gICAgfSxcbiAgICAgICAgQ2xhc3NOYW1lID0ge1xuICAgICAgICBJTlBVVDogTkFNRSArICctaW5wdXQnXG4gICAgfSxcbiAgICAgICAgRXZlbnQgPSB7XG4gICAgICAgIENIQU5HRTogJ2NoYW5nZScgKyBFVkVOVF9LRVksXG4gICAgICAgIEJMVVI6ICdibHVyJyArIEVWRU5UX0tFWSxcbiAgICAgICAgS0VZVVA6ICdrZXl1cCcgKyBFVkVOVF9LRVksXG4gICAgICAgIEtFWURPV046ICdrZXlkb3duJyArIEVWRU5UX0tFWSxcbiAgICAgICAgRk9DVVM6ICdmb2N1cycgKyBFVkVOVF9LRVksXG4gICAgICAgIENMSUNLX0RBVEFfQVBJOiAnY2xpY2snICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZLFxuICAgICAgICAvL2VtaXR0ZWRcbiAgICAgICAgVVBEQVRFOiAndXBkYXRlJyArIEVWRU5UX0tFWSxcbiAgICAgICAgRVJST1I6ICdlcnJvcicgKyBFVkVOVF9LRVksXG4gICAgICAgIEhJREU6ICdoaWRlJyArIEVWRU5UX0tFWSxcbiAgICAgICAgU0hPVzogJ3Nob3cnICsgRVZFTlRfS0VZXG4gICAgfSxcbiAgICAgICAgRGF0ZVBpY2tlck1vZGVzID0gW3tcbiAgICAgICAgQ0xBU1NfTkFNRTogJ2RheXMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICdNJyxcbiAgICAgICAgTkFWX1NURVA6IDFcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICdtb250aHMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICAgICAgTkFWX1NURVA6IDFcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICd5ZWFycycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ3knLFxuICAgICAgICBOQVZfU1RFUDogMTBcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICdkZWNhZGVzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAneScsXG4gICAgICAgIE5BVl9TVEVQOiAxMDBcbiAgICB9XSxcbiAgICAgICAgS2V5TWFwID0ge1xuICAgICAgICAndXAnOiAzOCxcbiAgICAgICAgMzg6ICd1cCcsXG4gICAgICAgICdkb3duJzogNDAsXG4gICAgICAgIDQwOiAnZG93bicsXG4gICAgICAgICdsZWZ0JzogMzcsXG4gICAgICAgIDM3OiAnbGVmdCcsXG4gICAgICAgICdyaWdodCc6IDM5LFxuICAgICAgICAzOTogJ3JpZ2h0JyxcbiAgICAgICAgJ3RhYic6IDksXG4gICAgICAgIDk6ICd0YWInLFxuICAgICAgICAnZXNjYXBlJzogMjcsXG4gICAgICAgIDI3OiAnZXNjYXBlJyxcbiAgICAgICAgJ2VudGVyJzogMTMsXG4gICAgICAgIDEzOiAnZW50ZXInLFxuICAgICAgICAncGFnZVVwJzogMzMsXG4gICAgICAgIDMzOiAncGFnZVVwJyxcbiAgICAgICAgJ3BhZ2VEb3duJzogMzQsXG4gICAgICAgIDM0OiAncGFnZURvd24nLFxuICAgICAgICAnc2hpZnQnOiAxNixcbiAgICAgICAgMTY6ICdzaGlmdCcsXG4gICAgICAgICdjb250cm9sJzogMTcsXG4gICAgICAgIDE3OiAnY29udHJvbCcsXG4gICAgICAgICdzcGFjZSc6IDMyLFxuICAgICAgICAzMjogJ3NwYWNlJyxcbiAgICAgICAgJ3QnOiA4NCxcbiAgICAgICAgODQ6ICd0JyxcbiAgICAgICAgJ2RlbGV0ZSc6IDQ2LFxuICAgICAgICA0NjogJ2RlbGV0ZSdcbiAgICB9LFxuICAgICAgICBWaWV3TW9kZXMgPSBbJ3RpbWVzJywgJ2RheXMnLCAnbW9udGhzJywgJ3llYXJzJywgJ2RlY2FkZXMnXSxcbiAgICAgICAga2V5U3RhdGUgPSB7fSxcbiAgICAgICAga2V5UHJlc3NIYW5kbGVkID0ge307XG5cbiAgICB2YXIgRGVmYXVsdCA9IHtcbiAgICAgICAgdGltZVpvbmU6ICcnLFxuICAgICAgICBmb3JtYXQ6IGZhbHNlLFxuICAgICAgICBkYXlWaWV3SGVhZGVyRm9ybWF0OiAnTU1NTSBZWVlZJyxcbiAgICAgICAgZXh0cmFGb3JtYXRzOiBmYWxzZSxcbiAgICAgICAgc3RlcHBpbmc6IDEsXG4gICAgICAgIG1pbkRhdGU6IGZhbHNlLFxuICAgICAgICBtYXhEYXRlOiBmYWxzZSxcbiAgICAgICAgdXNlQ3VycmVudDogdHJ1ZSxcbiAgICAgICAgY29sbGFwc2U6IHRydWUsXG4gICAgICAgIGxvY2FsZTogbW9tZW50LmxvY2FsZSgpLFxuICAgICAgICBkZWZhdWx0RGF0ZTogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkRGF0ZXM6IGZhbHNlLFxuICAgICAgICBlbmFibGVkRGF0ZXM6IGZhbHNlLFxuICAgICAgICBpY29uczoge1xuICAgICAgICAgICAgdGltZTogJ2ZhIGZhLWNsb2NrLW8nLFxuICAgICAgICAgICAgZGF0ZTogJ2ZhIGZhLWNhbGVuZGFyJyxcbiAgICAgICAgICAgIHVwOiAnZmEgZmEtYXJyb3ctdXAnLFxuICAgICAgICAgICAgZG93bjogJ2ZhIGZhLWFycm93LWRvd24nLFxuICAgICAgICAgICAgcHJldmlvdXM6ICdmYSBmYS1jaGV2cm9uLWxlZnQnLFxuICAgICAgICAgICAgbmV4dDogJ2ZhIGZhLWNoZXZyb24tcmlnaHQnLFxuICAgICAgICAgICAgdG9kYXk6ICdmYSBmYS1jYWxlbmRhci1jaGVjay1vJyxcbiAgICAgICAgICAgIGNsZWFyOiAnZmEgZmEtZGVsZXRlJyxcbiAgICAgICAgICAgIGNsb3NlOiAnZmEgZmEtdGltZXMnXG4gICAgICAgIH0sXG4gICAgICAgIHRvb2x0aXBzOiB7XG4gICAgICAgICAgICB0b2RheTogJ0dvIHRvIHRvZGF5JyxcbiAgICAgICAgICAgIGNsZWFyOiAnQ2xlYXIgc2VsZWN0aW9uJyxcbiAgICAgICAgICAgIGNsb3NlOiAnQ2xvc2UgdGhlIHBpY2tlcicsXG4gICAgICAgICAgICBzZWxlY3RNb250aDogJ1NlbGVjdCBNb250aCcsXG4gICAgICAgICAgICBwcmV2TW9udGg6ICdQcmV2aW91cyBNb250aCcsXG4gICAgICAgICAgICBuZXh0TW9udGg6ICdOZXh0IE1vbnRoJyxcbiAgICAgICAgICAgIHNlbGVjdFllYXI6ICdTZWxlY3QgWWVhcicsXG4gICAgICAgICAgICBwcmV2WWVhcjogJ1ByZXZpb3VzIFllYXInLFxuICAgICAgICAgICAgbmV4dFllYXI6ICdOZXh0IFllYXInLFxuICAgICAgICAgICAgc2VsZWN0RGVjYWRlOiAnU2VsZWN0IERlY2FkZScsXG4gICAgICAgICAgICBwcmV2RGVjYWRlOiAnUHJldmlvdXMgRGVjYWRlJyxcbiAgICAgICAgICAgIG5leHREZWNhZGU6ICdOZXh0IERlY2FkZScsXG4gICAgICAgICAgICBwcmV2Q2VudHVyeTogJ1ByZXZpb3VzIENlbnR1cnknLFxuICAgICAgICAgICAgbmV4dENlbnR1cnk6ICdOZXh0IENlbnR1cnknLFxuICAgICAgICAgICAgcGlja0hvdXI6ICdQaWNrIEhvdXInLFxuICAgICAgICAgICAgaW5jcmVtZW50SG91cjogJ0luY3JlbWVudCBIb3VyJyxcbiAgICAgICAgICAgIGRlY3JlbWVudEhvdXI6ICdEZWNyZW1lbnQgSG91cicsXG4gICAgICAgICAgICBwaWNrTWludXRlOiAnUGljayBNaW51dGUnLFxuICAgICAgICAgICAgaW5jcmVtZW50TWludXRlOiAnSW5jcmVtZW50IE1pbnV0ZScsXG4gICAgICAgICAgICBkZWNyZW1lbnRNaW51dGU6ICdEZWNyZW1lbnQgTWludXRlJyxcbiAgICAgICAgICAgIHBpY2tTZWNvbmQ6ICdQaWNrIFNlY29uZCcsXG4gICAgICAgICAgICBpbmNyZW1lbnRTZWNvbmQ6ICdJbmNyZW1lbnQgU2Vjb25kJyxcbiAgICAgICAgICAgIGRlY3JlbWVudFNlY29uZDogJ0RlY3JlbWVudCBTZWNvbmQnLFxuICAgICAgICAgICAgdG9nZ2xlUGVyaW9kOiAnVG9nZ2xlIFBlcmlvZCcsXG4gICAgICAgICAgICBzZWxlY3RUaW1lOiAnU2VsZWN0IFRpbWUnLFxuICAgICAgICAgICAgc2VsZWN0RGF0ZTogJ1NlbGVjdCBEYXRlJ1xuICAgICAgICB9LFxuICAgICAgICB1c2VTdHJpY3Q6IGZhbHNlLFxuICAgICAgICBzaWRlQnlTaWRlOiBmYWxzZSxcbiAgICAgICAgZGF5c09mV2Vla0Rpc2FibGVkOiBmYWxzZSxcbiAgICAgICAgY2FsZW5kYXJXZWVrczogZmFsc2UsXG4gICAgICAgIHZpZXdNb2RlOiAnZGF5cycsXG4gICAgICAgIHRvb2xiYXJQbGFjZW1lbnQ6ICdkZWZhdWx0JyxcbiAgICAgICAgYnV0dG9uczoge1xuICAgICAgICAgICAgc2hvd1RvZGF5OiBmYWxzZSxcbiAgICAgICAgICAgIHNob3dDbGVhcjogZmFsc2UsXG4gICAgICAgICAgICBzaG93Q2xvc2U6IGZhbHNlXG4gICAgICAgIH0sXG4gICAgICAgIHdpZGdldFBvc2l0aW9uaW5nOiB7XG4gICAgICAgICAgICBob3Jpem9udGFsOiAnYXV0bycsXG4gICAgICAgICAgICB2ZXJ0aWNhbDogJ2F1dG8nXG4gICAgICAgIH0sXG4gICAgICAgIHdpZGdldFBhcmVudDogbnVsbCxcbiAgICAgICAgaWdub3JlUmVhZG9ubHk6IGZhbHNlLFxuICAgICAgICBrZWVwT3BlbjogZmFsc2UsXG4gICAgICAgIGZvY3VzT25TaG93OiB0cnVlLFxuICAgICAgICBpbmxpbmU6IGZhbHNlLFxuICAgICAgICBrZWVwSW52YWxpZDogZmFsc2UsXG4gICAgICAgIGtleUJpbmRzOiB7XG4gICAgICAgICAgICB1cDogZnVuY3Rpb24gdXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDcsICdkJykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKHRoaXMuc3RlcHBpbmcoKSwgJ20nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRvd246IGZ1bmN0aW9uIGRvd24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoNywgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLnN0ZXBwaW5nKCksICdtJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnY29udHJvbCB1cCc6IGZ1bmN0aW9uIGNvbnRyb2xVcCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ3knKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ2gnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdjb250cm9sIGRvd24nOiBmdW5jdGlvbiBjb250cm9sRG93bigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICd5JykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ2gnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxlZnQ6IGZ1bmN0aW9uIGxlZnQoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdkJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByaWdodDogZnVuY3Rpb24gcmlnaHQoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFnZVVwOiBmdW5jdGlvbiBwYWdlVXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdNJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYWdlRG93bjogZnVuY3Rpb24gcGFnZURvd24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnTScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uIGVudGVyKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlc2NhcGU6IGZ1bmN0aW9uIGVzY2FwZSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2NvbnRyb2wgc3BhY2UnOiBmdW5jdGlvbiBjb250cm9sU3BhY2UoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5idG5bZGF0YS1hY3Rpb249XCJ0b2dnbGVQZXJpb2RcIl0nKS5jbGljaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0OiBmdW5jdGlvbiB0KCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmRhdGUodGhpcy5nZXRNb21lbnQoKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2RlbGV0ZSc6IGZ1bmN0aW9uIF9kZWxldGUoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGVidWc6IGZhbHNlLFxuICAgICAgICBhbGxvd0lucHV0VG9nZ2xlOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWRUaW1lSW50ZXJ2YWxzOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWRIb3VyczogZmFsc2UsXG4gICAgICAgIGVuYWJsZWRIb3VyczogZmFsc2UsXG4gICAgICAgIHZpZXdEYXRlOiBmYWxzZSxcbiAgICAgICAgYWxsb3dNdWx0aWRhdGU6IGZhbHNlLFxuICAgICAgICBtdWx0aWRhdGVTZXBhcmF0b3I6ICcsJ1xuICAgIH07XG5cbiAgICAvLyBSZVNoYXJwZXIgcmVzdG9yZSBJbmNvbnNpc3RlbnROYW1pbmdcblxuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgRGVjbGFyYXRpb25IaWRlc1xuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG5cbiAgICB2YXIgRGF0ZVRpbWVQaWNrZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8qKiBAbmFtZXNwYWNlIGVEYXRhLmRhdGVPcHRpb25zICovXG4gICAgICAgIC8qKiBAbmFtZXNwYWNlIG1vbWVudC50eiAqL1xuXG4gICAgICAgIGZ1bmN0aW9uIERhdGVUaW1lUGlja2VyKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBEYXRlVGltZVBpY2tlcik7XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMgPSB0aGlzLl9nZXRPcHRpb25zKG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgICAgICB0aGlzLl9kYXRlcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWQgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudW5zZXQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnVzZTI0SG91cnMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5hY3R1YWxGb3JtYXQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wYXJzZUZvcm1hdHMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDA7XG5cbiAgICAgICAgICAgIHRoaXMuX2ludCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAqL1xuXG5cbiAgICAgICAgLy9wcml2YXRlXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbnQgPSBmdW5jdGlvbiBfaW50KCkge1xuICAgICAgICAgICAgdmFyIHRhcmdldElucHV0ID0gdGhpcy5fZWxlbWVudC5kYXRhKCd0YXJnZXQtaW5wdXQnKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9lbGVtZW50LmlzKCdpbnB1dCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dCA9IHRoaXMuX2VsZW1lbnQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldElucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0SW5wdXQgPT09ICduZWFyZXN0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0ID0gdGhpcy5fZWxlbWVudC5maW5kKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQgPSAkKHRhcmdldElucHV0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICAgICAgICB0aGlzLl9kYXRlc1swXSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCkuY2xvbmUoKTtcblxuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgdGhpcy5fb3B0aW9ucywgdGhpcy5fZGF0YVRvT3B0aW9ucygpKTtcblxuICAgICAgICAgICAgdGhpcy5vcHRpb25zKHRoaXMuX29wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQuaXMoJ2lucHV0JykgJiYgdGhpcy5pbnB1dC52YWwoKS50cmltKCkubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fcGFyc2VJbnB1dERhdGUodGhpcy5pbnB1dC52YWwoKS50cmltKCkpLCAwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiB0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC5hdHRyKCdwbGFjZWhvbGRlcicpID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fdXBkYXRlID0gZnVuY3Rpb24gX3VwZGF0ZSgpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fZmlsbFRpbWUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3NldFZhbHVlID0gZnVuY3Rpb24gX3NldFZhbHVlKHRhcmdldE1vbWVudCwgaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBvbGREYXRlID0gdGhpcy51bnNldCA/IG51bGwgOiB0aGlzLl9kYXRlc1tpbmRleF07XG4gICAgICAgICAgICB2YXIgb3V0cFZhbHVlID0gJyc7XG4gICAgICAgICAgICAvLyBjYXNlIG9mIGNhbGxpbmcgc2V0VmFsdWUobnVsbCBvciBmYWxzZSlcbiAgICAgICAgICAgIGlmICghdGFyZ2V0TW9tZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlIHx8IHRoaXMuX2RhdGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVuc2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWQgPSBbXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnKSArICcsJztcbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gb3V0cFZhbHVlLnJlcGxhY2Uob2xkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpICsgJywnLCAnJykucmVwbGFjZSgnLCwnLCAnJykucmVwbGFjZSgvLFxccyokLywgJycpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5kYXRhKCdkYXRlJywgb3V0cFZhbHVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRhcmdldE1vbWVudCA9IHRhcmdldE1vbWVudC5jbG9uZSgpLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0TW9tZW50LnR6KHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5zdGVwcGluZyAhPT0gMSkge1xuICAgICAgICAgICAgICAgIHRhcmdldE1vbWVudC5taW51dGVzKE1hdGgucm91bmQodGFyZ2V0TW9tZW50Lm1pbnV0ZXMoKSAvIHRoaXMuX29wdGlvbnMuc3RlcHBpbmcpICogdGhpcy5fb3B0aW9ucy5zdGVwcGluZykuc2Vjb25kcygwKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQodGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2luZGV4XSA9IHRhcmdldE1vbWVudDtcbiAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZFtpbmRleF0gPSB0YXJnZXRNb21lbnQuZm9ybWF0KCdZWVlZLU1NLUREJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSB0YXJnZXRNb21lbnQuY2xvbmUoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSAmJiB0aGlzLl9kYXRlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSArPSAnJyArIHRoaXMuX2RhdGVzW2ldLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkgKyB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSBvdXRwVmFsdWUucmVwbGFjZSgvLFxccyokLywgJycpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSA9IHRoaXMuX2RhdGVzW2luZGV4XS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5kYXRhKCdkYXRlJywgb3V0cFZhbHVlKTtcblxuICAgICAgICAgICAgICAgIHRoaXMudW5zZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogdGhpcy5fZGF0ZXNbaW5kZXhdLmNsb25lKCksXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKCcnICsgKHRoaXMudW5zZXQgPyAnJyA6IHRoaXMuX2RhdGVzW2luZGV4XS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnRyaWdnZXIoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkVSUk9SLFxuICAgICAgICAgICAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQsXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2NoYW5nZSA9IGZ1bmN0aW9uIF9jaGFuZ2UoZSkge1xuICAgICAgICAgICAgdmFyIHZhbCA9ICQoZS50YXJnZXQpLnZhbCgpLnRyaW0oKSxcbiAgICAgICAgICAgICAgICBwYXJzZWREYXRlID0gdmFsID8gdGhpcy5fcGFyc2VJbnB1dERhdGUodmFsKSA6IG51bGw7XG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShwYXJzZWREYXRlKTtcbiAgICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNNZXRob2RDYW5CZVN0YXRpY1xuXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9nZXRPcHRpb25zID0gZnVuY3Rpb24gX2dldE9wdGlvbnMob3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIHt9LCBEZWZhdWx0LCBvcHRpb25zKTtcbiAgICAgICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzVGltZVpvbmUgPSBmdW5jdGlvbiBfaGFzVGltZVpvbmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9tZW50LnR6ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuX29wdGlvbnMudGltZVpvbmUgIT09IG51bGwgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gJyc7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0VuYWJsZWQgPSBmdW5jdGlvbiBfaXNFbmFibGVkKGdyYW51bGFyaXR5KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGdyYW51bGFyaXR5ICE9PSAnc3RyaW5nJyB8fCBncmFudWxhcml0eS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaXNFbmFibGVkIGV4cGVjdHMgYSBzaW5nbGUgY2hhcmFjdGVyIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN3aXRjaCAoZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgICAgICAgICBjYXNlICd5JzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ1knKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC5pbmRleE9mKCdNJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdkJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0gnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdoJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZignbScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ3MnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnYSc6XG4gICAgICAgICAgICAgICAgY2FzZSAnQSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2EnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzVGltZSA9IGZ1bmN0aW9uIF9oYXNUaW1lKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzRW5hYmxlZCgnaCcpIHx8IHRoaXMuX2lzRW5hYmxlZCgnbScpIHx8IHRoaXMuX2lzRW5hYmxlZCgncycpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzRGF0ZSA9IGZ1bmN0aW9uIF9oYXNEYXRlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzRW5hYmxlZCgneScpIHx8IHRoaXMuX2lzRW5hYmxlZCgnTScpIHx8IHRoaXMuX2lzRW5hYmxlZCgnZCcpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZGF0YVRvT3B0aW9ucyA9IGZ1bmN0aW9uIF9kYXRhVG9PcHRpb25zKCkge1xuICAgICAgICAgICAgdmFyIGVEYXRhID0gdGhpcy5fZWxlbWVudC5kYXRhKCk7XG4gICAgICAgICAgICB2YXIgZGF0YU9wdGlvbnMgPSB7fTtcblxuICAgICAgICAgICAgaWYgKGVEYXRhLmRhdGVPcHRpb25zICYmIGVEYXRhLmRhdGVPcHRpb25zIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgZGF0YU9wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCBkYXRhT3B0aW9ucywgZURhdGEuZGF0ZU9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucywgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgICAgIHZhciBhdHRyaWJ1dGVOYW1lID0gJ2RhdGUnICsga2V5LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsga2V5LnNsaWNlKDEpOyAvL3RvZG8gZGF0YSBhcGkga2V5XG4gICAgICAgICAgICAgICAgaWYgKGVEYXRhW2F0dHJpYnV0ZU5hbWVdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YU9wdGlvbnNba2V5XSA9IGVEYXRhW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBkYXRhT3B0aW9uc1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGRhdGFPcHRpb25zO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fbm90aWZ5RXZlbnQgPSBmdW5jdGlvbiBfbm90aWZ5RXZlbnQoZSkge1xuICAgICAgICAgICAgaWYgKGUudHlwZSA9PT0gRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFICYmIChlLmRhdGUgJiYgZS5kYXRlLmlzU2FtZShlLm9sZERhdGUpKSB8fCAhZS5kYXRlICYmICFlLm9sZERhdGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50LnRyaWdnZXIoZSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl92aWV3VXBkYXRlID0gZnVuY3Rpb24gX3ZpZXdVcGRhdGUoZSkge1xuICAgICAgICAgICAgaWYgKGUgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgIGUgPSAnWVlZWSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuVVBEQVRFLFxuICAgICAgICAgICAgICAgIGNoYW5nZTogZSxcbiAgICAgICAgICAgICAgICB2aWV3RGF0ZTogdGhpcy5fdmlld0RhdGUuY2xvbmUoKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9zaG93TW9kZSA9IGZ1bmN0aW9uIF9zaG93TW9kZShkaXIpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGlyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heCh0aGlzLk1pblZpZXdNb2RlTnVtYmVyLCBNYXRoLm1pbigzLCB0aGlzLmN1cnJlbnRWaWV3TW9kZSArIGRpcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXIgPiBkaXYnKS5oaWRlKCkuZmlsdGVyKCcuZGF0ZXBpY2tlci0nICsgRGF0ZVBpY2tlck1vZGVzW3RoaXMuY3VycmVudFZpZXdNb2RlXS5DTEFTU19OQU1FKS5zaG93KCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRGlzYWJsZWREYXRlcyA9IGZ1bmN0aW9uIF9pc0luRGlzYWJsZWREYXRlcyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlc1t0ZXN0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRW5hYmxlZERhdGVzID0gZnVuY3Rpb24gX2lzSW5FbmFibGVkRGF0ZXModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlc1t0ZXN0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRGlzYWJsZWRIb3VycyA9IGZ1bmN0aW9uIF9pc0luRGlzYWJsZWRIb3Vycyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3Vyc1t0ZXN0RGF0ZS5mb3JtYXQoJ0gnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRW5hYmxlZEhvdXJzID0gZnVuY3Rpb24gX2lzSW5FbmFibGVkSG91cnModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3Vyc1t0ZXN0RGF0ZS5mb3JtYXQoJ0gnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc1ZhbGlkID0gZnVuY3Rpb24gX2lzVmFsaWQodGFyZ2V0TW9tZW50LCBncmFudWxhcml0eSkge1xuICAgICAgICAgICAgaWYgKCF0YXJnZXRNb21lbnQuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmIHRoaXMuX2lzSW5EaXNhYmxlZERhdGVzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiAhdGhpcy5faXNJbkVuYWJsZWREYXRlcyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiB0YXJnZXRNb21lbnQuaXNCZWZvcmUodGhpcy5fb3B0aW9ucy5taW5EYXRlLCBncmFudWxhcml0eSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHRhcmdldE1vbWVudC5pc0FmdGVyKHRoaXMuX29wdGlvbnMubWF4RGF0ZSwgZ3JhbnVsYXJpdHkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQuaW5kZXhPZih0YXJnZXRNb21lbnQuZGF5KCkpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSAmJiB0aGlzLl9pc0luRGlzYWJsZWRIb3Vycyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykgJiYgIXRoaXMuX2lzSW5FbmFibGVkSG91cnModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgJC5lYWNoKHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0YXJnZXRNb21lbnQuaXNCZXR3ZWVuKHRoaXNbMF0sIHRoaXNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoZm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fcGFyc2VJbnB1dERhdGUgPSBmdW5jdGlvbiBfcGFyc2VJbnB1dERhdGUoaW5wdXREYXRlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFtb21lbnQuaXNNb21lbnQoaW5wdXREYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dERhdGUgPSB0aGlzLmdldE1vbWVudChpbnB1dERhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaW5wdXREYXRlID0gdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZShpbnB1dERhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy9pbnB1dERhdGUubG9jYWxlKHRoaXMub3B0aW9ucy5sb2NhbGUpO1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0RGF0ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2tleWRvd24gPSBmdW5jdGlvbiBfa2V5ZG93bihlKSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlciA9IG51bGwsXG4gICAgICAgICAgICAgICAgaW5kZXggPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgaW5kZXgyID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGtleUJpbmRLZXlzID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGFsbE1vZGlmaWVyc1ByZXNzZWQgPSB2b2lkIDA7XG4gICAgICAgICAgICB2YXIgcHJlc3NlZEtleXMgPSBbXSxcbiAgICAgICAgICAgICAgICBwcmVzc2VkTW9kaWZpZXJzID0ge30sXG4gICAgICAgICAgICAgICAgY3VycmVudEtleSA9IGUud2hpY2gsXG4gICAgICAgICAgICAgICAgcHJlc3NlZCA9ICdwJztcblxuICAgICAgICAgICAga2V5U3RhdGVbY3VycmVudEtleV0gPSBwcmVzc2VkO1xuXG4gICAgICAgICAgICBmb3IgKGluZGV4IGluIGtleVN0YXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleVN0YXRlLmhhc093blByb3BlcnR5KGluZGV4KSAmJiBrZXlTdGF0ZVtpbmRleF0gPT09IHByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJlc3NlZEtleXMucHVzaChpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJzZUludChpbmRleCwgMTApICE9PSBjdXJyZW50S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmVzc2VkTW9kaWZpZXJzW2luZGV4XSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoaW5kZXggaW4gdGhpcy5fb3B0aW9ucy5rZXlCaW5kcykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmtleUJpbmRzLmhhc093blByb3BlcnR5KGluZGV4KSAmJiB0eXBlb2YgdGhpcy5fb3B0aW9ucy5rZXlCaW5kc1tpbmRleF0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5QmluZEtleXMgPSBpbmRleC5zcGxpdCgnICcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5QmluZEtleXMubGVuZ3RoID09PSBwcmVzc2VkS2V5cy5sZW5ndGggJiYgS2V5TWFwW2N1cnJlbnRLZXldID09PSBrZXlCaW5kS2V5c1trZXlCaW5kS2V5cy5sZW5ndGggLSAxXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGluZGV4MiA9IGtleUJpbmRLZXlzLmxlbmd0aCAtIDI7IGluZGV4MiA+PSAwOyBpbmRleDItLSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghKEtleU1hcFtrZXlCaW5kS2V5c1tpbmRleDJdXSBpbiBwcmVzc2VkTW9kaWZpZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbGxNb2RpZmllcnNQcmVzc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlciA9IHRoaXMuX29wdGlvbnMua2V5QmluZHNbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaGFuZGxlcikge1xuICAgICAgICAgICAgICAgIGlmIChoYW5kbGVyLmNhbGwodGhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvL25vaW5zcGVjdGlvbiBKU01ldGhvZENhbkJlU3RhdGljLFNwZWxsQ2hlY2tpbmdJbnNwZWN0aW9uXG5cblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2tleXVwID0gZnVuY3Rpb24gX2tleXVwKGUpIHtcbiAgICAgICAgICAgIGtleVN0YXRlW2Uud2hpY2hdID0gJ3InO1xuICAgICAgICAgICAgaWYgKGtleVByZXNzSGFuZGxlZFtlLndoaWNoXSkge1xuICAgICAgICAgICAgICAgIGtleVByZXNzSGFuZGxlZFtlLndoaWNoXSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW5kZXhHaXZlbkRhdGVzID0gZnVuY3Rpb24gX2luZGV4R2l2ZW5EYXRlcyhnaXZlbkRhdGVzQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIFN0b3JlIGdpdmVuIGVuYWJsZWREYXRlcyBhbmQgZGlzYWJsZWREYXRlcyBhcyBrZXlzLlxuICAgICAgICAgICAgLy8gVGhpcyB3YXkgd2UgY2FuIGNoZWNrIHRoZWlyIGV4aXN0ZW5jZSBpbiBPKDEpIHRpbWUgaW5zdGVhZCBvZiBsb29waW5nIHRocm91Z2ggd2hvbGUgYXJyYXkuXG4gICAgICAgICAgICAvLyAoZm9yIGV4YW1wbGU6IG9wdGlvbnMuZW5hYmxlZERhdGVzWycyMDE0LTAyLTI3J10gPT09IHRydWUpXG4gICAgICAgICAgICB2YXIgZ2l2ZW5EYXRlc0luZGV4ZWQgPSB7fSxcbiAgICAgICAgICAgICAgICBzZWxmID0gdGhpcztcbiAgICAgICAgICAgICQuZWFjaChnaXZlbkRhdGVzQXJyYXksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZERhdGUgPSBzZWxmLl9wYXJzZUlucHV0RGF0ZSh0aGlzKTtcbiAgICAgICAgICAgICAgICBpZiAoZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGdpdmVuRGF0ZXNJbmRleGVkW2REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoZ2l2ZW5EYXRlc0luZGV4ZWQpLmxlbmd0aCA/IGdpdmVuRGF0ZXNJbmRleGVkIDogZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbmRleEdpdmVuSG91cnMgPSBmdW5jdGlvbiBfaW5kZXhHaXZlbkhvdXJzKGdpdmVuSG91cnNBcnJheSkge1xuICAgICAgICAgICAgLy8gU3RvcmUgZ2l2ZW4gZW5hYmxlZEhvdXJzIGFuZCBkaXNhYmxlZEhvdXJzIGFzIGtleXMuXG4gICAgICAgICAgICAvLyBUaGlzIHdheSB3ZSBjYW4gY2hlY2sgdGhlaXIgZXhpc3RlbmNlIGluIE8oMSkgdGltZSBpbnN0ZWFkIG9mIGxvb3BpbmcgdGhyb3VnaCB3aG9sZSBhcnJheS5cbiAgICAgICAgICAgIC8vIChmb3IgZXhhbXBsZTogb3B0aW9ucy5lbmFibGVkSG91cnNbJzIwMTQtMDItMjcnXSA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIHZhciBnaXZlbkhvdXJzSW5kZXhlZCA9IHt9O1xuICAgICAgICAgICAgJC5lYWNoKGdpdmVuSG91cnNBcnJheSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGdpdmVuSG91cnNJbmRleGVkW3RoaXNdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGdpdmVuSG91cnNJbmRleGVkKS5sZW5ndGggPyBnaXZlbkhvdXJzSW5kZXhlZCA6IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW5pdEZvcm1hdHRpbmcgPSBmdW5jdGlvbiBfaW5pdEZvcm1hdHRpbmcoKSB7XG4gICAgICAgICAgICB2YXIgZm9ybWF0ID0gdGhpcy5fb3B0aW9ucy5mb3JtYXQgfHwgJ0wgTFQnLFxuICAgICAgICAgICAgICAgIHNlbGYgPSB0aGlzO1xuXG4gICAgICAgICAgICB0aGlzLmFjdHVhbEZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKC8oXFxbW15cXFtdKl0pfChcXFxcKT8oTFRTfExUfExMP0w/TD98bHsxLDR9KS9nLCBmdW5jdGlvbiAoZm9ybWF0SW5wdXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5fZGF0ZXNbMF0ubG9jYWxlRGF0YSgpLmxvbmdEYXRlRm9ybWF0KGZvcm1hdElucHV0KSB8fCBmb3JtYXRJbnB1dDsgLy90b2RvIHRha2luZyB0aGUgZmlyc3QgZGF0ZSBzaG91bGQgYmUgb2tcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0aGlzLnBhcnNlRm9ybWF0cyA9IHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzID8gdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMuc2xpY2UoKSA6IFtdO1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VGb3JtYXRzLmluZGV4T2YoZm9ybWF0KSA8IDAgJiYgdGhpcy5wYXJzZUZvcm1hdHMuaW5kZXhPZih0aGlzLmFjdHVhbEZvcm1hdCkgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJzZUZvcm1hdHMucHVzaCh0aGlzLmFjdHVhbEZvcm1hdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudXNlMjRIb3VycyA9IHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignYScpIDwgMSAmJiB0aGlzLmFjdHVhbEZvcm1hdC5yZXBsYWNlKC9cXFsuKj9dL2csICcnKS5pbmRleE9mKCdoJykgPCAxO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCd5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLk1pblZpZXdNb2RlTnVtYmVyID0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ00nKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuTWluVmlld01vZGVOdW1iZXIgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnZCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgodGhpcy5NaW5WaWV3TW9kZU51bWJlciwgdGhpcy5jdXJyZW50Vmlld01vZGUpO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1swXSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9nZXRMYXN0UGlja2VkRGF0ZSA9IGZ1bmN0aW9uIF9nZXRMYXN0UGlja2VkRGF0ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlc1t0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCldO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCA9IGZ1bmN0aW9uIF9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzLmxlbmd0aCAtIDE7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9wdWJsaWNcblxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5nZXRNb21lbnQgPSBmdW5jdGlvbiBnZXRNb21lbnQoZCkge1xuICAgICAgICAgICAgdmFyIHJldHVybk1vbWVudCA9IHZvaWQgMDtcblxuICAgICAgICAgICAgaWYgKGQgPT09IHVuZGVmaW5lZCB8fCBkID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50KCk7IC8vVE9ETyBzaG91bGQgdGhpcyB1c2UgZm9ybWF0PyBhbmQgbG9jYWxlP1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgaXMgYSBzdHJpbmcgdG8gcGFyc2UgYW5kIGEgZGVmYXVsdCB0aW1lIHpvbmVcbiAgICAgICAgICAgICAgICAvLyBwYXJzZSB3aXRoIHRoZSB0eiBmdW5jdGlvbiB3aGljaCB0YWtlcyBhIGRlZmF1bHQgdGltZSB6b25lIGlmIGl0IGlzIG5vdCBpbiB0aGUgZm9ybWF0IHN0cmluZ1xuICAgICAgICAgICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudC50eihkLCB0aGlzLnBhcnNlRm9ybWF0cywgdGhpcy5fb3B0aW9ucy5sb2NhbGUsIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0LCB0aGlzLl9vcHRpb25zLnRpbWVab25lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50KGQsIHRoaXMucGFyc2VGb3JtYXRzLCB0aGlzLl9vcHRpb25zLmxvY2FsZSwgdGhpcy5fb3B0aW9ucy51c2VTdHJpY3QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5faGFzVGltZVpvbmUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybk1vbWVudC50eih0aGlzLl9vcHRpb25zLnRpbWVab25lKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJldHVybk1vbWVudDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lkZ2V0ID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3coKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuaWdub3JlUmVhZG9ubHkgPSBmdW5jdGlvbiBpZ25vcmVSZWFkb25seShfaWdub3JlUmVhZG9ubHkpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuaWdub3JlUmVhZG9ubHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIF9pZ25vcmVSZWFkb25seSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaWdub3JlUmVhZG9ubHkgKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmlnbm9yZVJlYWRvbmx5ID0gX2lnbm9yZVJlYWRvbmx5O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5vcHRpb25zID0gZnVuY3Rpb24gb3B0aW9ucyhuZXdPcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh0cnVlLCB7fSwgdGhpcy5fb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKG5ld09wdGlvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb3B0aW9ucygpIHRoaXMub3B0aW9ucyBwYXJhbWV0ZXIgc2hvdWxkIGJlIGFuIG9iamVjdCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgdGhpcy5fb3B0aW9ucywgbmV3T3B0aW9ucyk7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZltrZXldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZltrZXldKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGF0ZSA9IGZ1bmN0aW9uIGRhdGUobmV3RGF0ZSwgaW5kZXgpIHtcbiAgICAgICAgICAgIGluZGV4ID0gaW5kZXggfHwgMDtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlcy5qb2luKHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXNbaW5kZXhdLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobmV3RGF0ZSAhPT0gbnVsbCAmJiB0eXBlb2YgbmV3RGF0ZSAhPT0gJ3N0cmluZycgJiYgIW1vbWVudC5pc01vbWVudChuZXdEYXRlKSAmJiAhKG5ld0RhdGUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgW251bGwsIHN0cmluZywgbW9tZW50IG9yIERhdGVdJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKG5ld0RhdGUgPT09IG51bGwgPyBudWxsIDogdGhpcy5fcGFyc2VJbnB1dERhdGUobmV3RGF0ZSksIGluZGV4KTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZm9ybWF0ID0gZnVuY3Rpb24gZm9ybWF0KG5ld0Zvcm1hdCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5mb3JtYXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3Rm9ybWF0ICE9PSAnc3RyaW5nJyAmJiAodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ2Jvb2xlYW4nIHx8IG5ld0Zvcm1hdCAhPT0gZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZm9ybWF0KCkgZXhwZWN0cyBhIHN0cmluZyBvciBib29sZWFuOmZhbHNlIHBhcmFtZXRlciAnICsgbmV3Rm9ybWF0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5mb3JtYXQgPSBuZXdGb3JtYXQ7XG4gICAgICAgICAgICBpZiAodGhpcy5hY3R1YWxGb3JtYXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXRpYWxpemUgZm9ybWF0dGluZ1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS50aW1lWm9uZSA9IGZ1bmN0aW9uIHRpbWVab25lKG5ld1pvbmUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudGltZVpvbmU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3Wm9uZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCduZXdab25lKCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSA9IG5ld1pvbmU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRheVZpZXdIZWFkZXJGb3JtYXQgPSBmdW5jdGlvbiBkYXlWaWV3SGVhZGVyRm9ybWF0KG5ld0Zvcm1hdCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXlWaWV3SGVhZGVyRm9ybWF0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXlWaWV3SGVhZGVyRm9ybWF0KCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXlWaWV3SGVhZGVyRm9ybWF0ID0gbmV3Rm9ybWF0O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5leHRyYUZvcm1hdHMgPSBmdW5jdGlvbiBleHRyYUZvcm1hdHMoZm9ybWF0cykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChmb3JtYXRzICE9PSBmYWxzZSAmJiAhKGZvcm1hdHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdleHRyYUZvcm1hdHMoKSBleHBlY3RzIGFuIGFycmF5IG9yIGZhbHNlIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cyA9IGZvcm1hdHM7XG4gICAgICAgICAgICBpZiAodGhpcy5wYXJzZUZvcm1hdHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXQgZm9ybWF0dGluZ1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kaXNhYmxlZERhdGVzID0gZnVuY3Rpb24gZGlzYWJsZWREYXRlcyhkYXRlcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghZGF0ZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKGRhdGVzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGlzYWJsZWREYXRlcygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSB0aGlzLl9pbmRleEdpdmVuRGF0ZXMoZGF0ZXMpO1xuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5lbmFibGVkRGF0ZXMgPSBmdW5jdGlvbiBlbmFibGVkRGF0ZXMoZGF0ZXMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzKSA6IHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWRhdGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKGRhdGVzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZW5hYmxlZERhdGVzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID0gdGhpcy5faW5kZXhHaXZlbkRhdGVzKGRhdGVzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRheXNPZldlZWtEaXNhYmxlZCA9IGZ1bmN0aW9uIGRheXNPZldlZWtEaXNhYmxlZChfZGF5c09mV2Vla0Rpc2FibGVkKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZC5zcGxpY2UoMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RheXNPZldlZWtEaXNhYmxlZCA9PT0gJ2Jvb2xlYW4nICYmICFfZGF5c09mV2Vla0Rpc2FibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX2RheXNPZldlZWtEaXNhYmxlZCBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RheXNPZldlZWtEaXNhYmxlZCgpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCA9IF9kYXlzT2ZXZWVrRGlzYWJsZWQucmVkdWNlKGZ1bmN0aW9uIChwcmV2aW91c1ZhbHVlLCBjdXJyZW50VmFsdWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBwYXJzZUludChjdXJyZW50VmFsdWUsIDEwKTtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudFZhbHVlID4gNiB8fCBjdXJyZW50VmFsdWUgPCAwIHx8IGlzTmFOKGN1cnJlbnRWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlLmluZGV4T2YoY3VycmVudFZhbHVlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS5wdXNoKGN1cnJlbnRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xuICAgICAgICAgICAgfSwgW10pLnNvcnQoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmllcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICghdGhpcy5faXNWYWxpZCh0aGlzLl9kYXRlc1tpXSwgJ2QnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0uYWRkKDEsICdkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDMxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgJ1RyaWVkIDMxIHRpbWVzIHRvIGZpbmQgYSB2YWxpZCBkYXRlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbaV0sIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5tYXhEYXRlID0gZnVuY3Rpb24gbWF4RGF0ZShfbWF4RGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5tYXhEYXRlID8gdGhpcy5fb3B0aW9ucy5tYXhEYXRlLmNsb25lKCkgOiB0aGlzLl9vcHRpb25zLm1heERhdGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21heERhdGUgPT09ICdib29sZWFuJyAmJiBfbWF4RGF0ZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1heERhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWF4RGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoX21heERhdGUgPT09ICdub3cnIHx8IF9tYXhEYXRlID09PSAnbW9tZW50Jykge1xuICAgICAgICAgICAgICAgICAgICBfbWF4RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKF9tYXhEYXRlKTtcblxuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21heERhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBfbWF4RGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHBhcnNlZERhdGUuaXNCZWZvcmUodGhpcy5fb3B0aW9ucy5taW5EYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21heERhdGUoKSBkYXRlIHBhcmFtZXRlciBpcyBiZWZvcmUgdGhpcy5vcHRpb25zLm1pbkRhdGU6ICcgKyBwYXJzZWREYXRlLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5tYXhEYXRlID0gcGFyc2VkRGF0ZTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkICYmIHRoaXMuX2RhdGVzW2ldLmlzQWZ0ZXIoX21heERhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMubWF4RGF0ZSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX3ZpZXdEYXRlLmlzQWZ0ZXIocGFyc2VkRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHBhcnNlZERhdGUuY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm1pbkRhdGUgPSBmdW5jdGlvbiBtaW5EYXRlKF9taW5EYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPyB0aGlzLl9vcHRpb25zLm1pbkRhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMubWluRGF0ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWluRGF0ZSA9PT0gJ2Jvb2xlYW4nICYmIF9taW5EYXRlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWluRGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9taW5EYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlmIChfbWluRGF0ZSA9PT0gJ25vdycgfHwgX21pbkRhdGUgPT09ICdtb21lbnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIF9taW5EYXRlID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwYXJzZWREYXRlID0gdGhpcy5fcGFyc2VJbnB1dERhdGUoX21pbkRhdGUpO1xuXG4gICAgICAgICAgICBpZiAoIXBhcnNlZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWluRGF0ZSgpIENvdWxkIG5vdCBwYXJzZSBkYXRlIHBhcmFtZXRlcjogJyArIF9taW5EYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgcGFyc2VkRGF0ZS5pc0FmdGVyKHRoaXMuX29wdGlvbnMubWF4RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtaW5EYXRlKCkgZGF0ZSBwYXJhbWV0ZXIgaXMgYWZ0ZXIgdGhpcy5vcHRpb25zLm1heERhdGU6ICcgKyBwYXJzZWREYXRlLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5taW5EYXRlID0gcGFyc2VkRGF0ZTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkICYmIHRoaXMuX2RhdGVzW2ldLmlzQmVmb3JlKF9taW5EYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLm1pbkRhdGUsIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl92aWV3RGF0ZS5pc0JlZm9yZShwYXJzZWREYXRlKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gcGFyc2VkRGF0ZS5jbG9uZSgpLmFkZCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRlZmF1bHREYXRlID0gZnVuY3Rpb24gZGVmYXVsdERhdGUoX2RlZmF1bHREYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlID8gdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZS5jbG9uZSgpIDogdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghX2RlZmF1bHREYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9kZWZhdWx0RGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoX2RlZmF1bHREYXRlID09PSAnbm93JyB8fCBfZGVmYXVsdERhdGUgPT09ICdtb21lbnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIF9kZWZhdWx0RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX2RlZmF1bHREYXRlID0gdGhpcy5nZXRNb21lbnQoX2RlZmF1bHREYXRlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwYXJzZWREYXRlID0gdGhpcy5fcGFyc2VJbnB1dERhdGUoX2RlZmF1bHREYXRlKTtcbiAgICAgICAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWZhdWx0RGF0ZSgpIENvdWxkIG5vdCBwYXJzZSBkYXRlIHBhcmFtZXRlcjogJyArIF9kZWZhdWx0RGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzVmFsaWQocGFyc2VkRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWZhdWx0RGF0ZSgpIGRhdGUgcGFzc2VkIGlzIGludmFsaWQgYWNjb3JkaW5nIHRvIGNvbXBvbmVudCBzZXR1cCB2YWxpZGF0aW9ucycpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlID0gcGFyc2VkRGF0ZTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgJiYgdGhpcy5fb3B0aW9ucy5pbmxpbmUgfHwgdGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQudmFsKCkudHJpbSgpID09PSAnJykge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5sb2NhbGUgPSBmdW5jdGlvbiBsb2NhbGUoX2xvY2FsZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5sb2NhbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghbW9tZW50LmxvY2FsZURhdGEoX2xvY2FsZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsb2NhbGUoKSBsb2NhbGUgJyArIF9sb2NhbGUgKyAnIGlzIG5vdCBsb2FkZWQgZnJvbSBtb21lbnQgbG9jYWxlcyEnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5sb2NhbGUgPSBfbG9jYWxlO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0ubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmFjdHVhbEZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7IC8vIHJlaW5pdGlhbGl6ZSBmb3JtYXR0aW5nXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuc3RlcHBpbmcgPSBmdW5jdGlvbiBzdGVwcGluZyhfc3RlcHBpbmcpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuc3RlcHBpbmc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIF9zdGVwcGluZyA9IHBhcnNlSW50KF9zdGVwcGluZywgMTApO1xuICAgICAgICAgICAgaWYgKGlzTmFOKF9zdGVwcGluZykgfHwgX3N0ZXBwaW5nIDwgMSkge1xuICAgICAgICAgICAgICAgIF9zdGVwcGluZyA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nID0gX3N0ZXBwaW5nO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS51c2VDdXJyZW50ID0gZnVuY3Rpb24gdXNlQ3VycmVudChfdXNlQ3VycmVudCkge1xuICAgICAgICAgICAgdmFyIHVzZUN1cnJlbnRPcHRpb25zID0gWyd5ZWFyJywgJ21vbnRoJywgJ2RheScsICdob3VyJywgJ21pbnV0ZSddO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF91c2VDdXJyZW50ICE9PSAnYm9vbGVhbicgJiYgdHlwZW9mIF91c2VDdXJyZW50ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VzZUN1cnJlbnQoKSBleHBlY3RzIGEgYm9vbGVhbiBvciBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIF91c2VDdXJyZW50ID09PSAnc3RyaW5nJyAmJiB1c2VDdXJyZW50T3B0aW9ucy5pbmRleE9mKF91c2VDdXJyZW50LnRvTG93ZXJDYXNlKCkpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VzZUN1cnJlbnQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlciBvZiAnICsgdXNlQ3VycmVudE9wdGlvbnMuam9pbignLCAnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgPSBfdXNlQ3VycmVudDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuY29sbGFwc2UgPSBmdW5jdGlvbiBjb2xsYXBzZShfY29sbGFwc2UpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuY29sbGFwc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2NvbGxhcHNlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjb2xsYXBzZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgPT09IF9jb2xsYXBzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5jb2xsYXBzZSA9IF9jb2xsYXBzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5pY29ucyA9IGZ1bmN0aW9uIGljb25zKF9pY29ucykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuaWNvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfaWNvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaWNvbnMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy5pY29ucywgX2ljb25zKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnRvb2x0aXBzID0gZnVuY3Rpb24gdG9vbHRpcHMoX3Rvb2x0aXBzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy50b29sdGlwcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF90b29sdGlwcyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0b29sdGlwcygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy50b29sdGlwcywgX3Rvb2x0aXBzKTtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS51c2VTdHJpY3QgPSBmdW5jdGlvbiB1c2VTdHJpY3QoX3VzZVN0cmljdCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy51c2VTdHJpY3Q7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3VzZVN0cmljdCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlU3RyaWN0KCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnVzZVN0cmljdCA9IF91c2VTdHJpY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnNpZGVCeVNpZGUgPSBmdW5jdGlvbiBzaWRlQnlTaWRlKF9zaWRlQnlTaWRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnNpZGVCeVNpZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3NpZGVCeVNpZGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3NpZGVCeVNpZGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZSA9IF9zaWRlQnlTaWRlO1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnZpZXdNb2RlID0gZnVuY3Rpb24gdmlld01vZGUoX3ZpZXdNb2RlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnZpZXdNb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF92aWV3TW9kZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3TW9kZSgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuaW5kZXhPZihfdmlld01vZGUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdNb2RlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mICgnICsgRGF0ZVRpbWVQaWNrZXIuVmlld01vZGVzLmpvaW4oJywgJykgKyAnKSB2YWx1ZScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnZpZXdNb2RlID0gX3ZpZXdNb2RlO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heChEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuaW5kZXhPZihfdmlld01vZGUpIC0gMSwgdGhpcy5NaW5WaWV3TW9kZU51bWJlcik7XG5cbiAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmNhbGVuZGFyV2Vla3MgPSBmdW5jdGlvbiBjYWxlbmRhcldlZWtzKF9jYWxlbmRhcldlZWtzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2NhbGVuZGFyV2Vla3MgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2NhbGVuZGFyV2Vla3MoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhIGJvb2xlYW4gdmFsdWUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzID0gX2NhbGVuZGFyV2Vla3M7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuYnV0dG9ucyA9IGZ1bmN0aW9uIGJ1dHRvbnMoX2J1dHRvbnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmJ1dHRvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfYnV0dG9ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYW4gT2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQuZXh0ZW5kKHRoaXMuX29wdGlvbnMuYnV0dG9ucywgX2J1dHRvbnMpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93VG9kYXkgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMuc2hvd1RvZGF5IGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd0NsZWFyICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zLnNob3dDbGVhciBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbG9zZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucy5zaG93Q2xvc2UgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZWVwT3BlbiA9IGZ1bmN0aW9uIGtlZXBPcGVuKF9rZWVwT3Blbikge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZWVwT3BlbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfa2VlcE9wZW4gIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2tlZXBPcGVuKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMua2VlcE9wZW4gPSBfa2VlcE9wZW47XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmZvY3VzT25TaG93ID0gZnVuY3Rpb24gZm9jdXNPblNob3coX2ZvY3VzT25TaG93KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmZvY3VzT25TaG93O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9mb2N1c09uU2hvdyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZm9jdXNPblNob3coKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5mb2N1c09uU2hvdyA9IF9mb2N1c09uU2hvdztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuaW5saW5lID0gZnVuY3Rpb24gaW5saW5lKF9pbmxpbmUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuaW5saW5lO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9pbmxpbmUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lubGluZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmlubGluZSA9IF9pbmxpbmU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShudWxsKTsgLy90b2RvXG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmtleUJpbmRzID0gZnVuY3Rpb24ga2V5QmluZHMoX2tleUJpbmRzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmtleUJpbmRzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtleUJpbmRzID0gX2tleUJpbmRzO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uIGRlYnVnKF9kZWJ1Zykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGVidWcgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlYnVnKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGVidWcgPSBfZGVidWc7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmFsbG93SW5wdXRUb2dnbGUgPSBmdW5jdGlvbiBhbGxvd0lucHV0VG9nZ2xlKF9hbGxvd0lucHV0VG9nZ2xlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmFsbG93SW5wdXRUb2dnbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2FsbG93SW5wdXRUb2dnbGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93SW5wdXRUb2dnbGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlID0gX2FsbG93SW5wdXRUb2dnbGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmtlZXBJbnZhbGlkID0gZnVuY3Rpb24ga2VlcEludmFsaWQoX2tlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9rZWVwSW52YWxpZCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigna2VlcEludmFsaWQoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMua2VlcEludmFsaWQgPSBfa2VlcEludmFsaWQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRhdGVwaWNrZXJJbnB1dCA9IGZ1bmN0aW9uIGRhdGVwaWNrZXJJbnB1dChfZGF0ZXBpY2tlcklucHV0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRhdGVwaWNrZXJJbnB1dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGF0ZXBpY2tlcklucHV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGVwaWNrZXJJbnB1dCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF0ZXBpY2tlcklucHV0ID0gX2RhdGVwaWNrZXJJbnB1dDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUucGFyc2VJbnB1dERhdGUgPSBmdW5jdGlvbiBwYXJzZUlucHV0RGF0ZShfcGFyc2VJbnB1dERhdGUyKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9wYXJzZUlucHV0RGF0ZTIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwYXJzZUlucHV0RGF0ZSgpIHNob3VsZCBiZSBhcyBmdW5jdGlvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlID0gX3BhcnNlSW5wdXREYXRlMjtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gZnVuY3Rpb24gZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKF9kaXNhYmxlZFRpbWVJbnRlcnZhbHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSA6IHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIV9kaXNhYmxlZFRpbWVJbnRlcnZhbHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoX2Rpc2FibGVkVGltZUludGVydmFscyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkVGltZUludGVydmFscygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA9IF9kaXNhYmxlZFRpbWVJbnRlcnZhbHM7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWRIb3VycyA9IGZ1bmN0aW9uIGRpc2FibGVkSG91cnMoaG91cnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMpIDogdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShob3VycyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkSG91cnMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gdGhpcy5faW5kZXhHaXZlbkhvdXJzKGhvdXJzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAyNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAyNCB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZW5hYmxlZEhvdXJzID0gZnVuY3Rpb24gZW5hYmxlZEhvdXJzKGhvdXJzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycykgOiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFob3Vycykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShob3VycyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuYWJsZWRIb3VycygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IHRoaXMuX2luZGV4R2l2ZW5Ib3Vycyhob3Vycyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmllcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICghdGhpcy5faXNWYWxpZCh0aGlzLl9kYXRlc1tpXSwgJ2gnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0uYWRkKDEsICdoJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDI0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgJ1RyaWVkIDI0IHRpbWVzIHRvIGZpbmQgYSB2YWxpZCBkYXRlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbaV0sIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS52aWV3RGF0ZSA9IGZ1bmN0aW9uIHZpZXdEYXRlKG5ld0RhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3ZpZXdEYXRlLmNsb25lKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghbmV3RGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gKHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCkpLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3RGF0ZSAhPT0gJ3N0cmluZycgJiYgIW1vbWVudC5pc01vbWVudChuZXdEYXRlKSAmJiAhKG5ld0RhdGUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdEYXRlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mIFtzdHJpbmcsIG1vbWVudCBvciBEYXRlXScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKG5ld0RhdGUpO1xuICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5hbGxvd011bHRpZGF0ZSA9IGZ1bmN0aW9uIGFsbG93TXVsdGlkYXRlKF9hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBfYWxsb3dNdWx0aWRhdGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93TXVsdGlkYXRlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgPSBfYWxsb3dNdWx0aWRhdGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm11bHRpZGF0ZVNlcGFyYXRvciA9IGZ1bmN0aW9uIG11bHRpZGF0ZVNlcGFyYXRvcihfbXVsdGlkYXRlU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbXVsdGlkYXRlU2VwYXJhdG9yICE9PSAnc3RyaW5nJyB8fCBfbXVsdGlkYXRlU2VwYXJhdG9yLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtdWx0aWRhdGVTZXBhcmF0b3IgZXhwZWN0cyBhIHNpbmdsZSBjaGFyYWN0ZXIgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciA9IF9tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgIH07XG5cbiAgICAgICAgX2NyZWF0ZUNsYXNzKERhdGVUaW1lUGlja2VyLCBudWxsLCBbe1xuICAgICAgICAgICAga2V5OiAnTkFNRScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTkFNRTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERBVEFfS0VZO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdFVkVOVF9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVWRU5UX0tFWTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9BUElfS0VZJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEQVRBX0FQSV9LRVk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RhdGVQaWNrZXJNb2RlcycsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGF0ZVBpY2tlck1vZGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdWaWV3TW9kZXMnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFZpZXdNb2RlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnRXZlbnQnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdTZWxlY3RvcicsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU2VsZWN0b3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RlZmF1bHQnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBEZWZhdWx0ID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0NsYXNzTmFtZScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gQ2xhc3NOYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XSk7XG5cbiAgICAgICAgcmV0dXJuIERhdGVUaW1lUGlja2VyO1xuICAgIH0oKTtcblxuICAgIHJldHVybiBEYXRlVGltZVBpY2tlcjtcbn0oalF1ZXJ5LCBtb21lbnQpO1xuIiwiLypAcHJlc2VydmVcclxuICogVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNCB2NS4xLjIgKGh0dHBzOi8vdGVtcHVzZG9taW51cy5naXRodWIuaW8vYm9vdHN0cmFwLTQvKVxyXG4gKiBDb3B5cmlnaHQgMjAxNi0yMDE4IEpvbmF0aGFuIFBldGVyc29uXHJcbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3RlbXB1c2RvbWludXMvYm9vdHN0cmFwLTMvYmxvYi9tYXN0ZXIvTElDRU5TRSlcclxuICovXHJcblxyXG5pZiAodHlwZW9mIGpRdWVyeSA9PT0gJ3VuZGVmaW5lZCcpIHtcclxuICB0aHJvdyBuZXcgRXJyb3IoJ1RlbXB1cyBEb21pbnVzIEJvb3RzdHJhcDRcXCdzIHJlcXVpcmVzIGpRdWVyeS4galF1ZXJ5IG11c3QgYmUgaW5jbHVkZWQgYmVmb3JlIFRlbXB1cyBEb21pbnVzIEJvb3RzdHJhcDRcXCdzIEphdmFTY3JpcHQuJyk7XHJcbn1cclxuXHJcbitmdW5jdGlvbiAoJCkge1xyXG4gIHZhciB2ZXJzaW9uID0gJC5mbi5qcXVlcnkuc3BsaXQoJyAnKVswXS5zcGxpdCgnLicpO1xyXG4gIGlmICgodmVyc2lvblswXSA8IDIgJiYgdmVyc2lvblsxXSA8IDkpIHx8ICh2ZXJzaW9uWzBdID09PSAxICYmIHZlcnNpb25bMV0gPT09IDkgJiYgdmVyc2lvblsyXSA8IDEpIHx8ICh2ZXJzaW9uWzBdID49IDQpKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbXB1cyBEb21pbnVzIEJvb3RzdHJhcDRcXCdzIHJlcXVpcmVzIGF0IGxlYXN0IGpRdWVyeSB2My4wLjAgYnV0IGxlc3MgdGhhbiB2NC4wLjAnKTtcclxuICB9XHJcbn0oalF1ZXJ5KTtcclxuXHJcblxyXG5pZiAodHlwZW9mIG1vbWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcclxuICB0aHJvdyBuZXcgRXJyb3IoJ1RlbXB1cyBEb21pbnVzIEJvb3RzdHJhcDRcXCdzIHJlcXVpcmVzIG1vbWVudC5qcy4gTW9tZW50LmpzIG11c3QgYmUgaW5jbHVkZWQgYmVmb3JlIFRlbXB1cyBEb21pbnVzIEJvb3RzdHJhcDRcXCdzIEphdmFTY3JpcHQuJyk7XHJcbn1cclxuXHJcbnZhciB2ZXJzaW9uID0gbW9tZW50LnZlcnNpb24uc3BsaXQoJy4nKVxyXG5pZiAoKHZlcnNpb25bMF0gPD0gMiAmJiB2ZXJzaW9uWzFdIDwgMTcpIHx8ICh2ZXJzaW9uWzBdID49IDMpKSB7XHJcbiAgdGhyb3cgbmV3IEVycm9yKCdUZW1wdXMgRG9taW51cyBCb290c3RyYXA0XFwncyByZXF1aXJlcyBhdCBsZWFzdCBtb21lbnQuanMgdjIuMTcuMCBidXQgbGVzcyB0aGFuIHYzLjAuMCcpO1xyXG59XHJcblxyXG4rZnVuY3Rpb24gKCkge1xyXG5cclxudmFyIF90eXBlb2YgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIiA/IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIHR5cGVvZiBvYmo7IH0gOiBmdW5jdGlvbiAob2JqKSB7IHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqOyB9O1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybihzZWxmLCBjYWxsKSB7IGlmICghc2VsZikgeyB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWRcIik7IH0gcmV0dXJuIGNhbGwgJiYgKHR5cGVvZiBjYWxsID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBjYWxsID09PSBcImZ1bmN0aW9uXCIpID8gY2FsbCA6IHNlbGY7IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbi8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG52YXIgRGF0ZVRpbWVQaWNrZXIgPSBmdW5jdGlvbiAoJCwgbW9tZW50KSB7XG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgSW5jb25zaXN0ZW50TmFtaW5nXG4gICAgdmFyIE5BTUUgPSAnZGF0ZXRpbWVwaWNrZXInLFxuICAgICAgICBEQVRBX0tFWSA9ICcnICsgTkFNRSxcbiAgICAgICAgRVZFTlRfS0VZID0gJy4nICsgREFUQV9LRVksXG4gICAgICAgIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknLFxuICAgICAgICBTZWxlY3RvciA9IHtcbiAgICAgICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCInICsgREFUQV9LRVkgKyAnXCJdJ1xuICAgIH0sXG4gICAgICAgIENsYXNzTmFtZSA9IHtcbiAgICAgICAgSU5QVVQ6IE5BTUUgKyAnLWlucHV0J1xuICAgIH0sXG4gICAgICAgIEV2ZW50ID0ge1xuICAgICAgICBDSEFOR0U6ICdjaGFuZ2UnICsgRVZFTlRfS0VZLFxuICAgICAgICBCTFVSOiAnYmx1cicgKyBFVkVOVF9LRVksXG4gICAgICAgIEtFWVVQOiAna2V5dXAnICsgRVZFTlRfS0VZLFxuICAgICAgICBLRVlET1dOOiAna2V5ZG93bicgKyBFVkVOVF9LRVksXG4gICAgICAgIEZPQ1VTOiAnZm9jdXMnICsgRVZFTlRfS0VZLFxuICAgICAgICBDTElDS19EQVRBX0FQSTogJ2NsaWNrJyArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSxcbiAgICAgICAgLy9lbWl0dGVkXG4gICAgICAgIFVQREFURTogJ3VwZGF0ZScgKyBFVkVOVF9LRVksXG4gICAgICAgIEVSUk9SOiAnZXJyb3InICsgRVZFTlRfS0VZLFxuICAgICAgICBISURFOiAnaGlkZScgKyBFVkVOVF9LRVksXG4gICAgICAgIFNIT1c6ICdzaG93JyArIEVWRU5UX0tFWVxuICAgIH0sXG4gICAgICAgIERhdGVQaWNrZXJNb2RlcyA9IFt7XG4gICAgICAgIENMQVNTX05BTUU6ICdkYXlzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAnTScsXG4gICAgICAgIE5BVl9TVEVQOiAxXG4gICAgfSwge1xuICAgICAgICBDTEFTU19OQU1FOiAnbW9udGhzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAneScsXG4gICAgICAgIE5BVl9TVEVQOiAxXG4gICAgfSwge1xuICAgICAgICBDTEFTU19OQU1FOiAneWVhcnMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICAgICAgTkFWX1NURVA6IDEwXG4gICAgfSwge1xuICAgICAgICBDTEFTU19OQU1FOiAnZGVjYWRlcycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ3knLFxuICAgICAgICBOQVZfU1RFUDogMTAwXG4gICAgfV0sXG4gICAgICAgIEtleU1hcCA9IHtcbiAgICAgICAgJ3VwJzogMzgsXG4gICAgICAgIDM4OiAndXAnLFxuICAgICAgICAnZG93bic6IDQwLFxuICAgICAgICA0MDogJ2Rvd24nLFxuICAgICAgICAnbGVmdCc6IDM3LFxuICAgICAgICAzNzogJ2xlZnQnLFxuICAgICAgICAncmlnaHQnOiAzOSxcbiAgICAgICAgMzk6ICdyaWdodCcsXG4gICAgICAgICd0YWInOiA5LFxuICAgICAgICA5OiAndGFiJyxcbiAgICAgICAgJ2VzY2FwZSc6IDI3LFxuICAgICAgICAyNzogJ2VzY2FwZScsXG4gICAgICAgICdlbnRlcic6IDEzLFxuICAgICAgICAxMzogJ2VudGVyJyxcbiAgICAgICAgJ3BhZ2VVcCc6IDMzLFxuICAgICAgICAzMzogJ3BhZ2VVcCcsXG4gICAgICAgICdwYWdlRG93bic6IDM0LFxuICAgICAgICAzNDogJ3BhZ2VEb3duJyxcbiAgICAgICAgJ3NoaWZ0JzogMTYsXG4gICAgICAgIDE2OiAnc2hpZnQnLFxuICAgICAgICAnY29udHJvbCc6IDE3LFxuICAgICAgICAxNzogJ2NvbnRyb2wnLFxuICAgICAgICAnc3BhY2UnOiAzMixcbiAgICAgICAgMzI6ICdzcGFjZScsXG4gICAgICAgICd0JzogODQsXG4gICAgICAgIDg0OiAndCcsXG4gICAgICAgICdkZWxldGUnOiA0NixcbiAgICAgICAgNDY6ICdkZWxldGUnXG4gICAgfSxcbiAgICAgICAgVmlld01vZGVzID0gWyd0aW1lcycsICdkYXlzJywgJ21vbnRocycsICd5ZWFycycsICdkZWNhZGVzJ10sXG4gICAgICAgIGtleVN0YXRlID0ge30sXG4gICAgICAgIGtleVByZXNzSGFuZGxlZCA9IHt9O1xuXG4gICAgdmFyIERlZmF1bHQgPSB7XG4gICAgICAgIHRpbWVab25lOiAnJyxcbiAgICAgICAgZm9ybWF0OiBmYWxzZSxcbiAgICAgICAgZGF5Vmlld0hlYWRlckZvcm1hdDogJ01NTU0gWVlZWScsXG4gICAgICAgIGV4dHJhRm9ybWF0czogZmFsc2UsXG4gICAgICAgIHN0ZXBwaW5nOiAxLFxuICAgICAgICBtaW5EYXRlOiBmYWxzZSxcbiAgICAgICAgbWF4RGF0ZTogZmFsc2UsXG4gICAgICAgIHVzZUN1cnJlbnQ6IHRydWUsXG4gICAgICAgIGNvbGxhcHNlOiB0cnVlLFxuICAgICAgICBsb2NhbGU6IG1vbWVudC5sb2NhbGUoKSxcbiAgICAgICAgZGVmYXVsdERhdGU6IGZhbHNlLFxuICAgICAgICBkaXNhYmxlZERhdGVzOiBmYWxzZSxcbiAgICAgICAgZW5hYmxlZERhdGVzOiBmYWxzZSxcbiAgICAgICAgaWNvbnM6IHtcbiAgICAgICAgICAgIHRpbWU6ICdmYSBmYS1jbG9jay1vJyxcbiAgICAgICAgICAgIGRhdGU6ICdmYSBmYS1jYWxlbmRhcicsXG4gICAgICAgICAgICB1cDogJ2ZhIGZhLWFycm93LXVwJyxcbiAgICAgICAgICAgIGRvd246ICdmYSBmYS1hcnJvdy1kb3duJyxcbiAgICAgICAgICAgIHByZXZpb3VzOiAnZmEgZmEtY2hldnJvbi1sZWZ0JyxcbiAgICAgICAgICAgIG5leHQ6ICdmYSBmYS1jaGV2cm9uLXJpZ2h0JyxcbiAgICAgICAgICAgIHRvZGF5OiAnZmEgZmEtY2FsZW5kYXItY2hlY2stbycsXG4gICAgICAgICAgICBjbGVhcjogJ2ZhIGZhLWRlbGV0ZScsXG4gICAgICAgICAgICBjbG9zZTogJ2ZhIGZhLXRpbWVzJ1xuICAgICAgICB9LFxuICAgICAgICB0b29sdGlwczoge1xuICAgICAgICAgICAgdG9kYXk6ICdHbyB0byB0b2RheScsXG4gICAgICAgICAgICBjbGVhcjogJ0NsZWFyIHNlbGVjdGlvbicsXG4gICAgICAgICAgICBjbG9zZTogJ0Nsb3NlIHRoZSBwaWNrZXInLFxuICAgICAgICAgICAgc2VsZWN0TW9udGg6ICdTZWxlY3QgTW9udGgnLFxuICAgICAgICAgICAgcHJldk1vbnRoOiAnUHJldmlvdXMgTW9udGgnLFxuICAgICAgICAgICAgbmV4dE1vbnRoOiAnTmV4dCBNb250aCcsXG4gICAgICAgICAgICBzZWxlY3RZZWFyOiAnU2VsZWN0IFllYXInLFxuICAgICAgICAgICAgcHJldlllYXI6ICdQcmV2aW91cyBZZWFyJyxcbiAgICAgICAgICAgIG5leHRZZWFyOiAnTmV4dCBZZWFyJyxcbiAgICAgICAgICAgIHNlbGVjdERlY2FkZTogJ1NlbGVjdCBEZWNhZGUnLFxuICAgICAgICAgICAgcHJldkRlY2FkZTogJ1ByZXZpb3VzIERlY2FkZScsXG4gICAgICAgICAgICBuZXh0RGVjYWRlOiAnTmV4dCBEZWNhZGUnLFxuICAgICAgICAgICAgcHJldkNlbnR1cnk6ICdQcmV2aW91cyBDZW50dXJ5JyxcbiAgICAgICAgICAgIG5leHRDZW50dXJ5OiAnTmV4dCBDZW50dXJ5JyxcbiAgICAgICAgICAgIHBpY2tIb3VyOiAnUGljayBIb3VyJyxcbiAgICAgICAgICAgIGluY3JlbWVudEhvdXI6ICdJbmNyZW1lbnQgSG91cicsXG4gICAgICAgICAgICBkZWNyZW1lbnRIb3VyOiAnRGVjcmVtZW50IEhvdXInLFxuICAgICAgICAgICAgcGlja01pbnV0ZTogJ1BpY2sgTWludXRlJyxcbiAgICAgICAgICAgIGluY3JlbWVudE1pbnV0ZTogJ0luY3JlbWVudCBNaW51dGUnLFxuICAgICAgICAgICAgZGVjcmVtZW50TWludXRlOiAnRGVjcmVtZW50IE1pbnV0ZScsXG4gICAgICAgICAgICBwaWNrU2Vjb25kOiAnUGljayBTZWNvbmQnLFxuICAgICAgICAgICAgaW5jcmVtZW50U2Vjb25kOiAnSW5jcmVtZW50IFNlY29uZCcsXG4gICAgICAgICAgICBkZWNyZW1lbnRTZWNvbmQ6ICdEZWNyZW1lbnQgU2Vjb25kJyxcbiAgICAgICAgICAgIHRvZ2dsZVBlcmlvZDogJ1RvZ2dsZSBQZXJpb2QnLFxuICAgICAgICAgICAgc2VsZWN0VGltZTogJ1NlbGVjdCBUaW1lJyxcbiAgICAgICAgICAgIHNlbGVjdERhdGU6ICdTZWxlY3QgRGF0ZSdcbiAgICAgICAgfSxcbiAgICAgICAgdXNlU3RyaWN0OiBmYWxzZSxcbiAgICAgICAgc2lkZUJ5U2lkZTogZmFsc2UsXG4gICAgICAgIGRheXNPZldlZWtEaXNhYmxlZDogZmFsc2UsXG4gICAgICAgIGNhbGVuZGFyV2Vla3M6IGZhbHNlLFxuICAgICAgICB2aWV3TW9kZTogJ2RheXMnLFxuICAgICAgICB0b29sYmFyUGxhY2VtZW50OiAnZGVmYXVsdCcsXG4gICAgICAgIGJ1dHRvbnM6IHtcbiAgICAgICAgICAgIHNob3dUb2RheTogZmFsc2UsXG4gICAgICAgICAgICBzaG93Q2xlYXI6IGZhbHNlLFxuICAgICAgICAgICAgc2hvd0Nsb3NlOiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICB3aWRnZXRQb3NpdGlvbmluZzoge1xuICAgICAgICAgICAgaG9yaXpvbnRhbDogJ2F1dG8nLFxuICAgICAgICAgICAgdmVydGljYWw6ICdhdXRvJ1xuICAgICAgICB9LFxuICAgICAgICB3aWRnZXRQYXJlbnQ6IG51bGwsXG4gICAgICAgIGlnbm9yZVJlYWRvbmx5OiBmYWxzZSxcbiAgICAgICAga2VlcE9wZW46IGZhbHNlLFxuICAgICAgICBmb2N1c09uU2hvdzogdHJ1ZSxcbiAgICAgICAgaW5saW5lOiBmYWxzZSxcbiAgICAgICAga2VlcEludmFsaWQ6IGZhbHNlLFxuICAgICAgICBrZXlCaW5kczoge1xuICAgICAgICAgICAgdXA6IGZ1bmN0aW9uIHVwKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCg3LCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCh0aGlzLnN0ZXBwaW5nKCksICdtJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkb3duOiBmdW5jdGlvbiBkb3duKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDcsICdkJykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QodGhpcy5zdGVwcGluZygpLCAnbScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2NvbnRyb2wgdXAnOiBmdW5jdGlvbiBjb250cm9sVXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICd5JykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICdoJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnY29udHJvbCBkb3duJzogZnVuY3Rpb24gY29udHJvbERvd24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAneScpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdoJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsZWZ0OiBmdW5jdGlvbiBsZWZ0KCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmlnaHQ6IGZ1bmN0aW9uIHJpZ2h0KCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhZ2VVcDogZnVuY3Rpb24gcGFnZVVwKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnTScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFnZURvd246IGZ1bmN0aW9uIHBhZ2VEb3duKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ00nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudGVyOiBmdW5jdGlvbiBlbnRlcigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXNjYXBlOiBmdW5jdGlvbiBlc2NhcGUoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdjb250cm9sIHNwYWNlJzogZnVuY3Rpb24gY29udHJvbFNwYWNlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcuYnRuW2RhdGEtYWN0aW9uPVwidG9nZ2xlUGVyaW9kXCJdJykuY2xpY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdDogZnVuY3Rpb24gdCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlKHRoaXMuZ2V0TW9tZW50KCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdkZWxldGUnOiBmdW5jdGlvbiBfZGVsZXRlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICAgICAgYWxsb3dJbnB1dFRvZ2dsZTogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkVGltZUludGVydmFsczogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkSG91cnM6IGZhbHNlLFxuICAgICAgICBlbmFibGVkSG91cnM6IGZhbHNlLFxuICAgICAgICB2aWV3RGF0ZTogZmFsc2UsXG4gICAgICAgIGFsbG93TXVsdGlkYXRlOiBmYWxzZSxcbiAgICAgICAgbXVsdGlkYXRlU2VwYXJhdG9yOiAnLCdcbiAgICB9O1xuXG4gICAgLy8gUmVTaGFycGVyIHJlc3RvcmUgSW5jb25zaXN0ZW50TmFtaW5nXG5cbiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIERlY2xhcmF0aW9uSGlkZXNcbiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIEluY29uc2lzdGVudE5hbWluZ1xuXG4gICAgdmFyIERhdGVUaW1lUGlja2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvKiogQG5hbWVzcGFjZSBlRGF0YS5kYXRlT3B0aW9ucyAqL1xuICAgICAgICAvKiogQG5hbWVzcGFjZSBtb21lbnQudHogKi9cblxuICAgICAgICBmdW5jdGlvbiBEYXRlVGltZVBpY2tlcihlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRGF0ZVRpbWVQaWNrZXIpO1xuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zID0gdGhpcy5fZ2V0T3B0aW9ucyhvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICAgICAgdGhpcy5fZGF0ZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkID0gW107XG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnVuc2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLndpZGdldCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy51c2UyNEhvdXJzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuYWN0dWFsRm9ybWF0ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMucGFyc2VGb3JtYXRzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuTWluVmlld01vZGVOdW1iZXIgPSAwO1xuXG4gICAgICAgICAgICB0aGlzLl9pbnQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgKi9cblxuXG4gICAgICAgIC8vcHJpdmF0ZVxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW50ID0gZnVuY3Rpb24gX2ludCgpIHtcbiAgICAgICAgICAgIHZhciB0YXJnZXRJbnB1dCA9IHRoaXMuX2VsZW1lbnQuZGF0YSgndGFyZ2V0LWlucHV0Jyk7XG4gICAgICAgICAgICBpZiAodGhpcy5fZWxlbWVudC5pcygnaW5wdXQnKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQgPSB0aGlzLl9lbGVtZW50O1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRJbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldElucHV0ID09PSAnbmVhcmVzdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dCA9IHRoaXMuX2VsZW1lbnQuZmluZCgnaW5wdXQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0ID0gJCh0YXJnZXRJbnB1dCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9kYXRlcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fZGF0ZXNbMF0gPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSB0aGlzLmdldE1vbWVudCgpLmNsb25lKCk7XG5cbiAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHRoaXMuX29wdGlvbnMsIHRoaXMuX2RhdGFUb09wdGlvbnMoKSk7XG5cbiAgICAgICAgICAgIHRoaXMub3B0aW9ucyh0aGlzLl9vcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LmlzKCdpbnB1dCcpICYmIHRoaXMuaW5wdXQudmFsKCkudHJpbSgpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX3BhcnNlSW5wdXREYXRlKHRoaXMuaW5wdXQudmFsKCkudHJpbSgpKSwgMCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgJiYgdGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQuYXR0cigncGxhY2Vob2xkZXInKSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3VwZGF0ZSA9IGZ1bmN0aW9uIF91cGRhdGUoKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fZmlsbERhdGUoKTtcbiAgICAgICAgICAgIHRoaXMuX2ZpbGxUaW1lKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9zZXRWYWx1ZSA9IGZ1bmN0aW9uIF9zZXRWYWx1ZSh0YXJnZXRNb21lbnQsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgb2xkRGF0ZSA9IHRoaXMudW5zZXQgPyBudWxsIDogdGhpcy5fZGF0ZXNbaW5kZXhdO1xuICAgICAgICAgICAgdmFyIG91dHBWYWx1ZSA9ICcnO1xuICAgICAgICAgICAgLy8gY2FzZSBvZiBjYWxsaW5nIHNldFZhbHVlKG51bGwgb3IgZmFsc2UpXG4gICAgICAgICAgICBpZiAoIXRhcmdldE1vbWVudCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSB8fCB0aGlzLl9kYXRlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51bnNldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkID0gW107XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gdGhpcy5fZWxlbWVudC5kYXRhKCdkYXRlJykgKyAnLCc7XG4gICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSA9IG91dHBWYWx1ZS5yZXBsYWNlKG9sZERhdGUuZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSArICcsJywgJycpLnJlcGxhY2UoJywsJywgJycpLnJlcGxhY2UoLyxcXHMqJC8sICcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWQuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnZhbChvdXRwVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnRyaWdnZXIoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQuZGF0YSgnZGF0ZScsIG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgICAgICAgICAgIGRhdGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0YXJnZXRNb21lbnQgPSB0YXJnZXRNb21lbnQuY2xvbmUoKS5sb2NhbGUodGhpcy5fb3B0aW9ucy5sb2NhbGUpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5faGFzVGltZVpvbmUoKSkge1xuICAgICAgICAgICAgICAgIHRhcmdldE1vbWVudC50eih0aGlzLl9vcHRpb25zLnRpbWVab25lKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuc3RlcHBpbmcgIT09IDEpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRNb21lbnQubWludXRlcyhNYXRoLnJvdW5kKHRhcmdldE1vbWVudC5taW51dGVzKCkgLyB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nKSAqIHRoaXMuX29wdGlvbnMuc3RlcHBpbmcpLnNlY29uZHMoMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpbmRleF0gPSB0YXJnZXRNb21lbnQ7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWRbaW5kZXhdID0gdGFyZ2V0TW9tZW50LmZvcm1hdCgnWVlZWS1NTS1ERCcpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gdGFyZ2V0TW9tZW50LmNsb25lKCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgJiYgdGhpcy5fZGF0ZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgKz0gJycgKyB0aGlzLl9kYXRlc1tpXS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpICsgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gb3V0cFZhbHVlLnJlcGxhY2UoLyxcXHMqJC8sICcnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSB0aGlzLl9kYXRlc1tpbmRleF0uZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnZhbChvdXRwVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnRyaWdnZXIoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQuZGF0YSgnZGF0ZScsIG91dHBWYWx1ZSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnVuc2V0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgICAgICAgICAgIGRhdGU6IHRoaXMuX2RhdGVzW2luZGV4XS5jbG9uZSgpLFxuICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnZhbCgnJyArICh0aGlzLnVuc2V0ID8gJycgOiB0aGlzLl9kYXRlc1tpbmRleF0uZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC50cmlnZ2VyKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZTogdGFyZ2V0TW9tZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5FUlJPUixcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogdGFyZ2V0TW9tZW50LFxuICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9jaGFuZ2UgPSBmdW5jdGlvbiBfY2hhbmdlKGUpIHtcbiAgICAgICAgICAgIHZhciB2YWwgPSAkKGUudGFyZ2V0KS52YWwoKS50cmltKCksXG4gICAgICAgICAgICAgICAgcGFyc2VkRGF0ZSA9IHZhbCA/IHRoaXMuX3BhcnNlSW5wdXREYXRlKHZhbCkgOiBudWxsO1xuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUocGFyc2VkRGF0ZSk7XG4gICAgICAgICAgICBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTTWV0aG9kQ2FuQmVTdGF0aWNcblxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uIF9nZXRPcHRpb25zKG9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgRGVmYXVsdCwgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm4gb3B0aW9ucztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2hhc1RpbWVab25lID0gZnVuY3Rpb24gX2hhc1RpbWVab25lKCkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbWVudC50eiAhPT0gdW5kZWZpbmVkICYmIHRoaXMuX29wdGlvbnMudGltZVpvbmUgIT09IHVuZGVmaW5lZCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSBudWxsICYmIHRoaXMuX29wdGlvbnMudGltZVpvbmUgIT09ICcnO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNFbmFibGVkID0gZnVuY3Rpb24gX2lzRW5hYmxlZChncmFudWxhcml0eSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBncmFudWxhcml0eSAhPT0gJ3N0cmluZycgfHwgZ3JhbnVsYXJpdHkubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lzRW5hYmxlZCBleHBlY3RzIGEgc2luZ2xlIGNoYXJhY3RlciBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzd2l0Y2ggKGdyYW51bGFyaXR5KSB7XG4gICAgICAgICAgICAgICAgY2FzZSAneSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC5pbmRleE9mKCdZJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZignTScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZCcpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgICAgICBjYXNlICdIJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignaCcpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdtJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ20nKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC5pbmRleE9mKCdzJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2EnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0EnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdhJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2hhc1RpbWUgPSBmdW5jdGlvbiBfaGFzVGltZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc0VuYWJsZWQoJ2gnKSB8fCB0aGlzLl9pc0VuYWJsZWQoJ20nKSB8fCB0aGlzLl9pc0VuYWJsZWQoJ3MnKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2hhc0RhdGUgPSBmdW5jdGlvbiBfaGFzRGF0ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc0VuYWJsZWQoJ3knKSB8fCB0aGlzLl9pc0VuYWJsZWQoJ00nKSB8fCB0aGlzLl9pc0VuYWJsZWQoJ2QnKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2RhdGFUb09wdGlvbnMgPSBmdW5jdGlvbiBfZGF0YVRvT3B0aW9ucygpIHtcbiAgICAgICAgICAgIHZhciBlRGF0YSA9IHRoaXMuX2VsZW1lbnQuZGF0YSgpO1xuICAgICAgICAgICAgdmFyIGRhdGFPcHRpb25zID0ge307XG5cbiAgICAgICAgICAgIGlmIChlRGF0YS5kYXRlT3B0aW9ucyAmJiBlRGF0YS5kYXRlT3B0aW9ucyBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgICAgICAgICAgICAgIGRhdGFPcHRpb25zID0gJC5leHRlbmQodHJ1ZSwgZGF0YU9wdGlvbnMsIGVEYXRhLmRhdGVPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJC5lYWNoKHRoaXMuX29wdGlvbnMsIGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXR0cmlidXRlTmFtZSA9ICdkYXRlJyArIGtleS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGtleS5zbGljZSgxKTsgLy90b2RvIGRhdGEgYXBpIGtleVxuICAgICAgICAgICAgICAgIGlmIChlRGF0YVthdHRyaWJ1dGVOYW1lXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFPcHRpb25zW2tleV0gPSBlRGF0YVthdHRyaWJ1dGVOYW1lXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZGF0YU9wdGlvbnNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBkYXRhT3B0aW9ucztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX25vdGlmeUV2ZW50ID0gZnVuY3Rpb24gX25vdGlmeUV2ZW50KGUpIHtcbiAgICAgICAgICAgIGlmIChlLnR5cGUgPT09IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSAmJiAoZS5kYXRlICYmIGUuZGF0ZS5pc1NhbWUoZS5vbGREYXRlKSkgfHwgIWUuZGF0ZSAmJiAhZS5vbGREYXRlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fZWxlbWVudC50cmlnZ2VyKGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fdmlld1VwZGF0ZSA9IGZ1bmN0aW9uIF92aWV3VXBkYXRlKGUpIHtcbiAgICAgICAgICAgIGlmIChlID09PSAneScpIHtcbiAgICAgICAgICAgICAgICBlID0gJ1lZWVknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LlVQREFURSxcbiAgICAgICAgICAgICAgICBjaGFuZ2U6IGUsXG4gICAgICAgICAgICAgICAgdmlld0RhdGU6IHRoaXMuX3ZpZXdEYXRlLmNsb25lKClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fc2hvd01vZGUgPSBmdW5jdGlvbiBfc2hvd01vZGUoZGlyKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRpcikge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgodGhpcy5NaW5WaWV3TW9kZU51bWJlciwgTWF0aC5taW4oMywgdGhpcy5jdXJyZW50Vmlld01vZGUgKyBkaXIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyID4gZGl2JykuaGlkZSgpLmZpbHRlcignLmRhdGVwaWNrZXItJyArIERhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uQ0xBU1NfTkFNRSkuc2hvdygpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNJbkRpc2FibGVkRGF0ZXMgPSBmdW5jdGlvbiBfaXNJbkRpc2FibGVkRGF0ZXModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXNbdGVzdERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID09PSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNJbkVuYWJsZWREYXRlcyA9IGZ1bmN0aW9uIF9pc0luRW5hYmxlZERhdGVzKHRlc3REYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXNbdGVzdERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID09PSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNJbkRpc2FibGVkSG91cnMgPSBmdW5jdGlvbiBfaXNJbkRpc2FibGVkSG91cnModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnNbdGVzdERhdGUuZm9ybWF0KCdIJyldID09PSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNJbkVuYWJsZWRIb3VycyA9IGZ1bmN0aW9uIF9pc0luRW5hYmxlZEhvdXJzKHRlc3REYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnNbdGVzdERhdGUuZm9ybWF0KCdIJyldID09PSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faXNWYWxpZCA9IGZ1bmN0aW9uIF9pc1ZhbGlkKHRhcmdldE1vbWVudCwgZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgICAgIGlmICghdGFyZ2V0TW9tZW50LmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiB0aGlzLl9pc0luRGlzYWJsZWREYXRlcyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgIXRoaXMuX2lzSW5FbmFibGVkRGF0ZXModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgdGFyZ2V0TW9tZW50LmlzQmVmb3JlKHRoaXMuX29wdGlvbnMubWluRGF0ZSwgZ3JhbnVsYXJpdHkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWF4RGF0ZSAmJiB0YXJnZXRNb21lbnQuaXNBZnRlcih0aGlzLl9vcHRpb25zLm1heERhdGUsIGdyYW51bGFyaXR5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkLmluZGV4T2YodGFyZ2V0TW9tZW50LmRheSgpKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykgJiYgdGhpcy5faXNJbkRpc2FibGVkSG91cnModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpICYmICF0aGlzLl9pc0luRW5hYmxlZEhvdXJzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSkge1xuICAgICAgICAgICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICQuZWFjaCh0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGFyZ2V0TW9tZW50LmlzQmV0d2Vlbih0aGlzWzBdLCB0aGlzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3BhcnNlSW5wdXREYXRlID0gZnVuY3Rpb24gX3BhcnNlSW5wdXREYXRlKGlucHV0RGF0ZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmICghbW9tZW50LmlzTW9tZW50KGlucHV0RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXREYXRlID0gdGhpcy5nZXRNb21lbnQoaW5wdXREYXRlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlucHV0RGF0ZSA9IHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUoaW5wdXREYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vaW5wdXREYXRlLmxvY2FsZSh0aGlzLm9wdGlvbnMubG9jYWxlKTtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dERhdGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9rZXlkb3duID0gZnVuY3Rpb24gX2tleWRvd24oZSkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZXIgPSBudWxsLFxuICAgICAgICAgICAgICAgIGluZGV4ID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGluZGV4MiA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBrZXlCaW5kS2V5cyA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIHByZXNzZWRLZXlzID0gW10sXG4gICAgICAgICAgICAgICAgcHJlc3NlZE1vZGlmaWVycyA9IHt9LFxuICAgICAgICAgICAgICAgIGN1cnJlbnRLZXkgPSBlLndoaWNoLFxuICAgICAgICAgICAgICAgIHByZXNzZWQgPSAncCc7XG5cbiAgICAgICAgICAgIGtleVN0YXRlW2N1cnJlbnRLZXldID0gcHJlc3NlZDtcblxuICAgICAgICAgICAgZm9yIChpbmRleCBpbiBrZXlTdGF0ZSkge1xuICAgICAgICAgICAgICAgIGlmIChrZXlTdGF0ZS5oYXNPd25Qcm9wZXJ0eShpbmRleCkgJiYga2V5U3RhdGVbaW5kZXhdID09PSBwcmVzc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXNzZWRLZXlzLnB1c2goaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGFyc2VJbnQoaW5kZXgsIDEwKSAhPT0gY3VycmVudEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJlc3NlZE1vZGlmaWVyc1tpbmRleF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKGluZGV4IGluIHRoaXMuX29wdGlvbnMua2V5QmluZHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5rZXlCaW5kcy5oYXNPd25Qcm9wZXJ0eShpbmRleCkgJiYgdHlwZW9mIHRoaXMuX29wdGlvbnMua2V5QmluZHNbaW5kZXhdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleUJpbmRLZXlzID0gaW5kZXguc3BsaXQoJyAnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleUJpbmRLZXlzLmxlbmd0aCA9PT0gcHJlc3NlZEtleXMubGVuZ3RoICYmIEtleU1hcFtjdXJyZW50S2V5XSA9PT0ga2V5QmluZEtleXNba2V5QmluZEtleXMubGVuZ3RoIC0gMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbE1vZGlmaWVyc1ByZXNzZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpbmRleDIgPSBrZXlCaW5kS2V5cy5sZW5ndGggLSAyOyBpbmRleDIgPj0gMDsgaW5kZXgyLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShLZXlNYXBba2V5QmluZEtleXNbaW5kZXgyXV0gaW4gcHJlc3NlZE1vZGlmaWVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWxsTW9kaWZpZXJzUHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZXIgPSB0aGlzLl9vcHRpb25zLmtleUJpbmRzW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlci5jYWxsKHRoaXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNNZXRob2RDYW5CZVN0YXRpYyxTcGVsbENoZWNraW5nSW5zcGVjdGlvblxuXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9rZXl1cCA9IGZ1bmN0aW9uIF9rZXl1cChlKSB7XG4gICAgICAgICAgICBrZXlTdGF0ZVtlLndoaWNoXSA9ICdyJztcbiAgICAgICAgICAgIGlmIChrZXlQcmVzc0hhbmRsZWRbZS53aGljaF0pIHtcbiAgICAgICAgICAgICAgICBrZXlQcmVzc0hhbmRsZWRbZS53aGljaF0gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2luZGV4R2l2ZW5EYXRlcyA9IGZ1bmN0aW9uIF9pbmRleEdpdmVuRGF0ZXMoZ2l2ZW5EYXRlc0FycmF5KSB7XG4gICAgICAgICAgICAvLyBTdG9yZSBnaXZlbiBlbmFibGVkRGF0ZXMgYW5kIGRpc2FibGVkRGF0ZXMgYXMga2V5cy5cbiAgICAgICAgICAgIC8vIFRoaXMgd2F5IHdlIGNhbiBjaGVjayB0aGVpciBleGlzdGVuY2UgaW4gTygxKSB0aW1lIGluc3RlYWQgb2YgbG9vcGluZyB0aHJvdWdoIHdob2xlIGFycmF5LlxuICAgICAgICAgICAgLy8gKGZvciBleGFtcGxlOiBvcHRpb25zLmVuYWJsZWREYXRlc1snMjAxNC0wMi0yNyddID09PSB0cnVlKVxuICAgICAgICAgICAgdmFyIGdpdmVuRGF0ZXNJbmRleGVkID0ge30sXG4gICAgICAgICAgICAgICAgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICAkLmVhY2goZ2l2ZW5EYXRlc0FycmF5LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGREYXRlID0gc2VsZi5fcGFyc2VJbnB1dERhdGUodGhpcyk7XG4gICAgICAgICAgICAgICAgaWYgKGREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgICAgICBnaXZlbkRhdGVzSW5kZXhlZFtkRGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGdpdmVuRGF0ZXNJbmRleGVkKS5sZW5ndGggPyBnaXZlbkRhdGVzSW5kZXhlZCA6IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW5kZXhHaXZlbkhvdXJzID0gZnVuY3Rpb24gX2luZGV4R2l2ZW5Ib3VycyhnaXZlbkhvdXJzQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIFN0b3JlIGdpdmVuIGVuYWJsZWRIb3VycyBhbmQgZGlzYWJsZWRIb3VycyBhcyBrZXlzLlxuICAgICAgICAgICAgLy8gVGhpcyB3YXkgd2UgY2FuIGNoZWNrIHRoZWlyIGV4aXN0ZW5jZSBpbiBPKDEpIHRpbWUgaW5zdGVhZCBvZiBsb29waW5nIHRocm91Z2ggd2hvbGUgYXJyYXkuXG4gICAgICAgICAgICAvLyAoZm9yIGV4YW1wbGU6IG9wdGlvbnMuZW5hYmxlZEhvdXJzWycyMDE0LTAyLTI3J10gPT09IHRydWUpXG4gICAgICAgICAgICB2YXIgZ2l2ZW5Ib3Vyc0luZGV4ZWQgPSB7fTtcbiAgICAgICAgICAgICQuZWFjaChnaXZlbkhvdXJzQXJyYXksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBnaXZlbkhvdXJzSW5kZXhlZFt0aGlzXSA9IHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhnaXZlbkhvdXJzSW5kZXhlZCkubGVuZ3RoID8gZ2l2ZW5Ib3Vyc0luZGV4ZWQgOiBmYWxzZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2luaXRGb3JtYXR0aW5nID0gZnVuY3Rpb24gX2luaXRGb3JtYXR0aW5nKCkge1xuICAgICAgICAgICAgdmFyIGZvcm1hdCA9IHRoaXMuX29wdGlvbnMuZm9ybWF0IHx8ICdMIExUJyxcbiAgICAgICAgICAgICAgICBzZWxmID0gdGhpcztcblxuICAgICAgICAgICAgdGhpcy5hY3R1YWxGb3JtYXQgPSBmb3JtYXQucmVwbGFjZSgvKFxcW1teXFxbXSpdKXwoXFxcXCk/KExUU3xMVHxMTD9MP0w/fGx7MSw0fSkvZywgZnVuY3Rpb24gKGZvcm1hdElucHV0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2RhdGVzWzBdLmxvY2FsZURhdGEoKS5sb25nRGF0ZUZvcm1hdChmb3JtYXRJbnB1dCkgfHwgZm9ybWF0SW5wdXQ7IC8vdG9kbyB0YWtpbmcgdGhlIGZpcnN0IGRhdGUgc2hvdWxkIGJlIG9rXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy5wYXJzZUZvcm1hdHMgPSB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cyA/IHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzLnNsaWNlKCkgOiBbXTtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhcnNlRm9ybWF0cy5pbmRleE9mKGZvcm1hdCkgPCAwICYmIHRoaXMucGFyc2VGb3JtYXRzLmluZGV4T2YodGhpcy5hY3R1YWxGb3JtYXQpIDwgMCkge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyc2VGb3JtYXRzLnB1c2godGhpcy5hY3R1YWxGb3JtYXQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnVzZTI0SG91cnMgPSB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2EnKSA8IDEgJiYgdGhpcy5hY3R1YWxGb3JtYXQucmVwbGFjZSgvXFxbLio/XS9nLCAnJykuaW5kZXhPZignaCcpIDwgMTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgneScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdNJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLk1pblZpZXdNb2RlTnVtYmVyID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ2QnKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuTWluVmlld01vZGVOdW1iZXIgPSAwO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRWaWV3TW9kZSA9IE1hdGgubWF4KHRoaXMuTWluVmlld01vZGVOdW1iZXIsIHRoaXMuY3VycmVudFZpZXdNb2RlKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnVuc2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbMF0sIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZ2V0TGFzdFBpY2tlZERhdGUgPSBmdW5jdGlvbiBfZ2V0TGFzdFBpY2tlZERhdGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXNbdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpXTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2dldExhc3RQaWNrZWREYXRlSW5kZXggPSBmdW5jdGlvbiBfZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlcy5sZW5ndGggLSAxO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vcHVibGljXG5cblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZ2V0TW9tZW50ID0gZnVuY3Rpb24gZ2V0TW9tZW50KGQpIHtcbiAgICAgICAgICAgIHZhciByZXR1cm5Nb21lbnQgPSB2b2lkIDA7XG5cbiAgICAgICAgICAgIGlmIChkID09PSB1bmRlZmluZWQgfHwgZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudCgpOyAvL1RPRE8gc2hvdWxkIHRoaXMgdXNlIGZvcm1hdD8gYW5kIGxvY2FsZT9cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5faGFzVGltZVpvbmUoKSkge1xuICAgICAgICAgICAgICAgIC8vIFRoZXJlIGlzIGEgc3RyaW5nIHRvIHBhcnNlIGFuZCBhIGRlZmF1bHQgdGltZSB6b25lXG4gICAgICAgICAgICAgICAgLy8gcGFyc2Ugd2l0aCB0aGUgdHogZnVuY3Rpb24gd2hpY2ggdGFrZXMgYSBkZWZhdWx0IHRpbWUgem9uZSBpZiBpdCBpcyBub3QgaW4gdGhlIGZvcm1hdCBzdHJpbmdcbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQgPSBtb21lbnQudHooZCwgdGhpcy5wYXJzZUZvcm1hdHMsIHRoaXMuX29wdGlvbnMubG9jYWxlLCB0aGlzLl9vcHRpb25zLnVzZVN0cmljdCwgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudChkLCB0aGlzLnBhcnNlRm9ybWF0cywgdGhpcy5fb3B0aW9ucy5sb2NhbGUsIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQudHoodGhpcy5fb3B0aW9ucy50aW1lWm9uZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXR1cm5Nb21lbnQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnRvZ2dsZSA9IGZ1bmN0aW9uIHRvZ2dsZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpZGdldCA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmlnbm9yZVJlYWRvbmx5ID0gZnVuY3Rpb24gaWdub3JlUmVhZG9ubHkoX2lnbm9yZVJlYWRvbmx5KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmlnbm9yZVJlYWRvbmx5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfaWdub3JlUmVhZG9ubHkgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lnbm9yZVJlYWRvbmx5ICgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5pZ25vcmVSZWFkb25seSA9IF9pZ25vcmVSZWFkb25seTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUub3B0aW9ucyA9IGZ1bmN0aW9uIG9wdGlvbnMobmV3T3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQodHJ1ZSwge30sIHRoaXMuX29wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShuZXdPcHRpb25zIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMoKSB0aGlzLm9wdGlvbnMgcGFyYW1ldGVyIHNob3VsZCBiZSBhbiBvYmplY3QnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHRoaXMuX29wdGlvbnMsIG5ld09wdGlvbnMpO1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgJC5lYWNoKHRoaXMuX29wdGlvbnMsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGZba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGZba2V5XSh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRhdGUgPSBmdW5jdGlvbiBkYXRlKG5ld0RhdGUsIGluZGV4KSB7XG4gICAgICAgICAgICBpbmRleCA9IGluZGV4IHx8IDA7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnVuc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXMuam9pbih0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzW2luZGV4XS5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG5ld0RhdGUgIT09IG51bGwgJiYgdHlwZW9mIG5ld0RhdGUgIT09ICdzdHJpbmcnICYmICFtb21lbnQuaXNNb21lbnQobmV3RGF0ZSkgJiYgIShuZXdEYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mIFtudWxsLCBzdHJpbmcsIG1vbWVudCBvciBEYXRlXScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShuZXdEYXRlID09PSBudWxsID8gbnVsbCA6IHRoaXMuX3BhcnNlSW5wdXREYXRlKG5ld0RhdGUpLCBpbmRleCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmZvcm1hdCA9IGZ1bmN0aW9uIGZvcm1hdChuZXdGb3JtYXQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZm9ybWF0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ3N0cmluZycgJiYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdib29sZWFuJyB8fCBuZXdGb3JtYXQgIT09IGZhbHNlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Zvcm1hdCgpIGV4cGVjdHMgYSBzdHJpbmcgb3IgYm9vbGVhbjpmYWxzZSBwYXJhbWV0ZXIgJyArIG5ld0Zvcm1hdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZm9ybWF0ID0gbmV3Rm9ybWF0O1xuICAgICAgICAgICAgaWYgKHRoaXMuYWN0dWFsRm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0aWFsaXplIGZvcm1hdHRpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudGltZVpvbmUgPSBmdW5jdGlvbiB0aW1lWm9uZShuZXdab25lKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnRpbWVab25lO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld1pvbmUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbmV3Wm9uZSgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudGltZVpvbmUgPSBuZXdab25lO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXlWaWV3SGVhZGVyRm9ybWF0ID0gZnVuY3Rpb24gZGF5Vmlld0hlYWRlckZvcm1hdChuZXdGb3JtYXQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGF5Vmlld0hlYWRlckZvcm1hdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF5Vmlld0hlYWRlckZvcm1hdCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF5Vmlld0hlYWRlckZvcm1hdCA9IG5ld0Zvcm1hdDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZXh0cmFGb3JtYXRzID0gZnVuY3Rpb24gZXh0cmFGb3JtYXRzKGZvcm1hdHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZm9ybWF0cyAhPT0gZmFsc2UgJiYgIShmb3JtYXRzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZXh0cmFGb3JtYXRzKCkgZXhwZWN0cyBhbiBhcnJheSBvciBmYWxzZSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMgPSBmb3JtYXRzO1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VGb3JtYXRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0IGZvcm1hdHRpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWREYXRlcyA9IGZ1bmN0aW9uIGRpc2FibGVkRGF0ZXMoZGF0ZXMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMpIDogdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWRhdGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShkYXRlcyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkRGF0ZXMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gdGhpcy5faW5kZXhHaXZlbkRhdGVzKGRhdGVzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZW5hYmxlZERhdGVzID0gZnVuY3Rpb24gZW5hYmxlZERhdGVzKGRhdGVzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcykgOiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFkYXRlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShkYXRlcyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuYWJsZWREYXRlcygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IHRoaXMuX2luZGV4R2l2ZW5EYXRlcyhkYXRlcyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBmdW5jdGlvbiBkYXlzT2ZXZWVrRGlzYWJsZWQoX2RheXNPZldlZWtEaXNhYmxlZCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQuc3BsaWNlKDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9kYXlzT2ZXZWVrRGlzYWJsZWQgPT09ICdib29sZWFuJyAmJiAhX2RheXNPZldlZWtEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF9kYXlzT2ZXZWVrRGlzYWJsZWQgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXlzT2ZXZWVrRGlzYWJsZWQoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBfZGF5c09mV2Vla0Rpc2FibGVkLnJlZHVjZShmdW5jdGlvbiAocHJldmlvdXNWYWx1ZSwgY3VycmVudFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFZhbHVlID0gcGFyc2VJbnQoY3VycmVudFZhbHVlLCAxMCk7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA+IDYgfHwgY3VycmVudFZhbHVlIDwgMCB8fCBpc05hTihjdXJyZW50VmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZS5pbmRleE9mKGN1cnJlbnRWYWx1ZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUucHVzaChjdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcbiAgICAgICAgICAgIH0sIFtdKS5zb3J0KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAzMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAzMSB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubWF4RGF0ZSA9IGZ1bmN0aW9uIG1heERhdGUoX21heERhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubWF4RGF0ZSA/IHRoaXMuX29wdGlvbnMubWF4RGF0ZS5jbG9uZSgpIDogdGhpcy5fb3B0aW9ucy5tYXhEYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9tYXhEYXRlID09PSAnYm9vbGVhbicgJiYgX21heERhdGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5tYXhEYXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21heERhdGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9tYXhEYXRlID09PSAnbm93JyB8fCBfbWF4RGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICAgICAgICAgICAgX21heERhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfbWF4RGF0ZSk7XG5cbiAgICAgICAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXhEYXRlKCkgQ291bGQgbm90IHBhcnNlIGRhdGUgcGFyYW1ldGVyOiAnICsgX21heERhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiBwYXJzZWREYXRlLmlzQmVmb3JlKHRoaXMuX29wdGlvbnMubWluRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXhEYXRlKCkgZGF0ZSBwYXJhbWV0ZXIgaXMgYmVmb3JlIHRoaXMub3B0aW9ucy5taW5EYXRlOiAnICsgcGFyc2VkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWF4RGF0ZSA9IHBhcnNlZERhdGU7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCAmJiB0aGlzLl9kYXRlc1tpXS5pc0FmdGVyKF9tYXhEYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLm1heERhdGUsIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl92aWV3RGF0ZS5pc0FmdGVyKHBhcnNlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSBwYXJzZWREYXRlLmNsb25lKCkuc3VidHJhY3QodGhpcy5fb3B0aW9ucy5zdGVwcGluZywgJ20nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5taW5EYXRlID0gZnVuY3Rpb24gbWluRGF0ZShfbWluRGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5taW5EYXRlID8gdGhpcy5fb3B0aW9ucy5taW5EYXRlLmNsb25lKCkgOiB0aGlzLl9vcHRpb25zLm1pbkRhdGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21pbkRhdGUgPT09ICdib29sZWFuJyAmJiBfbWluRGF0ZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWluRGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoX21pbkRhdGUgPT09ICdub3cnIHx8IF9taW5EYXRlID09PSAnbW9tZW50Jykge1xuICAgICAgICAgICAgICAgICAgICBfbWluRGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKF9taW5EYXRlKTtcblxuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21pbkRhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBfbWluRGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHBhcnNlZERhdGUuaXNBZnRlcih0aGlzLl9vcHRpb25zLm1heERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWluRGF0ZSgpIGRhdGUgcGFyYW1ldGVyIGlzIGFmdGVyIHRoaXMub3B0aW9ucy5tYXhEYXRlOiAnICsgcGFyc2VkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWluRGF0ZSA9IHBhcnNlZERhdGU7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCAmJiB0aGlzLl9kYXRlc1tpXS5pc0JlZm9yZShfbWluRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5taW5EYXRlLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fdmlld0RhdGUuaXNCZWZvcmUocGFyc2VkRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHBhcnNlZERhdGUuY2xvbmUoKS5hZGQodGhpcy5fb3B0aW9ucy5zdGVwcGluZywgJ20nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kZWZhdWx0RGF0ZSA9IGZ1bmN0aW9uIGRlZmF1bHREYXRlKF9kZWZhdWx0RGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA/IHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIV9kZWZhdWx0RGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGVmYXVsdERhdGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9kZWZhdWx0RGF0ZSA9PT0gJ25vdycgfHwgX2RlZmF1bHREYXRlID09PSAnbW9tZW50Jykge1xuICAgICAgICAgICAgICAgICAgICBfZGVmYXVsdERhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF9kZWZhdWx0RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KF9kZWZhdWx0RGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKF9kZWZhdWx0RGF0ZSk7XG4gICAgICAgICAgICBpZiAoIXBhcnNlZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVmYXVsdERhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBfZGVmYXVsdERhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHBhcnNlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVmYXVsdERhdGUoKSBkYXRlIHBhc3NlZCBpcyBpbnZhbGlkIGFjY29yZGluZyB0byBjb21wb25lbnQgc2V0dXAgdmFsaWRhdGlvbnMnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA9IHBhcnNlZERhdGU7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlICYmIHRoaXMuX29wdGlvbnMuaW5saW5lIHx8IHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubG9jYWxlID0gZnVuY3Rpb24gbG9jYWxlKF9sb2NhbGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubG9jYWxlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIW1vbWVudC5sb2NhbGVEYXRhKF9sb2NhbGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbG9jYWxlKCkgbG9jYWxlICcgKyBfbG9jYWxlICsgJyBpcyBub3QgbG9hZGVkIGZyb20gbW9tZW50IGxvY2FsZXMhJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubG9jYWxlID0gX2xvY2FsZTtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5sb2NhbGUodGhpcy5fb3B0aW9ucy5sb2NhbGUpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5hY3R1YWxGb3JtYXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXRpYWxpemUgZm9ybWF0dGluZ1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnN0ZXBwaW5nID0gZnVuY3Rpb24gc3RlcHBpbmcoX3N0ZXBwaW5nKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBfc3RlcHBpbmcgPSBwYXJzZUludChfc3RlcHBpbmcsIDEwKTtcbiAgICAgICAgICAgIGlmIChpc05hTihfc3RlcHBpbmcpIHx8IF9zdGVwcGluZyA8IDEpIHtcbiAgICAgICAgICAgICAgICBfc3RlcHBpbmcgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5zdGVwcGluZyA9IF9zdGVwcGluZztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudXNlQ3VycmVudCA9IGZ1bmN0aW9uIHVzZUN1cnJlbnQoX3VzZUN1cnJlbnQpIHtcbiAgICAgICAgICAgIHZhciB1c2VDdXJyZW50T3B0aW9ucyA9IFsneWVhcicsICdtb250aCcsICdkYXknLCAnaG91cicsICdtaW51dGUnXTtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfdXNlQ3VycmVudCAhPT0gJ2Jvb2xlYW4nICYmIHR5cGVvZiBfdXNlQ3VycmVudCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1c2VDdXJyZW50KCkgZXhwZWN0cyBhIGJvb2xlYW4gb3Igc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfdXNlQ3VycmVudCA9PT0gJ3N0cmluZycgJiYgdXNlQ3VycmVudE9wdGlvbnMuaW5kZXhPZihfdXNlQ3VycmVudC50b0xvd2VyQ2FzZSgpKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1c2VDdXJyZW50KCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXIgb2YgJyArIHVzZUN1cnJlbnRPcHRpb25zLmpvaW4oJywgJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ID0gX3VzZUN1cnJlbnQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmNvbGxhcHNlID0gZnVuY3Rpb24gY29sbGFwc2UoX2NvbGxhcHNlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmNvbGxhcHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9jb2xsYXBzZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignY29sbGFwc2UoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmNvbGxhcHNlID09PSBfY29sbGFwc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuY29sbGFwc2UgPSBfY29sbGFwc2U7XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuaWNvbnMgPSBmdW5jdGlvbiBpY29ucyhfaWNvbnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmljb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX2ljb25zIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2ljb25zKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYW4gT2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQuZXh0ZW5kKHRoaXMuX29wdGlvbnMuaWNvbnMsIF9pY29ucyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS50b29sdGlwcyA9IGZ1bmN0aW9uIHRvb2x0aXBzKF90b29sdGlwcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMudG9vbHRpcHMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfdG9vbHRpcHMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndG9vbHRpcHMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZXh0ZW5kKHRoaXMuX29wdGlvbnMudG9vbHRpcHMsIF90b29sdGlwcyk7XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudXNlU3RyaWN0ID0gZnVuY3Rpb24gdXNlU3RyaWN0KF91c2VTdHJpY3QpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF91c2VTdHJpY3QgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VzZVN0cmljdCgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy51c2VTdHJpY3QgPSBfdXNlU3RyaWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5zaWRlQnlTaWRlID0gZnVuY3Rpb24gc2lkZUJ5U2lkZShfc2lkZUJ5U2lkZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5zaWRlQnlTaWRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9zaWRlQnlTaWRlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzaWRlQnlTaWRlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnNpZGVCeVNpZGUgPSBfc2lkZUJ5U2lkZTtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS52aWV3TW9kZSA9IGZ1bmN0aW9uIHZpZXdNb2RlKF92aWV3TW9kZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy52aWV3TW9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfdmlld01vZGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmlld01vZGUoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoRGF0ZVRpbWVQaWNrZXIuVmlld01vZGVzLmluZGV4T2YoX3ZpZXdNb2RlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3TW9kZSgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiAoJyArIERhdGVUaW1lUGlja2VyLlZpZXdNb2Rlcy5qb2luKCcsICcpICsgJykgdmFsdWUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy52aWV3TW9kZSA9IF92aWV3TW9kZTtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgoRGF0ZVRpbWVQaWNrZXIuVmlld01vZGVzLmluZGV4T2YoX3ZpZXdNb2RlKSAtIDEsIHRoaXMuTWluVmlld01vZGVOdW1iZXIpO1xuXG4gICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5jYWxlbmRhcldlZWtzID0gZnVuY3Rpb24gY2FsZW5kYXJXZWVrcyhfY2FsZW5kYXJXZWVrcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9jYWxlbmRhcldlZWtzICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjYWxlbmRhcldlZWtzKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYSBib29sZWFuIHZhbHVlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcyA9IF9jYWxlbmRhcldlZWtzO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmJ1dHRvbnMgPSBmdW5jdGlvbiBidXR0b25zKF9idXR0b25zKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5idXR0b25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX2J1dHRvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkLmV4dGVuZCh0aGlzLl9vcHRpb25zLmJ1dHRvbnMsIF9idXR0b25zKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd1RvZGF5ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zLnNob3dUb2RheSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbGVhciAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucy5zaG93Q2xlYXIgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93Q2xvc2UgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMuc2hvd0Nsb3NlIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUua2VlcE9wZW4gPSBmdW5jdGlvbiBrZWVwT3Blbihfa2VlcE9wZW4pIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMua2VlcE9wZW47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2tlZXBPcGVuICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdrZWVwT3BlbigpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtlZXBPcGVuID0gX2tlZXBPcGVuO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5mb2N1c09uU2hvdyA9IGZ1bmN0aW9uIGZvY3VzT25TaG93KF9mb2N1c09uU2hvdykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5mb2N1c09uU2hvdztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZm9jdXNPblNob3cgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2ZvY3VzT25TaG93KCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZm9jdXNPblNob3cgPSBfZm9jdXNPblNob3c7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmlubGluZSA9IGZ1bmN0aW9uIGlubGluZShfaW5saW5lKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmlubGluZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfaW5saW5lICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpbmxpbmUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5pbmxpbmUgPSBfaW5saW5lO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobnVsbCk7IC8vdG9kb1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZXlCaW5kcyA9IGZ1bmN0aW9uIGtleUJpbmRzKF9rZXlCaW5kcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZXlCaW5kcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5rZXlCaW5kcyA9IF9rZXlCaW5kcztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGVidWcgPSBmdW5jdGlvbiBkZWJ1ZyhfZGVidWcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RlYnVnICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWJ1ZygpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRlYnVnID0gX2RlYnVnO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5hbGxvd0lucHV0VG9nZ2xlID0gZnVuY3Rpb24gYWxsb3dJbnB1dFRvZ2dsZShfYWxsb3dJbnB1dFRvZ2dsZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9hbGxvd0lucHV0VG9nZ2xlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdhbGxvd0lucHV0VG9nZ2xlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuYWxsb3dJbnB1dFRvZ2dsZSA9IF9hbGxvd0lucHV0VG9nZ2xlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZWVwSW52YWxpZCA9IGZ1bmN0aW9uIGtlZXBJbnZhbGlkKF9rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfa2VlcEludmFsaWQgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2tlZXBJbnZhbGlkKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkID0gX2tlZXBJbnZhbGlkO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXRlcGlja2VySW5wdXQgPSBmdW5jdGlvbiBkYXRlcGlja2VySW5wdXQoX2RhdGVwaWNrZXJJbnB1dCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXRlcGlja2VySW5wdXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RhdGVwaWNrZXJJbnB1dCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRlcGlja2VySW5wdXQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRhdGVwaWNrZXJJbnB1dCA9IF9kYXRlcGlja2VySW5wdXQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnBhcnNlSW5wdXREYXRlID0gZnVuY3Rpb24gcGFyc2VJbnB1dERhdGUoX3BhcnNlSW5wdXREYXRlMikge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfcGFyc2VJbnB1dERhdGUyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncGFyc2VJbnB1dERhdGUoKSBzaG91bGQgYmUgYXMgZnVuY3Rpb24nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZSA9IF9wYXJzZUlucHV0RGF0ZTI7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRpc2FibGVkVGltZUludGVydmFscyA9IGZ1bmN0aW9uIGRpc2FibGVkVGltZUludGVydmFscyhfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKF9kaXNhYmxlZFRpbWVJbnRlcnZhbHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZFRpbWVJbnRlcnZhbHMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRpc2FibGVkSG91cnMgPSBmdW5jdGlvbiBkaXNhYmxlZEhvdXJzKGhvdXJzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzKSA6IHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFob3Vycykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoaG91cnMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZEhvdXJzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA9IHRoaXMuX2luZGV4R2l2ZW5Ib3Vycyhob3Vycyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX2RhdGVzW2ldLCAnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpXS5hZGQoMSwgJ2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmllcyA9PT0gMjQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAnVHJpZWQgMjQgdGltZXMgdG8gZmluZCBhIHZhbGlkIGRhdGUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdHJpZXMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1tpXSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmVuYWJsZWRIb3VycyA9IGZ1bmN0aW9uIGVuYWJsZWRIb3Vycyhob3Vycykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMpIDogdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaG91cnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoaG91cnMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmFibGVkSG91cnMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPSB0aGlzLl9pbmRleEdpdmVuSG91cnMoaG91cnMpO1xuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAyNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAyNCB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudmlld0RhdGUgPSBmdW5jdGlvbiB2aWV3RGF0ZShuZXdEYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIW5ld0RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9ICh0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpKS5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0RhdGUgIT09ICdzdHJpbmcnICYmICFtb21lbnQuaXNNb21lbnQobmV3RGF0ZSkgJiYgIShuZXdEYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3RGF0ZSgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiBbc3RyaW5nLCBtb21lbnQgb3IgRGF0ZV0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShuZXdEYXRlKTtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuYWxsb3dNdWx0aWRhdGUgPSBmdW5jdGlvbiBhbGxvd011bHRpZGF0ZShfYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2FsbG93TXVsdGlkYXRlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdhbGxvd011bHRpZGF0ZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlID0gX2FsbG93TXVsdGlkYXRlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5tdWx0aWRhdGVTZXBhcmF0b3IgPSBmdW5jdGlvbiBtdWx0aWRhdGVTZXBhcmF0b3IoX211bHRpZGF0ZVNlcGFyYXRvcikge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX211bHRpZGF0ZVNlcGFyYXRvciAhPT0gJ3N0cmluZycgfHwgX211bHRpZGF0ZVNlcGFyYXRvci5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbXVsdGlkYXRlU2VwYXJhdG9yIGV4cGVjdHMgYSBzaW5nbGUgY2hhcmFjdGVyIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3IgPSBfbXVsdGlkYXRlU2VwYXJhdG9yO1xuICAgICAgICB9O1xuXG4gICAgICAgIF9jcmVhdGVDbGFzcyhEYXRlVGltZVBpY2tlciwgbnVsbCwgW3tcbiAgICAgICAgICAgIGtleTogJ05BTUUnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5BTUU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XHJcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RBVEFfS0VZJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEQVRBX0tFWTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnRVZFTlRfS0VZJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBFVkVOVF9LRVk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XHJcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RBVEFfQVBJX0tFWScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gREFUQV9BUElfS0VZO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdEYXRlUGlja2VyTW9kZXMnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERhdGVQaWNrZXJNb2RlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnVmlld01vZGVzJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBWaWV3TW9kZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0V2ZW50JyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBFdmVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnU2VsZWN0b3InLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFNlbGVjdG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdEZWZhdWx0JyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgRGVmYXVsdCA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdDbGFzc05hbWUnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIENsYXNzTmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfV0pO1xuXG4gICAgICAgIHJldHVybiBEYXRlVGltZVBpY2tlcjtcbiAgICB9KCk7XG5cbiAgICByZXR1cm4gRGF0ZVRpbWVQaWNrZXI7XG59KGpRdWVyeSwgbW9tZW50KTtcblxuLy9ub2luc3BlY3Rpb24gSlNVbnVzZWRHbG9iYWxTeW1ib2xzXG4vKiBnbG9iYWwgRGF0ZVRpbWVQaWNrZXIgKi9cbnZhciBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNCA9IGZ1bmN0aW9uICgkKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG4gICAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQuZm5bRGF0ZVRpbWVQaWNrZXIuTkFNRV0sXG4gICAgICAgIHZlcnRpY2FsTW9kZXMgPSBbJ3RvcCcsICdib3R0b20nLCAnYXV0byddLFxuICAgICAgICBob3Jpem9udGFsTW9kZXMgPSBbJ2xlZnQnLCAncmlnaHQnLCAnYXV0byddLFxuICAgICAgICB0b29sYmFyUGxhY2VtZW50cyA9IFsnZGVmYXVsdCcsICd0b3AnLCAnYm90dG9tJ10sXG4gICAgICAgIGdldFNlbGVjdG9yRnJvbUVsZW1lbnQgPSBmdW5jdGlvbiBnZXRTZWxlY3RvckZyb21FbGVtZW50KCRlbGVtZW50KSB7XG4gICAgICAgIHZhciBzZWxlY3RvciA9ICRlbGVtZW50LmRhdGEoJ3RhcmdldCcpLFxuICAgICAgICAgICAgJHNlbGVjdG9yID0gdm9pZCAwO1xuXG4gICAgICAgIGlmICghc2VsZWN0b3IpIHtcbiAgICAgICAgICAgIHNlbGVjdG9yID0gJGVsZW1lbnQuYXR0cignaHJlZicpIHx8ICcnO1xuICAgICAgICAgICAgc2VsZWN0b3IgPSAvXiNbYS16XS9pLnRlc3Qoc2VsZWN0b3IpID8gc2VsZWN0b3IgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgICRzZWxlY3RvciA9ICQoc2VsZWN0b3IpO1xuICAgICAgICBpZiAoJHNlbGVjdG9yLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuICRzZWxlY3RvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghJHNlbGVjdG9yLmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpKSB7XG4gICAgICAgICAgICAkLmV4dGVuZCh7fSwgJHNlbGVjdG9yLmRhdGEoKSwgJCh0aGlzKS5kYXRhKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICRzZWxlY3RvcjtcbiAgICB9O1xuXG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBJbmNvbnNpc3RlbnROYW1pbmdcblxuICAgIHZhciBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNCA9IGZ1bmN0aW9uIChfRGF0ZVRpbWVQaWNrZXIpIHtcbiAgICAgICAgX2luaGVyaXRzKFRlbXB1c0RvbWludXNCb290c3RyYXA0LCBfRGF0ZVRpbWVQaWNrZXIpO1xuXG4gICAgICAgIGZ1bmN0aW9uIFRlbXB1c0RvbWludXNCb290c3RyYXA0KGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNCk7XG5cbiAgICAgICAgICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIF9EYXRlVGltZVBpY2tlci5jYWxsKHRoaXMsIGVsZW1lbnQsIG9wdGlvbnMpKTtcblxuICAgICAgICAgICAgX3RoaXMuX2luaXQoKTtcbiAgICAgICAgICAgIHJldHVybiBfdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5faW5pdCA9IGZ1bmN0aW9uIF9pbml0KCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2VsZW1lbnQuaGFzQ2xhc3MoJ2lucHV0LWdyb3VwJykpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGF0ZXBpY2tlckJ1dHRvbiA9IHRoaXMuX2VsZW1lbnQuZmluZCgnLmRhdGVwaWNrZXJidXR0b24nKTtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZXBpY2tlckJ1dHRvbi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgPSB0aGlzLl9lbGVtZW50LmZpbmQoJ1tkYXRhLXRvZ2dsZT1cImRhdGV0aW1lcGlja2VyXCJdJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgPSBkYXRlcGlja2VyQnV0dG9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2dldERhdGVQaWNrZXJUZW1wbGF0ZSA9IGZ1bmN0aW9uIF9nZXREYXRlUGlja2VyVGVtcGxhdGUoKSB7XG4gICAgICAgICAgICB2YXIgaGVhZFRlbXBsYXRlID0gJCgnPHRoZWFkPicpLmFwcGVuZCgkKCc8dHI+JykuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygncHJldicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3ByZXZpb3VzJykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuaWNvbnMucHJldmlvdXMpKSkuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygncGlja2VyLXN3aXRjaCcpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3BpY2tlclN3aXRjaCcpLmF0dHIoJ2NvbHNwYW4nLCAnJyArICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MgPyAnNicgOiAnNScpKSkuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygnbmV4dCcpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ25leHQnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy5uZXh0KSkpKSxcbiAgICAgICAgICAgICAgICBjb250VGVtcGxhdGUgPSAkKCc8dGJvZHk+JykuYXBwZW5kKCQoJzx0cj4nKS5hcHBlbmQoJCgnPHRkPicpLmF0dHIoJ2NvbHNwYW4nLCAnJyArICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MgPyAnOCcgOiAnNycpKSkpO1xuXG4gICAgICAgICAgICByZXR1cm4gWyQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXItZGF5cycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlIHRhYmxlLXNtJykuYXBwZW5kKGhlYWRUZW1wbGF0ZSkuYXBwZW5kKCQoJzx0Ym9keT4nKSkpLCAkKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyLW1vbnRocycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpLmFwcGVuZChoZWFkVGVtcGxhdGUuY2xvbmUoKSkuYXBwZW5kKGNvbnRUZW1wbGF0ZS5jbG9uZSgpKSksICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXIteWVhcnMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKS5hcHBlbmQoaGVhZFRlbXBsYXRlLmNsb25lKCkpLmFwcGVuZChjb250VGVtcGxhdGUuY2xvbmUoKSkpLCAkKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyLWRlY2FkZXMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKS5hcHBlbmQoaGVhZFRlbXBsYXRlLmNsb25lKCkpLmFwcGVuZChjb250VGVtcGxhdGUuY2xvbmUoKSkpXTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2dldFRpbWVQaWNrZXJNYWluVGVtcGxhdGUgPSBmdW5jdGlvbiBfZ2V0VGltZVBpY2tlck1haW5UZW1wbGF0ZSgpIHtcbiAgICAgICAgICAgIHZhciB0b3BSb3cgPSAkKCc8dHI+JyksXG4gICAgICAgICAgICAgICAgbWlkZGxlUm93ID0gJCgnPHRyPicpLFxuICAgICAgICAgICAgICAgIGJvdHRvbVJvdyA9ICQoJzx0cj4nKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnaCcpKSB7XG4gICAgICAgICAgICAgICAgdG9wUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLmluY3JlbWVudEhvdXJcbiAgICAgICAgICAgICAgICB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnaW5jcmVtZW50SG91cnMnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy51cCkpKSk7XG4gICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLWhvdXInKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGEtdGltZS1jb21wb25lbnQnOiAnaG91cnMnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnBpY2tIb3VyXG4gICAgICAgICAgICAgICAgfSkuYXR0cignZGF0YS1hY3Rpb24nLCAnc2hvd0hvdXJzJykpKTtcbiAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuZGVjcmVtZW50SG91clxuICAgICAgICAgICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdkZWNyZW1lbnRIb3VycycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRvd24pKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnbScpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICAgICAgICAgIG1pZGRsZVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKS5odG1sKCc6JykpO1xuICAgICAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuaW5jcmVtZW50TWludXRlXG4gICAgICAgICAgICAgICAgfSkuYWRkQ2xhc3MoJ2J0bicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ2luY3JlbWVudE1pbnV0ZXMnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy51cCkpKSk7XG4gICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLW1pbnV0ZScpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnZGF0YS10aW1lLWNvbXBvbmVudCc6ICdtaW51dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5waWNrTWludXRlXG4gICAgICAgICAgICAgICAgfSkuYXR0cignZGF0YS1hY3Rpb24nLCAnc2hvd01pbnV0ZXMnKSkpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5kZWNyZW1lbnRNaW51dGVcbiAgICAgICAgICAgICAgICB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnZGVjcmVtZW50TWludXRlcycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRvd24pKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgncycpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnbScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICAgICAgICAgIG1pZGRsZVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKS5odG1sKCc6JykpO1xuICAgICAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuaW5jcmVtZW50U2Vjb25kXG4gICAgICAgICAgICAgICAgfSkuYWRkQ2xhc3MoJ2J0bicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ2luY3JlbWVudFNlY29uZHMnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy51cCkpKSk7XG4gICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLXNlY29uZCcpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnZGF0YS10aW1lLWNvbXBvbmVudCc6ICdzZWNvbmRzJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5waWNrU2Vjb25kXG4gICAgICAgICAgICAgICAgfSkuYXR0cignZGF0YS1hY3Rpb24nLCAnc2hvd1NlY29uZHMnKSkpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5kZWNyZW1lbnRTZWNvbmRcbiAgICAgICAgICAgICAgICB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnZGVjcmVtZW50U2Vjb25kcycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRvd24pKSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxidXR0b24+JykuYWRkQ2xhc3MoJ2J0biBidG4tcHJpbWFyeScpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnZGF0YS1hY3Rpb24nOiAndG9nZ2xlUGVyaW9kJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMudG9nZ2xlUGVyaW9kXG4gICAgICAgICAgICAgICAgfSkpKTtcbiAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gJCgnPGRpdj4nKS5hZGRDbGFzcygndGltZXBpY2tlci1waWNrZXInKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKS5hcHBlbmQoW3RvcFJvdywgbWlkZGxlUm93LCBib3R0b21Sb3ddKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9nZXRUaW1lUGlja2VyVGVtcGxhdGUgPSBmdW5jdGlvbiBfZ2V0VGltZVBpY2tlclRlbXBsYXRlKCkge1xuICAgICAgICAgICAgdmFyIGhvdXJzVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItaG91cnMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgICAgICAgbWludXRlc1ZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyLW1pbnV0ZXMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgICAgICAgc2Vjb25kc1ZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyLXNlY29uZHMnKS5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXG4gICAgICAgICAgICAgICAgcmV0ID0gW3RoaXMuX2dldFRpbWVQaWNrZXJNYWluVGVtcGxhdGUoKV07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ2gnKSkge1xuICAgICAgICAgICAgICAgIHJldC5wdXNoKGhvdXJzVmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdtJykpIHtcbiAgICAgICAgICAgICAgICByZXQucHVzaChtaW51dGVzVmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdzJykpIHtcbiAgICAgICAgICAgICAgICByZXQucHVzaChzZWNvbmRzVmlldyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9nZXRUb29sYmFyID0gZnVuY3Rpb24gX2dldFRvb2xiYXIoKSB7XG4gICAgICAgICAgICB2YXIgcm93ID0gW107XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dUb2RheSkge1xuICAgICAgICAgICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICdkYXRhLWFjdGlvbic6ICd0b2RheScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMudG9kYXlcbiAgICAgICAgICAgICAgICB9KS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy50b2RheSkpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZSAmJiB0aGlzLl9oYXNEYXRlKCkgJiYgdGhpcy5faGFzVGltZSgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRpdGxlID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgICAgICBpY29uID0gdm9pZCAwO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnZpZXdNb2RlID09PSAndGltZXMnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlID0gdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3REYXRlO1xuICAgICAgICAgICAgICAgICAgICBpY29uID0gdGhpcy5fb3B0aW9ucy5pY29ucy5kYXRlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlID0gdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3RUaW1lO1xuICAgICAgICAgICAgICAgICAgICBpY29uID0gdGhpcy5fb3B0aW9ucy5pY29ucy50aW1lO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByb3cucHVzaCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICAgICAgICAgICAnZGF0YS1hY3Rpb24nOiAndG9nZ2xlUGlja2VyJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGl0bGVcbiAgICAgICAgICAgICAgICB9KS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3MoaWNvbikpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbGVhcikge1xuICAgICAgICAgICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICdkYXRhLWFjdGlvbic6ICdjbGVhcicsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuY2xlYXJcbiAgICAgICAgICAgICAgICB9KS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy5jbGVhcikpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbG9zZSkge1xuICAgICAgICAgICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICdkYXRhLWFjdGlvbic6ICdjbG9zZScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuY2xvc2VcbiAgICAgICAgICAgICAgICB9KS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy5jbG9zZSkpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcm93Lmxlbmd0aCA9PT0gMCA/ICcnIDogJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKS5hcHBlbmQoJCgnPHRib2R5PicpLmFwcGVuZCgkKCc8dHI+JykuYXBwZW5kKHJvdykpKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2dldFRlbXBsYXRlID0gZnVuY3Rpb24gX2dldFRlbXBsYXRlKCkge1xuICAgICAgICAgICAgdmFyIHRlbXBsYXRlID0gJCgnPGRpdj4nKS5hZGRDbGFzcygnYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyLXdpZGdldCBkcm9wZG93bi1tZW51JyksXG4gICAgICAgICAgICAgICAgZGF0ZVZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyJykuYXBwZW5kKHRoaXMuX2dldERhdGVQaWNrZXJUZW1wbGF0ZSgpKSxcbiAgICAgICAgICAgICAgICB0aW1lVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXInKS5hcHBlbmQodGhpcy5fZ2V0VGltZVBpY2tlclRlbXBsYXRlKCkpLFxuICAgICAgICAgICAgICAgIGNvbnRlbnQgPSAkKCc8dWw+JykuYWRkQ2xhc3MoJ2xpc3QtdW5zdHlsZWQnKSxcbiAgICAgICAgICAgICAgICB0b29sYmFyID0gJCgnPGxpPicpLmFkZENsYXNzKCdwaWNrZXItc3dpdGNoJyArICh0aGlzLl9vcHRpb25zLmNvbGxhcHNlID8gJyBhY2NvcmRpb24tdG9nZ2xlJyA6ICcnKSkuYXBwZW5kKHRoaXMuX2dldFRvb2xiYXIoKSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlLnJlbW92ZUNsYXNzKCdkcm9wZG93bi1tZW51Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnVzZTI0SG91cnMpIHtcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5hZGRDbGFzcygndXNldHdlbnR5Zm91cicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgncycpICYmICF0aGlzLnVzZTI0SG91cnMpIHtcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5hZGRDbGFzcygnd2lkZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZSAmJiB0aGlzLl9oYXNEYXRlKCkgJiYgdGhpcy5faGFzVGltZSgpKSB7XG4gICAgICAgICAgICAgICAgdGVtcGxhdGUuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItc2JzJyk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGVtcGxhdGUuYXBwZW5kKHRvb2xiYXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5hcHBlbmQoJCgnPGRpdj4nKS5hZGRDbGFzcygncm93JykuYXBwZW5kKGRhdGVWaWV3LmFkZENsYXNzKCdjb2wtbWQtNicpKS5hcHBlbmQodGltZVZpZXcuYWRkQ2xhc3MoJ2NvbC1tZC02JykpKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAnYm90dG9tJyB8fCB0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICdkZWZhdWx0Jykge1xuICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5hcHBlbmQodG9vbGJhcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0ZW1wbGF0ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZCh0b29sYmFyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNEYXRlKCkpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZCgkKCc8bGk+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5jb2xsYXBzZSAmJiB0aGlzLl9oYXNUaW1lKCkgPyAnY29sbGFwc2UnIDogJycpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgJiYgdGhpcy5faGFzVGltZSgpICYmIHRoaXMuX29wdGlvbnMudmlld01vZGUgPT09ICd0aW1lcycgPyAnJyA6ICdzaG93JykuYXBwZW5kKGRhdGVWaWV3KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAnZGVmYXVsdCcpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZCh0b29sYmFyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZCgkKCc8bGk+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5jb2xsYXBzZSAmJiB0aGlzLl9oYXNEYXRlKCkgPyAnY29sbGFwc2UnIDogJycpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgJiYgdGhpcy5faGFzRGF0ZSgpICYmIHRoaXMuX29wdGlvbnMudmlld01vZGUgPT09ICd0aW1lcycgPyAnc2hvdycgOiAnJykuYXBwZW5kKHRpbWVWaWV3KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAnYm90dG9tJykge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKHRvb2xiYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlLmFwcGVuZChjb250ZW50KTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX3BsYWNlID0gZnVuY3Rpb24gX3BsYWNlKGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gZSAmJiBlLmRhdGEgJiYgZS5kYXRhLnBpY2tlciB8fCB0aGlzLFxuICAgICAgICAgICAgICAgIHZlcnRpY2FsID0gc2VsZi5fb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCxcbiAgICAgICAgICAgICAgICBob3Jpem9udGFsID0gc2VsZi5fb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsLFxuICAgICAgICAgICAgICAgIHBhcmVudCA9IHZvaWQgMDtcbiAgICAgICAgICAgIHZhciBwb3NpdGlvbiA9IChzZWxmLmNvbXBvbmVudCAmJiBzZWxmLmNvbXBvbmVudC5sZW5ndGggPyBzZWxmLmNvbXBvbmVudCA6IHNlbGYuX2VsZW1lbnQpLnBvc2l0aW9uKCksXG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gKHNlbGYuY29tcG9uZW50ICYmIHNlbGYuY29tcG9uZW50Lmxlbmd0aCA/IHNlbGYuY29tcG9uZW50IDogc2VsZi5fZWxlbWVudCkub2Zmc2V0KCk7XG4gICAgICAgICAgICBpZiAoc2VsZi5fb3B0aW9ucy53aWRnZXRQYXJlbnQpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBzZWxmLl9vcHRpb25zLndpZGdldFBhcmVudC5hcHBlbmQoc2VsZi53aWRnZXQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzZWxmLl9lbGVtZW50LmlzKCdpbnB1dCcpKSB7XG4gICAgICAgICAgICAgICAgcGFyZW50ID0gc2VsZi5fZWxlbWVudC5hZnRlcihzZWxmLndpZGdldCkucGFyZW50KCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHNlbGYuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgcGFyZW50ID0gc2VsZi5fZWxlbWVudC5hcHBlbmQoc2VsZi53aWRnZXQpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGFyZW50ID0gc2VsZi5fZWxlbWVudDtcbiAgICAgICAgICAgICAgICBzZWxmLl9lbGVtZW50LmNoaWxkcmVuKCkuZmlyc3QoKS5hZnRlcihzZWxmLndpZGdldCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRvcCBhbmQgYm90dG9tIGxvZ2ljXG4gICAgICAgICAgICBpZiAodmVydGljYWwgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVmFsaWRhdGVUeXBlc1xuICAgICAgICAgICAgICAgIGlmIChvZmZzZXQudG9wICsgc2VsZi53aWRnZXQuaGVpZ2h0KCkgKiAxLjUgPj0gJCh3aW5kb3cpLmhlaWdodCgpICsgJCh3aW5kb3cpLnNjcm9sbFRvcCgpICYmIHNlbGYud2lkZ2V0LmhlaWdodCgpICsgc2VsZi5fZWxlbWVudC5vdXRlckhlaWdodCgpIDwgb2Zmc2V0LnRvcCkge1xuICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbCA9ICd0b3AnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZlcnRpY2FsID0gJ2JvdHRvbSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMZWZ0IGFuZCByaWdodCBsb2dpY1xuICAgICAgICAgICAgaWYgKGhvcml6b250YWwgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgICAgIGlmIChwYXJlbnQud2lkdGgoKSA8IG9mZnNldC5sZWZ0ICsgc2VsZi53aWRnZXQub3V0ZXJXaWR0aCgpIC8gMiAmJiBvZmZzZXQubGVmdCArIHNlbGYud2lkZ2V0Lm91dGVyV2lkdGgoKSA+ICQod2luZG93KS53aWR0aCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGhvcml6b250YWwgPSAncmlnaHQnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGhvcml6b250YWwgPSAnbGVmdCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodmVydGljYWwgPT09ICd0b3AnKSB7XG4gICAgICAgICAgICAgICAgc2VsZi53aWRnZXQuYWRkQ2xhc3MoJ3RvcCcpLnJlbW92ZUNsYXNzKCdib3R0b20nKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi53aWRnZXQuYWRkQ2xhc3MoJ2JvdHRvbScpLnJlbW92ZUNsYXNzKCd0b3AnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGhvcml6b250YWwgPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgICBzZWxmLndpZGdldC5hZGRDbGFzcygnZmxvYXQtcmlnaHQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi53aWRnZXQucmVtb3ZlQ2xhc3MoJ2Zsb2F0LXJpZ2h0Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGZpbmQgdGhlIGZpcnN0IHBhcmVudCBlbGVtZW50IHRoYXQgaGFzIGEgcmVsYXRpdmUgY3NzIHBvc2l0aW9uaW5nXG4gICAgICAgICAgICBpZiAocGFyZW50LmNzcygncG9zaXRpb24nKSAhPT0gJ3JlbGF0aXZlJykge1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnRzKCkuZmlsdGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQodGhpcykuY3NzKCdwb3NpdGlvbicpID09PSAncmVsYXRpdmUnO1xuICAgICAgICAgICAgICAgIH0pLmZpcnN0KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwYXJlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkYXRldGltZXBpY2tlciBjb21wb25lbnQgc2hvdWxkIGJlIHBsYWNlZCB3aXRoaW4gYSByZWxhdGl2ZSBwb3NpdGlvbmVkIGNvbnRhaW5lcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzZWxmLndpZGdldC5jc3Moe1xuICAgICAgICAgICAgICAgIHRvcDogdmVydGljYWwgPT09ICd0b3AnID8gJ2F1dG8nIDogcG9zaXRpb24udG9wICsgc2VsZi5fZWxlbWVudC5vdXRlckhlaWdodCgpICsgJ3B4JyxcbiAgICAgICAgICAgICAgICBib3R0b206IHZlcnRpY2FsID09PSAndG9wJyA/IHBhcmVudC5vdXRlckhlaWdodCgpIC0gKHBhcmVudCA9PT0gc2VsZi5fZWxlbWVudCA/IDAgOiBwb3NpdGlvbi50b3ApICsgJ3B4JyA6ICdhdXRvJyxcbiAgICAgICAgICAgICAgICBsZWZ0OiBob3Jpem9udGFsID09PSAnbGVmdCcgPyAocGFyZW50ID09PSBzZWxmLl9lbGVtZW50ID8gMCA6IHBvc2l0aW9uLmxlZnQpICsgJ3B4JyA6ICdhdXRvJyxcbiAgICAgICAgICAgICAgICByaWdodDogaG9yaXpvbnRhbCA9PT0gJ2xlZnQnID8gJ2F1dG8nIDogcGFyZW50Lm91dGVyV2lkdGgoKSAtIHNlbGYuX2VsZW1lbnQub3V0ZXJXaWR0aCgpIC0gKHBhcmVudCA9PT0gc2VsZi5fZWxlbWVudCA/IDAgOiBwb3NpdGlvbi5sZWZ0KSArICdweCdcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZmlsbERvdyA9IGZ1bmN0aW9uIF9maWxsRG93KCkge1xuICAgICAgICAgICAgdmFyIHJvdyA9ICQoJzx0cj4nKSxcbiAgICAgICAgICAgICAgICBjdXJyZW50RGF0ZSA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuc3RhcnRPZigndycpLnN0YXJ0T2YoJ2QnKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHJvdy5hcHBlbmQoJCgnPHRoPicpLmFkZENsYXNzKCdjdycpLnRleHQoJyMnKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHdoaWxlIChjdXJyZW50RGF0ZS5pc0JlZm9yZSh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLmVuZE9mKCd3JykpKSB7XG4gICAgICAgICAgICAgICAgcm93LmFwcGVuZCgkKCc8dGg+JykuYWRkQ2xhc3MoJ2RvdycpLnRleHQoY3VycmVudERhdGUuZm9ybWF0KCdkZCcpKSk7XG4gICAgICAgICAgICAgICAgY3VycmVudERhdGUuYWRkKDEsICdkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci1kYXlzIHRoZWFkJykuYXBwZW5kKHJvdyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsTW9udGhzID0gZnVuY3Rpb24gX2ZpbGxNb250aHMoKSB7XG4gICAgICAgICAgICB2YXIgc3BhbnMgPSBbXSxcbiAgICAgICAgICAgICAgICBtb250aHNTaG9ydCA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuc3RhcnRPZigneScpLnN0YXJ0T2YoJ2QnKTtcbiAgICAgICAgICAgIHdoaWxlIChtb250aHNTaG9ydC5pc1NhbWUodGhpcy5fdmlld0RhdGUsICd5JykpIHtcbiAgICAgICAgICAgICAgICBzcGFucy5wdXNoKCQoJzxzcGFuPicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3NlbGVjdE1vbnRoJykuYWRkQ2xhc3MoJ21vbnRoJykudGV4dChtb250aHNTaG9ydC5mb3JtYXQoJ01NTScpKSk7XG4gICAgICAgICAgICAgICAgbW9udGhzU2hvcnQuYWRkKDEsICdNJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci1tb250aHMgdGQnKS5lbXB0eSgpLmFwcGVuZChzcGFucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl91cGRhdGVNb250aHMgPSBmdW5jdGlvbiBfdXBkYXRlTW9udGhzKCkge1xuICAgICAgICAgICAgdmFyIG1vbnRoc1ZpZXcgPSB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci1tb250aHMnKSxcbiAgICAgICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyID0gbW9udGhzVmlldy5maW5kKCd0aCcpLFxuICAgICAgICAgICAgICAgIG1vbnRocyA9IG1vbnRoc1ZpZXcuZmluZCgndGJvZHknKS5maW5kKCdzcGFuJyksXG4gICAgICAgICAgICAgICAgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMCkuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5wcmV2WWVhcik7XG4gICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyLmVxKDEpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3RZZWFyKTtcbiAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMikuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5uZXh0WWVhcik7XG5cbiAgICAgICAgICAgIG1vbnRoc1ZpZXcuZmluZCgnLmRpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZCh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN1YnRyYWN0KDEsICd5JyksICd5JykpIHtcbiAgICAgICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyLmVxKDApLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyLmVxKDEpLnRleHQodGhpcy5fdmlld0RhdGUueWVhcigpKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuYWRkKDEsICd5JyksICd5JykpIHtcbiAgICAgICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyLmVxKDIpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBtb250aHMucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICAgICAgaWYgKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuaXNTYW1lKHRoaXMuX3ZpZXdEYXRlLCAneScpICYmICF0aGlzLnVuc2V0KSB7XG4gICAgICAgICAgICAgICAgbW9udGhzLmVxKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkubW9udGgoKSkuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBtb250aHMuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXNlbGYuX2lzVmFsaWQoc2VsZi5fdmlld0RhdGUuY2xvbmUoKS5tb250aChpbmRleCksICdNJykpIHtcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2dldFN0YXJ0RW5kWWVhciA9IGZ1bmN0aW9uIF9nZXRTdGFydEVuZFllYXIoZmFjdG9yLCB5ZWFyKSB7XG4gICAgICAgICAgICB2YXIgc3RlcCA9IGZhY3RvciAvIDEwLFxuICAgICAgICAgICAgICAgIHN0YXJ0WWVhciA9IE1hdGguZmxvb3IoeWVhciAvIGZhY3RvcikgKiBmYWN0b3IsXG4gICAgICAgICAgICAgICAgZW5kWWVhciA9IHN0YXJ0WWVhciArIHN0ZXAgKiA5LFxuICAgICAgICAgICAgICAgIGZvY3VzVmFsdWUgPSBNYXRoLmZsb29yKHllYXIgLyBzdGVwKSAqIHN0ZXA7XG4gICAgICAgICAgICByZXR1cm4gW3N0YXJ0WWVhciwgZW5kWWVhciwgZm9jdXNWYWx1ZV07XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl91cGRhdGVZZWFycyA9IGZ1bmN0aW9uIF91cGRhdGVZZWFycygpIHtcbiAgICAgICAgICAgIHZhciB5ZWFyc1ZpZXcgPSB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci15ZWFycycpLFxuICAgICAgICAgICAgICAgIHllYXJzVmlld0hlYWRlciA9IHllYXJzVmlldy5maW5kKCd0aCcpLFxuICAgICAgICAgICAgICAgIHllYXJDYXBzID0gdGhpcy5fZ2V0U3RhcnRFbmRZZWFyKDEwLCB0aGlzLl92aWV3RGF0ZS55ZWFyKCkpLFxuICAgICAgICAgICAgICAgIHN0YXJ0WWVhciA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkueWVhcih5ZWFyQ2Fwc1swXSksXG4gICAgICAgICAgICAgICAgZW5kWWVhciA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkueWVhcih5ZWFyQ2Fwc1sxXSk7XG4gICAgICAgICAgICB2YXIgaHRtbCA9ICcnO1xuXG4gICAgICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMCkuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5wcmV2RGVjYWRlKTtcbiAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgxKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0RGVjYWRlKTtcbiAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHREZWNhZGUpO1xuXG4gICAgICAgICAgICB5ZWFyc1ZpZXcuZmluZCgnLmRpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgdGhpcy5fb3B0aW9ucy5taW5EYXRlLmlzQWZ0ZXIoc3RhcnRZZWFyLCAneScpKSB7XG4gICAgICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDApLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMSkudGV4dChzdGFydFllYXIueWVhcigpICsgJy0nICsgZW5kWWVhci55ZWFyKCkpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHRoaXMuX29wdGlvbnMubWF4RGF0ZS5pc0JlZm9yZShlbmRZZWFyLCAneScpKSB7XG4gICAgICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDIpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBodG1sICs9ICc8c3BhbiBkYXRhLWFjdGlvbj1cInNlbGVjdFllYXJcIiBjbGFzcz1cInllYXIgb2xkJyArICghdGhpcy5faXNWYWxpZChzdGFydFllYXIsICd5JykgPyAnIGRpc2FibGVkJyA6ICcnKSArICdcIj4nICsgKHN0YXJ0WWVhci55ZWFyKCkgLSAxKSArICc8L3NwYW4+JztcbiAgICAgICAgICAgIHdoaWxlICghc3RhcnRZZWFyLmlzQWZ0ZXIoZW5kWWVhciwgJ3knKSkge1xuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0WWVhclwiIGNsYXNzPVwieWVhcicgKyAoc3RhcnRZZWFyLmlzU2FtZSh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLCAneScpICYmICF0aGlzLnVuc2V0ID8gJyBhY3RpdmUnIDogJycpICsgKCF0aGlzLl9pc1ZhbGlkKHN0YXJ0WWVhciwgJ3knKSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiPicgKyBzdGFydFllYXIueWVhcigpICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgICAgIHN0YXJ0WWVhci5hZGQoMSwgJ3knKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0WWVhclwiIGNsYXNzPVwieWVhciBvbGQnICsgKCF0aGlzLl9pc1ZhbGlkKHN0YXJ0WWVhciwgJ3knKSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiPicgKyBzdGFydFllYXIueWVhcigpICsgJzwvc3Bhbj4nO1xuXG4gICAgICAgICAgICB5ZWFyc1ZpZXcuZmluZCgndGQnKS5odG1sKGh0bWwpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fdXBkYXRlRGVjYWRlcyA9IGZ1bmN0aW9uIF91cGRhdGVEZWNhZGVzKCkge1xuICAgICAgICAgICAgdmFyIGRlY2FkZXNWaWV3ID0gdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItZGVjYWRlcycpLFxuICAgICAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyID0gZGVjYWRlc1ZpZXcuZmluZCgndGgnKSxcbiAgICAgICAgICAgICAgICB5ZWFyQ2FwcyA9IHRoaXMuX2dldFN0YXJ0RW5kWWVhcigxMDAsIHRoaXMuX3ZpZXdEYXRlLnllYXIoKSksXG4gICAgICAgICAgICAgICAgc3RhcnREZWNhZGUgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnllYXIoeWVhckNhcHNbMF0pLFxuICAgICAgICAgICAgICAgIGVuZERlY2FkZSA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkueWVhcih5ZWFyQ2Fwc1sxXSk7XG4gICAgICAgICAgICB2YXIgbWluRGF0ZURlY2FkZSA9IGZhbHNlLFxuICAgICAgICAgICAgICAgIG1heERhdGVEZWNhZGUgPSBmYWxzZSxcbiAgICAgICAgICAgICAgICBlbmREZWNhZGVZZWFyID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGh0bWwgPSAnJztcblxuICAgICAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMCkuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5wcmV2Q2VudHVyeSk7XG4gICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHRDZW50dXJ5KTtcblxuICAgICAgICAgICAgZGVjYWRlc1ZpZXcuZmluZCgnLmRpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cbiAgICAgICAgICAgIGlmIChzdGFydERlY2FkZS55ZWFyKCkgPT09IDAgfHwgdGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHRoaXMuX29wdGlvbnMubWluRGF0ZS5pc0FmdGVyKHN0YXJ0RGVjYWRlLCAneScpKSB7XG4gICAgICAgICAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMCkuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyLmVxKDEpLnRleHQoc3RhcnREZWNhZGUueWVhcigpICsgJy0nICsgZW5kRGVjYWRlLnllYXIoKSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgdGhpcy5fb3B0aW9ucy5tYXhEYXRlLmlzQmVmb3JlKGVuZERlY2FkZSwgJ3knKSkge1xuICAgICAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyLmVxKDIpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoc3RhcnREZWNhZGUueWVhcigpIC0gMTAgPCAwKSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4+Jm5ic3A7PC9zcGFuPic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0RGVjYWRlXCIgY2xhc3M9XCJkZWNhZGUgb2xkXCIgZGF0YS1zZWxlY3Rpb249XCInICsgKHN0YXJ0RGVjYWRlLnllYXIoKSArIDYpICsgJ1wiPicgKyAoc3RhcnREZWNhZGUueWVhcigpIC0gMTApICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3aGlsZSAoIXN0YXJ0RGVjYWRlLmlzQWZ0ZXIoZW5kRGVjYWRlLCAneScpKSB7XG4gICAgICAgICAgICAgICAgZW5kRGVjYWRlWWVhciA9IHN0YXJ0RGVjYWRlLnllYXIoKSArIDExO1xuICAgICAgICAgICAgICAgIG1pbkRhdGVEZWNhZGUgPSB0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgdGhpcy5fb3B0aW9ucy5taW5EYXRlLmlzQWZ0ZXIoc3RhcnREZWNhZGUsICd5JykgJiYgdGhpcy5fb3B0aW9ucy5taW5EYXRlLnllYXIoKSA8PSBlbmREZWNhZGVZZWFyO1xuICAgICAgICAgICAgICAgIG1heERhdGVEZWNhZGUgPSB0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgdGhpcy5fb3B0aW9ucy5tYXhEYXRlLmlzQWZ0ZXIoc3RhcnREZWNhZGUsICd5JykgJiYgdGhpcy5fb3B0aW9ucy5tYXhEYXRlLnllYXIoKSA8PSBlbmREZWNhZGVZZWFyO1xuICAgICAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0RGVjYWRlXCIgY2xhc3M9XCJkZWNhZGUnICsgKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuaXNBZnRlcihzdGFydERlY2FkZSkgJiYgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS55ZWFyKCkgPD0gZW5kRGVjYWRlWWVhciA/ICcgYWN0aXZlJyA6ICcnKSArICghdGhpcy5faXNWYWxpZChzdGFydERlY2FkZSwgJ3knKSAmJiAhbWluRGF0ZURlY2FkZSAmJiAhbWF4RGF0ZURlY2FkZSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiIGRhdGEtc2VsZWN0aW9uPVwiJyArIChzdGFydERlY2FkZS55ZWFyKCkgKyA2KSArICdcIj4nICsgc3RhcnREZWNhZGUueWVhcigpICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgICAgIHN0YXJ0RGVjYWRlLmFkZCgxMCwgJ3knKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0RGVjYWRlXCIgY2xhc3M9XCJkZWNhZGUgb2xkXCIgZGF0YS1zZWxlY3Rpb249XCInICsgKHN0YXJ0RGVjYWRlLnllYXIoKSArIDYpICsgJ1wiPicgKyBzdGFydERlY2FkZS55ZWFyKCkgKyAnPC9zcGFuPic7XG5cbiAgICAgICAgICAgIGRlY2FkZXNWaWV3LmZpbmQoJ3RkJykuaHRtbChodG1sKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2ZpbGxEYXRlID0gZnVuY3Rpb24gX2ZpbGxEYXRlKCkge1xuICAgICAgICAgICAgdmFyIGRheXNWaWV3ID0gdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItZGF5cycpLFxuICAgICAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyID0gZGF5c1ZpZXcuZmluZCgndGgnKSxcbiAgICAgICAgICAgICAgICBodG1sID0gW107XG4gICAgICAgICAgICB2YXIgY3VycmVudERhdGUgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgcm93ID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGNsc05hbWUgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgaSA9IHZvaWQgMDtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNEYXRlKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDApLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMucHJldk1vbnRoKTtcbiAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDEpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3RNb250aCk7XG4gICAgICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHRNb250aCk7XG5cbiAgICAgICAgICAgIGRheXNWaWV3LmZpbmQoJy5kaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMSkudGV4dCh0aGlzLl92aWV3RGF0ZS5mb3JtYXQodGhpcy5fb3B0aW9ucy5kYXlWaWV3SGVhZGVyRm9ybWF0KSk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZCh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN1YnRyYWN0KDEsICdNJyksICdNJykpIHtcbiAgICAgICAgICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZCh0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLmFkZCgxLCAnTScpLCAnTScpKSB7XG4gICAgICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGN1cnJlbnREYXRlID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdNJykuc3RhcnRPZigndycpLnN0YXJ0T2YoJ2QnKTtcblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDQyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAvL2Fsd2F5cyBkaXNwbGF5IDQyIGRheXMgKHNob3VsZCBzaG93IDYgd2Vla3MpXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLndlZWtkYXkoKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSAkKCc8dHI+Jyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5hcHBlbmQoJzx0ZCBjbGFzcz1cImN3XCI+JyArIGN1cnJlbnREYXRlLndlZWsoKSArICc8L3RkPicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChyb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjbHNOYW1lID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmlzQmVmb3JlKHRoaXMuX3ZpZXdEYXRlLCAnTScpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsc05hbWUgKz0gJyBvbGQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuaXNBZnRlcih0aGlzLl92aWV3RGF0ZSwgJ00nKSkge1xuICAgICAgICAgICAgICAgICAgICBjbHNOYW1lICs9ICcgbmV3JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5fZGF0ZXNGb3JtYXR0ZWQuaW5kZXhPZihjdXJyZW50RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc1NhbWUodGhpcy5fZGF0ZXNGb3JtYXR0ZWRbaW5kZXhdLCAnZCcpICYmICF0aGlzLnVuc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xzTmFtZSArPSAnIGFjdGl2ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuaXNTYW1lKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCksICdkJykgJiYgIXRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsc05hbWUgKz0gJyBhY3RpdmUnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZChjdXJyZW50RGF0ZSwgJ2QnKSkge1xuICAgICAgICAgICAgICAgICAgICBjbHNOYW1lICs9ICcgZGlzYWJsZWQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuaXNTYW1lKHRoaXMuZ2V0TW9tZW50KCksICdkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xzTmFtZSArPSAnIHRvZGF5JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmRheSgpID09PSAwIHx8IGN1cnJlbnREYXRlLmRheSgpID09PSA2KSB7XG4gICAgICAgICAgICAgICAgICAgIGNsc05hbWUgKz0gJyB3ZWVrZW5kJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGRhdGEtYWN0aW9uPVwic2VsZWN0RGF5XCIgZGF0YS1kYXk9XCInICsgY3VycmVudERhdGUuZm9ybWF0KCdMJykgKyAnXCIgY2xhc3M9XCJkYXknICsgY2xzTmFtZSArICdcIj4nICsgY3VycmVudERhdGUuZGF0ZSgpICsgJzwvdGQ+Jyk7XG4gICAgICAgICAgICAgICAgY3VycmVudERhdGUuYWRkKDEsICdkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRheXNWaWV3LmZpbmQoJ3Rib2R5JykuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG5cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZU1vbnRocygpO1xuXG4gICAgICAgICAgICB0aGlzLl91cGRhdGVZZWFycygpO1xuXG4gICAgICAgICAgICB0aGlzLl91cGRhdGVEZWNhZGVzKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsSG91cnMgPSBmdW5jdGlvbiBfZmlsbEhvdXJzKCkge1xuICAgICAgICAgICAgdmFyIHRhYmxlID0gdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItaG91cnMgdGFibGUnKSxcbiAgICAgICAgICAgICAgICBjdXJyZW50SG91ciA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuc3RhcnRPZignZCcpLFxuICAgICAgICAgICAgICAgIGh0bWwgPSBbXTtcbiAgICAgICAgICAgIHZhciByb3cgPSAkKCc8dHI+Jyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl92aWV3RGF0ZS5ob3VyKCkgPiAxMSAmJiAhdGhpcy51c2UyNEhvdXJzKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEhvdXIuaG91cigxMik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudEhvdXIuaXNTYW1lKHRoaXMuX3ZpZXdEYXRlLCAnZCcpICYmICh0aGlzLnVzZTI0SG91cnMgfHwgdGhpcy5fdmlld0RhdGUuaG91cigpIDwgMTIgJiYgY3VycmVudEhvdXIuaG91cigpIDwgMTIgfHwgdGhpcy5fdmlld0RhdGUuaG91cigpID4gMTEpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRIb3VyLmhvdXIoKSAlIDQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xuICAgICAgICAgICAgICAgICAgICBodG1sLnB1c2gocm93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGRhdGEtYWN0aW9uPVwic2VsZWN0SG91clwiIGNsYXNzPVwiaG91cicgKyAoIXRoaXMuX2lzVmFsaWQoY3VycmVudEhvdXIsICdoJykgPyAnIGRpc2FibGVkJyA6ICcnKSArICdcIj4nICsgY3VycmVudEhvdXIuZm9ybWF0KHRoaXMudXNlMjRIb3VycyA/ICdISCcgOiAnaGgnKSArICc8L3RkPicpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRIb3VyLmFkZCgxLCAnaCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGFibGUuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsTWludXRlcyA9IGZ1bmN0aW9uIF9maWxsTWludXRlcygpIHtcbiAgICAgICAgICAgIHZhciB0YWJsZSA9IHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyLW1pbnV0ZXMgdGFibGUnKSxcbiAgICAgICAgICAgICAgICBjdXJyZW50TWludXRlID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdoJyksXG4gICAgICAgICAgICAgICAgaHRtbCA9IFtdLFxuICAgICAgICAgICAgICAgIHN0ZXAgPSB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nID09PSAxID8gNSA6IHRoaXMuX29wdGlvbnMuc3RlcHBpbmc7XG4gICAgICAgICAgICB2YXIgcm93ID0gJCgnPHRyPicpO1xuXG4gICAgICAgICAgICB3aGlsZSAodGhpcy5fdmlld0RhdGUuaXNTYW1lKGN1cnJlbnRNaW51dGUsICdoJykpIHtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudE1pbnV0ZS5taW51dGUoKSAlIChzdGVwICogNCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xuICAgICAgICAgICAgICAgICAgICBodG1sLnB1c2gocm93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGRhdGEtYWN0aW9uPVwic2VsZWN0TWludXRlXCIgY2xhc3M9XCJtaW51dGUnICsgKCF0aGlzLl9pc1ZhbGlkKGN1cnJlbnRNaW51dGUsICdtJykgPyAnIGRpc2FibGVkJyA6ICcnKSArICdcIj4nICsgY3VycmVudE1pbnV0ZS5mb3JtYXQoJ21tJykgKyAnPC90ZD4nKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50TWludXRlLmFkZChzdGVwLCAnbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGFibGUuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsU2Vjb25kcyA9IGZ1bmN0aW9uIF9maWxsU2Vjb25kcygpIHtcbiAgICAgICAgICAgIHZhciB0YWJsZSA9IHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyLXNlY29uZHMgdGFibGUnKSxcbiAgICAgICAgICAgICAgICBjdXJyZW50U2Vjb25kID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdtJyksXG4gICAgICAgICAgICAgICAgaHRtbCA9IFtdO1xuICAgICAgICAgICAgdmFyIHJvdyA9ICQoJzx0cj4nKTtcblxuICAgICAgICAgICAgd2hpbGUgKHRoaXMuX3ZpZXdEYXRlLmlzU2FtZShjdXJyZW50U2Vjb25kLCAnbScpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRTZWNvbmQuc2Vjb25kKCkgJSAyMCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSAkKCc8dHI+Jyk7XG4gICAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChyb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCc8dGQgZGF0YS1hY3Rpb249XCJzZWxlY3RTZWNvbmRcIiBjbGFzcz1cInNlY29uZCcgKyAoIXRoaXMuX2lzVmFsaWQoY3VycmVudFNlY29uZCwgJ3MnKSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiPicgKyBjdXJyZW50U2Vjb25kLmZvcm1hdCgnc3MnKSArICc8L3RkPicpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRTZWNvbmQuYWRkKDUsICdzJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRhYmxlLmVtcHR5KCkuYXBwZW5kKGh0bWwpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZmlsbFRpbWUgPSBmdW5jdGlvbiBfZmlsbFRpbWUoKSB7XG4gICAgICAgICAgICB2YXIgdG9nZ2xlID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIG5ld0RhdGUgPSB2b2lkIDA7XG4gICAgICAgICAgICB2YXIgdGltZUNvbXBvbmVudHMgPSB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciBzcGFuW2RhdGEtdGltZS1jb21wb25lbnRdJyk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy51c2UyNEhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdG9nZ2xlID0gdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgW2RhdGEtYWN0aW9uPXRvZ2dsZVBlcmlvZF0nKTtcbiAgICAgICAgICAgICAgICBuZXdEYXRlID0gdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5jbG9uZSgpLmFkZCh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLmhvdXJzKCkgPj0gMTIgPyAtMTIgOiAxMiwgJ2gnKTtcblxuICAgICAgICAgICAgICAgIHRvZ2dsZS50ZXh0KHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuZm9ybWF0KCdBJykpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQobmV3RGF0ZSwgJ2gnKSkge1xuICAgICAgICAgICAgICAgICAgICB0b2dnbGUucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdG9nZ2xlLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRpbWVDb21wb25lbnRzLmZpbHRlcignW2RhdGEtdGltZS1jb21wb25lbnQ9aG91cnNdJykudGV4dCh0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLmZvcm1hdCgnJyArICh0aGlzLnVzZTI0SG91cnMgPyAnSEgnIDogJ2hoJykpKTtcbiAgICAgICAgICAgIHRpbWVDb21wb25lbnRzLmZpbHRlcignW2RhdGEtdGltZS1jb21wb25lbnQ9bWludXRlc10nKS50ZXh0KHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuZm9ybWF0KCdtbScpKTtcbiAgICAgICAgICAgIHRpbWVDb21wb25lbnRzLmZpbHRlcignW2RhdGEtdGltZS1jb21wb25lbnQ9c2Vjb25kc10nKS50ZXh0KHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuZm9ybWF0KCdzcycpKTtcblxuICAgICAgICAgICAgdGhpcy5fZmlsbEhvdXJzKCk7XG4gICAgICAgICAgICB0aGlzLl9maWxsTWludXRlcygpO1xuICAgICAgICAgICAgdGhpcy5fZmlsbFNlY29uZHMoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2RvQWN0aW9uID0gZnVuY3Rpb24gX2RvQWN0aW9uKGUsIGFjdGlvbikge1xuICAgICAgICAgICAgdmFyIGxhc3RQaWNrZWQgPSB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpO1xuICAgICAgICAgICAgaWYgKCQoZS5jdXJyZW50VGFyZ2V0KS5pcygnLmRpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhY3Rpb24gPSBhY3Rpb24gfHwgJChlLmN1cnJlbnRUYXJnZXQpLmRhdGEoJ2FjdGlvbicpO1xuICAgICAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjYXNlICduZXh0JzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5hdkZuYyA9IERhdGVUaW1lUGlja2VyLkRhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uTkFWX0ZVTkNUSU9OO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUuYWRkKERhdGVUaW1lUGlja2VyLkRhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uTkFWX1NURVAsIG5hdkZuYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZShuYXZGbmMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdwcmV2aW91cyc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmF2Rm5jID0gRGF0ZVRpbWVQaWNrZXIuRGF0ZVBpY2tlck1vZGVzW3RoaXMuY3VycmVudFZpZXdNb2RlXS5OQVZfRlVOQ1RJT047XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5zdWJ0cmFjdChEYXRlVGltZVBpY2tlci5EYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLk5BVl9TVEVQLCBfbmF2Rm5jKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpbGxEYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3VXBkYXRlKF9uYXZGbmMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdwaWNrZXJTd2l0Y2gnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgxKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc2VsZWN0TW9udGgnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbW9udGggPSAkKGUudGFyZ2V0KS5jbG9zZXN0KCd0Ym9keScpLmZpbmQoJ3NwYW4nKS5pbmRleCgkKGUudGFyZ2V0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5tb250aChtb250aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50Vmlld01vZGUgPT09IHRoaXMuTWluVmlld01vZGVOdW1iZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkueWVhcih0aGlzLl92aWV3RGF0ZS55ZWFyKCkpLm1vbnRoKHRoaXMuX3ZpZXdEYXRlLm1vbnRoKCkpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgtMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZmlsbERhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoJ00nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnc2VsZWN0WWVhcic6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gcGFyc2VJbnQoJChlLnRhcmdldCkudGV4dCgpLCAxMCkgfHwgMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlLnllYXIoeWVhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50Vmlld01vZGUgPT09IHRoaXMuTWluVmlld01vZGVOdW1iZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkueWVhcih0aGlzLl92aWV3RGF0ZS55ZWFyKCkpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgtMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZmlsbERhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoJ1lZWVknKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnc2VsZWN0RGVjYWRlJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF95ZWFyID0gcGFyc2VJbnQoJChlLnRhcmdldCkuZGF0YSgnc2VsZWN0aW9uJyksIDEwKSB8fCAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUueWVhcihfeWVhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50Vmlld01vZGUgPT09IHRoaXMuTWluVmlld01vZGVOdW1iZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkueWVhcih0aGlzLl92aWV3RGF0ZS55ZWFyKCkpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgtMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZmlsbERhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoJ1lZWVknKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnc2VsZWN0RGF5JzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRheSA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJChlLnRhcmdldCkuaXMoJy5vbGQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheS5zdWJ0cmFjdCgxLCAnTScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCQoZS50YXJnZXQpLmlzKCcubmV3JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXkuYWRkKDEsICdNJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3REYXRlID0gZGF5LmRhdGUocGFyc2VJbnQoJChlLnRhcmdldCkudGV4dCgpLCAxMCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSB0aGlzLl9kYXRlc0Zvcm1hdHRlZC5pbmRleE9mKHNlbGVjdERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobnVsbCwgaW5kZXgpOyAvL2Rlc2VsZWN0IG11bHRpZGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHNlbGVjdERhdGUsIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoc2VsZWN0RGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9oYXNUaW1lKCkgJiYgIXRoaXMuX29wdGlvbnMua2VlcE9wZW4gJiYgIXRoaXMuX29wdGlvbnMuaW5saW5lICYmICF0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ2luY3JlbWVudEhvdXJzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0RhdGUgPSBsYXN0UGlja2VkLmNsb25lKCkuYWRkKDEsICdoJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZChuZXdEYXRlLCAnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobmV3RGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnaW5jcmVtZW50TWludXRlcyc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmV3RGF0ZSA9IGxhc3RQaWNrZWQuY2xvbmUoKS5hZGQodGhpcy5fb3B0aW9ucy5zdGVwcGluZywgJ20nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKF9uZXdEYXRlLCAnbScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGUsIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ2luY3JlbWVudFNlY29uZHMnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgX25ld0RhdGUyID0gbGFzdFBpY2tlZC5jbG9uZSgpLmFkZCgxLCAncycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGUyLCAncycpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGUyLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdkZWNyZW1lbnRIb3Vycyc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmV3RGF0ZTMgPSBsYXN0UGlja2VkLmNsb25lKCkuc3VidHJhY3QoMSwgJ2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKF9uZXdEYXRlMywgJ2gnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKF9uZXdEYXRlMywgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnZGVjcmVtZW50TWludXRlcyc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmV3RGF0ZTQgPSBsYXN0UGlja2VkLmNsb25lKCkuc3VidHJhY3QodGhpcy5fb3B0aW9ucy5zdGVwcGluZywgJ20nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKF9uZXdEYXRlNCwgJ20nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKF9uZXdEYXRlNCwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnZGVjcmVtZW50U2Vjb25kcyc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmV3RGF0ZTUgPSBsYXN0UGlja2VkLmNsb25lKCkuc3VidHJhY3QoMSwgJ3MnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKF9uZXdEYXRlNSwgJ3MnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKF9uZXdEYXRlNSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAndG9nZ2xlUGVyaW9kJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobGFzdFBpY2tlZC5jbG9uZSgpLmFkZChsYXN0UGlja2VkLmhvdXJzKCkgPj0gMTIgPyAtMTIgOiAxMiwgJ2gnKSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAndG9nZ2xlUGlja2VyJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyICR0aGlzID0gJChlLnRhcmdldCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGxpbmsgPSAkdGhpcy5jbG9zZXN0KCdhJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBhcmVudCA9ICR0aGlzLmNsb3Nlc3QoJ3VsJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWQgPSAkcGFyZW50LmZpbmQoJy5zaG93JyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VkID0gJHBhcmVudC5maW5kKCcuY29sbGFwc2U6bm90KC5zaG93KScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzcGFuID0gJHRoaXMuaXMoJ3NwYW4nKSA/ICR0aGlzIDogJHRoaXMuZmluZCgnc3BhbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNvbGxhcHNlRGF0YSA9IHZvaWQgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV4cGFuZGVkICYmIGV4cGFuZGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlRGF0YSA9IGV4cGFuZGVkLmRhdGEoJ2NvbGxhcHNlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbGxhcHNlRGF0YSAmJiBjb2xsYXBzZURhdGEudHJhbnNpdGlvbmluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV4cGFuZGVkLmNvbGxhcHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGNvbGxhcHNlIHBsdWdpbiBpcyBhdmFpbGFibGUgdGhyb3VnaCBib290c3RyYXAuanMgdGhlbiB1c2UgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWQuY29sbGFwc2UoJ2hpZGUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VkLmNvbGxhcHNlKCdzaG93Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGp1c3QgdG9nZ2xlIGluIGNsYXNzIG9uIHRoZSB0d28gdmlld3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWQucmVtb3ZlQ2xhc3MoJ3Nob3cnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VkLmFkZENsYXNzKCdzaG93Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzcGFuLnRvZ2dsZUNsYXNzKHRoaXMuX29wdGlvbnMuaWNvbnMudGltZSArICcgJyArIHRoaXMuX29wdGlvbnMuaWNvbnMuZGF0ZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJHNwYW4uaGFzQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy5kYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbGluay5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0RGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGxpbmsuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnNlbGVjdFRpbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzaG93UGlja2VyJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgPiBkaXY6bm90KC50aW1lcGlja2VyLXBpY2tlciknKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLXBpY2tlcicpLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc2hvd0hvdXJzJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1ob3VycycpLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc2hvd01pbnV0ZXMnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1waWNrZXInKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLW1pbnV0ZXMnKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3Nob3dTZWNvbmRzJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1zZWNvbmRzJykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3RIb3VyJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhvdXIgPSBwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnVzZTI0SG91cnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdFBpY2tlZC5ob3VycygpID49IDEyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChob3VyICE9PSAxMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91ciArPSAxMjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkuaG91cnMoaG91ciksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2lzRW5hYmxlZCgnYScpICYmICF0aGlzLl9pc0VuYWJsZWQoJ20nKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9BY3Rpb24oZSwgJ3Nob3dQaWNrZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnc2VsZWN0TWludXRlJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobGFzdFBpY2tlZC5jbG9uZSgpLm1pbnV0ZXMocGFyc2VJbnQoJChlLnRhcmdldCkudGV4dCgpLCAxMCkpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2lzRW5hYmxlZCgnYScpICYmICF0aGlzLl9pc0VuYWJsZWQoJ3MnKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9BY3Rpb24oZSwgJ3Nob3dQaWNrZXInKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3RTZWNvbmQnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkuc2Vjb25kcyhwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5faXNFbmFibGVkKCdhJykgJiYgIXRoaXMuX29wdGlvbnMua2VlcE9wZW4gJiYgIXRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RvQWN0aW9uKGUsICdzaG93UGlja2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xlYXInOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Nsb3NlJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3RvZGF5JzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRvZGF5c0RhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQodG9kYXlzRGF0ZSwgJ2QnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRvZGF5c0RhdGUsIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vcHVibGljXG5cblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uIGhpZGUoKSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElnbm9yZSBldmVudCBpZiBpbiB0aGUgbWlkZGxlIG9mIGEgcGlja2VyIHRyYW5zaXRpb25cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5jb2xsYXBzZScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBjb2xsYXBzZURhdGEgPSAkKHRoaXMpLmRhdGEoJ2NvbGxhcHNlJyk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbGxhcHNlRGF0YSAmJiBjb2xsYXBzZURhdGEudHJhbnNpdGlvbmluZykge1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHRyYW5zaXRpb25pbmcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5jb21wb25lbnQgJiYgdGhpcy5jb21wb25lbnQuaGFzQ2xhc3MoJ2J0bicpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb21wb25lbnQudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53aWRnZXQuaGlkZSgpO1xuXG4gICAgICAgICAgICAkKHdpbmRvdykub2ZmKCdyZXNpemUnLCB0aGlzLl9wbGFjZSgpKTtcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0Lm9mZignY2xpY2snLCAnW2RhdGEtYWN0aW9uXScpO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQub2ZmKCdtb3VzZWRvd24nLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0LnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQgPSBmYWxzZTtcblxuICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkhJREUsXG4gICAgICAgICAgICAgICAgZGF0ZTogdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5jbG9uZSgpXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQuYmx1cigpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuY2xvbmUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuc2hvdyA9IGZ1bmN0aW9uIHNob3coKSB7XG4gICAgICAgICAgICB2YXIgY3VycmVudE1vbWVudCA9IHZvaWQgMDtcbiAgICAgICAgICAgIHZhciB1c2VDdXJyZW50R3JhbnVsYXJpdHkgPSB7XG4gICAgICAgICAgICAgICAgJ3llYXInOiBmdW5jdGlvbiB5ZWFyKG0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0ubW9udGgoMCkuZGF0ZSgxKS5ob3VycygwKS5zZWNvbmRzKDApLm1pbnV0ZXMoMCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAnbW9udGgnOiBmdW5jdGlvbiBtb250aChtKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtLmRhdGUoMSkuaG91cnMoMCkuc2Vjb25kcygwKS5taW51dGVzKDApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ2RheSc6IGZ1bmN0aW9uIGRheShtKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtLmhvdXJzKDApLnNlY29uZHMoMCkubWludXRlcygwKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICdob3VyJzogZnVuY3Rpb24gaG91cihtKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtLnNlY29uZHMoMCkubWludXRlcygwKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICdtaW51dGUnOiBmdW5jdGlvbiBtaW51dGUobSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbS5zZWNvbmRzKDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dC5wcm9wKCdkaXNhYmxlZCcpIHx8ICF0aGlzLl9vcHRpb25zLmlnbm9yZVJlYWRvbmx5ICYmIHRoaXMuaW5wdXQucHJvcCgncmVhZG9ubHknKSB8fCB0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0LnZhbCgpICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC52YWwoKS50cmltKCkubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX3BhcnNlSW5wdXREYXRlKHRoaXMuaW5wdXQudmFsKCkudHJpbSgpKSwgMCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnVuc2V0ICYmIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50TW9tZW50ID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50TW9tZW50ID0gdXNlQ3VycmVudEdyYW51bGFyaXR5W3RoaXMuX29wdGlvbnMudXNlQ3VycmVudF0oY3VycmVudE1vbWVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoY3VycmVudE1vbWVudCwgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnVuc2V0ICYmIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRNb21lbnQgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50TW9tZW50ID0gdXNlQ3VycmVudEdyYW51bGFyaXR5W3RoaXMuX29wdGlvbnMudXNlQ3VycmVudF0oY3VycmVudE1vbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGN1cnJlbnRNb21lbnQsIDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLndpZGdldCA9IHRoaXMuX2dldFRlbXBsYXRlKCk7XG5cbiAgICAgICAgICAgIHRoaXMuX2ZpbGxEb3coKTtcbiAgICAgICAgICAgIHRoaXMuX2ZpbGxNb250aHMoKTtcblxuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItaG91cnMnKS5oaWRlKCk7XG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlci1taW51dGVzJykuaGlkZSgpO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItc2Vjb25kcycpLmhpZGUoKTtcblxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICB0aGlzLl9zaG93TW9kZSgpO1xuXG4gICAgICAgICAgICAkKHdpbmRvdykub24oJ3Jlc2l6ZScsIHsgcGlja2VyOiB0aGlzIH0sIHRoaXMuX3BsYWNlKTtcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0Lm9uKCdjbGljaycsICdbZGF0YS1hY3Rpb25dJywgJC5wcm94eSh0aGlzLl9kb0FjdGlvbiwgdGhpcykpOyAvLyB0aGlzIGhhbmRsZXMgY2xpY2tzIG9uIHRoZSB3aWRnZXRcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0Lm9uKCdtb3VzZWRvd24nLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudC50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9wbGFjZSgpO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQuc2hvdygpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLl9vcHRpb25zLmZvY3VzT25TaG93ICYmICF0aGlzLmlucHV0LmlzKCc6Zm9jdXMnKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fbm90aWZ5RXZlbnQoe1xuICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LlNIT1dcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgLy90b2RvIGRvYyBvZmY/XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50LnJlbW92ZURhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpO1xuICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5yZW1vdmVEYXRhKCdkYXRlJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLmRpc2FibGUgPSBmdW5jdGlvbiBkaXNhYmxlKCkge1xuICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb21wb25lbnQgJiYgdGhpcy5jb21wb25lbnQuaGFzQ2xhc3MoJ2J0bicpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb21wb25lbnQuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dC5wcm9wKCdkaXNhYmxlZCcsIHRydWUpOyAvL3RvZG8gZGlzYWJsZSB0aGlzL2NvbXAgaWYgaW5wdXQgaXMgbnVsbFxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5lbmFibGUgPSBmdW5jdGlvbiBlbmFibGUoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jb21wb25lbnQgJiYgdGhpcy5jb21wb25lbnQuaGFzQ2xhc3MoJ2J0bicpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb21wb25lbnQucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dC5wcm9wKCdkaXNhYmxlZCcsIGZhbHNlKTsgLy90b2RvIGVuYWJsZSBjb21wL3RoaXMgaWYgaW5wdXQgaXMgbnVsbFxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS50b29sYmFyUGxhY2VtZW50ID0gZnVuY3Rpb24gdG9vbGJhclBsYWNlbWVudChfdG9vbGJhclBsYWNlbWVudCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF90b29sYmFyUGxhY2VtZW50ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Rvb2xiYXJQbGFjZW1lbnQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRvb2xiYXJQbGFjZW1lbnRzLmluZGV4T2YoX3Rvb2xiYXJQbGFjZW1lbnQpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Rvb2xiYXJQbGFjZW1lbnQoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgKCcgKyB0b29sYmFyUGxhY2VtZW50cy5qb2luKCcsICcpICsgJykgdmFsdWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9IF90b29sYmFyUGxhY2VtZW50O1xuXG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUud2lkZ2V0UG9zaXRpb25pbmcgPSBmdW5jdGlvbiB3aWRnZXRQb3NpdGlvbmluZyhfd2lkZ2V0UG9zaXRpb25pbmcpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHt9LnRvU3RyaW5nLmNhbGwoX3dpZGdldFBvc2l0aW9uaW5nKSAhPT0gJ1tvYmplY3QgT2JqZWN0XScpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd3aWRnZXRQb3NpdGlvbmluZygpIGV4cGVjdHMgYW4gb2JqZWN0IHZhcmlhYmxlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIF93aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd3aWRnZXRQb3NpdGlvbmluZygpIGhvcml6b250YWwgdmFyaWFibGUgbXVzdCBiZSBhIHN0cmluZycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbCA9IF93aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgaWYgKGhvcml6b250YWxNb2Rlcy5pbmRleE9mKF93aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSBleHBlY3RzIGhvcml6b250YWwgcGFyYW1ldGVyIHRvIGJlIG9uZSBvZiAoJyArIGhvcml6b250YWxNb2Rlcy5qb2luKCcsICcpICsgJyknKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsID0gX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3dpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBfd2lkZ2V0UG9zaXRpb25pbmcudmVydGljYWwgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBvc2l0aW9uaW5nKCkgdmVydGljYWwgdmFyaWFibGUgbXVzdCBiZSBhIHN0cmluZycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfd2lkZ2V0UG9zaXRpb25pbmcudmVydGljYWwgPSBfd2lkZ2V0UG9zaXRpb25pbmcudmVydGljYWwudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICBpZiAodmVydGljYWxNb2Rlcy5pbmRleE9mKF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBvc2l0aW9uaW5nKCkgZXhwZWN0cyB2ZXJ0aWNhbCBwYXJhbWV0ZXIgdG8gYmUgb25lIG9mICgnICsgdmVydGljYWxNb2Rlcy5qb2luKCcsICcpICsgJyknKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCA9IF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS53aWRnZXRQYXJlbnQgPSBmdW5jdGlvbiB3aWRnZXRQYXJlbnQoX3dpZGdldFBhcmVudCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy53aWRnZXRQYXJlbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3dpZGdldFBhcmVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBfd2lkZ2V0UGFyZW50ID0gJChfd2lkZ2V0UGFyZW50KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKF93aWRnZXRQYXJlbnQgIT09IG51bGwgJiYgdHlwZW9mIF93aWRnZXRQYXJlbnQgIT09ICdzdHJpbmcnICYmICEoX3dpZGdldFBhcmVudCBpbnN0YW5jZW9mICQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UGFyZW50KCkgZXhwZWN0cyBhIHN0cmluZyBvciBhIGpRdWVyeSBvYmplY3QgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMud2lkZ2V0UGFyZW50ID0gX3dpZGdldFBhcmVudDtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vc3RhdGljXG5cblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SGFuZGxlVGhpcyA9IGZ1bmN0aW9uIF9qUXVlcnlIYW5kbGVUaGlzKG1lLCBvcHRpb24sIGFyZ3VtZW50KSB7XG4gICAgICAgICAgICB2YXIgZGF0YSA9ICQobWUpLmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpO1xuICAgICAgICAgICAgaWYgKCh0eXBlb2Ygb3B0aW9uID09PSAndW5kZWZpbmVkJyA/ICd1bmRlZmluZWQnIDogX3R5cGVvZihvcHRpb24pKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAkLmV4dGVuZCh7fSwgRGF0ZVRpbWVQaWNrZXIuRGVmYXVsdCwgb3B0aW9uKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9IG5ldyBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNCgkKG1lKSwgb3B0aW9uKTtcbiAgICAgICAgICAgICAgICAkKG1lKS5kYXRhKERhdGVUaW1lUGlja2VyLkRBVEFfS0VZLCBkYXRhKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGFbb3B0aW9uXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gbWV0aG9kIG5hbWVkIFwiJyArIG9wdGlvbiArICdcIicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YVtvcHRpb25dKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdGFbb3B0aW9uXShhcmd1bWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKG9wdGlvbiwgYXJndW1lbnQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SGFuZGxlVGhpcyh0aGlzWzBdLCBvcHRpb24sIGFyZ3VtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlIYW5kbGVUaGlzKHRoaXMsIG9wdGlvbiwgYXJndW1lbnQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIFRlbXB1c0RvbWludXNCb290c3RyYXA0O1xuICAgIH0oRGF0ZVRpbWVQaWNrZXIpO1xuXG4gICAgLyoqXHJcbiAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgKiBqUXVlcnlcclxuICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICAqL1xuXG5cbiAgICAkKGRvY3VtZW50KS5vbihEYXRlVGltZVBpY2tlci5FdmVudC5DTElDS19EQVRBX0FQSSwgRGF0ZVRpbWVQaWNrZXIuU2VsZWN0b3IuREFUQV9UT0dHTEUsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ3RvZ2dsZScpO1xuICAgIH0pLm9uKERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSwgJy4nICsgRGF0ZVRpbWVQaWNrZXIuQ2xhc3NOYW1lLklOUFVULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ19jaGFuZ2UnLCBldmVudCk7XG4gICAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQkxVUiwgJy4nICsgRGF0ZVRpbWVQaWNrZXIuQ2xhc3NOYW1lLklOUFVULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpLFxuICAgICAgICAgICAgY29uZmlnID0gJHRhcmdldC5kYXRhKERhdGVUaW1lUGlja2VyLkRBVEFfS0VZKTtcbiAgICAgICAgaWYgKCR0YXJnZXQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmZpZy5fb3B0aW9ucy5kZWJ1ZyB8fCB3aW5kb3cuZGVidWcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ2hpZGUnLCBldmVudCk7XG4gICAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuS0VZRE9XTiwgJy4nICsgRGF0ZVRpbWVQaWNrZXIuQ2xhc3NOYW1lLklOUFVULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSBnZXRTZWxlY3RvckZyb21FbGVtZW50KCQodGhpcykpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ19rZXlkb3duJywgZXZlbnQpO1xuICAgIH0pLm9uKERhdGVUaW1lUGlja2VyLkV2ZW50LktFWVVQLCAnLicgKyBEYXRlVGltZVBpY2tlci5DbGFzc05hbWUuSU5QVVQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSk7XG4gICAgICAgIGlmICgkdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkdGFyZ2V0LCAnX2tleXVwJywgZXZlbnQpO1xuICAgIH0pLm9uKERhdGVUaW1lUGlja2VyLkV2ZW50LkZPQ1VTLCAnLicgKyBEYXRlVGltZVBpY2tlci5DbGFzc05hbWUuSU5QVVQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSksXG4gICAgICAgICAgICBjb25maWcgPSAkdGFyZ2V0LmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbmZpZy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZS5jYWxsKCR0YXJnZXQsICdzaG93JywgZXZlbnQpO1xuICAgIH0pO1xuXG4gICAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXSA9IFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXS5Db25zdHJ1Y3RvciA9IFRlbXB1c0RvbWludXNCb290c3RyYXA0O1xuICAgICQuZm5bRGF0ZVRpbWVQaWNrZXIuTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgICAgcmV0dXJuIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2U7XG4gICAgfTtcblxuICAgIHJldHVybiBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNDtcbn0oalF1ZXJ5KTtcclxuXHJcbn0oKTtcclxuIiwiLyohXG4qIGpxdWVyeS5pbnB1dG1hc2suYnVuZGxlLmpzXG4qIGh0dHBzOi8vZ2l0aHViLmNvbS9Sb2JpbkhlcmJvdHMvSW5wdXRtYXNrXG4qIENvcHlyaWdodCAoYykgMjAxMCAtIDIwMTkgUm9iaW4gSGVyYm90c1xuKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgKGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwKVxuKiBWZXJzaW9uOiA0LjAuOVxuKi9cblxuKGZ1bmN0aW9uKG1vZHVsZXMpIHtcbiAgICB2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuICAgIGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcbiAgICAgICAgaWYgKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gICAgICAgICAgICBpOiBtb2R1bGVJZCxcbiAgICAgICAgICAgIGw6IGZhbHNlLFxuICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgfTtcbiAgICAgICAgbW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG4gICAgICAgIG1vZHVsZS5sID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuICAgIH1cbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuICAgIF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gICAgICAgIGlmICghX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwge1xuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZ2V0OiBnZXR0ZXJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSBmdW5jdGlvbihleHBvcnRzKSB7XG4gICAgICAgIGlmICh0eXBlb2YgU3ltYm9sICE9PSBcInVuZGVmaW5lZFwiICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywge1xuICAgICAgICAgICAgICAgIHZhbHVlOiBcIk1vZHVsZVwiXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgICAgICAgICAgIHZhbHVlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXy50ID0gZnVuY3Rpb24odmFsdWUsIG1vZGUpIHtcbiAgICAgICAgaWYgKG1vZGUgJiAxKSB2YWx1ZSA9IF9fd2VicGFja19yZXF1aXJlX18odmFsdWUpO1xuICAgICAgICBpZiAobW9kZSAmIDgpIHJldHVybiB2YWx1ZTtcbiAgICAgICAgaWYgKG1vZGUgJiA0ICYmIHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiAmJiB2YWx1ZSAmJiB2YWx1ZS5fX2VzTW9kdWxlKSByZXR1cm4gdmFsdWU7XG4gICAgICAgIHZhciBucyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgIF9fd2VicGFja19yZXF1aXJlX18ucihucyk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShucywgXCJkZWZhdWx0XCIsIHtcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICB2YWx1ZTogdmFsdWVcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChtb2RlICYgMiAmJiB0eXBlb2YgdmFsdWUgIT0gXCJzdHJpbmdcIikgZm9yICh2YXIga2V5IGluIHZhbHVlKSBfX3dlYnBhY2tfcmVxdWlyZV9fLmQobnMsIGtleSwgZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWVba2V5XTtcbiAgICAgICAgfS5iaW5kKG51bGwsIGtleSkpO1xuICAgICAgICByZXR1cm4gbnM7XG4gICAgfTtcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiAgICAgICAgdmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/IGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9kdWxlW1wiZGVmYXVsdFwiXTtcbiAgICAgICAgfSA6IGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9kdWxlO1xuICAgICAgICB9O1xuICAgICAgICBfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCBcImFcIiwgZ2V0dGVyKTtcbiAgICAgICAgcmV0dXJuIGdldHRlcjtcbiAgICB9O1xuICAgIF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTtcbiAgICB9O1xuICAgIF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG4gICAgcmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMCk7XG59KShbIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIF9fd2VicGFja19yZXF1aXJlX18oMSk7XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXyg2KTtcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fKDcpO1xuICAgIHZhciBfaW5wdXRtYXNrID0gX193ZWJwYWNrX3JlcXVpcmVfXygyKTtcbiAgICB2YXIgX2lucHV0bWFzazIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9pbnB1dG1hc2spO1xuICAgIHZhciBfaW5wdXRtYXNrMyA9IF9fd2VicGFja19yZXF1aXJlX18oMyk7XG4gICAgdmFyIF9pbnB1dG1hc2s0ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaW5wdXRtYXNrMyk7XG4gICAgdmFyIF9qcXVlcnkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQpO1xuICAgIHZhciBfanF1ZXJ5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2pxdWVyeSk7XG4gICAgZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHtcbiAgICAgICAgICAgIGRlZmF1bHQ6IG9ialxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoX2lucHV0bWFzazQuZGVmYXVsdCA9PT0gX2pxdWVyeTIuZGVmYXVsdCkge1xuICAgICAgICBfX3dlYnBhY2tfcmVxdWlyZV9fKDgpO1xuICAgIH1cbiAgICB3aW5kb3cuSW5wdXRtYXNrID0gX2lucHV0bWFzazIuZGVmYXVsdDtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fO1xuICAgIHZhciBfdHlwZW9mID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgfSA6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICB9O1xuICAgIChmdW5jdGlvbihmYWN0b3J5KSB7XG4gICAgICAgIGlmICh0cnVlKSB7XG4gICAgICAgICAgICAhKF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18gPSBbIF9fd2VicGFja19yZXF1aXJlX18oMikgXSwgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID0gZmFjdG9yeSwgXG4gICAgICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyA9IHR5cGVvZiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPT09IFwiZnVuY3Rpb25cIiA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgXG4gICAgICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyAhPT0gdW5kZWZpbmVkICYmIChtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fKSk7XG4gICAgICAgIH0gZWxzZSB7fVxuICAgIH0pKGZ1bmN0aW9uKElucHV0bWFzaykge1xuICAgICAgICBJbnB1dG1hc2suZXh0ZW5kRGVmaW5pdGlvbnMoe1xuICAgICAgICAgICAgQToge1xuICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbQS1aYS16XFx1MDQxMC1cXHUwNDRmXFx1MDQwMVxcdTA0NTFcXHhjMC1cXHhmZlxceGI1XVwiLFxuICAgICAgICAgICAgICAgIGNhc2luZzogXCJ1cHBlclwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCImXCI6IHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOUEtWmEtelxcdTA0MTAtXFx1MDQ0ZlxcdTA0MDFcXHUwNDUxXFx4YzAtXFx4ZmZcXHhiNV1cIixcbiAgICAgICAgICAgICAgICBjYXNpbmc6IFwidXBwZXJcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiI1wiOiB7XG4gICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTlBLUZhLWZdXCIsXG4gICAgICAgICAgICAgICAgY2FzaW5nOiBcInVwcGVyXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIElucHV0bWFzay5leHRlbmRBbGlhc2VzKHtcbiAgICAgICAgICAgIGNzc3VuaXQ6IHtcbiAgICAgICAgICAgICAgICByZWdleDogXCJbKy1dP1swLTldK1xcXFwuPyhbMC05XSspPyhweHxlbXxyZW18ZXh8JXxpbnxjbXxtbXxwdHxwYylcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVybDoge1xuICAgICAgICAgICAgICAgIHJlZ2V4OiBcIihodHRwcz98ZnRwKS8vLipcIixcbiAgICAgICAgICAgICAgICBhdXRvVW5tYXNrOiBmYWxzZVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlwOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJpW2lbaV1dLmlbaVtpXV0uaVtpW2ldXS5pW2lbaV1dXCIsXG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgaToge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoY2hycywgbWFza3NldCwgcG9zLCBzdHJpY3QsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9zIC0gMSA+IC0xICYmIG1hc2tzZXQuYnVmZmVyW3BvcyAtIDFdICE9PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaHJzID0gbWFza3NldC5idWZmZXJbcG9zIC0gMV0gKyBjaHJzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9zIC0gMiA+IC0xICYmIG1hc2tzZXQuYnVmZmVyW3BvcyAtIDJdICE9PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hycyA9IG1hc2tzZXQuYnVmZmVyW3BvcyAtIDJdICsgY2hycztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGNocnMgPSBcIjBcIiArIGNocnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGNocnMgPSBcIjAwXCIgKyBjaHJzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiMjVbMC01XXwyWzAtNF1bMC05XXxbMDFdWzAtOV1bMC05XVwiKS50ZXN0KGNocnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvblVuTWFzazogZnVuY3Rpb24gb25Vbk1hc2sobWFza2VkVmFsdWUsIHVubWFza2VkVmFsdWUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tlZFZhbHVlO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgaW5wdXRtb2RlOiBcIm51bWVyaWNcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVtYWlsOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCIqezEsNjR9Wy4qezEsNjR9XVsuKnsxLDY0fV1bLip7MSw2M31dQC17MSw2M30uLXsxLDYzfVsuLXsxLDYzfV1bLi17MSw2M31dXCIsXG4gICAgICAgICAgICAgICAgZ3JlZWR5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBjYXNpbmc6IFwibG93ZXJcIixcbiAgICAgICAgICAgICAgICBvbkJlZm9yZVBhc3RlOiBmdW5jdGlvbiBvbkJlZm9yZVBhc3RlKHBhc3RlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhc3RlZFZhbHVlID0gcGFzdGVkVmFsdWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhc3RlZFZhbHVlLnJlcGxhY2UoXCJtYWlsdG86XCIsIFwiXCIpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgXCIqXCI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbMC05XFx1ZmYxMS1cXHVmZjE5QS1aYS16XFx1MDQxMC1cXHUwNDRmXFx1MDQwMVxcdTA0NTFcXHhjMC1cXHhmZlxceGI1ISMkJSYnKisvPT9eX2B7fH1+LV1cIlxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBcIi1cIjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTlBLVphLXotXVwiXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uVW5NYXNrOiBmdW5jdGlvbiBvblVuTWFzayhtYXNrZWRWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza2VkVmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwiZW1haWxcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1hYzoge1xuICAgICAgICAgICAgICAgIG1hc2s6IFwiIyM6IyM6IyM6IyM6IyM6IyNcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHZpbjoge1xuICAgICAgICAgICAgICAgIG1hc2s6IFwiVnsxM305ezR9XCIsXG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgVjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIltBLUhKLU5QUi1aYS1oai1ucHItelxcXFxkXVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBcInVwcGVyXCJcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY2xlYXJJbmNvbXBsZXRlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6IHRydWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBJbnB1dG1hc2s7XG4gICAgfSk7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICB2YXIgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXztcbiAgICB2YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2Ygb2JqO1xuICAgIH0gOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7XG4gICAgfTtcbiAgICAoZnVuY3Rpb24oZmFjdG9yeSkge1xuICAgICAgICBpZiAodHJ1ZSkge1xuICAgICAgICAgICAgIShfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fID0gWyBfX3dlYnBhY2tfcmVxdWlyZV9fKDMpLCBfX3dlYnBhY2tfcmVxdWlyZV9fKDUpIF0sIFxuICAgICAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID0gZmFjdG9yeSwgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSB0eXBlb2YgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID09PSBcImZ1bmN0aW9uXCIgPyBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18uYXBwbHkoZXhwb3J0cywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXykgOiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIFxuICAgICAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gIT09IHVuZGVmaW5lZCAmJiAobW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXykpO1xuICAgICAgICB9IGVsc2Uge31cbiAgICB9KShmdW5jdGlvbigkLCB3aW5kb3csIHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgZG9jdW1lbnQgPSB3aW5kb3cuZG9jdW1lbnQsIHVhID0gbmF2aWdhdG9yLnVzZXJBZ2VudCwgaWUgPSB1YS5pbmRleE9mKFwiTVNJRSBcIikgPiAwIHx8IHVhLmluZGV4T2YoXCJUcmlkZW50L1wiKSA+IDAsIG1vYmlsZSA9IGlzSW5wdXRFdmVudFN1cHBvcnRlZChcInRvdWNoc3RhcnRcIiksIGllbW9iaWxlID0gL2llbW9iaWxlL2kudGVzdCh1YSksIGlwaG9uZSA9IC9pcGhvbmUvaS50ZXN0KHVhKSAmJiAhaWVtb2JpbGU7XG4gICAgICAgIGZ1bmN0aW9uIElucHV0bWFzayhhbGlhcywgb3B0aW9ucywgaW50ZXJuYWwpIHtcbiAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBJbnB1dG1hc2spKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBJbnB1dG1hc2soYWxpYXMsIG9wdGlvbnMsIGludGVybmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZWwgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmV2ZW50cyA9IHt9O1xuICAgICAgICAgICAgdGhpcy5tYXNrc2V0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoVmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChpbnRlcm5hbCAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGlmICgkLmlzUGxhaW5PYmplY3QoYWxpYXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBhbGlhcztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFsaWFzKSBvcHRpb25zLmFsaWFzID0gYWxpYXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMub3B0cyA9ICQuZXh0ZW5kKHRydWUsIHt9LCB0aGlzLmRlZmF1bHRzLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB0aGlzLm5vTWFza3NDYWNoZSA9IG9wdGlvbnMgJiYgb3B0aW9ucy5kZWZpbml0aW9ucyAhPT0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMudXNlck9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRoaXMuaXNSVEwgPSB0aGlzLm9wdHMubnVtZXJpY0lucHV0O1xuICAgICAgICAgICAgICAgIHJlc29sdmVBbGlhcyh0aGlzLm9wdHMuYWxpYXMsIG9wdGlvbnMsIHRoaXMub3B0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgSW5wdXRtYXNrLnByb3RvdHlwZSA9IHtcbiAgICAgICAgICAgIGRhdGFBdHRyaWJ1dGU6IFwiZGF0YS1pbnB1dG1hc2tcIixcbiAgICAgICAgICAgIGRlZmF1bHRzOiB7XG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiX1wiLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsbWFya2VyOiBbIFwiW1wiLCBcIl1cIiBdLFxuICAgICAgICAgICAgICAgIHF1YW50aWZpZXJtYXJrZXI6IFsgXCJ7XCIsIFwifVwiIF0sXG4gICAgICAgICAgICAgICAgZ3JvdXBtYXJrZXI6IFsgXCIoXCIsIFwiKVwiIF0sXG4gICAgICAgICAgICAgICAgYWx0ZXJuYXRvcm1hcmtlcjogXCJ8XCIsXG4gICAgICAgICAgICAgICAgZXNjYXBlQ2hhcjogXCJcXFxcXCIsXG4gICAgICAgICAgICAgICAgbWFzazogbnVsbCxcbiAgICAgICAgICAgICAgICByZWdleDogbnVsbCxcbiAgICAgICAgICAgICAgICBvbmNvbXBsZXRlOiAkLm5vb3AsXG4gICAgICAgICAgICAgICAgb25pbmNvbXBsZXRlOiAkLm5vb3AsXG4gICAgICAgICAgICAgICAgb25jbGVhcmVkOiAkLm5vb3AsXG4gICAgICAgICAgICAgICAgcmVwZWF0OiAwLFxuICAgICAgICAgICAgICAgIGdyZWVkeTogZmFsc2UsXG4gICAgICAgICAgICAgICAgYXV0b1VubWFzazogZmFsc2UsXG4gICAgICAgICAgICAgICAgcmVtb3ZlTWFza09uU3VibWl0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBjbGVhck1hc2tPbkxvc3RGb2N1czogdHJ1ZSxcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNsZWFySW5jb21wbGV0ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgYWxpYXM6IG51bGwsXG4gICAgICAgICAgICAgICAgb25LZXlEb3duOiAkLm5vb3AsXG4gICAgICAgICAgICAgICAgb25CZWZvcmVNYXNrOiBudWxsLFxuICAgICAgICAgICAgICAgIG9uQmVmb3JlUGFzdGU6IGZ1bmN0aW9uIG9uQmVmb3JlUGFzdGUocGFzdGVkVmFsdWUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQuaXNGdW5jdGlvbihvcHRzLm9uQmVmb3JlTWFzaykgPyBvcHRzLm9uQmVmb3JlTWFzay5jYWxsKHRoaXMsIHBhc3RlZFZhbHVlLCBvcHRzKSA6IHBhc3RlZFZhbHVlO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25CZWZvcmVXcml0ZTogbnVsbCxcbiAgICAgICAgICAgICAgICBvblVuTWFzazogbnVsbCxcbiAgICAgICAgICAgICAgICBzaG93TWFza09uRm9jdXM6IHRydWUsXG4gICAgICAgICAgICAgICAgc2hvd01hc2tPbkhvdmVyOiB0cnVlLFxuICAgICAgICAgICAgICAgIG9uS2V5VmFsaWRhdGlvbjogJC5ub29wLFxuICAgICAgICAgICAgICAgIHNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXI6IFwiIFwiLFxuICAgICAgICAgICAgICAgIG51bWVyaWNJbnB1dDogZmFsc2UsXG4gICAgICAgICAgICAgICAgcmlnaHRBbGlnbjogZmFsc2UsXG4gICAgICAgICAgICAgICAgdW5kb09uRXNjYXBlOiB0cnVlLFxuICAgICAgICAgICAgICAgIHJhZGl4UG9pbnQ6IFwiXCIsXG4gICAgICAgICAgICAgICAgX3JhZGl4RGFuY2U6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGdyb3VwU2VwYXJhdG9yOiBcIlwiLFxuICAgICAgICAgICAgICAgIGtlZXBTdGF0aWM6IG51bGwsXG4gICAgICAgICAgICAgICAgcG9zaXRpb25DYXJldE9uVGFiOiB0cnVlLFxuICAgICAgICAgICAgICAgIHRhYlRocm91Z2g6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHN1cHBvcnRzSW5wdXRUeXBlOiBbIFwidGV4dFwiLCBcInRlbFwiLCBcInVybFwiLCBcInBhc3N3b3JkXCIsIFwic2VhcmNoXCIgXSxcbiAgICAgICAgICAgICAgICBpZ25vcmFibGVzOiBbIDgsIDksIDEzLCAxOSwgMjcsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDUsIDQ2LCA5MywgMTEyLCAxMTMsIDExNCwgMTE1LCAxMTYsIDExNywgMTE4LCAxMTksIDEyMCwgMTIxLCAxMjIsIDEyMywgMCwgMjI5IF0sXG4gICAgICAgICAgICAgICAgaXNDb21wbGV0ZTogbnVsbCxcbiAgICAgICAgICAgICAgICBwcmVWYWxpZGF0aW9uOiBudWxsLFxuICAgICAgICAgICAgICAgIHBvc3RWYWxpZGF0aW9uOiBudWxsLFxuICAgICAgICAgICAgICAgIHN0YXRpY0RlZmluaXRpb25TeW1ib2w6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBqaXRNYXNraW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBpbnB1dEV2ZW50T25seTogZmFsc2UsXG4gICAgICAgICAgICAgICAgbm9WYWx1ZVBhdGNoaW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBwb3NpdGlvbkNhcmV0T25DbGljazogXCJsdnBcIixcbiAgICAgICAgICAgICAgICBjYXNpbmc6IG51bGwsXG4gICAgICAgICAgICAgICAgaW5wdXRtb2RlOiBcInZlcmJhdGltXCIsXG4gICAgICAgICAgICAgICAgY29sb3JNYXNrOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkaXNhYmxlUHJlZGljdGl2ZVRleHQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGltcG9ydERhdGFBdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICAgICAgICAgIHNoaWZ0UG9zaXRpb25zOiB0cnVlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICA5OiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbMC05XFx1ZmYxMS1cXHVmZjE5XVwiLFxuICAgICAgICAgICAgICAgICAgICBkZWZpbml0aW9uU3ltYm9sOiBcIipcIlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYToge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiW0EtWmEtelxcdTA0MTAtXFx1MDQ0ZlxcdTA0MDFcXHUwNDUxXFx4YzAtXFx4ZmZcXHhiNV1cIixcbiAgICAgICAgICAgICAgICAgICAgZGVmaW5pdGlvblN5bWJvbDogXCIqXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIFwiKlwiOiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbMC05XFx1ZmYxMS1cXHVmZjE5QS1aYS16XFx1MDQxMC1cXHUwNDRmXFx1MDQwMVxcdTA0NTFcXHhjMC1cXHhmZlxceGI1XVwiXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGFsaWFzZXM6IHt9LFxuICAgICAgICAgICAgbWFza3NDYWNoZToge30sXG4gICAgICAgICAgICBtYXNrOiBmdW5jdGlvbiBtYXNrKGVsZW1zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGltcG9ydEF0dHJpYnV0ZU9wdGlvbnMobnB0LCBvcHRzLCB1c2VyT3B0aW9ucywgZGF0YUF0dHJpYnV0ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5pbXBvcnREYXRhQXR0cmlidXRlcyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJPcHRpb25zID0gbnB0LmdldEF0dHJpYnV0ZShkYXRhQXR0cmlidXRlKSwgb3B0aW9uLCBkYXRhb3B0aW9ucywgb3B0aW9uRGF0YSwgcDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbXBvcnRPcHRpb24gPSBmdW5jdGlvbiBpbXBvcnRPcHRpb24ob3B0aW9uLCBvcHRpb25EYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uRGF0YSA9IG9wdGlvbkRhdGEgIT09IHVuZGVmaW5lZCA/IG9wdGlvbkRhdGEgOiBucHQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGUgKyBcIi1cIiArIG9wdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbkRhdGEgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25EYXRhID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9uLmluZGV4T2YoXCJvblwiKSA9PT0gMCkgb3B0aW9uRGF0YSA9IHdpbmRvd1tvcHRpb25EYXRhXTsgZWxzZSBpZiAob3B0aW9uRGF0YSA9PT0gXCJmYWxzZVwiKSBvcHRpb25EYXRhID0gZmFsc2U7IGVsc2UgaWYgKG9wdGlvbkRhdGEgPT09IFwidHJ1ZVwiKSBvcHRpb25EYXRhID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VyT3B0aW9uc1tvcHRpb25dID0gb3B0aW9uRGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJPcHRpb25zICYmIGF0dHJPcHRpb25zICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0ck9wdGlvbnMgPSBhdHRyT3B0aW9ucy5yZXBsYWNlKC8nL2csICdcIicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFvcHRpb25zID0gSlNPTi5wYXJzZShcIntcIiArIGF0dHJPcHRpb25zICsgXCJ9XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFvcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uRGF0YSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHAgaW4gZGF0YW9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHAudG9Mb3dlckNhc2UoKSA9PT0gXCJhbGlhc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25EYXRhID0gZGF0YW9wdGlvbnNbcF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGltcG9ydE9wdGlvbihcImFsaWFzXCIsIG9wdGlvbkRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJPcHRpb25zLmFsaWFzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZUFsaWFzKHVzZXJPcHRpb25zLmFsaWFzLCB1c2VyT3B0aW9ucywgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKG9wdGlvbiBpbiBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFvcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbkRhdGEgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAocCBpbiBkYXRhb3B0aW9ucykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHAudG9Mb3dlckNhc2UoKSA9PT0gb3B0aW9uLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25EYXRhID0gZGF0YW9wdGlvbnNbcF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1wb3J0T3B0aW9uKG9wdGlvbiwgb3B0aW9uRGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgb3B0cywgdXNlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobnB0LmRpciA9PT0gXCJydGxcIiB8fCBvcHRzLnJpZ2h0QWxpZ24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5wdC5zdHlsZS50ZXh0QWxpZ24gPSBcInJpZ2h0XCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5wdC5kaXIgPT09IFwicnRsXCIgfHwgb3B0cy5udW1lcmljSW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5wdC5kaXIgPSBcImx0clwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgbnB0LnJlbW92ZUF0dHJpYnV0ZShcImRpclwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuaXNSVEwgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh1c2VyT3B0aW9ucykubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGVsZW1zID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1zID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWxlbXMpIHx8IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoZWxlbXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbGVtcyA9IGVsZW1zLm5vZGVOYW1lID8gWyBlbGVtcyBdIDogZWxlbXM7XG4gICAgICAgICAgICAgICAgJC5lYWNoKGVsZW1zLCBmdW5jdGlvbihuZHgsIGVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzY29wZWRPcHRzID0gJC5leHRlbmQodHJ1ZSwge30sIHRoYXQub3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbXBvcnRBdHRyaWJ1dGVPcHRpb25zKGVsLCBzY29wZWRPcHRzLCAkLmV4dGVuZCh0cnVlLCB7fSwgdGhhdC51c2VyT3B0aW9ucyksIHRoYXQuZGF0YUF0dHJpYnV0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXNrc2V0ID0gZ2VuZXJhdGVNYXNrU2V0KHNjb3BlZE9wdHMsIHRoYXQubm9NYXNrc0NhY2hlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrc2V0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWwuaW5wdXRtYXNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLm9wdHMuYXV0b1VubWFzayA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrID0gbmV3IElucHV0bWFzayh1bmRlZmluZWQsIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLm9wdHMgPSBzY29wZWRPcHRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5ub01hc2tzQ2FjaGUgPSB0aGF0Lm5vTWFza3NDYWNoZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2sudXNlck9wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgdGhhdC51c2VyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLmlzUlRMID0gc2NvcGVkT3B0cy5pc1JUTCB8fCBzY29wZWRPcHRzLm51bWVyaWNJbnB1dDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2suZWwgPSBlbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2subWFza3NldCA9IG1hc2tzZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5kYXRhKGVsLCBcIl9pbnB1dG1hc2tfb3B0c1wiLCBzY29wZWRPcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrU2NvcGUuY2FsbChlbC5pbnB1dG1hc2ssIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcIm1hc2tcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1zICYmIGVsZW1zWzBdID8gZWxlbXNbMF0uaW5wdXRtYXNrIHx8IHRoaXMgOiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbjogZnVuY3Rpb24gb3B0aW9uKG9wdGlvbnMsIG5vcmVtYXNrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wdHNbb3B0aW9uc107XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICgodHlwZW9mIG9wdGlvbnMgPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogX3R5cGVvZihvcHRpb25zKSkgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgJC5leHRlbmQodGhpcy51c2VyT3B0aW9ucywgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmVsICYmIG5vcmVtYXNrICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hc2sodGhpcy5lbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVubWFza2VkdmFsdWU6IGZ1bmN0aW9uIHVubWFza2VkdmFsdWUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1hc2tzZXQgPSB0aGlzLm1hc2tzZXQgfHwgZ2VuZXJhdGVNYXNrU2V0KHRoaXMub3B0cywgdGhpcy5ub01hc2tzQ2FjaGUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrU2NvcGUuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogXCJ1bm1hc2tlZHZhbHVlXCIsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlbW92ZTogZnVuY3Rpb24gcmVtb3ZlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrU2NvcGUuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogXCJyZW1vdmVcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldGVtcHR5bWFzazogZnVuY3Rpb24gZ2V0ZW1wdHltYXNrKCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCBnZW5lcmF0ZU1hc2tTZXQodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcImdldGVtcHR5bWFza1wiXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGFzTWFza2VkVmFsdWU6IGZ1bmN0aW9uIGhhc01hc2tlZFZhbHVlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAhdGhpcy5vcHRzLmF1dG9Vbm1hc2s7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXNDb21wbGV0ZTogZnVuY3Rpb24gaXNDb21wbGV0ZSgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1hc2tzZXQgPSB0aGlzLm1hc2tzZXQgfHwgZ2VuZXJhdGVNYXNrU2V0KHRoaXMub3B0cywgdGhpcy5ub01hc2tzQ2FjaGUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrU2NvcGUuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogXCJpc0NvbXBsZXRlXCJcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXRtZXRhZGF0YTogZnVuY3Rpb24gZ2V0bWV0YWRhdGEoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tYXNrc2V0ID0gdGhpcy5tYXNrc2V0IHx8IGdlbmVyYXRlTWFza1NldCh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWFza1Njb3BlLmNhbGwodGhpcywge1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwiZ2V0bWV0YWRhdGFcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzVmFsaWQ6IGZ1bmN0aW9uIGlzVmFsaWQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1hc2tzZXQgPSB0aGlzLm1hc2tzZXQgfHwgZ2VuZXJhdGVNYXNrU2V0KHRoaXMub3B0cywgdGhpcy5ub01hc2tzQ2FjaGUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrU2NvcGUuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogXCJpc1ZhbGlkXCIsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZvcm1hdDogZnVuY3Rpb24gZm9ybWF0KHZhbHVlLCBtZXRhZGF0YSkge1xuICAgICAgICAgICAgICAgIHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCBnZW5lcmF0ZU1hc2tTZXQodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcImZvcm1hdFwiLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiBtZXRhZGF0YVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldFZhbHVlOiBmdW5jdGlvbiBzZXRWYWx1ZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmVsKSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcy5lbCkudHJpZ2dlcihcInNldHZhbHVlXCIsIFsgdmFsdWUgXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGFuYWx5c2VNYXNrOiBmdW5jdGlvbiBhbmFseXNlTWFzayhtYXNrLCByZWdleE1hc2ssIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9rZW5pemVyID0gLyg/Ols/KitdfFxce1swLTlcXCtcXCpdKyg/OixbMC05XFwrXFwqXSopPyg/OlxcfFswLTlcXCtcXCpdKik/XFx9KXxbXi4/KiteJHtbXSgpfFxcXFxdK3wuL2csIHJlZ2V4VG9rZW5pemVyID0gL1xcW1xcXj9dPyg/OlteXFxcXFxcXV0rfFxcXFxbXFxTXFxzXT8pKl0/fFxcXFwoPzowKD86WzAtM11bMC03XXswLDJ9fFs0LTddWzAtN10/KT98WzEtOV1bMC05XSp8eFswLTlBLUZhLWZdezJ9fHVbMC05QS1GYS1mXXs0fXxjW0EtWmEtel18W1xcU1xcc10/KXxcXCgoPzpcXD9bOj0hXT8pP3woPzpbPyorXXxcXHtbMC05XSsoPzosWzAtOV0qKT9cXH0pXFw/P3xbXi4/KiteJHtbKCl8XFxcXF0rfC4vZywgZXNjYXBlZCA9IGZhbHNlLCBjdXJyZW50VG9rZW4gPSBuZXcgTWFza1Rva2VuKCksIG1hdGNoLCBtLCBvcGVuZW5pbmdzID0gW10sIG1hc2tUb2tlbnMgPSBbXSwgb3BlbmluZ1Rva2VuLCBjdXJyZW50T3BlbmluZ1Rva2VuLCBhbHRlcm5hdG9yLCBsYXN0TWF0Y2gsIGdyb3VwVG9rZW47XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gTWFza1Rva2VuKGlzR3JvdXAsIGlzT3B0aW9uYWwsIGlzUXVhbnRpZmllciwgaXNBbHRlcm5hdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWF0Y2hlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW5Hcm91cCA9IGlzR3JvdXAgfHwgZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWx0ZXJuYXRvckdyb3VwID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNHcm91cCA9IGlzR3JvdXAgfHwgZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNPcHRpb25hbCA9IGlzT3B0aW9uYWwgfHwgZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNRdWFudGlmaWVyID0gaXNRdWFudGlmaWVyIHx8IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlzQWx0ZXJuYXRvciA9IGlzQWx0ZXJuYXRvciB8fCBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5xdWFudGlmaWVyID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4OiAxXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydFRlc3REZWZpbml0aW9uKG10b2tlbiwgZWxlbWVudCwgcG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbiAhPT0gdW5kZWZpbmVkID8gcG9zaXRpb24gOiBtdG9rZW4ubWF0Y2hlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2TWF0Y2ggPSBtdG9rZW4ubWF0Y2hlc1twb3NpdGlvbiAtIDFdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVnZXhNYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5pbmRleE9mKFwiW1wiKSA9PT0gMCB8fCBlc2NhcGVkICYmIC9cXFxcZHxcXFxcc3xcXFxcd10vaS50ZXN0KGVsZW1lbnQpIHx8IGVsZW1lbnQgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXRva2VuLm1hdGNoZXMuc3BsaWNlKHBvc2l0aW9uKyssIDAsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm46IG5ldyBSZWdFeHAoZWxlbWVudCwgb3B0cy5jYXNpbmcgPyBcImlcIiA6IFwiXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbGl0eTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0Jsb2NrTWFya2VyOiBwcmV2TWF0Y2ggPT09IHVuZGVmaW5lZCA/IFwibWFzdGVyXCIgOiBwcmV2TWF0Y2guZGVmICE9PSBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZjogZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF0aXZlRGVmOiBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlc2NhcGVkKSBlbGVtZW50ID0gZWxlbWVudFtlbGVtZW50Lmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChlbGVtZW50LnNwbGl0KFwiXCIpLCBmdW5jdGlvbihuZHgsIGxtbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldk1hdGNoID0gbXRva2VuLm1hdGNoZXNbcG9zaXRpb24gLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXRva2VuLm1hdGNoZXMuc3BsaWNlKHBvc2l0aW9uKyssIDAsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZuOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxpdHk6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3QmxvY2tNYXJrZXI6IHByZXZNYXRjaCA9PT0gdW5kZWZpbmVkID8gXCJtYXN0ZXJcIiA6IHByZXZNYXRjaC5kZWYgIT09IGxtbnQgJiYgcHJldk1hdGNoLmZuICE9PSBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgfHwgbG1udCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgIT09IHVuZGVmaW5lZCA/IGxtbnQgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVEZWY6IChlc2NhcGVkID8gXCInXCIgOiBcIlwiKSArIGxtbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlc2NhcGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWFza2RlZiA9IChvcHRzLmRlZmluaXRpb25zID8gb3B0cy5kZWZpbml0aW9uc1tlbGVtZW50XSA6IHVuZGVmaW5lZCkgfHwgSW5wdXRtYXNrLnByb3RvdHlwZS5kZWZpbml0aW9uc1tlbGVtZW50XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrZGVmICYmICFlc2NhcGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXRva2VuLm1hdGNoZXMuc3BsaWNlKHBvc2l0aW9uKyssIDAsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm46IG1hc2tkZWYudmFsaWRhdG9yID8gdHlwZW9mIG1hc2tkZWYudmFsaWRhdG9yID09IFwic3RyaW5nXCIgPyBuZXcgUmVnRXhwKG1hc2tkZWYudmFsaWRhdG9yLCBvcHRzLmNhc2luZyA/IFwiaVwiIDogXCJcIikgOiBuZXcgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRlc3QgPSBtYXNrZGVmLnZhbGlkYXRvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSgpIDogbmV3IFJlZ0V4cChcIi5cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsaXR5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3QmxvY2tNYXJrZXI6IHByZXZNYXRjaCA9PT0gdW5kZWZpbmVkID8gXCJtYXN0ZXJcIiA6IHByZXZNYXRjaC5kZWYgIT09IChtYXNrZGVmLmRlZmluaXRpb25TeW1ib2wgfHwgZWxlbWVudCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogbWFza2RlZi5jYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZjogbWFza2RlZi5kZWZpbml0aW9uU3ltYm9sIHx8IGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBtYXNrZGVmLnBsYWNlaG9sZGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVEZWY6IGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXRva2VuLm1hdGNoZXMuc3BsaWNlKHBvc2l0aW9uKyssIDAsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm46IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsaXR5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3QmxvY2tNYXJrZXI6IHByZXZNYXRjaCA9PT0gdW5kZWZpbmVkID8gXCJtYXN0ZXJcIiA6IHByZXZNYXRjaC5kZWYgIT09IGVsZW1lbnQgJiYgcHJldk1hdGNoLmZuICE9PSBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZjogb3B0cy5zdGF0aWNEZWZpbml0aW9uU3ltYm9sIHx8IGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgIT09IHVuZGVmaW5lZCA/IGVsZW1lbnQgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdGl2ZURlZjogKGVzY2FwZWQgPyBcIidcIiA6IFwiXCIpICsgZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzY2FwZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiB2ZXJpZnlHcm91cE1hcmtlcihtYXNrVG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tUb2tlbiAmJiBtYXNrVG9rZW4ubWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKG1hc2tUb2tlbi5tYXRjaGVzLCBmdW5jdGlvbihuZHgsIHRva2VuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRUb2tlbiA9IG1hc2tUb2tlbi5tYXRjaGVzW25keCArIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgobmV4dFRva2VuID09PSB1bmRlZmluZWQgfHwgbmV4dFRva2VuLm1hdGNoZXMgPT09IHVuZGVmaW5lZCB8fCBuZXh0VG9rZW4uaXNRdWFudGlmaWVyID09PSBmYWxzZSkgJiYgdG9rZW4gJiYgdG9rZW4uaXNHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlbi5pc0dyb3VwID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcmVnZXhNYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRUZXN0RGVmaW5pdGlvbih0b2tlbiwgb3B0cy5ncm91cG1hcmtlclswXSwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodG9rZW4ub3Blbkdyb3VwICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0VGVzdERlZmluaXRpb24odG9rZW4sIG9wdHMuZ3JvdXBtYXJrZXJbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmlmeUdyb3VwTWFya2VyKHRva2VuKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGRlZmF1bHRDYXNlKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3BlbmVuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuID0gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0VGVzdERlZmluaXRpb24oY3VycmVudE9wZW5pbmdUb2tlbiwgbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudE9wZW5pbmdUb2tlbi5pc0FsdGVybmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdG9yID0gb3BlbmVuaW5ncy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBtbmR4ID0gMDsgbW5keCA8IGFsdGVybmF0b3IubWF0Y2hlcy5sZW5ndGg7IG1uZHgrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWx0ZXJuYXRvci5tYXRjaGVzW21uZHhdLmlzR3JvdXApIGFsdGVybmF0b3IubWF0Y2hlc1ttbmR4XS5pc0dyb3VwID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcGVuZW5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudE9wZW5pbmdUb2tlbiA9IG9wZW5lbmluZ3Nbb3BlbmVuaW5ncy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudE9wZW5pbmdUb2tlbi5tYXRjaGVzLnB1c2goYWx0ZXJuYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFRva2VuLm1hdGNoZXMucHVzaChhbHRlcm5hdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRUZXN0RGVmaW5pdGlvbihjdXJyZW50VG9rZW4sIG0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJldmVyc2VUb2tlbnMobWFza1Rva2VuKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJldmVyc2VTdGF0aWMoc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdCA9PT0gb3B0cy5vcHRpb25hbG1hcmtlclswXSkgc3QgPSBvcHRzLm9wdGlvbmFsbWFya2VyWzFdOyBlbHNlIGlmIChzdCA9PT0gb3B0cy5vcHRpb25hbG1hcmtlclsxXSkgc3QgPSBvcHRzLm9wdGlvbmFsbWFya2VyWzBdOyBlbHNlIGlmIChzdCA9PT0gb3B0cy5ncm91cG1hcmtlclswXSkgc3QgPSBvcHRzLmdyb3VwbWFya2VyWzFdOyBlbHNlIGlmIChzdCA9PT0gb3B0cy5ncm91cG1hcmtlclsxXSkgc3QgPSBvcHRzLmdyb3VwbWFya2VyWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG1hc2tUb2tlbi5tYXRjaGVzID0gbWFza1Rva2VuLm1hdGNoZXMucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBtYXRjaCBpbiBtYXNrVG9rZW4ubWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tUb2tlbi5tYXRjaGVzLmhhc093blByb3BlcnR5KG1hdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnRNYXRjaCA9IHBhcnNlSW50KG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdLmlzUXVhbnRpZmllciAmJiBtYXNrVG9rZW4ubWF0Y2hlc1tpbnRNYXRjaCArIDFdICYmIG1hc2tUb2tlbi5tYXRjaGVzW2ludE1hdGNoICsgMV0uaXNHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcXQgPSBtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUb2tlbi5tYXRjaGVzLnNwbGljZShtYXRjaCwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUb2tlbi5tYXRjaGVzLnNwbGljZShpbnRNYXRjaCArIDEsIDAsIHF0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tUb2tlbi5tYXRjaGVzW21hdGNoXS5tYXRjaGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdID0gcmV2ZXJzZVRva2VucyhtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUb2tlbi5tYXRjaGVzW21hdGNoXSA9IHJldmVyc2VTdGF0aWMobWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tUb2tlbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gZ3JvdXBpZnkobWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZ3JvdXBUb2tlbiA9IG5ldyBNYXNrVG9rZW4odHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwVG9rZW4ub3Blbkdyb3VwID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwVG9rZW4ubWF0Y2hlcyA9IG1hdGNoZXM7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBncm91cFRva2VuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmVnZXhNYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMub3B0aW9uYWxtYXJrZXJbMF0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMub3B0aW9uYWxtYXJrZXJbMV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHJlZ2V4TWFzayA/IHJlZ2V4VG9rZW5pemVyLmV4ZWMobWFzaykgOiB0b2tlbml6ZXIuZXhlYyhtYXNrKSkge1xuICAgICAgICAgICAgICAgICAgICBtID0gbWF0Y2hbMF07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZWdleE1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobS5jaGFyQXQoMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIj9cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtID0gXCJ7MCwxfVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCIrXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCIqXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbSA9IFwie1wiICsgbSArIFwifVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChlc2NhcGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0Q2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtLmNoYXJBdCgwKSkge1xuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCIoPz1cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIig/IVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiKD88PVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiKD88IVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIG9wdHMuZXNjYXBlQ2hhcjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVzY2FwZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlZ2V4TWFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5vcHRpb25hbG1hcmtlclsxXTpcbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIG9wdHMuZ3JvdXBtYXJrZXJbMV06XG4gICAgICAgICAgICAgICAgICAgICAgICBvcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbmluZ1Rva2VuLm9wZW5Hcm91cCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wZW5pbmdUb2tlbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wZW5lbmluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuID0gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuLm1hdGNoZXMucHVzaChvcGVuaW5nVG9rZW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudE9wZW5pbmdUb2tlbi5pc0FsdGVybmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IgPSBvcGVuZW5pbmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbW5keCA9IDA7IG1uZHggPCBhbHRlcm5hdG9yLm1hdGNoZXMubGVuZ3RoOyBtbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdG9yLm1hdGNoZXNbbW5keF0uaXNHcm91cCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IubWF0Y2hlc1ttbmR4XS5hbHRlcm5hdG9yR3JvdXAgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcGVuZW5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuID0gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRPcGVuaW5nVG9rZW4ubWF0Y2hlcy5wdXNoKGFsdGVybmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wdXNoKGFsdGVybmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFRva2VuLm1hdGNoZXMucHVzaChvcGVuaW5nVG9rZW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBkZWZhdWx0Q2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIG9wdHMub3B0aW9uYWxtYXJrZXJbMF06XG4gICAgICAgICAgICAgICAgICAgICAgICBvcGVuZW5pbmdzLnB1c2gobmV3IE1hc2tUb2tlbihmYWxzZSwgdHJ1ZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIG9wdHMuZ3JvdXBtYXJrZXJbMF06XG4gICAgICAgICAgICAgICAgICAgICAgICBvcGVuZW5pbmdzLnB1c2gobmV3IE1hc2tUb2tlbih0cnVlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5xdWFudGlmaWVybWFya2VyWzBdOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHF1YW50aWZpZXIgPSBuZXcgTWFza1Rva2VuKGZhbHNlLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtID0gbS5yZXBsYWNlKC9be31dL2csIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1xaiA9IG0uc3BsaXQoXCJ8XCIpLCBtcSA9IG1xalswXS5zcGxpdChcIixcIiksIG1xMCA9IGlzTmFOKG1xWzBdKSA/IG1xWzBdIDogcGFyc2VJbnQobXFbMF0pLCBtcTEgPSBtcS5sZW5ndGggPT09IDEgPyBtcTAgOiBpc05hTihtcVsxXSkgPyBtcVsxXSA6IHBhcnNlSW50KG1xWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtcTAgPT09IFwiKlwiIHx8IG1xMCA9PT0gXCIrXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtcTAgPSBtcTEgPT09IFwiKlwiID8gMCA6IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBxdWFudGlmaWVyLnF1YW50aWZpZXIgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluOiBtcTAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4OiBtcTEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0OiBtcWpbMV1cbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IG9wZW5lbmluZ3MubGVuZ3RoID4gMCA/IG9wZW5lbmluZ3Nbb3BlbmVuaW5ncy5sZW5ndGggLSAxXS5tYXRjaGVzIDogY3VycmVudFRva2VuLm1hdGNoZXM7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IG1hdGNoZXMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2guaXNBbHRlcm5hdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzID0gbWF0Y2gubWF0Y2hlcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZ3JvdXBUb2tlbiA9IG5ldyBNYXNrVG9rZW4odHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRtcE1hdGNoID0gbWF0Y2hlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2goZ3JvdXBUb2tlbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IGdyb3VwVG9rZW4ubWF0Y2hlcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IHRtcE1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFtYXRjaC5pc0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBncm91cGlmeShbIG1hdGNoIF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMucHVzaChxdWFudGlmaWVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBvcHRzLmFsdGVybmF0b3JtYXJrZXI6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZ3JvdXBRdWFudGlmaWVyID0gZnVuY3Rpb24gZ3JvdXBRdWFudGlmaWVyKG1hdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGFzdE1hdGNoID0gbWF0Y2hlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdE1hdGNoLmlzUXVhbnRpZmllcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TWF0Y2ggPSBncm91cGlmeShbIG1hdGNoZXMucG9wKCksIGxhc3RNYXRjaCBdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxhc3RNYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3BlbmVuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudE9wZW5pbmdUb2tlbiA9IG9wZW5lbmluZ3Nbb3BlbmVuaW5ncy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3ViVG9rZW4gPSBjdXJyZW50T3BlbmluZ1Rva2VuLm1hdGNoZXNbY3VycmVudE9wZW5pbmdUb2tlbi5tYXRjaGVzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50T3BlbmluZ1Rva2VuLm9wZW5Hcm91cCAmJiAoc3ViVG9rZW4ubWF0Y2hlcyA9PT0gdW5kZWZpbmVkIHx8IHN1YlRva2VuLmlzR3JvdXAgPT09IGZhbHNlICYmIHN1YlRva2VuLmlzQWx0ZXJuYXRvciA9PT0gZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RNYXRjaCA9IG9wZW5lbmluZ3MucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdE1hdGNoID0gZ3JvdXBRdWFudGlmaWVyKGN1cnJlbnRPcGVuaW5nVG9rZW4ubWF0Y2hlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TWF0Y2ggPSBncm91cFF1YW50aWZpZXIoY3VycmVudFRva2VuLm1hdGNoZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RNYXRjaC5pc0FsdGVybmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVuZW5pbmdzLnB1c2gobGFzdE1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RNYXRjaC5hbHRlcm5hdG9yR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRvciA9IG9wZW5lbmluZ3MucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RNYXRjaC5hbHRlcm5hdG9yR3JvdXAgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdG9yID0gbmV3IE1hc2tUb2tlbihmYWxzZSwgZmFsc2UsIGZhbHNlLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRvci5tYXRjaGVzLnB1c2gobGFzdE1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVuZW5pbmdzLnB1c2goYWx0ZXJuYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RNYXRjaC5vcGVuR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdE1hdGNoLm9wZW5Hcm91cCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWx0ZXJuYXRvckdyb3VwID0gbmV3IE1hc2tUb2tlbih0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRvckdyb3VwLmFsdGVybmF0b3JHcm91cCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wZW5lbmluZ3MucHVzaChhbHRlcm5hdG9yR3JvdXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgd2hpbGUgKG9wZW5lbmluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBvcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wdXNoKG9wZW5pbmdUb2tlbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50VG9rZW4ubWF0Y2hlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZlcmlmeUdyb3VwTWFya2VyKGN1cnJlbnRUb2tlbik7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tUb2tlbnMucHVzaChjdXJyZW50VG9rZW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAob3B0cy5udW1lcmljSW5wdXQgfHwgb3B0cy5pc1JUTCkge1xuICAgICAgICAgICAgICAgICAgICByZXZlcnNlVG9rZW5zKG1hc2tUb2tlbnNbMF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbWFza1Rva2VucztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwb3NpdGlvbkNvbG9yTWFzazogZnVuY3Rpb24gcG9zaXRpb25Db2xvck1hc2soaW5wdXQsIHRlbXBsYXRlKSB7XG4gICAgICAgICAgICAgICAgaW5wdXQuc3R5bGUubGVmdCA9IHRlbXBsYXRlLm9mZnNldExlZnQgKyBcInB4XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIElucHV0bWFzay5leHRlbmREZWZhdWx0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIElucHV0bWFzay5wcm90b3R5cGUuZGVmYXVsdHMsIG9wdGlvbnMpO1xuICAgICAgICB9O1xuICAgICAgICBJbnB1dG1hc2suZXh0ZW5kRGVmaW5pdGlvbnMgPSBmdW5jdGlvbihkZWZpbml0aW9uKSB7XG4gICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCBJbnB1dG1hc2sucHJvdG90eXBlLmRlZmluaXRpb25zLCBkZWZpbml0aW9uKTtcbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLmV4dGVuZEFsaWFzZXMgPSBmdW5jdGlvbihhbGlhcykge1xuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgSW5wdXRtYXNrLnByb3RvdHlwZS5hbGlhc2VzLCBhbGlhcyk7XG4gICAgICAgIH07XG4gICAgICAgIElucHV0bWFzay5mb3JtYXQgPSBmdW5jdGlvbih2YWx1ZSwgb3B0aW9ucywgbWV0YWRhdGEpIHtcbiAgICAgICAgICAgIHJldHVybiBJbnB1dG1hc2sob3B0aW9ucykuZm9ybWF0KHZhbHVlLCBtZXRhZGF0YSk7XG4gICAgICAgIH07XG4gICAgICAgIElucHV0bWFzay51bm1hc2sgPSBmdW5jdGlvbih2YWx1ZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuIElucHV0bWFzayhvcHRpb25zKS51bm1hc2tlZHZhbHVlKHZhbHVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLmlzVmFsaWQgPSBmdW5jdGlvbih2YWx1ZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuIElucHV0bWFzayhvcHRpb25zKS5pc1ZhbGlkKHZhbHVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLnJlbW92ZSA9IGZ1bmN0aW9uKGVsZW1zKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVsZW1zID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgZWxlbXMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtcykgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChlbGVtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbGVtcyA9IGVsZW1zLm5vZGVOYW1lID8gWyBlbGVtcyBdIDogZWxlbXM7XG4gICAgICAgICAgICAkLmVhY2goZWxlbXMsIGZ1bmN0aW9uKG5keCwgZWwpIHtcbiAgICAgICAgICAgICAgICBpZiAoZWwuaW5wdXRtYXNrKSBlbC5pbnB1dG1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLnNldFZhbHVlID0gZnVuY3Rpb24oZWxlbXMsIHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVsZW1zID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgZWxlbXMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtcykgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChlbGVtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbGVtcyA9IGVsZW1zLm5vZGVOYW1lID8gWyBlbGVtcyBdIDogZWxlbXM7XG4gICAgICAgICAgICAkLmVhY2goZWxlbXMsIGZ1bmN0aW9uKG5keCwgZWwpIHtcbiAgICAgICAgICAgICAgICBpZiAoZWwuaW5wdXRtYXNrKSBlbC5pbnB1dG1hc2suc2V0VmFsdWUodmFsdWUpOyBlbHNlICQoZWwpLnRyaWdnZXIoXCJzZXR2YWx1ZVwiLCBbIHZhbHVlIF0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIElucHV0bWFzay5lc2NhcGVSZWdleCA9IGZ1bmN0aW9uKHN0cikge1xuICAgICAgICAgICAgdmFyIHNwZWNpYWxzID0gWyBcIi9cIiwgXCIuXCIsIFwiKlwiLCBcIitcIiwgXCI/XCIsIFwifFwiLCBcIihcIiwgXCIpXCIsIFwiW1wiLCBcIl1cIiwgXCJ7XCIsIFwifVwiLCBcIlxcXFxcIiwgXCIkXCIsIFwiXlwiIF07XG4gICAgICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UobmV3IFJlZ0V4cChcIihcXFxcXCIgKyBzcGVjaWFscy5qb2luKFwifFxcXFxcIikgKyBcIilcIiwgXCJnaW1cIiksIFwiXFxcXCQxXCIpO1xuICAgICAgICB9O1xuICAgICAgICBJbnB1dG1hc2sua2V5Q29kZSA9IHtcbiAgICAgICAgICAgIEJBQ0tTUEFDRTogOCxcbiAgICAgICAgICAgIEJBQ0tTUEFDRV9TQUZBUkk6IDEyNyxcbiAgICAgICAgICAgIERFTEVURTogNDYsXG4gICAgICAgICAgICBET1dOOiA0MCxcbiAgICAgICAgICAgIEVORDogMzUsXG4gICAgICAgICAgICBFTlRFUjogMTMsXG4gICAgICAgICAgICBFU0NBUEU6IDI3LFxuICAgICAgICAgICAgSE9NRTogMzYsXG4gICAgICAgICAgICBJTlNFUlQ6IDQ1LFxuICAgICAgICAgICAgTEVGVDogMzcsXG4gICAgICAgICAgICBQQUdFX0RPV046IDM0LFxuICAgICAgICAgICAgUEFHRV9VUDogMzMsXG4gICAgICAgICAgICBSSUdIVDogMzksXG4gICAgICAgICAgICBTUEFDRTogMzIsXG4gICAgICAgICAgICBUQUI6IDksXG4gICAgICAgICAgICBVUDogMzgsXG4gICAgICAgICAgICBYOiA4OCxcbiAgICAgICAgICAgIENPTlRST0w6IDE3XG4gICAgICAgIH07XG4gICAgICAgIElucHV0bWFzay5kZXBlbmRlbmN5TGliID0gJDtcbiAgICAgICAgZnVuY3Rpb24gcmVzb2x2ZUFsaWFzKGFsaWFzU3RyLCBvcHRpb25zLCBvcHRzKSB7XG4gICAgICAgICAgICB2YXIgYWxpYXNEZWZpbml0aW9uID0gSW5wdXRtYXNrLnByb3RvdHlwZS5hbGlhc2VzW2FsaWFzU3RyXTtcbiAgICAgICAgICAgIGlmIChhbGlhc0RlZmluaXRpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoYWxpYXNEZWZpbml0aW9uLmFsaWFzKSByZXNvbHZlQWxpYXMoYWxpYXNEZWZpbml0aW9uLmFsaWFzLCB1bmRlZmluZWQsIG9wdHMpO1xuICAgICAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIG9wdHMsIGFsaWFzRGVmaW5pdGlvbik7XG4gICAgICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgb3B0cywgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG9wdHMubWFzayA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG9wdHMubWFzayA9IGFsaWFzU3RyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdlbmVyYXRlTWFza1NldChvcHRzLCBub2NhY2hlKSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBnZW5lcmF0ZU1hc2sobWFzaywgbWV0YWRhdGEsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVnZXhNYXNrID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKG1hc2sgPT09IG51bGwgfHwgbWFzayA9PT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICByZWdleE1hc2sgPSBvcHRzLnJlZ2V4ICE9PSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVnZXhNYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrID0gb3B0cy5yZWdleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgPSBtYXNrLnJlcGxhY2UoL14oXFxeKSguKikoXFwkKSQvLCBcIiQyXCIpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVnZXhNYXNrID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgPSBcIi4qXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1hc2subGVuZ3RoID09PSAxICYmIG9wdHMuZ3JlZWR5ID09PSBmYWxzZSAmJiBvcHRzLnJlcGVhdCAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBvcHRzLnBsYWNlaG9sZGVyID0gXCJcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG9wdHMucmVwZWF0ID4gMCB8fCBvcHRzLnJlcGVhdCA9PT0gXCIqXCIgfHwgb3B0cy5yZXBlYXQgPT09IFwiK1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXBlYXRTdGFydCA9IG9wdHMucmVwZWF0ID09PSBcIipcIiA/IDAgOiBvcHRzLnJlcGVhdCA9PT0gXCIrXCIgPyAxIDogb3B0cy5yZXBlYXQ7XG4gICAgICAgICAgICAgICAgICAgIG1hc2sgPSBvcHRzLmdyb3VwbWFya2VyWzBdICsgbWFzayArIG9wdHMuZ3JvdXBtYXJrZXJbMV0gKyBvcHRzLnF1YW50aWZpZXJtYXJrZXJbMF0gKyByZXBlYXRTdGFydCArIFwiLFwiICsgb3B0cy5yZXBlYXQgKyBvcHRzLnF1YW50aWZpZXJtYXJrZXJbMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBtYXNrc2V0RGVmaW5pdGlvbiwgbWFza2RlZktleSA9IHJlZ2V4TWFzayA/IFwicmVnZXhfXCIgKyBvcHRzLnJlZ2V4IDogb3B0cy5udW1lcmljSW5wdXQgPyBtYXNrLnNwbGl0KFwiXCIpLnJldmVyc2UoKS5qb2luKFwiXCIpIDogbWFzaztcbiAgICAgICAgICAgICAgICBpZiAoSW5wdXRtYXNrLnByb3RvdHlwZS5tYXNrc0NhY2hlW21hc2tkZWZLZXldID09PSB1bmRlZmluZWQgfHwgbm9jYWNoZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICBtYXNrc2V0RGVmaW5pdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2s6IG1hc2ssXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrVG9rZW46IElucHV0bWFzay5wcm90b3R5cGUuYW5hbHlzZU1hc2sobWFzaywgcmVnZXhNYXNrLCBvcHRzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkUG9zaXRpb25zOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgICAgIF9idWZmZXI6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGVzdHM6IHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZXM6IHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IG1ldGFkYXRhLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWFza0xlbmd0aDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgaml0T2Zmc2V0OiB7fVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBpZiAobm9jYWNoZSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgSW5wdXRtYXNrLnByb3RvdHlwZS5tYXNrc0NhY2hlW21hc2tkZWZLZXldID0gbWFza3NldERlZmluaXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrc2V0RGVmaW5pdGlvbiA9ICQuZXh0ZW5kKHRydWUsIHt9LCBJbnB1dG1hc2sucHJvdG90eXBlLm1hc2tzQ2FjaGVbbWFza2RlZktleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIG1hc2tzZXREZWZpbml0aW9uID0gJC5leHRlbmQodHJ1ZSwge30sIElucHV0bWFzay5wcm90b3R5cGUubWFza3NDYWNoZVttYXNrZGVmS2V5XSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tzZXREZWZpbml0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG1zO1xuICAgICAgICAgICAgaWYgKCQuaXNGdW5jdGlvbihvcHRzLm1hc2spKSB7XG4gICAgICAgICAgICAgICAgb3B0cy5tYXNrID0gb3B0cy5tYXNrKG9wdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCQuaXNBcnJheShvcHRzLm1hc2spKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9wdHMubWFzay5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmtlZXBTdGF0aWMgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMua2VlcFN0YXRpYyA9IFwiYXV0b1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvcHRzLm1hc2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5tYXNrW2ldLmNoYXJBdCgwKSAhPT0gb3B0cy5tYXNrWzBdLmNoYXJBdCgwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmtlZXBTdGF0aWMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFsdE1hc2sgPSBvcHRzLmdyb3VwbWFya2VyWzBdO1xuICAgICAgICAgICAgICAgICAgICAkLmVhY2gob3B0cy5pc1JUTCA/IG9wdHMubWFzay5yZXZlcnNlKCkgOiBvcHRzLm1hc2ssIGZ1bmN0aW9uKG5keCwgbXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWx0TWFzay5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0TWFzayArPSBvcHRzLmdyb3VwbWFya2VyWzFdICsgb3B0cy5hbHRlcm5hdG9ybWFya2VyICsgb3B0cy5ncm91cG1hcmtlclswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtc2subWFzayAhPT0gdW5kZWZpbmVkICYmICEkLmlzRnVuY3Rpb24obXNrLm1hc2spKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0TWFzayArPSBtc2subWFzaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0TWFzayArPSBtc2s7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBhbHRNYXNrICs9IG9wdHMuZ3JvdXBtYXJrZXJbMV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBnZW5lcmF0ZU1hc2soYWx0TWFzaywgb3B0cy5tYXNrLCBvcHRzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Ugb3B0cy5tYXNrID0gb3B0cy5tYXNrLnBvcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMubWFzayAmJiBvcHRzLm1hc2subWFzayAhPT0gdW5kZWZpbmVkICYmICEkLmlzRnVuY3Rpb24ob3B0cy5tYXNrLm1hc2spKSB7XG4gICAgICAgICAgICAgICAgbXMgPSBnZW5lcmF0ZU1hc2sob3B0cy5tYXNrLm1hc2ssIG9wdHMubWFzaywgb3B0cyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1zID0gZ2VuZXJhdGVNYXNrKG9wdHMubWFzaywgb3B0cy5tYXNrLCBvcHRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtcztcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc0lucHV0RXZlbnRTdXBwb3J0ZWQoZXZlbnROYW1lKSB7XG4gICAgICAgICAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIiksIGV2TmFtZSA9IFwib25cIiArIGV2ZW50TmFtZSwgaXNTdXBwb3J0ZWQgPSBldk5hbWUgaW4gZWw7XG4gICAgICAgICAgICBpZiAoIWlzU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICAgICAgZWwuc2V0QXR0cmlidXRlKGV2TmFtZSwgXCJyZXR1cm47XCIpO1xuICAgICAgICAgICAgICAgIGlzU3VwcG9ydGVkID0gdHlwZW9mIGVsW2V2TmFtZV0gPT09IFwiZnVuY3Rpb25cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBpc1N1cHBvcnRlZDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBtYXNrU2NvcGUoYWN0aW9uT2JqLCBtYXNrc2V0LCBvcHRzKSB7XG4gICAgICAgICAgICBtYXNrc2V0ID0gbWFza3NldCB8fCB0aGlzLm1hc2tzZXQ7XG4gICAgICAgICAgICBvcHRzID0gb3B0cyB8fCB0aGlzLm9wdHM7XG4gICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcywgZWwgPSB0aGlzLmVsLCBpc1JUTCA9IHRoaXMuaXNSVEwsIHVuZG9WYWx1ZSwgJGVsLCBza2lwS2V5UHJlc3NFdmVudCA9IGZhbHNlLCBza2lwSW5wdXRFdmVudCA9IGZhbHNlLCBpZ25vcmFibGUgPSBmYWxzZSwgbWF4TGVuZ3RoLCBtb3VzZUVudGVyID0gZmFsc2UsIGNvbG9yTWFzaywgb3JpZ2luYWxQbGFjZWhvbGRlcjtcbiAgICAgICAgICAgIHZhciBnZXRNYXNrVGVtcGxhdGUgPSBmdW5jdGlvbiBnZXRNYXNrVGVtcGxhdGUoYmFzZU9uSW5wdXQsIG1pbmltYWxQb3MsIGluY2x1ZGVNb2RlLCBub0ppdCwgY2xlYXJPcHRpb25hbFRhaWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JlZWR5ID0gb3B0cy5ncmVlZHk7XG4gICAgICAgICAgICAgICAgaWYgKGNsZWFyT3B0aW9uYWxUYWlsKSBvcHRzLmdyZWVkeSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIG1pbmltYWxQb3MgPSBtaW5pbWFsUG9zIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1hc2tUZW1wbGF0ZSA9IFtdLCBuZHhJbnRsenIsIHBvcyA9IDAsIHRlc3QsIHRlc3RQb3MsIGx2cCA9IGdldExhc3RWYWxpZFBvc2l0aW9uKCk7XG4gICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZU9uSW5wdXQgPT09IHRydWUgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RQb3MgPSBjbGVhck9wdGlvbmFsVGFpbCAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXS5tYXRjaC5vcHRpb25hbGl0eSA9PT0gdHJ1ZSAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zICsgMV0gPT09IHVuZGVmaW5lZCAmJiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10uZ2VuZXJhdGVkSW5wdXQgPT09IHRydWUgfHwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10uaW5wdXQgPT0gb3B0cy5za2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyICYmIHBvcyA+IDApID8gZGV0ZXJtaW5lVGVzdFRlbXBsYXRlKHBvcywgZ2V0VGVzdHMocG9zLCBuZHhJbnRsenIsIHBvcyAtIDEpKSA6IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9IHRlc3RQb3MubWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUZW1wbGF0ZS5wdXNoKGluY2x1ZGVNb2RlID09PSB0cnVlID8gdGVzdFBvcy5pbnB1dCA6IGluY2x1ZGVNb2RlID09PSBmYWxzZSA/IHRlc3QubmF0aXZlRGVmIDogZ2V0UGxhY2Vob2xkZXIocG9zLCB0ZXN0KSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXN0UG9zID0gZ2V0VGVzdFRlbXBsYXRlKHBvcywgbmR4SW50bHpyLCBwb3MgLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSB0ZXN0UG9zLm1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgbmR4SW50bHpyID0gdGVzdFBvcy5sb2NhdG9yLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaml0TWFza2luZyA9IG5vSml0ID09PSB0cnVlID8gZmFsc2UgOiBvcHRzLmppdE1hc2tpbmcgIT09IGZhbHNlID8gb3B0cy5qaXRNYXNraW5nIDogdGVzdC5qaXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaml0TWFza2luZyA9PT0gZmFsc2UgfHwgaml0TWFza2luZyA9PT0gdW5kZWZpbmVkIHx8IHR5cGVvZiBqaXRNYXNraW5nID09PSBcIm51bWJlclwiICYmIGlzRmluaXRlKGppdE1hc2tpbmcpICYmIGppdE1hc2tpbmcgPiBwb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrVGVtcGxhdGUucHVzaChpbmNsdWRlTW9kZSA9PT0gZmFsc2UgPyB0ZXN0Lm5hdGl2ZURlZiA6IGdldFBsYWNlaG9sZGVyKHBvcywgdGVzdCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmtlZXBTdGF0aWMgPT09IFwiYXV0b1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVzdC5uZXdCbG9ja01hcmtlciAmJiB0ZXN0LmZuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5rZWVwU3RhdGljID0gcG9zIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwb3MrKztcbiAgICAgICAgICAgICAgICB9IHdoaWxlICgobWF4TGVuZ3RoID09PSB1bmRlZmluZWQgfHwgcG9zIDwgbWF4TGVuZ3RoKSAmJiAodGVzdC5mbiAhPT0gbnVsbCB8fCB0ZXN0LmRlZiAhPT0gXCJcIikgfHwgbWluaW1hbFBvcyA+IHBvcyk7XG4gICAgICAgICAgICAgICAgaWYgKG1hc2tUZW1wbGF0ZVttYXNrVGVtcGxhdGUubGVuZ3RoIC0gMV0gPT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbWFza1RlbXBsYXRlLnBvcCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW5jbHVkZU1vZGUgIT09IGZhbHNlIHx8IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoID09PSB1bmRlZmluZWQpIGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoID0gcG9zIC0gMTtcbiAgICAgICAgICAgICAgICBvcHRzLmdyZWVkeSA9IGdyZWVkeTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWFza1RlbXBsYXRlO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldE1hc2tTZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tzZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiByZXNldE1hc2tTZXQoc29mdCkge1xuICAgICAgICAgICAgICAgIHZhciBtYXNrc2V0ID0gZ2V0TWFza1NldCgpO1xuICAgICAgICAgICAgICAgIG1hc2tzZXQuYnVmZmVyID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGlmIChzb2Z0ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tzZXQudmFsaWRQb3NpdGlvbnMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgbWFza3NldC5wID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRMYXN0VmFsaWRQb3NpdGlvbihjbG9zZXN0VG8sIHN0cmljdCwgdmFsaWRQb3NpdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgYmVmb3JlID0gLTEsIGFmdGVyID0gLTEsIHZhbGlkcyA9IHZhbGlkUG9zaXRpb25zIHx8IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucztcbiAgICAgICAgICAgICAgICBpZiAoY2xvc2VzdFRvID09PSB1bmRlZmluZWQpIGNsb3Nlc3RUbyA9IC0xO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHBvc05keCBpbiB2YWxpZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBzTmR4ID0gcGFyc2VJbnQocG9zTmR4KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbGlkc1twc05keF0gJiYgKHN0cmljdCB8fCB2YWxpZHNbcHNOZHhdLmdlbmVyYXRlZElucHV0ICE9PSB0cnVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBzTmR4IDw9IGNsb3Nlc3RUbykgYmVmb3JlID0gcHNOZHg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHNOZHggPj0gY2xvc2VzdFRvKSBhZnRlciA9IHBzTmR4O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBiZWZvcmUgPT09IC0xIHx8IGJlZm9yZSA9PSBjbG9zZXN0VG8gPyBhZnRlciA6IGFmdGVyID09IC0xID8gYmVmb3JlIDogY2xvc2VzdFRvIC0gYmVmb3JlIDwgYWZ0ZXIgLSBjbG9zZXN0VG8gPyBiZWZvcmUgOiBhZnRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldERlY2lzaW9uVGFrZXIodHN0KSB7XG4gICAgICAgICAgICAgICAgdmFyIGRlY2lzaW9uVGFrZXIgPSB0c3QubG9jYXRvclt0c3QuYWx0ZXJuYXRpb25dO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGVjaXNpb25UYWtlciA9PSBcInN0cmluZ1wiICYmIGRlY2lzaW9uVGFrZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBkZWNpc2lvblRha2VyID0gZGVjaXNpb25UYWtlci5zcGxpdChcIixcIilbMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBkZWNpc2lvblRha2VyICE9PSB1bmRlZmluZWQgPyBkZWNpc2lvblRha2VyLnRvU3RyaW5nKCkgOiBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0TG9jYXRvcih0c3QsIGFsaWduKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxvY2F0b3IgPSAodHN0LmFsdGVybmF0aW9uICE9IHVuZGVmaW5lZCA/IHRzdC5tbG9jW2dldERlY2lzaW9uVGFrZXIodHN0KV0gOiB0c3QubG9jYXRvcikuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICBpZiAobG9jYXRvciAhPT0gXCJcIikgd2hpbGUgKGxvY2F0b3IubGVuZ3RoIDwgYWxpZ24pIHtcbiAgICAgICAgICAgICAgICAgICAgbG9jYXRvciArPSBcIjBcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxvY2F0b3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBkZXRlcm1pbmVUZXN0VGVtcGxhdGUocG9zLCB0ZXN0cykge1xuICAgICAgICAgICAgICAgIHBvcyA9IHBvcyA+IDAgPyBwb3MgLSAxIDogMDtcbiAgICAgICAgICAgICAgICB2YXIgYWx0VGVzdCA9IGdldFRlc3QocG9zKSwgdGFyZ2V0TG9jYXRvciA9IGdldExvY2F0b3IoYWx0VGVzdCksIHRzdExvY2F0b3IsIGNsb3Nlc3QsIGJlc3RNYXRjaDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBuZHggPSAwOyBuZHggPCB0ZXN0cy5sZW5ndGg7IG5keCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0c3QgPSB0ZXN0c1tuZHhdO1xuICAgICAgICAgICAgICAgICAgICB0c3RMb2NhdG9yID0gZ2V0TG9jYXRvcih0c3QsIHRhcmdldExvY2F0b3IubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RhbmNlID0gTWF0aC5hYnModHN0TG9jYXRvciAtIHRhcmdldExvY2F0b3IpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2xvc2VzdCA9PT0gdW5kZWZpbmVkIHx8IHRzdExvY2F0b3IgIT09IFwiXCIgJiYgZGlzdGFuY2UgPCBjbG9zZXN0IHx8IGJlc3RNYXRjaCAmJiAhb3B0cy5ncmVlZHkgJiYgYmVzdE1hdGNoLm1hdGNoLm9wdGlvbmFsaXR5ICYmIGJlc3RNYXRjaC5tYXRjaC5uZXdCbG9ja01hcmtlciA9PT0gXCJtYXN0ZXJcIiAmJiAoIXRzdC5tYXRjaC5vcHRpb25hbGl0eSB8fCAhdHN0Lm1hdGNoLm5ld0Jsb2NrTWFya2VyKSB8fCBiZXN0TWF0Y2ggJiYgYmVzdE1hdGNoLm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciAmJiAhdHN0Lm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VzdCA9IGRpc3RhbmNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVzdE1hdGNoID0gdHN0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBiZXN0TWF0Y2g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRUZXN0VGVtcGxhdGUocG9zLCBuZHhJbnRsenIsIHRzdFBzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdIHx8IGRldGVybWluZVRlc3RUZW1wbGF0ZShwb3MsIGdldFRlc3RzKHBvcywgbmR4SW50bHpyID8gbmR4SW50bHpyLnNsaWNlKCkgOiBuZHhJbnRsenIsIHRzdFBzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRUZXN0KHBvcywgdGVzdHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gKHRlc3RzIHx8IGdldFRlc3RzKHBvcykpWzBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gcG9zaXRpb25DYW5NYXRjaERlZmluaXRpb24ocG9zLCBkZWYpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsaWQgPSBmYWxzZSwgdGVzdHMgPSBnZXRUZXN0cyhwb3MpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHRuZHggPSAwOyB0bmR4IDwgdGVzdHMubGVuZ3RoOyB0bmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RzW3RuZHhdLm1hdGNoICYmIHRlc3RzW3RuZHhdLm1hdGNoLmRlZiA9PT0gZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRUZXN0cyhwb3MsIG5keEludGx6ciwgdHN0UHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbWFza1Rva2VucyA9IGdldE1hc2tTZXQoKS5tYXNrVG9rZW4sIHRlc3RQb3MgPSBuZHhJbnRsenIgPyB0c3RQcyA6IDAsIG5keEluaXRpYWxpemVyID0gbmR4SW50bHpyID8gbmR4SW50bHpyLnNsaWNlKCkgOiBbIDAgXSwgbWF0Y2hlcyA9IFtdLCBpbnNlcnRTdG9wID0gZmFsc2UsIGxhdGVzdE1hdGNoLCBjYWNoZURlcGVuZGVuY3kgPSBuZHhJbnRsenIgPyBuZHhJbnRsenIuam9pbihcIlwiKSA6IFwiXCI7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gcmVzb2x2ZVRlc3RGcm9tVG9rZW4obWFza1Rva2VuLCBuZHhJbml0aWFsaXplciwgbG9vcE5keCwgcXVhbnRpZmllclJlY3Vyc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlTWF0Y2gobWF0Y2gsIGxvb3BOZHgsIHF1YW50aWZpZXJSZWN1cnNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBpc0ZpcnN0TWF0Y2gobGF0ZXN0TWF0Y2gsIHRva2VuR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmlyc3RNYXRjaCA9ICQuaW5BcnJheShsYXRlc3RNYXRjaCwgdG9rZW5Hcm91cC5tYXRjaGVzKSA9PT0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWZpcnN0TWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKHRva2VuR3JvdXAubWF0Y2hlcywgZnVuY3Rpb24obmR4LCBtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmlzUXVhbnRpZmllciA9PT0gdHJ1ZSkgZmlyc3RNYXRjaCA9IGlzRmlyc3RNYXRjaChsYXRlc3RNYXRjaCwgdG9rZW5Hcm91cC5tYXRjaGVzW25keCAtIDFdKTsgZWxzZSBpZiAobWF0Y2guaGFzT3duUHJvcGVydHkoXCJtYXRjaGVzXCIpKSBmaXJzdE1hdGNoID0gaXNGaXJzdE1hdGNoKGxhdGVzdE1hdGNoLCBtYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmlyc3RNYXRjaCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpcnN0TWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiByZXNvbHZlTmR4SW5pdGlhbGl6ZXIocG9zLCBhbHRlcm5hdGVOZHgsIHRhcmdldEFsdGVybmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJlc3RNYXRjaCwgaW5kZXhQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS50ZXN0c1twb3NdIHx8IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChnZXRNYXNrU2V0KCkudGVzdHNbcG9zXSB8fCBbIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdIF0sIGZ1bmN0aW9uKG5keCwgbG1udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxtbnQubWxvY1thbHRlcm5hdGVOZHhdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVzdE1hdGNoID0gbG1udDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWx0ZXJuYXRpb24gPSB0YXJnZXRBbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkID8gdGFyZ2V0QWx0ZXJuYXRpb24gOiBsbW50LmFsdGVybmF0aW9uLCBuZHhQb3MgPSBsbW50LmxvY2F0b3JbYWx0ZXJuYXRpb25dICE9PSB1bmRlZmluZWQgPyBsbW50LmxvY2F0b3JbYWx0ZXJuYXRpb25dLnRvU3RyaW5nKCkuaW5kZXhPZihhbHRlcm5hdGVOZHgpIDogLTE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGluZGV4UG9zID09PSB1bmRlZmluZWQgfHwgbmR4UG9zIDwgaW5kZXhQb3MpICYmIG5keFBvcyAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSBsbW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4UG9zID0gbmR4UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJlc3RNYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYmVzdE1hdGNoQWx0SW5kZXggPSBiZXN0TWF0Y2gubG9jYXRvcltiZXN0TWF0Y2guYWx0ZXJuYXRpb25dO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbG9jYXRvciA9IGJlc3RNYXRjaC5tbG9jW2FsdGVybmF0ZU5keF0gfHwgYmVzdE1hdGNoLm1sb2NbYmVzdE1hdGNoQWx0SW5kZXhdIHx8IGJlc3RNYXRjaC5sb2NhdG9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbG9jYXRvci5zbGljZSgodGFyZ2V0QWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCA/IHRhcmdldEFsdGVybmF0aW9uIDogYmVzdE1hdGNoLmFsdGVybmF0aW9uKSArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0YXJnZXRBbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkID8gcmVzb2x2ZU5keEluaXRpYWxpemVyKHBvcywgYWx0ZXJuYXRlTmR4KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBpc1N1YnNldE9mKHNvdXJjZSwgdGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gZXhwYW5kKHBhdHRlcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGV4cGFuZGVkID0gW10sIHN0YXJ0LCBlbmQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gcGF0dGVybi5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXR0ZXJuLmNoYXJBdChpKSA9PT0gXCItXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBwYXR0ZXJuLmNoYXJDb2RlQXQoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlICgrK3N0YXJ0IDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGFuZGVkLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShzdGFydCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQgPSBwYXR0ZXJuLmNoYXJDb2RlQXQoaSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWQucHVzaChwYXR0ZXJuLmNoYXJBdChpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGFuZGVkLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnJlZ2V4ICYmIHNvdXJjZS5tYXRjaC5mbiAhPT0gbnVsbCAmJiB0YXJnZXQubWF0Y2guZm4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGFuZCh0YXJnZXQubWF0Y2guZGVmLnJlcGxhY2UoL1tcXFtcXF1dL2csIFwiXCIpKS5pbmRleE9mKGV4cGFuZChzb3VyY2UubWF0Y2guZGVmLnJlcGxhY2UoL1tcXFtcXF1dL2csIFwiXCIpKSkgIT09IC0xO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc291cmNlLm1hdGNoLmRlZiA9PT0gdGFyZ2V0Lm1hdGNoLm5hdGl2ZURlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHN0YXRpY0Nhbk1hdGNoRGVmaW5pdGlvbihzb3VyY2UsIHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzbG9jID0gc291cmNlLmxvY2F0b3Iuc2xpY2Uoc291cmNlLmFsdGVybmF0aW9uKS5qb2luKFwiXCIpLCB0bG9jID0gdGFyZ2V0LmxvY2F0b3Iuc2xpY2UodGFyZ2V0LmFsdGVybmF0aW9uKS5qb2luKFwiXCIpLCBjYW5NYXRjaCA9IHNsb2MgPT0gdGxvYztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW5NYXRjaCA9IGNhbk1hdGNoICYmIHNvdXJjZS5tYXRjaC5mbiA9PT0gbnVsbCAmJiB0YXJnZXQubWF0Y2guZm4gIT09IG51bGwgPyB0YXJnZXQubWF0Y2guZm4udGVzdChzb3VyY2UubWF0Y2guZGVmLCBnZXRNYXNrU2V0KCksIHBvcywgZmFsc2UsIG9wdHMsIGZhbHNlKSA6IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYW5NYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHNldE1lcmdlTG9jYXRvcnModGFyZ2V0TWF0Y2gsIGFsdE1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsdE1hdGNoID09PSB1bmRlZmluZWQgfHwgdGFyZ2V0TWF0Y2guYWx0ZXJuYXRpb24gPT09IGFsdE1hdGNoLmFsdGVybmF0aW9uICYmIHRhcmdldE1hdGNoLmxvY2F0b3JbdGFyZ2V0TWF0Y2guYWx0ZXJuYXRpb25dLnRvU3RyaW5nKCkuaW5kZXhPZihhbHRNYXRjaC5sb2NhdG9yW2FsdE1hdGNoLmFsdGVybmF0aW9uXSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldE1hdGNoLm1sb2MgPSB0YXJnZXRNYXRjaC5tbG9jIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbG9jTmR4ID0gdGFyZ2V0TWF0Y2gubG9jYXRvclt0YXJnZXRNYXRjaC5hbHRlcm5hdGlvbl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsb2NOZHggPT09IHVuZGVmaW5lZCkgdGFyZ2V0TWF0Y2guYWx0ZXJuYXRpb24gPSB1bmRlZmluZWQ7IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBsb2NOZHggPT09IFwic3RyaW5nXCIpIGxvY05keCA9IGxvY05keC5zcGxpdChcIixcIilbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFyZ2V0TWF0Y2gubWxvY1tsb2NOZHhdID09PSB1bmRlZmluZWQpIHRhcmdldE1hdGNoLm1sb2NbbG9jTmR4XSA9IHRhcmdldE1hdGNoLmxvY2F0b3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHRNYXRjaCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbmR4IGluIGFsdE1hdGNoLm1sb2MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBuZHggPT09IFwic3RyaW5nXCIpIG5keCA9IG5keC5zcGxpdChcIixcIilbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0YXJnZXRNYXRjaC5tbG9jW25keF0gPT09IHVuZGVmaW5lZCkgdGFyZ2V0TWF0Y2gubWxvY1tuZHhdID0gYWx0TWF0Y2gubWxvY1tuZHhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRNYXRjaC5sb2NhdG9yW3RhcmdldE1hdGNoLmFsdGVybmF0aW9uXSA9IE9iamVjdC5rZXlzKHRhcmdldE1hdGNoLm1sb2MpLmpvaW4oXCIsXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RQb3MgPiA1MDAgJiYgcXVhbnRpZmllclJlY3Vyc2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiSW5wdXRtYXNrOiBUaGVyZSBpcyBwcm9iYWJseSBhbiBlcnJvciBpbiB5b3VyIG1hc2sgZGVmaW5pdGlvbiBvciBpbiB0aGUgY29kZS4gQ3JlYXRlIGFuIGlzc3VlIG9uIGdpdGh1YiB3aXRoIGFuIGV4YW1wbGUgb2YgdGhlIG1hc2sgeW91IGFyZSB1c2luZy4gXCIgKyBnZXRNYXNrU2V0KCkubWFzaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0UG9zID09PSBwb3MgJiYgbWF0Y2gubWF0Y2hlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2g6IG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhdG9yOiBsb29wTmR4LnJldmVyc2UoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2Q6IGNhY2hlRGVwZW5kZW5jeSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWxvYzoge31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2gubWF0Y2hlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmlzR3JvdXAgJiYgcXVhbnRpZmllclJlY3Vyc2UgIT09IG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gaGFuZGxlTWF0Y2gobWFza1Rva2VuLm1hdGNoZXNbJC5pbkFycmF5KG1hdGNoLCBtYXNrVG9rZW4ubWF0Y2hlcykgKyAxXSwgbG9vcE5keCwgcXVhbnRpZmllclJlY3Vyc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2guaXNPcHRpb25hbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3B0aW9uYWxUb2tlbiA9IG1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IHJlc29sdmVUZXN0RnJvbVRva2VuKG1hdGNoLCBuZHhJbml0aWFsaXplciwgbG9vcE5keCwgcXVhbnRpZmllclJlY3Vyc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChtYXRjaGVzLCBmdW5jdGlvbihuZHgsIG10Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdGNoLm1hdGNoLm9wdGlvbmFsaXR5ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0ZXN0TWF0Y2ggPSBtYXRjaGVzW21hdGNoZXMubGVuZ3RoIC0gMV0ubWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocXVhbnRpZmllclJlY3Vyc2UgPT09IHVuZGVmaW5lZCAmJiBpc0ZpcnN0TWF0Y2gobGF0ZXN0TWF0Y2gsIG9wdGlvbmFsVG9rZW4pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0U3RvcCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IHBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2guaXNBbHRlcm5hdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRlcm5hdGVUb2tlbiA9IG1hdGNoLCBtYWx0ZXJuYXRlTWF0Y2hlcyA9IFtdLCBtYWx0TWF0Y2hlcywgY3VycmVudE1hdGNoZXMgPSBtYXRjaGVzLnNsaWNlKCksIGxvb3BOZHhDbnQgPSBsb29wTmR4Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdEluZGV4ID0gbmR4SW5pdGlhbGl6ZXIubGVuZ3RoID4gMCA/IG5keEluaXRpYWxpemVyLnNoaWZ0KCkgOiAtMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsdEluZGV4ID09PSAtMSB8fCB0eXBlb2YgYWx0SW5kZXggPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjdXJyZW50UG9zID0gdGVzdFBvcywgbmR4SW5pdGlhbGl6ZXJDbG9uZSA9IG5keEluaXRpYWxpemVyLnNsaWNlKCksIGFsdEluZGV4QXJyID0gW10sIGFtbmR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhbHRJbmRleCA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0SW5kZXhBcnIgPSBhbHRJbmRleC5zcGxpdChcIixcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoYW1uZHggPSAwOyBhbW5keCA8IGFsdGVybmF0ZVRva2VuLm1hdGNoZXMubGVuZ3RoOyBhbW5keCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdEluZGV4QXJyLnB1c2goYW1uZHgudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS5leGNsdWRlc1twb3NdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdEluZGV4QXJyQ2xvbmUgPSBhbHRJbmRleEFyci5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBlbCA9IGdldE1hc2tTZXQoKS5leGNsdWRlc1twb3NdLmxlbmd0aDsgaSA8IGVsOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0SW5kZXhBcnIuc3BsaWNlKGFsdEluZGV4QXJyLmluZGV4T2YoZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW3Bvc11baV0udG9TdHJpbmcoKSksIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWx0SW5kZXhBcnIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5leGNsdWRlc1twb3NdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRJbmRleEFyciA9IGFsdEluZGV4QXJyQ2xvbmU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMua2VlcFN0YXRpYyA9PT0gdHJ1ZSB8fCBpc0Zpbml0ZShwYXJzZUludChvcHRzLmtlZXBTdGF0aWMpKSAmJiBjdXJyZW50UG9zID49IG9wdHMua2VlcFN0YXRpYykgYWx0SW5kZXhBcnIgPSBhbHRJbmRleEFyci5zbGljZSgwLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB1bk1hdGNoZWRBbHRlcm5hdGlvbiA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbmR4ID0gMDsgbmR4IDwgYWx0SW5kZXhBcnIubGVuZ3RoOyBuZHgrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFtbmR4ID0gcGFyc2VJbnQoYWx0SW5kZXhBcnJbbmR4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5keEluaXRpYWxpemVyID0gdHlwZW9mIGFsdEluZGV4ID09PSBcInN0cmluZ1wiID8gcmVzb2x2ZU5keEluaXRpYWxpemVyKHRlc3RQb3MsIGFtbmR4LCBsb29wTmR4Q250KSB8fCBuZHhJbml0aWFsaXplckNsb25lLnNsaWNlKCkgOiBuZHhJbml0aWFsaXplckNsb25lLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsdGVybmF0ZVRva2VuLm1hdGNoZXNbYW1uZHhdICYmIGhhbmRsZU1hdGNoKGFsdGVybmF0ZVRva2VuLm1hdGNoZXNbYW1uZHhdLCBbIGFtbmR4IF0uY29uY2F0KGxvb3BOZHgpLCBxdWFudGlmaWVyUmVjdXJzZSkpIG1hdGNoID0gdHJ1ZTsgZWxzZSBpZiAobmR4ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuTWF0Y2hlZEFsdGVybmF0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsdE1hdGNoZXMgPSBtYXRjaGVzLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IGN1cnJlbnRQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG5keDEgPSAwOyBuZHgxIDwgbWFsdE1hdGNoZXMubGVuZ3RoOyBuZHgxKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdE1hdGNoID0gbWFsdE1hdGNoZXNbbmR4MV0sIGRyb3BNYXRjaCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRNYXRjaC5tYXRjaC5qaXQgPSBhbHRNYXRjaC5tYXRjaC5qaXQgfHwgdW5NYXRjaGVkQWx0ZXJuYXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdE1hdGNoLmFsdGVybmF0aW9uID0gYWx0TWF0Y2guYWx0ZXJuYXRpb24gfHwgbG9vcE5keENudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0TWVyZ2VMb2NhdG9ycyhhbHRNYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG5keDIgPSAwOyBuZHgyIDwgbWFsdGVybmF0ZU1hdGNoZXMubGVuZ3RoOyBuZHgyKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRNYXRjaDIgPSBtYWx0ZXJuYXRlTWF0Y2hlc1tuZHgyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYWx0SW5kZXggIT09IFwic3RyaW5nXCIgfHwgYWx0TWF0Y2guYWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCAmJiAkLmluQXJyYXkoYWx0TWF0Y2gubG9jYXRvclthbHRNYXRjaC5hbHRlcm5hdGlvbl0udG9TdHJpbmcoKSwgYWx0SW5kZXhBcnIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHRNYXRjaC5tYXRjaC5uYXRpdmVEZWYgPT09IGFsdE1hdGNoMi5tYXRjaC5uYXRpdmVEZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJvcE1hdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0TWVyZ2VMb2NhdG9ycyhhbHRNYXRjaDIsIGFsdE1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1N1YnNldE9mKGFsdE1hdGNoLCBhbHRNYXRjaDIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXRNZXJnZUxvY2F0b3JzKGFsdE1hdGNoLCBhbHRNYXRjaDIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wTWF0Y2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsdGVybmF0ZU1hdGNoZXMuc3BsaWNlKG1hbHRlcm5hdGVNYXRjaGVzLmluZGV4T2YoYWx0TWF0Y2gyKSwgMCwgYWx0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNTdWJzZXRPZihhbHRNYXRjaDIsIGFsdE1hdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRNZXJnZUxvY2F0b3JzKGFsdE1hdGNoMiwgYWx0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXRpY0Nhbk1hdGNoRGVmaW5pdGlvbihhbHRNYXRjaCwgYWx0TWF0Y2gyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2V0TWVyZ2VMb2NhdG9ycyhhbHRNYXRjaCwgYWx0TWF0Y2gyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJvcE1hdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbHRlcm5hdGVNYXRjaGVzLnNwbGljZShtYWx0ZXJuYXRlTWF0Y2hlcy5pbmRleE9mKGFsdE1hdGNoMiksIDAsIGFsdE1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkcm9wTWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbHRlcm5hdGVNYXRjaGVzLnB1c2goYWx0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IGN1cnJlbnRNYXRjaGVzLmNvbmNhdChtYWx0ZXJuYXRlTWF0Y2hlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0UG9zID0gcG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0U3RvcCA9IG1hdGNoZXMubGVuZ3RoID4gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gbWFsdGVybmF0ZU1hdGNoZXMubGVuZ3RoID4gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5keEluaXRpYWxpemVyID0gbmR4SW5pdGlhbGl6ZXJDbG9uZS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgbWF0Y2ggPSBoYW5kbGVNYXRjaChhbHRlcm5hdGVUb2tlbi5tYXRjaGVzW2FsdEluZGV4XSB8fCBtYXNrVG9rZW4ubWF0Y2hlc1thbHRJbmRleF0sIFsgYWx0SW5kZXggXS5jb25jYXQobG9vcE5keCksIHF1YW50aWZpZXJSZWN1cnNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoLmlzUXVhbnRpZmllciAmJiBxdWFudGlmaWVyUmVjdXJzZSAhPT0gbWFza1Rva2VuLm1hdGNoZXNbJC5pbkFycmF5KG1hdGNoLCBtYXNrVG9rZW4ubWF0Y2hlcykgLSAxXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcXQgPSBtYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcW5keCA9IG5keEluaXRpYWxpemVyLmxlbmd0aCA+IDAgPyBuZHhJbml0aWFsaXplci5zaGlmdCgpIDogMDsgcW5keCA8IChpc05hTihxdC5xdWFudGlmaWVyLm1heCkgPyBxbmR4ICsgMSA6IHF0LnF1YW50aWZpZXIubWF4KSAmJiB0ZXN0UG9zIDw9IHBvczsgcW5keCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG9rZW5Hcm91cCA9IG1hc2tUb2tlbi5tYXRjaGVzWyQuaW5BcnJheShxdCwgbWFza1Rva2VuLm1hdGNoZXMpIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IGhhbmRsZU1hdGNoKHRva2VuR3JvdXAsIFsgcW5keCBdLmNvbmNhdChsb29wTmR4KSwgdG9rZW5Hcm91cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRlc3RNYXRjaCA9IG1hdGNoZXNbbWF0Y2hlcy5sZW5ndGggLSAxXS5tYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRlc3RNYXRjaC5vcHRpb25hbFF1YW50aWZpZXIgPSBxbmR4ID49IHF0LnF1YW50aWZpZXIubWluO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdGVzdE1hdGNoLmppdCA9IChxbmR4IHx8IDEpICogdG9rZW5Hcm91cC5tYXRjaGVzLmluZGV4T2YobGF0ZXN0TWF0Y2gpID49IHF0LnF1YW50aWZpZXIuaml0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXRlc3RNYXRjaC5vcHRpb25hbFF1YW50aWZpZXIgJiYgaXNGaXJzdE1hdGNoKGxhdGVzdE1hdGNoLCB0b2tlbkdyb3VwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRTdG9wID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IHBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXRlc3RNYXRjaC5qaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLmppdE9mZnNldFtwb3NdID0gdG9rZW5Hcm91cC5tYXRjaGVzLmluZGV4T2YobGF0ZXN0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gcmVzb2x2ZVRlc3RGcm9tVG9rZW4obWF0Y2gsIG5keEluaXRpYWxpemVyLCBsb29wTmR4LCBxdWFudGlmaWVyUmVjdXJzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0UG9zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgdG5keCA9IG5keEluaXRpYWxpemVyLmxlbmd0aCA+IDAgPyBuZHhJbml0aWFsaXplci5zaGlmdCgpIDogMDsgdG5keCA8IG1hc2tUb2tlbi5tYXRjaGVzLmxlbmd0aDsgdG5keCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFza1Rva2VuLm1hdGNoZXNbdG5keF0uaXNRdWFudGlmaWVyICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gaGFuZGxlTWF0Y2gobWFza1Rva2VuLm1hdGNoZXNbdG5keF0sIFsgdG5keCBdLmNvbmNhdChsb29wTmR4KSwgcXVhbnRpZmllclJlY3Vyc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCAmJiB0ZXN0UG9zID09PSBwb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGVzdFBvcyA+IHBvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gbWVyZ2VMb2NhdG9ycyhwb3MsIHRlc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsb2NhdG9yID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmICghJC5pc0FycmF5KHRlc3RzKSkgdGVzdHMgPSBbIHRlc3RzIF07XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVzdHNbMF0uYWx0ZXJuYXRpb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2F0b3IgPSBkZXRlcm1pbmVUZXN0VGVtcGxhdGUocG9zLCB0ZXN0cy5zbGljZSgpKS5sb2NhdG9yLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxvY2F0b3IubGVuZ3RoID09PSAwKSBsb2NhdG9yID0gdGVzdHNbMF0ubG9jYXRvci5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2godGVzdHMsIGZ1bmN0aW9uKG5keCwgdHN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0c3QuZGVmICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobG9jYXRvci5sZW5ndGggPT09IDApIGxvY2F0b3IgPSB0c3QubG9jYXRvci5zbGljZSgpOyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxvY2F0b3IubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRzdC5sb2NhdG9yW2ldICYmIGxvY2F0b3JbaV0udG9TdHJpbmcoKS5pbmRleE9mKHRzdC5sb2NhdG9yW2ldKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2F0b3JbaV0gKz0gXCIsXCIgKyB0c3QubG9jYXRvcltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBsb2NhdG9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocG9zID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5keEludGx6ciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNQb3MgPSBwb3MgLSAxLCB0ZXN0O1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCh0ZXN0ID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3ByZXZpb3VzUG9zXSB8fCBnZXRNYXNrU2V0KCkudGVzdHNbcHJldmlvdXNQb3NdKSA9PT0gdW5kZWZpbmVkICYmIHByZXZpb3VzUG9zID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1Bvcy0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3QgIT09IHVuZGVmaW5lZCAmJiBwcmV2aW91c1BvcyA+IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmR4SW5pdGlhbGl6ZXIgPSBtZXJnZUxvY2F0b3JzKHByZXZpb3VzUG9zLCB0ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZURlcGVuZGVuY3kgPSBuZHhJbml0aWFsaXplci5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RQb3MgPSBwcmV2aW91c1BvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnRlc3RzW3Bvc10gJiYgZ2V0TWFza1NldCgpLnRlc3RzW3Bvc11bMF0uY2QgPT09IGNhY2hlRGVwZW5kZW5jeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdldE1hc2tTZXQoKS50ZXN0c1twb3NdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG10bmR4ID0gbmR4SW5pdGlhbGl6ZXIuc2hpZnQoKTsgbXRuZHggPCBtYXNrVG9rZW5zLmxlbmd0aDsgbXRuZHgrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gcmVzb2x2ZVRlc3RGcm9tVG9rZW4obWFza1Rva2Vuc1ttdG5keF0sIG5keEluaXRpYWxpemVyLCBbIG10bmR4IF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoICYmIHRlc3RQb3MgPT09IHBvcyB8fCB0ZXN0UG9zID4gcG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoZXMubGVuZ3RoID09PSAwIHx8IGluc2VydFN0b3ApIHtcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm46IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxpdHk6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWY6IFwiXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBsb2NhdG9yOiBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1sb2M6IHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgY2Q6IGNhY2hlRGVwZW5kZW5jeVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG5keEludGx6ciAhPT0gdW5kZWZpbmVkICYmIGdldE1hc2tTZXQoKS50ZXN0c1twb3NdKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh0cnVlLCBbXSwgbWF0Y2hlcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS50ZXN0c1twb3NdID0gJC5leHRlbmQodHJ1ZSwgW10sIG1hdGNoZXMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBnZXRNYXNrU2V0KCkudGVzdHNbcG9zXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldEJ1ZmZlclRlbXBsYXRlKCkge1xuICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkuX2J1ZmZlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5fYnVmZmVyID0gZ2V0TWFza1RlbXBsYXRlKGZhbHNlLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS5idWZmZXIgPT09IHVuZGVmaW5lZCkgZ2V0TWFza1NldCgpLmJ1ZmZlciA9IGdldE1hc2tTZXQoKS5fYnVmZmVyLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBnZXRNYXNrU2V0KCkuX2J1ZmZlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldEJ1ZmZlcihub0NhY2hlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS5idWZmZXIgPT09IHVuZGVmaW5lZCB8fCBub0NhY2hlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5idWZmZXIgPSBnZXRNYXNrVGVtcGxhdGUodHJ1ZSwgZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkuX2J1ZmZlciA9PT0gdW5kZWZpbmVkKSBnZXRNYXNrU2V0KCkuX2J1ZmZlciA9IGdldE1hc2tTZXQoKS5idWZmZXIuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldE1hc2tTZXQoKS5idWZmZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiByZWZyZXNoRnJvbUJ1ZmZlcihzdGFydCwgZW5kLCBidWZmZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgaSwgcDtcbiAgICAgICAgICAgICAgICBpZiAoc3RhcnQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzZXRNYXNrU2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgZW5kID0gYnVmZmVyLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHAgPSBzdGFydDtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJ1ZmZlcltpXSAhPT0gb3B0cy5za2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsUmVzdWx0ID0gaXNWYWxpZChwLCBidWZmZXJbaV0sIHRydWUsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbFJlc3VsdCAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcCA9IHZhbFJlc3VsdC5jYXJldCAhPT0gdW5kZWZpbmVkID8gdmFsUmVzdWx0LmNhcmV0IDogdmFsUmVzdWx0LnBvcyArIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBjYXNpbmcoZWxlbSwgdGVzdCwgcG9zKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChvcHRzLmNhc2luZyB8fCB0ZXN0LmNhc2luZykge1xuICAgICAgICAgICAgICAgICAgY2FzZSBcInVwcGVyXCI6XG4gICAgICAgICAgICAgICAgICAgIGVsZW0gPSBlbGVtLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICBjYXNlIFwibG93ZXJcIjpcbiAgICAgICAgICAgICAgICAgICAgZWxlbSA9IGVsZW0udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0aXRsZVwiOlxuICAgICAgICAgICAgICAgICAgICB2YXIgcG9zQmVmb3JlID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocG9zID09PSAwIHx8IHBvc0JlZm9yZSAmJiBwb3NCZWZvcmUuaW5wdXQgPT09IFN0cmluZy5mcm9tQ2hhckNvZGUoSW5wdXRtYXNrLmtleUNvZGUuU1BBQ0UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtID0gZWxlbS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbSA9IGVsZW0udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaXNGdW5jdGlvbihvcHRzLmNhc2luZykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MucHVzaChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbSA9IG9wdHMuY2FzaW5nLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gY2hlY2tBbHRlcm5hdGlvbk1hdGNoKGFsdEFycjEsIGFsdEFycjIsIG5hKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFsdEFyckMgPSBvcHRzLmdyZWVkeSA/IGFsdEFycjIgOiBhbHRBcnIyLnNsaWNlKDAsIDEpLCBpc01hdGNoID0gZmFsc2UsIG5hQXJyID0gbmEgIT09IHVuZGVmaW5lZCA/IG5hLnNwbGl0KFwiLFwiKSA6IFtdLCBuYU5keDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hQXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgobmFOZHggPSBhbHRBcnIxLmluZGV4T2YobmFBcnJbaV0pKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsdEFycjEuc3BsaWNlKG5hTmR4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhbG5keCA9IDA7IGFsbmR4IDwgYWx0QXJyMS5sZW5ndGg7IGFsbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaW5BcnJheShhbHRBcnIxW2FsbmR4XSwgYWx0QXJyQykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc01hdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBpc01hdGNoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gYWx0ZXJuYXRlKHBvcywgYywgc3RyaWN0LCBmcm9tU2V0VmFsaWQsIHJBbHRQb3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsaWRQc0Nsb25lID0gJC5leHRlbmQodHJ1ZSwge30sIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucyksIGxhc3RBbHQsIGFsdGVybmF0aW9uLCBpc1ZhbGlkUnNsdCA9IGZhbHNlLCBhbHRQb3MsIHByZXZBbHRQb3MsIGksIHZhbGlkUG9zLCBkZWNpc2lvblBvcywgbEFsdFBvcyA9IHJBbHRQb3MgIT09IHVuZGVmaW5lZCA/IHJBbHRQb3MgOiBnZXRMYXN0VmFsaWRQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmIChsQWx0UG9zID09PSAtMSAmJiByQWx0UG9zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgbGFzdEFsdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHByZXZBbHRQb3MgPSBnZXRUZXN0KGxhc3RBbHQpO1xuICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdGlvbiA9IHByZXZBbHRQb3MuYWx0ZXJuYXRpb247XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICg7bEFsdFBvcyA+PSAwOyBsQWx0UG9zLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsdFBvcyA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tsQWx0UG9zXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHRQb3MgJiYgYWx0UG9zLmFsdGVybmF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJldkFsdFBvcyAmJiBwcmV2QWx0UG9zLmxvY2F0b3JbYWx0UG9zLmFsdGVybmF0aW9uXSAhPT0gYWx0UG9zLmxvY2F0b3JbYWx0UG9zLmFsdGVybmF0aW9uXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEFsdCA9IGxBbHRQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRpb24gPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbGFzdEFsdF0uYWx0ZXJuYXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldkFsdFBvcyA9IGFsdFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBkZWNpc2lvblBvcyA9IHBhcnNlSW50KGxhc3RBbHQpO1xuICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkuZXhjbHVkZXNbZGVjaXNpb25Qb3NdID0gZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXSB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvcyAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXS5wdXNoKGdldERlY2lzaW9uVGFrZXIocHJldkFsdFBvcykpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWxpZElucHV0c0Nsb25lID0gW10sIHN0YXRpY0lucHV0c0JlZm9yZVBvcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IGRlY2lzaW9uUG9zOyBpIDwgZ2V0TGFzdFZhbGlkUG9zaXRpb24odW5kZWZpbmVkLCB0cnVlKSArIDE7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRQb3MgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsaWRQb3MgJiYgdmFsaWRQb3MuZ2VuZXJhdGVkSW5wdXQgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZElucHV0c0Nsb25lLnB1c2godmFsaWRQb3MuaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpIDwgcG9zKSBzdGF0aWNJbnB1dHNCZWZvcmVQb3MrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGdldE1hc2tTZXQoKS5leGNsdWRlc1tkZWNpc2lvblBvc10gJiYgZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXS5sZW5ndGggPCAxMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBvc09mZnNldCA9IHN0YXRpY0lucHV0c0JlZm9yZVBvcyAqIC0xLCB2YWxpZElucHV0cyA9IHZhbGlkSW5wdXRzQ2xvbmUuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS50ZXN0c1tkZWNpc2lvblBvc10gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkUnNsdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAodmFsaWRJbnB1dHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHZhbGlkSW5wdXRzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEoaXNWYWxpZFJzbHQgPSBpc1ZhbGlkKGdldExhc3RWYWxpZFBvc2l0aW9uKHVuZGVmaW5lZCwgdHJ1ZSkgKyAxLCBpbnB1dCwgZmFsc2UsIGZyb21TZXRWYWxpZCwgdHJ1ZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkUnNsdCAmJiBjICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGFyZ2V0THZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24ocG9zKSArIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gZGVjaXNpb25Qb3M7IGkgPCBnZXRMYXN0VmFsaWRQb3NpdGlvbigpICsgMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkUG9zID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHZhbGlkUG9zID09PSB1bmRlZmluZWQgfHwgdmFsaWRQb3MubWF0Y2guZm4gPT0gbnVsbCkgJiYgaSA8IHBvcyArIHBvc09mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zT2Zmc2V0Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zICsgcG9zT2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWRSc2x0ID0gaXNWYWxpZChwb3MgPiB0YXJnZXRMdnAgPyB0YXJnZXRMdnAgOiBwb3MsIGMsIHN0cmljdCwgZnJvbVNldFZhbGlkLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNWYWxpZFJzbHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2QWx0UG9zID0gZ2V0VGVzdChkZWNpc2lvblBvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zID0gJC5leHRlbmQodHJ1ZSwge30sIHZhbGlkUHNDbG9uZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS5leGNsdWRlc1tkZWNpc2lvblBvc10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRlY2lzaW9uVGFrZXIgPSBnZXREZWNpc2lvblRha2VyKHByZXZBbHRQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXS5pbmRleE9mKGRlY2lzaW9uVGFrZXIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZFJzbHQgPSBhbHRlcm5hdGUocG9zLCBjLCBzdHJpY3QsIGZyb21TZXRWYWxpZCwgZGVjaXNpb25Qb3MgLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5leGNsdWRlc1tkZWNpc2lvblBvc10ucHVzaChkZWNpc2lvblRha2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gZGVjaXNpb25Qb3M7IGkgPCBnZXRMYXN0VmFsaWRQb3NpdGlvbih1bmRlZmluZWQsIHRydWUpICsgMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZFJzbHQgPSBhbHRlcm5hdGUocG9zLCBjLCBzdHJpY3QsIGZyb21TZXRWYWxpZCwgZGVjaXNpb25Qb3MgLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5leGNsdWRlc1tkZWNpc2lvblBvc10gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRSc2x0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWYWxpZChwb3MsIGMsIHN0cmljdCwgZnJvbVNldFZhbGlkLCBmcm9tQWx0ZXJuYXRlLCB2YWxpZGF0ZU9ubHkpIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBpc1NlbGVjdGlvbihwb3NPYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzUlRMID8gcG9zT2JqLmJlZ2luIC0gcG9zT2JqLmVuZCA+IDEgfHwgcG9zT2JqLmJlZ2luIC0gcG9zT2JqLmVuZCA9PT0gMSA6IHBvc09iai5lbmQgLSBwb3NPYmouYmVnaW4gPiAxIHx8IHBvc09iai5lbmQgLSBwb3NPYmouYmVnaW4gPT09IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN0cmljdCA9IHN0cmljdCA9PT0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB2YXIgbWFza1BvcyA9IHBvcztcbiAgICAgICAgICAgICAgICBpZiAocG9zLmJlZ2luICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgbWFza1BvcyA9IGlzUlRMID8gcG9zLmVuZCA6IHBvcy5iZWdpbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gX2lzVmFsaWQocG9zaXRpb24sIGMsIHN0cmljdCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcnNsdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAkLmVhY2goZ2V0VGVzdHMocG9zaXRpb24pLCBmdW5jdGlvbihuZHgsIHRzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRlc3QgPSB0c3QubWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRCdWZmZXIodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByc2x0ID0gdGVzdC5mbiAhPSBudWxsID8gdGVzdC5mbi50ZXN0KGMsIGdldE1hc2tTZXQoKSwgcG9zaXRpb24sIHN0cmljdCwgb3B0cywgaXNTZWxlY3Rpb24ocG9zKSkgOiAoYyA9PT0gdGVzdC5kZWYgfHwgYyA9PT0gb3B0cy5za2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyKSAmJiB0ZXN0LmRlZiAhPT0gXCJcIiA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjOiBnZXRQbGFjZWhvbGRlcihwb3NpdGlvbiwgdGVzdCwgdHJ1ZSkgfHwgdGVzdC5kZWYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfSA6IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJzbHQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVsZW0gPSByc2x0LmMgIT09IHVuZGVmaW5lZCA/IHJzbHQuYyA6IGMsIHZhbGlkYXRlZFBvcyA9IHBvc2l0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0gPSBlbGVtID09PSBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIgJiYgdGVzdC5mbiA9PT0gbnVsbCA/IGdldFBsYWNlaG9sZGVyKHBvc2l0aW9uLCB0ZXN0LCB0cnVlKSB8fCB0ZXN0LmRlZiA6IGVsZW07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJzbHQucmVtb3ZlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEkLmlzQXJyYXkocnNsdC5yZW1vdmUpKSByc2x0LnJlbW92ZSA9IFsgcnNsdC5yZW1vdmUgXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKHJzbHQucmVtb3ZlLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGIgLSBhO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgZnVuY3Rpb24obmR4LCBsbW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXZhbGlkYXRlTWFzayh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW46IGxtbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBsbW50ICsgMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocnNsdC5pbnNlcnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISQuaXNBcnJheShyc2x0Lmluc2VydCkpIHJzbHQuaW5zZXJ0ID0gWyByc2x0Lmluc2VydCBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2gocnNsdC5pbnNlcnQuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYSAtIGI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLCBmdW5jdGlvbihuZHgsIGxtbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQobG1udC5wb3MsIGxtbnQuYywgdHJ1ZSwgZnJvbVNldFZhbGlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyc2x0ICE9PSB0cnVlICYmIHJzbHQucG9zICE9PSB1bmRlZmluZWQgJiYgcnNsdC5wb3MgIT09IHBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRlZFBvcyA9IHJzbHQucG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocnNsdCAhPT0gdHJ1ZSAmJiByc2x0LnBvcyA9PT0gdW5kZWZpbmVkICYmIHJzbHQuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFyZXZhbGlkYXRlTWFzayhwb3MsICQuZXh0ZW5kKHt9LCB0c3QsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQ6IGNhc2luZyhlbGVtLCB0ZXN0LCB2YWxpZGF0ZWRQb3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksIGZyb21TZXRWYWxpZCwgdmFsaWRhdGVkUG9zKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByc2x0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByc2x0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gdHJ1ZSwgcG9zaXRpb25zQ2xvbmUgPSAkLmV4dGVuZCh0cnVlLCB7fSwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zKTtcbiAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMucHJlVmFsaWRhdGlvbikgJiYgIXN0cmljdCAmJiBmcm9tU2V0VmFsaWQgIT09IHRydWUgJiYgdmFsaWRhdGVPbmx5ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IG9wdHMucHJlVmFsaWRhdGlvbihnZXRCdWZmZXIoKSwgbWFza1BvcywgYywgaXNTZWxlY3Rpb24ocG9zKSwgb3B0cywgZ2V0TWFza1NldCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICB0cmFja2JhY2tQb3NpdGlvbnModW5kZWZpbmVkLCBtYXNrUG9zLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1heExlbmd0aCA9PT0gdW5kZWZpbmVkIHx8IG1hc2tQb3MgPCBtYXhMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IF9pc1ZhbGlkKG1hc2tQb3MsIGMsIHN0cmljdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKCFzdHJpY3QgfHwgZnJvbVNldFZhbGlkID09PSB0cnVlKSAmJiByZXN1bHQgPT09IGZhbHNlICYmIHZhbGlkYXRlT25seSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjdXJyZW50UG9zVmFsaWQgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbWFza1Bvc107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRQb3NWYWxpZCAmJiBjdXJyZW50UG9zVmFsaWQubWF0Y2guZm4gPT09IG51bGwgJiYgKGN1cnJlbnRQb3NWYWxpZC5tYXRjaC5kZWYgPT09IGMgfHwgYyA9PT0gb3B0cy5za2lwT3B0aW9uYWxQYXJ0Q2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogc2Vla05leHQobWFza1BvcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKG9wdHMuaW5zZXJ0TW9kZSB8fCBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbc2Vla05leHQobWFza1BvcyldID09PSB1bmRlZmluZWQpICYmICghaXNNYXNrKG1hc2tQb3MsIHRydWUpIHx8IGdldE1hc2tTZXQoKS5qaXRPZmZzZXRbbWFza1Bvc10pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLmppdE9mZnNldFttYXNrUG9zXSAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbc2Vla05leHQobWFza1BvcyldID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBpc1ZhbGlkKG1hc2tQb3MgKyBnZXRNYXNrU2V0KCkuaml0T2Zmc2V0W21hc2tQb3NdLCBjLCBzdHJpY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IGZhbHNlKSByZXN1bHQuY2FyZXQgPSBtYXNrUG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGZvciAodmFyIG5Qb3MgPSBtYXNrUG9zICsgMSwgc25Qb3MgPSBzZWVrTmV4dChtYXNrUG9zKTsgblBvcyA8PSBzblBvczsgblBvcysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gX2lzVmFsaWQoblBvcywgYywgc3RyaWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0cmFja2JhY2tQb3NpdGlvbnMobWFza1BvcywgcmVzdWx0LnBvcyAhPT0gdW5kZWZpbmVkID8gcmVzdWx0LnBvcyA6IG5Qb3MpIHx8IHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza1BvcyA9IG5Qb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ID09PSBmYWxzZSAmJiBvcHRzLmtlZXBTdGF0aWMgIT09IGZhbHNlICYmIChvcHRzLnJlZ2V4ID09IG51bGwgfHwgaXNDb21wbGV0ZShnZXRCdWZmZXIoKSkpICYmICFzdHJpY3QgJiYgZnJvbUFsdGVybmF0ZSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gYWx0ZXJuYXRlKG1hc2tQb3MsIGMsIHN0cmljdCwgZnJvbVNldFZhbGlkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBtYXNrUG9zXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgkLmlzRnVuY3Rpb24ob3B0cy5wb3N0VmFsaWRhdGlvbikgJiYgcmVzdWx0ICE9PSBmYWxzZSAmJiAhc3RyaWN0ICYmIGZyb21TZXRWYWxpZCAhPT0gdHJ1ZSAmJiB2YWxpZGF0ZU9ubHkgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvc3RSZXN1bHQgPSBvcHRzLnBvc3RWYWxpZGF0aW9uKGdldEJ1ZmZlcih0cnVlKSwgcG9zLmJlZ2luICE9PSB1bmRlZmluZWQgPyBpc1JUTCA/IHBvcy5lbmQgOiBwb3MuYmVnaW4gOiBwb3MsIHJlc3VsdCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwb3N0UmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwb3N0UmVzdWx0LnJlZnJlc2hGcm9tQnVmZmVyICYmIHBvc3RSZXN1bHQuYnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlZnJlc2ggPSBwb3N0UmVzdWx0LnJlZnJlc2hGcm9tQnVmZmVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2hGcm9tQnVmZmVyKHJlZnJlc2ggPT09IHRydWUgPyByZWZyZXNoIDogcmVmcmVzaC5zdGFydCwgcmVmcmVzaC5lbmQsIHBvc3RSZXN1bHQuYnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHBvc3RSZXN1bHQgPT09IHRydWUgPyByZXN1bHQgOiBwb3N0UmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgJiYgcmVzdWx0LnBvcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wb3MgPSBtYXNrUG9zO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ID09PSBmYWxzZSB8fCB2YWxpZGF0ZU9ubHkgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzZXRNYXNrU2V0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgcG9zaXRpb25zQ2xvbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhY2tiYWNrUG9zaXRpb25zKG9yaWdpbmFsUG9zLCBuZXdQb3MsIGZpbGxPbmx5KSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdDtcbiAgICAgICAgICAgICAgICBpZiAob3JpZ2luYWxQb3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKG9yaWdpbmFsUG9zID0gbmV3UG9zIC0gMTsgb3JpZ2luYWxQb3MgPiAwOyBvcmlnaW5hbFBvcy0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW29yaWdpbmFsUG9zXSkgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHMgPSBvcmlnaW5hbFBvczsgcHMgPCBuZXdQb3M7IHBzKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twc10gPT09IHVuZGVmaW5lZCAmJiAhaXNNYXNrKHBzLCB0cnVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZwID0gcHMgPT0gMCA/IGdldFRlc3QocHMpIDogZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BzIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodnApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdHMgPSBnZXRUZXN0cyhwcykuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVzdHNbdGVzdHMubGVuZ3RoIC0gMV0ubWF0Y2guZGVmID09PSBcIlwiKSB0ZXN0cy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYmVzdE1hdGNoID0gZGV0ZXJtaW5lVGVzdFRlbXBsYXRlKHBzLCB0ZXN0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVzdE1hdGNoID0gJC5leHRlbmQoe30sIGJlc3RNYXRjaCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dDogZ2V0UGxhY2Vob2xkZXIocHMsIGJlc3RNYXRjaC5tYXRjaCwgdHJ1ZSkgfHwgYmVzdE1hdGNoLm1hdGNoLmRlZlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlc3RNYXRjaC5nZW5lcmF0ZWRJbnB1dCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV2YWxpZGF0ZU1hc2socHMsIGJlc3RNYXRjaCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGxPbmx5ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjdnBJbnB1dCA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tuZXdQb3NdLmlucHV0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbmV3UG9zXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gaXNWYWxpZChuZXdQb3MsIGN2cElucHV0LCB0cnVlLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJldmFsaWRhdGVNYXNrKHBvcywgdmFsaWRUZXN0LCBmcm9tU2V0VmFsaWQsIHZhbGlkYXRlZFBvcykge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIElzRW5jbG9zZWRTdGF0aWMocG9zLCB2YWxpZHMsIHNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcG9zTWF0Y2ggPSB2YWxpZHNbcG9zXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvc01hdGNoICE9PSB1bmRlZmluZWQgJiYgKHBvc01hdGNoLm1hdGNoLmZuID09PSBudWxsICYmIHBvc01hdGNoLm1hdGNoLm9wdGlvbmFsaXR5ICE9PSB0cnVlIHx8IHBvc01hdGNoLmlucHV0ID09PSBvcHRzLnJhZGl4UG9pbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJldk1hdGNoID0gc2VsZWN0aW9uLmJlZ2luIDw9IHBvcyAtIDEgPyB2YWxpZHNbcG9zIC0gMV0gJiYgdmFsaWRzW3BvcyAtIDFdLm1hdGNoLmZuID09PSBudWxsICYmIHZhbGlkc1twb3MgLSAxXSA6IHZhbGlkc1twb3MgLSAxXSwgbmV4dE1hdGNoID0gc2VsZWN0aW9uLmVuZCA+IHBvcyArIDEgPyB2YWxpZHNbcG9zICsgMV0gJiYgdmFsaWRzW3BvcyArIDFdLm1hdGNoLmZuID09PSBudWxsICYmIHZhbGlkc1twb3MgKyAxXSA6IHZhbGlkc1twb3MgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwcmV2TWF0Y2ggJiYgbmV4dE1hdGNoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGJlZ2luID0gcG9zLmJlZ2luICE9PSB1bmRlZmluZWQgPyBwb3MuYmVnaW4gOiBwb3MsIGVuZCA9IHBvcy5lbmQgIT09IHVuZGVmaW5lZCA/IHBvcy5lbmQgOiBwb3M7XG4gICAgICAgICAgICAgICAgaWYgKHBvcy5iZWdpbiA+IHBvcy5lbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVnaW4gPSBwb3MuZW5kO1xuICAgICAgICAgICAgICAgICAgICBlbmQgPSBwb3MuYmVnaW47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhbGlkYXRlZFBvcyA9IHZhbGlkYXRlZFBvcyAhPT0gdW5kZWZpbmVkID8gdmFsaWRhdGVkUG9zIDogYmVnaW47XG4gICAgICAgICAgICAgICAgaWYgKGJlZ2luICE9PSBlbmQgfHwgb3B0cy5pbnNlcnRNb2RlICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1t2YWxpZGF0ZWRQb3NdICE9PSB1bmRlZmluZWQgJiYgZnJvbVNldFZhbGlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvc2l0aW9uc0Nsb25lID0gJC5leHRlbmQodHJ1ZSwge30sIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucyksIGx2cCA9IGdldExhc3RWYWxpZFBvc2l0aW9uKHVuZGVmaW5lZCwgdHJ1ZSksIGk7XG4gICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5wID0gYmVnaW47XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IGx2cDsgaSA+PSBiZWdpbjsgaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXS5tYXRjaC5uYXRpdmVEZWYgPT09IFwiK1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5pc05lZ2F0aXZlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWxpZCA9IHRydWUsIGogPSB2YWxpZGF0ZWRQb3MsIHZwcyA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucywgbmVlZHNWYWxpZGF0aW9uID0gZmFsc2UsIHBvc01hdGNoID0gaiwgaSA9IGo7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWxpZFRlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1t2YWxpZGF0ZWRQb3NdID0gJC5leHRlbmQodHJ1ZSwge30sIHZhbGlkVGVzdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NNYXRjaCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJlZ2luIDwgZW5kKSBpKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZm9yICg7aSA8PSBsdnA7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHQgPSBwb3NpdGlvbnNDbG9uZVtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ICE9PSB1bmRlZmluZWQgJiYgKGkgPj0gZW5kIHx8IGkgPj0gYmVnaW4gJiYgdC5nZW5lcmF0ZWRJbnB1dCAhPT0gdHJ1ZSAmJiBJc0VuY2xvc2VkU3RhdGljKGksIHBvc2l0aW9uc0Nsb25lLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW46IGJlZ2luLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogZW5kXG4gICAgICAgICAgICAgICAgICAgICAgICB9KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoZ2V0VGVzdChwb3NNYXRjaCkubWF0Y2guZGVmICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZWVkc1ZhbGlkYXRpb24gPT09IGZhbHNlICYmIHBvc2l0aW9uc0Nsb25lW3Bvc01hdGNoXSAmJiBwb3NpdGlvbnNDbG9uZVtwb3NNYXRjaF0ubWF0Y2gubmF0aXZlRGVmID09PSB0Lm1hdGNoLm5hdGl2ZURlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc01hdGNoXSA9ICQuZXh0ZW5kKHRydWUsIHt9LCBwb3NpdGlvbnNDbG9uZVtwb3NNYXRjaF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc01hdGNoXS5pbnB1dCA9IHQuaW5wdXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFja2JhY2tQb3NpdGlvbnModW5kZWZpbmVkLCBwb3NNYXRjaCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqID0gcG9zTWF0Y2ggKyAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9wdHMuc2hpZnRQb3NpdGlvbnMgJiYgcG9zaXRpb25DYW5NYXRjaERlZmluaXRpb24ocG9zTWF0Y2gsIHQubWF0Y2guZGVmKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGlzVmFsaWQocG9zTWF0Y2gsIHQuaW5wdXQsIHRydWUsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWQgPSByZXN1bHQgIT09IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaiA9IHJlc3VsdC5jYXJldCB8fCByZXN1bHQuaW5zZXJ0ID8gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSA6IHBvc01hdGNoICsgMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5lZWRzVmFsaWRhdGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZCA9IHQuZ2VuZXJhdGVkSW5wdXQgPT09IHRydWUgfHwgdC5pbnB1dCA9PT0gb3B0cy5yYWRpeFBvaW50ICYmIG9wdHMubnVtZXJpY0lucHV0ID09PSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxpZCkgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdmFsaWQgJiYgcG9zTWF0Y2ggPiBlbmQgJiYgaXNNYXNrKHBvc01hdGNoLCB0cnVlKSAmJiAodC5tYXRjaC5mbiAhPT0gbnVsbCB8fCBwb3NNYXRjaCA+IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zTWF0Y2grKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFRlc3QocG9zTWF0Y2gpLm1hdGNoLmRlZiA9PSBcIlwiKSB2YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc01hdGNoID0gajtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdmFsaWQpIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghdmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIHt9LCBwb3NpdGlvbnNDbG9uZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbGlkVGVzdCkge1xuICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbdmFsaWRhdGVkUG9zXSA9ICQuZXh0ZW5kKHRydWUsIHt9LCB2YWxpZFRlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBpc01hc2socG9zLCBzdHJpY3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGVzdCA9IGdldFRlc3RUZW1wbGF0ZShwb3MpLm1hdGNoO1xuICAgICAgICAgICAgICAgIGlmICh0ZXN0LmRlZiA9PT0gXCJcIikgdGVzdCA9IGdldFRlc3QocG9zKS5tYXRjaDtcbiAgICAgICAgICAgICAgICBpZiAodGVzdC5mbiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0ZXN0LmZuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc3RyaWN0ICE9PSB0cnVlICYmIHBvcyA+IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZXN0cyA9IGdldFRlc3RzKHBvcyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0ZXN0cy5sZW5ndGggPiAxICsgKHRlc3RzW3Rlc3RzLmxlbmd0aCAtIDFdLm1hdGNoLmRlZiA9PT0gXCJcIiA/IDEgOiAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gc2Vla05leHQocG9zLCBuZXdCbG9jaykge1xuICAgICAgICAgICAgICAgIHZhciBwb3NpdGlvbiA9IHBvcyArIDE7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGdldFRlc3QocG9zaXRpb24pLm1hdGNoLmRlZiAhPT0gXCJcIiAmJiAobmV3QmxvY2sgPT09IHRydWUgJiYgKGdldFRlc3QocG9zaXRpb24pLm1hdGNoLm5ld0Jsb2NrTWFya2VyICE9PSB0cnVlIHx8ICFpc01hc2socG9zaXRpb24pKSB8fCBuZXdCbG9jayAhPT0gdHJ1ZSAmJiAhaXNNYXNrKHBvc2l0aW9uKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvc2l0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gc2Vla1ByZXZpb3VzKHBvcywgbmV3QmxvY2spIHtcbiAgICAgICAgICAgICAgICB2YXIgcG9zaXRpb24gPSBwb3MsIHRlc3RzO1xuICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvbiA8PSAwKSByZXR1cm4gMDtcbiAgICAgICAgICAgICAgICB3aGlsZSAoLS1wb3NpdGlvbiA+IDAgJiYgKG5ld0Jsb2NrID09PSB0cnVlICYmIGdldFRlc3QocG9zaXRpb24pLm1hdGNoLm5ld0Jsb2NrTWFya2VyICE9PSB0cnVlIHx8IG5ld0Jsb2NrICE9PSB0cnVlICYmICFpc01hc2socG9zaXRpb24pICYmICh0ZXN0cyA9IGdldFRlc3RzKHBvc2l0aW9uKSwgXG4gICAgICAgICAgICAgICAgdGVzdHMubGVuZ3RoIDwgMiB8fCB0ZXN0cy5sZW5ndGggPT09IDIgJiYgdGVzdHNbMV0ubWF0Y2guZGVmID09PSBcIlwiKSkpIHt9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvc2l0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gd3JpdGVCdWZmZXIoaW5wdXQsIGJ1ZmZlciwgY2FyZXRQb3MsIGV2ZW50LCB0cmlnZ2VyRXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50ICYmICQuaXNGdW5jdGlvbihvcHRzLm9uQmVmb3JlV3JpdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBvcHRzLm9uQmVmb3JlV3JpdGUuY2FsbChpbnB1dG1hc2ssIGV2ZW50LCBidWZmZXIsIGNhcmV0UG9zLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5yZWZyZXNoRnJvbUJ1ZmZlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZWZyZXNoID0gcmVzdWx0LnJlZnJlc2hGcm9tQnVmZmVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2hGcm9tQnVmZmVyKHJlZnJlc2ggPT09IHRydWUgPyByZWZyZXNoIDogcmVmcmVzaC5zdGFydCwgcmVmcmVzaC5lbmQsIHJlc3VsdC5idWZmZXIgfHwgYnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXIgPSBnZXRCdWZmZXIodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FyZXRQb3MgIT09IHVuZGVmaW5lZCkgY2FyZXRQb3MgPSByZXN1bHQuY2FyZXQgIT09IHVuZGVmaW5lZCA/IHJlc3VsdC5jYXJldCA6IGNhcmV0UG9zO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0LmlucHV0bWFzay5fdmFsdWVTZXQoYnVmZmVyLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2FyZXRQb3MgIT09IHVuZGVmaW5lZCAmJiAoZXZlbnQgPT09IHVuZGVmaW5lZCB8fCBldmVudC50eXBlICE9PSBcImJsdXJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0KGlucHV0LCBjYXJldFBvcyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSByZW5kZXJDb2xvck1hc2soaW5wdXQsIGNhcmV0UG9zLCBidWZmZXIubGVuZ3RoID09PSAwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWdnZXJFdmVudHMgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkaW5wdXQgPSAkKGlucHV0KSwgbnB0VmFsID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2tpcElucHV0RXZlbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJpbnB1dFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5wdFZhbCA9PT0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5qb2luKFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwiY2xlYXJlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ29tcGxldGUoYnVmZmVyKSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcImNvbXBsZXRlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UGxhY2Vob2xkZXIocG9zLCB0ZXN0LCByZXR1cm5QTCkge1xuICAgICAgICAgICAgICAgIHRlc3QgPSB0ZXN0IHx8IGdldFRlc3QocG9zKS5tYXRjaDtcbiAgICAgICAgICAgICAgICBpZiAodGVzdC5wbGFjZWhvbGRlciAhPT0gdW5kZWZpbmVkIHx8IHJldHVyblBMID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkLmlzRnVuY3Rpb24odGVzdC5wbGFjZWhvbGRlcikgPyB0ZXN0LnBsYWNlaG9sZGVyKG9wdHMpIDogdGVzdC5wbGFjZWhvbGRlcjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRlc3QuZm4gPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvcyA+IC0xICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ZXN0cyA9IGdldFRlc3RzKHBvcyksIHN0YXRpY0FsdGVybmF0aW9ucyA9IFtdLCBwcmV2VGVzdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0cy5sZW5ndGggPiAxICsgKHRlc3RzW3Rlc3RzLmxlbmd0aCAtIDFdLm1hdGNoLmRlZiA9PT0gXCJcIiA/IDEgOiAwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGVzdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RzW2ldLm1hdGNoLm9wdGlvbmFsaXR5ICE9PSB0cnVlICYmIHRlc3RzW2ldLm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciAhPT0gdHJ1ZSAmJiAodGVzdHNbaV0ubWF0Y2guZm4gPT09IG51bGwgfHwgcHJldlRlc3QgPT09IHVuZGVmaW5lZCB8fCB0ZXN0c1tpXS5tYXRjaC5mbi50ZXN0KHByZXZUZXN0Lm1hdGNoLmRlZiwgZ2V0TWFza1NldCgpLCBwb3MsIHRydWUsIG9wdHMpICE9PSBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRpY0FsdGVybmF0aW9ucy5wdXNoKHRlc3RzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0c1tpXS5tYXRjaC5mbiA9PT0gbnVsbCkgcHJldlRlc3QgPSB0ZXN0c1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0aWNBbHRlcm5hdGlvbnMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgvWzAtOWEtYkEtWl0vLnRlc3Qoc3RhdGljQWx0ZXJuYXRpb25zWzBdLm1hdGNoLmRlZikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KHBvcyAlIG9wdHMucGxhY2Vob2xkZXIubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRlc3QuZGVmO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQocG9zICUgb3B0cy5wbGFjZWhvbGRlci5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gSGFuZGxlTmF0aXZlUGxhY2Vob2xkZXIobnB0LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChpZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobnB0LmlucHV0bWFzay5fdmFsdWVHZXQoKSAhPT0gdmFsdWUgJiYgKG5wdC5wbGFjZWhvbGRlciAhPT0gdmFsdWUgfHwgbnB0LnBsYWNlaG9sZGVyID09PSBcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IGdldEJ1ZmZlcigpLnNsaWNlKCksIG5wdFZhbHVlID0gbnB0LmlucHV0bWFzay5fdmFsdWVHZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChucHRWYWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobHZwID09PSAtMSAmJiBucHRWYWx1ZSA9PT0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5qb2luKFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobHZwICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhck9wdGlvbmFsVGFpbChidWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0ZUJ1ZmZlcihucHQsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG5wdC5wbGFjZWhvbGRlciAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbnB0LnBsYWNlaG9sZGVyID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChucHQucGxhY2Vob2xkZXIgPT09IFwiXCIpIG5wdC5yZW1vdmVBdHRyaWJ1dGUoXCJwbGFjZWhvbGRlclwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgRXZlbnRSdWxlciA9IHtcbiAgICAgICAgICAgICAgICBvbjogZnVuY3Rpb24gb24oaW5wdXQsIGV2ZW50TmFtZSwgZXZlbnRIYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBldiA9IGZ1bmN0aW9uIGV2KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGF0LmlucHV0bWFzayA9PT0gdW5kZWZpbmVkICYmIHRoaXMubm9kZU5hbWUgIT09IFwiRk9STVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGltT3B0cyA9ICQuZGF0YSh0aGF0LCBcIl9pbnB1dG1hc2tfb3B0c1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW1PcHRzKSBuZXcgSW5wdXRtYXNrKGltT3B0cykubWFzayh0aGF0KTsgZWxzZSBFdmVudFJ1bGVyLm9mZih0aGF0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZS50eXBlICE9PSBcInNldHZhbHVlXCIgJiYgdGhpcy5ub2RlTmFtZSAhPT0gXCJGT1JNXCIgJiYgKHRoYXQuZGlzYWJsZWQgfHwgdGhhdC5yZWFkT25seSAmJiAhKGUudHlwZSA9PT0gXCJrZXlkb3duXCIgJiYgZS5jdHJsS2V5ICYmIGUua2V5Q29kZSA9PT0gNjcgfHwgb3B0cy50YWJUaHJvdWdoID09PSBmYWxzZSAmJiBlLmtleUNvZGUgPT09IElucHV0bWFzay5rZXlDb2RlLlRBQikpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGUudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImlucHV0XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChza2lwSW5wdXRFdmVudCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2tpcElucHV0RXZlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1vYmlsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50SGFuZGxlci5hcHBseSh0aGF0LCBhcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldCh0aGF0LCB0aGF0LmlucHV0bWFzay5jYXJldFBvcywgdW5kZWZpbmVkLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwia2V5ZG93blwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwS2V5UHJlc3NFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwSW5wdXRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImtleXByZXNzXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChza2lwS2V5UHJlc3NFdmVudCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwS2V5UHJlc3NFdmVudCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY2xpY2tcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGllbW9iaWxlIHx8IGlwaG9uZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50SGFuZGxlci5hcHBseSh0aGF0LCBhcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmV0dXJuVmFsID0gZXZlbnRIYW5kbGVyLmFwcGx5KHRoYXQsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJldHVyblZhbCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmV0dXJuVmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50TmFtZV0gPSBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50TmFtZV0gfHwgW107XG4gICAgICAgICAgICAgICAgICAgIGlucHV0LmlucHV0bWFzay5ldmVudHNbZXZlbnROYW1lXS5wdXNoKGV2KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaW5BcnJheShldmVudE5hbWUsIFsgXCJzdWJtaXRcIiwgXCJyZXNldFwiIF0pICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmZvcm0gIT09IG51bGwpICQoaW5wdXQuZm9ybSkub24oZXZlbnROYW1lLCBldik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKGlucHV0KS5vbihldmVudE5hbWUsIGV2KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb2ZmOiBmdW5jdGlvbiBvZmYoaW5wdXQsIGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5pbnB1dG1hc2sgJiYgaW5wdXQuaW5wdXRtYXNrLmV2ZW50cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50c1tldmVudF0gPSBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzID0gaW5wdXQuaW5wdXRtYXNrLmV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChldmVudHMsIGZ1bmN0aW9uKGV2ZW50TmFtZSwgZXZBcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoZXZBcnIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXYgPSBldkFyci5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCQuaW5BcnJheShldmVudE5hbWUsIFsgXCJzdWJtaXRcIiwgXCJyZXNldFwiIF0pICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmZvcm0gIT09IG51bGwpICQoaW5wdXQuZm9ybSkub2ZmKGV2ZW50TmFtZSwgZXYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChpbnB1dCkub2ZmKGV2ZW50TmFtZSwgZXYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBpbnB1dC5pbnB1dG1hc2suZXZlbnRzW2V2ZW50TmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgRXZlbnRIYW5kbGVycyA9IHtcbiAgICAgICAgICAgICAgICBrZXlkb3duRXZlbnQ6IGZ1bmN0aW9uIGtleWRvd25FdmVudChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMsICRpbnB1dCA9ICQoaW5wdXQpLCBrID0gZS5rZXlDb2RlLCBwb3MgPSBjYXJldChpbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrID09PSBJbnB1dG1hc2sua2V5Q29kZS5CQUNLU1BBQ0UgfHwgayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuREVMRVRFIHx8IGlwaG9uZSAmJiBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5CQUNLU1BBQ0VfU0FGQVJJIHx8IGUuY3RybEtleSAmJiBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5YICYmICFpc0lucHV0RXZlbnRTdXBwb3J0ZWQoXCJjdXRcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZVJlbW92ZShpbnB1dCwgaywgcG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBnZXRCdWZmZXIodHJ1ZSksIGdldE1hc2tTZXQoKS5wLCBlLCBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgIT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLkVORCB8fCBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5QQUdFX0RPV04pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYXJldFBvcyA9IHNlZWtOZXh0KGdldExhc3RWYWxpZFBvc2l0aW9uKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIGUuc2hpZnRLZXkgPyBwb3MuYmVnaW4gOiBjYXJldFBvcywgY2FyZXRQb3MsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLkhPTUUgJiYgIWUuc2hpZnRLZXkgfHwgayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuUEFHRV9VUCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIDAsIGUuc2hpZnRLZXkgPyBwb3MuYmVnaW4gOiAwLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgob3B0cy51bmRvT25Fc2NhcGUgJiYgayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuRVNDQVBFIHx8IGsgPT09IDkwICYmIGUuY3RybEtleSkgJiYgZS5hbHRLZXkgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrVmFsKGlucHV0LCB0cnVlLCBmYWxzZSwgdW5kb1ZhbHVlLnNwbGl0KFwiXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwiY2xpY2tcIik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuSU5TRVJUICYmICEoZS5zaGlmdEtleSB8fCBlLmN0cmxLZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmluc2VydE1vZGUgPSAhb3B0cy5pbnNlcnRNb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKFwiaW0taW5zZXJ0XCIsIG9wdHMuaW5zZXJ0TW9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0cy50YWJUaHJvdWdoID09PSB0cnVlICYmIGsgPT09IElucHV0bWFzay5rZXlDb2RlLlRBQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUuc2hpZnRLZXkgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0VGVzdChwb3MuYmVnaW4pLm1hdGNoLmZuID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5iZWdpbiA9IHNlZWtOZXh0KHBvcy5iZWdpbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5lbmQgPSBzZWVrUHJldmlvdXMocG9zLmJlZ2luLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MuYmVnaW4gPSBzZWVrUHJldmlvdXMocG9zLmVuZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5iZWdpbiA9IHNlZWtOZXh0KHBvcy5iZWdpbiwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmVuZCA9IHNlZWtOZXh0KHBvcy5iZWdpbiwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvcy5lbmQgPCBnZXRNYXNrU2V0KCkubWFza0xlbmd0aCkgcG9zLmVuZC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvcy5iZWdpbiA8IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0KGlucHV0LCBwb3MuYmVnaW4sIHBvcy5lbmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG9wdHMub25LZXlEb3duLmNhbGwodGhpcywgZSwgZ2V0QnVmZmVyKCksIGNhcmV0KGlucHV0KS5iZWdpbiwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlnbm9yYWJsZSA9ICQuaW5BcnJheShrLCBvcHRzLmlnbm9yYWJsZXMpICE9PSAtMTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGtleXByZXNzRXZlbnQ6IGZ1bmN0aW9uIGtleXByZXNzRXZlbnQoZSwgY2hlY2t2YWwsIHdyaXRlT3V0LCBzdHJpY3QsIG5keCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLCAkaW5wdXQgPSAkKGlucHV0KSwgayA9IGUud2hpY2ggfHwgZS5jaGFyQ29kZSB8fCBlLmtleUNvZGU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGVja3ZhbCAhPT0gdHJ1ZSAmJiAhKGUuY3RybEtleSAmJiBlLmFsdEtleSkgJiYgKGUuY3RybEtleSB8fCBlLm1ldGFLZXkgfHwgaWdub3JhYmxlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLkVOVEVSICYmIHVuZG9WYWx1ZSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuZG9WYWx1ZSA9IGdldEJ1ZmZlcigpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGsgPT09IDQ2ICYmIGUuc2hpZnRLZXkgPT09IGZhbHNlICYmIG9wdHMucmFkaXhQb2ludCAhPT0gXCJcIikgayA9IG9wdHMucmFkaXhQb2ludC5jaGFyQ29kZUF0KDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwb3MgPSBjaGVja3ZhbCA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW46IG5keCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBuZHhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IDogY2FyZXQoaW5wdXQpLCBmb3J3YXJkUG9zaXRpb24sIGMgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGspLCBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLl9yYWRpeERhbmNlICYmIG9wdHMubnVtZXJpY0lucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYXJldFBvcyA9IGdldEJ1ZmZlcigpLmluZGV4T2Yob3B0cy5yYWRpeFBvaW50LmNoYXJBdCgwKSkgKyAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9zLmJlZ2luIDw9IGNhcmV0UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoayA9PT0gb3B0cy5yYWRpeFBvaW50LmNoYXJDb2RlQXQoMCkpIG9mZnNldCA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MuYmVnaW4gLT0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5lbmQgLT0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkud3JpdGVPdXRCdWZmZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWxSZXN1bHQgPSBpc1ZhbGlkKHBvcywgYywgc3RyaWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsUmVzdWx0ICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcndhcmRQb3NpdGlvbiA9IHZhbFJlc3VsdC5jYXJldCAhPT0gdW5kZWZpbmVkID8gdmFsUmVzdWx0LmNhcmV0IDogc2Vla05leHQodmFsUmVzdWx0LnBvcy5iZWdpbiA/IHZhbFJlc3VsdC5wb3MuYmVnaW4gOiB2YWxSZXN1bHQucG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnAgPSBmb3J3YXJkUG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcndhcmRQb3NpdGlvbiA9IChvcHRzLm51bWVyaWNJbnB1dCAmJiB2YWxSZXN1bHQuY2FyZXQgPT09IHVuZGVmaW5lZCA/IHNlZWtQcmV2aW91cyhmb3J3YXJkUG9zaXRpb24pIDogZm9yd2FyZFBvc2l0aW9uKSArIG9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAod3JpdGVPdXQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLm9uS2V5VmFsaWRhdGlvbi5jYWxsKGlucHV0LCBrLCB2YWxSZXN1bHQsIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS53cml0ZU91dEJ1ZmZlciAmJiB2YWxSZXN1bHQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gZ2V0QnVmZmVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0ZUJ1ZmZlcihpbnB1dCwgYnVmZmVyLCBmb3J3YXJkUG9zaXRpb24sIGUsIGNoZWNrdmFsICE9PSB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoZWNrdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxSZXN1bHQgIT09IGZhbHNlKSB2YWxSZXN1bHQuZm9yd2FyZFBvc2l0aW9uID0gZm9yd2FyZFBvc2l0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsUmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcGFzdGVFdmVudDogZnVuY3Rpb24gcGFzdGVFdmVudChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMsIGV2ID0gZS5vcmlnaW5hbEV2ZW50IHx8IGUsICRpbnB1dCA9ICQoaW5wdXQpLCBpbnB1dFZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCh0cnVlKSwgY2FyZXRQb3MgPSBjYXJldChpbnB1dCksIHRlbXBWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZW1wVmFsdWUgPSBjYXJldFBvcy5lbmQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvcy5lbmQgPSBjYXJldFBvcy5iZWdpbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zLmJlZ2luID0gdGVtcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZUJlZm9yZUNhcmV0ID0gaW5wdXRWYWx1ZS5zdWJzdHIoMCwgY2FyZXRQb3MuYmVnaW4pLCB2YWx1ZUFmdGVyQ2FyZXQgPSBpbnB1dFZhbHVlLnN1YnN0cihjYXJldFBvcy5lbmQsIGlucHV0VmFsdWUubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlQmVmb3JlQ2FyZXQgPT09IChpc1JUTCA/IGdldEJ1ZmZlclRlbXBsYXRlKCkucmV2ZXJzZSgpIDogZ2V0QnVmZmVyVGVtcGxhdGUoKSkuc2xpY2UoMCwgY2FyZXRQb3MuYmVnaW4pLmpvaW4oXCJcIikpIHZhbHVlQmVmb3JlQ2FyZXQgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWVBZnRlckNhcmV0ID09PSAoaXNSVEwgPyBnZXRCdWZmZXJUZW1wbGF0ZSgpLnJldmVyc2UoKSA6IGdldEJ1ZmZlclRlbXBsYXRlKCkpLnNsaWNlKGNhcmV0UG9zLmVuZCkuam9pbihcIlwiKSkgdmFsdWVBZnRlckNhcmV0ID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdpbmRvdy5jbGlwYm9hcmREYXRhICYmIHdpbmRvdy5jbGlwYm9hcmREYXRhLmdldERhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0VmFsdWUgPSB2YWx1ZUJlZm9yZUNhcmV0ICsgd2luZG93LmNsaXBib2FyZERhdGEuZ2V0RGF0YShcIlRleHRcIikgKyB2YWx1ZUFmdGVyQ2FyZXQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXYuY2xpcGJvYXJkRGF0YSAmJiBldi5jbGlwYm9hcmREYXRhLmdldERhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0VmFsdWUgPSB2YWx1ZUJlZm9yZUNhcmV0ICsgZXYuY2xpcGJvYXJkRGF0YS5nZXREYXRhKFwidGV4dC9wbGFpblwiKSArIHZhbHVlQWZ0ZXJDYXJldDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFzdGVWYWx1ZSA9IGlucHV0VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIGlmICgkLmlzRnVuY3Rpb24ob3B0cy5vbkJlZm9yZVBhc3RlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGVWYWx1ZSA9IG9wdHMub25CZWZvcmVQYXN0ZS5jYWxsKGlucHV0bWFzaywgaW5wdXRWYWx1ZSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFzdGVWYWx1ZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXN0ZVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGVWYWx1ZSA9IGlucHV0VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2hlY2tWYWwoaW5wdXQsIGZhbHNlLCBmYWxzZSwgcGFzdGVWYWx1ZS50b1N0cmluZygpLnNwbGl0KFwiXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoaW5wdXQsIGdldEJ1ZmZlcigpLCBzZWVrTmV4dChnZXRMYXN0VmFsaWRQb3NpdGlvbigpKSwgZSwgdW5kb1ZhbHVlICE9PSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGlucHV0RmFsbEJhY2tFdmVudDogZnVuY3Rpb24gaW5wdXRGYWxsQmFja0V2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gcmFkaXhQb2ludEhhbmRsZXIoaW5wdXQsIGlucHV0VmFsdWUsIGNhcmV0UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXRWYWx1ZS5jaGFyQXQoY2FyZXRQb3MuYmVnaW4gLSAxKSA9PT0gXCIuXCIgJiYgb3B0cy5yYWRpeFBvaW50ICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGlucHV0VmFsdWUuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZVtjYXJldFBvcy5iZWdpbiAtIDFdID0gb3B0cy5yYWRpeFBvaW50LmNoYXJBdCgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlID0gaW5wdXRWYWx1ZS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gaWVNb2JpbGVIYW5kbGVyKGlucHV0LCBpbnB1dFZhbHVlLCBjYXJldFBvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGllbW9iaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0Q2hhciA9IGlucHV0VmFsdWUucmVwbGFjZShnZXRCdWZmZXIoKS5qb2luKFwiXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXRDaGFyLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXYgPSBpbnB1dFZhbHVlLnNwbGl0KFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdi5zcGxpY2UoY2FyZXRQb3MuYmVnaW4sIDAsIGlucHV0Q2hhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0VmFsdWUgPSBpdi5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMsIGlucHV0VmFsdWUgPSBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChnZXRCdWZmZXIoKS5qb2luKFwiXCIpICE9PSBpbnB1dFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2FyZXRQb3MgPSBjYXJldChpbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlID0gcmFkaXhQb2ludEhhbmRsZXIoaW5wdXQsIGlucHV0VmFsdWUsIGNhcmV0UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0VmFsdWUgPSBpZU1vYmlsZUhhbmRsZXIoaW5wdXQsIGlucHV0VmFsdWUsIGNhcmV0UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRCdWZmZXIoKS5qb2luKFwiXCIpICE9PSBpbnB1dFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IGdldEJ1ZmZlcigpLmpvaW4oXCJcIiksIG9mZnNldCA9ICFvcHRzLm51bWVyaWNJbnB1dCAmJiBpbnB1dFZhbHVlLmxlbmd0aCA+IGJ1ZmZlci5sZW5ndGggPyAtMSA6IDAsIGZyb250UGFydCA9IGlucHV0VmFsdWUuc3Vic3RyKDAsIGNhcmV0UG9zLmJlZ2luKSwgYmFja1BhcnQgPSBpbnB1dFZhbHVlLnN1YnN0cihjYXJldFBvcy5iZWdpbiksIGZyb250QnVmZmVyUGFydCA9IGJ1ZmZlci5zdWJzdHIoMCwgY2FyZXRQb3MuYmVnaW4gKyBvZmZzZXQpLCBiYWNrQnVmZmVyUGFydCA9IGJ1ZmZlci5zdWJzdHIoY2FyZXRQb3MuYmVnaW4gKyBvZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3Rpb24gPSBjYXJldFBvcywgZW50cmllcyA9IFwiXCIsIGlzRW50cnkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJvbnRQYXJ0ICE9PSBmcm9udEJ1ZmZlclBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZwbCA9IChpc0VudHJ5ID0gZnJvbnRQYXJ0Lmxlbmd0aCA+PSBmcm9udEJ1ZmZlclBhcnQubGVuZ3RoKSA/IGZyb250UGFydC5sZW5ndGggOiBmcm9udEJ1ZmZlclBhcnQubGVuZ3RoLCBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBmcm9udFBhcnQuY2hhckF0KGkpID09PSBmcm9udEJ1ZmZlclBhcnQuY2hhckF0KGkpICYmIGkgPCBmcGw7IGkrKykge31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5iZWdpbiA9IGkgLSBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyaWVzICs9IGZyb250UGFydC5zbGljZShpLCBzZWxlY3Rpb24uZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmFja1BhcnQgIT09IGJhY2tCdWZmZXJQYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYWNrUGFydC5sZW5ndGggPiBiYWNrQnVmZmVyUGFydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJpZXMgKz0gYmFja1BhcnQuc2xpY2UoMCwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmFja1BhcnQubGVuZ3RoIDwgYmFja0J1ZmZlclBhcnQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uLmVuZCArPSBiYWNrQnVmZmVyUGFydC5sZW5ndGggLSBiYWNrUGFydC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0VudHJ5ICYmIG9wdHMucmFkaXhQb2ludCAhPT0gXCJcIiAmJiBiYWNrUGFydCA9PT0gXCJcIiAmJiBmcm9udFBhcnQuY2hhckF0KHNlbGVjdGlvbi5iZWdpbiArIG9mZnNldCAtIDEpID09PSBvcHRzLnJhZGl4UG9pbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uLmJlZ2luLS07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJpZXMgPSBvcHRzLnJhZGl4UG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBnZXRCdWZmZXIoKSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogc2VsZWN0aW9uLmJlZ2luICsgb2Zmc2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IHNlbGVjdGlvbi5lbmQgKyBvZmZzZXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW50cmllcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChlbnRyaWVzLnNwbGl0KFwiXCIpLCBmdW5jdGlvbihuZHgsIGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5cHJlc3MgPSBuZXcgJC5FdmVudChcImtleXByZXNzXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cHJlc3Mud2hpY2ggPSBlbnRyeS5jaGFyQ29kZUF0KDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudEhhbmRsZXJzLmtleXByZXNzRXZlbnQuY2FsbChpbnB1dCwga2V5cHJlc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZWN0aW9uLmJlZ2luID09PSBzZWxlY3Rpb24uZW5kIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uLmJlZ2luID0gc2Vla1ByZXZpb3VzKHNlbGVjdGlvbi5iZWdpbiArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGVjdGlvbi5iZWdpbiA9PT0gc2VsZWN0aW9uLmVuZCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgc2VsZWN0aW9uLmJlZ2luKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIHNlbGVjdGlvbi5iZWdpbiwgc2VsZWN0aW9uLmVuZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGtleWRvd24gPSBuZXcgJC5FdmVudChcImtleWRvd25cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleWRvd24ua2V5Q29kZSA9IG9wdHMubnVtZXJpY0lucHV0ID8gSW5wdXRtYXNrLmtleUNvZGUuQkFDS1NQQUNFIDogSW5wdXRtYXNrLmtleUNvZGUuREVMRVRFO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudEhhbmRsZXJzLmtleWRvd25FdmVudC5jYWxsKGlucHV0LCBrZXlkb3duKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBiZWZvcmVJbnB1dEV2ZW50OiBmdW5jdGlvbiBiZWZvcmVJbnB1dEV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUuY2FuY2VsYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZS5pbnB1dFR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImluc2VydFRleHRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2goZS5kYXRhLnNwbGl0KFwiXCIpLCBmdW5jdGlvbihuZHgsIGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrZXlwcmVzcyA9IG5ldyAkLkV2ZW50KFwia2V5cHJlc3NcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleXByZXNzLndoaWNoID0gZW50cnkuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50SGFuZGxlcnMua2V5cHJlc3NFdmVudC5jYWxsKGlucHV0LCBrZXlwcmVzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZGVsZXRlQ29udGVudEJhY2t3YXJkXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGtleWRvd24gPSBuZXcgJC5FdmVudChcImtleWRvd25cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5ZG93bi5rZXlDb2RlID0gSW5wdXRtYXNrLmtleUNvZGUuQkFDS1NQQUNFO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50SGFuZGxlcnMua2V5ZG93bkV2ZW50LmNhbGwoaW5wdXQsIGtleWRvd24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImRlbGV0ZUNvbnRlbnRGb3J3YXJkXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGtleWRvd24gPSBuZXcgJC5FdmVudChcImtleWRvd25cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5ZG93bi5rZXlDb2RlID0gSW5wdXRtYXNrLmtleUNvZGUuREVMRVRFO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50SGFuZGxlcnMua2V5ZG93bkV2ZW50LmNhbGwoaW5wdXQsIGtleWRvd24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldFZhbHVlRXZlbnQ6IGZ1bmN0aW9uIHNldFZhbHVlRXZlbnQoZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0bWFzay5yZWZyZXNoVmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcywgdmFsdWUgPSBlICYmIGUuZGV0YWlsID8gZS5kZXRhaWxbMF0gOiBhcmd1bWVudHNbMV0sIHZhbHVlID0gdmFsdWUgfHwgaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaXNGdW5jdGlvbihvcHRzLm9uQmVmb3JlTWFzaykpIHZhbHVlID0gb3B0cy5vbkJlZm9yZU1hc2suY2FsbChpbnB1dG1hc2ssIHZhbHVlLCBvcHRzKSB8fCB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpLnNwbGl0KFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBjaGVja1ZhbChpbnB1dCwgdHJ1ZSwgZmFsc2UsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgdW5kb1ZhbHVlID0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzIHx8IG9wdHMuY2xlYXJJbmNvbXBsZXRlKSAmJiBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgPT09IGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLl92YWx1ZVNldChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZm9jdXNFdmVudDogZnVuY3Rpb24gZm9jdXNFdmVudChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMsIG5wdFZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5zaG93TWFza09uRm9jdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChucHRWYWx1ZSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBnZXRCdWZmZXIoKSwgc2Vla05leHQoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtb3VzZUVudGVyID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0KGlucHV0LCBzZWVrTmV4dChnZXRMYXN0VmFsaWRQb3NpdGlvbigpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucG9zaXRpb25DYXJldE9uVGFiID09PSB0cnVlICYmIG1vdXNlRW50ZXIgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudEhhbmRsZXJzLmNsaWNrRXZlbnQuYXBwbHkoaW5wdXQsIFsgZSwgdHJ1ZSBdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB1bmRvVmFsdWUgPSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbW91c2VsZWF2ZUV2ZW50OiBmdW5jdGlvbiBtb3VzZWxlYXZlRXZlbnQoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICBtb3VzZUVudGVyID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzICYmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgIT09IGlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBIYW5kbGVOYXRpdmVQbGFjZWhvbGRlcihpbnB1dCwgb3JpZ2luYWxQbGFjZWhvbGRlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNsaWNrRXZlbnQ6IGZ1bmN0aW9uIGNsaWNrRXZlbnQoZSwgdGFiYmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGRvUmFkaXhGb2N1cyhjbGlja1Bvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmFkaXhQb2ludCAhPT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2cHMgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZwc1tjbGlja1Bvc10gPT09IHVuZGVmaW5lZCB8fCB2cHNbY2xpY2tQb3NdLmlucHV0ID09PSBnZXRQbGFjZWhvbGRlcihjbGlja1BvcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNsaWNrUG9zIDwgc2Vla05leHQoLTEpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhZGl4UG9zID0gJC5pbkFycmF5KG9wdHMucmFkaXhQb2ludCwgZ2V0QnVmZmVyKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFkaXhQb3MgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciB2cCBpbiB2cHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFkaXhQb3MgPCB2cCAmJiB2cHNbdnBdLmlucHV0ICE9PSBnZXRQbGFjZWhvbGRlcih2cCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWRDYXJldCA9IGNhcmV0KGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFiYmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1JUTCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRDYXJldC5lbmQgPSBzZWxlY3RlZENhcmV0LmJlZ2luO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRDYXJldC5iZWdpbiA9IHNlbGVjdGVkQ2FyZXQuZW5kO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZENhcmV0LmJlZ2luID09PSBzZWxlY3RlZENhcmV0LmVuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKG9wdHMucG9zaXRpb25DYXJldE9uQ2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwibm9uZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwic2VsZWN0XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgMCwgZ2V0QnVmZmVyKCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImlnbm9yZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIHNlZWtOZXh0KGdldExhc3RWYWxpZFBvc2l0aW9uKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInJhZGl4Rm9jdXNcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb1JhZGl4Rm9jdXMoc2VsZWN0ZWRDYXJldC5iZWdpbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFkaXhQb3MgPSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpLmluZGV4T2Yob3B0cy5yYWRpeFBvaW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgb3B0cy5udW1lcmljSW5wdXQgPyBzZWVrTmV4dChyYWRpeFBvcykgOiByYWRpeFBvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNsaWNrUG9zaXRpb24gPSBzZWxlY3RlZENhcmV0LmJlZ2luLCBsdmNsaWNrUG9zaXRpb24gPSBnZXRMYXN0VmFsaWRQb3NpdGlvbihjbGlja1Bvc2l0aW9uLCB0cnVlKSwgbGFzdFBvc2l0aW9uID0gc2Vla05leHQobHZjbGlja1Bvc2l0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjbGlja1Bvc2l0aW9uIDwgbGFzdFBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsICFpc01hc2soY2xpY2tQb3NpdGlvbiwgdHJ1ZSkgJiYgIWlzTWFzayhjbGlja1Bvc2l0aW9uIC0gMSwgdHJ1ZSkgPyBzZWVrTmV4dChjbGlja1Bvc2l0aW9uKSA6IGNsaWNrUG9zaXRpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbHZwID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2x2Y2xpY2tQb3NpdGlvbl0sIHR0ID0gZ2V0VGVzdFRlbXBsYXRlKGxhc3RQb3NpdGlvbiwgbHZwID8gbHZwLm1hdGNoLmxvY2F0b3IgOiB1bmRlZmluZWQsIGx2cCksIHBsYWNlaG9sZGVyID0gZ2V0UGxhY2Vob2xkZXIobGFzdFBvc2l0aW9uLCB0dC5tYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBsYWNlaG9sZGVyICE9PSBcIlwiICYmIGdldEJ1ZmZlcigpW2xhc3RQb3NpdGlvbl0gIT09IHBsYWNlaG9sZGVyICYmIHR0Lm1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciAhPT0gdHJ1ZSAmJiB0dC5tYXRjaC5uZXdCbG9ja01hcmtlciAhPT0gdHJ1ZSB8fCAhaXNNYXNrKGxhc3RQb3NpdGlvbiwgb3B0cy5rZWVwU3RhdGljKSAmJiB0dC5tYXRjaC5kZWYgPT09IHBsYWNlaG9sZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdQb3MgPSBzZWVrTmV4dChsYXN0UG9zaXRpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2xpY2tQb3NpdGlvbiA+PSBuZXdQb3MgfHwgY2xpY2tQb3NpdGlvbiA9PT0gbGFzdFBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0UG9zaXRpb24gPSBuZXdQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIGxhc3RQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjdXRFdmVudDogZnVuY3Rpb24gY3V0RXZlbnQoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLCAkaW5wdXQgPSAkKGlucHV0KSwgcG9zID0gY2FyZXQoaW5wdXQpLCBldiA9IGUub3JpZ2luYWxFdmVudCB8fCBlO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2xpcGJvYXJkRGF0YSA9IHdpbmRvdy5jbGlwYm9hcmREYXRhIHx8IGV2LmNsaXBib2FyZERhdGEsIGNsaXBEYXRhID0gaXNSVEwgPyBnZXRCdWZmZXIoKS5zbGljZShwb3MuZW5kLCBwb3MuYmVnaW4pIDogZ2V0QnVmZmVyKCkuc2xpY2UocG9zLmJlZ2luLCBwb3MuZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgY2xpcGJvYXJkRGF0YS5zZXREYXRhKFwidGV4dFwiLCBpc1JUTCA/IGNsaXBEYXRhLnJldmVyc2UoKS5qb2luKFwiXCIpIDogY2xpcERhdGEuam9pbihcIlwiKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5leGVjQ29tbWFuZCkgZG9jdW1lbnQuZXhlY0NvbW1hbmQoXCJjb3B5XCIpO1xuICAgICAgICAgICAgICAgICAgICBoYW5kbGVSZW1vdmUoaW5wdXQsIElucHV0bWFzay5rZXlDb2RlLkRFTEVURSwgcG9zKTtcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoaW5wdXQsIGdldEJ1ZmZlcigpLCBnZXRNYXNrU2V0KCkucCwgZSwgdW5kb1ZhbHVlICE9PSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGJsdXJFdmVudDogZnVuY3Rpb24gYmx1ckV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQodGhpcyksIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmlucHV0bWFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgSGFuZGxlTmF0aXZlUGxhY2Vob2xkZXIoaW5wdXQsIG9yaWdpbmFsUGxhY2Vob2xkZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5wdFZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpLCBidWZmZXIgPSBnZXRCdWZmZXIoKS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5wdFZhbHVlICE9PSBcIlwiIHx8IGNvbG9yTWFzayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldExhc3RWYWxpZFBvc2l0aW9uKCkgPT09IC0xICYmIG5wdFZhbHVlID09PSBnZXRCdWZmZXJUZW1wbGF0ZSgpLmpvaW4oXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJPcHRpb25hbFRhaWwoYnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNDb21wbGV0ZShidWZmZXIpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJpbmNvbXBsZXRlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY2xlYXJJbmNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IGdldEJ1ZmZlclRlbXBsYXRlKCkuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0ZUJ1ZmZlcihpbnB1dCwgYnVmZmVyLCB1bmRlZmluZWQsIGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVuZG9WYWx1ZSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuZG9WYWx1ZSA9IGJ1ZmZlci5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBtb3VzZWVudGVyRXZlbnQ6IGZ1bmN0aW9uIG1vdXNlZW50ZXJFdmVudChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgICAgIG1vdXNlRW50ZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAhPT0gaW5wdXQgJiYgb3B0cy5zaG93TWFza09uSG92ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEhhbmRsZU5hdGl2ZVBsYWNlaG9sZGVyKGlucHV0LCAoaXNSVEwgPyBnZXRCdWZmZXIoKS5zbGljZSgpLnJldmVyc2UoKSA6IGdldEJ1ZmZlcigpKS5qb2luKFwiXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc3VibWl0RXZlbnQ6IGZ1bmN0aW9uIHN1Ym1pdEV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHVuZG9WYWx1ZSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGVsLnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgJiYgZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSA9PT0gLTEgJiYgZWwuaW5wdXRtYXNrLl92YWx1ZUdldCAmJiBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkgPT09IGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLl92YWx1ZVNldChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5jbGVhckluY29tcGxldGUgJiYgaXNDb21wbGV0ZShnZXRCdWZmZXIoKSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2suX3ZhbHVlU2V0KFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnJlbW92ZU1hc2tPblN1Ym1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLl92YWx1ZVNldChlbC5pbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoZWwsIGdldEJ1ZmZlcigpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByZXNldEV2ZW50OiBmdW5jdGlvbiByZXNldEV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLnJlZnJlc2hWYWx1ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZWwudHJpZ2dlcihcInNldHZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZnVuY3Rpb24gY2hlY2tWYWwoaW5wdXQsIHdyaXRlT3V0LCBzdHJpY3QsIG5wdHZsLCBpbml0aWF0aW5nRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRtYXNrID0gdGhpcyB8fCBpbnB1dC5pbnB1dG1hc2ssIGlucHV0VmFsdWUgPSBucHR2bC5zbGljZSgpLCBjaGFyQ29kZXMgPSBcIlwiLCBpbml0aWFsTmR4ID0gLTEsIHJlc3VsdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBpc1RlbXBsYXRlTWF0Y2gobmR4LCBjaGFyQ29kZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoYXJDb2RlTmR4ID0gZ2V0TWFza1RlbXBsYXRlKHRydWUsIDAsIGZhbHNlKS5zbGljZShuZHgsIHNlZWtOZXh0KG5keCkpLmpvaW4oXCJcIikucmVwbGFjZSgvJy9nLCBcIlwiKS5pbmRleE9mKGNoYXJDb2Rlcyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjaGFyQ29kZU5keCAhPT0gLTEgJiYgIWlzTWFzayhuZHgpICYmIChnZXRUZXN0KG5keCkubWF0Y2gubmF0aXZlRGVmID09PSBjaGFyQ29kZXMuY2hhckF0KDApIHx8IGdldFRlc3QobmR4KS5tYXRjaC5mbiA9PT0gbnVsbCAmJiBnZXRUZXN0KG5keCkubWF0Y2gubmF0aXZlRGVmID09PSBcIidcIiArIGNoYXJDb2Rlcy5jaGFyQXQoMCkgfHwgZ2V0VGVzdChuZHgpLm1hdGNoLm5hdGl2ZURlZiA9PT0gXCIgXCIgJiYgKGdldFRlc3QobmR4ICsgMSkubWF0Y2gubmF0aXZlRGVmID09PSBjaGFyQ29kZXMuY2hhckF0KDApIHx8IGdldFRlc3QobmR4ICsgMSkubWF0Y2guZm4gPT09IG51bGwgJiYgZ2V0VGVzdChuZHggKyAxKS5tYXRjaC5uYXRpdmVEZWYgPT09IFwiJ1wiICsgY2hhckNvZGVzLmNoYXJBdCgwKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQoKTtcbiAgICAgICAgICAgICAgICBpZiAoIXN0cmljdCAmJiBvcHRzLmF1dG9Vbm1hc2sgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHN0YXRpY0lucHV0ID0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5zbGljZSgwLCBzZWVrTmV4dCgtMSkpLmpvaW4oXCJcIiksIG1hdGNoZXMgPSBpbnB1dFZhbHVlLmpvaW4oXCJcIikubWF0Y2gobmV3IFJlZ0V4cChcIl5cIiArIElucHV0bWFzay5lc2NhcGVSZWdleChzdGF0aWNJbnB1dCksIFwiZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaGVzICYmIG1hdGNoZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZS5zcGxpY2UoMCwgbWF0Y2hlcy5sZW5ndGggKiBzdGF0aWNJbnB1dC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbE5keCA9IHNlZWtOZXh0KGluaXRpYWxOZHgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5pdGlhbE5keCA9IHNlZWtOZXh0KGluaXRpYWxOZHgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW5pdGlhbE5keCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnAgPSBzZWVrTmV4dChpbml0aWFsTmR4KTtcbiAgICAgICAgICAgICAgICAgICAgaW5pdGlhbE5keCA9IDA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGdldE1hc2tTZXQoKS5wID0gaW5pdGlhbE5keDtcbiAgICAgICAgICAgICAgICBpbnB1dG1hc2suY2FyZXRQb3MgPSB7XG4gICAgICAgICAgICAgICAgICAgIGJlZ2luOiBpbml0aWFsTmR4XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAkLmVhY2goaW5wdXRWYWx1ZSwgZnVuY3Rpb24obmR4LCBjaGFyQ29kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckNvZGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tuZHhdID09PSB1bmRlZmluZWQgJiYgaW5wdXRWYWx1ZVtuZHhdID09PSBnZXRQbGFjZWhvbGRlcihuZHgpICYmIGlzTWFzayhuZHgsIHRydWUpICYmIGlzVmFsaWQobmR4LCBpbnB1dFZhbHVlW25keF0sIHRydWUsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB0cnVlKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkucCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5cHJlc3MgPSBuZXcgJC5FdmVudChcIl9jaGVja3ZhbFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlwcmVzcy53aGljaCA9IGNoYXJDb2RlLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhckNvZGVzICs9IGNoYXJDb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbih1bmRlZmluZWQsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNUZW1wbGF0ZU1hdGNoKGluaXRpYWxOZHgsIGNoYXJDb2RlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gRXZlbnRIYW5kbGVycy5rZXlwcmVzc0V2ZW50LmNhbGwoaW5wdXQsIGtleXByZXNzLCB0cnVlLCBmYWxzZSwgc3RyaWN0LCBpbnB1dG1hc2suY2FyZXRQb3MuYmVnaW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsTmR4ID0gaW5wdXRtYXNrLmNhcmV0UG9zLmJlZ2luICsgMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJDb2RlcyA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBFdmVudEhhbmRsZXJzLmtleXByZXNzRXZlbnQuY2FsbChpbnB1dCwga2V5cHJlc3MsIHRydWUsIGZhbHNlLCBzdHJpY3QsIGx2cCArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKHVuZGVmaW5lZCwgZ2V0QnVmZmVyKCksIHJlc3VsdC5mb3J3YXJkUG9zaXRpb24sIGtleXByZXNzLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0bWFzay5jYXJldFBvcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiByZXN1bHQuZm9yd2FyZFBvc2l0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiByZXN1bHQuZm9yd2FyZFBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHdyaXRlT3V0KSB3cml0ZUJ1ZmZlcihpbnB1dCwgZ2V0QnVmZmVyKCksIHJlc3VsdCA/IHJlc3VsdC5mb3J3YXJkUG9zaXRpb24gOiB1bmRlZmluZWQsIGluaXRpYXRpbmdFdmVudCB8fCBuZXcgJC5FdmVudChcImNoZWNrdmFsXCIpLCBpbml0aWF0aW5nRXZlbnQgJiYgaW5pdGlhdGluZ0V2ZW50LnR5cGUgPT09IFwiaW5wdXRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiB1bm1hc2tlZHZhbHVlKGlucHV0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5pbnB1dG1hc2sgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0LnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5pbnB1dG1hc2sgJiYgaW5wdXQuaW5wdXRtYXNrLnJlZnJlc2hWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRIYW5kbGVycy5zZXRWYWx1ZUV2ZW50LmNhbGwoaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciB1bVZhbHVlID0gW10sIHZwcyA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucztcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwbmR4IGluIHZwcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodnBzW3BuZHhdLm1hdGNoICYmIHZwc1twbmR4XS5tYXRjaC5mbiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1bVZhbHVlLnB1c2godnBzW3BuZHhdLmlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgdW5tYXNrZWRWYWx1ZSA9IHVtVmFsdWUubGVuZ3RoID09PSAwID8gXCJcIiA6IChpc1JUTCA/IHVtVmFsdWUucmV2ZXJzZSgpIDogdW1WYWx1ZSkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMub25Vbk1hc2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXJWYWx1ZSA9IChpc1JUTCA/IGdldEJ1ZmZlcigpLnNsaWNlKCkucmV2ZXJzZSgpIDogZ2V0QnVmZmVyKCkpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHVubWFza2VkVmFsdWUgPSBvcHRzLm9uVW5NYXNrLmNhbGwoaW5wdXRtYXNrLCBidWZmZXJWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB1bm1hc2tlZFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gY2FyZXQoaW5wdXQsIGJlZ2luLCBlbmQsIG5vdHJhbnNsYXRlKSB7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNsYXRlUG9zaXRpb24ocG9zKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1JUTCAmJiB0eXBlb2YgcG9zID09PSBcIm51bWJlclwiICYmICghb3B0cy5ncmVlZHkgfHwgb3B0cy5wbGFjZWhvbGRlciAhPT0gXCJcIikgJiYgZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvcyA9IGVsLmlucHV0bWFzay5fdmFsdWVHZXQoKS5sZW5ndGggLSBwb3M7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHJhbmdlO1xuICAgICAgICAgICAgICAgIGlmIChiZWdpbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgkLmlzQXJyYXkoYmVnaW4pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBpc1JUTCA/IGJlZ2luWzBdIDogYmVnaW5bMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBiZWdpbiA9IGlzUlRMID8gYmVnaW5bMV0gOiBiZWdpblswXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoYmVnaW4uYmVnaW4gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0gaXNSVEwgPyBiZWdpbi5iZWdpbiA6IGJlZ2luLmVuZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luID0gaXNSVEwgPyBiZWdpbi5lbmQgOiBiZWdpbi5iZWdpbjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGJlZ2luID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiZWdpbiA9IG5vdHJhbnNsYXRlID8gYmVnaW4gOiB0cmFuc2xhdGVQb3NpdGlvbihiZWdpbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBub3RyYW5zbGF0ZSA/IGVuZCA6IHRyYW5zbGF0ZVBvc2l0aW9uKGVuZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSB0eXBlb2YgZW5kID09IFwibnVtYmVyXCIgPyBlbmQgOiBiZWdpbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzY3JvbGxDYWxjID0gcGFyc2VJbnQoKChpbnB1dC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3IHx8IHdpbmRvdykuZ2V0Q29tcHV0ZWRTdHlsZSA/IChpbnB1dC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3IHx8IHdpbmRvdykuZ2V0Q29tcHV0ZWRTdHlsZShpbnB1dCwgbnVsbCkgOiBpbnB1dC5jdXJyZW50U3R5bGUpLmZvbnRTaXplKSAqIGVuZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LnNjcm9sbExlZnQgPSBzY3JvbGxDYWxjID4gaW5wdXQuc2Nyb2xsV2lkdGggPyBzY3JvbGxDYWxjIDogMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LmlucHV0bWFzay5jYXJldFBvcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogYmVnaW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBlbmRcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQgPT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJzZWxlY3Rpb25TdGFydFwiIGluIGlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LnNlbGVjdGlvblN0YXJ0ID0gYmVnaW47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LnNlbGVjdGlvbkVuZCA9IGVuZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdpbmRvdy5nZXRTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuZmlyc3RDaGlsZCA9PT0gdW5kZWZpbmVkIHx8IGlucHV0LmZpcnN0Q2hpbGQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ZXh0Tm9kZSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQuYXBwZW5kQ2hpbGQodGV4dE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlLnNldFN0YXJ0KGlucHV0LmZpcnN0Q2hpbGQsIGJlZ2luIDwgaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpLmxlbmd0aCA/IGJlZ2luIDogaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlLnNldEVuZChpbnB1dC5maXJzdENoaWxkLCBlbmQgPCBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkubGVuZ3RoID8gZW5kIDogaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlLmNvbGxhcHNlKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWwucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC5hZGRSYW5nZShyYW5nZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpbnB1dC5jcmVhdGVUZXh0UmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgPSBpbnB1dC5jcmVhdGVUZXh0UmFuZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UuY29sbGFwc2UodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlLm1vdmVFbmQoXCJjaGFyYWN0ZXJcIiwgZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UubW92ZVN0YXJ0KFwiY2hhcmFjdGVyXCIsIGJlZ2luKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2Uuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlckNvbG9yTWFzayhpbnB1dCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogYmVnaW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogZW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJzZWxlY3Rpb25TdGFydFwiIGluIGlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiZWdpbiA9IGlucHV0LnNlbGVjdGlvblN0YXJ0O1xuICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0gaW5wdXQuc2VsZWN0aW9uRW5kO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdpbmRvdy5nZXRTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlID0gd2luZG93LmdldFNlbGVjdGlvbigpLmdldFJhbmdlQXQoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFuZ2UuY29tbW9uQW5jZXN0b3JDb250YWluZXIucGFyZW50Tm9kZSA9PT0gaW5wdXQgfHwgcmFuZ2UuY29tbW9uQW5jZXN0b3JDb250YWluZXIgPT09IGlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW4gPSByYW5nZS5zdGFydE9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSByYW5nZS5lbmRPZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZG9jdW1lbnQuc2VsZWN0aW9uICYmIGRvY3VtZW50LnNlbGVjdGlvbi5jcmVhdGVSYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgPSBkb2N1bWVudC5zZWxlY3Rpb24uY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luID0gMCAtIHJhbmdlLmR1cGxpY2F0ZSgpLm1vdmVTdGFydChcImNoYXJhY3RlclwiLCAtaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBiZWdpbiArIHJhbmdlLnRleHQubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogbm90cmFuc2xhdGUgPyBiZWdpbiA6IHRyYW5zbGF0ZVBvc2l0aW9uKGJlZ2luKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogbm90cmFuc2xhdGUgPyBlbmQgOiB0cmFuc2xhdGVQb3NpdGlvbihlbmQpXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZGV0ZXJtaW5lTGFzdFJlcXVpcmVkUG9zaXRpb24ocmV0dXJuRGVmaW5pdGlvbikge1xuICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSBnZXRNYXNrVGVtcGxhdGUodHJ1ZSwgZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSwgdHJ1ZSwgdHJ1ZSksIGJsID0gYnVmZmVyLmxlbmd0aCwgcG9zLCBsdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbigpLCBwb3NpdGlvbnMgPSB7fSwgbHZUZXN0ID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2x2cF0sIG5keEludGx6ciA9IGx2VGVzdCAhPT0gdW5kZWZpbmVkID8gbHZUZXN0LmxvY2F0b3Iuc2xpY2UoKSA6IHVuZGVmaW5lZCwgdGVzdFBvcztcbiAgICAgICAgICAgICAgICBmb3IgKHBvcyA9IGx2cCArIDE7IHBvcyA8IGJ1ZmZlci5sZW5ndGg7IHBvcysrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRlc3RQb3MgPSBnZXRUZXN0VGVtcGxhdGUocG9zLCBuZHhJbnRsenIsIHBvcyAtIDEpO1xuICAgICAgICAgICAgICAgICAgICBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zW3Bvc10gPSAkLmV4dGVuZCh0cnVlLCB7fSwgdGVzdFBvcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsdlRlc3RBbHQgPSBsdlRlc3QgJiYgbHZUZXN0LmFsdGVybmF0aW9uICE9PSB1bmRlZmluZWQgPyBsdlRlc3QubG9jYXRvcltsdlRlc3QuYWx0ZXJuYXRpb25dIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGZvciAocG9zID0gYmwgLSAxOyBwb3MgPiBsdnA7IHBvcy0tKSB7XG4gICAgICAgICAgICAgICAgICAgIHRlc3RQb3MgPSBwb3NpdGlvbnNbcG9zXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0ZXN0UG9zLm1hdGNoLm9wdGlvbmFsaXR5IHx8IHRlc3RQb3MubWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyICYmIHRlc3RQb3MubWF0Y2gubmV3QmxvY2tNYXJrZXIgfHwgbHZUZXN0QWx0ICYmIChsdlRlc3RBbHQgIT09IHBvc2l0aW9uc1twb3NdLmxvY2F0b3JbbHZUZXN0LmFsdGVybmF0aW9uXSAmJiB0ZXN0UG9zLm1hdGNoLmZuICE9IG51bGwgfHwgdGVzdFBvcy5tYXRjaC5mbiA9PT0gbnVsbCAmJiB0ZXN0UG9zLmxvY2F0b3JbbHZUZXN0LmFsdGVybmF0aW9uXSAmJiBjaGVja0FsdGVybmF0aW9uTWF0Y2godGVzdFBvcy5sb2NhdG9yW2x2VGVzdC5hbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5zcGxpdChcIixcIiksIGx2VGVzdEFsdC50b1N0cmluZygpLnNwbGl0KFwiLFwiKSkgJiYgZ2V0VGVzdHMocG9zKVswXS5kZWYgIT09IFwiXCIpKSAmJiBidWZmZXJbcG9zXSA9PT0gZ2V0UGxhY2Vob2xkZXIocG9zLCB0ZXN0UG9zLm1hdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYmwtLTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmV0dXJuRGVmaW5pdGlvbiA/IHtcbiAgICAgICAgICAgICAgICAgICAgbDogYmwsXG4gICAgICAgICAgICAgICAgICAgIGRlZjogcG9zaXRpb25zW2JsXSA/IHBvc2l0aW9uc1tibF0ubWF0Y2ggOiB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICB9IDogYmw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhck9wdGlvbmFsVGFpbChidWZmZXIpIHtcbiAgICAgICAgICAgICAgICBidWZmZXIubGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSBnZXRNYXNrVGVtcGxhdGUodHJ1ZSwgMCwgdHJ1ZSwgdW5kZWZpbmVkLCB0cnVlKSwgbG1udCwgdmFsaWRQb3M7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGxtbnQgPSB0ZW1wbGF0ZS5zaGlmdCgpLCBsbW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYnVmZmVyLnB1c2gobG1udCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NvbXBsZXRlKGJ1ZmZlcikge1xuICAgICAgICAgICAgICAgIGlmICgkLmlzRnVuY3Rpb24ob3B0cy5pc0NvbXBsZXRlKSkgcmV0dXJuIG9wdHMuaXNDb21wbGV0ZShidWZmZXIsIG9wdHMpO1xuICAgICAgICAgICAgICAgIGlmIChvcHRzLnJlcGVhdCA9PT0gXCIqXCIpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdmFyIGNvbXBsZXRlID0gZmFsc2UsIGxycCA9IGRldGVybWluZUxhc3RSZXF1aXJlZFBvc2l0aW9uKHRydWUpLCBhbWwgPSBzZWVrUHJldmlvdXMobHJwLmwpO1xuICAgICAgICAgICAgICAgIGlmIChscnAuZGVmID09PSB1bmRlZmluZWQgfHwgbHJwLmRlZi5uZXdCbG9ja01hcmtlciB8fCBscnAuZGVmLm9wdGlvbmFsaXR5IHx8IGxycC5kZWYub3B0aW9uYWxRdWFudGlmaWVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gYW1sOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ZXN0ID0gZ2V0VGVzdFRlbXBsYXRlKGkpLm1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3QuZm4gIT09IG51bGwgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldID09PSB1bmRlZmluZWQgJiYgdGVzdC5vcHRpb25hbGl0eSAhPT0gdHJ1ZSAmJiB0ZXN0Lm9wdGlvbmFsUXVhbnRpZmllciAhPT0gdHJ1ZSB8fCB0ZXN0LmZuID09PSBudWxsICYmIGJ1ZmZlcltpXSAhPT0gZ2V0UGxhY2Vob2xkZXIoaSwgdGVzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBjb21wbGV0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVJlbW92ZShpbnB1dCwgaywgcG9zLCBzdHJpY3QsIGZyb21Jc1ZhbGlkKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9wdHMubnVtZXJpY0lucHV0IHx8IGlzUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrID09PSBJbnB1dG1hc2sua2V5Q29kZS5CQUNLU1BBQ0UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGsgPSBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuREVMRVRFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrID0gSW5wdXRtYXNrLmtleUNvZGUuQkFDS1NQQUNFO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1JUTCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBlbmQgPSBwb3MuZW5kO1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmVuZCA9IHBvcy5iZWdpbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5iZWdpbiA9IHBlbmQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLkJBQ0tTUEFDRSAmJiBwb3MuZW5kIC0gcG9zLmJlZ2luIDwgMSkge1xuICAgICAgICAgICAgICAgICAgICBwb3MuYmVnaW4gPSBzZWVrUHJldmlvdXMocG9zLmJlZ2luKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MuYmVnaW5dICE9PSB1bmRlZmluZWQgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvcy5iZWdpbl0uaW5wdXQgPT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5iZWdpbi0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChrID09PSBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEUgJiYgcG9zLmJlZ2luID09PSBwb3MuZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvcy5lbmQgPSBpc01hc2socG9zLmVuZCwgdHJ1ZSkgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvcy5lbmRdICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MuZW5kXS5pbnB1dCAhPT0gb3B0cy5yYWRpeFBvaW50ID8gcG9zLmVuZCArIDEgOiBzZWVrTmV4dChwb3MuZW5kKSArIDE7XG4gICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zLmJlZ2luXSAhPT0gdW5kZWZpbmVkICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MuYmVnaW5dLmlucHV0ID09PSBvcHRzLmdyb3VwU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3MuZW5kKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV2YWxpZGF0ZU1hc2socG9zKTtcbiAgICAgICAgICAgICAgICBpZiAoc3RyaWN0ICE9PSB0cnVlICYmIG9wdHMua2VlcFN0YXRpYyAhPT0gZmFsc2UgfHwgb3B0cy5yZWdleCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gYWx0ZXJuYXRlKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3UG9zID0gcmVzdWx0LmNhcmV0ICE9PSB1bmRlZmluZWQgPyByZXN1bHQuY2FyZXQgOiByZXN1bHQucG9zID8gc2Vla05leHQocmVzdWx0LnBvcy5iZWdpbiA/IHJlc3VsdC5wb3MuYmVnaW4gOiByZXN1bHQucG9zKSA6IGdldExhc3RWYWxpZFBvc2l0aW9uKC0xLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrICE9PSBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEUgfHwgcG9zLmJlZ2luID4gbmV3UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmJlZ2luID09IG5ld1BvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24ocG9zLmJlZ2luLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBpZiAobHZwIDwgcG9zLmJlZ2luIHx8IHBvcy5iZWdpbiA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnAgPSBzZWVrTmV4dChsdnApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RyaWN0ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5wID0gcG9zLmJlZ2luO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZnJvbUlzVmFsaWQgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChnZXRNYXNrU2V0KCkucCA8IGx2cCAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbZ2V0TWFza1NldCgpLnBdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkucCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5pdGlhbGl6ZUNvbG9yTWFzayhpbnB1dCkge1xuICAgICAgICAgICAgICAgIHZhciBjb21wdXRlZFN0eWxlID0gKGlucHV0Lm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcgfHwgd2luZG93KS5nZXRDb21wdXRlZFN0eWxlKGlucHV0LCBudWxsKTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBmaW5kQ2FyZXRQb3MoY2xpZW50eCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpLCBjYXJldFBvcztcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgc3R5bGUgaW4gY29tcHV0ZWRTdHlsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmFOKHN0eWxlKSAmJiBzdHlsZS5pbmRleE9mKFwiZm9udFwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnN0eWxlW3N0eWxlXSA9IGNvbXB1dGVkU3R5bGVbc3R5bGVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGUuc3R5bGUudGV4dFRyYW5zZm9ybSA9IGNvbXB1dGVkU3R5bGUudGV4dFRyYW5zZm9ybTtcbiAgICAgICAgICAgICAgICAgICAgZS5zdHlsZS5sZXR0ZXJTcGFjaW5nID0gY29tcHV0ZWRTdHlsZS5sZXR0ZXJTcGFjaW5nO1xuICAgICAgICAgICAgICAgICAgICBlLnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICAgICAgICAgICAgICBlLnN0eWxlLmhlaWdodCA9IFwiYXV0b1wiO1xuICAgICAgICAgICAgICAgICAgICBlLnN0eWxlLndpZHRoID0gXCJhdXRvXCI7XG4gICAgICAgICAgICAgICAgICAgIGUuc3R5bGUudmlzaWJpbGl0eSA9IFwiaGlkZGVuXCI7XG4gICAgICAgICAgICAgICAgICAgIGUuc3R5bGUud2hpdGVTcGFjZSA9IFwibm93cmFwXCI7XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dFRleHQgPSBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCksIHByZXZpb3VzV2lkdGggPSAwLCBpdGw7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY2FyZXRQb3MgPSAwLCBpdGwgPSBpbnB1dFRleHQubGVuZ3RoOyBjYXJldFBvcyA8PSBpdGw7IGNhcmV0UG9zKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuaW5uZXJIVE1MICs9IGlucHV0VGV4dC5jaGFyQXQoY2FyZXRQb3MpIHx8IFwiX1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUub2Zmc2V0V2lkdGggPj0gY2xpZW50eCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvZmZzZXQxID0gY2xpZW50eCAtIHByZXZpb3VzV2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9mZnNldDIgPSBlLm9mZnNldFdpZHRoIC0gY2xpZW50eDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLmlubmVySFRNTCA9IGlucHV0VGV4dC5jaGFyQXQoY2FyZXRQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldDEgLT0gZS5vZmZzZXRXaWR0aCAvIDM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3MgPSBvZmZzZXQxIDwgb2Zmc2V0MiA/IGNhcmV0UG9zIC0gMSA6IGNhcmV0UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNXaWR0aCA9IGUub2Zmc2V0V2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhcmV0UG9zO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlLnN0eWxlLndpZHRoID0gY29tcHV0ZWRTdHlsZS53aWR0aDtcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5zdHlsZS50ZXh0QWxpZ24gPSBjb21wdXRlZFN0eWxlLnRleHRBbGlnbjtcbiAgICAgICAgICAgICAgICBjb2xvck1hc2sgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICAgICAgICAgIGlucHV0LmlucHV0bWFzay5jb2xvck1hc2sgPSBjb2xvck1hc2s7XG4gICAgICAgICAgICAgICAgY29sb3JNYXNrLmNsYXNzTmFtZSA9IFwiaW0tY29sb3JtYXNrXCI7XG4gICAgICAgICAgICAgICAgaW5wdXQucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoY29sb3JNYXNrLCBpbnB1dCk7XG4gICAgICAgICAgICAgICAgaW5wdXQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChpbnB1dCk7XG4gICAgICAgICAgICAgICAgY29sb3JNYXNrLmFwcGVuZENoaWxkKGlucHV0KTtcbiAgICAgICAgICAgICAgICBjb2xvck1hc2suYXBwZW5kQ2hpbGQodGVtcGxhdGUpO1xuICAgICAgICAgICAgICAgIGlucHV0LnN0eWxlLmxlZnQgPSB0ZW1wbGF0ZS5vZmZzZXRMZWZ0ICsgXCJweFwiO1xuICAgICAgICAgICAgICAgICQoY29sb3JNYXNrKS5vbihcIm1vdXNlbGVhdmVcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRXZlbnRIYW5kbGVycy5tb3VzZWxlYXZlRXZlbnQuY2FsbChpbnB1dCwgWyBlIF0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICQoY29sb3JNYXNrKS5vbihcIm1vdXNlZW50ZXJcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRXZlbnRIYW5kbGVycy5tb3VzZWVudGVyRXZlbnQuY2FsbChpbnB1dCwgWyBlIF0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICQoY29sb3JNYXNrKS5vbihcImNsaWNrXCIsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIGZpbmRDYXJldFBvcyhlLmNsaWVudFgpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEV2ZW50SGFuZGxlcnMuY2xpY2tFdmVudC5jYWxsKGlucHV0LCBbIGUgXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJDb2xvck1hc2soaW5wdXQsIGNhcmV0UG9zLCBjbGVhcikge1xuICAgICAgICAgICAgICAgIHZhciBtYXNrVGVtcGxhdGUgPSBbXSwgaXNTdGF0aWMgPSBmYWxzZSwgdGVzdCwgdGVzdFBvcywgbmR4SW50bHpyLCBwb3MgPSAwO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHNldEVudHJ5KGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbnRyeSA9PT0gdW5kZWZpbmVkKSBlbnRyeSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNTdGF0aWMgJiYgKHRlc3QuZm4gPT09IG51bGwgfHwgdGVzdFBvcy5pbnB1dCA9PT0gdW5kZWZpbmVkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNTdGF0aWMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFza1RlbXBsYXRlLnB1c2goXCI8c3BhbiBjbGFzcz0naW0tc3RhdGljJz5cIiArIGVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1N0YXRpYyAmJiAodGVzdC5mbiAhPT0gbnVsbCAmJiB0ZXN0UG9zLmlucHV0ICE9PSB1bmRlZmluZWQgfHwgdGVzdC5kZWYgPT09IFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1N0YXRpYyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG10bCA9IG1hc2tUZW1wbGF0ZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrVGVtcGxhdGVbbXRsIC0gMV0gPSBtYXNrVGVtcGxhdGVbbXRsIC0gMV0gKyBcIjwvc3Bhbj5cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUZW1wbGF0ZS5wdXNoKGVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIG1hc2tUZW1wbGF0ZS5wdXNoKGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gc2V0Q2FyZXQoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSBpbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFza1RlbXBsYXRlLnNwbGljZShjYXJldFBvcy5iZWdpbiwgMCwgY2FyZXRQb3MuYmVnaW4gPT09IGNhcmV0UG9zLmVuZCB8fCBjYXJldFBvcy5lbmQgPiBnZXRNYXNrU2V0KCkubWFza0xlbmd0aCA/ICc8bWFyayBjbGFzcz1cImltLWNhcmV0XCIgc3R5bGU9XCJib3JkZXItcmlnaHQtd2lkdGg6IDFweDtib3JkZXItcmlnaHQtc3R5bGU6IHNvbGlkO1wiPicgOiAnPG1hcmsgY2xhc3M9XCJpbS1jYXJldC1zZWxlY3RcIj4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUZW1wbGF0ZS5zcGxpY2UoY2FyZXRQb3MuZW5kICsgMSwgMCwgXCI8L21hcms+XCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjb2xvck1hc2sgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gZ2V0QnVmZmVyKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjYXJldFBvcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvcyA9IGNhcmV0KGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjYXJldFBvcy5iZWdpbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogY2FyZXRQb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBjYXJldFBvc1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoY2xlYXIgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0UG9zID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSB0ZXN0UG9zLm1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0RW50cnkoYnVmZmVyW3Bvc10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RQb3MgPSBnZXRUZXN0VGVtcGxhdGUocG9zLCBuZHhJbnRsenIsIHBvcyAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gdGVzdFBvcy5tYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmR4SW50bHpyID0gdGVzdFBvcy5sb2NhdG9yLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmppdE1hc2tpbmcgPT09IGZhbHNlIHx8IHBvcyA8IGx2cCB8fCB0eXBlb2Ygb3B0cy5qaXRNYXNraW5nID09PSBcIm51bWJlclwiICYmIGlzRmluaXRlKG9wdHMuaml0TWFza2luZykgJiYgb3B0cy5qaXRNYXNraW5nID4gcG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRFbnRyeShnZXRQbGFjZWhvbGRlcihwb3MsIHRlc3QpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlzU3RhdGljID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSB3aGlsZSAoKG1heExlbmd0aCA9PT0gdW5kZWZpbmVkIHx8IHBvcyA8IG1heExlbmd0aCkgJiYgKHRlc3QuZm4gIT09IG51bGwgfHwgdGVzdC5kZWYgIT09IFwiXCIpIHx8IGx2cCA+IHBvcyB8fCBpc1N0YXRpYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNTdGF0aWMpIHNldEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRDYXJldCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IGNvbG9yTWFzay5nZXRFbGVtZW50c0J5VGFnTmFtZShcImRpdlwiKVswXTtcbiAgICAgICAgICAgICAgICAgICAgdGVtcGxhdGUuaW5uZXJIVE1MID0gbWFza1RlbXBsYXRlLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0LmlucHV0bWFzay5wb3NpdGlvbkNvbG9yTWFzayhpbnB1dCwgdGVtcGxhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIG1hc2soZWxlbSkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzRWxlbWVudFR5cGVTdXBwb3J0ZWQoaW5wdXQsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hWYWx1ZVByb3BlcnR5KG5wdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlR2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlU2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hWYWxob29rKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJC52YWxIb29rcyAmJiAoJC52YWxIb29rc1t0eXBlXSA9PT0gdW5kZWZpbmVkIHx8ICQudmFsSG9va3NbdHlwZV0uaW5wdXRtYXNrcGF0Y2ggIT09IHRydWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWxob29rR2V0ID0gJC52YWxIb29rc1t0eXBlXSAmJiAkLnZhbEhvb2tzW3R5cGVdLmdldCA/ICQudmFsSG9va3NbdHlwZV0uZ2V0IDogZnVuY3Rpb24oZWxlbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW0udmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWxob29rU2V0ID0gJC52YWxIb29rc1t0eXBlXSAmJiAkLnZhbEhvb2tzW3R5cGVdLnNldCA/ICQudmFsSG9va3NbdHlwZV0uc2V0IDogZnVuY3Rpb24oZWxlbSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0udmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLnZhbEhvb2tzW3R5cGVdID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoZWxlbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtLmlucHV0bWFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbS5pbnB1dG1hc2sub3B0cy5hdXRvVW5tYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZWxlbS5pbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHZhbGhvb2tHZXQoZWxlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TGFzdFZhbGlkUG9zaXRpb24odW5kZWZpbmVkLCB1bmRlZmluZWQsIGVsZW0uaW5wdXRtYXNrLm1hc2tzZXQudmFsaWRQb3NpdGlvbnMpICE9PSAtMSB8fCBvcHRzLm51bGxhYmxlICE9PSB0cnVlID8gcmVzdWx0IDogXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSByZXR1cm4gdmFsaG9va0dldChlbGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uIHNldChlbGVtLCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkZWxlbSA9ICQoZWxlbSksIHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB2YWxob29rU2V0KGVsZW0sIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbS5pbnB1dG1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVsZW0udHJpZ2dlcihcInNldHZhbHVlXCIsIFsgdmFsdWUgXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRtYXNrcGF0Y2g6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXR0ZXIoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRtYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmlucHV0bWFzay5vcHRzLmF1dG9Vbm1hc2sgPyB0aGlzLmlucHV0bWFzay51bm1hc2tlZHZhbHVlKCkgOiBnZXRMYXN0VmFsaWRQb3NpdGlvbigpICE9PSAtMSB8fCBvcHRzLm51bGxhYmxlICE9PSB0cnVlID8gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gdGhpcyAmJiBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzID8gKGlzUlRMID8gY2xlYXJPcHRpb25hbFRhaWwoZ2V0QnVmZmVyKCkuc2xpY2UoKSkucmV2ZXJzZSgpIDogY2xlYXJPcHRpb25hbFRhaWwoZ2V0QnVmZmVyKCkuc2xpY2UoKSkpLmpvaW4oXCJcIikgOiB2YWx1ZUdldC5jYWxsKHRoaXMpIDogXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgcmV0dXJuIHZhbHVlR2V0LmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBzZXR0ZXIodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldC5jYWxsKHRoaXMsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dG1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS50cmlnZ2VyKFwic2V0dmFsdWVcIiwgWyB2YWx1ZSBdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBpbnN0YWxsTmF0aXZlVmFsdWVTZXRGYWxsYmFjayhucHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKG5wdCwgXCJtb3VzZWVudGVyXCIsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkaW5wdXQgPSAkKHRoaXMpLCBpbnB1dCA9IHRoaXMsIHZhbHVlID0gaW5wdXQuaW5wdXRtYXNrLl92YWx1ZUdldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgIT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbnB0LmlucHV0bWFzay5fX3ZhbHVlR2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMubm9WYWx1ZVBhdGNoaW5nICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE9iamVjdC5nZXRQcm90b3R5cGVPZiAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmdldFByb3RvdHlwZU9mID0gX3R5cGVvZihcInRlc3RcIi5fX3Byb3RvX18pID09PSBcIm9iamVjdFwiID8gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3QuX19wcm90b19fO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gOiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdC5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZVByb3BlcnR5ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihPYmplY3QuZ2V0UHJvdG90eXBlT2YobnB0KSwgXCJ2YWx1ZVwiKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZVByb3BlcnR5ICYmIHZhbHVlUHJvcGVydHkuZ2V0ICYmIHZhbHVlUHJvcGVydHkuc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVHZXQgPSB2YWx1ZVByb3BlcnR5LmdldDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldCA9IHZhbHVlUHJvcGVydHkuc2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShucHQsIFwidmFsdWVcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGdldHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0OiBzZXR0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChucHQudGFnTmFtZSAhPT0gXCJJTlBVVFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVHZXQgPSBmdW5jdGlvbiB2YWx1ZUdldCgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudGV4dENvbnRlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldCA9IGZ1bmN0aW9uIHZhbHVlU2V0KHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dENvbnRlbnQgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShucHQsIFwidmFsdWVcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGdldHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0OiBzZXR0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRvY3VtZW50Ll9fbG9va3VwR2V0dGVyX18gJiYgbnB0Ll9fbG9va3VwR2V0dGVyX18oXCJ2YWx1ZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVHZXQgPSBucHQuX19sb29rdXBHZXR0ZXJfXyhcInZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVTZXQgPSBucHQuX19sb29rdXBTZXR0ZXJfXyhcInZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnB0Ll9fZGVmaW5lR2V0dGVyX18oXCJ2YWx1ZVwiLCBnZXR0ZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnB0Ll9fZGVmaW5lU2V0dGVyX18oXCJ2YWx1ZVwiLCBzZXR0ZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5wdC5pbnB1dG1hc2suX192YWx1ZUdldCA9IHZhbHVlR2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBucHQuaW5wdXRtYXNrLl9fdmFsdWVTZXQgPSB2YWx1ZVNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbnB0LmlucHV0bWFzay5fdmFsdWVHZXQgPSBmdW5jdGlvbihvdmVycnVsZVJUTCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNSVEwgJiYgb3ZlcnJ1bGVSVEwgIT09IHRydWUgPyB2YWx1ZUdldC5jYWxsKHRoaXMuZWwpLnNwbGl0KFwiXCIpLnJldmVyc2UoKS5qb2luKFwiXCIpIDogdmFsdWVHZXQuY2FsbCh0aGlzLmVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5wdC5pbnB1dG1hc2suX3ZhbHVlU2V0ID0gZnVuY3Rpb24odmFsdWUsIG92ZXJydWxlUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlU2V0LmNhbGwodGhpcy5lbCwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCA/IFwiXCIgOiBvdmVycnVsZVJUTCAhPT0gdHJ1ZSAmJiBpc1JUTCA/IHZhbHVlLnNwbGl0KFwiXCIpLnJldmVyc2UoKS5qb2luKFwiXCIpIDogdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlR2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVHZXQgPSBmdW5jdGlvbiB2YWx1ZUdldCgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldCA9IGZ1bmN0aW9uIHZhbHVlU2V0KHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoVmFsaG9vayhucHQudHlwZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbGxOYXRpdmVWYWx1ZVNldEZhbGxiYWNrKG5wdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBlbGVtZW50VHlwZSA9IGlucHV0LmdldEF0dHJpYnV0ZShcInR5cGVcIik7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpc1N1cHBvcnRlZCA9IGlucHV0LnRhZ05hbWUgPT09IFwiSU5QVVRcIiAmJiAkLmluQXJyYXkoZWxlbWVudFR5cGUsIG9wdHMuc3VwcG9ydHNJbnB1dFR5cGUpICE9PSAtMSB8fCBpbnB1dC5pc0NvbnRlbnRFZGl0YWJsZSB8fCBpbnB1dC50YWdOYW1lID09PSBcIlRFWFRBUkVBXCI7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNTdXBwb3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC50YWdOYW1lID09PSBcIklOUFVUXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuc2V0QXR0cmlidXRlKFwidHlwZVwiLCBlbGVtZW50VHlwZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNTdXBwb3J0ZWQgPSBlbC50eXBlID09PSBcInRleHRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbCA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaXNTdXBwb3J0ZWQgPSBcInBhcnRpYWxcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNTdXBwb3J0ZWQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFZhbHVlUHJvcGVydHkoaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaW5wdXQuaW5wdXRtYXNrID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNTdXBwb3J0ZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub2ZmKGVsZW0pO1xuICAgICAgICAgICAgICAgIHZhciBpc1N1cHBvcnRlZCA9IGlzRWxlbWVudFR5cGVTdXBwb3J0ZWQoZWxlbSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgaWYgKGlzU3VwcG9ydGVkICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICBlbCA9IGVsZW07XG4gICAgICAgICAgICAgICAgICAgICRlbCA9ICQoZWwpO1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbFBsYWNlaG9sZGVyID0gZWwucGxhY2Vob2xkZXI7XG4gICAgICAgICAgICAgICAgICAgIG1heExlbmd0aCA9IGVsICE9PSB1bmRlZmluZWQgPyBlbC5tYXhMZW5ndGggOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXhMZW5ndGggPT09IC0xKSBtYXhMZW5ndGggPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmNvbG9yTWFzayA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbGl6ZUNvbG9yTWFzayhlbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vYmlsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwiaW5wdXRNb2RlXCIgaW4gZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1vZGUgPSBvcHRzLmlucHV0bW9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoXCJpbnB1dG1vZGVcIiwgb3B0cy5pbnB1dG1vZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuZGlzYWJsZVByZWRpY3RpdmVUZXh0ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFwiYXV0b2NvcnJlY3RcIiBpbiBlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5hdXRvY29ycmVjdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmNvbG9yTWFzayAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbGl6ZUNvbG9yTWFzayhlbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwudHlwZSA9IFwicGFzc3dvcmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzU3VwcG9ydGVkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoXCJpbS1pbnNlcnRcIiwgb3B0cy5pbnNlcnRNb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwic3VibWl0XCIsIEV2ZW50SGFuZGxlcnMuc3VibWl0RXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJyZXNldFwiLCBFdmVudEhhbmRsZXJzLnJlc2V0RXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJibHVyXCIsIEV2ZW50SGFuZGxlcnMuYmx1ckV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiZm9jdXNcIiwgRXZlbnRIYW5kbGVycy5mb2N1c0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmNvbG9yTWFzayAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiY2xpY2tcIiwgRXZlbnRIYW5kbGVycy5jbGlja0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcIm1vdXNlbGVhdmVcIiwgRXZlbnRIYW5kbGVycy5tb3VzZWxlYXZlRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwibW91c2VlbnRlclwiLCBFdmVudEhhbmRsZXJzLm1vdXNlZW50ZXJFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcInBhc3RlXCIsIEV2ZW50SGFuZGxlcnMucGFzdGVFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcImN1dFwiLCBFdmVudEhhbmRsZXJzLmN1dEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiY29tcGxldGVcIiwgb3B0cy5vbmNvbXBsZXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiaW5jb21wbGV0ZVwiLCBvcHRzLm9uaW5jb21wbGV0ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcImNsZWFyZWRcIiwgb3B0cy5vbmNsZWFyZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFtb2JpbGUgJiYgb3B0cy5pbnB1dEV2ZW50T25seSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwia2V5ZG93blwiLCBFdmVudEhhbmRsZXJzLmtleWRvd25FdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJrZXlwcmVzc1wiLCBFdmVudEhhbmRsZXJzLmtleXByZXNzRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5yZW1vdmVBdHRyaWJ1dGUoXCJtYXhMZW5ndGhcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcImlucHV0XCIsIEV2ZW50SGFuZGxlcnMuaW5wdXRGYWxsQmFja0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiYmVmb3JlaW5wdXRcIiwgRXZlbnRIYW5kbGVycy5iZWZvcmVJbnB1dEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcInNldHZhbHVlXCIsIEV2ZW50SGFuZGxlcnMuc2V0VmFsdWVFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgIHVuZG9WYWx1ZSA9IGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsLmlucHV0bWFzay5fdmFsdWVHZXQodHJ1ZSkgIT09IFwiXCIgfHwgb3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cyA9PT0gZmFsc2UgfHwgZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbml0aWFsVmFsdWUgPSAkLmlzRnVuY3Rpb24ob3B0cy5vbkJlZm9yZU1hc2spID8gb3B0cy5vbkJlZm9yZU1hc2suY2FsbChpbnB1dG1hc2ssIGVsLmlucHV0bWFzay5fdmFsdWVHZXQodHJ1ZSksIG9wdHMpIHx8IGVsLmlucHV0bWFzay5fdmFsdWVHZXQodHJ1ZSkgOiBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluaXRpYWxWYWx1ZSAhPT0gXCJcIikgY2hlY2tWYWwoZWwsIHRydWUsIGZhbHNlLCBpbml0aWFsVmFsdWUuc3BsaXQoXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IGdldEJ1ZmZlcigpLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB1bmRvVmFsdWUgPSBidWZmZXIuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0NvbXBsZXRlKGJ1ZmZlcikgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY2xlYXJJbmNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzICYmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgIT09IGVsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldExhc3RWYWxpZFBvc2l0aW9uKCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyT3B0aW9uYWxUYWlsKGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgPT09IGZhbHNlIHx8IG9wdHMuc2hvd01hc2tPbkZvY3VzICYmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGVsIHx8IGVsLmlucHV0bWFzay5fdmFsdWVHZXQodHJ1ZSkgIT09IFwiXCIpIHdyaXRlQnVmZmVyKGVsLCBidWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGVsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoZWwsIHNlZWtOZXh0KGdldExhc3RWYWxpZFBvc2l0aW9uKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB2YWx1ZUJ1ZmZlcjtcbiAgICAgICAgICAgIGlmIChhY3Rpb25PYmogIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoYWN0aW9uT2JqLmFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgY2FzZSBcImlzQ29tcGxldGVcIjpcbiAgICAgICAgICAgICAgICAgICAgZWwgPSBhY3Rpb25PYmouZWw7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpc0NvbXBsZXRlKGdldEJ1ZmZlcigpKTtcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcInVubWFza2VkdmFsdWVcIjpcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsID09PSB1bmRlZmluZWQgfHwgYWN0aW9uT2JqLnZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlQnVmZmVyID0gYWN0aW9uT2JqLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVCdWZmZXIgPSAoJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVNYXNrKSA/IG9wdHMub25CZWZvcmVNYXNrLmNhbGwoaW5wdXRtYXNrLCB2YWx1ZUJ1ZmZlciwgb3B0cykgfHwgdmFsdWVCdWZmZXIgOiB2YWx1ZUJ1ZmZlcikuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGVja1ZhbC5jYWxsKHRoaXMsIHVuZGVmaW5lZCwgZmFsc2UsIGZhbHNlLCB2YWx1ZUJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVXcml0ZSkpIG9wdHMub25CZWZvcmVXcml0ZS5jYWxsKGlucHV0bWFzaywgdW5kZWZpbmVkLCBnZXRCdWZmZXIoKSwgMCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVubWFza2VkdmFsdWUoZWwpO1xuXG4gICAgICAgICAgICAgICAgICBjYXNlIFwibWFza1wiOlxuICAgICAgICAgICAgICAgICAgICBtYXNrKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJmb3JtYXRcIjpcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVCdWZmZXIgPSAoJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVNYXNrKSA/IG9wdHMub25CZWZvcmVNYXNrLmNhbGwoaW5wdXRtYXNrLCBhY3Rpb25PYmoudmFsdWUsIG9wdHMpIHx8IGFjdGlvbk9iai52YWx1ZSA6IGFjdGlvbk9iai52YWx1ZSkuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrVmFsLmNhbGwodGhpcywgdW5kZWZpbmVkLCB0cnVlLCBmYWxzZSwgdmFsdWVCdWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYWN0aW9uT2JqLm1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBpc1JUTCA/IGdldEJ1ZmZlcigpLnNsaWNlKCkucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBnZXRCdWZmZXIoKS5qb2luKFwiXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiBtYXNrU2NvcGUuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbjogXCJnZXRtZXRhZGF0YVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgbWFza3NldCwgb3B0cylcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzUlRMID8gZ2V0QnVmZmVyKCkuc2xpY2UoKS5yZXZlcnNlKCkuam9pbihcIlwiKSA6IGdldEJ1ZmZlcigpLmpvaW4oXCJcIik7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJpc1ZhbGlkXCI6XG4gICAgICAgICAgICAgICAgICAgIGlmIChhY3Rpb25PYmoudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlQnVmZmVyID0gYWN0aW9uT2JqLnZhbHVlLnNwbGl0KFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tWYWwuY2FsbCh0aGlzLCB1bmRlZmluZWQsIHRydWUsIHRydWUsIHZhbHVlQnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbk9iai52YWx1ZSA9IGdldEJ1ZmZlcigpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IGdldEJ1ZmZlcigpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmwgPSBkZXRlcm1pbmVMYXN0UmVxdWlyZWRQb3NpdGlvbigpLCBsbWliID0gYnVmZmVyLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoO2xtaWIgPiBybDsgbG1pYi0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNNYXNrKGxtaWIpKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBidWZmZXIuc3BsaWNlKHJsLCBsbWliICsgMSAtIHJsKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzQ29tcGxldGUoYnVmZmVyKSAmJiBhY3Rpb25PYmoudmFsdWUgPT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIik7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJnZXRlbXB0eW1hc2tcIjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKTtcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcInJlbW92ZVwiOlxuICAgICAgICAgICAgICAgICAgICBpZiAoZWwgJiYgZWwuaW5wdXRtYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkLmRhdGEoZWwsIFwiX2lucHV0bWFza19vcHRzXCIsIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGVsID0gJChlbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2suX3ZhbHVlU2V0KG9wdHMuYXV0b1VubWFzayA/IHVubWFza2VkdmFsdWUoZWwpIDogZWwuaW5wdXRtYXNrLl92YWx1ZUdldCh0cnVlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9mZihlbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWwuaW5wdXRtYXNrLmNvbG9yTWFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yTWFzayA9IGVsLmlucHV0bWFzay5jb2xvck1hc2s7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JNYXNrLnJlbW92ZUNoaWxkKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvck1hc2sucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoZWwsIGNvbG9yTWFzayk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JNYXNrLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY29sb3JNYXNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZVByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVQcm9wZXJ0eSA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoT2JqZWN0LmdldFByb3RvdHlwZU9mKGVsKSwgXCJ2YWx1ZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWVQcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWwuaW5wdXRtYXNrLl9fdmFsdWVHZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlbCwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0OiBlbC5pbnB1dG1hc2suX192YWx1ZUdldCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXQ6IGVsLmlucHV0bWFzay5fX3ZhbHVlU2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRvY3VtZW50Ll9fbG9va3VwR2V0dGVyX18gJiYgZWwuX19sb29rdXBHZXR0ZXJfXyhcInZhbHVlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsLmlucHV0bWFzay5fX3ZhbHVlR2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLl9fZGVmaW5lR2V0dGVyX18oXCJ2YWx1ZVwiLCBlbC5pbnB1dG1hc2suX192YWx1ZUdldCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLl9fZGVmaW5lU2V0dGVyX18oXCJ2YWx1ZVwiLCBlbC5pbnB1dG1hc2suX192YWx1ZVNldCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBlbDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJnZXRtZXRhZGF0YVwiOlxuICAgICAgICAgICAgICAgICAgICBpZiAoJC5pc0FycmF5KG1hc2tzZXQubWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWFza1RhcmdldCA9IGdldE1hc2tUZW1wbGF0ZSh0cnVlLCAwLCBmYWxzZSkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChtYXNrc2V0Lm1ldGFkYXRhLCBmdW5jdGlvbihuZHgsIG10ZHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobXRkdC5tYXNrID09PSBtYXNrVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUYXJnZXQgPSBtdGR0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza1RhcmdldDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza3NldC5tZXRhZGF0YTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIElucHV0bWFzaztcbiAgICB9KTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fO1xuICAgIHZhciBfdHlwZW9mID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgfSA6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICB9O1xuICAgIChmdW5jdGlvbihmYWN0b3J5KSB7XG4gICAgICAgIGlmICh0cnVlKSB7XG4gICAgICAgICAgICAhKF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18gPSBbIF9fd2VicGFja19yZXF1aXJlX18oNCkgXSwgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID0gZmFjdG9yeSwgXG4gICAgICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyA9IHR5cGVvZiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPT09IFwiZnVuY3Rpb25cIiA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgXG4gICAgICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyAhPT0gdW5kZWZpbmVkICYmIChtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fKSk7XG4gICAgICAgIH0gZWxzZSB7fVxuICAgIH0pKGZ1bmN0aW9uKCQpIHtcbiAgICAgICAgcmV0dXJuICQ7XG4gICAgfSk7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGpRdWVyeTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXztcbiAgICB2YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2Ygb2JqO1xuICAgIH0gOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7XG4gICAgfTtcbiAgICBpZiAodHJ1ZSkgIShfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IG5ldyAoZXZhbChcInJlcXVpcmUoJ2pzZG9tJykuSlNET01cIikpKFwiXCIpLndpbmRvdztcbiAgICB9LmNhbGwoZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXywgZXhwb3J0cywgbW9kdWxlKSwgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gIT09IHVuZGVmaW5lZCAmJiAobW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXykpOyBlbHNlIHt9XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICB2YXIgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXztcbiAgICB2YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2Ygb2JqO1xuICAgIH0gOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7XG4gICAgfTtcbiAgICAoZnVuY3Rpb24oZmFjdG9yeSkge1xuICAgICAgICBpZiAodHJ1ZSkge1xuICAgICAgICAgICAgIShfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fID0gWyBfX3dlYnBhY2tfcmVxdWlyZV9fKDIpIF0sIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9IGZhY3RvcnksIFxuICAgICAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSB0eXBlb2YgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID09PSBcImZ1bmN0aW9uXCIgPyBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18uYXBwbHkoZXhwb3J0cywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXykgOiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIFxuICAgICAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gIT09IHVuZGVmaW5lZCAmJiAobW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXykpO1xuICAgICAgICB9IGVsc2Uge31cbiAgICB9KShmdW5jdGlvbihJbnB1dG1hc2spIHtcbiAgICAgICAgdmFyICQgPSBJbnB1dG1hc2suZGVwZW5kZW5jeUxpYjtcbiAgICAgICAgdmFyIGZvcm1hdENvZGUgPSB7XG4gICAgICAgICAgICBkOiBbIFwiWzEtOV18WzEyXVswLTldfDNbMDFdXCIsIERhdGUucHJvdG90eXBlLnNldERhdGUsIFwiZGF5XCIsIERhdGUucHJvdG90eXBlLmdldERhdGUgXSxcbiAgICAgICAgICAgIGRkOiBbIFwiMFsxLTldfFsxMl1bMC05XXwzWzAxXVwiLCBEYXRlLnByb3RvdHlwZS5zZXREYXRlLCBcImRheVwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldERhdGUuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICBkZGQ6IFsgXCJcIiBdLFxuICAgICAgICAgICAgZGRkZDogWyBcIlwiIF0sXG4gICAgICAgICAgICBtOiBbIFwiWzEtOV18MVswMTJdXCIsIERhdGUucHJvdG90eXBlLnNldE1vbnRoLCBcIm1vbnRoXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEYXRlLnByb3RvdHlwZS5nZXRNb250aC5jYWxsKHRoaXMpICsgMTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIG1tOiBbIFwiMFsxLTldfDFbMDEyXVwiLCBEYXRlLnByb3RvdHlwZS5zZXRNb250aCwgXCJtb250aFwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldE1vbnRoLmNhbGwodGhpcykgKyAxLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIG1tbTogWyBcIlwiIF0sXG4gICAgICAgICAgICBtbW1tOiBbIFwiXCIgXSxcbiAgICAgICAgICAgIHl5OiBbIFwiWzAtOV17Mn1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0RnVsbFllYXIsIFwieWVhclwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldEZ1bGxZZWFyLmNhbGwodGhpcyksIDIpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgeXl5eTogWyBcIlswLTldezR9XCIsIERhdGUucHJvdG90eXBlLnNldEZ1bGxZZWFyLCBcInllYXJcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhZChEYXRlLnByb3RvdHlwZS5nZXRGdWxsWWVhci5jYWxsKHRoaXMpLCA0KTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIGg6IFsgXCJbMS05XXwxWzAtMl1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0SG91cnMsIFwiaG91cnNcIiwgRGF0ZS5wcm90b3R5cGUuZ2V0SG91cnMgXSxcbiAgICAgICAgICAgIGhoOiBbIFwiMFsxLTldfDFbMC0yXVwiLCBEYXRlLnByb3RvdHlwZS5zZXRIb3VycywgXCJob3Vyc1wiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldEhvdXJzLmNhbGwodGhpcyksIDIpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgaGhoOiBbIFwiWzAtOV0rXCIsIERhdGUucHJvdG90eXBlLnNldEhvdXJzLCBcImhvdXJzXCIsIERhdGUucHJvdG90eXBlLmdldEhvdXJzIF0sXG4gICAgICAgICAgICBIOiBbIFwiMT9bMC05XXwyWzAtM11cIiwgRGF0ZS5wcm90b3R5cGUuc2V0SG91cnMsIFwiaG91cnNcIiwgRGF0ZS5wcm90b3R5cGUuZ2V0SG91cnMgXSxcbiAgICAgICAgICAgIEhIOiBbIFwiMFswLTldfDFbMC05XXwyWzAtM11cIiwgRGF0ZS5wcm90b3R5cGUuc2V0SG91cnMsIFwiaG91cnNcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhZChEYXRlLnByb3RvdHlwZS5nZXRIb3Vycy5jYWxsKHRoaXMpLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIEhISDogWyBcIlswLTldK1wiLCBEYXRlLnByb3RvdHlwZS5zZXRIb3VycywgXCJob3Vyc1wiLCBEYXRlLnByb3RvdHlwZS5nZXRIb3VycyBdLFxuICAgICAgICAgICAgTTogWyBcIlsxLTVdP1swLTldXCIsIERhdGUucHJvdG90eXBlLnNldE1pbnV0ZXMsIFwibWludXRlc1wiLCBEYXRlLnByb3RvdHlwZS5nZXRNaW51dGVzIF0sXG4gICAgICAgICAgICBNTTogWyBcIjBbMC05XXwxWzAtOV18MlswLTldfDNbMC05XXw0WzAtOV18NVswLTldXCIsIERhdGUucHJvdG90eXBlLnNldE1pbnV0ZXMsIFwibWludXRlc1wiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldE1pbnV0ZXMuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICBzczogWyBcIlswLTVdWzAtOV1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0U2Vjb25kcywgXCJzZWNvbmRzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0U2Vjb25kcy5jYWxsKHRoaXMpLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIGw6IFsgXCJbMC05XXszfVwiLCBEYXRlLnByb3RvdHlwZS5zZXRNaWxsaXNlY29uZHMsIFwibWlsbGlzZWNvbmRzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0TWlsbGlzZWNvbmRzLmNhbGwodGhpcyksIDMpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgTDogWyBcIlswLTldezJ9XCIsIERhdGUucHJvdG90eXBlLnNldE1pbGxpc2Vjb25kcywgXCJtaWxsaXNlY29uZHNcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhZChEYXRlLnByb3RvdHlwZS5nZXRNaWxsaXNlY29uZHMuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICB0OiBbIFwiW2FwXVwiIF0sXG4gICAgICAgICAgICB0dDogWyBcIlthcF1tXCIgXSxcbiAgICAgICAgICAgIFQ6IFsgXCJbQVBdXCIgXSxcbiAgICAgICAgICAgIFRUOiBbIFwiW0FQXU1cIiBdLFxuICAgICAgICAgICAgWjogWyBcIlwiIF0sXG4gICAgICAgICAgICBvOiBbIFwiXCIgXSxcbiAgICAgICAgICAgIFM6IFsgXCJcIiBdXG4gICAgICAgIH0sIGZvcm1hdEFsaWFzID0ge1xuICAgICAgICAgICAgaXNvRGF0ZTogXCJ5eXl5LW1tLWRkXCIsXG4gICAgICAgICAgICBpc29UaW1lOiBcIkhIOk1NOnNzXCIsXG4gICAgICAgICAgICBpc29EYXRlVGltZTogXCJ5eXl5LW1tLWRkJ1QnSEg6TU06c3NcIixcbiAgICAgICAgICAgIGlzb1V0Y0RhdGVUaW1lOiBcIlVUQzp5eXl5LW1tLWRkJ1QnSEg6TU06c3MnWidcIlxuICAgICAgICB9O1xuICAgICAgICBmdW5jdGlvbiBnZXRUb2tlbml6ZXIob3B0cykge1xuICAgICAgICAgICAgaWYgKCFvcHRzLnRva2VuaXplcikge1xuICAgICAgICAgICAgICAgIHZhciB0b2tlbnMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBuZHggaW4gZm9ybWF0Q29kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodG9rZW5zLmluZGV4T2YobmR4WzBdKSA9PT0gLTEpIHRva2Vucy5wdXNoKG5keFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG9wdHMudG9rZW5pemVyID0gXCIoXCIgKyB0b2tlbnMuam9pbihcIit8XCIpICsgXCIpKz98LlwiO1xuICAgICAgICAgICAgICAgIG9wdHMudG9rZW5pemVyID0gbmV3IFJlZ0V4cChvcHRzLnRva2VuaXplciwgXCJnXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9wdHMudG9rZW5pemVyO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGlzVmFsaWREYXRlKGRhdGVQYXJ0cywgY3VycmVudFJlc3VsdCkge1xuICAgICAgICAgICAgcmV0dXJuICFpc0Zpbml0ZShkYXRlUGFydHMucmF3ZGF5KSB8fCBkYXRlUGFydHMuZGF5ID09IFwiMjlcIiAmJiAhaXNGaW5pdGUoZGF0ZVBhcnRzLnJhd3llYXIpIHx8IG5ldyBEYXRlKGRhdGVQYXJ0cy5kYXRlLmdldEZ1bGxZZWFyKCksIGlzRmluaXRlKGRhdGVQYXJ0cy5yYXdtb250aCkgPyBkYXRlUGFydHMubW9udGggOiBkYXRlUGFydHMuZGF0ZS5nZXRNb250aCgpICsgMSwgMCkuZ2V0RGF0ZSgpID49IGRhdGVQYXJ0cy5kYXkgPyBjdXJyZW50UmVzdWx0IDogZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gaXNEYXRlSW5SYW5nZShkYXRlUGFydHMsIG9wdHMpIHtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKG9wdHMubWluKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGVQYXJ0c1tcInJhd3llYXJcIl0pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJhd1llYXIgPSBkYXRlUGFydHNbXCJyYXd5ZWFyXCJdLnJlcGxhY2UoL1teMC05XS9nLCBcIlwiKSwgbWluWWVhciA9IG9wdHMubWluLnllYXIuc3Vic3RyKDAsIHJhd1llYXIubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gbWluWWVhciA8PSByYXdZZWFyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZGF0ZVBhcnRzW1wieWVhclwiXSA9PT0gZGF0ZVBhcnRzW1wicmF3eWVhclwiXSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5taW4uZGF0ZS5nZXRUaW1lKCkgPT09IG9wdHMubWluLmRhdGUuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBvcHRzLm1pbi5kYXRlLmdldFRpbWUoKSA8PSBkYXRlUGFydHMuZGF0ZS5nZXRUaW1lKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzdWx0ICYmIG9wdHMubWF4ICYmIG9wdHMubWF4LmRhdGUuZ2V0VGltZSgpID09PSBvcHRzLm1heC5kYXRlLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IG9wdHMubWF4LmRhdGUuZ2V0VGltZSgpID49IGRhdGVQYXJ0cy5kYXRlLmdldFRpbWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcGFyc2UoZm9ybWF0LCBkYXRlT2JqVmFsdWUsIG9wdHMsIHJhdykge1xuICAgICAgICAgICAgdmFyIG1hc2sgPSBcIlwiLCBtYXRjaDtcbiAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IGdldFRva2VuaXplcihvcHRzKS5leGVjKGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZU9ialZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZvcm1hdENvZGVbbWF0Y2hbMF1dKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrICs9IFwiKFwiICsgZm9ybWF0Q29kZVttYXRjaFswXV1bMF0gKyBcIilcIjtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobWF0Y2hbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIltcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrICs9IFwiKFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJdXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFzayArPSBcIik/XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrICs9IElucHV0bWFzay5lc2NhcGVSZWdleChtYXRjaFswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZm9ybWF0Q29kZVttYXRjaFswXV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYXcgIT09IHRydWUgJiYgZm9ybWF0Q29kZVttYXRjaFswXV1bM10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZ2V0Rm4gPSBmb3JtYXRDb2RlW21hdGNoWzBdXVszXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrICs9IGdldEZuLmNhbGwoZGF0ZU9ialZhbHVlLmRhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChmb3JtYXRDb2RlW21hdGNoWzBdXVsyXSkgbWFzayArPSBkYXRlT2JqVmFsdWVbXCJyYXdcIiArIGZvcm1hdENvZGVbbWF0Y2hbMF1dWzJdXTsgZWxzZSBtYXNrICs9IG1hdGNoWzBdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgbWFzayArPSBtYXRjaFswXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWFzaztcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBwYWQodmFsLCBsZW4pIHtcbiAgICAgICAgICAgIHZhbCA9IFN0cmluZyh2YWwpO1xuICAgICAgICAgICAgbGVuID0gbGVuIHx8IDI7XG4gICAgICAgICAgICB3aGlsZSAodmFsLmxlbmd0aCA8IGxlbikge1xuICAgICAgICAgICAgICAgIHZhbCA9IFwiMFwiICsgdmFsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBhbmFseXNlTWFzayhtYXNrU3RyaW5nLCBmb3JtYXQsIG9wdHMpIHtcbiAgICAgICAgICAgIHZhciBkYXRlT2JqID0ge1xuICAgICAgICAgICAgICAgIGRhdGU6IG5ldyBEYXRlKDEsIDAsIDEpXG4gICAgICAgICAgICB9LCB0YXJnZXRQcm9wLCBtYXNrID0gbWFza1N0cmluZywgbWF0Y2gsIGRhdGVPcGVyYXRpb24sIHRhcmdldFZhbGlkYXRvcjtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGV4dGVuZFByb3BlcnR5KHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvcnJlY3RlZFZhbHVlID0gdmFsdWUucmVwbGFjZSgvW14wLTldL2csIFwiMFwiKTtcbiAgICAgICAgICAgICAgICBpZiAoY29ycmVjdGVkVmFsdWUgIT0gdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVudGVyZWRQYXJ0ID0gdmFsdWUucmVwbGFjZSgvW14wLTldL2csIFwiXCIpLCBtaW4gPSAob3B0cy5taW4gJiYgb3B0cy5taW5bdGFyZ2V0UHJvcF0gfHwgdmFsdWUpLnRvU3RyaW5nKCksIG1heCA9IChvcHRzLm1heCAmJiBvcHRzLm1heFt0YXJnZXRQcm9wXSB8fCB2YWx1ZSkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgY29ycmVjdGVkVmFsdWUgPSBlbnRlcmVkUGFydCArIChlbnRlcmVkUGFydCA8IG1pbi5zbGljZSgwLCBlbnRlcmVkUGFydC5sZW5ndGgpID8gbWluLnNsaWNlKGVudGVyZWRQYXJ0Lmxlbmd0aCkgOiBlbnRlcmVkUGFydCA+IG1heC5zbGljZSgwLCBlbnRlcmVkUGFydC5sZW5ndGgpID8gbWF4LnNsaWNlKGVudGVyZWRQYXJ0Lmxlbmd0aCkgOiBjb3JyZWN0ZWRWYWx1ZS50b1N0cmluZygpLnNsaWNlKGVudGVyZWRQYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gY29ycmVjdGVkVmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBzZXRWYWx1ZShkYXRlT2JqLCB2YWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIGRhdGVPYmpbdGFyZ2V0UHJvcF0gPSBleHRlbmRQcm9wZXJ0eSh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgZGF0ZU9ialtcInJhd1wiICsgdGFyZ2V0UHJvcF0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZU9wZXJhdGlvbiAhPT0gdW5kZWZpbmVkKSBkYXRlT3BlcmF0aW9uLmNhbGwoZGF0ZU9iai5kYXRlLCB0YXJnZXRQcm9wID09IFwibW9udGhcIiA/IHBhcnNlSW50KGRhdGVPYmpbdGFyZ2V0UHJvcF0pIC0gMSA6IGRhdGVPYmpbdGFyZ2V0UHJvcF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtYXNrID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gZ2V0VG9rZW5pemVyKG9wdHMpLmV4ZWMoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBtYXNrLnNsaWNlKDAsIG1hdGNoWzBdLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmb3JtYXRDb2RlLmhhc093blByb3BlcnR5KG1hdGNoWzBdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0VmFsaWRhdG9yID0gZm9ybWF0Q29kZVttYXRjaFswXV1bMF07XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRQcm9wID0gZm9ybWF0Q29kZVttYXRjaFswXV1bMl07XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlT3BlcmF0aW9uID0gZm9ybWF0Q29kZVttYXRjaFswXV1bMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShkYXRlT2JqLCB2YWx1ZSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbWFzayA9IG1hc2suc2xpY2UodmFsdWUubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRhdGVPYmo7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1hc2sgJiYgKHR5cGVvZiBtYXNrID09PSBcInVuZGVmaW5lZFwiID8gXCJ1bmRlZmluZWRcIiA6IF90eXBlb2YobWFzaykpID09PSBcIm9iamVjdFwiICYmIG1hc2suaGFzT3duUHJvcGVydHkoXCJkYXRlXCIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2s7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIElucHV0bWFzay5leHRlbmRBbGlhc2VzKHtcbiAgICAgICAgICAgIGRhdGV0aW1lOiB7XG4gICAgICAgICAgICAgICAgbWFzazogZnVuY3Rpb24gbWFzayhvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1hdENvZGUuUyA9IG9wdHMuaTE4bi5vcmRpbmFsU3VmZml4LmpvaW4oXCJ8XCIpO1xuICAgICAgICAgICAgICAgICAgICBvcHRzLmlucHV0Rm9ybWF0ID0gZm9ybWF0QWxpYXNbb3B0cy5pbnB1dEZvcm1hdF0gfHwgb3B0cy5pbnB1dEZvcm1hdDtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5kaXNwbGF5Rm9ybWF0ID0gZm9ybWF0QWxpYXNbb3B0cy5kaXNwbGF5Rm9ybWF0XSB8fCBvcHRzLmRpc3BsYXlGb3JtYXQgfHwgb3B0cy5pbnB1dEZvcm1hdDtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5vdXRwdXRGb3JtYXQgPSBmb3JtYXRBbGlhc1tvcHRzLm91dHB1dEZvcm1hdF0gfHwgb3B0cy5vdXRwdXRGb3JtYXQgfHwgb3B0cy5pbnB1dEZvcm1hdDtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5wbGFjZWhvbGRlciA9IG9wdHMucGxhY2Vob2xkZXIgIT09IFwiXCIgPyBvcHRzLnBsYWNlaG9sZGVyIDogb3B0cy5pbnB1dEZvcm1hdC5yZXBsYWNlKC9bXFxbXFxdXS8sIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBvcHRzLnJlZ2V4ID0gcGFyc2Uob3B0cy5pbnB1dEZvcm1hdCwgdW5kZWZpbmVkLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJcIixcbiAgICAgICAgICAgICAgICBpbnB1dEZvcm1hdDogXCJpc29EYXRlVGltZVwiLFxuICAgICAgICAgICAgICAgIGRpc3BsYXlGb3JtYXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBvdXRwdXRGb3JtYXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBtaW46IG51bGwsXG4gICAgICAgICAgICAgICAgbWF4OiBudWxsLFxuICAgICAgICAgICAgICAgIGkxOG46IHtcbiAgICAgICAgICAgICAgICAgICAgZGF5TmFtZXM6IFsgXCJNb25cIiwgXCJUdWVcIiwgXCJXZWRcIiwgXCJUaHVcIiwgXCJGcmlcIiwgXCJTYXRcIiwgXCJTdW5cIiwgXCJNb25kYXlcIiwgXCJUdWVzZGF5XCIsIFwiV2VkbmVzZGF5XCIsIFwiVGh1cnNkYXlcIiwgXCJGcmlkYXlcIiwgXCJTYXR1cmRheVwiLCBcIlN1bmRheVwiIF0sXG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZXM6IFsgXCJKYW5cIiwgXCJGZWJcIiwgXCJNYXJcIiwgXCJBcHJcIiwgXCJNYXlcIiwgXCJKdW5cIiwgXCJKdWxcIiwgXCJBdWdcIiwgXCJTZXBcIiwgXCJPY3RcIiwgXCJOb3ZcIiwgXCJEZWNcIiwgXCJKYW51YXJ5XCIsIFwiRmVicnVhcnlcIiwgXCJNYXJjaFwiLCBcIkFwcmlsXCIsIFwiTWF5XCIsIFwiSnVuZVwiLCBcIkp1bHlcIiwgXCJBdWd1c3RcIiwgXCJTZXB0ZW1iZXJcIiwgXCJPY3RvYmVyXCIsIFwiTm92ZW1iZXJcIiwgXCJEZWNlbWJlclwiIF0sXG4gICAgICAgICAgICAgICAgICAgIG9yZGluYWxTdWZmaXg6IFsgXCJzdFwiLCBcIm5kXCIsIFwicmRcIiwgXCJ0aFwiIF1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBvc3RWYWxpZGF0aW9uOiBmdW5jdGlvbiBwb3N0VmFsaWRhdGlvbihidWZmZXIsIHBvcywgY3VycmVudFJlc3VsdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICBvcHRzLm1pbiA9IGFuYWx5c2VNYXNrKG9wdHMubWluLCBvcHRzLmlucHV0Rm9ybWF0LCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5tYXggPSBhbmFseXNlTWFzayhvcHRzLm1heCwgb3B0cy5pbnB1dEZvcm1hdCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBjdXJyZW50UmVzdWx0LCBkYXRlUGFydHMgPSBhbmFseXNlTWFzayhidWZmZXIuam9pbihcIlwiKSwgb3B0cy5pbnB1dEZvcm1hdCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgJiYgZGF0ZVBhcnRzLmRhdGUuZ2V0VGltZSgpID09PSBkYXRlUGFydHMuZGF0ZS5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGlzVmFsaWREYXRlKGRhdGVQYXJ0cywgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdCAmJiBpc0RhdGVJblJhbmdlKGRhdGVQYXJ0cywgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvcyAmJiByZXN1bHQgJiYgY3VycmVudFJlc3VsdC5wb3MgIT09IHBvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXI6IHBhcnNlKG9wdHMuaW5wdXRGb3JtYXQsIGRhdGVQYXJ0cywgb3B0cyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBjdXJyZW50UmVzdWx0LnBvc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uS2V5RG93bjogZnVuY3Rpb24gb25LZXlEb3duKGUsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUuY3RybEtleSAmJiBlLmtleUNvZGUgPT09IElucHV0bWFzay5rZXlDb2RlLlJJR0hUKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG9kYXkgPSBuZXcgRGF0ZSgpLCBtYXRjaCwgZGF0ZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBnZXRUb2tlbml6ZXIob3B0cykuZXhlYyhvcHRzLmlucHV0Rm9ybWF0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaFswXS5jaGFyQXQoMCkgPT09IFwiZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGUgKz0gcGFkKHRvZGF5LmdldERhdGUoKSwgbWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoWzBdLmNoYXJBdCgwKSA9PT0gXCJtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSArPSBwYWQodG9kYXkuZ2V0TW9udGgoKSArIDEsIG1hdGNoWzBdLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaFswXSA9PT0gXCJ5eXl5XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSArPSB0b2RheS5nZXRGdWxsWWVhcigpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaFswXS5jaGFyQXQoMCkgPT09IFwieVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGUgKz0gcGFkKHRvZGF5LmdldFllYXIoKSwgbWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlU2V0KGRhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJChpbnB1dCkudHJpZ2dlcihcInNldHZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvblVuTWFzazogZnVuY3Rpb24gb25Vbk1hc2sobWFza2VkVmFsdWUsIHVubWFza2VkVmFsdWUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlKG9wdHMub3V0cHV0Rm9ybWF0LCBhbmFseXNlTWFzayhtYXNrZWRWYWx1ZSwgb3B0cy5pbnB1dEZvcm1hdCwgb3B0cyksIG9wdHMsIHRydWUpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY2FzaW5nOiBmdW5jdGlvbiBjYXNpbmcoZWxlbSwgdGVzdCwgcG9zLCB2YWxpZFBvc2l0aW9ucykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGVzdC5uYXRpdmVEZWYuaW5kZXhPZihcIlthcF1cIikgPT0gMCkgcmV0dXJuIGVsZW0udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3QubmF0aXZlRGVmLmluZGV4T2YoXCJbQVBdXCIpID09IDApIHJldHVybiBlbGVtLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgc2hpZnRQb3NpdGlvbnM6IGZhbHNlXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gSW5wdXRtYXNrO1xuICAgIH0pO1xufSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX187XG4gICAgdmFyIF90eXBlb2YgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIiA/IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9iajtcbiAgICB9IDogZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xuICAgIH07XG4gICAgKGZ1bmN0aW9uKGZhY3RvcnkpIHtcbiAgICAgICAgaWYgKHRydWUpIHtcbiAgICAgICAgICAgICEoX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXyA9IFsgX193ZWJwYWNrX3JlcXVpcmVfXygyKSBdLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5LCBcbiAgICAgICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fID0gdHlwZW9mIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9PT0gXCJmdW5jdGlvblwiID8gX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLmFwcGx5KGV4cG9ydHMsIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18pIDogX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBcbiAgICAgICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fICE9PSB1bmRlZmluZWQgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pKTtcbiAgICAgICAgfSBlbHNlIHt9XG4gICAgfSkoZnVuY3Rpb24oSW5wdXRtYXNrKSB7XG4gICAgICAgIHZhciAkID0gSW5wdXRtYXNrLmRlcGVuZGVuY3lMaWI7XG4gICAgICAgIGZ1bmN0aW9uIGF1dG9Fc2NhcGUodHh0LCBvcHRzKSB7XG4gICAgICAgICAgICB2YXIgZXNjYXBlZFR4dCA9IFwiXCI7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHR4dC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChJbnB1dG1hc2sucHJvdG90eXBlLmRlZmluaXRpb25zW3R4dC5jaGFyQXQoaSldIHx8IG9wdHMuZGVmaW5pdGlvbnNbdHh0LmNoYXJBdChpKV0gfHwgb3B0cy5vcHRpb25hbG1hcmtlci5zdGFydCA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLm9wdGlvbmFsbWFya2VyLmVuZCA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLnF1YW50aWZpZXJtYXJrZXIuc3RhcnQgPT09IHR4dC5jaGFyQXQoaSkgfHwgb3B0cy5xdWFudGlmaWVybWFya2VyLmVuZCA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLmdyb3VwbWFya2VyLnN0YXJ0ID09PSB0eHQuY2hhckF0KGkpIHx8IG9wdHMuZ3JvdXBtYXJrZXIuZW5kID09PSB0eHQuY2hhckF0KGkpIHx8IG9wdHMuYWx0ZXJuYXRvcm1hcmtlciA9PT0gdHh0LmNoYXJBdChpKSkge1xuICAgICAgICAgICAgICAgICAgICBlc2NhcGVkVHh0ICs9IFwiXFxcXFwiICsgdHh0LmNoYXJBdChpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgZXNjYXBlZFR4dCArPSB0eHQuY2hhckF0KGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGVzY2FwZWRUeHQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gYWxpZ25EaWdpdHMoYnVmZmVyLCBkaWdpdHMsIG9wdHMpIHtcbiAgICAgICAgICAgIGlmIChkaWdpdHMgPiAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJhZGl4UG9zaXRpb24gPSAkLmluQXJyYXkob3B0cy5yYWRpeFBvaW50LCBidWZmZXIpO1xuICAgICAgICAgICAgICAgIGlmIChyYWRpeFBvc2l0aW9uID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBidWZmZXIucHVzaChvcHRzLnJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICByYWRpeFBvc2l0aW9uID0gYnVmZmVyLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IGRpZ2l0czsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlcltyYWRpeFBvc2l0aW9uICsgaV0gPSBidWZmZXJbcmFkaXhQb3NpdGlvbiArIGldIHx8IFwiMFwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgICAgIH1cbiAgICAgICAgSW5wdXRtYXNrLmV4dGVuZEFsaWFzZXMoe1xuICAgICAgICAgICAgbnVtZXJpYzoge1xuICAgICAgICAgICAgICAgIG1hc2s6IGZ1bmN0aW9uIG1hc2sob3B0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5yZXBlYXQgIT09IDAgJiYgaXNOYU4ob3B0cy5pbnRlZ2VyRGlnaXRzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5pbnRlZ2VyRGlnaXRzID0gb3B0cy5yZXBlYXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3B0cy5yZXBlYXQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5ncm91cFNlcGFyYXRvciA9PT0gb3B0cy5yYWRpeFBvaW50ICYmIG9wdHMuZGlnaXRzICYmIG9wdHMuZGlnaXRzICE9PSBcIjBcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmFkaXhQb2ludCA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmdyb3VwU2VwYXJhdG9yID0gXCIsXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9wdHMucmFkaXhQb2ludCA9PT0gXCIsXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmdyb3VwU2VwYXJhdG9yID0gXCIuXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugb3B0cy5ncm91cFNlcGFyYXRvciA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuZ3JvdXBTZXBhcmF0b3IgPT09IFwiIFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3B0cy5hdXRvR3JvdXAgPSBvcHRzLmF1dG9Hcm91cCAmJiBvcHRzLmdyb3VwU2VwYXJhdG9yICE9PSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5hdXRvR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0cy5ncm91cFNpemUgPT0gXCJzdHJpbmdcIiAmJiBpc0Zpbml0ZShvcHRzLmdyb3VwU2l6ZSkpIG9wdHMuZ3JvdXBTaXplID0gcGFyc2VJbnQob3B0cy5ncm91cFNpemUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmluaXRlKG9wdHMuaW50ZWdlckRpZ2l0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VwcyA9IE1hdGguZmxvb3Iob3B0cy5pbnRlZ2VyRGlnaXRzIC8gb3B0cy5ncm91cFNpemUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtb2QgPSBvcHRzLmludGVnZXJEaWdpdHMgJSBvcHRzLmdyb3VwU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmludGVnZXJEaWdpdHMgPSBwYXJzZUludChvcHRzLmludGVnZXJEaWdpdHMpICsgKG1vZCA9PT0gMCA/IHNlcHMgLSAxIDogc2Vwcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuaW50ZWdlckRpZ2l0cyA8IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5pbnRlZ2VyRGlnaXRzID0gXCIqXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnBsYWNlaG9sZGVyLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMucGxhY2Vob2xkZXIgPSBvcHRzLnBsYWNlaG9sZGVyLmNoYXJBdCgwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5wb3NpdGlvbkNhcmV0T25DbGljayA9PT0gXCJyYWRpeEZvY3VzXCIgJiYgb3B0cy5wbGFjZWhvbGRlciA9PT0gXCJcIiAmJiBvcHRzLmludGVnZXJPcHRpb25hbCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMucG9zaXRpb25DYXJldE9uQ2xpY2sgPSBcImx2cFwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG9wdHMuZGVmaW5pdGlvbnNbXCI7XCJdID0gb3B0cy5kZWZpbml0aW9uc1tcIn5cIl07XG4gICAgICAgICAgICAgICAgICAgIG9wdHMuZGVmaW5pdGlvbnNbXCI7XCJdLmRlZmluaXRpb25TeW1ib2wgPSBcIn5cIjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMubnVtZXJpY0lucHV0ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLnBvc2l0aW9uQ2FyZXRPbkNsaWNrID0gb3B0cy5wb3NpdGlvbkNhcmV0T25DbGljayA9PT0gXCJyYWRpeEZvY3VzXCIgPyBcImx2cFwiIDogb3B0cy5wb3NpdGlvbkNhcmV0T25DbGljaztcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuZGlnaXRzT3B0aW9uYWwgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc05hTihvcHRzLmRpZ2l0cykpIG9wdHMuZGlnaXRzID0gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuZGVjaW1hbFByb3RlY3QgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgbWFzayA9IFwiWytdXCI7XG4gICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gYXV0b0VzY2FwZShvcHRzLnByZWZpeCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmludGVnZXJPcHRpb25hbCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFzayArPSBcIn57MSxcIiArIG9wdHMuaW50ZWdlckRpZ2l0cyArIFwifVwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgbWFzayArPSBcIn57XCIgKyBvcHRzLmludGVnZXJEaWdpdHMgKyBcIn1cIjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuZGlnaXRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeERlZiA9IG9wdHMuZGVjaW1hbFByb3RlY3QgPyBcIjpcIiA6IG9wdHMucmFkaXhQb2ludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkcSA9IG9wdHMuZGlnaXRzLnRvU3RyaW5nKCkuc3BsaXQoXCIsXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmluaXRlKGRxWzBdKSAmJiBkcVsxXSAmJiBpc0Zpbml0ZShkcVsxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrICs9IHJhZGl4RGVmICsgXCI7e1wiICsgb3B0cy5kaWdpdHMgKyBcIn1cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNOYU4ob3B0cy5kaWdpdHMpIHx8IHBhcnNlSW50KG9wdHMuZGlnaXRzKSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5kaWdpdHNPcHRpb25hbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrICs9IFwiW1wiICsgcmFkaXhEZWYgKyBcIjt7MSxcIiArIG9wdHMuZGlnaXRzICsgXCJ9XVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBtYXNrICs9IHJhZGl4RGVmICsgXCI7e1wiICsgb3B0cy5kaWdpdHMgKyBcIn1cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtYXNrICs9IGF1dG9Fc2NhcGUob3B0cy5zdWZmaXgsIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBtYXNrICs9IFwiWy1dXCI7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMuZ3JlZWR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXNrO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiXCIsXG4gICAgICAgICAgICAgICAgZ3JlZWR5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBkaWdpdHM6IFwiKlwiLFxuICAgICAgICAgICAgICAgIGRpZ2l0c09wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICAgIGVuZm9yY2VEaWdpdHNPbkJsdXI6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHJhZGl4UG9pbnQ6IFwiLlwiLFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uQ2FyZXRPbkNsaWNrOiBcInJhZGl4Rm9jdXNcIixcbiAgICAgICAgICAgICAgICBncm91cFNpemU6IDMsXG4gICAgICAgICAgICAgICAgZ3JvdXBTZXBhcmF0b3I6IFwiXCIsXG4gICAgICAgICAgICAgICAgYXV0b0dyb3VwOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhbGxvd01pbnVzOiB0cnVlLFxuICAgICAgICAgICAgICAgIG5lZ2F0aW9uU3ltYm9sOiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb250OiBcIi1cIixcbiAgICAgICAgICAgICAgICAgICAgYmFjazogXCJcIlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgaW50ZWdlckRpZ2l0czogXCIrXCIsXG4gICAgICAgICAgICAgICAgaW50ZWdlck9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICAgIHByZWZpeDogXCJcIixcbiAgICAgICAgICAgICAgICBzdWZmaXg6IFwiXCIsXG4gICAgICAgICAgICAgICAgcmlnaHRBbGlnbjogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkZWNpbWFsUHJvdGVjdDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBtaW46IG51bGwsXG4gICAgICAgICAgICAgICAgbWF4OiBudWxsLFxuICAgICAgICAgICAgICAgIHN0ZXA6IDEsXG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhdXRvVW5tYXNrOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB1bm1hc2tBc051bWJlcjogZmFsc2UsXG4gICAgICAgICAgICAgICAgaW5wdXRUeXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwibnVtZXJpY1wiLFxuICAgICAgICAgICAgICAgIHByZVZhbGlkYXRpb246IGZ1bmN0aW9uIHByZVZhbGlkYXRpb24oYnVmZmVyLCBwb3MsIGMsIGlzU2VsZWN0aW9uLCBvcHRzLCBtYXNrc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjID09PSBcIi1cIiB8fCBjID09PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5hbGxvd01pbnVzICE9PSB0cnVlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmlzTmVnYXRpdmUgPSBvcHRzLmlzTmVnYXRpdmUgPT09IHVuZGVmaW5lZCA/IHRydWUgOiAhb3B0cy5pc05lZ2F0aXZlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJ1ZmZlci5qb2luKFwiXCIpID09PSBcIlwiKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXSA/IHBvcyA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3Bvc3Q6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzU2VsZWN0aW9uID09PSBmYWxzZSAmJiBjID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgb3B0cy5kaWdpdHMgIT09IHVuZGVmaW5lZCAmJiAoaXNOYU4ob3B0cy5kaWdpdHMpIHx8IHBhcnNlSW50KG9wdHMuZGlnaXRzKSA+IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFkaXhQb3MgPSAkLmluQXJyYXkob3B0cy5yYWRpeFBvaW50LCBidWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhZGl4UG9zICE9PSAtMSAmJiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3JhZGl4UG9zXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMubnVtZXJpY0lucHV0ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwb3MgPT09IHJhZGl4UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogcmFkaXhQb3MgKyAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBvc3RWYWxpZGF0aW9uOiBmdW5jdGlvbiBwb3N0VmFsaWRhdGlvbihidWZmZXIsIHBvcywgY3VycmVudFJlc3VsdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBidWlsZFBvc3RNYXNrKGJ1ZmZlciwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBvc3RNYXNrID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc3RNYXNrICs9IFwiKFwiICsgb3B0cy5ncm91cFNlcGFyYXRvciArIFwiKntcIiArIG9wdHMuZ3JvdXBTaXplICsgXCJ9KXsqfVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmFkaXhQb2ludCAhPT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFNwbGl0ID0gYnVmZmVyLmpvaW4oXCJcIikuc3BsaXQob3B0cy5yYWRpeFBvaW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFkaXhTcGxpdFsxXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3N0TWFzayArPSBvcHRzLnJhZGl4UG9pbnQgKyBcIip7XCIgKyByYWRpeFNwbGl0WzFdLm1hdGNoKC9eXFxkKlxcPz9cXGQqLylbMF0ubGVuZ3RoICsgXCJ9XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvc3RNYXNrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBzdWZmaXggPSBvcHRzLnN1ZmZpeC5zcGxpdChcIlwiKSwgcHJlZml4ID0gb3B0cy5wcmVmaXguc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50UmVzdWx0LnBvcyA9PT0gdW5kZWZpbmVkICYmIGN1cnJlbnRSZXN1bHQuY2FyZXQgIT09IHVuZGVmaW5lZCAmJiBjdXJyZW50UmVzdWx0LmRvcG9zdCAhPT0gdHJ1ZSkgcmV0dXJuIGN1cnJlbnRSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjYXJldFBvcyA9IGN1cnJlbnRSZXN1bHQuY2FyZXQgIT09IHVuZGVmaW5lZCA/IGN1cnJlbnRSZXN1bHQuY2FyZXQgOiBjdXJyZW50UmVzdWx0LnBvcztcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1hc2tlZFZhbHVlID0gYnVmZmVyLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm51bWVyaWNJbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3MgPSBtYXNrZWRWYWx1ZS5sZW5ndGggLSBjYXJldFBvcyAtIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrZWRWYWx1ZSA9IG1hc2tlZFZhbHVlLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgY2hhckF0UG9zID0gbWFza2VkVmFsdWVbY2FyZXRQb3NdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckF0UG9zID09PSBvcHRzLmdyb3VwU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvcyArPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hhckF0UG9zID0gbWFza2VkVmFsdWVbY2FyZXRQb3NdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChjYXJldFBvcyA9PT0gbWFza2VkVmFsdWUubGVuZ3RoIC0gb3B0cy5zdWZmaXgubGVuZ3RoIC0gMSAmJiBjaGFyQXRQb3MgPT09IG9wdHMucmFkaXhQb2ludCkgcmV0dXJuIGN1cnJlbnRSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGFyQXRQb3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoYXJBdFBvcyAhPT0gb3B0cy5yYWRpeFBvaW50ICYmIGNoYXJBdFBvcyAhPT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCAmJiBjaGFyQXRQb3MgIT09IG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tlZFZhbHVlW2NhcmV0UG9zXSA9IFwiP1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnByZWZpeC5sZW5ndGggPiAwICYmIGNhcmV0UG9zID49IChvcHRzLmlzTmVnYXRpdmUgPT09IGZhbHNlID8gMSA6IDApICYmIGNhcmV0UG9zIDwgb3B0cy5wcmVmaXgubGVuZ3RoIC0gMSArIChvcHRzLmlzTmVnYXRpdmUgPT09IGZhbHNlID8gMSA6IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeFtjYXJldFBvcyAtIChvcHRzLmlzTmVnYXRpdmUgPT09IGZhbHNlID8gMSA6IDApXSA9IFwiP1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0cy5zdWZmaXgubGVuZ3RoID4gMCAmJiBjYXJldFBvcyA+PSBtYXNrZWRWYWx1ZS5sZW5ndGggLSBvcHRzLnN1ZmZpeC5sZW5ndGggLSAob3B0cy5pc05lZ2F0aXZlID09PSBmYWxzZSA/IDEgOiAwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWZmaXhbY2FyZXRQb3MgLSAobWFza2VkVmFsdWUubGVuZ3RoIC0gb3B0cy5zdWZmaXgubGVuZ3RoIC0gKG9wdHMuaXNOZWdhdGl2ZSA9PT0gZmFsc2UgPyAxIDogMCkpXSA9IFwiP1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwcmVmaXggPSBwcmVmaXguam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgc3VmZml4ID0gc3VmZml4LmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9jZXNzVmFsdWUgPSBtYXNrZWRWYWx1ZS5qb2luKFwiXCIpLnJlcGxhY2UocHJlZml4LCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2Uoc3VmZml4LCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5ncm91cFNlcGFyYXRvciksIFwiZ1wiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoXCJbLVwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpICsgXCJdXCIsIFwiZ1wiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaykgKyBcIiRcIiksIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNOYU4ob3B0cy5wbGFjZWhvbGRlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMucGxhY2Vob2xkZXIpLCBcImdcIiksIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9jZXNzVmFsdWUubGVuZ3RoID4gMSAmJiBwcm9jZXNzVmFsdWUuaW5kZXhPZihvcHRzLnJhZGl4UG9pbnQpICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckF0UG9zID09PSBcIjBcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKC9eXFw/L2csIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UoL14wL2csIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9jZXNzVmFsdWUuY2hhckF0KDApID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgb3B0cy5yYWRpeFBvaW50ICE9PSBcIlwiICYmIG9wdHMubnVtZXJpY0lucHV0ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBcIjBcIiArIHByb2Nlc3NWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvY2Vzc1ZhbHVlICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKCFvcHRzLmRpZ2l0c09wdGlvbmFsIHx8IG9wdHMuZW5mb3JjZURpZ2l0c09uQmx1ciAmJiBjdXJyZW50UmVzdWx0LmV2ZW50ID09PSBcImJsdXJcIikgJiYgaXNGaW5pdGUob3B0cy5kaWdpdHMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhZGl4UG9zaXRpb24gPSAkLmluQXJyYXkob3B0cy5yYWRpeFBvaW50LCBwcm9jZXNzVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBycGIgPSAkLmluQXJyYXkob3B0cy5yYWRpeFBvaW50LCBtYXNrZWRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhZGl4UG9zaXRpb24gPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZS5wdXNoKG9wdHMucmFkaXhQb2ludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhZGl4UG9zaXRpb24gPSBwcm9jZXNzVmFsdWUubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gb3B0cy5kaWdpdHM7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKCFvcHRzLmRpZ2l0c09wdGlvbmFsIHx8IG9wdHMuZW5mb3JjZURpZ2l0c09uQmx1ciAmJiBjdXJyZW50UmVzdWx0LmV2ZW50ID09PSBcImJsdXJcIikgJiYgKHByb2Nlc3NWYWx1ZVtyYWRpeFBvc2l0aW9uICsgaV0gPT09IHVuZGVmaW5lZCB8fCBwcm9jZXNzVmFsdWVbcmFkaXhQb3NpdGlvbiArIGldID09PSBvcHRzLnBsYWNlaG9sZGVyLmNoYXJBdCgwKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZVtyYWRpeFBvc2l0aW9uICsgaV0gPSBjdXJyZW50UmVzdWx0LnBsYWNlaG9sZGVyIHx8IG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJwYiAhPT0gLTEgJiYgbWFza2VkVmFsdWVbcnBiICsgaV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlW3JhZGl4UG9zaXRpb24gKyBpXSA9IHByb2Nlc3NWYWx1ZVtyYWRpeFBvc2l0aW9uICsgaV0gfHwgbWFza2VkVmFsdWVbcnBiICsgaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5hdXRvR3JvdXAgPT09IHRydWUgJiYgb3B0cy5ncm91cFNlcGFyYXRvciAhPT0gXCJcIiAmJiAoY2hhckF0UG9zICE9PSBvcHRzLnJhZGl4UG9pbnQgfHwgY3VycmVudFJlc3VsdC5wb3MgIT09IHVuZGVmaW5lZCB8fCBjdXJyZW50UmVzdWx0LmRvcG9zdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWRkUmFkaXggPSBwcm9jZXNzVmFsdWVbcHJvY2Vzc1ZhbHVlLmxlbmd0aCAtIDFdID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgY3VycmVudFJlc3VsdC5jID09PSBvcHRzLnJhZGl4UG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gSW5wdXRtYXNrKGJ1aWxkUG9zdE1hc2socHJvY2Vzc1ZhbHVlLCBvcHRzKSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1lcmljSW5wdXQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdE1hc2tpbmc6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluaXRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIipcIjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbMC05P11cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuZm9ybWF0KHByb2Nlc3NWYWx1ZS5qb2luKFwiXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWRkUmFkaXgpIHByb2Nlc3NWYWx1ZSArPSBvcHRzLnJhZGl4UG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb2Nlc3NWYWx1ZS5jaGFyQXQoMCkgPT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlLnN1YnN0cigxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuaXNOZWdhdGl2ZSAmJiBjdXJyZW50UmVzdWx0LmV2ZW50ID09PSBcImJsdXJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5pc05lZ2F0aXZlID0gcHJvY2Vzc1ZhbHVlICE9PSBcIjBcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcmVmaXggKyBwcm9jZXNzVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSArPSBzdWZmaXg7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmlzTmVnYXRpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQgKyBwcm9jZXNzVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgKz0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5zcGxpdChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoYXJBdFBvcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckF0UG9zICE9PSBvcHRzLnJhZGl4UG9pbnQgJiYgY2hhckF0UG9zICE9PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250ICYmIGNoYXJBdFBvcyAhPT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3MgPSAkLmluQXJyYXkoXCI/XCIsIHByb2Nlc3NWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhcmV0UG9zID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlW2NhcmV0UG9zXSA9IGNoYXJBdFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgY2FyZXRQb3MgPSBjdXJyZW50UmVzdWx0LmNhcmV0IHx8IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNoYXJBdFBvcyA9PT0gb3B0cy5yYWRpeFBvaW50IHx8IGNoYXJBdFBvcyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCB8fCBjaGFyQXRQb3MgPT09IG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdDYXJldFBvcyA9ICQuaW5BcnJheShjaGFyQXRQb3MsIHByb2Nlc3NWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0NhcmV0UG9zICE9PSAtMSkgY2FyZXRQb3MgPSBuZXdDYXJldFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5udW1lcmljSW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zID0gcHJvY2Vzc1ZhbHVlLmxlbmd0aCAtIGNhcmV0UG9zIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHJzbHQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogKGNoYXJBdFBvcyA9PT0gdW5kZWZpbmVkIHx8IGN1cnJlbnRSZXN1bHQucG9zICE9PSB1bmRlZmluZWQpICYmIGNhcmV0UG9zICE9PSB1bmRlZmluZWQgPyBjYXJldFBvcyArIChvcHRzLm51bWVyaWNJbnB1dCA/IC0xIDogMSkgOiBjYXJldFBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlcjogcHJvY2Vzc1ZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXI6IGN1cnJlbnRSZXN1bHQuZG9wb3N0IHx8IGJ1ZmZlci5qb2luKFwiXCIpICE9PSBwcm9jZXNzVmFsdWUuam9pbihcIlwiKVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcnNsdC5yZWZyZXNoRnJvbUJ1ZmZlciA/IHJzbHQgOiBjdXJyZW50UmVzdWx0O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25CZWZvcmVXcml0ZTogZnVuY3Rpb24gb25CZWZvcmVXcml0ZShlLCBidWZmZXIsIGNhcmV0UG9zLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlTWluTWF4T3B0aW9ucyhvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5wYXJzZU1pbk1heE9wdGlvbnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm1pbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLm1pbiA9IG9wdHMubWluLnRvU3RyaW5nKCkucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLmdyb3VwU2VwYXJhdG9yKSwgXCJnXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmFkaXhQb2ludCA9PT0gXCIsXCIpIG9wdHMubWluID0gb3B0cy5taW4ucmVwbGFjZShvcHRzLnJhZGl4UG9pbnQsIFwiLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5taW4gPSBpc0Zpbml0ZShvcHRzLm1pbikgPyBwYXJzZUZsb2F0KG9wdHMubWluKSA6IE5hTjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmFOKG9wdHMubWluKSkgb3B0cy5taW4gPSBOdW1iZXIuTUlOX1ZBTFVFO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5tYXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5tYXggPSBvcHRzLm1heC50b1N0cmluZygpLnJlcGxhY2UobmV3IFJlZ0V4cChJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5ncm91cFNlcGFyYXRvciksIFwiZ1wiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnJhZGl4UG9pbnQgPT09IFwiLFwiKSBvcHRzLm1heCA9IG9wdHMubWF4LnJlcGxhY2Uob3B0cy5yYWRpeFBvaW50LCBcIi5cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMubWF4ID0gaXNGaW5pdGUob3B0cy5tYXgpID8gcGFyc2VGbG9hdChvcHRzLm1heCkgOiBOYU47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc05hTihvcHRzLm1heCkpIG9wdHMubWF4ID0gTnVtYmVyLk1BWF9WQUxVRTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5wYXJzZU1pbk1heE9wdGlvbnMgPSBcImRvbmVcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImtleWRvd25cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5wb3N0VmFsaWRhdGlvbihidWZmZXIsIGNhcmV0UG9zLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBjYXJldFBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9wb3N0OiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgb3B0cyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImJsdXJcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImNoZWNrdmFsXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHVubWFza2VkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlTWluTWF4T3B0aW9ucyhvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5taW4gIT09IG51bGwgfHwgb3B0cy5tYXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5tYXNrZWQgPSBvcHRzLm9uVW5NYXNrKGJ1ZmZlci5qb2luKFwiXCIpLCB1bmRlZmluZWQsICQuZXh0ZW5kKHt9LCBvcHRzLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bm1hc2tBc051bWJlcjogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm1pbiAhPT0gbnVsbCAmJiB1bm1hc2tlZCA8IG9wdHMubWluKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmlzTmVnYXRpdmUgPSBvcHRzLm1pbiA8IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5wb3N0VmFsaWRhdGlvbihvcHRzLm1pbi50b1N0cmluZygpLnJlcGxhY2UoXCIuXCIsIG9wdHMucmFkaXhQb2ludCkuc3BsaXQoXCJcIiksIGNhcmV0UG9zLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IGNhcmV0UG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvcG9zdDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCIwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9wdHMubWF4ICE9PSBudWxsICYmIHVubWFza2VkID4gb3B0cy5tYXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuaXNOZWdhdGl2ZSA9IG9wdHMubWF4IDwgMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLnBvc3RWYWxpZGF0aW9uKG9wdHMubWF4LnRvU3RyaW5nKCkucmVwbGFjZShcIi5cIiwgb3B0cy5yYWRpeFBvaW50KS5zcGxpdChcIlwiKSwgY2FyZXRQb3MsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogY2FyZXRQb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9wb3N0OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMucG9zdFZhbGlkYXRpb24oYnVmZmVyLCBjYXJldFBvcywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogY2FyZXRQb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIjBcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IFwiYmx1clwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgb3B0cyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIl9jaGVja3ZhbFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBjYXJldFBvc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcmVnZXg6IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZWdlclBhcnQ6IGZ1bmN0aW9uIGludGVnZXJQYXJ0KG9wdHMsIGVtcHR5Q2hlY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbXB0eUNoZWNrID8gbmV3IFJlZ0V4cChcIltcIiArIElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250KSArIFwiK10/XCIpIDogbmV3IFJlZ0V4cChcIltcIiArIElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250KSArIFwiK10/XFxcXGQrXCIpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBpbnRlZ2VyTlBhcnQ6IGZ1bmN0aW9uIGludGVnZXJOUGFydChvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cChcIltcXFxcZFwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMuZ3JvdXBTZXBhcmF0b3IpICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApKSArIFwiXStcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGRlZmluaXRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIFwiflwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cywgaXNTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXNWYWxpZCwgbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hycyA9PT0gXCJrXCIgfHwgY2hycyA9PT0gXCJtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydDogW10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjOiAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gY2hycyA9PT0gXCJrXCIgPyAyIDogNTsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZC5pbnNlcnQucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3MgKyBpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQucG9zID0gcG9zICsgbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSBzdHJpY3QgPyBuZXcgUmVnRXhwKFwiWzAtOVwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMuZ3JvdXBTZXBhcmF0b3IpICsgXCJdXCIpLnRlc3QoY2hycykgOiBuZXcgUmVnRXhwKFwiWzAtOV1cIikudGVzdChjaHJzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5udW1lcmljSW5wdXQgIT09IHRydWUgJiYgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdICE9PSB1bmRlZmluZWQgJiYgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdLm1hdGNoLmRlZiA9PT0gXCJ+XCIgJiYgIWlzU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvY2Vzc1ZhbHVlID0gbWFza3NldC5idWZmZXIuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoXCJbLVwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpICsgXCJdXCIsIFwiZ1wiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2spICsgXCIkXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwdlJhZGl4U3BsaXQgPSBwcm9jZXNzVmFsdWUuc3BsaXQob3B0cy5yYWRpeFBvaW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwdlJhZGl4U3BsaXQubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2UmFkaXhTcGxpdFsxXSA9IHB2UmFkaXhTcGxpdFsxXS5yZXBsYWNlKC8wL2csIG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwdlJhZGl4U3BsaXRbMF0gPT09IFwiMFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZSYWRpeFNwbGl0WzBdID0gcHZSYWRpeFNwbGl0WzBdLnJlcGxhY2UoLzAvZywgb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHZSYWRpeFNwbGl0WzBdICsgb3B0cy5yYWRpeFBvaW50ICsgcHZSYWRpeFNwbGl0WzFdIHx8IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyVGVtcGxhdGUgPSBtYXNrc2V0Ll9idWZmZXIuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9jZXNzVmFsdWUgPT09IG9wdHMucmFkaXhQb2ludCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IGJ1ZmZlclRlbXBsYXRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHByb2Nlc3NWYWx1ZS5tYXRjaChJbnB1dG1hc2suZXNjYXBlUmVnZXgoYnVmZmVyVGVtcGxhdGUpICsgXCIkXCIpID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyVGVtcGxhdGUgPSBidWZmZXJUZW1wbGF0ZS5zbGljZSgxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKGJ1ZmZlclRlbXBsYXRlLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5zcGxpdChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9jZXNzVmFsdWVbcG9zXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZTogcG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghc3RyaWN0ICYmIGNocnMgPT09IG9wdHMucmFkaXhQb2ludCAmJiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3BvcyAtIDFdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvcyArIDFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDFcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCIrXCI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogZnVuY3Rpb24gdmFsaWRhdG9yKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMuYWxsb3dNaW51cyAmJiAoY2hycyA9PT0gXCItXCIgfHwgY2hycyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZGluYWxpdHk6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJcIlxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBcIi1cIjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoY2hycywgbWFza3NldCwgcG9zLCBzdHJpY3QsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5hbGxvd01pbnVzICYmIGNocnMgPT09IG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIlwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiOlwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeCA9IFwiW1wiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMucmFkaXhQb2ludCkgKyBcIl1cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXNWYWxpZCA9IG5ldyBSZWdFeHAocmFkaXgpLnRlc3QoY2hycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWQgJiYgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdICYmIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zXS5tYXRjaC5wbGFjZWhvbGRlciA9PT0gb3B0cy5yYWRpeFBvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogcG9zICsgMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNWYWxpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBmdW5jdGlvbiBwbGFjZWhvbGRlcihvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMucmFkaXhQb2ludDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25Vbk1hc2s6IGZ1bmN0aW9uIG9uVW5NYXNrKG1hc2tlZFZhbHVlLCB1bm1hc2tlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1bm1hc2tlZFZhbHVlID09PSBcIlwiICYmIG9wdHMubnVsbGFibGUgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB1bm1hc2tlZFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9jZXNzVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXBsYWNlKG9wdHMucHJlZml4LCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2Uob3B0cy5zdWZmaXgsIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLmdyb3VwU2VwYXJhdG9yKSwgXCJnXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApLCBcImdcIiksIFwiMFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy51bm1hc2tBc051bWJlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmFkaXhQb2ludCAhPT0gXCJcIiAmJiBwcm9jZXNzVmFsdWUuaW5kZXhPZihvcHRzLnJhZGl4UG9pbnQpICE9PSAtMSkgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4LmNhbGwodGhpcywgb3B0cy5yYWRpeFBvaW50KSwgXCIuXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChcIl5cIiArIElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250KSksIFwiLVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaykgKyBcIiRcIiksIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE51bWJlcihwcm9jZXNzVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwcm9jZXNzVmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpc0NvbXBsZXRlOiBmdW5jdGlvbiBpc0NvbXBsZXRlKGJ1ZmZlciwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWFza2VkVmFsdWUgPSAob3B0cy5udW1lcmljSW5wdXQgPyBidWZmZXIuc2xpY2UoKS5yZXZlcnNlKCkgOiBidWZmZXIpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKFwiXlwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpKSwgXCItXCIpO1xuICAgICAgICAgICAgICAgICAgICBtYXNrZWRWYWx1ZSA9IG1hc2tlZFZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSArIFwiJFwiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmVwbGFjZShvcHRzLnByZWZpeCwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmVwbGFjZShvcHRzLnN1ZmZpeCwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLmdyb3VwU2VwYXJhdG9yKSArIFwiKFswLTldezN9KVwiLCBcImdcIiksIFwiJDFcIik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnJhZGl4UG9pbnQgPT09IFwiLFwiKSBtYXNrZWRWYWx1ZSA9IG1hc2tlZFZhbHVlLnJlcGxhY2UoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMucmFkaXhQb2ludCksIFwiLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzRmluaXRlKG1hc2tlZFZhbHVlKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uQmVmb3JlTWFzazogZnVuY3Rpb24gb25CZWZvcmVNYXNrKGluaXRpYWxWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICBvcHRzLmlzTmVnYXRpdmUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvaW50ID0gb3B0cy5yYWRpeFBvaW50IHx8IFwiLFwiO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHR5cGVvZiBpbml0aWFsVmFsdWUgPT0gXCJudW1iZXJcIiB8fCBvcHRzLmlucHV0VHlwZSA9PT0gXCJudW1iZXJcIikgJiYgcmFkaXhQb2ludCAhPT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gaW5pdGlhbFZhbHVlLnRvU3RyaW5nKCkucmVwbGFjZShcIi5cIiwgcmFkaXhQb2ludCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlUGFydHMgPSBpbml0aWFsVmFsdWUuc3BsaXQocmFkaXhQb2ludCksIGludGVnZXJQYXJ0ID0gdmFsdWVQYXJ0c1swXS5yZXBsYWNlKC9bXlxcLTAtOV0vZywgXCJcIiksIGRlY2ltYWxQYXJ0ID0gdmFsdWVQYXJ0cy5sZW5ndGggPiAxID8gdmFsdWVQYXJ0c1sxXS5yZXBsYWNlKC9bXjAtOV0vZywgXCJcIikgOiBcIlwiO1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBpbnRlZ2VyUGFydCArIChkZWNpbWFsUGFydCAhPT0gXCJcIiA/IHJhZGl4UG9pbnQgKyBkZWNpbWFsUGFydCA6IGRlY2ltYWxQYXJ0KTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpZ2l0cyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyYWRpeFBvaW50ICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSBkZWNpbWFsUGFydC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGVjaW1hbFBhcnQgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGlnaXRzRmFjdG9yID0gTWF0aC5wb3coMTAsIGRpZ2l0cyB8fCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNGaW5pdGUob3B0cy5kaWdpdHMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IHBhcnNlSW50KG9wdHMuZGlnaXRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlnaXRzRmFjdG9yID0gTWF0aC5wb3coMTAsIGRpZ2l0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGluaXRpYWxWYWx1ZS5yZXBsYWNlKElucHV0bWFzay5lc2NhcGVSZWdleChyYWRpeFBvaW50KSwgXCIuXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0Zpbml0ZShpbml0aWFsVmFsdWUpKSBpbml0aWFsVmFsdWUgPSBNYXRoLnJvdW5kKHBhcnNlRmxvYXQoaW5pdGlhbFZhbHVlKSAqIGRpZ2l0c0ZhY3RvcikgLyBkaWdpdHNGYWN0b3I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gaW5pdGlhbFZhbHVlLnRvU3RyaW5nKCkucmVwbGFjZShcIi5cIiwgcmFkaXhQb2ludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuZGlnaXRzID09PSAwICYmIGluaXRpYWxWYWx1ZS5pbmRleE9mKElucHV0bWFzay5lc2NhcGVSZWdleChyYWRpeFBvaW50KSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUuc3Vic3RyaW5nKDAsIGluaXRpYWxWYWx1ZS5pbmRleE9mKElucHV0bWFzay5lc2NhcGVSZWdleChyYWRpeFBvaW50KSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhbGlnbkRpZ2l0cyhpbml0aWFsVmFsdWUudG9TdHJpbmcoKS5zcGxpdChcIlwiKSwgZGlnaXRzLCBvcHRzKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25LZXlEb3duOiBmdW5jdGlvbiBvbktleURvd24oZSwgYnVmZmVyLCBjYXJldFBvcywgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgJGlucHV0ID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUuY3RybEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlLmtleUNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBJbnB1dG1hc2sua2V5Q29kZS5VUDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudmFsKHBhcnNlRmxvYXQodGhpcy5pbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpKSArIHBhcnNlSW50KG9wdHMuc3RlcCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBJbnB1dG1hc2sua2V5Q29kZS5ET1dOOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwocGFyc2VGbG9hdCh0aGlzLmlucHV0bWFzay51bm1hc2tlZHZhbHVlKCkpIC0gcGFyc2VJbnQob3B0cy5zdGVwKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJzZXR2YWx1ZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjdXJyZW5jeToge1xuICAgICAgICAgICAgICAgIHByZWZpeDogXCIkIFwiLFxuICAgICAgICAgICAgICAgIGdyb3VwU2VwYXJhdG9yOiBcIixcIixcbiAgICAgICAgICAgICAgICBhbGlhczogXCJudW1lcmljXCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiMFwiLFxuICAgICAgICAgICAgICAgIGF1dG9Hcm91cDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkaWdpdHM6IDIsXG4gICAgICAgICAgICAgICAgZGlnaXRzT3B0aW9uYWw6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNsZWFyTWFza09uTG9zdEZvY3VzOiBmYWxzZVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlY2ltYWw6IHtcbiAgICAgICAgICAgICAgICBhbGlhczogXCJudW1lcmljXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbnRlZ2VyOiB7XG4gICAgICAgICAgICAgICAgYWxpYXM6IFwibnVtZXJpY1wiLFxuICAgICAgICAgICAgICAgIGRpZ2l0czogMCxcbiAgICAgICAgICAgICAgICByYWRpeFBvaW50OiBcIlwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGVyY2VudGFnZToge1xuICAgICAgICAgICAgICAgIGFsaWFzOiBcIm51bWVyaWNcIixcbiAgICAgICAgICAgICAgICBkaWdpdHM6IDIsXG4gICAgICAgICAgICAgICAgZGlnaXRzT3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgcmFkaXhQb2ludDogXCIuXCIsXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiMFwiLFxuICAgICAgICAgICAgICAgIGF1dG9Hcm91cDogZmFsc2UsXG4gICAgICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgICAgIG1heDogMTAwLFxuICAgICAgICAgICAgICAgIHN1ZmZpeDogXCIgJVwiLFxuICAgICAgICAgICAgICAgIGFsbG93TWludXM6IGZhbHNlXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gSW5wdXRtYXNrO1xuICAgIH0pO1xufSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX187XG4gICAgdmFyIF90eXBlb2YgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIiA/IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9iajtcbiAgICB9IDogZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xuICAgIH07XG4gICAgKGZ1bmN0aW9uKGZhY3RvcnkpIHtcbiAgICAgICAgaWYgKHRydWUpIHtcbiAgICAgICAgICAgICEoX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXyA9IFsgX193ZWJwYWNrX3JlcXVpcmVfXyg0KSwgX193ZWJwYWNrX3JlcXVpcmVfXygyKSBdLCBcbiAgICAgICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9IGZhY3RvcnksIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fID0gdHlwZW9mIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9PT0gXCJmdW5jdGlvblwiID8gX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLmFwcGx5KGV4cG9ydHMsIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18pIDogX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBcbiAgICAgICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fICE9PSB1bmRlZmluZWQgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pKTtcbiAgICAgICAgfSBlbHNlIHt9XG4gICAgfSkoZnVuY3Rpb24oJCwgSW5wdXRtYXNrKSB7XG4gICAgICAgIGlmICgkLmZuLmlucHV0bWFzayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAkLmZuLmlucHV0bWFzayA9IGZ1bmN0aW9uKGZuLCBvcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5wdG1hc2ssIGlucHV0ID0gdGhpc1swXTtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkKSBvcHRpb25zID0ge307XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmbiA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGZuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInVubWFza2VkdmFsdWVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dCAmJiBpbnB1dC5pbnB1dG1hc2sgPyBpbnB1dC5pbnB1dG1hc2sudW5tYXNrZWR2YWx1ZSgpIDogJChpbnB1dCkudmFsKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwicmVtb3ZlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0bWFzaykgdGhpcy5pbnB1dG1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJnZXRlbXB0eW1hc2tcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dCAmJiBpbnB1dC5pbnB1dG1hc2sgPyBpbnB1dC5pbnB1dG1hc2suZ2V0ZW1wdHltYXNrKCkgOiBcIlwiO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImhhc01hc2tlZFZhbHVlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5wdXQgJiYgaW5wdXQuaW5wdXRtYXNrID8gaW5wdXQuaW5wdXRtYXNrLmhhc01hc2tlZFZhbHVlKCkgOiBmYWxzZTtcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJpc0NvbXBsZXRlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5wdXQgJiYgaW5wdXQuaW5wdXRtYXNrID8gaW5wdXQuaW5wdXRtYXNrLmlzQ29tcGxldGUoKSA6IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZ2V0bWV0YWRhdGFcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dCAmJiBpbnB1dC5pbnB1dG1hc2sgPyBpbnB1dC5pbnB1dG1hc2suZ2V0bWV0YWRhdGEoKSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzZXR2YWx1ZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgSW5wdXRtYXNrLnNldFZhbHVlKGlucHV0LCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIm9wdGlvblwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0ICYmIGlucHV0LmlucHV0bWFzayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dC5pbnB1dG1hc2sub3B0aW9uKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRtYXNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmlucHV0bWFzay5vcHRpb24ob3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuYWxpYXMgPSBmbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5wdG1hc2sgPSBuZXcgSW5wdXRtYXNrKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBucHRtYXNrLm1hc2sodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShmbikpIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5hbGlhcyA9IGZuO1xuICAgICAgICAgICAgICAgICAgICBucHRtYXNrID0gbmV3IElucHV0bWFzayhvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5wdG1hc2subWFzayh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICgodHlwZW9mIGZuID09PSBcInVuZGVmaW5lZFwiID8gXCJ1bmRlZmluZWRcIiA6IF90eXBlb2YoZm4pKSA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG5wdG1hc2sgPSBuZXcgSW5wdXRtYXNrKGZuKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZuLm1hc2sgPT09IHVuZGVmaW5lZCAmJiBmbi5hbGlhcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0bWFzayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmlucHV0bWFzay5vcHRpb24oZm4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBucHRtYXNrLm1hc2sodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbnB0bWFzay5tYXNrKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGZuID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5wdG1hc2sgPSBuZXcgSW5wdXRtYXNrKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbnB0bWFzay5tYXNrKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAkLmZuLmlucHV0bWFzaztcbiAgICB9KTtcbn0gXSk7IiwiKCBmdW5jdGlvbiggZmFjdG9yeSApIHtcblx0aWYgKCB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCApIHtcblxuXHRcdC8vIEFNRC4gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIG1vZHVsZS5cblx0XHRkZWZpbmUoIFsgXCJqcXVlcnlcIiBdLCBmYWN0b3J5ICk7XG5cdH0gZWxzZSB7XG5cblx0XHQvLyBCcm93c2VyIGdsb2JhbHNcblx0XHRmYWN0b3J5KCBqUXVlcnkgKTtcblx0fVxufSAoIGZ1bmN0aW9uKCAkICkge1xuXG4kLnVpID0gJC51aSB8fCB7fTtcblxucmV0dXJuICQudWkudmVyc2lvbiA9IFwiMS4xMi4xXCI7XG5cbn0gKSApO1xuIiwiLyohXG4gKiBqUXVlcnkgVUkgUG9zaXRpb24gMS4xMi4xXG4gKiBodHRwOi8vanF1ZXJ5dWkuY29tXG4gKlxuICogQ29weXJpZ2h0IGpRdWVyeSBGb3VuZGF0aW9uIGFuZCBvdGhlciBjb250cmlidXRvcnNcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZS5cbiAqIGh0dHA6Ly9qcXVlcnkub3JnL2xpY2Vuc2VcbiAqXG4gKiBodHRwOi8vYXBpLmpxdWVyeXVpLmNvbS9wb3NpdGlvbi9cbiAqL1xuXG4vLz4+bGFiZWw6IFBvc2l0aW9uXG4vLz4+Z3JvdXA6IENvcmVcbi8vPj5kZXNjcmlwdGlvbjogUG9zaXRpb25zIGVsZW1lbnRzIHJlbGF0aXZlIHRvIG90aGVyIGVsZW1lbnRzLlxuLy8+PmRvY3M6IGh0dHA6Ly9hcGkuanF1ZXJ5dWkuY29tL3Bvc2l0aW9uL1xuLy8+PmRlbW9zOiBodHRwOi8vanF1ZXJ5dWkuY29tL3Bvc2l0aW9uL1xuXG4oIGZ1bmN0aW9uKCBmYWN0b3J5ICkge1xuXHRpZiAoIHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICkge1xuXG5cdFx0Ly8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxuXHRcdGRlZmluZSggWyBcImpxdWVyeVwiLCBcIi4vdmVyc2lvblwiIF0sIGZhY3RvcnkgKTtcblx0fSBlbHNlIHtcblxuXHRcdC8vIEJyb3dzZXIgZ2xvYmFsc1xuXHRcdGZhY3RvcnkoIGpRdWVyeSApO1xuXHR9XG59KCBmdW5jdGlvbiggJCApIHtcbiggZnVuY3Rpb24oKSB7XG52YXIgY2FjaGVkU2Nyb2xsYmFyV2lkdGgsXG5cdG1heCA9IE1hdGgubWF4LFxuXHRhYnMgPSBNYXRoLmFicyxcblx0cmhvcml6b250YWwgPSAvbGVmdHxjZW50ZXJ8cmlnaHQvLFxuXHRydmVydGljYWwgPSAvdG9wfGNlbnRlcnxib3R0b20vLFxuXHRyb2Zmc2V0ID0gL1tcXCtcXC1dXFxkKyhcXC5bXFxkXSspPyU/Lyxcblx0cnBvc2l0aW9uID0gL15cXHcrLyxcblx0cnBlcmNlbnQgPSAvJSQvLFxuXHRfcG9zaXRpb24gPSAkLmZuLnBvc2l0aW9uO1xuXG5mdW5jdGlvbiBnZXRPZmZzZXRzKCBvZmZzZXRzLCB3aWR0aCwgaGVpZ2h0ICkge1xuXHRyZXR1cm4gW1xuXHRcdHBhcnNlRmxvYXQoIG9mZnNldHNbIDAgXSApICogKCBycGVyY2VudC50ZXN0KCBvZmZzZXRzWyAwIF0gKSA/IHdpZHRoIC8gMTAwIDogMSApLFxuXHRcdHBhcnNlRmxvYXQoIG9mZnNldHNbIDEgXSApICogKCBycGVyY2VudC50ZXN0KCBvZmZzZXRzWyAxIF0gKSA/IGhlaWdodCAvIDEwMCA6IDEgKVxuXHRdO1xufVxuXG5mdW5jdGlvbiBwYXJzZUNzcyggZWxlbWVudCwgcHJvcGVydHkgKSB7XG5cdHJldHVybiBwYXJzZUludCggJC5jc3MoIGVsZW1lbnQsIHByb3BlcnR5ICksIDEwICkgfHwgMDtcbn1cblxuZnVuY3Rpb24gZ2V0RGltZW5zaW9ucyggZWxlbSApIHtcblx0dmFyIHJhdyA9IGVsZW1bIDAgXTtcblx0aWYgKCByYXcubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHdpZHRoOiBlbGVtLndpZHRoKCksXG5cdFx0XHRoZWlnaHQ6IGVsZW0uaGVpZ2h0KCksXG5cdFx0XHRvZmZzZXQ6IHsgdG9wOiAwLCBsZWZ0OiAwIH1cblx0XHR9O1xuXHR9XG5cdGlmICggJC5pc1dpbmRvdyggcmF3ICkgKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHdpZHRoOiBlbGVtLndpZHRoKCksXG5cdFx0XHRoZWlnaHQ6IGVsZW0uaGVpZ2h0KCksXG5cdFx0XHRvZmZzZXQ6IHsgdG9wOiBlbGVtLnNjcm9sbFRvcCgpLCBsZWZ0OiBlbGVtLnNjcm9sbExlZnQoKSB9XG5cdFx0fTtcblx0fVxuXHRpZiAoIHJhdy5wcmV2ZW50RGVmYXVsdCApIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0d2lkdGg6IDAsXG5cdFx0XHRoZWlnaHQ6IDAsXG5cdFx0XHRvZmZzZXQ6IHsgdG9wOiByYXcucGFnZVksIGxlZnQ6IHJhdy5wYWdlWCB9XG5cdFx0fTtcblx0fVxuXHRyZXR1cm4ge1xuXHRcdHdpZHRoOiBlbGVtLm91dGVyV2lkdGgoKSxcblx0XHRoZWlnaHQ6IGVsZW0ub3V0ZXJIZWlnaHQoKSxcblx0XHRvZmZzZXQ6IGVsZW0ub2Zmc2V0KClcblx0fTtcbn1cblxuJC5wb3NpdGlvbiA9IHtcblx0c2Nyb2xsYmFyV2lkdGg6IGZ1bmN0aW9uKCkge1xuXHRcdGlmICggY2FjaGVkU2Nyb2xsYmFyV2lkdGggIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybiBjYWNoZWRTY3JvbGxiYXJXaWR0aDtcblx0XHR9XG5cdFx0dmFyIHcxLCB3Mixcblx0XHRcdGRpdiA9ICQoIFwiPGRpdiBcIiArXG5cdFx0XHRcdFwic3R5bGU9J2Rpc3BsYXk6YmxvY2s7cG9zaXRpb246YWJzb2x1dGU7d2lkdGg6NTBweDtoZWlnaHQ6NTBweDtvdmVyZmxvdzpoaWRkZW47Jz5cIiArXG5cdFx0XHRcdFwiPGRpdiBzdHlsZT0naGVpZ2h0OjEwMHB4O3dpZHRoOmF1dG87Jz48L2Rpdj48L2Rpdj5cIiApLFxuXHRcdFx0aW5uZXJEaXYgPSBkaXYuY2hpbGRyZW4oKVsgMCBdO1xuXG5cdFx0JCggXCJib2R5XCIgKS5hcHBlbmQoIGRpdiApO1xuXHRcdHcxID0gaW5uZXJEaXYub2Zmc2V0V2lkdGg7XG5cdFx0ZGl2LmNzcyggXCJvdmVyZmxvd1wiLCBcInNjcm9sbFwiICk7XG5cblx0XHR3MiA9IGlubmVyRGl2Lm9mZnNldFdpZHRoO1xuXG5cdFx0aWYgKCB3MSA9PT0gdzIgKSB7XG5cdFx0XHR3MiA9IGRpdlsgMCBdLmNsaWVudFdpZHRoO1xuXHRcdH1cblxuXHRcdGRpdi5yZW1vdmUoKTtcblxuXHRcdHJldHVybiAoIGNhY2hlZFNjcm9sbGJhcldpZHRoID0gdzEgLSB3MiApO1xuXHR9LFxuXHRnZXRTY3JvbGxJbmZvOiBmdW5jdGlvbiggd2l0aGluICkge1xuXHRcdHZhciBvdmVyZmxvd1ggPSB3aXRoaW4uaXNXaW5kb3cgfHwgd2l0aGluLmlzRG9jdW1lbnQgPyBcIlwiIDpcblx0XHRcdFx0d2l0aGluLmVsZW1lbnQuY3NzKCBcIm92ZXJmbG93LXhcIiApLFxuXHRcdFx0b3ZlcmZsb3dZID0gd2l0aGluLmlzV2luZG93IHx8IHdpdGhpbi5pc0RvY3VtZW50ID8gXCJcIiA6XG5cdFx0XHRcdHdpdGhpbi5lbGVtZW50LmNzcyggXCJvdmVyZmxvdy15XCIgKSxcblx0XHRcdGhhc092ZXJmbG93WCA9IG92ZXJmbG93WCA9PT0gXCJzY3JvbGxcIiB8fFxuXHRcdFx0XHQoIG92ZXJmbG93WCA9PT0gXCJhdXRvXCIgJiYgd2l0aGluLndpZHRoIDwgd2l0aGluLmVsZW1lbnRbIDAgXS5zY3JvbGxXaWR0aCApLFxuXHRcdFx0aGFzT3ZlcmZsb3dZID0gb3ZlcmZsb3dZID09PSBcInNjcm9sbFwiIHx8XG5cdFx0XHRcdCggb3ZlcmZsb3dZID09PSBcImF1dG9cIiAmJiB3aXRoaW4uaGVpZ2h0IDwgd2l0aGluLmVsZW1lbnRbIDAgXS5zY3JvbGxIZWlnaHQgKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0d2lkdGg6IGhhc092ZXJmbG93WSA/ICQucG9zaXRpb24uc2Nyb2xsYmFyV2lkdGgoKSA6IDAsXG5cdFx0XHRoZWlnaHQ6IGhhc092ZXJmbG93WCA/ICQucG9zaXRpb24uc2Nyb2xsYmFyV2lkdGgoKSA6IDBcblx0XHR9O1xuXHR9LFxuXHRnZXRXaXRoaW5JbmZvOiBmdW5jdGlvbiggZWxlbWVudCApIHtcblx0XHR2YXIgd2l0aGluRWxlbWVudCA9ICQoIGVsZW1lbnQgfHwgd2luZG93ICksXG5cdFx0XHRpc1dpbmRvdyA9ICQuaXNXaW5kb3coIHdpdGhpbkVsZW1lbnRbIDAgXSApLFxuXHRcdFx0aXNEb2N1bWVudCA9ICEhd2l0aGluRWxlbWVudFsgMCBdICYmIHdpdGhpbkVsZW1lbnRbIDAgXS5ub2RlVHlwZSA9PT0gOSxcblx0XHRcdGhhc09mZnNldCA9ICFpc1dpbmRvdyAmJiAhaXNEb2N1bWVudDtcblx0XHRyZXR1cm4ge1xuXHRcdFx0ZWxlbWVudDogd2l0aGluRWxlbWVudCxcblx0XHRcdGlzV2luZG93OiBpc1dpbmRvdyxcblx0XHRcdGlzRG9jdW1lbnQ6IGlzRG9jdW1lbnQsXG5cdFx0XHRvZmZzZXQ6IGhhc09mZnNldCA/ICQoIGVsZW1lbnQgKS5vZmZzZXQoKSA6IHsgbGVmdDogMCwgdG9wOiAwIH0sXG5cdFx0XHRzY3JvbGxMZWZ0OiB3aXRoaW5FbGVtZW50LnNjcm9sbExlZnQoKSxcblx0XHRcdHNjcm9sbFRvcDogd2l0aGluRWxlbWVudC5zY3JvbGxUb3AoKSxcblx0XHRcdHdpZHRoOiB3aXRoaW5FbGVtZW50Lm91dGVyV2lkdGgoKSxcblx0XHRcdGhlaWdodDogd2l0aGluRWxlbWVudC5vdXRlckhlaWdodCgpXG5cdFx0fTtcblx0fVxufTtcblxuJC5mbi5wb3NpdGlvbiA9IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXHRpZiAoICFvcHRpb25zIHx8ICFvcHRpb25zLm9mICkge1xuXHRcdHJldHVybiBfcG9zaXRpb24uYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHR9XG5cblx0Ly8gTWFrZSBhIGNvcHksIHdlIGRvbid0IHdhbnQgdG8gbW9kaWZ5IGFyZ3VtZW50c1xuXHRvcHRpb25zID0gJC5leHRlbmQoIHt9LCBvcHRpb25zICk7XG5cblx0dmFyIGF0T2Zmc2V0LCB0YXJnZXRXaWR0aCwgdGFyZ2V0SGVpZ2h0LCB0YXJnZXRPZmZzZXQsIGJhc2VQb3NpdGlvbiwgZGltZW5zaW9ucyxcblx0XHR0YXJnZXQgPSAkKCBvcHRpb25zLm9mICksXG5cdFx0d2l0aGluID0gJC5wb3NpdGlvbi5nZXRXaXRoaW5JbmZvKCBvcHRpb25zLndpdGhpbiApLFxuXHRcdHNjcm9sbEluZm8gPSAkLnBvc2l0aW9uLmdldFNjcm9sbEluZm8oIHdpdGhpbiApLFxuXHRcdGNvbGxpc2lvbiA9ICggb3B0aW9ucy5jb2xsaXNpb24gfHwgXCJmbGlwXCIgKS5zcGxpdCggXCIgXCIgKSxcblx0XHRvZmZzZXRzID0ge307XG5cblx0ZGltZW5zaW9ucyA9IGdldERpbWVuc2lvbnMoIHRhcmdldCApO1xuXHRpZiAoIHRhcmdldFsgMCBdLnByZXZlbnREZWZhdWx0ICkge1xuXG5cdFx0Ly8gRm9yY2UgbGVmdCB0b3AgdG8gYWxsb3cgZmxpcHBpbmdcblx0XHRvcHRpb25zLmF0ID0gXCJsZWZ0IHRvcFwiO1xuXHR9XG5cdHRhcmdldFdpZHRoID0gZGltZW5zaW9ucy53aWR0aDtcblx0dGFyZ2V0SGVpZ2h0ID0gZGltZW5zaW9ucy5oZWlnaHQ7XG5cdHRhcmdldE9mZnNldCA9IGRpbWVuc2lvbnMub2Zmc2V0O1xuXG5cdC8vIENsb25lIHRvIHJldXNlIG9yaWdpbmFsIHRhcmdldE9mZnNldCBsYXRlclxuXHRiYXNlUG9zaXRpb24gPSAkLmV4dGVuZCgge30sIHRhcmdldE9mZnNldCApO1xuXG5cdC8vIEZvcmNlIG15IGFuZCBhdCB0byBoYXZlIHZhbGlkIGhvcml6b250YWwgYW5kIHZlcnRpY2FsIHBvc2l0aW9uc1xuXHQvLyBpZiBhIHZhbHVlIGlzIG1pc3Npbmcgb3IgaW52YWxpZCwgaXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gY2VudGVyXG5cdCQuZWFjaCggWyBcIm15XCIsIFwiYXRcIiBdLCBmdW5jdGlvbigpIHtcblx0XHR2YXIgcG9zID0gKCBvcHRpb25zWyB0aGlzIF0gfHwgXCJcIiApLnNwbGl0KCBcIiBcIiApLFxuXHRcdFx0aG9yaXpvbnRhbE9mZnNldCxcblx0XHRcdHZlcnRpY2FsT2Zmc2V0O1xuXG5cdFx0aWYgKCBwb3MubGVuZ3RoID09PSAxICkge1xuXHRcdFx0cG9zID0gcmhvcml6b250YWwudGVzdCggcG9zWyAwIF0gKSA/XG5cdFx0XHRcdHBvcy5jb25jYXQoIFsgXCJjZW50ZXJcIiBdICkgOlxuXHRcdFx0XHRydmVydGljYWwudGVzdCggcG9zWyAwIF0gKSA/XG5cdFx0XHRcdFx0WyBcImNlbnRlclwiIF0uY29uY2F0KCBwb3MgKSA6XG5cdFx0XHRcdFx0WyBcImNlbnRlclwiLCBcImNlbnRlclwiIF07XG5cdFx0fVxuXHRcdHBvc1sgMCBdID0gcmhvcml6b250YWwudGVzdCggcG9zWyAwIF0gKSA/IHBvc1sgMCBdIDogXCJjZW50ZXJcIjtcblx0XHRwb3NbIDEgXSA9IHJ2ZXJ0aWNhbC50ZXN0KCBwb3NbIDEgXSApID8gcG9zWyAxIF0gOiBcImNlbnRlclwiO1xuXG5cdFx0Ly8gQ2FsY3VsYXRlIG9mZnNldHNcblx0XHRob3Jpem9udGFsT2Zmc2V0ID0gcm9mZnNldC5leGVjKCBwb3NbIDAgXSApO1xuXHRcdHZlcnRpY2FsT2Zmc2V0ID0gcm9mZnNldC5leGVjKCBwb3NbIDEgXSApO1xuXHRcdG9mZnNldHNbIHRoaXMgXSA9IFtcblx0XHRcdGhvcml6b250YWxPZmZzZXQgPyBob3Jpem9udGFsT2Zmc2V0WyAwIF0gOiAwLFxuXHRcdFx0dmVydGljYWxPZmZzZXQgPyB2ZXJ0aWNhbE9mZnNldFsgMCBdIDogMFxuXHRcdF07XG5cblx0XHQvLyBSZWR1Y2UgdG8ganVzdCB0aGUgcG9zaXRpb25zIHdpdGhvdXQgdGhlIG9mZnNldHNcblx0XHRvcHRpb25zWyB0aGlzIF0gPSBbXG5cdFx0XHRycG9zaXRpb24uZXhlYyggcG9zWyAwIF0gKVsgMCBdLFxuXHRcdFx0cnBvc2l0aW9uLmV4ZWMoIHBvc1sgMSBdIClbIDAgXVxuXHRcdF07XG5cdH0gKTtcblxuXHQvLyBOb3JtYWxpemUgY29sbGlzaW9uIG9wdGlvblxuXHRpZiAoIGNvbGxpc2lvbi5sZW5ndGggPT09IDEgKSB7XG5cdFx0Y29sbGlzaW9uWyAxIF0gPSBjb2xsaXNpb25bIDAgXTtcblx0fVxuXG5cdGlmICggb3B0aW9ucy5hdFsgMCBdID09PSBcInJpZ2h0XCIgKSB7XG5cdFx0YmFzZVBvc2l0aW9uLmxlZnQgKz0gdGFyZ2V0V2lkdGg7XG5cdH0gZWxzZSBpZiAoIG9wdGlvbnMuYXRbIDAgXSA9PT0gXCJjZW50ZXJcIiApIHtcblx0XHRiYXNlUG9zaXRpb24ubGVmdCArPSB0YXJnZXRXaWR0aCAvIDI7XG5cdH1cblxuXHRpZiAoIG9wdGlvbnMuYXRbIDEgXSA9PT0gXCJib3R0b21cIiApIHtcblx0XHRiYXNlUG9zaXRpb24udG9wICs9IHRhcmdldEhlaWdodDtcblx0fSBlbHNlIGlmICggb3B0aW9ucy5hdFsgMSBdID09PSBcImNlbnRlclwiICkge1xuXHRcdGJhc2VQb3NpdGlvbi50b3AgKz0gdGFyZ2V0SGVpZ2h0IC8gMjtcblx0fVxuXG5cdGF0T2Zmc2V0ID0gZ2V0T2Zmc2V0cyggb2Zmc2V0cy5hdCwgdGFyZ2V0V2lkdGgsIHRhcmdldEhlaWdodCApO1xuXHRiYXNlUG9zaXRpb24ubGVmdCArPSBhdE9mZnNldFsgMCBdO1xuXHRiYXNlUG9zaXRpb24udG9wICs9IGF0T2Zmc2V0WyAxIF07XG5cblx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGNvbGxpc2lvblBvc2l0aW9uLCB1c2luZyxcblx0XHRcdGVsZW0gPSAkKCB0aGlzICksXG5cdFx0XHRlbGVtV2lkdGggPSBlbGVtLm91dGVyV2lkdGgoKSxcblx0XHRcdGVsZW1IZWlnaHQgPSBlbGVtLm91dGVySGVpZ2h0KCksXG5cdFx0XHRtYXJnaW5MZWZ0ID0gcGFyc2VDc3MoIHRoaXMsIFwibWFyZ2luTGVmdFwiICksXG5cdFx0XHRtYXJnaW5Ub3AgPSBwYXJzZUNzcyggdGhpcywgXCJtYXJnaW5Ub3BcIiApLFxuXHRcdFx0Y29sbGlzaW9uV2lkdGggPSBlbGVtV2lkdGggKyBtYXJnaW5MZWZ0ICsgcGFyc2VDc3MoIHRoaXMsIFwibWFyZ2luUmlnaHRcIiApICtcblx0XHRcdFx0c2Nyb2xsSW5mby53aWR0aCxcblx0XHRcdGNvbGxpc2lvbkhlaWdodCA9IGVsZW1IZWlnaHQgKyBtYXJnaW5Ub3AgKyBwYXJzZUNzcyggdGhpcywgXCJtYXJnaW5Cb3R0b21cIiApICtcblx0XHRcdFx0c2Nyb2xsSW5mby5oZWlnaHQsXG5cdFx0XHRwb3NpdGlvbiA9ICQuZXh0ZW5kKCB7fSwgYmFzZVBvc2l0aW9uICksXG5cdFx0XHRteU9mZnNldCA9IGdldE9mZnNldHMoIG9mZnNldHMubXksIGVsZW0ub3V0ZXJXaWR0aCgpLCBlbGVtLm91dGVySGVpZ2h0KCkgKTtcblxuXHRcdGlmICggb3B0aW9ucy5teVsgMCBdID09PSBcInJpZ2h0XCIgKSB7XG5cdFx0XHRwb3NpdGlvbi5sZWZ0IC09IGVsZW1XaWR0aDtcblx0XHR9IGVsc2UgaWYgKCBvcHRpb25zLm15WyAwIF0gPT09IFwiY2VudGVyXCIgKSB7XG5cdFx0XHRwb3NpdGlvbi5sZWZ0IC09IGVsZW1XaWR0aCAvIDI7XG5cdFx0fVxuXG5cdFx0aWYgKCBvcHRpb25zLm15WyAxIF0gPT09IFwiYm90dG9tXCIgKSB7XG5cdFx0XHRwb3NpdGlvbi50b3AgLT0gZWxlbUhlaWdodDtcblx0XHR9IGVsc2UgaWYgKCBvcHRpb25zLm15WyAxIF0gPT09IFwiY2VudGVyXCIgKSB7XG5cdFx0XHRwb3NpdGlvbi50b3AgLT0gZWxlbUhlaWdodCAvIDI7XG5cdFx0fVxuXG5cdFx0cG9zaXRpb24ubGVmdCArPSBteU9mZnNldFsgMCBdO1xuXHRcdHBvc2l0aW9uLnRvcCArPSBteU9mZnNldFsgMSBdO1xuXG5cdFx0Y29sbGlzaW9uUG9zaXRpb24gPSB7XG5cdFx0XHRtYXJnaW5MZWZ0OiBtYXJnaW5MZWZ0LFxuXHRcdFx0bWFyZ2luVG9wOiBtYXJnaW5Ub3Bcblx0XHR9O1xuXG5cdFx0JC5lYWNoKCBbIFwibGVmdFwiLCBcInRvcFwiIF0sIGZ1bmN0aW9uKCBpLCBkaXIgKSB7XG5cdFx0XHRpZiAoICQudWkucG9zaXRpb25bIGNvbGxpc2lvblsgaSBdIF0gKSB7XG5cdFx0XHRcdCQudWkucG9zaXRpb25bIGNvbGxpc2lvblsgaSBdIF1bIGRpciBdKCBwb3NpdGlvbiwge1xuXHRcdFx0XHRcdHRhcmdldFdpZHRoOiB0YXJnZXRXaWR0aCxcblx0XHRcdFx0XHR0YXJnZXRIZWlnaHQ6IHRhcmdldEhlaWdodCxcblx0XHRcdFx0XHRlbGVtV2lkdGg6IGVsZW1XaWR0aCxcblx0XHRcdFx0XHRlbGVtSGVpZ2h0OiBlbGVtSGVpZ2h0LFxuXHRcdFx0XHRcdGNvbGxpc2lvblBvc2l0aW9uOiBjb2xsaXNpb25Qb3NpdGlvbixcblx0XHRcdFx0XHRjb2xsaXNpb25XaWR0aDogY29sbGlzaW9uV2lkdGgsXG5cdFx0XHRcdFx0Y29sbGlzaW9uSGVpZ2h0OiBjb2xsaXNpb25IZWlnaHQsXG5cdFx0XHRcdFx0b2Zmc2V0OiBbIGF0T2Zmc2V0WyAwIF0gKyBteU9mZnNldFsgMCBdLCBhdE9mZnNldCBbIDEgXSArIG15T2Zmc2V0WyAxIF0gXSxcblx0XHRcdFx0XHRteTogb3B0aW9ucy5teSxcblx0XHRcdFx0XHRhdDogb3B0aW9ucy5hdCxcblx0XHRcdFx0XHR3aXRoaW46IHdpdGhpbixcblx0XHRcdFx0XHRlbGVtOiBlbGVtXG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cblx0XHRpZiAoIG9wdGlvbnMudXNpbmcgKSB7XG5cblx0XHRcdC8vIEFkZHMgZmVlZGJhY2sgYXMgc2Vjb25kIGFyZ3VtZW50IHRvIHVzaW5nIGNhbGxiYWNrLCBpZiBwcmVzZW50XG5cdFx0XHR1c2luZyA9IGZ1bmN0aW9uKCBwcm9wcyApIHtcblx0XHRcdFx0dmFyIGxlZnQgPSB0YXJnZXRPZmZzZXQubGVmdCAtIHBvc2l0aW9uLmxlZnQsXG5cdFx0XHRcdFx0cmlnaHQgPSBsZWZ0ICsgdGFyZ2V0V2lkdGggLSBlbGVtV2lkdGgsXG5cdFx0XHRcdFx0dG9wID0gdGFyZ2V0T2Zmc2V0LnRvcCAtIHBvc2l0aW9uLnRvcCxcblx0XHRcdFx0XHRib3R0b20gPSB0b3AgKyB0YXJnZXRIZWlnaHQgLSBlbGVtSGVpZ2h0LFxuXHRcdFx0XHRcdGZlZWRiYWNrID0ge1xuXHRcdFx0XHRcdFx0dGFyZ2V0OiB7XG5cdFx0XHRcdFx0XHRcdGVsZW1lbnQ6IHRhcmdldCxcblx0XHRcdFx0XHRcdFx0bGVmdDogdGFyZ2V0T2Zmc2V0LmxlZnQsXG5cdFx0XHRcdFx0XHRcdHRvcDogdGFyZ2V0T2Zmc2V0LnRvcCxcblx0XHRcdFx0XHRcdFx0d2lkdGg6IHRhcmdldFdpZHRoLFxuXHRcdFx0XHRcdFx0XHRoZWlnaHQ6IHRhcmdldEhlaWdodFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdGVsZW1lbnQ6IHtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudDogZWxlbSxcblx0XHRcdFx0XHRcdFx0bGVmdDogcG9zaXRpb24ubGVmdCxcblx0XHRcdFx0XHRcdFx0dG9wOiBwb3NpdGlvbi50b3AsXG5cdFx0XHRcdFx0XHRcdHdpZHRoOiBlbGVtV2lkdGgsXG5cdFx0XHRcdFx0XHRcdGhlaWdodDogZWxlbUhlaWdodFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdGhvcml6b250YWw6IHJpZ2h0IDwgMCA/IFwibGVmdFwiIDogbGVmdCA+IDAgPyBcInJpZ2h0XCIgOiBcImNlbnRlclwiLFxuXHRcdFx0XHRcdFx0dmVydGljYWw6IGJvdHRvbSA8IDAgPyBcInRvcFwiIDogdG9wID4gMCA/IFwiYm90dG9tXCIgOiBcIm1pZGRsZVwiXG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0aWYgKCB0YXJnZXRXaWR0aCA8IGVsZW1XaWR0aCAmJiBhYnMoIGxlZnQgKyByaWdodCApIDwgdGFyZ2V0V2lkdGggKSB7XG5cdFx0XHRcdFx0ZmVlZGJhY2suaG9yaXpvbnRhbCA9IFwiY2VudGVyXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCB0YXJnZXRIZWlnaHQgPCBlbGVtSGVpZ2h0ICYmIGFicyggdG9wICsgYm90dG9tICkgPCB0YXJnZXRIZWlnaHQgKSB7XG5cdFx0XHRcdFx0ZmVlZGJhY2sudmVydGljYWwgPSBcIm1pZGRsZVwiO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggbWF4KCBhYnMoIGxlZnQgKSwgYWJzKCByaWdodCApICkgPiBtYXgoIGFicyggdG9wICksIGFicyggYm90dG9tICkgKSApIHtcblx0XHRcdFx0XHRmZWVkYmFjay5pbXBvcnRhbnQgPSBcImhvcml6b250YWxcIjtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRmZWVkYmFjay5pbXBvcnRhbnQgPSBcInZlcnRpY2FsXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0b3B0aW9ucy51c2luZy5jYWxsKCB0aGlzLCBwcm9wcywgZmVlZGJhY2sgKTtcblx0XHRcdH07XG5cdFx0fVxuXG5cdFx0ZWxlbS5vZmZzZXQoICQuZXh0ZW5kKCBwb3NpdGlvbiwgeyB1c2luZzogdXNpbmcgfSApICk7XG5cdH0gKTtcbn07XG5cbiQudWkucG9zaXRpb24gPSB7XG5cdGZpdDoge1xuXHRcdGxlZnQ6IGZ1bmN0aW9uKCBwb3NpdGlvbiwgZGF0YSApIHtcblx0XHRcdHZhciB3aXRoaW4gPSBkYXRhLndpdGhpbixcblx0XHRcdFx0d2l0aGluT2Zmc2V0ID0gd2l0aGluLmlzV2luZG93ID8gd2l0aGluLnNjcm9sbExlZnQgOiB3aXRoaW4ub2Zmc2V0LmxlZnQsXG5cdFx0XHRcdG91dGVyV2lkdGggPSB3aXRoaW4ud2lkdGgsXG5cdFx0XHRcdGNvbGxpc2lvblBvc0xlZnQgPSBwb3NpdGlvbi5sZWZ0IC0gZGF0YS5jb2xsaXNpb25Qb3NpdGlvbi5tYXJnaW5MZWZ0LFxuXHRcdFx0XHRvdmVyTGVmdCA9IHdpdGhpbk9mZnNldCAtIGNvbGxpc2lvblBvc0xlZnQsXG5cdFx0XHRcdG92ZXJSaWdodCA9IGNvbGxpc2lvblBvc0xlZnQgKyBkYXRhLmNvbGxpc2lvbldpZHRoIC0gb3V0ZXJXaWR0aCAtIHdpdGhpbk9mZnNldCxcblx0XHRcdFx0bmV3T3ZlclJpZ2h0O1xuXG5cdFx0XHQvLyBFbGVtZW50IGlzIHdpZGVyIHRoYW4gd2l0aGluXG5cdFx0XHRpZiAoIGRhdGEuY29sbGlzaW9uV2lkdGggPiBvdXRlcldpZHRoICkge1xuXG5cdFx0XHRcdC8vIEVsZW1lbnQgaXMgaW5pdGlhbGx5IG92ZXIgdGhlIGxlZnQgc2lkZSBvZiB3aXRoaW5cblx0XHRcdFx0aWYgKCBvdmVyTGVmdCA+IDAgJiYgb3ZlclJpZ2h0IDw9IDAgKSB7XG5cdFx0XHRcdFx0bmV3T3ZlclJpZ2h0ID0gcG9zaXRpb24ubGVmdCArIG92ZXJMZWZ0ICsgZGF0YS5jb2xsaXNpb25XaWR0aCAtIG91dGVyV2lkdGggLVxuXHRcdFx0XHRcdFx0d2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRcdHBvc2l0aW9uLmxlZnQgKz0gb3ZlckxlZnQgLSBuZXdPdmVyUmlnaHQ7XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciByaWdodCBzaWRlIG9mIHdpdGhpblxuXHRcdFx0XHR9IGVsc2UgaWYgKCBvdmVyUmlnaHQgPiAwICYmIG92ZXJMZWZ0IDw9IDAgKSB7XG5cdFx0XHRcdFx0cG9zaXRpb24ubGVmdCA9IHdpdGhpbk9mZnNldDtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIGJvdGggbGVmdCBhbmQgcmlnaHQgc2lkZXMgb2Ygd2l0aGluXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aWYgKCBvdmVyTGVmdCA+IG92ZXJSaWdodCApIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uLmxlZnQgPSB3aXRoaW5PZmZzZXQgKyBvdXRlcldpZHRoIC0gZGF0YS5jb2xsaXNpb25XaWR0aDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0cG9zaXRpb24ubGVmdCA9IHdpdGhpbk9mZnNldDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gVG9vIGZhciBsZWZ0IC0+IGFsaWduIHdpdGggbGVmdCBlZGdlXG5cdFx0XHR9IGVsc2UgaWYgKCBvdmVyTGVmdCA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLmxlZnQgKz0gb3ZlckxlZnQ7XG5cblx0XHRcdC8vIFRvbyBmYXIgcmlnaHQgLT4gYWxpZ24gd2l0aCByaWdodCBlZGdlXG5cdFx0XHR9IGVsc2UgaWYgKCBvdmVyUmlnaHQgPiAwICkge1xuXHRcdFx0XHRwb3NpdGlvbi5sZWZ0IC09IG92ZXJSaWdodDtcblxuXHRcdFx0Ly8gQWRqdXN0IGJhc2VkIG9uIHBvc2l0aW9uIGFuZCBtYXJnaW5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHBvc2l0aW9uLmxlZnQgPSBtYXgoIHBvc2l0aW9uLmxlZnQgLSBjb2xsaXNpb25Qb3NMZWZ0LCBwb3NpdGlvbi5sZWZ0ICk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHR0b3A6IGZ1bmN0aW9uKCBwb3NpdGlvbiwgZGF0YSApIHtcblx0XHRcdHZhciB3aXRoaW4gPSBkYXRhLndpdGhpbixcblx0XHRcdFx0d2l0aGluT2Zmc2V0ID0gd2l0aGluLmlzV2luZG93ID8gd2l0aGluLnNjcm9sbFRvcCA6IHdpdGhpbi5vZmZzZXQudG9wLFxuXHRcdFx0XHRvdXRlckhlaWdodCA9IGRhdGEud2l0aGluLmhlaWdodCxcblx0XHRcdFx0Y29sbGlzaW9uUG9zVG9wID0gcG9zaXRpb24udG9wIC0gZGF0YS5jb2xsaXNpb25Qb3NpdGlvbi5tYXJnaW5Ub3AsXG5cdFx0XHRcdG92ZXJUb3AgPSB3aXRoaW5PZmZzZXQgLSBjb2xsaXNpb25Qb3NUb3AsXG5cdFx0XHRcdG92ZXJCb3R0b20gPSBjb2xsaXNpb25Qb3NUb3AgKyBkYXRhLmNvbGxpc2lvbkhlaWdodCAtIG91dGVySGVpZ2h0IC0gd2l0aGluT2Zmc2V0LFxuXHRcdFx0XHRuZXdPdmVyQm90dG9tO1xuXG5cdFx0XHQvLyBFbGVtZW50IGlzIHRhbGxlciB0aGFuIHdpdGhpblxuXHRcdFx0aWYgKCBkYXRhLmNvbGxpc2lvbkhlaWdodCA+IG91dGVySGVpZ2h0ICkge1xuXG5cdFx0XHRcdC8vIEVsZW1lbnQgaXMgaW5pdGlhbGx5IG92ZXIgdGhlIHRvcCBvZiB3aXRoaW5cblx0XHRcdFx0aWYgKCBvdmVyVG9wID4gMCAmJiBvdmVyQm90dG9tIDw9IDAgKSB7XG5cdFx0XHRcdFx0bmV3T3ZlckJvdHRvbSA9IHBvc2l0aW9uLnRvcCArIG92ZXJUb3AgKyBkYXRhLmNvbGxpc2lvbkhlaWdodCAtIG91dGVySGVpZ2h0IC1cblx0XHRcdFx0XHRcdHdpdGhpbk9mZnNldDtcblx0XHRcdFx0XHRwb3NpdGlvbi50b3AgKz0gb3ZlclRvcCAtIG5ld092ZXJCb3R0b207XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciBib3R0b20gb2Ygd2l0aGluXG5cdFx0XHRcdH0gZWxzZSBpZiAoIG92ZXJCb3R0b20gPiAwICYmIG92ZXJUb3AgPD0gMCApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi50b3AgPSB3aXRoaW5PZmZzZXQ7XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciBib3RoIHRvcCBhbmQgYm90dG9tIG9mIHdpdGhpblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlmICggb3ZlclRvcCA+IG92ZXJCb3R0b20gKSB7XG5cdFx0XHRcdFx0XHRwb3NpdGlvbi50b3AgPSB3aXRoaW5PZmZzZXQgKyBvdXRlckhlaWdodCAtIGRhdGEuY29sbGlzaW9uSGVpZ2h0O1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRwb3NpdGlvbi50b3AgPSB3aXRoaW5PZmZzZXQ7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdC8vIFRvbyBmYXIgdXAgLT4gYWxpZ24gd2l0aCB0b3Bcblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJUb3AgPiAwICkge1xuXHRcdFx0XHRwb3NpdGlvbi50b3AgKz0gb3ZlclRvcDtcblxuXHRcdFx0Ly8gVG9vIGZhciBkb3duIC0+IGFsaWduIHdpdGggYm90dG9tIGVkZ2Vcblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJCb3R0b20gPiAwICkge1xuXHRcdFx0XHRwb3NpdGlvbi50b3AgLT0gb3ZlckJvdHRvbTtcblxuXHRcdFx0Ly8gQWRqdXN0IGJhc2VkIG9uIHBvc2l0aW9uIGFuZCBtYXJnaW5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHBvc2l0aW9uLnRvcCA9IG1heCggcG9zaXRpb24udG9wIC0gY29sbGlzaW9uUG9zVG9wLCBwb3NpdGlvbi50b3AgKTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdGZsaXA6IHtcblx0XHRsZWZ0OiBmdW5jdGlvbiggcG9zaXRpb24sIGRhdGEgKSB7XG5cdFx0XHR2YXIgd2l0aGluID0gZGF0YS53aXRoaW4sXG5cdFx0XHRcdHdpdGhpbk9mZnNldCA9IHdpdGhpbi5vZmZzZXQubGVmdCArIHdpdGhpbi5zY3JvbGxMZWZ0LFxuXHRcdFx0XHRvdXRlcldpZHRoID0gd2l0aGluLndpZHRoLFxuXHRcdFx0XHRvZmZzZXRMZWZ0ID0gd2l0aGluLmlzV2luZG93ID8gd2l0aGluLnNjcm9sbExlZnQgOiB3aXRoaW4ub2Zmc2V0LmxlZnQsXG5cdFx0XHRcdGNvbGxpc2lvblBvc0xlZnQgPSBwb3NpdGlvbi5sZWZ0IC0gZGF0YS5jb2xsaXNpb25Qb3NpdGlvbi5tYXJnaW5MZWZ0LFxuXHRcdFx0XHRvdmVyTGVmdCA9IGNvbGxpc2lvblBvc0xlZnQgLSBvZmZzZXRMZWZ0LFxuXHRcdFx0XHRvdmVyUmlnaHQgPSBjb2xsaXNpb25Qb3NMZWZ0ICsgZGF0YS5jb2xsaXNpb25XaWR0aCAtIG91dGVyV2lkdGggLSBvZmZzZXRMZWZ0LFxuXHRcdFx0XHRteU9mZnNldCA9IGRhdGEubXlbIDAgXSA9PT0gXCJsZWZ0XCIgP1xuXHRcdFx0XHRcdC1kYXRhLmVsZW1XaWR0aCA6XG5cdFx0XHRcdFx0ZGF0YS5teVsgMCBdID09PSBcInJpZ2h0XCIgP1xuXHRcdFx0XHRcdFx0ZGF0YS5lbGVtV2lkdGggOlxuXHRcdFx0XHRcdFx0MCxcblx0XHRcdFx0YXRPZmZzZXQgPSBkYXRhLmF0WyAwIF0gPT09IFwibGVmdFwiID9cblx0XHRcdFx0XHRkYXRhLnRhcmdldFdpZHRoIDpcblx0XHRcdFx0XHRkYXRhLmF0WyAwIF0gPT09IFwicmlnaHRcIiA/XG5cdFx0XHRcdFx0XHQtZGF0YS50YXJnZXRXaWR0aCA6XG5cdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRvZmZzZXQgPSAtMiAqIGRhdGEub2Zmc2V0WyAwIF0sXG5cdFx0XHRcdG5ld092ZXJSaWdodCxcblx0XHRcdFx0bmV3T3ZlckxlZnQ7XG5cblx0XHRcdGlmICggb3ZlckxlZnQgPCAwICkge1xuXHRcdFx0XHRuZXdPdmVyUmlnaHQgPSBwb3NpdGlvbi5sZWZ0ICsgbXlPZmZzZXQgKyBhdE9mZnNldCArIG9mZnNldCArIGRhdGEuY29sbGlzaW9uV2lkdGggLVxuXHRcdFx0XHRcdG91dGVyV2lkdGggLSB3aXRoaW5PZmZzZXQ7XG5cdFx0XHRcdGlmICggbmV3T3ZlclJpZ2h0IDwgMCB8fCBuZXdPdmVyUmlnaHQgPCBhYnMoIG92ZXJMZWZ0ICkgKSB7XG5cdFx0XHRcdFx0cG9zaXRpb24ubGVmdCArPSBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0O1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKCBvdmVyUmlnaHQgPiAwICkge1xuXHRcdFx0XHRuZXdPdmVyTGVmdCA9IHBvc2l0aW9uLmxlZnQgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpbkxlZnQgKyBteU9mZnNldCArXG5cdFx0XHRcdFx0YXRPZmZzZXQgKyBvZmZzZXQgLSBvZmZzZXRMZWZ0O1xuXHRcdFx0XHRpZiAoIG5ld092ZXJMZWZ0ID4gMCB8fCBhYnMoIG5ld092ZXJMZWZ0ICkgPCBvdmVyUmlnaHQgKSB7XG5cdFx0XHRcdFx0cG9zaXRpb24ubGVmdCArPSBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblx0XHR0b3A6IGZ1bmN0aW9uKCBwb3NpdGlvbiwgZGF0YSApIHtcblx0XHRcdHZhciB3aXRoaW4gPSBkYXRhLndpdGhpbixcblx0XHRcdFx0d2l0aGluT2Zmc2V0ID0gd2l0aGluLm9mZnNldC50b3AgKyB3aXRoaW4uc2Nyb2xsVG9wLFxuXHRcdFx0XHRvdXRlckhlaWdodCA9IHdpdGhpbi5oZWlnaHQsXG5cdFx0XHRcdG9mZnNldFRvcCA9IHdpdGhpbi5pc1dpbmRvdyA/IHdpdGhpbi5zY3JvbGxUb3AgOiB3aXRoaW4ub2Zmc2V0LnRvcCxcblx0XHRcdFx0Y29sbGlzaW9uUG9zVG9wID0gcG9zaXRpb24udG9wIC0gZGF0YS5jb2xsaXNpb25Qb3NpdGlvbi5tYXJnaW5Ub3AsXG5cdFx0XHRcdG92ZXJUb3AgPSBjb2xsaXNpb25Qb3NUb3AgLSBvZmZzZXRUb3AsXG5cdFx0XHRcdG92ZXJCb3R0b20gPSBjb2xsaXNpb25Qb3NUb3AgKyBkYXRhLmNvbGxpc2lvbkhlaWdodCAtIG91dGVySGVpZ2h0IC0gb2Zmc2V0VG9wLFxuXHRcdFx0XHR0b3AgPSBkYXRhLm15WyAxIF0gPT09IFwidG9wXCIsXG5cdFx0XHRcdG15T2Zmc2V0ID0gdG9wID9cblx0XHRcdFx0XHQtZGF0YS5lbGVtSGVpZ2h0IDpcblx0XHRcdFx0XHRkYXRhLm15WyAxIF0gPT09IFwiYm90dG9tXCIgP1xuXHRcdFx0XHRcdFx0ZGF0YS5lbGVtSGVpZ2h0IDpcblx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdGF0T2Zmc2V0ID0gZGF0YS5hdFsgMSBdID09PSBcInRvcFwiID9cblx0XHRcdFx0XHRkYXRhLnRhcmdldEhlaWdodCA6XG5cdFx0XHRcdFx0ZGF0YS5hdFsgMSBdID09PSBcImJvdHRvbVwiID9cblx0XHRcdFx0XHRcdC1kYXRhLnRhcmdldEhlaWdodCA6XG5cdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRvZmZzZXQgPSAtMiAqIGRhdGEub2Zmc2V0WyAxIF0sXG5cdFx0XHRcdG5ld092ZXJUb3AsXG5cdFx0XHRcdG5ld092ZXJCb3R0b207XG5cdFx0XHRpZiAoIG92ZXJUb3AgPCAwICkge1xuXHRcdFx0XHRuZXdPdmVyQm90dG9tID0gcG9zaXRpb24udG9wICsgbXlPZmZzZXQgKyBhdE9mZnNldCArIG9mZnNldCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC1cblx0XHRcdFx0XHRvdXRlckhlaWdodCAtIHdpdGhpbk9mZnNldDtcblx0XHRcdFx0aWYgKCBuZXdPdmVyQm90dG9tIDwgMCB8fCBuZXdPdmVyQm90dG9tIDwgYWJzKCBvdmVyVG9wICkgKSB7XG5cdFx0XHRcdFx0cG9zaXRpb24udG9wICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJCb3R0b20gPiAwICkge1xuXHRcdFx0XHRuZXdPdmVyVG9wID0gcG9zaXRpb24udG9wIC0gZGF0YS5jb2xsaXNpb25Qb3NpdGlvbi5tYXJnaW5Ub3AgKyBteU9mZnNldCArIGF0T2Zmc2V0ICtcblx0XHRcdFx0XHRvZmZzZXQgLSBvZmZzZXRUb3A7XG5cdFx0XHRcdGlmICggbmV3T3ZlclRvcCA+IDAgfHwgYWJzKCBuZXdPdmVyVG9wICkgPCBvdmVyQm90dG9tICkge1xuXHRcdFx0XHRcdHBvc2l0aW9uLnRvcCArPSBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHRmbGlwZml0OiB7XG5cdFx0bGVmdDogZnVuY3Rpb24oKSB7XG5cdFx0XHQkLnVpLnBvc2l0aW9uLmZsaXAubGVmdC5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHQkLnVpLnBvc2l0aW9uLmZpdC5sZWZ0LmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHR9LFxuXHRcdHRvcDogZnVuY3Rpb24oKSB7XG5cdFx0XHQkLnVpLnBvc2l0aW9uLmZsaXAudG9wLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdCQudWkucG9zaXRpb24uZml0LnRvcC5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0fVxuXHR9XG59O1xuXG59ICkoKTtcblxucmV0dXJuICQudWkucG9zaXRpb247XG5cbn0gKSApO1xuIiwiOy8qISBzaG93ZG93biB2IDEuOS4xIC0gMDItMTEtMjAxOSAqL1xyXG4oZnVuY3Rpb24oKXtcclxuLyoqXG4gKiBDcmVhdGVkIGJ5IFRpdmllIG9uIDEzLTA3LTIwMTUuXG4gKi9cblxuZnVuY3Rpb24gZ2V0RGVmYXVsdE9wdHMgKHNpbXBsZSkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIGRlZmF1bHRPcHRpb25zID0ge1xuICAgIG9taXRFeHRyYVdMSW5Db2RlQmxvY2tzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdPbWl0IHRoZSBkZWZhdWx0IGV4dHJhIHdoaXRlbGluZSBhZGRlZCB0byBjb2RlIGJsb2NrcycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIG5vSGVhZGVySWQ6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1R1cm4gb24vb2ZmIGdlbmVyYXRlZCBoZWFkZXIgaWQnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBwcmVmaXhIZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnQWRkIGEgcHJlZml4IHRvIHRoZSBnZW5lcmF0ZWQgaGVhZGVyIGlkcy4gUGFzc2luZyBhIHN0cmluZyB3aWxsIHByZWZpeCB0aGF0IHN0cmluZyB0byB0aGUgaGVhZGVyIGlkLiBTZXR0aW5nIHRvIHRydWUgd2lsbCBhZGQgYSBnZW5lcmljIFxcJ3NlY3Rpb24tXFwnIHByZWZpeCcsXG4gICAgICB0eXBlOiAnc3RyaW5nJ1xuICAgIH0sXG4gICAgcmF3UHJlZml4SGVhZGVySWQ6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1NldHRpbmcgdGhpcyBvcHRpb24gdG8gdHJ1ZSB3aWxsIHByZXZlbnQgc2hvd2Rvd24gZnJvbSBtb2RpZnlpbmcgdGhlIHByZWZpeC4gVGhpcyBtaWdodCByZXN1bHQgaW4gbWFsZm9ybWVkIElEcyAoaWYsIGZvciBpbnN0YW5jZSwgdGhlIFwiIGNoYXIgaXMgdXNlZCBpbiB0aGUgcHJlZml4KScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoQ29tcGF0aWJsZUhlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdHZW5lcmF0ZSBoZWFkZXIgaWRzIGNvbXBhdGlibGUgd2l0aCBnaXRodWIgc3R5bGUgKHNwYWNlcyBhcmUgcmVwbGFjZWQgd2l0aCBkYXNoZXMsIGEgYnVuY2ggb2Ygbm9uIGFscGhhbnVtZXJpYyBjaGFycyBhcmUgcmVtb3ZlZCknLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICByYXdIZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnUmVtb3ZlIG9ubHkgc3BhY2VzLCBcXCcgYW5kIFwiIGZyb20gZ2VuZXJhdGVkIGhlYWRlciBpZHMgKGluY2x1ZGluZyBwcmVmaXhlcyksIHJlcGxhY2luZyB0aGVtIHdpdGggZGFzaGVzICgtKS4gV0FSTklORzogVGhpcyBtaWdodCByZXN1bHQgaW4gbWFsZm9ybWVkIGlkcycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGhlYWRlckxldmVsU3RhcnQ6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1RoZSBoZWFkZXIgYmxvY2tzIGxldmVsIHN0YXJ0JyxcbiAgICAgIHR5cGU6ICdpbnRlZ2VyJ1xuICAgIH0sXG4gICAgcGFyc2VJbWdEaW1lbnNpb25zOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiBpbWFnZSBkaW1lbnNpb24gcGFyc2luZycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHNpbXBsaWZpZWRBdXRvTGluazoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgR0ZNIGF1dG9saW5rIHN0eWxlJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZXhjbHVkZVRyYWlsaW5nUHVuY3R1YXRpb25Gcm9tVVJMczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnRXhjbHVkZXMgdHJhaWxpbmcgcHVuY3R1YXRpb24gZnJvbSBsaW5rcyBnZW5lcmF0ZWQgd2l0aCBhdXRvTGlua2luZycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGxpdGVyYWxNaWRXb3JkVW5kZXJzY29yZXM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1BhcnNlIG1pZHdvcmQgdW5kZXJzY29yZXMgYXMgbGl0ZXJhbCB1bmRlcnNjb3JlcycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGxpdGVyYWxNaWRXb3JkQXN0ZXJpc2tzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdQYXJzZSBtaWR3b3JkIGFzdGVyaXNrcyBhcyBsaXRlcmFsIGFzdGVyaXNrcycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHN0cmlrZXRocm91Z2g6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1R1cm4gb24vb2ZmIHN0cmlrZXRocm91Z2ggc3VwcG9ydCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHRhYmxlczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgdGFibGVzIHN1cHBvcnQnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICB0YWJsZXNIZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnQWRkIGFuIGlkIHRvIHRhYmxlIGhlYWRlcnMnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBnaENvZGVCbG9ja3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogdHJ1ZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgR0ZNIGZlbmNlZCBjb2RlIGJsb2NrcyBzdXBwb3J0JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgdGFza2xpc3RzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiBHRk0gdGFza2xpc3Qgc3VwcG9ydCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHNtb290aExpdmVQcmV2aWV3OiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdQcmV2ZW50cyB3ZWlyZCBlZmZlY3RzIGluIGxpdmUgcHJldmlld3MgZHVlIHRvIGluY29tcGxldGUgaW5wdXQnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBzbWFydEluZGVudGF0aW9uRml4OiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdUcmllcyB0byBzbWFydGx5IGZpeCBpbmRlbnRhdGlvbiBpbiBlczYgc3RyaW5ncycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGRpc2FibGVGb3JjZWQ0U3BhY2VzSW5kZW50ZWRTdWJsaXN0czoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRGlzYWJsZXMgdGhlIHJlcXVpcmVtZW50IG9mIGluZGVudGluZyBuZXN0ZWQgc3VibGlzdHMgYnkgNCBzcGFjZXMnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBzaW1wbGVMaW5lQnJlYWtzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdQYXJzZXMgc2ltcGxlIGxpbmUgYnJlYWtzIGFzIDxicj4gKEdGTSBTdHlsZSknLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICByZXF1aXJlU3BhY2VCZWZvcmVIZWFkaW5nVGV4dDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnTWFrZXMgYWRkaW5nIGEgc3BhY2UgYmV0d2VlbiBgI2AgYW5kIHRoZSBoZWFkZXIgdGV4dCBtYW5kYXRvcnkgKEdGTSBTdHlsZSknLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBnaE1lbnRpb25zOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdFbmFibGVzIGdpdGh1YiBAbWVudGlvbnMnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBnaE1lbnRpb25zTGluazoge1xuICAgICAgZGVmYXVsdFZhbHVlOiAnaHR0cHM6Ly9naXRodWIuY29tL3t1fScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0NoYW5nZXMgdGhlIGxpbmsgZ2VuZXJhdGVkIGJ5IEBtZW50aW9ucy4gT25seSBhcHBsaWVzIGlmIGdoTWVudGlvbnMgb3B0aW9uIGlzIGVuYWJsZWQuJyxcbiAgICAgIHR5cGU6ICdzdHJpbmcnXG4gICAgfSxcbiAgICBlbmNvZGVFbWFpbHM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogdHJ1ZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW5jb2RlIGUtbWFpbCBhZGRyZXNzZXMgdGhyb3VnaCB0aGUgdXNlIG9mIENoYXJhY3RlciBFbnRpdGllcywgdHJhbnNmb3JtaW5nIEFTQ0lJIGUtbWFpbCBhZGRyZXNzZXMgaW50byBpdHMgZXF1aXZhbGVudCBkZWNpbWFsIGVudGl0aWVzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgb3BlbkxpbmtzSW5OZXdXaW5kb3c6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ09wZW4gYWxsIGxpbmtzIGluIG5ldyB3aW5kb3dzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgYmFja3NsYXNoRXNjYXBlc0hUTUxUYWdzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdTdXBwb3J0IGZvciBIVE1MIFRhZyBlc2NhcGluZy4gZXg6IFxcPGRpdj5mb29cXDwvZGl2PicsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGVtb2ppOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdFbmFibGUgZW1vamkgc3VwcG9ydC4gRXg6IGB0aGlzIGlzIGEgOnNtaWxlOiBlbW9qaWAnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICB1bmRlcmxpbmU6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VuYWJsZSBzdXBwb3J0IGZvciB1bmRlcmxpbmUuIFN5bnRheCBpcyBkb3VibGUgb3IgdHJpcGxlIHVuZGVyc2NvcmVzOiBgX191bmRlcmxpbmUgd29yZF9fYC4gV2l0aCB0aGlzIG9wdGlvbiBlbmFibGVkLCB1bmRlcnNjb3JlcyBubyBsb25nZXIgcGFyc2VzIGludG8gYDxlbT5gIGFuZCBgPHN0cm9uZz5gJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgY29tcGxldGVIVE1MRG9jdW1lbnQ6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ091dHB1dHMgYSBjb21wbGV0ZSBodG1sIGRvY3VtZW50LCBpbmNsdWRpbmcgYDxodG1sPmAsIGA8aGVhZD5gIGFuZCBgPGJvZHk+YCB0YWdzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbWV0YWRhdGE6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VuYWJsZSBzdXBwb3J0IGZvciBkb2N1bWVudCBtZXRhZGF0YSAoZGVmaW5lZCBhdCB0aGUgdG9wIG9mIHRoZSBkb2N1bWVudCBiZXR3ZWVuIGDCq8KrwqtgIGFuZCBgwrvCu8K7YCBvciBiZXR3ZWVuIGAtLS1gIGFuZCBgLS0tYCkuJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc3BsaXRBZGphY2VudEJsb2NrcXVvdGVzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdTcGxpdCBhZGphY2VudCBibG9ja3F1b3RlIGJsb2NrcycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9XG4gIH07XG4gIGlmIChzaW1wbGUgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZGVmYXVsdE9wdGlvbnMpKTtcbiAgfVxuICB2YXIgcmV0ID0ge307XG4gIGZvciAodmFyIG9wdCBpbiBkZWZhdWx0T3B0aW9ucykge1xuICAgIGlmIChkZWZhdWx0T3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShvcHQpKSB7XG4gICAgICByZXRbb3B0XSA9IGRlZmF1bHRPcHRpb25zW29wdF0uZGVmYXVsdFZhbHVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBhbGxPcHRpb25zT24gKCkge1xuICAndXNlIHN0cmljdCc7XG4gIHZhciBvcHRpb25zID0gZ2V0RGVmYXVsdE9wdHModHJ1ZSksXG4gICAgICByZXQgPSB7fTtcbiAgZm9yICh2YXIgb3B0IGluIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShvcHQpKSB7XG4gICAgICByZXRbb3B0XSA9IHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXQ7XG59XG5cclxuLyoqXG4gKiBDcmVhdGVkIGJ5IFRpdmllIG9uIDA2LTAxLTIwMTUuXG4gKi9cblxuLy8gUHJpdmF0ZSBwcm9wZXJ0aWVzXG52YXIgc2hvd2Rvd24gPSB7fSxcbiAgICBwYXJzZXJzID0ge30sXG4gICAgZXh0ZW5zaW9ucyA9IHt9LFxuICAgIGdsb2JhbE9wdGlvbnMgPSBnZXREZWZhdWx0T3B0cyh0cnVlKSxcbiAgICBzZXRGbGF2b3IgPSAndmFuaWxsYScsXG4gICAgZmxhdm9yID0ge1xuICAgICAgZ2l0aHViOiB7XG4gICAgICAgIG9taXRFeHRyYVdMSW5Db2RlQmxvY2tzOiAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc2ltcGxpZmllZEF1dG9MaW5rOiAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBleGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzOiAgIHRydWUsXG4gICAgICAgIGxpdGVyYWxNaWRXb3JkVW5kZXJzY29yZXM6ICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc3RyaWtldGhyb3VnaDogICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YWJsZXM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhYmxlc0hlYWRlcklkOiAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZ2hDb2RlQmxvY2tzOiAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YXNrbGlzdHM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGRpc2FibGVGb3JjZWQ0U3BhY2VzSW5kZW50ZWRTdWJsaXN0czogdHJ1ZSxcbiAgICAgICAgc2ltcGxlTGluZUJyZWFrczogICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICByZXF1aXJlU3BhY2VCZWZvcmVIZWFkaW5nVGV4dDogICAgICAgIHRydWUsXG4gICAgICAgIGdoQ29tcGF0aWJsZUhlYWRlcklkOiAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZ2hNZW50aW9uczogICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBiYWNrc2xhc2hFc2NhcGVzSFRNTFRhZ3M6ICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGVtb2ppOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc3BsaXRBZGphY2VudEJsb2NrcXVvdGVzOiAgICAgICAgICAgICB0cnVlXG4gICAgICB9LFxuICAgICAgb3JpZ2luYWw6IHtcbiAgICAgICAgbm9IZWFkZXJJZDogICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBnaENvZGVCbG9ja3M6ICAgICAgICAgICAgICAgICAgICAgICAgIGZhbHNlXG4gICAgICB9LFxuICAgICAgZ2hvc3Q6IHtcbiAgICAgICAgb21pdEV4dHJhV0xJbkNvZGVCbG9ja3M6ICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBwYXJzZUltZ0RpbWVuc2lvbnM6ICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHNpbXBsaWZpZWRBdXRvTGluazogICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZXhjbHVkZVRyYWlsaW5nUHVuY3R1YXRpb25Gcm9tVVJMczogICB0cnVlLFxuICAgICAgICBsaXRlcmFsTWlkV29yZFVuZGVyc2NvcmVzOiAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHN0cmlrZXRocm91Z2g6ICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgdGFibGVzOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YWJsZXNIZWFkZXJJZDogICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGdoQ29kZUJsb2NrczogICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgdGFza2xpc3RzOiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBzbW9vdGhMaXZlUHJldmlldzogICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHNpbXBsZUxpbmVCcmVha3M6ICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgcmVxdWlyZVNwYWNlQmVmb3JlSGVhZGluZ1RleHQ6ICAgICAgICB0cnVlLFxuICAgICAgICBnaE1lbnRpb25zOiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICBlbmNvZGVFbWFpbHM6ICAgICAgICAgICAgICAgICAgICAgICAgIHRydWVcbiAgICAgIH0sXG4gICAgICB2YW5pbGxhOiBnZXREZWZhdWx0T3B0cyh0cnVlKSxcbiAgICAgIGFsbE9uOiBhbGxPcHRpb25zT24oKVxuICAgIH07XG5cbi8qKlxuICogaGVscGVyIG5hbWVzcGFjZVxuICogQHR5cGUge3t9fVxuICovXG5zaG93ZG93bi5oZWxwZXIgPSB7fTtcblxuLyoqXG4gKiBUT0RPIExFR0FDWSBTVVBQT1JUIENPREVcbiAqIEB0eXBlIHt7fX1cbiAqL1xuc2hvd2Rvd24uZXh0ZW5zaW9ucyA9IHt9O1xuXG4vKipcbiAqIFNldCBhIGdsb2JhbCBvcHRpb25cbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAqIEByZXR1cm5zIHtzaG93ZG93bn1cbiAqL1xuc2hvd2Rvd24uc2V0T3B0aW9uID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBnbG9iYWxPcHRpb25zW2tleV0gPSB2YWx1ZTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIEdldCBhIGdsb2JhbCBvcHRpb25cbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAqIEByZXR1cm5zIHsqfVxuICovXG5zaG93ZG93bi5nZXRPcHRpb24gPSBmdW5jdGlvbiAoa2V5KSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIGdsb2JhbE9wdGlvbnNba2V5XTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBnbG9iYWwgb3B0aW9uc1xuICogQHN0YXRpY1xuICogQHJldHVybnMge3t9fVxuICovXG5zaG93ZG93bi5nZXRPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBnbG9iYWxPcHRpb25zO1xufTtcblxuLyoqXG4gKiBSZXNldCBnbG9iYWwgb3B0aW9ucyB0byB0aGUgZGVmYXVsdCB2YWx1ZXNcbiAqIEBzdGF0aWNcbiAqL1xuc2hvd2Rvd24ucmVzZXRPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAndXNlIHN0cmljdCc7XG4gIGdsb2JhbE9wdGlvbnMgPSBnZXREZWZhdWx0T3B0cyh0cnVlKTtcbn07XG5cbi8qKlxuICogU2V0IHRoZSBmbGF2b3Igc2hvd2Rvd24gc2hvdWxkIHVzZSBhcyBkZWZhdWx0XG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICovXG5zaG93ZG93bi5zZXRGbGF2b3IgPSBmdW5jdGlvbiAobmFtZSkge1xuICAndXNlIHN0cmljdCc7XG4gIGlmICghZmxhdm9yLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgdGhyb3cgRXJyb3IobmFtZSArICcgZmxhdm9yIHdhcyBub3QgZm91bmQnKTtcbiAgfVxuICBzaG93ZG93bi5yZXNldE9wdGlvbnMoKTtcbiAgdmFyIHByZXNldCA9IGZsYXZvcltuYW1lXTtcbiAgc2V0Rmxhdm9yID0gbmFtZTtcbiAgZm9yICh2YXIgb3B0aW9uIGluIHByZXNldCkge1xuICAgIGlmIChwcmVzZXQuaGFzT3duUHJvcGVydHkob3B0aW9uKSkge1xuICAgICAgZ2xvYmFsT3B0aW9uc1tvcHRpb25dID0gcHJlc2V0W29wdGlvbl07XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEdldCB0aGUgY3VycmVudGx5IHNldCBmbGF2b3JcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbnNob3dkb3duLmdldEZsYXZvciA9IGZ1bmN0aW9uICgpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gc2V0Rmxhdm9yO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIG9wdGlvbnMgb2YgYSBzcGVjaWZpZWQgZmxhdm9yLiBSZXR1cm5zIHVuZGVmaW5lZCBpZiB0aGUgZmxhdm9yIHdhcyBub3QgZm91bmRcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIGZsYXZvclxuICogQHJldHVybnMge3t9fHVuZGVmaW5lZH1cbiAqL1xuc2hvd2Rvd24uZ2V0Rmxhdm9yT3B0aW9ucyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgaWYgKGZsYXZvci5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgIHJldHVybiBmbGF2b3JbbmFtZV07XG4gIH1cbn07XG5cbi8qKlxuICogR2V0IHRoZSBkZWZhdWx0IG9wdGlvbnNcbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW3NpbXBsZT10cnVlXVxuICogQHJldHVybnMge3t9fVxuICovXG5zaG93ZG93bi5nZXREZWZhdWx0T3B0aW9ucyA9IGZ1bmN0aW9uIChzaW1wbGUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gZ2V0RGVmYXVsdE9wdHMoc2ltcGxlKTtcbn07XG5cbi8qKlxuICogR2V0IG9yIHNldCBhIHN1YlBhcnNlclxuICpcbiAqIHN1YlBhcnNlcihuYW1lKSAgICAgICAtIEdldCBhIHJlZ2lzdGVyZWQgc3ViUGFyc2VyXG4gKiBzdWJQYXJzZXIobmFtZSwgZnVuYykgLSBSZWdpc3RlciBhIHN1YlBhcnNlclxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IFtmdW5jXVxuICogQHJldHVybnMgeyp9XG4gKi9cbnNob3dkb3duLnN1YlBhcnNlciA9IGZ1bmN0aW9uIChuYW1lLCBmdW5jKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgaWYgKHNob3dkb3duLmhlbHBlci5pc1N0cmluZyhuYW1lKSkge1xuICAgIGlmICh0eXBlb2YgZnVuYyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHBhcnNlcnNbbmFtZV0gPSBmdW5jO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocGFyc2Vycy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICByZXR1cm4gcGFyc2Vyc1tuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IEVycm9yKCdTdWJQYXJzZXIgbmFtZWQgJyArIG5hbWUgKyAnIG5vdCByZWdpc3RlcmVkIScpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBHZXRzIG9yIHJlZ2lzdGVycyBhbiBleHRlbnNpb25cbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0ge29iamVjdHxmdW5jdGlvbj19IGV4dFxuICogQHJldHVybnMgeyp9XG4gKi9cbnNob3dkb3duLmV4dGVuc2lvbiA9IGZ1bmN0aW9uIChuYW1lLCBleHQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG5hbWUpKSB7XG4gICAgdGhyb3cgRXJyb3IoJ0V4dGVuc2lvbiBcXCduYW1lXFwnIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgfVxuXG4gIG5hbWUgPSBzaG93ZG93bi5oZWxwZXIuc3RkRXh0TmFtZShuYW1lKTtcblxuICAvLyBHZXR0ZXJcbiAgaWYgKHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChleHQpKSB7XG4gICAgaWYgKCFleHRlbnNpb25zLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICB0aHJvdyBFcnJvcignRXh0ZW5zaW9uIG5hbWVkICcgKyBuYW1lICsgJyBpcyBub3QgcmVnaXN0ZXJlZCEnKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4dGVuc2lvbnNbbmFtZV07XG5cbiAgICAvLyBTZXR0ZXJcbiAgfSBlbHNlIHtcbiAgICAvLyBFeHBhbmQgZXh0ZW5zaW9uIGlmIGl0J3Mgd3JhcHBlZCBpbiBhIGZ1bmN0aW9uXG4gICAgaWYgKHR5cGVvZiBleHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGV4dCA9IGV4dCgpO1xuICAgIH1cblxuICAgIC8vIEVuc3VyZSBleHRlbnNpb24gaXMgYW4gYXJyYXlcbiAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0FycmF5KGV4dCkpIHtcbiAgICAgIGV4dCA9IFtleHRdO1xuICAgIH1cblxuICAgIHZhciB2YWxpZEV4dGVuc2lvbiA9IHZhbGlkYXRlKGV4dCwgbmFtZSk7XG5cbiAgICBpZiAodmFsaWRFeHRlbnNpb24udmFsaWQpIHtcbiAgICAgIGV4dGVuc2lvbnNbbmFtZV0gPSBleHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IEVycm9yKHZhbGlkRXh0ZW5zaW9uLmVycm9yKTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogR2V0cyBhbGwgZXh0ZW5zaW9ucyByZWdpc3RlcmVkXG4gKiBAcmV0dXJucyB7e319XG4gKi9cbnNob3dkb3duLmdldEFsbEV4dGVuc2lvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIGV4dGVuc2lvbnM7XG59O1xuXG4vKipcbiAqIFJlbW92ZSBhbiBleHRlbnNpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKi9cbnNob3dkb3duLnJlbW92ZUV4dGVuc2lvbiA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgZGVsZXRlIGV4dGVuc2lvbnNbbmFtZV07XG59O1xuXG4vKipcbiAqIFJlbW92ZXMgYWxsIGV4dGVuc2lvbnNcbiAqL1xuc2hvd2Rvd24ucmVzZXRFeHRlbnNpb25zID0gZnVuY3Rpb24gKCkge1xuICAndXNlIHN0cmljdCc7XG4gIGV4dGVuc2lvbnMgPSB7fTtcbn07XG5cbi8qKlxuICogVmFsaWRhdGUgZXh0ZW5zaW9uXG4gKiBAcGFyYW0ge2FycmF5fSBleHRlbnNpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcmV0dXJucyB7e3ZhbGlkOiBib29sZWFuLCBlcnJvcjogc3RyaW5nfX1cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGUgKGV4dGVuc2lvbiwgbmFtZSkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIGVyck1zZyA9IChuYW1lKSA/ICdFcnJvciBpbiAnICsgbmFtZSArICcgZXh0ZW5zaW9uLT4nIDogJ0Vycm9yIGluIHVubmFtZWQgZXh0ZW5zaW9uJyxcbiAgICAgIHJldCA9IHtcbiAgICAgICAgdmFsaWQ6IHRydWUsXG4gICAgICAgIGVycm9yOiAnJ1xuICAgICAgfTtcblxuICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0FycmF5KGV4dGVuc2lvbikpIHtcbiAgICBleHRlbnNpb24gPSBbZXh0ZW5zaW9uXTtcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZXh0ZW5zaW9uLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGJhc2VNc2cgPSBlcnJNc2cgKyAnIHN1Yi1leHRlbnNpb24gJyArIGkgKyAnOiAnLFxuICAgICAgICBleHQgPSBleHRlbnNpb25baV07XG4gICAgaWYgKHR5cGVvZiBleHQgIT09ICdvYmplY3QnKSB7XG4gICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyAnbXVzdCBiZSBhbiBvYmplY3QsIGJ1dCAnICsgdHlwZW9mIGV4dCArICcgZ2l2ZW4nO1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG5cbiAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1N0cmluZyhleHQudHlwZSkpIHtcbiAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdwcm9wZXJ0eSBcInR5cGVcIiBtdXN0IGJlIGEgc3RyaW5nLCBidXQgJyArIHR5cGVvZiBleHQudHlwZSArICcgZ2l2ZW4nO1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG5cbiAgICB2YXIgdHlwZSA9IGV4dC50eXBlID0gZXh0LnR5cGUudG9Mb3dlckNhc2UoKTtcblxuICAgIC8vIG5vcm1hbGl6ZSBleHRlbnNpb24gdHlwZVxuICAgIGlmICh0eXBlID09PSAnbGFuZ3VhZ2UnKSB7XG4gICAgICB0eXBlID0gZXh0LnR5cGUgPSAnbGFuZyc7XG4gICAgfVxuXG4gICAgaWYgKHR5cGUgPT09ICdodG1sJykge1xuICAgICAgdHlwZSA9IGV4dC50eXBlID0gJ291dHB1dCc7XG4gICAgfVxuXG4gICAgaWYgKHR5cGUgIT09ICdsYW5nJyAmJiB0eXBlICE9PSAnb3V0cHV0JyAmJiB0eXBlICE9PSAnbGlzdGVuZXInKSB7XG4gICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyAndHlwZSAnICsgdHlwZSArICcgaXMgbm90IHJlY29nbml6ZWQuIFZhbGlkIHZhbHVlczogXCJsYW5nL2xhbmd1YWdlXCIsIFwib3V0cHV0L2h0bWxcIiBvciBcImxpc3RlbmVyXCInO1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gJ2xpc3RlbmVyJykge1xuICAgICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChleHQubGlzdGVuZXJzKSkge1xuICAgICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICcuIEV4dGVuc2lvbnMgb2YgdHlwZSBcImxpc3RlbmVyXCIgbXVzdCBoYXZlIGEgcHJvcGVydHkgY2FsbGVkIFwibGlzdGVuZXJzXCInO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dC5maWx0ZXIpICYmIHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChleHQucmVnZXgpKSB7XG4gICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgdHlwZSArICcgZXh0ZW5zaW9ucyBtdXN0IGRlZmluZSBlaXRoZXIgYSBcInJlZ2V4XCIgcHJvcGVydHkgb3IgYSBcImZpbHRlclwiIG1ldGhvZCc7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGV4dC5saXN0ZW5lcnMpIHtcbiAgICAgIGlmICh0eXBlb2YgZXh0Lmxpc3RlbmVycyAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyAnXCJsaXN0ZW5lcnNcIiBwcm9wZXJ0eSBtdXN0IGJlIGFuIG9iamVjdCBidXQgJyArIHR5cGVvZiBleHQubGlzdGVuZXJzICsgJyBnaXZlbic7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBsbiBpbiBleHQubGlzdGVuZXJzKSB7XG4gICAgICAgIGlmIChleHQubGlzdGVuZXJzLmhhc093blByb3BlcnR5KGxuKSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZXh0Lmxpc3RlbmVyc1tsbl0gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdcImxpc3RlbmVyc1wiIHByb3BlcnR5IG11c3QgYmUgYW4gaGFzaCBvZiBbZXZlbnQgbmFtZV06IFtjYWxsYmFja10uIGxpc3RlbmVycy4nICsgbG4gK1xuICAgICAgICAgICAgICAnIG11c3QgYmUgYSBmdW5jdGlvbiBidXQgJyArIHR5cGVvZiBleHQubGlzdGVuZXJzW2xuXSArICcgZ2l2ZW4nO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZXh0LmZpbHRlcikge1xuICAgICAgaWYgKHR5cGVvZiBleHQuZmlsdGVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ1wiZmlsdGVyXCIgbXVzdCBiZSBhIGZ1bmN0aW9uLCBidXQgJyArIHR5cGVvZiBleHQuZmlsdGVyICsgJyBnaXZlbic7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChleHQucmVnZXgpIHtcbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcoZXh0LnJlZ2V4KSkge1xuICAgICAgICBleHQucmVnZXggPSBuZXcgUmVnRXhwKGV4dC5yZWdleCwgJ2cnKTtcbiAgICAgIH1cbiAgICAgIGlmICghKGV4dC5yZWdleCBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyAnXCJyZWdleFwiIHByb3BlcnR5IG11c3QgZWl0aGVyIGJlIGEgc3RyaW5nIG9yIGEgUmVnRXhwIG9iamVjdCwgYnV0ICcgKyB0eXBlb2YgZXh0LnJlZ2V4ICsgJyBnaXZlbic7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG4gICAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dC5yZXBsYWNlKSkge1xuICAgICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdcInJlZ2V4XCIgZXh0ZW5zaW9ucyBtdXN0IGltcGxlbWVudCBhIHJlcGxhY2Ugc3RyaW5nIG9yIGZ1bmN0aW9uJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSBleHRlbnNpb25cbiAqIEBwYXJhbSB7b2JqZWN0fSBleHRcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5zaG93ZG93bi52YWxpZGF0ZUV4dGVuc2lvbiA9IGZ1bmN0aW9uIChleHQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB2YWxpZGF0ZUV4dGVuc2lvbiA9IHZhbGlkYXRlKGV4dCwgbnVsbCk7XG4gIGlmICghdmFsaWRhdGVFeHRlbnNpb24udmFsaWQpIHtcbiAgICBjb25zb2xlLndhcm4odmFsaWRhdGVFeHRlbnNpb24uZXJyb3IpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn07XG5cclxuLyoqXG4gKiBzaG93ZG93bmpzIGhlbHBlciBmdW5jdGlvbnNcbiAqL1xuXG5pZiAoIXNob3dkb3duLmhhc093blByb3BlcnR5KCdoZWxwZXInKSkge1xuICBzaG93ZG93bi5oZWxwZXIgPSB7fTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiB2YXIgaXMgc3RyaW5nXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0ge3N0cmluZ30gYVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnNob3dkb3duLmhlbHBlci5pc1N0cmluZyA9IGZ1bmN0aW9uIChhKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuICh0eXBlb2YgYSA9PT0gJ3N0cmluZycgfHwgYSBpbnN0YW5jZW9mIFN0cmluZyk7XG59O1xuXG4vKipcbiAqIENoZWNrIGlmIHZhciBpcyBhIGZ1bmN0aW9uXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0geyp9IGFcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5zaG93ZG93bi5oZWxwZXIuaXNGdW5jdGlvbiA9IGZ1bmN0aW9uIChhKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIGdldFR5cGUgPSB7fTtcbiAgcmV0dXJuIGEgJiYgZ2V0VHlwZS50b1N0cmluZy5jYWxsKGEpID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufTtcblxuLyoqXG4gKiBpc0FycmF5IGhlbHBlciBmdW5jdGlvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHsqfSBhXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkgPSBmdW5jdGlvbiAoYSkge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGEpO1xufTtcblxuLyoqXG4gKiBDaGVjayBpZiB2YWx1ZSBpcyB1bmRlZmluZWRcbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAsIGVsc2UgYGZhbHNlYC5cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59O1xuXG4vKipcbiAqIEZvckVhY2ggaGVscGVyIGZ1bmN0aW9uXG4gKiBJdGVyYXRlcyBvdmVyIEFycmF5cyBhbmQgT2JqZWN0cyAob3duIHByb3BlcnRpZXMgb25seSlcbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7Kn0gb2JqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayBBY2NlcHRzIDMgcGFyYW1zOiAxLiB2YWx1ZSwgMi4ga2V5LCAzLiB0aGUgb3JpZ2luYWwgYXJyYXkvb2JqZWN0XG4gKi9cbnNob3dkb3duLmhlbHBlci5mb3JFYWNoID0gZnVuY3Rpb24gKG9iaiwgY2FsbGJhY2spIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICAvLyBjaGVjayBpZiBvYmogaXMgZGVmaW5lZFxuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKG9iaikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ29iaiBwYXJhbSBpcyByZXF1aXJlZCcpO1xuICB9XG5cbiAgaWYgKHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChjYWxsYmFjaykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NhbGxiYWNrIHBhcmFtIGlzIHJlcXVpcmVkJyk7XG4gIH1cblxuICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2FsbGJhY2sgcGFyYW0gbXVzdCBiZSBhIGZ1bmN0aW9uL2Nsb3N1cmUnKTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb2JqLmZvckVhY2ggPT09ICdmdW5jdGlvbicpIHtcbiAgICBvYmouZm9yRWFjaChjYWxsYmFjayk7XG4gIH0gZWxzZSBpZiAoc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkob2JqKSkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjYWxsYmFjayhvYmpbaV0sIGksIG9iaik7XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGVvZiAob2JqKSA9PT0gJ29iamVjdCcpIHtcbiAgICBmb3IgKHZhciBwcm9wIGluIG9iaikge1xuICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShwcm9wKSkge1xuICAgICAgICBjYWxsYmFjayhvYmpbcHJvcF0sIHByb3AsIG9iaik7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignb2JqIGRvZXMgbm90IHNlZW0gdG8gYmUgYW4gYXJyYXkgb3IgYW4gaXRlcmFibGUgb2JqZWN0Jyk7XG4gIH1cbn07XG5cbi8qKlxuICogU3RhbmRhcmRpZGl6ZSBleHRlbnNpb24gbmFtZVxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IHMgZXh0ZW5zaW9uIG5hbWVcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbnNob3dkb3duLmhlbHBlci5zdGRFeHROYW1lID0gZnVuY3Rpb24gKHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gcy5yZXBsYWNlKC9bXz8qK1xcL1xcXFwuXi1dL2csICcnKS5yZXBsYWNlKC9cXHMvZywgJycpLnRvTG93ZXJDYXNlKCk7XG59O1xuXG5mdW5jdGlvbiBlc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2sgKHdob2xlTWF0Y2gsIG0xKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIGNoYXJDb2RlVG9Fc2NhcGUgPSBtMS5jaGFyQ29kZUF0KDApO1xuICByZXR1cm4gJ8KoRScgKyBjaGFyQ29kZVRvRXNjYXBlICsgJ0UnO1xufVxuXG4vKipcbiAqIENhbGxiYWNrIHVzZWQgdG8gZXNjYXBlIGNoYXJhY3RlcnMgd2hlbiBwYXNzaW5nIHRocm91Z2ggU3RyaW5nLnJlcGxhY2VcbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7c3RyaW5nfSB3aG9sZU1hdGNoXG4gKiBAcGFyYW0ge3N0cmluZ30gbTFcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbnNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2sgPSBlc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2s7XG5cbi8qKlxuICogRXNjYXBlIGNoYXJhY3RlcnMgaW4gYSBzdHJpbmdcbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gKiBAcGFyYW0ge3N0cmluZ30gY2hhcnNUb0VzY2FwZVxuICogQHBhcmFtIHtib29sZWFufSBhZnRlckJhY2tzbGFzaFxuICogQHJldHVybnMge1hNTHxzdHJpbmd8dm9pZHwqfVxuICovXG5zaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyA9IGZ1bmN0aW9uICh0ZXh0LCBjaGFyc1RvRXNjYXBlLCBhZnRlckJhY2tzbGFzaCkge1xuICAndXNlIHN0cmljdCc7XG4gIC8vIEZpcnN0IHdlIGhhdmUgdG8gZXNjYXBlIHRoZSBlc2NhcGUgY2hhcmFjdGVycyBzbyB0aGF0XG4gIC8vIHdlIGNhbiBidWlsZCBhIGNoYXJhY3RlciBjbGFzcyBvdXQgb2YgdGhlbVxuICB2YXIgcmVnZXhTdHJpbmcgPSAnKFsnICsgY2hhcnNUb0VzY2FwZS5yZXBsYWNlKC8oW1xcW1xcXVxcXFxdKS9nLCAnXFxcXCQxJykgKyAnXSknO1xuXG4gIGlmIChhZnRlckJhY2tzbGFzaCkge1xuICAgIHJlZ2V4U3RyaW5nID0gJ1xcXFxcXFxcJyArIHJlZ2V4U3RyaW5nO1xuICB9XG5cbiAgdmFyIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleFN0cmluZywgJ2cnKTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZShyZWdleCwgZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICByZXR1cm4gdGV4dDtcbn07XG5cbi8qKlxuICogVW5lc2NhcGUgSFRNTCBlbnRpdGllc1xuICogQHBhcmFtIHR4dFxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLnVuZXNjYXBlSFRNTEVudGl0aWVzID0gZnVuY3Rpb24gKHR4dCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgcmV0dXJuIHR4dFxuICAgIC5yZXBsYWNlKC8mcXVvdDsvZywgJ1wiJylcbiAgICAucmVwbGFjZSgvJmx0Oy9nLCAnPCcpXG4gICAgLnJlcGxhY2UoLyZndDsvZywgJz4nKVxuICAgIC5yZXBsYWNlKC8mYW1wOy9nLCAnJicpO1xufTtcblxudmFyIHJneEZpbmRNYXRjaFBvcyA9IGZ1bmN0aW9uIChzdHIsIGxlZnQsIHJpZ2h0LCBmbGFncykge1xuICAndXNlIHN0cmljdCc7XG4gIHZhciBmID0gZmxhZ3MgfHwgJycsXG4gICAgICBnID0gZi5pbmRleE9mKCdnJykgPiAtMSxcbiAgICAgIHggPSBuZXcgUmVnRXhwKGxlZnQgKyAnfCcgKyByaWdodCwgJ2cnICsgZi5yZXBsYWNlKC9nL2csICcnKSksXG4gICAgICBsID0gbmV3IFJlZ0V4cChsZWZ0LCBmLnJlcGxhY2UoL2cvZywgJycpKSxcbiAgICAgIHBvcyA9IFtdLFxuICAgICAgdCwgcywgbSwgc3RhcnQsIGVuZDtcblxuICBkbyB7XG4gICAgdCA9IDA7XG4gICAgd2hpbGUgKChtID0geC5leGVjKHN0cikpKSB7XG4gICAgICBpZiAobC50ZXN0KG1bMF0pKSB7XG4gICAgICAgIGlmICghKHQrKykpIHtcbiAgICAgICAgICBzID0geC5sYXN0SW5kZXg7XG4gICAgICAgICAgc3RhcnQgPSBzIC0gbVswXS5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodCkge1xuICAgICAgICBpZiAoIS0tdCkge1xuICAgICAgICAgIGVuZCA9IG0uaW5kZXggKyBtWzBdLmxlbmd0aDtcbiAgICAgICAgICB2YXIgb2JqID0ge1xuICAgICAgICAgICAgbGVmdDoge3N0YXJ0OiBzdGFydCwgZW5kOiBzfSxcbiAgICAgICAgICAgIG1hdGNoOiB7c3RhcnQ6IHMsIGVuZDogbS5pbmRleH0sXG4gICAgICAgICAgICByaWdodDoge3N0YXJ0OiBtLmluZGV4LCBlbmQ6IGVuZH0sXG4gICAgICAgICAgICB3aG9sZU1hdGNoOiB7c3RhcnQ6IHN0YXJ0LCBlbmQ6IGVuZH1cbiAgICAgICAgICB9O1xuICAgICAgICAgIHBvcy5wdXNoKG9iaik7XG4gICAgICAgICAgaWYgKCFnKSB7XG4gICAgICAgICAgICByZXR1cm4gcG9zO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSB3aGlsZSAodCAmJiAoeC5sYXN0SW5kZXggPSBzKSk7XG5cbiAgcmV0dXJuIHBvcztcbn07XG5cbi8qKlxuICogbWF0Y2hSZWN1cnNpdmVSZWdFeHBcbiAqXG4gKiAoYykgMjAwNyBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAqIE1JVCBMaWNlbnNlXG4gKlxuICogQWNjZXB0cyBhIHN0cmluZyB0byBzZWFyY2gsIGEgbGVmdCBhbmQgcmlnaHQgZm9ybWF0IGRlbGltaXRlclxuICogYXMgcmVnZXggcGF0dGVybnMsIGFuZCBvcHRpb25hbCByZWdleCBmbGFncy4gUmV0dXJucyBhbiBhcnJheVxuICogb2YgbWF0Y2hlcywgYWxsb3dpbmcgbmVzdGVkIGluc3RhbmNlcyBvZiBsZWZ0L3JpZ2h0IGRlbGltaXRlcnMuXG4gKiBVc2UgdGhlIFwiZ1wiIGZsYWcgdG8gcmV0dXJuIGFsbCBtYXRjaGVzLCBvdGhlcndpc2Ugb25seSB0aGVcbiAqIGZpcnN0IGlzIHJldHVybmVkLiBCZSBjYXJlZnVsIHRvIGVuc3VyZSB0aGF0IHRoZSBsZWZ0IGFuZFxuICogcmlnaHQgZm9ybWF0IGRlbGltaXRlcnMgcHJvZHVjZSBtdXR1YWxseSBleGNsdXNpdmUgbWF0Y2hlcy5cbiAqIEJhY2tyZWZlcmVuY2VzIGFyZSBub3Qgc3VwcG9ydGVkIHdpdGhpbiB0aGUgcmlnaHQgZGVsaW1pdGVyXG4gKiBkdWUgdG8gaG93IGl0IGlzIGludGVybmFsbHkgY29tYmluZWQgd2l0aCB0aGUgbGVmdCBkZWxpbWl0ZXIuXG4gKiBXaGVuIG1hdGNoaW5nIHN0cmluZ3Mgd2hvc2UgZm9ybWF0IGRlbGltaXRlcnMgYXJlIHVuYmFsYW5jZWRcbiAqIHRvIHRoZSBsZWZ0IG9yIHJpZ2h0LCB0aGUgb3V0cHV0IGlzIGludGVudGlvbmFsbHkgYXMgYVxuICogY29udmVudGlvbmFsIHJlZ2V4IGxpYnJhcnkgd2l0aCByZWN1cnNpb24gc3VwcG9ydCB3b3VsZFxuICogcHJvZHVjZSwgZS5nLiBcIjw8eD5cIiBhbmQgXCI8eD4+XCIgYm90aCBwcm9kdWNlIFtcInhcIl0gd2hlbiB1c2luZ1xuICogXCI8XCIgYW5kIFwiPlwiIGFzIHRoZSBkZWxpbWl0ZXJzIChib3RoIHN0cmluZ3MgY29udGFpbiBhIHNpbmdsZSxcbiAqIGJhbGFuY2VkIGluc3RhbmNlIG9mIFwiPHg+XCIpLlxuICpcbiAqIGV4YW1wbGVzOlxuICogbWF0Y2hSZWN1cnNpdmVSZWdFeHAoXCJ0ZXN0XCIsIFwiXFxcXChcIiwgXCJcXFxcKVwiKVxuICogcmV0dXJuczogW11cbiAqIG1hdGNoUmVjdXJzaXZlUmVnRXhwKFwiPHQ8PGU+PjxzPj50PD5cIiwgXCI8XCIsIFwiPlwiLCBcImdcIilcbiAqIHJldHVybnM6IFtcInQ8PGU+PjxzPlwiLCBcIlwiXVxuICogbWF0Y2hSZWN1cnNpdmVSZWdFeHAoXCI8ZGl2IGlkPVxcXCJ4XFxcIj50ZXN0PC9kaXY+XCIsIFwiPGRpdlxcXFxiW14+XSo+XCIsIFwiPC9kaXY+XCIsIFwiZ2lcIilcbiAqIHJldHVybnM6IFtcInRlc3RcIl1cbiAqL1xuc2hvd2Rvd24uaGVscGVyLm1hdGNoUmVjdXJzaXZlUmVnRXhwID0gZnVuY3Rpb24gKHN0ciwgbGVmdCwgcmlnaHQsIGZsYWdzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgbWF0Y2hQb3MgPSByZ3hGaW5kTWF0Y2hQb3MgKHN0ciwgbGVmdCwgcmlnaHQsIGZsYWdzKSxcbiAgICAgIHJlc3VsdHMgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG1hdGNoUG9zLmxlbmd0aDsgKytpKSB7XG4gICAgcmVzdWx0cy5wdXNoKFtcbiAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS53aG9sZU1hdGNoLnN0YXJ0LCBtYXRjaFBvc1tpXS53aG9sZU1hdGNoLmVuZCksXG4gICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ubWF0Y2guc3RhcnQsIG1hdGNoUG9zW2ldLm1hdGNoLmVuZCksXG4gICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ubGVmdC5zdGFydCwgbWF0Y2hQb3NbaV0ubGVmdC5lbmQpLFxuICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLnJpZ2h0LnN0YXJ0LCBtYXRjaFBvc1tpXS5yaWdodC5lbmQpXG4gICAgXSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdHM7XG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gKiBAcGFyYW0ge3N0cmluZ3xmdW5jdGlvbn0gcmVwbGFjZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBsZWZ0XG4gKiBAcGFyYW0ge3N0cmluZ30gcmlnaHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBmbGFnc1xuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLnJlcGxhY2VSZWN1cnNpdmVSZWdFeHAgPSBmdW5jdGlvbiAoc3RyLCByZXBsYWNlbWVudCwgbGVmdCwgcmlnaHQsIGZsYWdzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0Z1bmN0aW9uKHJlcGxhY2VtZW50KSkge1xuICAgIHZhciByZXBTdHIgPSByZXBsYWNlbWVudDtcbiAgICByZXBsYWNlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiByZXBTdHI7XG4gICAgfTtcbiAgfVxuXG4gIHZhciBtYXRjaFBvcyA9IHJneEZpbmRNYXRjaFBvcyhzdHIsIGxlZnQsIHJpZ2h0LCBmbGFncyksXG4gICAgICBmaW5hbFN0ciA9IHN0cixcbiAgICAgIGxuZyA9IG1hdGNoUG9zLmxlbmd0aDtcblxuICBpZiAobG5nID4gMCkge1xuICAgIHZhciBiaXRzID0gW107XG4gICAgaWYgKG1hdGNoUG9zWzBdLndob2xlTWF0Y2guc3RhcnQgIT09IDApIHtcbiAgICAgIGJpdHMucHVzaChzdHIuc2xpY2UoMCwgbWF0Y2hQb3NbMF0ud2hvbGVNYXRjaC5zdGFydCkpO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxuZzsgKytpKSB7XG4gICAgICBiaXRzLnB1c2goXG4gICAgICAgIHJlcGxhY2VtZW50KFxuICAgICAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS53aG9sZU1hdGNoLnN0YXJ0LCBtYXRjaFBvc1tpXS53aG9sZU1hdGNoLmVuZCksXG4gICAgICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLm1hdGNoLnN0YXJ0LCBtYXRjaFBvc1tpXS5tYXRjaC5lbmQpLFxuICAgICAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS5sZWZ0LnN0YXJ0LCBtYXRjaFBvc1tpXS5sZWZ0LmVuZCksXG4gICAgICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLnJpZ2h0LnN0YXJ0LCBtYXRjaFBvc1tpXS5yaWdodC5lbmQpXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgICBpZiAoaSA8IGxuZyAtIDEpIHtcbiAgICAgICAgYml0cy5wdXNoKHN0ci5zbGljZShtYXRjaFBvc1tpXS53aG9sZU1hdGNoLmVuZCwgbWF0Y2hQb3NbaSArIDFdLndob2xlTWF0Y2guc3RhcnQpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG1hdGNoUG9zW2xuZyAtIDFdLndob2xlTWF0Y2guZW5kIDwgc3RyLmxlbmd0aCkge1xuICAgICAgYml0cy5wdXNoKHN0ci5zbGljZShtYXRjaFBvc1tsbmcgLSAxXS53aG9sZU1hdGNoLmVuZCkpO1xuICAgIH1cbiAgICBmaW5hbFN0ciA9IGJpdHMuam9pbignJyk7XG4gIH1cbiAgcmV0dXJuIGZpbmFsU3RyO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhlIHBhc3NlZCBTdHJpbmcgb2JqZWN0IG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIHRoZSBzcGVjaWZpZWQgcmVnZXgsXG4gKiBzdGFydGluZyB0aGUgc2VhcmNoIGF0IGZyb21JbmRleC4gUmV0dXJucyAtMSBpZiB0aGUgdmFsdWUgaXMgbm90IGZvdW5kLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgc3RyaW5nIHRvIHNlYXJjaFxuICogQHBhcmFtIHtSZWdFeHB9IHJlZ2V4IFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBzZWFyY2hcbiAqIEBwYXJhbSB7aW50fSBbZnJvbUluZGV4ID0gMF0gSW5kZXggdG8gc3RhcnQgdGhlIHNlYXJjaFxuICogQHJldHVybnMge051bWJlcn1cbiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXJyb3JcbiAqL1xuc2hvd2Rvd24uaGVscGVyLnJlZ2V4SW5kZXhPZiA9IGZ1bmN0aW9uIChzdHIsIHJlZ2V4LCBmcm9tSW5kZXgpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1N0cmluZyhzdHIpKSB7XG4gICAgdGhyb3cgJ0ludmFsaWRBcmd1bWVudEVycm9yOiBmaXJzdCBwYXJhbWV0ZXIgb2Ygc2hvd2Rvd24uaGVscGVyLnJlZ2V4SW5kZXhPZiBmdW5jdGlvbiBtdXN0IGJlIGEgc3RyaW5nJztcbiAgfVxuICBpZiAocmVnZXggaW5zdGFuY2VvZiBSZWdFeHAgPT09IGZhbHNlKSB7XG4gICAgdGhyb3cgJ0ludmFsaWRBcmd1bWVudEVycm9yOiBzZWNvbmQgcGFyYW1ldGVyIG9mIHNob3dkb3duLmhlbHBlci5yZWdleEluZGV4T2YgZnVuY3Rpb24gbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBSZWdFeHAnO1xuICB9XG4gIHZhciBpbmRleE9mID0gc3RyLnN1YnN0cmluZyhmcm9tSW5kZXggfHwgMCkuc2VhcmNoKHJlZ2V4KTtcbiAgcmV0dXJuIChpbmRleE9mID49IDApID8gKGluZGV4T2YgKyAoZnJvbUluZGV4IHx8IDApKSA6IGluZGV4T2Y7XG59O1xuXG4vKipcbiAqIFNwbGl0cyB0aGUgcGFzc2VkIHN0cmluZyBvYmplY3QgYXQgdGhlIGRlZmluZWQgaW5kZXgsIGFuZCByZXR1cm5zIGFuIGFycmF5IGNvbXBvc2VkIG9mIHRoZSB0d28gc3Vic3RyaW5nc1xuICogQHBhcmFtIHtzdHJpbmd9IHN0ciBzdHJpbmcgdG8gc3BsaXRcbiAqIEBwYXJhbSB7aW50fSBpbmRleCBpbmRleCB0byBzcGxpdCBzdHJpbmcgYXRcbiAqIEByZXR1cm5zIHtbc3RyaW5nLHN0cmluZ119XG4gKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEVycm9yXG4gKi9cbnNob3dkb3duLmhlbHBlci5zcGxpdEF0SW5kZXggPSBmdW5jdGlvbiAoc3RyLCBpbmRleCkge1xuICAndXNlIHN0cmljdCc7XG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKHN0cikpIHtcbiAgICB0aHJvdyAnSW52YWxpZEFyZ3VtZW50RXJyb3I6IGZpcnN0IHBhcmFtZXRlciBvZiBzaG93ZG93bi5oZWxwZXIucmVnZXhJbmRleE9mIGZ1bmN0aW9uIG11c3QgYmUgYSBzdHJpbmcnO1xuICB9XG4gIHJldHVybiBbc3RyLnN1YnN0cmluZygwLCBpbmRleCksIHN0ci5zdWJzdHJpbmcoaW5kZXgpXTtcbn07XG5cbi8qKlxuICogT2JmdXNjYXRlIGFuIGUtbWFpbCBhZGRyZXNzIHRocm91Z2ggdGhlIHVzZSBvZiBDaGFyYWN0ZXIgRW50aXRpZXMsXG4gKiB0cmFuc2Zvcm1pbmcgQVNDSUkgY2hhcmFjdGVycyBpbnRvIHRoZWlyIGVxdWl2YWxlbnQgZGVjaW1hbCBvciBoZXggZW50aXRpZXMuXG4gKlxuICogU2luY2UgaXQgaGFzIGEgcmFuZG9tIGNvbXBvbmVudCwgc3Vic2VxdWVudCBjYWxscyB0byB0aGlzIGZ1bmN0aW9uIHByb2R1Y2UgZGlmZmVyZW50IHJlc3VsdHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbWFpbFxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmVuY29kZUVtYWlsQWRkcmVzcyA9IGZ1bmN0aW9uIChtYWlsKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIGVuY29kZSA9IFtcbiAgICBmdW5jdGlvbiAoY2gpIHtcbiAgICAgIHJldHVybiAnJiMnICsgY2guY2hhckNvZGVBdCgwKSArICc7JztcbiAgICB9LFxuICAgIGZ1bmN0aW9uIChjaCkge1xuICAgICAgcmV0dXJuICcmI3gnICsgY2guY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikgKyAnOyc7XG4gICAgfSxcbiAgICBmdW5jdGlvbiAoY2gpIHtcbiAgICAgIHJldHVybiBjaDtcbiAgICB9XG4gIF07XG5cbiAgbWFpbCA9IG1haWwucmVwbGFjZSgvLi9nLCBmdW5jdGlvbiAoY2gpIHtcbiAgICBpZiAoY2ggPT09ICdAJykge1xuICAgICAgLy8gdGhpcyAqbXVzdCogYmUgZW5jb2RlZC4gSSBpbnNpc3QuXG4gICAgICBjaCA9IGVuY29kZVtNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAyKV0oY2gpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgciA9IE1hdGgucmFuZG9tKCk7XG4gICAgICAvLyByb3VnaGx5IDEwJSByYXcsIDQ1JSBoZXgsIDQ1JSBkZWNcbiAgICAgIGNoID0gKFxuICAgICAgICByID4gMC45ID8gZW5jb2RlWzJdKGNoKSA6IHIgPiAwLjQ1ID8gZW5jb2RlWzFdKGNoKSA6IGVuY29kZVswXShjaClcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjaDtcbiAgfSk7XG5cbiAgcmV0dXJuIG1haWw7XG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0gc3RyXG4gKiBAcGFyYW0gdGFyZ2V0TGVuZ3RoXG4gKiBAcGFyYW0gcGFkU3RyaW5nXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5zaG93ZG93bi5oZWxwZXIucGFkRW5kID0gZnVuY3Rpb24gcGFkRW5kIChzdHIsIHRhcmdldExlbmd0aCwgcGFkU3RyaW5nKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgLypqc2hpbnQgYml0d2lzZTogZmFsc2UqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc3BhY2UtaW5maXgtb3BzXG4gIHRhcmdldExlbmd0aCA9IHRhcmdldExlbmd0aD4+MDsgLy9mbG9vciBpZiBudW1iZXIgb3IgY29udmVydCBub24tbnVtYmVyIHRvIDA7XG4gIC8qanNoaW50IGJpdHdpc2U6IHRydWUqL1xuICBwYWRTdHJpbmcgPSBTdHJpbmcocGFkU3RyaW5nIHx8ICcgJyk7XG4gIGlmIChzdHIubGVuZ3RoID4gdGFyZ2V0TGVuZ3RoKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHIpO1xuICB9IGVsc2Uge1xuICAgIHRhcmdldExlbmd0aCA9IHRhcmdldExlbmd0aCAtIHN0ci5sZW5ndGg7XG4gICAgaWYgKHRhcmdldExlbmd0aCA+IHBhZFN0cmluZy5sZW5ndGgpIHtcbiAgICAgIHBhZFN0cmluZyArPSBwYWRTdHJpbmcucmVwZWF0KHRhcmdldExlbmd0aCAvIHBhZFN0cmluZy5sZW5ndGgpOyAvL2FwcGVuZCB0byBvcmlnaW5hbCB0byBlbnN1cmUgd2UgYXJlIGxvbmdlciB0aGFuIG5lZWRlZFxuICAgIH1cbiAgICByZXR1cm4gU3RyaW5nKHN0cikgKyBwYWRTdHJpbmcuc2xpY2UoMCx0YXJnZXRMZW5ndGgpO1xuICB9XG59O1xuXG4vKipcbiAqIFBPTFlGSUxMU1xuICovXG4vLyB1c2UgdGhpcyBpbnN0ZWFkIG9mIGJ1aWx0aW4gaXMgdW5kZWZpbmVkIGZvciBJRTggY29tcGF0aWJpbGl0eVxuaWYgKHR5cGVvZiBjb25zb2xlID09PSAndW5kZWZpbmVkJykge1xuICBjb25zb2xlID0ge1xuICAgIHdhcm46IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgIGFsZXJ0KG1zZyk7XG4gICAgfSxcbiAgICBsb2c6IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgIGFsZXJ0KG1zZyk7XG4gICAgfSxcbiAgICBlcnJvcjogZnVuY3Rpb24gKG1zZykge1xuICAgICAgJ3VzZSBzdHJpY3QnO1xuICAgICAgdGhyb3cgbXNnO1xuICAgIH1cbiAgfTtcbn1cblxuLyoqXG4gKiBDb21tb24gcmVnZXhlcy5cbiAqIFdlIGRlY2xhcmUgc29tZSBjb21tb24gcmVnZXhlcyB0byBpbXByb3ZlIHBlcmZvcm1hbmNlXG4gKi9cbnNob3dkb3duLmhlbHBlci5yZWdleGVzID0ge1xuICBhc3Rlcmlza0Rhc2hBbmRDb2xvbjogLyhbKl86fl0pL2dcbn07XG5cbi8qKlxuICogRU1PSklTIExJU1RcbiAqL1xuc2hvd2Rvd24uaGVscGVyLmVtb2ppcyA9IHtcbiAgJysxJzonXFx1ZDgzZFxcdWRjNGQnLFxuICAnLTEnOidcXHVkODNkXFx1ZGM0ZScsXG4gICcxMDAnOidcXHVkODNkXFx1ZGNhZicsXG4gICcxMjM0JzonXFx1ZDgzZFxcdWRkMjInLFxuICAnMXN0X3BsYWNlX21lZGFsJzonXFx1ZDgzZVxcdWRkNDcnLFxuICAnMm5kX3BsYWNlX21lZGFsJzonXFx1ZDgzZVxcdWRkNDgnLFxuICAnM3JkX3BsYWNlX21lZGFsJzonXFx1ZDgzZVxcdWRkNDknLFxuICAnOGJhbGwnOidcXHVkODNjXFx1ZGZiMScsXG4gICdhJzonXFx1ZDgzY1xcdWRkNzBcXHVmZTBmJyxcbiAgJ2FiJzonXFx1ZDgzY1xcdWRkOGUnLFxuICAnYWJjJzonXFx1ZDgzZFxcdWRkMjQnLFxuICAnYWJjZCc6J1xcdWQ4M2RcXHVkZDIxJyxcbiAgJ2FjY2VwdCc6J1xcdWQ4M2NcXHVkZTUxJyxcbiAgJ2FlcmlhbF90cmFtd2F5JzonXFx1ZDgzZFxcdWRlYTEnLFxuICAnYWlycGxhbmUnOidcXHUyNzA4XFx1ZmUwZicsXG4gICdhbGFybV9jbG9jayc6J1xcdTIzZjAnLFxuICAnYWxlbWJpYyc6J1xcdTI2OTdcXHVmZTBmJyxcbiAgJ2FsaWVuJzonXFx1ZDgzZFxcdWRjN2QnLFxuICAnYW1idWxhbmNlJzonXFx1ZDgzZFxcdWRlOTEnLFxuICAnYW1waG9yYSc6J1xcdWQ4M2NcXHVkZmZhJyxcbiAgJ2FuY2hvcic6J1xcdTI2OTNcXHVmZTBmJyxcbiAgJ2FuZ2VsJzonXFx1ZDgzZFxcdWRjN2MnLFxuICAnYW5nZXInOidcXHVkODNkXFx1ZGNhMicsXG4gICdhbmdyeSc6J1xcdWQ4M2RcXHVkZTIwJyxcbiAgJ2FuZ3Vpc2hlZCc6J1xcdWQ4M2RcXHVkZTI3JyxcbiAgJ2FudCc6J1xcdWQ4M2RcXHVkYzFjJyxcbiAgJ2FwcGxlJzonXFx1ZDgzY1xcdWRmNGUnLFxuICAnYXF1YXJpdXMnOidcXHUyNjUyXFx1ZmUwZicsXG4gICdhcmllcyc6J1xcdTI2NDhcXHVmZTBmJyxcbiAgJ2Fycm93X2JhY2t3YXJkJzonXFx1MjVjMFxcdWZlMGYnLFxuICAnYXJyb3dfZG91YmxlX2Rvd24nOidcXHUyM2VjJyxcbiAgJ2Fycm93X2RvdWJsZV91cCc6J1xcdTIzZWInLFxuICAnYXJyb3dfZG93bic6J1xcdTJiMDdcXHVmZTBmJyxcbiAgJ2Fycm93X2Rvd25fc21hbGwnOidcXHVkODNkXFx1ZGQzZCcsXG4gICdhcnJvd19mb3J3YXJkJzonXFx1MjViNlxcdWZlMGYnLFxuICAnYXJyb3dfaGVhZGluZ19kb3duJzonXFx1MjkzNVxcdWZlMGYnLFxuICAnYXJyb3dfaGVhZGluZ191cCc6J1xcdTI5MzRcXHVmZTBmJyxcbiAgJ2Fycm93X2xlZnQnOidcXHUyYjA1XFx1ZmUwZicsXG4gICdhcnJvd19sb3dlcl9sZWZ0JzonXFx1MjE5OVxcdWZlMGYnLFxuICAnYXJyb3dfbG93ZXJfcmlnaHQnOidcXHUyMTk4XFx1ZmUwZicsXG4gICdhcnJvd19yaWdodCc6J1xcdTI3YTFcXHVmZTBmJyxcbiAgJ2Fycm93X3JpZ2h0X2hvb2snOidcXHUyMWFhXFx1ZmUwZicsXG4gICdhcnJvd191cCc6J1xcdTJiMDZcXHVmZTBmJyxcbiAgJ2Fycm93X3VwX2Rvd24nOidcXHUyMTk1XFx1ZmUwZicsXG4gICdhcnJvd191cF9zbWFsbCc6J1xcdWQ4M2RcXHVkZDNjJyxcbiAgJ2Fycm93X3VwcGVyX2xlZnQnOidcXHUyMTk2XFx1ZmUwZicsXG4gICdhcnJvd191cHBlcl9yaWdodCc6J1xcdTIxOTdcXHVmZTBmJyxcbiAgJ2Fycm93c19jbG9ja3dpc2UnOidcXHVkODNkXFx1ZGQwMycsXG4gICdhcnJvd3NfY291bnRlcmNsb2Nrd2lzZSc6J1xcdWQ4M2RcXHVkZDA0JyxcbiAgJ2FydCc6J1xcdWQ4M2NcXHVkZmE4JyxcbiAgJ2FydGljdWxhdGVkX2xvcnJ5JzonXFx1ZDgzZFxcdWRlOWInLFxuICAnYXJ0aWZpY2lhbF9zYXRlbGxpdGUnOidcXHVkODNkXFx1ZGVmMCcsXG4gICdhc3RvbmlzaGVkJzonXFx1ZDgzZFxcdWRlMzInLFxuICAnYXRobGV0aWNfc2hvZSc6J1xcdWQ4M2RcXHVkYzVmJyxcbiAgJ2F0bSc6J1xcdWQ4M2NcXHVkZmU3JyxcbiAgJ2F0b21fc3ltYm9sJzonXFx1MjY5YlxcdWZlMGYnLFxuICAnYXZvY2Fkbyc6J1xcdWQ4M2VcXHVkZDUxJyxcbiAgJ2InOidcXHVkODNjXFx1ZGQ3MVxcdWZlMGYnLFxuICAnYmFieSc6J1xcdWQ4M2RcXHVkYzc2JyxcbiAgJ2JhYnlfYm90dGxlJzonXFx1ZDgzY1xcdWRmN2MnLFxuICAnYmFieV9jaGljayc6J1xcdWQ4M2RcXHVkYzI0JyxcbiAgJ2JhYnlfc3ltYm9sJzonXFx1ZDgzZFxcdWRlYmMnLFxuICAnYmFjayc6J1xcdWQ4M2RcXHVkZDE5JyxcbiAgJ2JhY29uJzonXFx1ZDgzZVxcdWRkNTMnLFxuICAnYmFkbWludG9uJzonXFx1ZDgzY1xcdWRmZjgnLFxuICAnYmFnZ2FnZV9jbGFpbSc6J1xcdWQ4M2RcXHVkZWM0JyxcbiAgJ2JhZ3VldHRlX2JyZWFkJzonXFx1ZDgzZVxcdWRkNTYnLFxuICAnYmFsYW5jZV9zY2FsZSc6J1xcdTI2OTZcXHVmZTBmJyxcbiAgJ2JhbGxvb24nOidcXHVkODNjXFx1ZGY4OCcsXG4gICdiYWxsb3RfYm94JzonXFx1ZDgzZFxcdWRkZjMnLFxuICAnYmFsbG90X2JveF93aXRoX2NoZWNrJzonXFx1MjYxMVxcdWZlMGYnLFxuICAnYmFtYm9vJzonXFx1ZDgzY1xcdWRmOGQnLFxuICAnYmFuYW5hJzonXFx1ZDgzY1xcdWRmNGMnLFxuICAnYmFuZ2JhbmcnOidcXHUyMDNjXFx1ZmUwZicsXG4gICdiYW5rJzonXFx1ZDgzY1xcdWRmZTYnLFxuICAnYmFyX2NoYXJ0JzonXFx1ZDgzZFxcdWRjY2EnLFxuICAnYmFyYmVyJzonXFx1ZDgzZFxcdWRjODgnLFxuICAnYmFzZWJhbGwnOidcXHUyNmJlXFx1ZmUwZicsXG4gICdiYXNrZXRiYWxsJzonXFx1ZDgzY1xcdWRmYzAnLFxuICAnYmFza2V0YmFsbF9tYW4nOidcXHUyNmY5XFx1ZmUwZicsXG4gICdiYXNrZXRiYWxsX3dvbWFuJzonXFx1MjZmOVxcdWZlMGYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2JhdCc6J1xcdWQ4M2VcXHVkZDg3JyxcbiAgJ2JhdGgnOidcXHVkODNkXFx1ZGVjMCcsXG4gICdiYXRodHViJzonXFx1ZDgzZFxcdWRlYzEnLFxuICAnYmF0dGVyeSc6J1xcdWQ4M2RcXHVkZDBiJyxcbiAgJ2JlYWNoX3VtYnJlbGxhJzonXFx1ZDgzY1xcdWRmZDYnLFxuICAnYmVhcic6J1xcdWQ4M2RcXHVkYzNiJyxcbiAgJ2JlZCc6J1xcdWQ4M2RcXHVkZWNmJyxcbiAgJ2JlZSc6J1xcdWQ4M2RcXHVkYzFkJyxcbiAgJ2JlZXInOidcXHVkODNjXFx1ZGY3YScsXG4gICdiZWVycyc6J1xcdWQ4M2NcXHVkZjdiJyxcbiAgJ2JlZXRsZSc6J1xcdWQ4M2RcXHVkYzFlJyxcbiAgJ2JlZ2lubmVyJzonXFx1ZDgzZFxcdWRkMzAnLFxuICAnYmVsbCc6J1xcdWQ4M2RcXHVkZDE0JyxcbiAgJ2JlbGxob3BfYmVsbCc6J1xcdWQ4M2RcXHVkZWNlJyxcbiAgJ2JlbnRvJzonXFx1ZDgzY1xcdWRmNzEnLFxuICAnYmlraW5nX21hbic6J1xcdWQ4M2RcXHVkZWI0JyxcbiAgJ2Jpa2UnOidcXHVkODNkXFx1ZGViMicsXG4gICdiaWtpbmdfd29tYW4nOidcXHVkODNkXFx1ZGViNCZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnYmlraW5pJzonXFx1ZDgzZFxcdWRjNTknLFxuICAnYmlvaGF6YXJkJzonXFx1MjYyM1xcdWZlMGYnLFxuICAnYmlyZCc6J1xcdWQ4M2RcXHVkYzI2JyxcbiAgJ2JpcnRoZGF5JzonXFx1ZDgzY1xcdWRmODInLFxuICAnYmxhY2tfY2lyY2xlJzonXFx1MjZhYlxcdWZlMGYnLFxuICAnYmxhY2tfZmxhZyc6J1xcdWQ4M2NcXHVkZmY0JyxcbiAgJ2JsYWNrX2hlYXJ0JzonXFx1ZDgzZFxcdWRkYTQnLFxuICAnYmxhY2tfam9rZXInOidcXHVkODNjXFx1ZGNjZicsXG4gICdibGFja19sYXJnZV9zcXVhcmUnOidcXHUyYjFiXFx1ZmUwZicsXG4gICdibGFja19tZWRpdW1fc21hbGxfc3F1YXJlJzonXFx1MjVmZVxcdWZlMGYnLFxuICAnYmxhY2tfbWVkaXVtX3NxdWFyZSc6J1xcdTI1ZmNcXHVmZTBmJyxcbiAgJ2JsYWNrX25pYic6J1xcdTI3MTJcXHVmZTBmJyxcbiAgJ2JsYWNrX3NtYWxsX3NxdWFyZSc6J1xcdTI1YWFcXHVmZTBmJyxcbiAgJ2JsYWNrX3NxdWFyZV9idXR0b24nOidcXHVkODNkXFx1ZGQzMicsXG4gICdibG9uZGVfbWFuJzonXFx1ZDgzZFxcdWRjNzEnLFxuICAnYmxvbmRlX3dvbWFuJzonXFx1ZDgzZFxcdWRjNzEmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2Jsb3Nzb20nOidcXHVkODNjXFx1ZGYzYycsXG4gICdibG93ZmlzaCc6J1xcdWQ4M2RcXHVkYzIxJyxcbiAgJ2JsdWVfYm9vayc6J1xcdWQ4M2RcXHVkY2Q4JyxcbiAgJ2JsdWVfY2FyJzonXFx1ZDgzZFxcdWRlOTknLFxuICAnYmx1ZV9oZWFydCc6J1xcdWQ4M2RcXHVkYzk5JyxcbiAgJ2JsdXNoJzonXFx1ZDgzZFxcdWRlMGEnLFxuICAnYm9hcic6J1xcdWQ4M2RcXHVkYzE3JyxcbiAgJ2JvYXQnOidcXHUyNmY1XFx1ZmUwZicsXG4gICdib21iJzonXFx1ZDgzZFxcdWRjYTMnLFxuICAnYm9vayc6J1xcdWQ4M2RcXHVkY2Q2JyxcbiAgJ2Jvb2ttYXJrJzonXFx1ZDgzZFxcdWRkMTYnLFxuICAnYm9va21hcmtfdGFicyc6J1xcdWQ4M2RcXHVkY2QxJyxcbiAgJ2Jvb2tzJzonXFx1ZDgzZFxcdWRjZGEnLFxuICAnYm9vbSc6J1xcdWQ4M2RcXHVkY2E1JyxcbiAgJ2Jvb3QnOidcXHVkODNkXFx1ZGM2MicsXG4gICdib3VxdWV0JzonXFx1ZDgzZFxcdWRjOTAnLFxuICAnYm93aW5nX21hbic6J1xcdWQ4M2RcXHVkZTQ3JyxcbiAgJ2Jvd19hbmRfYXJyb3cnOidcXHVkODNjXFx1ZGZmOScsXG4gICdib3dpbmdfd29tYW4nOidcXHVkODNkXFx1ZGU0NyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnYm93bGluZyc6J1xcdWQ4M2NcXHVkZmIzJyxcbiAgJ2JveGluZ19nbG92ZSc6J1xcdWQ4M2VcXHVkZDRhJyxcbiAgJ2JveSc6J1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2JyZWFkJzonXFx1ZDgzY1xcdWRmNWUnLFxuICAnYnJpZGVfd2l0aF92ZWlsJzonXFx1ZDgzZFxcdWRjNzAnLFxuICAnYnJpZGdlX2F0X25pZ2h0JzonXFx1ZDgzY1xcdWRmMDknLFxuICAnYnJpZWZjYXNlJzonXFx1ZDgzZFxcdWRjYmMnLFxuICAnYnJva2VuX2hlYXJ0JzonXFx1ZDgzZFxcdWRjOTQnLFxuICAnYnVnJzonXFx1ZDgzZFxcdWRjMWInLFxuICAnYnVpbGRpbmdfY29uc3RydWN0aW9uJzonXFx1ZDgzY1xcdWRmZDcnLFxuICAnYnVsYic6J1xcdWQ4M2RcXHVkY2ExJyxcbiAgJ2J1bGxldHRyYWluX2Zyb250JzonXFx1ZDgzZFxcdWRlODUnLFxuICAnYnVsbGV0dHJhaW5fc2lkZSc6J1xcdWQ4M2RcXHVkZTg0JyxcbiAgJ2J1cnJpdG8nOidcXHVkODNjXFx1ZGYyZicsXG4gICdidXMnOidcXHVkODNkXFx1ZGU4YycsXG4gICdidXNpbmVzc19zdWl0X2xldml0YXRpbmcnOidcXHVkODNkXFx1ZGQ3NCcsXG4gICdidXNzdG9wJzonXFx1ZDgzZFxcdWRlOGYnLFxuICAnYnVzdF9pbl9zaWxob3VldHRlJzonXFx1ZDgzZFxcdWRjNjQnLFxuICAnYnVzdHNfaW5fc2lsaG91ZXR0ZSc6J1xcdWQ4M2RcXHVkYzY1JyxcbiAgJ2J1dHRlcmZseSc6J1xcdWQ4M2VcXHVkZDhiJyxcbiAgJ2NhY3R1cyc6J1xcdWQ4M2NcXHVkZjM1JyxcbiAgJ2Nha2UnOidcXHVkODNjXFx1ZGY3MCcsXG4gICdjYWxlbmRhcic6J1xcdWQ4M2RcXHVkY2M2JyxcbiAgJ2NhbGxfbWVfaGFuZCc6J1xcdWQ4M2VcXHVkZDE5JyxcbiAgJ2NhbGxpbmcnOidcXHVkODNkXFx1ZGNmMicsXG4gICdjYW1lbCc6J1xcdWQ4M2RcXHVkYzJiJyxcbiAgJ2NhbWVyYSc6J1xcdWQ4M2RcXHVkY2Y3JyxcbiAgJ2NhbWVyYV9mbGFzaCc6J1xcdWQ4M2RcXHVkY2Y4JyxcbiAgJ2NhbXBpbmcnOidcXHVkODNjXFx1ZGZkNScsXG4gICdjYW5jZXInOidcXHUyNjRiXFx1ZmUwZicsXG4gICdjYW5kbGUnOidcXHVkODNkXFx1ZGQ2ZicsXG4gICdjYW5keSc6J1xcdWQ4M2NcXHVkZjZjJyxcbiAgJ2Nhbm9lJzonXFx1ZDgzZFxcdWRlZjYnLFxuICAnY2FwaXRhbF9hYmNkJzonXFx1ZDgzZFxcdWRkMjAnLFxuICAnY2Fwcmljb3JuJzonXFx1MjY1MVxcdWZlMGYnLFxuICAnY2FyJzonXFx1ZDgzZFxcdWRlOTcnLFxuICAnY2FyZF9maWxlX2JveCc6J1xcdWQ4M2RcXHVkZGMzJyxcbiAgJ2NhcmRfaW5kZXgnOidcXHVkODNkXFx1ZGNjNycsXG4gICdjYXJkX2luZGV4X2RpdmlkZXJzJzonXFx1ZDgzZFxcdWRkYzInLFxuICAnY2Fyb3VzZWxfaG9yc2UnOidcXHVkODNjXFx1ZGZhMCcsXG4gICdjYXJyb3QnOidcXHVkODNlXFx1ZGQ1NScsXG4gICdjYXQnOidcXHVkODNkXFx1ZGMzMScsXG4gICdjYXQyJzonXFx1ZDgzZFxcdWRjMDgnLFxuICAnY2QnOidcXHVkODNkXFx1ZGNiZicsXG4gICdjaGFpbnMnOidcXHUyNmQzJyxcbiAgJ2NoYW1wYWduZSc6J1xcdWQ4M2NcXHVkZjdlJyxcbiAgJ2NoYXJ0JzonXFx1ZDgzZFxcdWRjYjknLFxuICAnY2hhcnRfd2l0aF9kb3dud2FyZHNfdHJlbmQnOidcXHVkODNkXFx1ZGNjOScsXG4gICdjaGFydF93aXRoX3Vwd2FyZHNfdHJlbmQnOidcXHVkODNkXFx1ZGNjOCcsXG4gICdjaGVja2VyZWRfZmxhZyc6J1xcdWQ4M2NcXHVkZmMxJyxcbiAgJ2NoZWVzZSc6J1xcdWQ4M2VcXHVkZGMwJyxcbiAgJ2NoZXJyaWVzJzonXFx1ZDgzY1xcdWRmNTInLFxuICAnY2hlcnJ5X2Jsb3Nzb20nOidcXHVkODNjXFx1ZGYzOCcsXG4gICdjaGVzdG51dCc6J1xcdWQ4M2NcXHVkZjMwJyxcbiAgJ2NoaWNrZW4nOidcXHVkODNkXFx1ZGMxNCcsXG4gICdjaGlsZHJlbl9jcm9zc2luZyc6J1xcdWQ4M2RcXHVkZWI4JyxcbiAgJ2NoaXBtdW5rJzonXFx1ZDgzZFxcdWRjM2YnLFxuICAnY2hvY29sYXRlX2Jhcic6J1xcdWQ4M2NcXHVkZjZiJyxcbiAgJ2NocmlzdG1hc190cmVlJzonXFx1ZDgzY1xcdWRmODQnLFxuICAnY2h1cmNoJzonXFx1MjZlYVxcdWZlMGYnLFxuICAnY2luZW1hJzonXFx1ZDgzY1xcdWRmYTYnLFxuICAnY2lyY3VzX3RlbnQnOidcXHVkODNjXFx1ZGZhYScsXG4gICdjaXR5X3N1bnJpc2UnOidcXHVkODNjXFx1ZGYwNycsXG4gICdjaXR5X3N1bnNldCc6J1xcdWQ4M2NcXHVkZjA2JyxcbiAgJ2NpdHlzY2FwZSc6J1xcdWQ4M2NcXHVkZmQ5JyxcbiAgJ2NsJzonXFx1ZDgzY1xcdWRkOTEnLFxuICAnY2xhbXAnOidcXHVkODNkXFx1ZGRkYycsXG4gICdjbGFwJzonXFx1ZDgzZFxcdWRjNGYnLFxuICAnY2xhcHBlcic6J1xcdWQ4M2NcXHVkZmFjJyxcbiAgJ2NsYXNzaWNhbF9idWlsZGluZyc6J1xcdWQ4M2NcXHVkZmRiJyxcbiAgJ2NsaW5raW5nX2dsYXNzZXMnOidcXHVkODNlXFx1ZGQ0MicsXG4gICdjbGlwYm9hcmQnOidcXHVkODNkXFx1ZGNjYicsXG4gICdjbG9jazEnOidcXHVkODNkXFx1ZGQ1MCcsXG4gICdjbG9jazEwJzonXFx1ZDgzZFxcdWRkNTknLFxuICAnY2xvY2sxMDMwJzonXFx1ZDgzZFxcdWRkNjUnLFxuICAnY2xvY2sxMSc6J1xcdWQ4M2RcXHVkZDVhJyxcbiAgJ2Nsb2NrMTEzMCc6J1xcdWQ4M2RcXHVkZDY2JyxcbiAgJ2Nsb2NrMTInOidcXHVkODNkXFx1ZGQ1YicsXG4gICdjbG9jazEyMzAnOidcXHVkODNkXFx1ZGQ2NycsXG4gICdjbG9jazEzMCc6J1xcdWQ4M2RcXHVkZDVjJyxcbiAgJ2Nsb2NrMic6J1xcdWQ4M2RcXHVkZDUxJyxcbiAgJ2Nsb2NrMjMwJzonXFx1ZDgzZFxcdWRkNWQnLFxuICAnY2xvY2szJzonXFx1ZDgzZFxcdWRkNTInLFxuICAnY2xvY2szMzAnOidcXHVkODNkXFx1ZGQ1ZScsXG4gICdjbG9jazQnOidcXHVkODNkXFx1ZGQ1MycsXG4gICdjbG9jazQzMCc6J1xcdWQ4M2RcXHVkZDVmJyxcbiAgJ2Nsb2NrNSc6J1xcdWQ4M2RcXHVkZDU0JyxcbiAgJ2Nsb2NrNTMwJzonXFx1ZDgzZFxcdWRkNjAnLFxuICAnY2xvY2s2JzonXFx1ZDgzZFxcdWRkNTUnLFxuICAnY2xvY2s2MzAnOidcXHVkODNkXFx1ZGQ2MScsXG4gICdjbG9jazcnOidcXHVkODNkXFx1ZGQ1NicsXG4gICdjbG9jazczMCc6J1xcdWQ4M2RcXHVkZDYyJyxcbiAgJ2Nsb2NrOCc6J1xcdWQ4M2RcXHVkZDU3JyxcbiAgJ2Nsb2NrODMwJzonXFx1ZDgzZFxcdWRkNjMnLFxuICAnY2xvY2s5JzonXFx1ZDgzZFxcdWRkNTgnLFxuICAnY2xvY2s5MzAnOidcXHVkODNkXFx1ZGQ2NCcsXG4gICdjbG9zZWRfYm9vayc6J1xcdWQ4M2RcXHVkY2Q1JyxcbiAgJ2Nsb3NlZF9sb2NrX3dpdGhfa2V5JzonXFx1ZDgzZFxcdWRkMTAnLFxuICAnY2xvc2VkX3VtYnJlbGxhJzonXFx1ZDgzY1xcdWRmMDInLFxuICAnY2xvdWQnOidcXHUyNjAxXFx1ZmUwZicsXG4gICdjbG91ZF93aXRoX2xpZ2h0bmluZyc6J1xcdWQ4M2NcXHVkZjI5JyxcbiAgJ2Nsb3VkX3dpdGhfbGlnaHRuaW5nX2FuZF9yYWluJzonXFx1MjZjOCcsXG4gICdjbG91ZF93aXRoX3JhaW4nOidcXHVkODNjXFx1ZGYyNycsXG4gICdjbG91ZF93aXRoX3Nub3cnOidcXHVkODNjXFx1ZGYyOCcsXG4gICdjbG93bl9mYWNlJzonXFx1ZDgzZVxcdWRkMjEnLFxuICAnY2x1YnMnOidcXHUyNjYzXFx1ZmUwZicsXG4gICdjb2NrdGFpbCc6J1xcdWQ4M2NcXHVkZjc4JyxcbiAgJ2NvZmZlZSc6J1xcdTI2MTVcXHVmZTBmJyxcbiAgJ2NvZmZpbic6J1xcdTI2YjBcXHVmZTBmJyxcbiAgJ2NvbGRfc3dlYXQnOidcXHVkODNkXFx1ZGUzMCcsXG4gICdjb21ldCc6J1xcdTI2MDRcXHVmZTBmJyxcbiAgJ2NvbXB1dGVyJzonXFx1ZDgzZFxcdWRjYmInLFxuICAnY29tcHV0ZXJfbW91c2UnOidcXHVkODNkXFx1ZGRiMScsXG4gICdjb25mZXR0aV9iYWxsJzonXFx1ZDgzY1xcdWRmOGEnLFxuICAnY29uZm91bmRlZCc6J1xcdWQ4M2RcXHVkZTE2JyxcbiAgJ2NvbmZ1c2VkJzonXFx1ZDgzZFxcdWRlMTUnLFxuICAnY29uZ3JhdHVsYXRpb25zJzonXFx1MzI5N1xcdWZlMGYnLFxuICAnY29uc3RydWN0aW9uJzonXFx1ZDgzZFxcdWRlYTcnLFxuICAnY29uc3RydWN0aW9uX3dvcmtlcl9tYW4nOidcXHVkODNkXFx1ZGM3NycsXG4gICdjb25zdHJ1Y3Rpb25fd29ya2VyX3dvbWFuJzonXFx1ZDgzZFxcdWRjNzcmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2NvbnRyb2xfa25vYnMnOidcXHVkODNjXFx1ZGY5YicsXG4gICdjb252ZW5pZW5jZV9zdG9yZSc6J1xcdWQ4M2NcXHVkZmVhJyxcbiAgJ2Nvb2tpZSc6J1xcdWQ4M2NcXHVkZjZhJyxcbiAgJ2Nvb2wnOidcXHVkODNjXFx1ZGQ5MicsXG4gICdwb2xpY2VtYW4nOidcXHVkODNkXFx1ZGM2ZScsXG4gICdjb3B5cmlnaHQnOidcXHUwMGE5XFx1ZmUwZicsXG4gICdjb3JuJzonXFx1ZDgzY1xcdWRmM2QnLFxuICAnY291Y2hfYW5kX2xhbXAnOidcXHVkODNkXFx1ZGVjYicsXG4gICdjb3VwbGUnOidcXHVkODNkXFx1ZGM2YicsXG4gICdjb3VwbGVfd2l0aF9oZWFydF93b21hbl9tYW4nOidcXHVkODNkXFx1ZGM5MScsXG4gICdjb3VwbGVfd2l0aF9oZWFydF9tYW5fbWFuJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdTI3NjRcXHVmZTBmJnp3ajtcXHVkODNkXFx1ZGM2OCcsXG4gICdjb3VwbGVfd2l0aF9oZWFydF93b21hbl93b21hbic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHUyNzY0XFx1ZmUwZiZ6d2o7XFx1ZDgzZFxcdWRjNjknLFxuICAnY291cGxla2lzc19tYW5fbWFuJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdTI3NjRcXHVmZTBmJnp3ajtcXHVkODNkXFx1ZGM4YiZ6d2o7XFx1ZDgzZFxcdWRjNjgnLFxuICAnY291cGxla2lzc19tYW5fd29tYW4nOidcXHVkODNkXFx1ZGM4ZicsXG4gICdjb3VwbGVraXNzX3dvbWFuX3dvbWFuJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdTI3NjRcXHVmZTBmJnp3ajtcXHVkODNkXFx1ZGM4YiZ6d2o7XFx1ZDgzZFxcdWRjNjknLFxuICAnY293JzonXFx1ZDgzZFxcdWRjMmUnLFxuICAnY293Mic6J1xcdWQ4M2RcXHVkYzA0JyxcbiAgJ2Nvd2JveV9oYXRfZmFjZSc6J1xcdWQ4M2VcXHVkZDIwJyxcbiAgJ2NyYWInOidcXHVkODNlXFx1ZGQ4MCcsXG4gICdjcmF5b24nOidcXHVkODNkXFx1ZGQ4ZCcsXG4gICdjcmVkaXRfY2FyZCc6J1xcdWQ4M2RcXHVkY2IzJyxcbiAgJ2NyZXNjZW50X21vb24nOidcXHVkODNjXFx1ZGYxOScsXG4gICdjcmlja2V0JzonXFx1ZDgzY1xcdWRmY2YnLFxuICAnY3JvY29kaWxlJzonXFx1ZDgzZFxcdWRjMGEnLFxuICAnY3JvaXNzYW50JzonXFx1ZDgzZVxcdWRkNTAnLFxuICAnY3Jvc3NlZF9maW5nZXJzJzonXFx1ZDgzZVxcdWRkMWUnLFxuICAnY3Jvc3NlZF9mbGFncyc6J1xcdWQ4M2NcXHVkZjhjJyxcbiAgJ2Nyb3NzZWRfc3dvcmRzJzonXFx1MjY5NFxcdWZlMGYnLFxuICAnY3Jvd24nOidcXHVkODNkXFx1ZGM1MScsXG4gICdjcnknOidcXHVkODNkXFx1ZGUyMicsXG4gICdjcnlpbmdfY2F0X2ZhY2UnOidcXHVkODNkXFx1ZGUzZicsXG4gICdjcnlzdGFsX2JhbGwnOidcXHVkODNkXFx1ZGQyZScsXG4gICdjdWN1bWJlcic6J1xcdWQ4M2VcXHVkZDUyJyxcbiAgJ2N1cGlkJzonXFx1ZDgzZFxcdWRjOTgnLFxuICAnY3VybHlfbG9vcCc6J1xcdTI3YjAnLFxuICAnY3VycmVuY3lfZXhjaGFuZ2UnOidcXHVkODNkXFx1ZGNiMScsXG4gICdjdXJyeSc6J1xcdWQ4M2NcXHVkZjViJyxcbiAgJ2N1c3RhcmQnOidcXHVkODNjXFx1ZGY2ZScsXG4gICdjdXN0b21zJzonXFx1ZDgzZFxcdWRlYzMnLFxuICAnY3ljbG9uZSc6J1xcdWQ4M2NcXHVkZjAwJyxcbiAgJ2RhZ2dlcic6J1xcdWQ4M2RcXHVkZGUxJyxcbiAgJ2RhbmNlcic6J1xcdWQ4M2RcXHVkYzgzJyxcbiAgJ2RhbmNpbmdfd29tZW4nOidcXHVkODNkXFx1ZGM2ZicsXG4gICdkYW5jaW5nX21lbic6J1xcdWQ4M2RcXHVkYzZmJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdkYW5nbyc6J1xcdWQ4M2NcXHVkZjYxJyxcbiAgJ2Rhcmtfc3VuZ2xhc3Nlcyc6J1xcdWQ4M2RcXHVkZDc2JyxcbiAgJ2RhcnQnOidcXHVkODNjXFx1ZGZhZicsXG4gICdkYXNoJzonXFx1ZDgzZFxcdWRjYTgnLFxuICAnZGF0ZSc6J1xcdWQ4M2RcXHVkY2M1JyxcbiAgJ2RlY2lkdW91c190cmVlJzonXFx1ZDgzY1xcdWRmMzMnLFxuICAnZGVlcic6J1xcdWQ4M2VcXHVkZDhjJyxcbiAgJ2RlcGFydG1lbnRfc3RvcmUnOidcXHVkODNjXFx1ZGZlYycsXG4gICdkZXJlbGljdF9ob3VzZSc6J1xcdWQ4M2NcXHVkZmRhJyxcbiAgJ2Rlc2VydCc6J1xcdWQ4M2NcXHVkZmRjJyxcbiAgJ2Rlc2VydF9pc2xhbmQnOidcXHVkODNjXFx1ZGZkZCcsXG4gICdkZXNrdG9wX2NvbXB1dGVyJzonXFx1ZDgzZFxcdWRkYTUnLFxuICAnbWFsZV9kZXRlY3RpdmUnOidcXHVkODNkXFx1ZGQ3NVxcdWZlMGYnLFxuICAnZGlhbW9uZF9zaGFwZV93aXRoX2FfZG90X2luc2lkZSc6J1xcdWQ4M2RcXHVkY2EwJyxcbiAgJ2RpYW1vbmRzJzonXFx1MjY2NlxcdWZlMGYnLFxuICAnZGlzYXBwb2ludGVkJzonXFx1ZDgzZFxcdWRlMWUnLFxuICAnZGlzYXBwb2ludGVkX3JlbGlldmVkJzonXFx1ZDgzZFxcdWRlMjUnLFxuICAnZGl6enknOidcXHVkODNkXFx1ZGNhYicsXG4gICdkaXp6eV9mYWNlJzonXFx1ZDgzZFxcdWRlMzUnLFxuICAnZG9fbm90X2xpdHRlcic6J1xcdWQ4M2RcXHVkZWFmJyxcbiAgJ2RvZyc6J1xcdWQ4M2RcXHVkYzM2JyxcbiAgJ2RvZzInOidcXHVkODNkXFx1ZGMxNScsXG4gICdkb2xsYXInOidcXHVkODNkXFx1ZGNiNScsXG4gICdkb2xscyc6J1xcdWQ4M2NcXHVkZjhlJyxcbiAgJ2RvbHBoaW4nOidcXHVkODNkXFx1ZGMyYycsXG4gICdkb29yJzonXFx1ZDgzZFxcdWRlYWEnLFxuICAnZG91Z2hudXQnOidcXHVkODNjXFx1ZGY2OScsXG4gICdkb3ZlJzonXFx1ZDgzZFxcdWRkNGEnLFxuICAnZHJhZ29uJzonXFx1ZDgzZFxcdWRjMDknLFxuICAnZHJhZ29uX2ZhY2UnOidcXHVkODNkXFx1ZGMzMicsXG4gICdkcmVzcyc6J1xcdWQ4M2RcXHVkYzU3JyxcbiAgJ2Ryb21lZGFyeV9jYW1lbCc6J1xcdWQ4M2RcXHVkYzJhJyxcbiAgJ2Ryb29saW5nX2ZhY2UnOidcXHVkODNlXFx1ZGQyNCcsXG4gICdkcm9wbGV0JzonXFx1ZDgzZFxcdWRjYTcnLFxuICAnZHJ1bSc6J1xcdWQ4M2VcXHVkZDQxJyxcbiAgJ2R1Y2snOidcXHVkODNlXFx1ZGQ4NicsXG4gICdkdmQnOidcXHVkODNkXFx1ZGNjMCcsXG4gICdlLW1haWwnOidcXHVkODNkXFx1ZGNlNycsXG4gICdlYWdsZSc6J1xcdWQ4M2VcXHVkZDg1JyxcbiAgJ2Vhcic6J1xcdWQ4M2RcXHVkYzQyJyxcbiAgJ2Vhcl9vZl9yaWNlJzonXFx1ZDgzY1xcdWRmM2UnLFxuICAnZWFydGhfYWZyaWNhJzonXFx1ZDgzY1xcdWRmMGQnLFxuICAnZWFydGhfYW1lcmljYXMnOidcXHVkODNjXFx1ZGYwZScsXG4gICdlYXJ0aF9hc2lhJzonXFx1ZDgzY1xcdWRmMGYnLFxuICAnZWdnJzonXFx1ZDgzZVxcdWRkNWEnLFxuICAnZWdncGxhbnQnOidcXHVkODNjXFx1ZGY0NicsXG4gICdlaWdodF9wb2ludGVkX2JsYWNrX3N0YXInOidcXHUyNzM0XFx1ZmUwZicsXG4gICdlaWdodF9zcG9rZWRfYXN0ZXJpc2snOidcXHUyNzMzXFx1ZmUwZicsXG4gICdlbGVjdHJpY19wbHVnJzonXFx1ZDgzZFxcdWRkMGMnLFxuICAnZWxlcGhhbnQnOidcXHVkODNkXFx1ZGMxOCcsXG4gICdlbWFpbCc6J1xcdTI3MDlcXHVmZTBmJyxcbiAgJ2VuZCc6J1xcdWQ4M2RcXHVkZDFhJyxcbiAgJ2VudmVsb3BlX3dpdGhfYXJyb3cnOidcXHVkODNkXFx1ZGNlOScsXG4gICdldXJvJzonXFx1ZDgzZFxcdWRjYjYnLFxuICAnZXVyb3BlYW5fY2FzdGxlJzonXFx1ZDgzY1xcdWRmZjAnLFxuICAnZXVyb3BlYW5fcG9zdF9vZmZpY2UnOidcXHVkODNjXFx1ZGZlNCcsXG4gICdldmVyZ3JlZW5fdHJlZSc6J1xcdWQ4M2NcXHVkZjMyJyxcbiAgJ2V4Y2xhbWF0aW9uJzonXFx1Mjc1N1xcdWZlMGYnLFxuICAnZXhwcmVzc2lvbmxlc3MnOidcXHVkODNkXFx1ZGUxMScsXG4gICdleWUnOidcXHVkODNkXFx1ZGM0MScsXG4gICdleWVfc3BlZWNoX2J1YmJsZSc6J1xcdWQ4M2RcXHVkYzQxJnp3ajtcXHVkODNkXFx1ZGRlOCcsXG4gICdleWVnbGFzc2VzJzonXFx1ZDgzZFxcdWRjNTMnLFxuICAnZXllcyc6J1xcdWQ4M2RcXHVkYzQwJyxcbiAgJ2ZhY2Vfd2l0aF9oZWFkX2JhbmRhZ2UnOidcXHVkODNlXFx1ZGQxNScsXG4gICdmYWNlX3dpdGhfdGhlcm1vbWV0ZXInOidcXHVkODNlXFx1ZGQxMicsXG4gICdmaXN0X29uY29taW5nJzonXFx1ZDgzZFxcdWRjNGEnLFxuICAnZmFjdG9yeSc6J1xcdWQ4M2NcXHVkZmVkJyxcbiAgJ2ZhbGxlbl9sZWFmJzonXFx1ZDgzY1xcdWRmNDInLFxuICAnZmFtaWx5X21hbl93b21hbl9ib3knOidcXHVkODNkXFx1ZGM2YScsXG4gICdmYW1pbHlfbWFuX2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjYmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfbWFuX2dpcmxfYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X21hbl9tYW5fYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX21hbl9ib3lfYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NiZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl9tYW5fZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X21hbl9tYW5fZ2lybF9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX21hbl9naXJsX2dpcmwnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfbWFuX3dvbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY2Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX3dvbWFuX2dpcmwnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV9tYW5fd29tYW5fZ2lybF9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX3dvbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV93b21hbl9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjYmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV93b21hbl9naXJsJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV93b21hbl9naXJsX2JveSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2JveSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY2Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfd29tYW5fd29tYW5fZ2lybCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2dpcmxfYm95JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2Zhc3RfZm9yd2FyZCc6J1xcdTIzZTknLFxuICAnZmF4JzonXFx1ZDgzZFxcdWRjZTAnLFxuICAnZmVhcmZ1bCc6J1xcdWQ4M2RcXHVkZTI4JyxcbiAgJ2ZlZXQnOidcXHVkODNkXFx1ZGMzZScsXG4gICdmZW1hbGVfZGV0ZWN0aXZlJzonXFx1ZDgzZFxcdWRkNzVcXHVmZTBmJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdmZXJyaXNfd2hlZWwnOidcXHVkODNjXFx1ZGZhMScsXG4gICdmZXJyeSc6J1xcdTI2ZjQnLFxuICAnZmllbGRfaG9ja2V5JzonXFx1ZDgzY1xcdWRmZDEnLFxuICAnZmlsZV9jYWJpbmV0JzonXFx1ZDgzZFxcdWRkYzQnLFxuICAnZmlsZV9mb2xkZXInOidcXHVkODNkXFx1ZGNjMScsXG4gICdmaWxtX3Byb2plY3Rvcic6J1xcdWQ4M2RcXHVkY2ZkJyxcbiAgJ2ZpbG1fc3RyaXAnOidcXHVkODNjXFx1ZGY5ZScsXG4gICdmaXJlJzonXFx1ZDgzZFxcdWRkMjUnLFxuICAnZmlyZV9lbmdpbmUnOidcXHVkODNkXFx1ZGU5MicsXG4gICdmaXJld29ya3MnOidcXHVkODNjXFx1ZGY4NicsXG4gICdmaXJzdF9xdWFydGVyX21vb24nOidcXHVkODNjXFx1ZGYxMycsXG4gICdmaXJzdF9xdWFydGVyX21vb25fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWInLFxuICAnZmlzaCc6J1xcdWQ4M2RcXHVkYzFmJyxcbiAgJ2Zpc2hfY2FrZSc6J1xcdWQ4M2NcXHVkZjY1JyxcbiAgJ2Zpc2hpbmdfcG9sZV9hbmRfZmlzaCc6J1xcdWQ4M2NcXHVkZmEzJyxcbiAgJ2Zpc3RfcmFpc2VkJzonXFx1MjcwYScsXG4gICdmaXN0X2xlZnQnOidcXHVkODNlXFx1ZGQxYicsXG4gICdmaXN0X3JpZ2h0JzonXFx1ZDgzZVxcdWRkMWMnLFxuICAnZmxhZ3MnOidcXHVkODNjXFx1ZGY4ZicsXG4gICdmbGFzaGxpZ2h0JzonXFx1ZDgzZFxcdWRkMjYnLFxuICAnZmxldXJfZGVfbGlzJzonXFx1MjY5Y1xcdWZlMGYnLFxuICAnZmxpZ2h0X2Fycml2YWwnOidcXHVkODNkXFx1ZGVlYycsXG4gICdmbGlnaHRfZGVwYXJ0dXJlJzonXFx1ZDgzZFxcdWRlZWInLFxuICAnZmxvcHB5X2Rpc2snOidcXHVkODNkXFx1ZGNiZScsXG4gICdmbG93ZXJfcGxheWluZ19jYXJkcyc6J1xcdWQ4M2NcXHVkZmI0JyxcbiAgJ2ZsdXNoZWQnOidcXHVkODNkXFx1ZGUzMycsXG4gICdmb2cnOidcXHVkODNjXFx1ZGYyYicsXG4gICdmb2dneSc6J1xcdWQ4M2NcXHVkZjAxJyxcbiAgJ2Zvb3RiYWxsJzonXFx1ZDgzY1xcdWRmYzgnLFxuICAnZm9vdHByaW50cyc6J1xcdWQ4M2RcXHVkYzYzJyxcbiAgJ2ZvcmtfYW5kX2tuaWZlJzonXFx1ZDgzY1xcdWRmNzQnLFxuICAnZm91bnRhaW4nOidcXHUyNmYyXFx1ZmUwZicsXG4gICdmb3VudGFpbl9wZW4nOidcXHVkODNkXFx1ZGQ4YicsXG4gICdmb3VyX2xlYWZfY2xvdmVyJzonXFx1ZDgzY1xcdWRmNDAnLFxuICAnZm94X2ZhY2UnOidcXHVkODNlXFx1ZGQ4YScsXG4gICdmcmFtZWRfcGljdHVyZSc6J1xcdWQ4M2RcXHVkZGJjJyxcbiAgJ2ZyZWUnOidcXHVkODNjXFx1ZGQ5MycsXG4gICdmcmllZF9lZ2cnOidcXHVkODNjXFx1ZGY3MycsXG4gICdmcmllZF9zaHJpbXAnOidcXHVkODNjXFx1ZGY2NCcsXG4gICdmcmllcyc6J1xcdWQ4M2NcXHVkZjVmJyxcbiAgJ2Zyb2cnOidcXHVkODNkXFx1ZGMzOCcsXG4gICdmcm93bmluZyc6J1xcdWQ4M2RcXHVkZTI2JyxcbiAgJ2Zyb3duaW5nX2ZhY2UnOidcXHUyNjM5XFx1ZmUwZicsXG4gICdmcm93bmluZ19tYW4nOidcXHVkODNkXFx1ZGU0ZCZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnZnJvd25pbmdfd29tYW4nOidcXHVkODNkXFx1ZGU0ZCcsXG4gICdtaWRkbGVfZmluZ2VyJzonXFx1ZDgzZFxcdWRkOTUnLFxuICAnZnVlbHB1bXAnOidcXHUyNmZkXFx1ZmUwZicsXG4gICdmdWxsX21vb24nOidcXHVkODNjXFx1ZGYxNScsXG4gICdmdWxsX21vb25fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWQnLFxuICAnZnVuZXJhbF91cm4nOidcXHUyNmIxXFx1ZmUwZicsXG4gICdnYW1lX2RpZSc6J1xcdWQ4M2NcXHVkZmIyJyxcbiAgJ2dlYXInOidcXHUyNjk5XFx1ZmUwZicsXG4gICdnZW0nOidcXHVkODNkXFx1ZGM4ZScsXG4gICdnZW1pbmknOidcXHUyNjRhXFx1ZmUwZicsXG4gICdnaG9zdCc6J1xcdWQ4M2RcXHVkYzdiJyxcbiAgJ2dpZnQnOidcXHVkODNjXFx1ZGY4MScsXG4gICdnaWZ0X2hlYXJ0JzonXFx1ZDgzZFxcdWRjOWQnLFxuICAnZ2lybCc6J1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2dsb2JlX3dpdGhfbWVyaWRpYW5zJzonXFx1ZDgzY1xcdWRmMTAnLFxuICAnZ29hbF9uZXQnOidcXHVkODNlXFx1ZGQ0NScsXG4gICdnb2F0JzonXFx1ZDgzZFxcdWRjMTAnLFxuICAnZ29sZic6J1xcdTI2ZjNcXHVmZTBmJyxcbiAgJ2dvbGZpbmdfbWFuJzonXFx1ZDgzY1xcdWRmY2NcXHVmZTBmJyxcbiAgJ2dvbGZpbmdfd29tYW4nOidcXHVkODNjXFx1ZGZjY1xcdWZlMGYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2dvcmlsbGEnOidcXHVkODNlXFx1ZGQ4ZCcsXG4gICdncmFwZXMnOidcXHVkODNjXFx1ZGY0NycsXG4gICdncmVlbl9hcHBsZSc6J1xcdWQ4M2NcXHVkZjRmJyxcbiAgJ2dyZWVuX2Jvb2snOidcXHVkODNkXFx1ZGNkNycsXG4gICdncmVlbl9oZWFydCc6J1xcdWQ4M2RcXHVkYzlhJyxcbiAgJ2dyZWVuX3NhbGFkJzonXFx1ZDgzZVxcdWRkNTcnLFxuICAnZ3JleV9leGNsYW1hdGlvbic6J1xcdTI3NTUnLFxuICAnZ3JleV9xdWVzdGlvbic6J1xcdTI3NTQnLFxuICAnZ3JpbWFjaW5nJzonXFx1ZDgzZFxcdWRlMmMnLFxuICAnZ3Jpbic6J1xcdWQ4M2RcXHVkZTAxJyxcbiAgJ2dyaW5uaW5nJzonXFx1ZDgzZFxcdWRlMDAnLFxuICAnZ3VhcmRzbWFuJzonXFx1ZDgzZFxcdWRjODInLFxuICAnZ3VhcmRzd29tYW4nOidcXHVkODNkXFx1ZGM4MiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnZ3VpdGFyJzonXFx1ZDgzY1xcdWRmYjgnLFxuICAnZ3VuJzonXFx1ZDgzZFxcdWRkMmInLFxuICAnaGFpcmN1dF93b21hbic6J1xcdWQ4M2RcXHVkYzg3JyxcbiAgJ2hhaXJjdXRfbWFuJzonXFx1ZDgzZFxcdWRjODcmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ2hhbWJ1cmdlcic6J1xcdWQ4M2NcXHVkZjU0JyxcbiAgJ2hhbW1lcic6J1xcdWQ4M2RcXHVkZDI4JyxcbiAgJ2hhbW1lcl9hbmRfcGljayc6J1xcdTI2OTInLFxuICAnaGFtbWVyX2FuZF93cmVuY2gnOidcXHVkODNkXFx1ZGVlMCcsXG4gICdoYW1zdGVyJzonXFx1ZDgzZFxcdWRjMzknLFxuICAnaGFuZCc6J1xcdTI3MGInLFxuICAnaGFuZGJhZyc6J1xcdWQ4M2RcXHVkYzVjJyxcbiAgJ2hhbmRzaGFrZSc6J1xcdWQ4M2VcXHVkZDFkJyxcbiAgJ2hhbmtleSc6J1xcdWQ4M2RcXHVkY2E5JyxcbiAgJ2hhdGNoZWRfY2hpY2snOidcXHVkODNkXFx1ZGMyNScsXG4gICdoYXRjaGluZ19jaGljayc6J1xcdWQ4M2RcXHVkYzIzJyxcbiAgJ2hlYWRwaG9uZXMnOidcXHVkODNjXFx1ZGZhNycsXG4gICdoZWFyX25vX2V2aWwnOidcXHVkODNkXFx1ZGU0OScsXG4gICdoZWFydCc6J1xcdTI3NjRcXHVmZTBmJyxcbiAgJ2hlYXJ0X2RlY29yYXRpb24nOidcXHVkODNkXFx1ZGM5ZicsXG4gICdoZWFydF9leWVzJzonXFx1ZDgzZFxcdWRlMGQnLFxuICAnaGVhcnRfZXllc19jYXQnOidcXHVkODNkXFx1ZGUzYicsXG4gICdoZWFydGJlYXQnOidcXHVkODNkXFx1ZGM5MycsXG4gICdoZWFydHB1bHNlJzonXFx1ZDgzZFxcdWRjOTcnLFxuICAnaGVhcnRzJzonXFx1MjY2NVxcdWZlMGYnLFxuICAnaGVhdnlfY2hlY2tfbWFyayc6J1xcdTI3MTRcXHVmZTBmJyxcbiAgJ2hlYXZ5X2RpdmlzaW9uX3NpZ24nOidcXHUyNzk3JyxcbiAgJ2hlYXZ5X2RvbGxhcl9zaWduJzonXFx1ZDgzZFxcdWRjYjInLFxuICAnaGVhdnlfaGVhcnRfZXhjbGFtYXRpb24nOidcXHUyNzYzXFx1ZmUwZicsXG4gICdoZWF2eV9taW51c19zaWduJzonXFx1Mjc5NicsXG4gICdoZWF2eV9tdWx0aXBsaWNhdGlvbl94JzonXFx1MjcxNlxcdWZlMGYnLFxuICAnaGVhdnlfcGx1c19zaWduJzonXFx1Mjc5NScsXG4gICdoZWxpY29wdGVyJzonXFx1ZDgzZFxcdWRlODEnLFxuICAnaGVyYic6J1xcdWQ4M2NcXHVkZjNmJyxcbiAgJ2hpYmlzY3VzJzonXFx1ZDgzY1xcdWRmM2EnLFxuICAnaGlnaF9icmlnaHRuZXNzJzonXFx1ZDgzZFxcdWRkMDYnLFxuICAnaGlnaF9oZWVsJzonXFx1ZDgzZFxcdWRjNjAnLFxuICAnaG9jaG8nOidcXHVkODNkXFx1ZGQyYScsXG4gICdob2xlJzonXFx1ZDgzZFxcdWRkNzMnLFxuICAnaG9uZXlfcG90JzonXFx1ZDgzY1xcdWRmNmYnLFxuICAnaG9yc2UnOidcXHVkODNkXFx1ZGMzNCcsXG4gICdob3JzZV9yYWNpbmcnOidcXHVkODNjXFx1ZGZjNycsXG4gICdob3NwaXRhbCc6J1xcdWQ4M2NcXHVkZmU1JyxcbiAgJ2hvdF9wZXBwZXInOidcXHVkODNjXFx1ZGYzNicsXG4gICdob3Rkb2cnOidcXHVkODNjXFx1ZGYyZCcsXG4gICdob3RlbCc6J1xcdWQ4M2NcXHVkZmU4JyxcbiAgJ2hvdHNwcmluZ3MnOidcXHUyNjY4XFx1ZmUwZicsXG4gICdob3VyZ2xhc3MnOidcXHUyMzFiXFx1ZmUwZicsXG4gICdob3VyZ2xhc3NfZmxvd2luZ19zYW5kJzonXFx1MjNmMycsXG4gICdob3VzZSc6J1xcdWQ4M2NcXHVkZmUwJyxcbiAgJ2hvdXNlX3dpdGhfZ2FyZGVuJzonXFx1ZDgzY1xcdWRmZTEnLFxuICAnaG91c2VzJzonXFx1ZDgzY1xcdWRmZDgnLFxuICAnaHVncyc6J1xcdWQ4M2VcXHVkZDE3JyxcbiAgJ2h1c2hlZCc6J1xcdWQ4M2RcXHVkZTJmJyxcbiAgJ2ljZV9jcmVhbSc6J1xcdWQ4M2NcXHVkZjY4JyxcbiAgJ2ljZV9ob2NrZXknOidcXHVkODNjXFx1ZGZkMicsXG4gICdpY2Vfc2thdGUnOidcXHUyNmY4JyxcbiAgJ2ljZWNyZWFtJzonXFx1ZDgzY1xcdWRmNjYnLFxuICAnaWQnOidcXHVkODNjXFx1ZGQ5NCcsXG4gICdpZGVvZ3JhcGhfYWR2YW50YWdlJzonXFx1ZDgzY1xcdWRlNTAnLFxuICAnaW1wJzonXFx1ZDgzZFxcdWRjN2YnLFxuICAnaW5ib3hfdHJheSc6J1xcdWQ4M2RcXHVkY2U1JyxcbiAgJ2luY29taW5nX2VudmVsb3BlJzonXFx1ZDgzZFxcdWRjZTgnLFxuICAndGlwcGluZ19oYW5kX3dvbWFuJzonXFx1ZDgzZFxcdWRjODEnLFxuICAnaW5mb3JtYXRpb25fc291cmNlJzonXFx1MjEzOVxcdWZlMGYnLFxuICAnaW5ub2NlbnQnOidcXHVkODNkXFx1ZGUwNycsXG4gICdpbnRlcnJvYmFuZyc6J1xcdTIwNDlcXHVmZTBmJyxcbiAgJ2lwaG9uZSc6J1xcdWQ4M2RcXHVkY2YxJyxcbiAgJ2l6YWtheWFfbGFudGVybic6J1xcdWQ4M2NcXHVkZmVlJyxcbiAgJ2phY2tfb19sYW50ZXJuJzonXFx1ZDgzY1xcdWRmODMnLFxuICAnamFwYW4nOidcXHVkODNkXFx1ZGRmZScsXG4gICdqYXBhbmVzZV9jYXN0bGUnOidcXHVkODNjXFx1ZGZlZicsXG4gICdqYXBhbmVzZV9nb2JsaW4nOidcXHVkODNkXFx1ZGM3YScsXG4gICdqYXBhbmVzZV9vZ3JlJzonXFx1ZDgzZFxcdWRjNzknLFxuICAnamVhbnMnOidcXHVkODNkXFx1ZGM1NicsXG4gICdqb3knOidcXHVkODNkXFx1ZGUwMicsXG4gICdqb3lfY2F0JzonXFx1ZDgzZFxcdWRlMzknLFxuICAnam95c3RpY2snOidcXHVkODNkXFx1ZGQ3OScsXG4gICdrYWFiYSc6J1xcdWQ4M2RcXHVkZDRiJyxcbiAgJ2tleSc6J1xcdWQ4M2RcXHVkZDExJyxcbiAgJ2tleWJvYXJkJzonXFx1MjMyOFxcdWZlMGYnLFxuICAna2V5Y2FwX3Rlbic6J1xcdWQ4M2RcXHVkZDFmJyxcbiAgJ2tpY2tfc2Nvb3Rlcic6J1xcdWQ4M2RcXHVkZWY0JyxcbiAgJ2tpbW9ubyc6J1xcdWQ4M2RcXHVkYzU4JyxcbiAgJ2tpc3MnOidcXHVkODNkXFx1ZGM4YicsXG4gICdraXNzaW5nJzonXFx1ZDgzZFxcdWRlMTcnLFxuICAna2lzc2luZ19jYXQnOidcXHVkODNkXFx1ZGUzZCcsXG4gICdraXNzaW5nX2Nsb3NlZF9leWVzJzonXFx1ZDgzZFxcdWRlMWEnLFxuICAna2lzc2luZ19oZWFydCc6J1xcdWQ4M2RcXHVkZTE4JyxcbiAgJ2tpc3Npbmdfc21pbGluZ19leWVzJzonXFx1ZDgzZFxcdWRlMTknLFxuICAna2l3aV9mcnVpdCc6J1xcdWQ4M2VcXHVkZDVkJyxcbiAgJ2tvYWxhJzonXFx1ZDgzZFxcdWRjMjgnLFxuICAna29rbyc6J1xcdWQ4M2NcXHVkZTAxJyxcbiAgJ2xhYmVsJzonXFx1ZDgzY1xcdWRmZjcnLFxuICAnbGFyZ2VfYmx1ZV9jaXJjbGUnOidcXHVkODNkXFx1ZGQzNScsXG4gICdsYXJnZV9ibHVlX2RpYW1vbmQnOidcXHVkODNkXFx1ZGQzNycsXG4gICdsYXJnZV9vcmFuZ2VfZGlhbW9uZCc6J1xcdWQ4M2RcXHVkZDM2JyxcbiAgJ2xhc3RfcXVhcnRlcl9tb29uJzonXFx1ZDgzY1xcdWRmMTcnLFxuICAnbGFzdF9xdWFydGVyX21vb25fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWMnLFxuICAnbGF0aW5fY3Jvc3MnOidcXHUyNzFkXFx1ZmUwZicsXG4gICdsYXVnaGluZyc6J1xcdWQ4M2RcXHVkZTA2JyxcbiAgJ2xlYXZlcyc6J1xcdWQ4M2NcXHVkZjQzJyxcbiAgJ2xlZGdlcic6J1xcdWQ4M2RcXHVkY2QyJyxcbiAgJ2xlZnRfbHVnZ2FnZSc6J1xcdWQ4M2RcXHVkZWM1JyxcbiAgJ2xlZnRfcmlnaHRfYXJyb3cnOidcXHUyMTk0XFx1ZmUwZicsXG4gICdsZWZ0d2FyZHNfYXJyb3dfd2l0aF9ob29rJzonXFx1MjFhOVxcdWZlMGYnLFxuICAnbGVtb24nOidcXHVkODNjXFx1ZGY0YicsXG4gICdsZW8nOidcXHUyNjRjXFx1ZmUwZicsXG4gICdsZW9wYXJkJzonXFx1ZDgzZFxcdWRjMDYnLFxuICAnbGV2ZWxfc2xpZGVyJzonXFx1ZDgzY1xcdWRmOWEnLFxuICAnbGlicmEnOidcXHUyNjRlXFx1ZmUwZicsXG4gICdsaWdodF9yYWlsJzonXFx1ZDgzZFxcdWRlODgnLFxuICAnbGluayc6J1xcdWQ4M2RcXHVkZDE3JyxcbiAgJ2xpb24nOidcXHVkODNlXFx1ZGQ4MScsXG4gICdsaXBzJzonXFx1ZDgzZFxcdWRjNDQnLFxuICAnbGlwc3RpY2snOidcXHVkODNkXFx1ZGM4NCcsXG4gICdsaXphcmQnOidcXHVkODNlXFx1ZGQ4ZScsXG4gICdsb2NrJzonXFx1ZDgzZFxcdWRkMTInLFxuICAnbG9ja193aXRoX2lua19wZW4nOidcXHVkODNkXFx1ZGQwZicsXG4gICdsb2xsaXBvcCc6J1xcdWQ4M2NcXHVkZjZkJyxcbiAgJ2xvb3AnOidcXHUyN2JmJyxcbiAgJ2xvdWRfc291bmQnOidcXHVkODNkXFx1ZGQwYScsXG4gICdsb3Vkc3BlYWtlcic6J1xcdWQ4M2RcXHVkY2UyJyxcbiAgJ2xvdmVfaG90ZWwnOidcXHVkODNjXFx1ZGZlOScsXG4gICdsb3ZlX2xldHRlcic6J1xcdWQ4M2RcXHVkYzhjJyxcbiAgJ2xvd19icmlnaHRuZXNzJzonXFx1ZDgzZFxcdWRkMDUnLFxuICAnbHlpbmdfZmFjZSc6J1xcdWQ4M2VcXHVkZDI1JyxcbiAgJ20nOidcXHUyNGMyXFx1ZmUwZicsXG4gICdtYWcnOidcXHVkODNkXFx1ZGQwZCcsXG4gICdtYWdfcmlnaHQnOidcXHVkODNkXFx1ZGQwZScsXG4gICdtYWhqb25nJzonXFx1ZDgzY1xcdWRjMDRcXHVmZTBmJyxcbiAgJ21haWxib3gnOidcXHVkODNkXFx1ZGNlYicsXG4gICdtYWlsYm94X2Nsb3NlZCc6J1xcdWQ4M2RcXHVkY2VhJyxcbiAgJ21haWxib3hfd2l0aF9tYWlsJzonXFx1ZDgzZFxcdWRjZWMnLFxuICAnbWFpbGJveF93aXRoX25vX21haWwnOidcXHVkODNkXFx1ZGNlZCcsXG4gICdtYW4nOidcXHVkODNkXFx1ZGM2OCcsXG4gICdtYW5fYXJ0aXN0JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZmE4JyxcbiAgJ21hbl9hc3Ryb25hdXQnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRlODAnLFxuICAnbWFuX2NhcnR3aGVlbGluZyc6J1xcdWQ4M2VcXHVkZDM4Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fY29vayc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGY3MycsXG4gICdtYW5fZGFuY2luZyc6J1xcdWQ4M2RcXHVkZDdhJyxcbiAgJ21hbl9mYWNlcGFsbWluZyc6J1xcdWQ4M2VcXHVkZDI2Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fZmFjdG9yeV93b3JrZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzY1xcdWRmZWQnLFxuICAnbWFuX2Zhcm1lcic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGYzZScsXG4gICdtYW5fZmlyZWZpZ2h0ZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRlOTInLFxuICAnbWFuX2hlYWx0aF93b3JrZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1MjY5NVxcdWZlMGYnLFxuICAnbWFuX2luX3R1eGVkbyc6J1xcdWQ4M2VcXHVkZDM1JyxcbiAgJ21hbl9qdWRnZSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHUyNjk2XFx1ZmUwZicsXG4gICdtYW5fanVnZ2xpbmcnOidcXHVkODNlXFx1ZGQzOSZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWFuX21lY2hhbmljJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkZDI3JyxcbiAgJ21hbl9vZmZpY2Vfd29ya2VyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkY2JjJyxcbiAgJ21hbl9waWxvdCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHUyNzA4XFx1ZmUwZicsXG4gICdtYW5fcGxheWluZ19oYW5kYmFsbCc6J1xcdWQ4M2VcXHVkZDNlJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fcGxheWluZ193YXRlcl9wb2xvJzonXFx1ZDgzZVxcdWRkM2QmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21hbl9zY2llbnRpc3QnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRkMmMnLFxuICAnbWFuX3NocnVnZ2luZyc6J1xcdWQ4M2VcXHVkZDM3Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fc2luZ2VyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZmE0JyxcbiAgJ21hbl9zdHVkZW50JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZjkzJyxcbiAgJ21hbl90ZWFjaGVyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZmViJyxcbiAgJ21hbl90ZWNobm9sb2dpc3QnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjYmInLFxuICAnbWFuX3dpdGhfZ3VhX3BpX21hbyc6J1xcdWQ4M2RcXHVkYzcyJyxcbiAgJ21hbl93aXRoX3R1cmJhbic6J1xcdWQ4M2RcXHVkYzczJyxcbiAgJ3RhbmdlcmluZSc6J1xcdWQ4M2NcXHVkZjRhJyxcbiAgJ21hbnNfc2hvZSc6J1xcdWQ4M2RcXHVkYzVlJyxcbiAgJ21hbnRlbHBpZWNlX2Nsb2NrJzonXFx1ZDgzZFxcdWRkNzAnLFxuICAnbWFwbGVfbGVhZic6J1xcdWQ4M2NcXHVkZjQxJyxcbiAgJ21hcnRpYWxfYXJ0c191bmlmb3JtJzonXFx1ZDgzZVxcdWRkNGInLFxuICAnbWFzayc6J1xcdWQ4M2RcXHVkZTM3JyxcbiAgJ21hc3NhZ2Vfd29tYW4nOidcXHVkODNkXFx1ZGM4NicsXG4gICdtYXNzYWdlX21hbic6J1xcdWQ4M2RcXHVkYzg2Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtZWF0X29uX2JvbmUnOidcXHVkODNjXFx1ZGY1NicsXG4gICdtZWRhbF9taWxpdGFyeSc6J1xcdWQ4M2NcXHVkZjk2JyxcbiAgJ21lZGFsX3Nwb3J0cyc6J1xcdWQ4M2NcXHVkZmM1JyxcbiAgJ21lZ2EnOidcXHVkODNkXFx1ZGNlMycsXG4gICdtZWxvbic6J1xcdWQ4M2NcXHVkZjQ4JyxcbiAgJ21lbW8nOidcXHVkODNkXFx1ZGNkZCcsXG4gICdtZW5fd3Jlc3RsaW5nJzonXFx1ZDgzZVxcdWRkM2MmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21lbm9yYWgnOidcXHVkODNkXFx1ZGQ0ZScsXG4gICdtZW5zJzonXFx1ZDgzZFxcdWRlYjknLFxuICAnbWV0YWwnOidcXHVkODNlXFx1ZGQxOCcsXG4gICdtZXRybyc6J1xcdWQ4M2RcXHVkZTg3JyxcbiAgJ21pY3JvcGhvbmUnOidcXHVkODNjXFx1ZGZhNCcsXG4gICdtaWNyb3Njb3BlJzonXFx1ZDgzZFxcdWRkMmMnLFxuICAnbWlsa19nbGFzcyc6J1xcdWQ4M2VcXHVkZDViJyxcbiAgJ21pbGt5X3dheSc6J1xcdWQ4M2NcXHVkZjBjJyxcbiAgJ21pbmlidXMnOidcXHVkODNkXFx1ZGU5MCcsXG4gICdtaW5pZGlzYyc6J1xcdWQ4M2RcXHVkY2JkJyxcbiAgJ21vYmlsZV9waG9uZV9vZmYnOidcXHVkODNkXFx1ZGNmNCcsXG4gICdtb25leV9tb3V0aF9mYWNlJzonXFx1ZDgzZVxcdWRkMTEnLFxuICAnbW9uZXlfd2l0aF93aW5ncyc6J1xcdWQ4M2RcXHVkY2I4JyxcbiAgJ21vbmV5YmFnJzonXFx1ZDgzZFxcdWRjYjAnLFxuICAnbW9ua2V5JzonXFx1ZDgzZFxcdWRjMTInLFxuICAnbW9ua2V5X2ZhY2UnOidcXHVkODNkXFx1ZGMzNScsXG4gICdtb25vcmFpbCc6J1xcdWQ4M2RcXHVkZTlkJyxcbiAgJ21vb24nOidcXHVkODNjXFx1ZGYxNCcsXG4gICdtb3J0YXJfYm9hcmQnOidcXHVkODNjXFx1ZGY5MycsXG4gICdtb3NxdWUnOidcXHVkODNkXFx1ZGQ0YycsXG4gICdtb3Rvcl9ib2F0JzonXFx1ZDgzZFxcdWRlZTUnLFxuICAnbW90b3Jfc2Nvb3Rlcic6J1xcdWQ4M2RcXHVkZWY1JyxcbiAgJ21vdG9yY3ljbGUnOidcXHVkODNjXFx1ZGZjZCcsXG4gICdtb3RvcndheSc6J1xcdWQ4M2RcXHVkZWUzJyxcbiAgJ21vdW50X2Z1amknOidcXHVkODNkXFx1ZGRmYicsXG4gICdtb3VudGFpbic6J1xcdTI2ZjAnLFxuICAnbW91bnRhaW5fYmlraW5nX21hbic6J1xcdWQ4M2RcXHVkZWI1JyxcbiAgJ21vdW50YWluX2Jpa2luZ193b21hbic6J1xcdWQ4M2RcXHVkZWI1Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdtb3VudGFpbl9jYWJsZXdheSc6J1xcdWQ4M2RcXHVkZWEwJyxcbiAgJ21vdW50YWluX3JhaWx3YXknOidcXHVkODNkXFx1ZGU5ZScsXG4gICdtb3VudGFpbl9zbm93JzonXFx1ZDgzY1xcdWRmZDQnLFxuICAnbW91c2UnOidcXHVkODNkXFx1ZGMyZCcsXG4gICdtb3VzZTInOidcXHVkODNkXFx1ZGMwMScsXG4gICdtb3ZpZV9jYW1lcmEnOidcXHVkODNjXFx1ZGZhNScsXG4gICdtb3lhaSc6J1xcdWQ4M2RcXHVkZGZmJyxcbiAgJ21yc19jbGF1cyc6J1xcdWQ4M2VcXHVkZDM2JyxcbiAgJ211c2NsZSc6J1xcdWQ4M2RcXHVkY2FhJyxcbiAgJ211c2hyb29tJzonXFx1ZDgzY1xcdWRmNDQnLFxuICAnbXVzaWNhbF9rZXlib2FyZCc6J1xcdWQ4M2NcXHVkZmI5JyxcbiAgJ211c2ljYWxfbm90ZSc6J1xcdWQ4M2NcXHVkZmI1JyxcbiAgJ211c2ljYWxfc2NvcmUnOidcXHVkODNjXFx1ZGZiYycsXG4gICdtdXRlJzonXFx1ZDgzZFxcdWRkMDcnLFxuICAnbmFpbF9jYXJlJzonXFx1ZDgzZFxcdWRjODUnLFxuICAnbmFtZV9iYWRnZSc6J1xcdWQ4M2RcXHVkY2RiJyxcbiAgJ25hdGlvbmFsX3BhcmsnOidcXHVkODNjXFx1ZGZkZScsXG4gICduYXVzZWF0ZWRfZmFjZSc6J1xcdWQ4M2VcXHVkZDIyJyxcbiAgJ25lY2t0aWUnOidcXHVkODNkXFx1ZGM1NCcsXG4gICduZWdhdGl2ZV9zcXVhcmVkX2Nyb3NzX21hcmsnOidcXHUyNzRlJyxcbiAgJ25lcmRfZmFjZSc6J1xcdWQ4M2VcXHVkZDEzJyxcbiAgJ25ldXRyYWxfZmFjZSc6J1xcdWQ4M2RcXHVkZTEwJyxcbiAgJ25ldyc6J1xcdWQ4M2NcXHVkZDk1JyxcbiAgJ25ld19tb29uJzonXFx1ZDgzY1xcdWRmMTEnLFxuICAnbmV3X21vb25fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWEnLFxuICAnbmV3c3BhcGVyJzonXFx1ZDgzZFxcdWRjZjAnLFxuICAnbmV3c3BhcGVyX3JvbGwnOidcXHVkODNkXFx1ZGRkZScsXG4gICduZXh0X3RyYWNrX2J1dHRvbic6J1xcdTIzZWQnLFxuICAnbmcnOidcXHVkODNjXFx1ZGQ5NicsXG4gICdub19nb29kX21hbic6J1xcdWQ4M2RcXHVkZTQ1Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdub19nb29kX3dvbWFuJzonXFx1ZDgzZFxcdWRlNDUnLFxuICAnbmlnaHRfd2l0aF9zdGFycyc6J1xcdWQ4M2NcXHVkZjAzJyxcbiAgJ25vX2JlbGwnOidcXHVkODNkXFx1ZGQxNScsXG4gICdub19iaWN5Y2xlcyc6J1xcdWQ4M2RcXHVkZWIzJyxcbiAgJ25vX2VudHJ5JzonXFx1MjZkNFxcdWZlMGYnLFxuICAnbm9fZW50cnlfc2lnbic6J1xcdWQ4M2RcXHVkZWFiJyxcbiAgJ25vX21vYmlsZV9waG9uZXMnOidcXHVkODNkXFx1ZGNmNScsXG4gICdub19tb3V0aCc6J1xcdWQ4M2RcXHVkZTM2JyxcbiAgJ25vX3BlZGVzdHJpYW5zJzonXFx1ZDgzZFxcdWRlYjcnLFxuICAnbm9fc21va2luZyc6J1xcdWQ4M2RcXHVkZWFkJyxcbiAgJ25vbi1wb3RhYmxlX3dhdGVyJzonXFx1ZDgzZFxcdWRlYjEnLFxuICAnbm9zZSc6J1xcdWQ4M2RcXHVkYzQzJyxcbiAgJ25vdGVib29rJzonXFx1ZDgzZFxcdWRjZDMnLFxuICAnbm90ZWJvb2tfd2l0aF9kZWNvcmF0aXZlX2NvdmVyJzonXFx1ZDgzZFxcdWRjZDQnLFxuICAnbm90ZXMnOidcXHVkODNjXFx1ZGZiNicsXG4gICdudXRfYW5kX2JvbHQnOidcXHVkODNkXFx1ZGQyOScsXG4gICdvJzonXFx1MmI1NVxcdWZlMGYnLFxuICAnbzInOidcXHVkODNjXFx1ZGQ3ZVxcdWZlMGYnLFxuICAnb2NlYW4nOidcXHVkODNjXFx1ZGYwYScsXG4gICdvY3RvcHVzJzonXFx1ZDgzZFxcdWRjMTknLFxuICAnb2Rlbic6J1xcdWQ4M2NcXHVkZjYyJyxcbiAgJ29mZmljZSc6J1xcdWQ4M2NcXHVkZmUyJyxcbiAgJ29pbF9kcnVtJzonXFx1ZDgzZFxcdWRlZTInLFxuICAnb2snOidcXHVkODNjXFx1ZGQ5NycsXG4gICdva19oYW5kJzonXFx1ZDgzZFxcdWRjNGMnLFxuICAnb2tfbWFuJzonXFx1ZDgzZFxcdWRlNDYmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ29rX3dvbWFuJzonXFx1ZDgzZFxcdWRlNDYnLFxuICAnb2xkX2tleSc6J1xcdWQ4M2RcXHVkZGRkJyxcbiAgJ29sZGVyX21hbic6J1xcdWQ4M2RcXHVkYzc0JyxcbiAgJ29sZGVyX3dvbWFuJzonXFx1ZDgzZFxcdWRjNzUnLFxuICAnb20nOidcXHVkODNkXFx1ZGQ0OScsXG4gICdvbic6J1xcdWQ4M2RcXHVkZDFiJyxcbiAgJ29uY29taW5nX2F1dG9tb2JpbGUnOidcXHVkODNkXFx1ZGU5OCcsXG4gICdvbmNvbWluZ19idXMnOidcXHVkODNkXFx1ZGU4ZCcsXG4gICdvbmNvbWluZ19wb2xpY2VfY2FyJzonXFx1ZDgzZFxcdWRlOTQnLFxuICAnb25jb21pbmdfdGF4aSc6J1xcdWQ4M2RcXHVkZTk2JyxcbiAgJ29wZW5fZmlsZV9mb2xkZXInOidcXHVkODNkXFx1ZGNjMicsXG4gICdvcGVuX2hhbmRzJzonXFx1ZDgzZFxcdWRjNTAnLFxuICAnb3Blbl9tb3V0aCc6J1xcdWQ4M2RcXHVkZTJlJyxcbiAgJ29wZW5fdW1icmVsbGEnOidcXHUyNjAyXFx1ZmUwZicsXG4gICdvcGhpdWNodXMnOidcXHUyNmNlJyxcbiAgJ29yYW5nZV9ib29rJzonXFx1ZDgzZFxcdWRjZDknLFxuICAnb3J0aG9kb3hfY3Jvc3MnOidcXHUyNjI2XFx1ZmUwZicsXG4gICdvdXRib3hfdHJheSc6J1xcdWQ4M2RcXHVkY2U0JyxcbiAgJ293bCc6J1xcdWQ4M2VcXHVkZDg5JyxcbiAgJ294JzonXFx1ZDgzZFxcdWRjMDInLFxuICAncGFja2FnZSc6J1xcdWQ4M2RcXHVkY2U2JyxcbiAgJ3BhZ2VfZmFjaW5nX3VwJzonXFx1ZDgzZFxcdWRjYzQnLFxuICAncGFnZV93aXRoX2N1cmwnOidcXHVkODNkXFx1ZGNjMycsXG4gICdwYWdlcic6J1xcdWQ4M2RcXHVkY2RmJyxcbiAgJ3BhaW50YnJ1c2gnOidcXHVkODNkXFx1ZGQ4YycsXG4gICdwYWxtX3RyZWUnOidcXHVkODNjXFx1ZGYzNCcsXG4gICdwYW5jYWtlcyc6J1xcdWQ4M2VcXHVkZDVlJyxcbiAgJ3BhbmRhX2ZhY2UnOidcXHVkODNkXFx1ZGMzYycsXG4gICdwYXBlcmNsaXAnOidcXHVkODNkXFx1ZGNjZScsXG4gICdwYXBlcmNsaXBzJzonXFx1ZDgzZFxcdWRkODcnLFxuICAncGFyYXNvbF9vbl9ncm91bmQnOidcXHUyNmYxJyxcbiAgJ3BhcmtpbmcnOidcXHVkODNjXFx1ZGQ3ZlxcdWZlMGYnLFxuICAncGFydF9hbHRlcm5hdGlvbl9tYXJrJzonXFx1MzAzZFxcdWZlMGYnLFxuICAncGFydGx5X3N1bm55JzonXFx1MjZjNVxcdWZlMGYnLFxuICAncGFzc2VuZ2VyX3NoaXAnOidcXHVkODNkXFx1ZGVmMycsXG4gICdwYXNzcG9ydF9jb250cm9sJzonXFx1ZDgzZFxcdWRlYzInLFxuICAncGF1c2VfYnV0dG9uJzonXFx1MjNmOCcsXG4gICdwZWFjZV9zeW1ib2wnOidcXHUyNjJlXFx1ZmUwZicsXG4gICdwZWFjaCc6J1xcdWQ4M2NcXHVkZjUxJyxcbiAgJ3BlYW51dHMnOidcXHVkODNlXFx1ZGQ1YycsXG4gICdwZWFyJzonXFx1ZDgzY1xcdWRmNTAnLFxuICAncGVuJzonXFx1ZDgzZFxcdWRkOGEnLFxuICAncGVuY2lsMic6J1xcdTI3MGZcXHVmZTBmJyxcbiAgJ3Blbmd1aW4nOidcXHVkODNkXFx1ZGMyNycsXG4gICdwZW5zaXZlJzonXFx1ZDgzZFxcdWRlMTQnLFxuICAncGVyZm9ybWluZ19hcnRzJzonXFx1ZDgzY1xcdWRmYWQnLFxuICAncGVyc2V2ZXJlJzonXFx1ZDgzZFxcdWRlMjMnLFxuICAncGVyc29uX2ZlbmNpbmcnOidcXHVkODNlXFx1ZGQzYScsXG4gICdwb3V0aW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlNGUnLFxuICAncGhvbmUnOidcXHUyNjBlXFx1ZmUwZicsXG4gICdwaWNrJzonXFx1MjZjZicsXG4gICdwaWcnOidcXHVkODNkXFx1ZGMzNycsXG4gICdwaWcyJzonXFx1ZDgzZFxcdWRjMTYnLFxuICAncGlnX25vc2UnOidcXHVkODNkXFx1ZGMzZCcsXG4gICdwaWxsJzonXFx1ZDgzZFxcdWRjOGEnLFxuICAncGluZWFwcGxlJzonXFx1ZDgzY1xcdWRmNGQnLFxuICAncGluZ19wb25nJzonXFx1ZDgzY1xcdWRmZDMnLFxuICAncGlzY2VzJzonXFx1MjY1M1xcdWZlMGYnLFxuICAncGl6emEnOidcXHVkODNjXFx1ZGY1NScsXG4gICdwbGFjZV9vZl93b3JzaGlwJzonXFx1ZDgzZFxcdWRlZDAnLFxuICAncGxhdGVfd2l0aF9jdXRsZXJ5JzonXFx1ZDgzY1xcdWRmN2QnLFxuICAncGxheV9vcl9wYXVzZV9idXR0b24nOidcXHUyM2VmJyxcbiAgJ3BvaW50X2Rvd24nOidcXHVkODNkXFx1ZGM0NycsXG4gICdwb2ludF9sZWZ0JzonXFx1ZDgzZFxcdWRjNDgnLFxuICAncG9pbnRfcmlnaHQnOidcXHVkODNkXFx1ZGM0OScsXG4gICdwb2ludF91cCc6J1xcdTI2MWRcXHVmZTBmJyxcbiAgJ3BvaW50X3VwXzInOidcXHVkODNkXFx1ZGM0NicsXG4gICdwb2xpY2VfY2FyJzonXFx1ZDgzZFxcdWRlOTMnLFxuICAncG9saWNld29tYW4nOidcXHVkODNkXFx1ZGM2ZSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAncG9vZGxlJzonXFx1ZDgzZFxcdWRjMjknLFxuICAncG9wY29ybic6J1xcdWQ4M2NcXHVkZjdmJyxcbiAgJ3Bvc3Rfb2ZmaWNlJzonXFx1ZDgzY1xcdWRmZTMnLFxuICAncG9zdGFsX2hvcm4nOidcXHVkODNkXFx1ZGNlZicsXG4gICdwb3N0Ym94JzonXFx1ZDgzZFxcdWRjZWUnLFxuICAncG90YWJsZV93YXRlcic6J1xcdWQ4M2RcXHVkZWIwJyxcbiAgJ3BvdGF0byc6J1xcdWQ4M2VcXHVkZDU0JyxcbiAgJ3BvdWNoJzonXFx1ZDgzZFxcdWRjNWQnLFxuICAncG91bHRyeV9sZWcnOidcXHVkODNjXFx1ZGY1NycsXG4gICdwb3VuZCc6J1xcdWQ4M2RcXHVkY2I3JyxcbiAgJ3JhZ2UnOidcXHVkODNkXFx1ZGUyMScsXG4gICdwb3V0aW5nX2NhdCc6J1xcdWQ4M2RcXHVkZTNlJyxcbiAgJ3BvdXRpbmdfbWFuJzonXFx1ZDgzZFxcdWRlNGUmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ3ByYXknOidcXHVkODNkXFx1ZGU0ZicsXG4gICdwcmF5ZXJfYmVhZHMnOidcXHVkODNkXFx1ZGNmZicsXG4gICdwcmVnbmFudF93b21hbic6J1xcdWQ4M2VcXHVkZDMwJyxcbiAgJ3ByZXZpb3VzX3RyYWNrX2J1dHRvbic6J1xcdTIzZWUnLFxuICAncHJpbmNlJzonXFx1ZDgzZVxcdWRkMzQnLFxuICAncHJpbmNlc3MnOidcXHVkODNkXFx1ZGM3OCcsXG4gICdwcmludGVyJzonXFx1ZDgzZFxcdWRkYTgnLFxuICAncHVycGxlX2hlYXJ0JzonXFx1ZDgzZFxcdWRjOWMnLFxuICAncHVyc2UnOidcXHVkODNkXFx1ZGM1YicsXG4gICdwdXNocGluJzonXFx1ZDgzZFxcdWRjY2MnLFxuICAncHV0X2xpdHRlcl9pbl9pdHNfcGxhY2UnOidcXHVkODNkXFx1ZGVhZScsXG4gICdxdWVzdGlvbic6J1xcdTI3NTMnLFxuICAncmFiYml0JzonXFx1ZDgzZFxcdWRjMzAnLFxuICAncmFiYml0Mic6J1xcdWQ4M2RcXHVkYzA3JyxcbiAgJ3JhY2Vob3JzZSc6J1xcdWQ4M2RcXHVkYzBlJyxcbiAgJ3JhY2luZ19jYXInOidcXHVkODNjXFx1ZGZjZScsXG4gICdyYWRpbyc6J1xcdWQ4M2RcXHVkY2ZiJyxcbiAgJ3JhZGlvX2J1dHRvbic6J1xcdWQ4M2RcXHVkZDE4JyxcbiAgJ3JhZGlvYWN0aXZlJzonXFx1MjYyMlxcdWZlMGYnLFxuICAncmFpbHdheV9jYXInOidcXHVkODNkXFx1ZGU4MycsXG4gICdyYWlsd2F5X3RyYWNrJzonXFx1ZDgzZFxcdWRlZTQnLFxuICAncmFpbmJvdyc6J1xcdWQ4M2NcXHVkZjA4JyxcbiAgJ3JhaW5ib3dfZmxhZyc6J1xcdWQ4M2NcXHVkZmYzXFx1ZmUwZiZ6d2o7XFx1ZDgzY1xcdWRmMDgnLFxuICAncmFpc2VkX2JhY2tfb2ZfaGFuZCc6J1xcdWQ4M2VcXHVkZDFhJyxcbiAgJ3JhaXNlZF9oYW5kX3dpdGhfZmluZ2Vyc19zcGxheWVkJzonXFx1ZDgzZFxcdWRkOTAnLFxuICAncmFpc2VkX2hhbmRzJzonXFx1ZDgzZFxcdWRlNGMnLFxuICAncmFpc2luZ19oYW5kX3dvbWFuJzonXFx1ZDgzZFxcdWRlNGInLFxuICAncmFpc2luZ19oYW5kX21hbic6J1xcdWQ4M2RcXHVkZTRiJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdyYW0nOidcXHVkODNkXFx1ZGMwZicsXG4gICdyYW1lbic6J1xcdWQ4M2NcXHVkZjVjJyxcbiAgJ3JhdCc6J1xcdWQ4M2RcXHVkYzAwJyxcbiAgJ3JlY29yZF9idXR0b24nOidcXHUyM2ZhJyxcbiAgJ3JlY3ljbGUnOidcXHUyNjdiXFx1ZmUwZicsXG4gICdyZWRfY2lyY2xlJzonXFx1ZDgzZFxcdWRkMzQnLFxuICAncmVnaXN0ZXJlZCc6J1xcdTAwYWVcXHVmZTBmJyxcbiAgJ3JlbGF4ZWQnOidcXHUyNjNhXFx1ZmUwZicsXG4gICdyZWxpZXZlZCc6J1xcdWQ4M2RcXHVkZTBjJyxcbiAgJ3JlbWluZGVyX3JpYmJvbic6J1xcdWQ4M2NcXHVkZjk3JyxcbiAgJ3JlcGVhdCc6J1xcdWQ4M2RcXHVkZDAxJyxcbiAgJ3JlcGVhdF9vbmUnOidcXHVkODNkXFx1ZGQwMicsXG4gICdyZXNjdWVfd29ya2VyX2hlbG1ldCc6J1xcdTI2ZDEnLFxuICAncmVzdHJvb20nOidcXHVkODNkXFx1ZGViYicsXG4gICdyZXZvbHZpbmdfaGVhcnRzJzonXFx1ZDgzZFxcdWRjOWUnLFxuICAncmV3aW5kJzonXFx1MjNlYScsXG4gICdyaGlub2Nlcm9zJzonXFx1ZDgzZVxcdWRkOGYnLFxuICAncmliYm9uJzonXFx1ZDgzY1xcdWRmODAnLFxuICAncmljZSc6J1xcdWQ4M2NcXHVkZjVhJyxcbiAgJ3JpY2VfYmFsbCc6J1xcdWQ4M2NcXHVkZjU5JyxcbiAgJ3JpY2VfY3JhY2tlcic6J1xcdWQ4M2NcXHVkZjU4JyxcbiAgJ3JpY2Vfc2NlbmUnOidcXHVkODNjXFx1ZGY5MScsXG4gICdyaWdodF9hbmdlcl9idWJibGUnOidcXHVkODNkXFx1ZGRlZicsXG4gICdyaW5nJzonXFx1ZDgzZFxcdWRjOGQnLFxuICAncm9ib3QnOidcXHVkODNlXFx1ZGQxNicsXG4gICdyb2NrZXQnOidcXHVkODNkXFx1ZGU4MCcsXG4gICdyb2ZsJzonXFx1ZDgzZVxcdWRkMjMnLFxuICAncm9sbF9leWVzJzonXFx1ZDgzZFxcdWRlNDQnLFxuICAncm9sbGVyX2NvYXN0ZXInOidcXHVkODNjXFx1ZGZhMicsXG4gICdyb29zdGVyJzonXFx1ZDgzZFxcdWRjMTMnLFxuICAncm9zZSc6J1xcdWQ4M2NcXHVkZjM5JyxcbiAgJ3Jvc2V0dGUnOidcXHVkODNjXFx1ZGZmNScsXG4gICdyb3RhdGluZ19saWdodCc6J1xcdWQ4M2RcXHVkZWE4JyxcbiAgJ3JvdW5kX3B1c2hwaW4nOidcXHVkODNkXFx1ZGNjZCcsXG4gICdyb3dpbmdfbWFuJzonXFx1ZDgzZFxcdWRlYTMnLFxuICAncm93aW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlYTMmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3J1Z2J5X2Zvb3RiYWxsJzonXFx1ZDgzY1xcdWRmYzknLFxuICAncnVubmluZ19tYW4nOidcXHVkODNjXFx1ZGZjMycsXG4gICdydW5uaW5nX3NoaXJ0X3dpdGhfc2FzaCc6J1xcdWQ4M2NcXHVkZmJkJyxcbiAgJ3J1bm5pbmdfd29tYW4nOidcXHVkODNjXFx1ZGZjMyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnc2EnOidcXHVkODNjXFx1ZGUwMlxcdWZlMGYnLFxuICAnc2FnaXR0YXJpdXMnOidcXHUyNjUwXFx1ZmUwZicsXG4gICdzYWtlJzonXFx1ZDgzY1xcdWRmNzYnLFxuICAnc2FuZGFsJzonXFx1ZDgzZFxcdWRjNjEnLFxuICAnc2FudGEnOidcXHVkODNjXFx1ZGY4NScsXG4gICdzYXRlbGxpdGUnOidcXHVkODNkXFx1ZGNlMScsXG4gICdzYXhvcGhvbmUnOidcXHVkODNjXFx1ZGZiNycsXG4gICdzY2hvb2wnOidcXHVkODNjXFx1ZGZlYicsXG4gICdzY2hvb2xfc2F0Y2hlbCc6J1xcdWQ4M2NcXHVkZjkyJyxcbiAgJ3NjaXNzb3JzJzonXFx1MjcwMlxcdWZlMGYnLFxuICAnc2NvcnBpb24nOidcXHVkODNlXFx1ZGQ4MicsXG4gICdzY29ycGl1cyc6J1xcdTI2NGZcXHVmZTBmJyxcbiAgJ3NjcmVhbSc6J1xcdWQ4M2RcXHVkZTMxJyxcbiAgJ3NjcmVhbV9jYXQnOidcXHVkODNkXFx1ZGU0MCcsXG4gICdzY3JvbGwnOidcXHVkODNkXFx1ZGNkYycsXG4gICdzZWF0JzonXFx1ZDgzZFxcdWRjYmEnLFxuICAnc2VjcmV0JzonXFx1MzI5OVxcdWZlMGYnLFxuICAnc2VlX25vX2V2aWwnOidcXHVkODNkXFx1ZGU0OCcsXG4gICdzZWVkbGluZyc6J1xcdWQ4M2NcXHVkZjMxJyxcbiAgJ3NlbGZpZSc6J1xcdWQ4M2VcXHVkZDMzJyxcbiAgJ3NoYWxsb3dfcGFuX29mX2Zvb2QnOidcXHVkODNlXFx1ZGQ1OCcsXG4gICdzaGFtcm9jayc6J1xcdTI2MThcXHVmZTBmJyxcbiAgJ3NoYXJrJzonXFx1ZDgzZVxcdWRkODgnLFxuICAnc2hhdmVkX2ljZSc6J1xcdWQ4M2NcXHVkZjY3JyxcbiAgJ3NoZWVwJzonXFx1ZDgzZFxcdWRjMTEnLFxuICAnc2hlbGwnOidcXHVkODNkXFx1ZGMxYScsXG4gICdzaGllbGQnOidcXHVkODNkXFx1ZGVlMScsXG4gICdzaGludG9fc2hyaW5lJzonXFx1MjZlOScsXG4gICdzaGlwJzonXFx1ZDgzZFxcdWRlYTInLFxuICAnc2hpcnQnOidcXHVkODNkXFx1ZGM1NScsXG4gICdzaG9wcGluZyc6J1xcdWQ4M2RcXHVkZWNkJyxcbiAgJ3Nob3BwaW5nX2NhcnQnOidcXHVkODNkXFx1ZGVkMicsXG4gICdzaG93ZXInOidcXHVkODNkXFx1ZGViZicsXG4gICdzaHJpbXAnOidcXHVkODNlXFx1ZGQ5MCcsXG4gICdzaWduYWxfc3RyZW5ndGgnOidcXHVkODNkXFx1ZGNmNicsXG4gICdzaXhfcG9pbnRlZF9zdGFyJzonXFx1ZDgzZFxcdWRkMmYnLFxuICAnc2tpJzonXFx1ZDgzY1xcdWRmYmYnLFxuICAnc2tpZXInOidcXHUyNmY3JyxcbiAgJ3NrdWxsJzonXFx1ZDgzZFxcdWRjODAnLFxuICAnc2t1bGxfYW5kX2Nyb3NzYm9uZXMnOidcXHUyNjIwXFx1ZmUwZicsXG4gICdzbGVlcGluZyc6J1xcdWQ4M2RcXHVkZTM0JyxcbiAgJ3NsZWVwaW5nX2JlZCc6J1xcdWQ4M2RcXHVkZWNjJyxcbiAgJ3NsZWVweSc6J1xcdWQ4M2RcXHVkZTJhJyxcbiAgJ3NsaWdodGx5X2Zyb3duaW5nX2ZhY2UnOidcXHVkODNkXFx1ZGU0MScsXG4gICdzbGlnaHRseV9zbWlsaW5nX2ZhY2UnOidcXHVkODNkXFx1ZGU0MicsXG4gICdzbG90X21hY2hpbmUnOidcXHVkODNjXFx1ZGZiMCcsXG4gICdzbWFsbF9haXJwbGFuZSc6J1xcdWQ4M2RcXHVkZWU5JyxcbiAgJ3NtYWxsX2JsdWVfZGlhbW9uZCc6J1xcdWQ4M2RcXHVkZDM5JyxcbiAgJ3NtYWxsX29yYW5nZV9kaWFtb25kJzonXFx1ZDgzZFxcdWRkMzgnLFxuICAnc21hbGxfcmVkX3RyaWFuZ2xlJzonXFx1ZDgzZFxcdWRkM2EnLFxuICAnc21hbGxfcmVkX3RyaWFuZ2xlX2Rvd24nOidcXHVkODNkXFx1ZGQzYicsXG4gICdzbWlsZSc6J1xcdWQ4M2RcXHVkZTA0JyxcbiAgJ3NtaWxlX2NhdCc6J1xcdWQ4M2RcXHVkZTM4JyxcbiAgJ3NtaWxleSc6J1xcdWQ4M2RcXHVkZTAzJyxcbiAgJ3NtaWxleV9jYXQnOidcXHVkODNkXFx1ZGUzYScsXG4gICdzbWlsaW5nX2ltcCc6J1xcdWQ4M2RcXHVkZTA4JyxcbiAgJ3NtaXJrJzonXFx1ZDgzZFxcdWRlMGYnLFxuICAnc21pcmtfY2F0JzonXFx1ZDgzZFxcdWRlM2MnLFxuICAnc21va2luZyc6J1xcdWQ4M2RcXHVkZWFjJyxcbiAgJ3NuYWlsJzonXFx1ZDgzZFxcdWRjMGMnLFxuICAnc25ha2UnOidcXHVkODNkXFx1ZGMwZCcsXG4gICdzbmVlemluZ19mYWNlJzonXFx1ZDgzZVxcdWRkMjcnLFxuICAnc25vd2JvYXJkZXInOidcXHVkODNjXFx1ZGZjMicsXG4gICdzbm93Zmxha2UnOidcXHUyNzQ0XFx1ZmUwZicsXG4gICdzbm93bWFuJzonXFx1MjZjNFxcdWZlMGYnLFxuICAnc25vd21hbl93aXRoX3Nub3cnOidcXHUyNjAzXFx1ZmUwZicsXG4gICdzb2InOidcXHVkODNkXFx1ZGUyZCcsXG4gICdzb2NjZXInOidcXHUyNmJkXFx1ZmUwZicsXG4gICdzb29uJzonXFx1ZDgzZFxcdWRkMWMnLFxuICAnc29zJzonXFx1ZDgzY1xcdWRkOTgnLFxuICAnc291bmQnOidcXHVkODNkXFx1ZGQwOScsXG4gICdzcGFjZV9pbnZhZGVyJzonXFx1ZDgzZFxcdWRjN2UnLFxuICAnc3BhZGVzJzonXFx1MjY2MFxcdWZlMGYnLFxuICAnc3BhZ2hldHRpJzonXFx1ZDgzY1xcdWRmNWQnLFxuICAnc3BhcmtsZSc6J1xcdTI3NDdcXHVmZTBmJyxcbiAgJ3NwYXJrbGVyJzonXFx1ZDgzY1xcdWRmODcnLFxuICAnc3BhcmtsZXMnOidcXHUyNzI4JyxcbiAgJ3NwYXJrbGluZ19oZWFydCc6J1xcdWQ4M2RcXHVkYzk2JyxcbiAgJ3NwZWFrX25vX2V2aWwnOidcXHVkODNkXFx1ZGU0YScsXG4gICdzcGVha2VyJzonXFx1ZDgzZFxcdWRkMDgnLFxuICAnc3BlYWtpbmdfaGVhZCc6J1xcdWQ4M2RcXHVkZGUzJyxcbiAgJ3NwZWVjaF9iYWxsb29uJzonXFx1ZDgzZFxcdWRjYWMnLFxuICAnc3BlZWRib2F0JzonXFx1ZDgzZFxcdWRlYTQnLFxuICAnc3BpZGVyJzonXFx1ZDgzZFxcdWRkNzcnLFxuICAnc3BpZGVyX3dlYic6J1xcdWQ4M2RcXHVkZDc4JyxcbiAgJ3NwaXJhbF9jYWxlbmRhcic6J1xcdWQ4M2RcXHVkZGQzJyxcbiAgJ3NwaXJhbF9ub3RlcGFkJzonXFx1ZDgzZFxcdWRkZDInLFxuICAnc3Bvb24nOidcXHVkODNlXFx1ZGQ0NCcsXG4gICdzcXVpZCc6J1xcdWQ4M2VcXHVkZDkxJyxcbiAgJ3N0YWRpdW0nOidcXHVkODNjXFx1ZGZkZicsXG4gICdzdGFyJzonXFx1MmI1MFxcdWZlMGYnLFxuICAnc3RhcjInOidcXHVkODNjXFx1ZGYxZicsXG4gICdzdGFyX2FuZF9jcmVzY2VudCc6J1xcdTI2MmFcXHVmZTBmJyxcbiAgJ3N0YXJfb2ZfZGF2aWQnOidcXHUyNzIxXFx1ZmUwZicsXG4gICdzdGFycyc6J1xcdWQ4M2NcXHVkZjIwJyxcbiAgJ3N0YXRpb24nOidcXHVkODNkXFx1ZGU4OScsXG4gICdzdGF0dWVfb2ZfbGliZXJ0eSc6J1xcdWQ4M2RcXHVkZGZkJyxcbiAgJ3N0ZWFtX2xvY29tb3RpdmUnOidcXHVkODNkXFx1ZGU4MicsXG4gICdzdGV3JzonXFx1ZDgzY1xcdWRmNzInLFxuICAnc3RvcF9idXR0b24nOidcXHUyM2Y5JyxcbiAgJ3N0b3Bfc2lnbic6J1xcdWQ4M2RcXHVkZWQxJyxcbiAgJ3N0b3B3YXRjaCc6J1xcdTIzZjEnLFxuICAnc3RyYWlnaHRfcnVsZXInOidcXHVkODNkXFx1ZGNjZicsXG4gICdzdHJhd2JlcnJ5JzonXFx1ZDgzY1xcdWRmNTMnLFxuICAnc3R1Y2tfb3V0X3Rvbmd1ZSc6J1xcdWQ4M2RcXHVkZTFiJyxcbiAgJ3N0dWNrX291dF90b25ndWVfY2xvc2VkX2V5ZXMnOidcXHVkODNkXFx1ZGUxZCcsXG4gICdzdHVja19vdXRfdG9uZ3VlX3dpbmtpbmdfZXllJzonXFx1ZDgzZFxcdWRlMWMnLFxuICAnc3R1ZGlvX21pY3JvcGhvbmUnOidcXHVkODNjXFx1ZGY5OScsXG4gICdzdHVmZmVkX2ZsYXRicmVhZCc6J1xcdWQ4M2VcXHVkZDU5JyxcbiAgJ3N1bl9iZWhpbmRfbGFyZ2VfY2xvdWQnOidcXHVkODNjXFx1ZGYyNScsXG4gICdzdW5fYmVoaW5kX3JhaW5fY2xvdWQnOidcXHVkODNjXFx1ZGYyNicsXG4gICdzdW5fYmVoaW5kX3NtYWxsX2Nsb3VkJzonXFx1ZDgzY1xcdWRmMjQnLFxuICAnc3VuX3dpdGhfZmFjZSc6J1xcdWQ4M2NcXHVkZjFlJyxcbiAgJ3N1bmZsb3dlcic6J1xcdWQ4M2NcXHVkZjNiJyxcbiAgJ3N1bmdsYXNzZXMnOidcXHVkODNkXFx1ZGUwZScsXG4gICdzdW5ueSc6J1xcdTI2MDBcXHVmZTBmJyxcbiAgJ3N1bnJpc2UnOidcXHVkODNjXFx1ZGYwNScsXG4gICdzdW5yaXNlX292ZXJfbW91bnRhaW5zJzonXFx1ZDgzY1xcdWRmMDQnLFxuICAnc3VyZmluZ19tYW4nOidcXHVkODNjXFx1ZGZjNCcsXG4gICdzdXJmaW5nX3dvbWFuJzonXFx1ZDgzY1xcdWRmYzQmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3N1c2hpJzonXFx1ZDgzY1xcdWRmNjMnLFxuICAnc3VzcGVuc2lvbl9yYWlsd2F5JzonXFx1ZDgzZFxcdWRlOWYnLFxuICAnc3dlYXQnOidcXHVkODNkXFx1ZGUxMycsXG4gICdzd2VhdF9kcm9wcyc6J1xcdWQ4M2RcXHVkY2E2JyxcbiAgJ3N3ZWF0X3NtaWxlJzonXFx1ZDgzZFxcdWRlMDUnLFxuICAnc3dlZXRfcG90YXRvJzonXFx1ZDgzY1xcdWRmNjAnLFxuICAnc3dpbW1pbmdfbWFuJzonXFx1ZDgzY1xcdWRmY2EnLFxuICAnc3dpbW1pbmdfd29tYW4nOidcXHVkODNjXFx1ZGZjYSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnc3ltYm9scyc6J1xcdWQ4M2RcXHVkZDIzJyxcbiAgJ3N5bmFnb2d1ZSc6J1xcdWQ4M2RcXHVkZDRkJyxcbiAgJ3N5cmluZ2UnOidcXHVkODNkXFx1ZGM4OScsXG4gICd0YWNvJzonXFx1ZDgzY1xcdWRmMmUnLFxuICAndGFkYSc6J1xcdWQ4M2NcXHVkZjg5JyxcbiAgJ3RhbmFiYXRhX3RyZWUnOidcXHVkODNjXFx1ZGY4YicsXG4gICd0YXVydXMnOidcXHUyNjQ5XFx1ZmUwZicsXG4gICd0YXhpJzonXFx1ZDgzZFxcdWRlOTUnLFxuICAndGVhJzonXFx1ZDgzY1xcdWRmNzUnLFxuICAndGVsZXBob25lX3JlY2VpdmVyJzonXFx1ZDgzZFxcdWRjZGUnLFxuICAndGVsZXNjb3BlJzonXFx1ZDgzZFxcdWRkMmQnLFxuICAndGVubmlzJzonXFx1ZDgzY1xcdWRmYmUnLFxuICAndGVudCc6J1xcdTI2ZmFcXHVmZTBmJyxcbiAgJ3RoZXJtb21ldGVyJzonXFx1ZDgzY1xcdWRmMjEnLFxuICAndGhpbmtpbmcnOidcXHVkODNlXFx1ZGQxNCcsXG4gICd0aG91Z2h0X2JhbGxvb24nOidcXHVkODNkXFx1ZGNhZCcsXG4gICd0aWNrZXQnOidcXHVkODNjXFx1ZGZhYicsXG4gICd0aWNrZXRzJzonXFx1ZDgzY1xcdWRmOWYnLFxuICAndGlnZXInOidcXHVkODNkXFx1ZGMyZicsXG4gICd0aWdlcjInOidcXHVkODNkXFx1ZGMwNScsXG4gICd0aW1lcl9jbG9jayc6J1xcdTIzZjInLFxuICAndGlwcGluZ19oYW5kX21hbic6J1xcdWQ4M2RcXHVkYzgxJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICd0aXJlZF9mYWNlJzonXFx1ZDgzZFxcdWRlMmInLFxuICAndG0nOidcXHUyMTIyXFx1ZmUwZicsXG4gICd0b2lsZXQnOidcXHVkODNkXFx1ZGViZCcsXG4gICd0b2t5b190b3dlcic6J1xcdWQ4M2RcXHVkZGZjJyxcbiAgJ3RvbWF0byc6J1xcdWQ4M2NcXHVkZjQ1JyxcbiAgJ3Rvbmd1ZSc6J1xcdWQ4M2RcXHVkYzQ1JyxcbiAgJ3RvcCc6J1xcdWQ4M2RcXHVkZDFkJyxcbiAgJ3RvcGhhdCc6J1xcdWQ4M2NcXHVkZmE5JyxcbiAgJ3Rvcm5hZG8nOidcXHVkODNjXFx1ZGYyYScsXG4gICd0cmFja2JhbGwnOidcXHVkODNkXFx1ZGRiMicsXG4gICd0cmFjdG9yJzonXFx1ZDgzZFxcdWRlOWMnLFxuICAndHJhZmZpY19saWdodCc6J1xcdWQ4M2RcXHVkZWE1JyxcbiAgJ3RyYWluJzonXFx1ZDgzZFxcdWRlOGInLFxuICAndHJhaW4yJzonXFx1ZDgzZFxcdWRlODYnLFxuICAndHJhbSc6J1xcdWQ4M2RcXHVkZThhJyxcbiAgJ3RyaWFuZ3VsYXJfZmxhZ19vbl9wb3N0JzonXFx1ZDgzZFxcdWRlYTknLFxuICAndHJpYW5ndWxhcl9ydWxlcic6J1xcdWQ4M2RcXHVkY2QwJyxcbiAgJ3RyaWRlbnQnOidcXHVkODNkXFx1ZGQzMScsXG4gICd0cml1bXBoJzonXFx1ZDgzZFxcdWRlMjQnLFxuICAndHJvbGxleWJ1cyc6J1xcdWQ4M2RcXHVkZThlJyxcbiAgJ3Ryb3BoeSc6J1xcdWQ4M2NcXHVkZmM2JyxcbiAgJ3Ryb3BpY2FsX2RyaW5rJzonXFx1ZDgzY1xcdWRmNzknLFxuICAndHJvcGljYWxfZmlzaCc6J1xcdWQ4M2RcXHVkYzIwJyxcbiAgJ3RydWNrJzonXFx1ZDgzZFxcdWRlOWEnLFxuICAndHJ1bXBldCc6J1xcdWQ4M2NcXHVkZmJhJyxcbiAgJ3R1bGlwJzonXFx1ZDgzY1xcdWRmMzcnLFxuICAndHVtYmxlcl9nbGFzcyc6J1xcdWQ4M2VcXHVkZDQzJyxcbiAgJ3R1cmtleSc6J1xcdWQ4M2VcXHVkZDgzJyxcbiAgJ3R1cnRsZSc6J1xcdWQ4M2RcXHVkYzIyJyxcbiAgJ3R2JzonXFx1ZDgzZFxcdWRjZmEnLFxuICAndHdpc3RlZF9yaWdodHdhcmRzX2Fycm93cyc6J1xcdWQ4M2RcXHVkZDAwJyxcbiAgJ3R3b19oZWFydHMnOidcXHVkODNkXFx1ZGM5NScsXG4gICd0d29fbWVuX2hvbGRpbmdfaGFuZHMnOidcXHVkODNkXFx1ZGM2YycsXG4gICd0d29fd29tZW5faG9sZGluZ19oYW5kcyc6J1xcdWQ4M2RcXHVkYzZkJyxcbiAgJ3U1MjcyJzonXFx1ZDgzY1xcdWRlMzknLFxuICAndTU0MDgnOidcXHVkODNjXFx1ZGUzNCcsXG4gICd1NTViNic6J1xcdWQ4M2NcXHVkZTNhJyxcbiAgJ3U2MzA3JzonXFx1ZDgzY1xcdWRlMmZcXHVmZTBmJyxcbiAgJ3U2NzA4JzonXFx1ZDgzY1xcdWRlMzdcXHVmZTBmJyxcbiAgJ3U2NzA5JzonXFx1ZDgzY1xcdWRlMzYnLFxuICAndTZlODAnOidcXHVkODNjXFx1ZGUzNScsXG4gICd1NzEyMSc6J1xcdWQ4M2NcXHVkZTFhXFx1ZmUwZicsXG4gICd1NzUzMyc6J1xcdWQ4M2NcXHVkZTM4JyxcbiAgJ3U3OTgxJzonXFx1ZDgzY1xcdWRlMzInLFxuICAndTdhN2EnOidcXHVkODNjXFx1ZGUzMycsXG4gICd1bWJyZWxsYSc6J1xcdTI2MTRcXHVmZTBmJyxcbiAgJ3VuYW11c2VkJzonXFx1ZDgzZFxcdWRlMTInLFxuICAndW5kZXJhZ2UnOidcXHVkODNkXFx1ZGQxZScsXG4gICd1bmljb3JuJzonXFx1ZDgzZVxcdWRkODQnLFxuICAndW5sb2NrJzonXFx1ZDgzZFxcdWRkMTMnLFxuICAndXAnOidcXHVkODNjXFx1ZGQ5OScsXG4gICd1cHNpZGVfZG93bl9mYWNlJzonXFx1ZDgzZFxcdWRlNDMnLFxuICAndic6J1xcdTI3MGNcXHVmZTBmJyxcbiAgJ3ZlcnRpY2FsX3RyYWZmaWNfbGlnaHQnOidcXHVkODNkXFx1ZGVhNicsXG4gICd2aHMnOidcXHVkODNkXFx1ZGNmYycsXG4gICd2aWJyYXRpb25fbW9kZSc6J1xcdWQ4M2RcXHVkY2YzJyxcbiAgJ3ZpZGVvX2NhbWVyYSc6J1xcdWQ4M2RcXHVkY2Y5JyxcbiAgJ3ZpZGVvX2dhbWUnOidcXHVkODNjXFx1ZGZhZScsXG4gICd2aW9saW4nOidcXHVkODNjXFx1ZGZiYicsXG4gICd2aXJnbyc6J1xcdTI2NGRcXHVmZTBmJyxcbiAgJ3ZvbGNhbm8nOidcXHVkODNjXFx1ZGYwYicsXG4gICd2b2xsZXliYWxsJzonXFx1ZDgzY1xcdWRmZDAnLFxuICAndnMnOidcXHVkODNjXFx1ZGQ5YScsXG4gICd2dWxjYW5fc2FsdXRlJzonXFx1ZDgzZFxcdWRkOTYnLFxuICAnd2Fsa2luZ19tYW4nOidcXHVkODNkXFx1ZGViNicsXG4gICd3YWxraW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlYjYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dhbmluZ19jcmVzY2VudF9tb29uJzonXFx1ZDgzY1xcdWRmMTgnLFxuICAnd2FuaW5nX2dpYmJvdXNfbW9vbic6J1xcdWQ4M2NcXHVkZjE2JyxcbiAgJ3dhcm5pbmcnOidcXHUyNmEwXFx1ZmUwZicsXG4gICd3YXN0ZWJhc2tldCc6J1xcdWQ4M2RcXHVkZGQxJyxcbiAgJ3dhdGNoJzonXFx1MjMxYVxcdWZlMGYnLFxuICAnd2F0ZXJfYnVmZmFsbyc6J1xcdWQ4M2RcXHVkYzAzJyxcbiAgJ3dhdGVybWVsb24nOidcXHVkODNjXFx1ZGY0OScsXG4gICd3YXZlJzonXFx1ZDgzZFxcdWRjNGInLFxuICAnd2F2eV9kYXNoJzonXFx1MzAzMFxcdWZlMGYnLFxuICAnd2F4aW5nX2NyZXNjZW50X21vb24nOidcXHVkODNjXFx1ZGYxMicsXG4gICd3Yyc6J1xcdWQ4M2RcXHVkZWJlJyxcbiAgJ3dlYXJ5JzonXFx1ZDgzZFxcdWRlMjknLFxuICAnd2VkZGluZyc6J1xcdWQ4M2RcXHVkYzkyJyxcbiAgJ3dlaWdodF9saWZ0aW5nX21hbic6J1xcdWQ4M2NcXHVkZmNiXFx1ZmUwZicsXG4gICd3ZWlnaHRfbGlmdGluZ193b21hbic6J1xcdWQ4M2NcXHVkZmNiXFx1ZmUwZiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd2hhbGUnOidcXHVkODNkXFx1ZGMzMycsXG4gICd3aGFsZTInOidcXHVkODNkXFx1ZGMwYicsXG4gICd3aGVlbF9vZl9kaGFybWEnOidcXHUyNjM4XFx1ZmUwZicsXG4gICd3aGVlbGNoYWlyJzonXFx1MjY3ZlxcdWZlMGYnLFxuICAnd2hpdGVfY2hlY2tfbWFyayc6J1xcdTI3MDUnLFxuICAnd2hpdGVfY2lyY2xlJzonXFx1MjZhYVxcdWZlMGYnLFxuICAnd2hpdGVfZmxhZyc6J1xcdWQ4M2NcXHVkZmYzXFx1ZmUwZicsXG4gICd3aGl0ZV9mbG93ZXInOidcXHVkODNkXFx1ZGNhZScsXG4gICd3aGl0ZV9sYXJnZV9zcXVhcmUnOidcXHUyYjFjXFx1ZmUwZicsXG4gICd3aGl0ZV9tZWRpdW1fc21hbGxfc3F1YXJlJzonXFx1MjVmZFxcdWZlMGYnLFxuICAnd2hpdGVfbWVkaXVtX3NxdWFyZSc6J1xcdTI1ZmJcXHVmZTBmJyxcbiAgJ3doaXRlX3NtYWxsX3NxdWFyZSc6J1xcdTI1YWJcXHVmZTBmJyxcbiAgJ3doaXRlX3NxdWFyZV9idXR0b24nOidcXHVkODNkXFx1ZGQzMycsXG4gICd3aWx0ZWRfZmxvd2VyJzonXFx1ZDgzZVxcdWRkNDAnLFxuICAnd2luZF9jaGltZSc6J1xcdWQ4M2NcXHVkZjkwJyxcbiAgJ3dpbmRfZmFjZSc6J1xcdWQ4M2NcXHVkZjJjJyxcbiAgJ3dpbmVfZ2xhc3MnOidcXHVkODNjXFx1ZGY3NycsXG4gICd3aW5rJzonXFx1ZDgzZFxcdWRlMDknLFxuICAnd29sZic6J1xcdWQ4M2RcXHVkYzNhJyxcbiAgJ3dvbWFuJzonXFx1ZDgzZFxcdWRjNjknLFxuICAnd29tYW5fYXJ0aXN0JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZmE4JyxcbiAgJ3dvbWFuX2FzdHJvbmF1dCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGU4MCcsXG4gICd3b21hbl9jYXJ0d2hlZWxpbmcnOidcXHVkODNlXFx1ZGQzOCZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fY29vayc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGY3MycsXG4gICd3b21hbl9mYWNlcGFsbWluZyc6J1xcdWQ4M2VcXHVkZDI2Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbl9mYWN0b3J5X3dvcmtlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGZlZCcsXG4gICd3b21hbl9mYXJtZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmM2UnLFxuICAnd29tYW5fZmlyZWZpZ2h0ZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRlOTInLFxuICAnd29tYW5faGVhbHRoX3dvcmtlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHUyNjk1XFx1ZmUwZicsXG4gICd3b21hbl9qdWRnZSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHUyNjk2XFx1ZmUwZicsXG4gICd3b21hbl9qdWdnbGluZyc6J1xcdWQ4M2VcXHVkZDM5Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbl9tZWNoYW5pYyc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGQyNycsXG4gICd3b21hbl9vZmZpY2Vfd29ya2VyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkY2JjJyxcbiAgJ3dvbWFuX3BpbG90JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdTI3MDhcXHVmZTBmJyxcbiAgJ3dvbWFuX3BsYXlpbmdfaGFuZGJhbGwnOidcXHVkODNlXFx1ZGQzZSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fcGxheWluZ193YXRlcl9wb2xvJzonXFx1ZDgzZVxcdWRkM2QmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWFuX3NjaWVudGlzdCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGQyYycsXG4gICd3b21hbl9zaHJ1Z2dpbmcnOidcXHVkODNlXFx1ZGQzNyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fc2luZ2VyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZmE0JyxcbiAgJ3dvbWFuX3N0dWRlbnQnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmOTMnLFxuICAnd29tYW5fdGVhY2hlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGZlYicsXG4gICd3b21hbl90ZWNobm9sb2dpc3QnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjYmInLFxuICAnd29tYW5fd2l0aF90dXJiYW4nOidcXHVkODNkXFx1ZGM3MyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5zX2Nsb3RoZXMnOidcXHVkODNkXFx1ZGM1YScsXG4gICd3b21hbnNfaGF0JzonXFx1ZDgzZFxcdWRjNTInLFxuICAnd29tZW5fd3Jlc3RsaW5nJzonXFx1ZDgzZVxcdWRkM2MmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWVucyc6J1xcdWQ4M2RcXHVkZWJhJyxcbiAgJ3dvcmxkX21hcCc6J1xcdWQ4M2RcXHVkZGZhJyxcbiAgJ3dvcnJpZWQnOidcXHVkODNkXFx1ZGUxZicsXG4gICd3cmVuY2gnOidcXHVkODNkXFx1ZGQyNycsXG4gICd3cml0aW5nX2hhbmQnOidcXHUyNzBkXFx1ZmUwZicsXG4gICd4JzonXFx1Mjc0YycsXG4gICd5ZWxsb3dfaGVhcnQnOidcXHVkODNkXFx1ZGM5YicsXG4gICd5ZW4nOidcXHVkODNkXFx1ZGNiNCcsXG4gICd5aW5feWFuZyc6J1xcdTI2MmZcXHVmZTBmJyxcbiAgJ3l1bSc6J1xcdWQ4M2RcXHVkZTBiJyxcbiAgJ3phcCc6J1xcdTI2YTFcXHVmZTBmJyxcbiAgJ3ppcHBlcl9tb3V0aF9mYWNlJzonXFx1ZDgzZVxcdWRkMTAnLFxuICAnenp6JzonXFx1ZDgzZFxcdWRjYTQnLFxuXG4gIC8qIHNwZWNpYWwgZW1vamlzIDpQICovXG4gICdvY3RvY2F0JzogICc8aW1nIGFsdD1cIjpvY3RvY2F0OlwiIGhlaWdodD1cIjIwXCIgd2lkdGg9XCIyMFwiIGFsaWduPVwiYWJzbWlkZGxlXCIgc3JjPVwiaHR0cHM6Ly9hc3NldHMtY2RuLmdpdGh1Yi5jb20vaW1hZ2VzL2ljb25zL2Vtb2ppL29jdG9jYXQucG5nXCI+JyxcbiAgJ3Nob3dkb3duJzogJzxzcGFuIHN0eWxlPVwiZm9udC1mYW1pbHk6IFxcJ0Fub255bW91cyBQcm9cXCcsIG1vbm9zcGFjZTsgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7IHRleHQtZGVjb3JhdGlvbi1zdHlsZTogZGFzaGVkOyB0ZXh0LWRlY29yYXRpb24tY29sb3I6ICMzZThiOGE7dGV4dC11bmRlcmxpbmUtcG9zaXRpb246IHVuZGVyO1wiPlM8L3NwYW4+J1xufTtcblxyXG4vKipcbiAqIENyZWF0ZWQgYnkgRXN0ZXZhbyBvbiAzMS0wNS0yMDE1LlxuICovXG5cbi8qKlxuICogU2hvd2Rvd24gQ29udmVydGVyIGNsYXNzXG4gKiBAY2xhc3NcbiAqIEBwYXJhbSB7b2JqZWN0fSBbY29udmVydGVyT3B0aW9uc11cbiAqIEByZXR1cm5zIHtDb252ZXJ0ZXJ9XG4gKi9cbnNob3dkb3duLkNvbnZlcnRlciA9IGZ1bmN0aW9uIChjb252ZXJ0ZXJPcHRpb25zKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXJcbiAgICAgIC8qKlxuICAgICAgICogT3B0aW9ucyB1c2VkIGJ5IHRoaXMgY29udmVydGVyXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICogQHR5cGUge3t9fVxuICAgICAgICovXG4gICAgICBvcHRpb25zID0ge30sXG5cbiAgICAgIC8qKlxuICAgICAgICogTGFuZ3VhZ2UgZXh0ZW5zaW9ucyB1c2VkIGJ5IHRoaXMgY29udmVydGVyXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICogQHR5cGUge0FycmF5fVxuICAgICAgICovXG4gICAgICBsYW5nRXh0ZW5zaW9ucyA9IFtdLFxuXG4gICAgICAvKipcbiAgICAgICAqIE91dHB1dCBtb2RpZmllcnMgZXh0ZW5zaW9ucyB1c2VkIGJ5IHRoaXMgY29udmVydGVyXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICogQHR5cGUge0FycmF5fVxuICAgICAgICovXG4gICAgICBvdXRwdXRNb2RpZmllcnMgPSBbXSxcblxuICAgICAgLyoqXG4gICAgICAgKiBFdmVudCBsaXN0ZW5lcnNcbiAgICAgICAqIEBwcml2YXRlXG4gICAgICAgKiBAdHlwZSB7e319XG4gICAgICAgKi9cbiAgICAgIGxpc3RlbmVycyA9IHt9LFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBmbGF2b3Igc2V0IGluIHRoaXMgY29udmVydGVyXG4gICAgICAgKi9cbiAgICAgIHNldENvbnZGbGF2b3IgPSBzZXRGbGF2b3IsXG5cbiAgICAgIC8qKlxuICAgICAgICogTWV0YWRhdGEgb2YgdGhlIGRvY3VtZW50XG4gICAgICAgKiBAdHlwZSB7e3BhcnNlZDoge30sIHJhdzogc3RyaW5nLCBmb3JtYXQ6IHN0cmluZ319XG4gICAgICAgKi9cbiAgICAgIG1ldGFkYXRhID0ge1xuICAgICAgICBwYXJzZWQ6IHt9LFxuICAgICAgICByYXc6ICcnLFxuICAgICAgICBmb3JtYXQ6ICcnXG4gICAgICB9O1xuXG4gIF9jb25zdHJ1Y3RvcigpO1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0ZXIgY29uc3RydWN0b3JcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGZ1bmN0aW9uIF9jb25zdHJ1Y3RvciAoKSB7XG4gICAgY29udmVydGVyT3B0aW9ucyA9IGNvbnZlcnRlck9wdGlvbnMgfHwge307XG5cbiAgICBmb3IgKHZhciBnT3B0IGluIGdsb2JhbE9wdGlvbnMpIHtcbiAgICAgIGlmIChnbG9iYWxPcHRpb25zLmhhc093blByb3BlcnR5KGdPcHQpKSB7XG4gICAgICAgIG9wdGlvbnNbZ09wdF0gPSBnbG9iYWxPcHRpb25zW2dPcHRdO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE1lcmdlIG9wdGlvbnNcbiAgICBpZiAodHlwZW9mIGNvbnZlcnRlck9wdGlvbnMgPT09ICdvYmplY3QnKSB7XG4gICAgICBmb3IgKHZhciBvcHQgaW4gY29udmVydGVyT3B0aW9ucykge1xuICAgICAgICBpZiAoY29udmVydGVyT3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShvcHQpKSB7XG4gICAgICAgICAgb3B0aW9uc1tvcHRdID0gY29udmVydGVyT3B0aW9uc1tvcHRdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IEVycm9yKCdDb252ZXJ0ZXIgZXhwZWN0cyB0aGUgcGFzc2VkIHBhcmFtZXRlciB0byBiZSBhbiBvYmplY3QsIGJ1dCAnICsgdHlwZW9mIGNvbnZlcnRlck9wdGlvbnMgK1xuICAgICAgJyB3YXMgcGFzc2VkIGluc3RlYWQuJyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuZXh0ZW5zaW9ucykge1xuICAgICAgc2hvd2Rvd24uaGVscGVyLmZvckVhY2gob3B0aW9ucy5leHRlbnNpb25zLCBfcGFyc2VFeHRlbnNpb24pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBleHRlbnNpb25cbiAgICogQHBhcmFtIHsqfSBleHRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lPScnXVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZnVuY3Rpb24gX3BhcnNlRXh0ZW5zaW9uIChleHQsIG5hbWUpIHtcblxuICAgIG5hbWUgPSBuYW1lIHx8IG51bGw7XG4gICAgLy8gSWYgaXQncyBhIHN0cmluZywgdGhlIGV4dGVuc2lvbiB3YXMgcHJldmlvdXNseSBsb2FkZWRcbiAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKGV4dCkpIHtcbiAgICAgIGV4dCA9IHNob3dkb3duLmhlbHBlci5zdGRFeHROYW1lKGV4dCk7XG4gICAgICBuYW1lID0gZXh0O1xuXG4gICAgICAvLyBMRUdBQ1lfU1VQUE9SVCBDT0RFXG4gICAgICBpZiAoc2hvd2Rvd24uZXh0ZW5zaW9uc1tleHRdKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignREVQUkVDQVRJT04gV0FSTklORzogJyArIGV4dCArICcgaXMgYW4gb2xkIGV4dGVuc2lvbiB0aGF0IHVzZXMgYSBkZXByZWNhdGVkIGxvYWRpbmcgbWV0aG9kLicgK1xuICAgICAgICAgICdQbGVhc2UgaW5mb3JtIHRoZSBkZXZlbG9wZXIgdGhhdCB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSB1cGRhdGVkIScpO1xuICAgICAgICBsZWdhY3lFeHRlbnNpb25Mb2FkaW5nKHNob3dkb3duLmV4dGVuc2lvbnNbZXh0XSwgZXh0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBFTkQgTEVHQUNZIFNVUFBPUlQgQ09ERVxuXG4gICAgICB9IGVsc2UgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZXh0ZW5zaW9uc1tleHRdKSkge1xuICAgICAgICBleHQgPSBleHRlbnNpb25zW2V4dF07XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IEVycm9yKCdFeHRlbnNpb24gXCInICsgZXh0ICsgJ1wiIGNvdWxkIG5vdCBiZSBsb2FkZWQuIEl0IHdhcyBlaXRoZXIgbm90IGZvdW5kIG9yIGlzIG5vdCBhIHZhbGlkIGV4dGVuc2lvbi4nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZXh0ID0gZXh0KCk7XG4gICAgfVxuXG4gICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNBcnJheShleHQpKSB7XG4gICAgICBleHQgPSBbZXh0XTtcbiAgICB9XG5cbiAgICB2YXIgdmFsaWRFeHQgPSB2YWxpZGF0ZShleHQsIG5hbWUpO1xuICAgIGlmICghdmFsaWRFeHQudmFsaWQpIHtcbiAgICAgIHRocm93IEVycm9yKHZhbGlkRXh0LmVycm9yKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV4dC5sZW5ndGg7ICsraSkge1xuICAgICAgc3dpdGNoIChleHRbaV0udHlwZSkge1xuXG4gICAgICAgIGNhc2UgJ2xhbmcnOlxuICAgICAgICAgIGxhbmdFeHRlbnNpb25zLnB1c2goZXh0W2ldKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdvdXRwdXQnOlxuICAgICAgICAgIG91dHB1dE1vZGlmaWVycy5wdXNoKGV4dFtpXSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoZXh0W2ldLmhhc093blByb3BlcnR5KCdsaXN0ZW5lcnMnKSkge1xuICAgICAgICBmb3IgKHZhciBsbiBpbiBleHRbaV0ubGlzdGVuZXJzKSB7XG4gICAgICAgICAgaWYgKGV4dFtpXS5saXN0ZW5lcnMuaGFzT3duUHJvcGVydHkobG4pKSB7XG4gICAgICAgICAgICBsaXN0ZW4obG4sIGV4dFtpXS5saXN0ZW5lcnNbbG5dKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBMRUdBQ1lfU1VQUE9SVFxuICAgKiBAcGFyYW0geyp9IGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgKi9cbiAgZnVuY3Rpb24gbGVnYWN5RXh0ZW5zaW9uTG9hZGluZyAoZXh0LCBuYW1lKSB7XG4gICAgaWYgKHR5cGVvZiBleHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGV4dCA9IGV4dChuZXcgc2hvd2Rvd24uQ29udmVydGVyKCkpO1xuICAgIH1cbiAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0FycmF5KGV4dCkpIHtcbiAgICAgIGV4dCA9IFtleHRdO1xuICAgIH1cbiAgICB2YXIgdmFsaWQgPSB2YWxpZGF0ZShleHQsIG5hbWUpO1xuXG4gICAgaWYgKCF2YWxpZC52YWxpZCkge1xuICAgICAgdGhyb3cgRXJyb3IodmFsaWQuZXJyb3IpO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXh0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBzd2l0Y2ggKGV4dFtpXS50eXBlKSB7XG4gICAgICAgIGNhc2UgJ2xhbmcnOlxuICAgICAgICAgIGxhbmdFeHRlbnNpb25zLnB1c2goZXh0W2ldKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnb3V0cHV0JzpcbiAgICAgICAgICBvdXRwdXRNb2RpZmllcnMucHVzaChleHRbaV0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0Oi8vIHNob3VsZCBuZXZlciByZWFjaCBoZXJlXG4gICAgICAgICAgdGhyb3cgRXJyb3IoJ0V4dGVuc2lvbiBsb2FkZXIgZXJyb3I6IFR5cGUgdW5yZWNvZ25pemVkISEhJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbiB0byBhbiBldmVudFxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgZnVuY3Rpb24gbGlzdGVuIChuYW1lLCBjYWxsYmFjaykge1xuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG5hbWUpKSB7XG4gICAgICB0aHJvdyBFcnJvcignSW52YWxpZCBhcmd1bWVudCBpbiBjb252ZXJ0ZXIubGlzdGVuKCkgbWV0aG9kOiBuYW1lIG11c3QgYmUgYSBzdHJpbmcsIGJ1dCAnICsgdHlwZW9mIG5hbWUgKyAnIGdpdmVuJyk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhyb3cgRXJyb3IoJ0ludmFsaWQgYXJndW1lbnQgaW4gY29udmVydGVyLmxpc3RlbigpIG1ldGhvZDogY2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uLCBidXQgJyArIHR5cGVvZiBjYWxsYmFjayArICcgZ2l2ZW4nKTtcbiAgICB9XG5cbiAgICBpZiAoIWxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgbGlzdGVuZXJzW25hbWVdID0gW107XG4gICAgfVxuICAgIGxpc3RlbmVyc1tuYW1lXS5wdXNoKGNhbGxiYWNrKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJUcmltSW5wdXRUZXh0ICh0ZXh0KSB7XG4gICAgdmFyIHJzcCA9IHRleHQubWF0Y2goL15cXHMqLylbMF0ubGVuZ3RoLFxuICAgICAgICByZ3ggPSBuZXcgUmVnRXhwKCdeXFxcXHN7MCwnICsgcnNwICsgJ30nLCAnZ20nKTtcbiAgICByZXR1cm4gdGV4dC5yZXBsYWNlKHJneCwgJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3BhdGNoIGFuIGV2ZW50XG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBldnROYW1lIEV2ZW50IG5hbWVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgVGV4dFxuICAgKiBAcGFyYW0ge3t9fSBvcHRpb25zIENvbnZlcnRlciBPcHRpb25zXG4gICAqIEBwYXJhbSB7e319IGdsb2JhbHNcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHRoaXMuX2Rpc3BhdGNoID0gZnVuY3Rpb24gZGlzcGF0Y2ggKGV2dE5hbWUsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGV2dE5hbWUpKSB7XG4gICAgICBmb3IgKHZhciBlaSA9IDA7IGVpIDwgbGlzdGVuZXJzW2V2dE5hbWVdLmxlbmd0aDsgKytlaSkge1xuICAgICAgICB2YXIgblRleHQgPSBsaXN0ZW5lcnNbZXZ0TmFtZV1bZWldKGV2dE5hbWUsIHRleHQsIHRoaXMsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICBpZiAoblRleHQgJiYgdHlwZW9mIG5UZXh0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRleHQgPSBuVGV4dDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGV4dDtcbiAgfTtcblxuICAvKipcbiAgICogTGlzdGVuIHRvIGFuIGV2ZW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAqIEByZXR1cm5zIHtzaG93ZG93bi5Db252ZXJ0ZXJ9XG4gICAqL1xuICB0aGlzLmxpc3RlbiA9IGZ1bmN0aW9uIChuYW1lLCBjYWxsYmFjaykge1xuICAgIGxpc3RlbihuYW1lLCBjYWxsYmFjayk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgbWFya2Rvd24gc3RyaW5nIGludG8gSFRNTFxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHRoaXMubWFrZUh0bWwgPSBmdW5jdGlvbiAodGV4dCkge1xuICAgIC8vY2hlY2sgaWYgdGV4dCBpcyBub3QgZmFsc3lcbiAgICBpZiAoIXRleHQpIHtcbiAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cblxuICAgIHZhciBnbG9iYWxzID0ge1xuICAgICAgZ0h0bWxCbG9ja3M6ICAgICBbXSxcbiAgICAgIGdIdG1sTWRCbG9ja3M6ICAgW10sXG4gICAgICBnSHRtbFNwYW5zOiAgICAgIFtdLFxuICAgICAgZ1VybHM6ICAgICAgICAgICB7fSxcbiAgICAgIGdUaXRsZXM6ICAgICAgICAge30sXG4gICAgICBnRGltZW5zaW9uczogICAgIHt9LFxuICAgICAgZ0xpc3RMZXZlbDogICAgICAwLFxuICAgICAgaGFzaExpbmtDb3VudHM6ICB7fSxcbiAgICAgIGxhbmdFeHRlbnNpb25zOiAgbGFuZ0V4dGVuc2lvbnMsXG4gICAgICBvdXRwdXRNb2RpZmllcnM6IG91dHB1dE1vZGlmaWVycyxcbiAgICAgIGNvbnZlcnRlcjogICAgICAgdGhpcyxcbiAgICAgIGdoQ29kZUJsb2NrczogICAgW10sXG4gICAgICBtZXRhZGF0YToge1xuICAgICAgICBwYXJzZWQ6IHt9LFxuICAgICAgICByYXc6ICcnLFxuICAgICAgICBmb3JtYXQ6ICcnXG4gICAgICB9XG4gICAgfTtcblxuICAgIC8vIFRoaXMgbGV0cyB1cyB1c2UgwqggdHJlbWEgYXMgYW4gZXNjYXBlIGNoYXIgdG8gYXZvaWQgbWQ1IGhhc2hlc1xuICAgIC8vIFRoZSBjaG9pY2Ugb2YgY2hhcmFjdGVyIGlzIGFyYml0cmFyeTsgYW55dGhpbmcgdGhhdCBpc24ndFxuICAgIC8vIG1hZ2ljIGluIE1hcmtkb3duIHdpbGwgd29yay5cbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqC9nLCAnwqhUJyk7XG5cbiAgICAvLyBSZXBsYWNlICQgd2l0aCDCqERcbiAgICAvLyBSZWdFeHAgaW50ZXJwcmV0cyAkIGFzIGEgc3BlY2lhbCBjaGFyYWN0ZXJcbiAgICAvLyB3aGVuIGl0J3MgaW4gYSByZXBsYWNlbWVudCBzdHJpbmdcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXCQvZywgJ8KoRCcpO1xuXG4gICAgLy8gU3RhbmRhcmRpemUgbGluZSBlbmRpbmdzXG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxyXFxuL2csICdcXG4nKTsgLy8gRE9TIHRvIFVuaXhcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHIvZywgJ1xcbicpOyAvLyBNYWMgdG8gVW5peFxuXG4gICAgLy8gU3RhcmRhcmRpemUgbGluZSBzcGFjZXNcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHUwMEEwL2csICcmbmJzcDsnKTtcblxuICAgIGlmIChvcHRpb25zLnNtYXJ0SW5kZW50YXRpb25GaXgpIHtcbiAgICAgIHRleHQgPSByVHJpbUlucHV0VGV4dCh0ZXh0KTtcbiAgICB9XG5cbiAgICAvLyBNYWtlIHN1cmUgdGV4dCBiZWdpbnMgYW5kIGVuZHMgd2l0aCBhIGNvdXBsZSBvZiBuZXdsaW5lczpcbiAgICB0ZXh0ID0gJ1xcblxcbicgKyB0ZXh0ICsgJ1xcblxcbic7XG5cbiAgICAvLyBkZXRhYlxuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2RldGFiJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgICAvKipcbiAgICAgKiBTdHJpcCBhbnkgbGluZXMgY29uc2lzdGluZyBvbmx5IG9mIHNwYWNlcyBhbmQgdGFicy5cbiAgICAgKiBUaGlzIG1ha2VzIHN1YnNlcXVlbnQgcmVnZXhzIGVhc2llciB0byB3cml0ZSwgYmVjYXVzZSB3ZSBjYW5cbiAgICAgKiBtYXRjaCBjb25zZWN1dGl2ZSBibGFuayBsaW5lcyB3aXRoIC9cXG4rLyBpbnN0ZWFkIG9mIHNvbWV0aGluZ1xuICAgICAqIGNvbnRvcnRlZCBsaWtlIC9bIFxcdF0qXFxuKy9cbiAgICAgKi9cbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eWyBcXHRdKyQvbWcsICcnKTtcblxuICAgIC8vcnVuIGxhbmd1YWdlRXh0ZW5zaW9uc1xuICAgIHNob3dkb3duLmhlbHBlci5mb3JFYWNoKGxhbmdFeHRlbnNpb25zLCBmdW5jdGlvbiAoZXh0KSB7XG4gICAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdydW5FeHRlbnNpb24nKShleHQsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIH0pO1xuXG4gICAgLy8gcnVuIHRoZSBzdWIgcGFyc2Vyc1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ldGFkYXRhJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaFByZUNvZGVUYWdzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZ2l0aHViQ29kZUJsb2NrcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hIVE1MQmxvY2tzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaENvZGVUYWdzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignc3RyaXBMaW5rRGVmaW5pdGlvbnMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdibG9ja0dhbXV0JykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcigndW5oYXNoSFRNTFNwYW5zJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcigndW5lc2NhcGVTcGVjaWFsQ2hhcnMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAgIC8vIGF0dGFja2xhYjogUmVzdG9yZSBkb2xsYXIgc2lnbnNcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqEQvZywgJyQkJyk7XG5cbiAgICAvLyBhdHRhY2tsYWI6IFJlc3RvcmUgdHJlbWFzXG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqhUL2csICfCqCcpO1xuXG4gICAgLy8gcmVuZGVyIGEgY29tcGxldGUgaHRtbCBkb2N1bWVudCBpbnN0ZWFkIG9mIGEgcGFydGlhbCBpZiB0aGUgb3B0aW9uIGlzIGVuYWJsZWRcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdjb21wbGV0ZUhUTUxEb2N1bWVudCcpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gICAgLy8gUnVuIG91dHB1dCBtb2RpZmllcnNcbiAgICBzaG93ZG93bi5oZWxwZXIuZm9yRWFjaChvdXRwdXRNb2RpZmllcnMsIGZ1bmN0aW9uIChleHQpIHtcbiAgICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3J1bkV4dGVuc2lvbicpKGV4dCwgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgfSk7XG5cbiAgICAvLyB1cGRhdGUgbWV0YWRhdGFcbiAgICBtZXRhZGF0YSA9IGdsb2JhbHMubWV0YWRhdGE7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH07XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGFuIEhUTUwgc3RyaW5nIGludG8gYSBtYXJrZG93biBzdHJpbmdcbiAgICogQHBhcmFtIHNyY1xuICAgKiBAcGFyYW0gW0hUTUxQYXJzZXJdIEEgV0hBVFdHIERPTSBhbmQgSFRNTCBwYXJzZXIsIHN1Y2ggYXMgSlNET00uIElmIG5vbmUgaXMgc3VwcGxpZWQsIHdpbmRvdy5kb2N1bWVudCB3aWxsIGJlIHVzZWQuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICB0aGlzLm1ha2VNYXJrZG93biA9IHRoaXMubWFrZU1kID0gZnVuY3Rpb24gKHNyYywgSFRNTFBhcnNlcikge1xuXG4gICAgLy8gcmVwbGFjZSBcXHJcXG4gd2l0aCBcXG5cbiAgICBzcmMgPSBzcmMucmVwbGFjZSgvXFxyXFxuL2csICdcXG4nKTtcbiAgICBzcmMgPSBzcmMucmVwbGFjZSgvXFxyL2csICdcXG4nKTsgLy8gb2xkIG1hY3NcblxuICAgIC8vIGR1ZSB0byBhbiBlZGdlIGNhc2UsIHdlIG5lZWQgdG8gZmluZCB0aGlzOiA+IDxcbiAgICAvLyB0byBwcmV2ZW50IHJlbW92aW5nIG9mIG5vbiBzaWxlbnQgd2hpdGUgc3BhY2VzXG4gICAgLy8gZXg6IDxlbT50aGlzIGlzPC9lbT4gPHN0cm9uZz5zcGFydGE8L3N0cm9uZz5cbiAgICBzcmMgPSBzcmMucmVwbGFjZSgvPlsgXFx0XSs8LywgJz7CqE5CU1A7PCcpO1xuXG4gICAgaWYgKCFIVE1MUGFyc2VyKSB7XG4gICAgICBpZiAod2luZG93ICYmIHdpbmRvdy5kb2N1bWVudCkge1xuICAgICAgICBIVE1MUGFyc2VyID0gd2luZG93LmRvY3VtZW50O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIVE1MUGFyc2VyIGlzIHVuZGVmaW5lZC4gSWYgaW4gYSB3ZWJ3b3JrZXIgb3Igbm9kZWpzIGVudmlyb25tZW50LCB5b3UgbmVlZCB0byBwcm92aWRlIGEgV0hBVFdHIERPTSBhbmQgSFRNTCBzdWNoIGFzIEpTRE9NJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGRvYyA9IEhUTUxQYXJzZXIuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZG9jLmlubmVySFRNTCA9IHNyYztcblxuICAgIHZhciBnbG9iYWxzID0ge1xuICAgICAgcHJlTGlzdDogc3Vic3RpdHV0ZVByZUNvZGVUYWdzKGRvYylcbiAgICB9O1xuXG4gICAgLy8gcmVtb3ZlIGFsbCBuZXdsaW5lcyBhbmQgY29sbGFwc2Ugc3BhY2VzXG4gICAgY2xlYW4oZG9jKTtcblxuICAgIC8vIHNvbWUgc3R1ZmYsIGxpa2UgYWNjaWRlbnRhbCByZWZlcmVuY2UgbGlua3MgbXVzdCBub3cgYmUgZXNjYXBlZFxuICAgIC8vIFRPRE9cbiAgICAvLyBkb2MuaW5uZXJIVE1MID0gZG9jLmlubmVySFRNTC5yZXBsYWNlKC9cXFtbXFxTXFx0IF1dLyk7XG5cbiAgICB2YXIgbm9kZXMgPSBkb2MuY2hpbGROb2RlcyxcbiAgICAgICAgbWREb2MgPSAnJztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIG1kRG9jICs9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShub2Rlc1tpXSwgZ2xvYmFscyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xlYW4gKG5vZGUpIHtcbiAgICAgIGZvciAodmFyIG4gPSAwOyBuIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgKytuKSB7XG4gICAgICAgIHZhciBjaGlsZCA9IG5vZGUuY2hpbGROb2Rlc1tuXTtcbiAgICAgICAgaWYgKGNoaWxkLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgaWYgKCEvXFxTLy50ZXN0KGNoaWxkLm5vZGVWYWx1ZSkpIHtcbiAgICAgICAgICAgIG5vZGUucmVtb3ZlQ2hpbGQoY2hpbGQpO1xuICAgICAgICAgICAgLS1uO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGlsZC5ub2RlVmFsdWUgPSBjaGlsZC5ub2RlVmFsdWUuc3BsaXQoJ1xcbicpLmpvaW4oJyAnKTtcbiAgICAgICAgICAgIGNoaWxkLm5vZGVWYWx1ZSA9IGNoaWxkLm5vZGVWYWx1ZS5yZXBsYWNlKC8oXFxzKSsvZywgJyQxJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGNoaWxkLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICAgICAgY2xlYW4oY2hpbGQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gZmluZCBhbGwgcHJlIHRhZ3MgYW5kIHJlcGxhY2UgY29udGVudHMgd2l0aCBwbGFjZWhvbGRlclxuICAgIC8vIHdlIG5lZWQgdGhpcyBzbyB0aGF0IHdlIGNhbiByZW1vdmUgYWxsIGluZGVudGF0aW9uIGZyb20gaHRtbFxuICAgIC8vIHRvIGVhc2UgdXAgcGFyc2luZ1xuICAgIGZ1bmN0aW9uIHN1YnN0aXR1dGVQcmVDb2RlVGFncyAoZG9jKSB7XG5cbiAgICAgIHZhciBwcmVzID0gZG9jLnF1ZXJ5U2VsZWN0b3JBbGwoJ3ByZScpLFxuICAgICAgICAgIHByZXNQSCA9IFtdO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByZXMubGVuZ3RoOyArK2kpIHtcblxuICAgICAgICBpZiAocHJlc1tpXS5jaGlsZEVsZW1lbnRDb3VudCA9PT0gMSAmJiBwcmVzW2ldLmZpcnN0Q2hpbGQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnY29kZScpIHtcbiAgICAgICAgICB2YXIgY29udGVudCA9IHByZXNbaV0uZmlyc3RDaGlsZC5pbm5lckhUTUwudHJpbSgpLFxuICAgICAgICAgICAgICBsYW5ndWFnZSA9IHByZXNbaV0uZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoJ2RhdGEtbGFuZ3VhZ2UnKSB8fCAnJztcblxuICAgICAgICAgIC8vIGlmIGRhdGEtbGFuZ3VhZ2UgYXR0cmlidXRlIGlzIG5vdCBkZWZpbmVkLCB0aGVuIHdlIGxvb2sgZm9yIGNsYXNzIGxhbmd1YWdlLSpcbiAgICAgICAgICBpZiAobGFuZ3VhZ2UgPT09ICcnKSB7XG4gICAgICAgICAgICB2YXIgY2xhc3NlcyA9IHByZXNbaV0uZmlyc3RDaGlsZC5jbGFzc05hbWUuc3BsaXQoJyAnKTtcbiAgICAgICAgICAgIGZvciAodmFyIGMgPSAwOyBjIDwgY2xhc3Nlcy5sZW5ndGg7ICsrYykge1xuICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IGNsYXNzZXNbY10ubWF0Y2goL15sYW5ndWFnZS0oLispJC8pO1xuICAgICAgICAgICAgICBpZiAobWF0Y2hlcyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGxhbmd1YWdlID0gbWF0Y2hlc1sxXTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIHVuZXNjYXBlIGh0bWwgZW50aXRpZXMgaW4gY29udGVudFxuICAgICAgICAgIGNvbnRlbnQgPSBzaG93ZG93bi5oZWxwZXIudW5lc2NhcGVIVE1MRW50aXRpZXMoY29udGVudCk7XG5cbiAgICAgICAgICBwcmVzUEgucHVzaChjb250ZW50KTtcbiAgICAgICAgICBwcmVzW2ldLm91dGVySFRNTCA9ICc8cHJlY29kZSBsYW5ndWFnZT1cIicgKyBsYW5ndWFnZSArICdcIiBwcmVjb2RlbnVtPVwiJyArIGkudG9TdHJpbmcoKSArICdcIj48L3ByZWNvZGU+JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwcmVzUEgucHVzaChwcmVzW2ldLmlubmVySFRNTCk7XG4gICAgICAgICAgcHJlc1tpXS5pbm5lckhUTUwgPSAnJztcbiAgICAgICAgICBwcmVzW2ldLnNldEF0dHJpYnV0ZSgncHJlbnVtJywgaS50b1N0cmluZygpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHByZXNQSDtcbiAgICB9XG5cbiAgICByZXR1cm4gbWREb2M7XG4gIH07XG5cbiAgLyoqXG4gICAqIFNldCBhbiBvcHRpb24gb2YgdGhpcyBDb252ZXJ0ZXIgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICAgKiBAcGFyYW0geyp9IHZhbHVlXG4gICAqL1xuICB0aGlzLnNldE9wdGlvbiA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgb3B0aW9uc1trZXldID0gdmFsdWU7XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgb3B0aW9uIG9mIHRoaXMgQ29udmVydGVyIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICB0aGlzLmdldE9wdGlvbiA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gb3B0aW9uc1trZXldO1xuICB9O1xuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG9wdGlvbnMgb2YgdGhpcyBDb252ZXJ0ZXIgaW5zdGFuY2VcbiAgICogQHJldHVybnMge3t9fVxuICAgKi9cbiAgdGhpcy5nZXRPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBvcHRpb25zO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBZGQgZXh0ZW5zaW9uIHRvIFRISVMgY29udmVydGVyXG4gICAqIEBwYXJhbSB7e319IGV4dGVuc2lvblxuICAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWU9bnVsbF1cbiAgICovXG4gIHRoaXMuYWRkRXh0ZW5zaW9uID0gZnVuY3Rpb24gKGV4dGVuc2lvbiwgbmFtZSkge1xuICAgIG5hbWUgPSBuYW1lIHx8IG51bGw7XG4gICAgX3BhcnNlRXh0ZW5zaW9uKGV4dGVuc2lvbiwgbmFtZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVzZSBhIGdsb2JhbCByZWdpc3RlcmVkIGV4dGVuc2lvbiB3aXRoIFRISVMgY29udmVydGVyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBleHRlbnNpb25OYW1lIE5hbWUgb2YgdGhlIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCBleHRlbnNpb25cbiAgICovXG4gIHRoaXMudXNlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKGV4dGVuc2lvbk5hbWUpIHtcbiAgICBfcGFyc2VFeHRlbnNpb24oZXh0ZW5zaW9uTmFtZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgZmxhdm9yIFRISVMgY29udmVydGVyIHNob3VsZCB1c2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICovXG4gIHRoaXMuc2V0Rmxhdm9yID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICBpZiAoIWZsYXZvci5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgdGhyb3cgRXJyb3IobmFtZSArICcgZmxhdm9yIHdhcyBub3QgZm91bmQnKTtcbiAgICB9XG4gICAgdmFyIHByZXNldCA9IGZsYXZvcltuYW1lXTtcbiAgICBzZXRDb252Rmxhdm9yID0gbmFtZTtcbiAgICBmb3IgKHZhciBvcHRpb24gaW4gcHJlc2V0KSB7XG4gICAgICBpZiAocHJlc2V0Lmhhc093blByb3BlcnR5KG9wdGlvbikpIHtcbiAgICAgICAgb3B0aW9uc1tvcHRpb25dID0gcHJlc2V0W29wdGlvbl07XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGN1cnJlbnRseSBzZXQgZmxhdm9yIG9mIHRoaXMgY29udmVydGVyXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICB0aGlzLmdldEZsYXZvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gc2V0Q29udkZsYXZvcjtcbiAgfTtcblxuICAvKipcbiAgICogUmVtb3ZlIGFuIGV4dGVuc2lvbiBmcm9tIFRISVMgY29udmVydGVyLlxuICAgKiBOb3RlOiBUaGlzIGlzIGEgY29zdGx5IG9wZXJhdGlvbi4gSXQncyBiZXR0ZXIgdG8gaW5pdGlhbGl6ZSBhIG5ldyBjb252ZXJ0ZXJcbiAgICogYW5kIHNwZWNpZnkgdGhlIGV4dGVuc2lvbnMgeW91IHdpc2ggdG8gdXNlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGV4dGVuc2lvblxuICAgKi9cbiAgdGhpcy5yZW1vdmVFeHRlbnNpb24gPSBmdW5jdGlvbiAoZXh0ZW5zaW9uKSB7XG4gICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNBcnJheShleHRlbnNpb24pKSB7XG4gICAgICBleHRlbnNpb24gPSBbZXh0ZW5zaW9uXTtcbiAgICB9XG4gICAgZm9yICh2YXIgYSA9IDA7IGEgPCBleHRlbnNpb24ubGVuZ3RoOyArK2EpIHtcbiAgICAgIHZhciBleHQgPSBleHRlbnNpb25bYV07XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxhbmdFeHRlbnNpb25zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmIChsYW5nRXh0ZW5zaW9uc1tpXSA9PT0gZXh0KSB7XG4gICAgICAgICAgbGFuZ0V4dGVuc2lvbnNbaV0uc3BsaWNlKGksIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgb3V0cHV0TW9kaWZpZXJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmIChvdXRwdXRNb2RpZmllcnNbaWldID09PSBleHQpIHtcbiAgICAgICAgICBvdXRwdXRNb2RpZmllcnNbaWldLnNwbGljZShpLCAxKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogR2V0IGFsbCBleHRlbnNpb24gb2YgVEhJUyBjb252ZXJ0ZXJcbiAgICogQHJldHVybnMge3tsYW5ndWFnZTogQXJyYXksIG91dHB1dDogQXJyYXl9fVxuICAgKi9cbiAgdGhpcy5nZXRBbGxFeHRlbnNpb25zID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB7XG4gICAgICBsYW5ndWFnZTogbGFuZ0V4dGVuc2lvbnMsXG4gICAgICBvdXRwdXQ6IG91dHB1dE1vZGlmaWVyc1xuICAgIH07XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbWV0YWRhdGEgb2YgdGhlIHByZXZpb3VzbHkgcGFyc2VkIGRvY3VtZW50XG4gICAqIEBwYXJhbSByYXdcbiAgICogQHJldHVybnMge3N0cmluZ3x7fX1cbiAgICovXG4gIHRoaXMuZ2V0TWV0YWRhdGEgPSBmdW5jdGlvbiAocmF3KSB7XG4gICAgaWYgKHJhdykge1xuICAgICAgcmV0dXJuIG1ldGFkYXRhLnJhdztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG1ldGFkYXRhLnBhcnNlZDtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbWV0YWRhdGEgZm9ybWF0IG9mIHRoZSBwcmV2aW91c2x5IHBhcnNlZCBkb2N1bWVudFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgdGhpcy5nZXRNZXRhZGF0YUZvcm1hdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gbWV0YWRhdGEuZm9ybWF0O1xuICB9O1xuXG4gIC8qKlxuICAgKiBQcml2YXRlOiBzZXQgYSBzaW5nbGUga2V5LCB2YWx1ZSBtZXRhZGF0YSBwYWlyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAqL1xuICB0aGlzLl9zZXRNZXRhZGF0YVBhaXIgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgIG1ldGFkYXRhLnBhcnNlZFtrZXldID0gdmFsdWU7XG4gIH07XG5cbiAgLyoqXG4gICAqIFByaXZhdGU6IHNldCBtZXRhZGF0YSBmb3JtYXRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGZvcm1hdFxuICAgKi9cbiAgdGhpcy5fc2V0TWV0YWRhdGFGb3JtYXQgPSBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgbWV0YWRhdGEuZm9ybWF0ID0gZm9ybWF0O1xuICB9O1xuXG4gIC8qKlxuICAgKiBQcml2YXRlOiBzZXQgbWV0YWRhdGEgcmF3IHRleHRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJhd1xuICAgKi9cbiAgdGhpcy5fc2V0TWV0YWRhdGFSYXcgPSBmdW5jdGlvbiAocmF3KSB7XG4gICAgbWV0YWRhdGEucmF3ID0gcmF3O1xuICB9O1xufTtcblxyXG4vKipcbiAqIFR1cm4gTWFya2Rvd24gbGluayBzaG9ydGN1dHMgaW50byBYSFRNTCA8YT4gdGFncy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdhbmNob3JzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2FuY2hvcnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdmFyIHdyaXRlQW5jaG9yVGFnID0gZnVuY3Rpb24gKHdob2xlTWF0Y2gsIGxpbmtUZXh0LCBsaW5rSWQsIHVybCwgbTUsIG02LCB0aXRsZSkge1xuICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQodGl0bGUpKSB7XG4gICAgICB0aXRsZSA9ICcnO1xuICAgIH1cbiAgICBsaW5rSWQgPSBsaW5rSWQudG9Mb3dlckNhc2UoKTtcblxuICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgZXhwbGljaXQgZW1wdHkgdXJsXG4gICAgaWYgKHdob2xlTWF0Y2guc2VhcmNoKC9cXCg8P1xccyo+PyA/KFsnXCJdLipbJ1wiXSk/XFwpJC9tKSA+IC0xKSB7XG4gICAgICB1cmwgPSAnJztcbiAgICB9IGVsc2UgaWYgKCF1cmwpIHtcbiAgICAgIGlmICghbGlua0lkKSB7XG4gICAgICAgIC8vIGxvd2VyLWNhc2UgYW5kIHR1cm4gZW1iZWRkZWQgbmV3bGluZXMgaW50byBzcGFjZXNcbiAgICAgICAgbGlua0lkID0gbGlua1RleHQudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC8gP1xcbi9nLCAnICcpO1xuICAgICAgfVxuICAgICAgdXJsID0gJyMnICsgbGlua0lkO1xuXG4gICAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChnbG9iYWxzLmdVcmxzW2xpbmtJZF0pKSB7XG4gICAgICAgIHVybCA9IGdsb2JhbHMuZ1VybHNbbGlua0lkXTtcbiAgICAgICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZ2xvYmFscy5nVGl0bGVzW2xpbmtJZF0pKSB7XG4gICAgICAgICAgdGl0bGUgPSBnbG9iYWxzLmdUaXRsZXNbbGlua0lkXTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHdob2xlTWF0Y2g7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy91cmwgPSBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyh1cmwsICcqXycsIGZhbHNlKTsgLy8gcmVwbGFjZWQgbGluZSB0byBpbXByb3ZlIHBlcmZvcm1hbmNlXG4gICAgdXJsID0gdXJsLnJlcGxhY2Uoc2hvd2Rvd24uaGVscGVyLnJlZ2V4ZXMuYXN0ZXJpc2tEYXNoQW5kQ29sb24sIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gICAgdmFyIHJlc3VsdCA9ICc8YSBocmVmPVwiJyArIHVybCArICdcIic7XG5cbiAgICBpZiAodGl0bGUgIT09ICcnICYmIHRpdGxlICE9PSBudWxsKSB7XG4gICAgICB0aXRsZSA9IHRpdGxlLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKTtcbiAgICAgIC8vdGl0bGUgPSBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyh0aXRsZSwgJypfJywgZmFsc2UpOyAvLyByZXBsYWNlZCBsaW5lIHRvIGltcHJvdmUgcGVyZm9ybWFuY2VcbiAgICAgIHRpdGxlID0gdGl0bGUucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgICByZXN1bHQgKz0gJyB0aXRsZT1cIicgKyB0aXRsZSArICdcIic7XG4gICAgfVxuXG4gICAgLy8gb3B0aW9uTGlua3NJbk5ld1dpbmRvdyBvbmx5IGFwcGxpZXNcbiAgICAvLyB0byBleHRlcm5hbCBsaW5rcy4gSGFzaCBsaW5rcyAoIykgb3BlbiBpbiBzYW1lIHBhZ2VcbiAgICBpZiAob3B0aW9ucy5vcGVuTGlua3NJbk5ld1dpbmRvdyAmJiAhL14jLy50ZXN0KHVybCkpIHtcbiAgICAgIC8vIGVzY2FwZWQgX1xuICAgICAgcmVzdWx0ICs9ICcgcmVsPVwibm9vcGVuZXIgbm9yZWZlcnJlclwiIHRhcmdldD1cIsKoRTk1RWJsYW5rXCInO1xuICAgIH1cblxuICAgIHJlc3VsdCArPSAnPicgKyBsaW5rVGV4dCArICc8L2E+JztcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gRmlyc3QsIGhhbmRsZSByZWZlcmVuY2Utc3R5bGUgbGlua3M6IFtsaW5rIHRleHRdIFtpZF1cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxbKCg/OlxcW1teXFxdXSpdfFteXFxbXFxdXSkqKV0gPyg/OlxcbiAqKT9cXFsoLio/KV0oKSgpKCkoKS9nLCB3cml0ZUFuY2hvclRhZyk7XG5cbiAgLy8gTmV4dCwgaW5saW5lLXN0eWxlIGxpbmtzOiBbbGluayB0ZXh0XSh1cmwgXCJvcHRpb25hbCB0aXRsZVwiKVxuICAvLyBjYXNlcyB3aXRoIGNyYXp5IHVybHMgbGlrZSAuL2ltYWdlL2NhdDEpLnBuZ1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFsoKD86XFxbW15cXF1dKl18W15cXFtcXF1dKSopXSgpWyBcXHRdKlxcKFsgXFx0XT88KFtePl0qKT4oPzpbIFxcdF0qKChbXCInXSkoW15cIl0qPylcXDUpKT9bIFxcdF0/XFwpL2csXG4gICAgd3JpdGVBbmNob3JUYWcpO1xuXG4gIC8vIG5vcm1hbCBjYXNlc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFsoKD86XFxbW15cXF1dKl18W15cXFtcXF1dKSopXSgpWyBcXHRdKlxcKFsgXFx0XT88PyhbXFxTXSs/KD86XFwoW1xcU10qP1xcKVtcXFNdKj8pPyk+Pyg/OlsgXFx0XSooKFtcIiddKShbXlwiXSo/KVxcNSkpP1sgXFx0XT9cXCkvZyxcbiAgICB3cml0ZUFuY2hvclRhZyk7XG5cbiAgLy8gaGFuZGxlIHJlZmVyZW5jZS1zdHlsZSBzaG9ydGN1dHM6IFtsaW5rIHRleHRdXG4gIC8vIFRoZXNlIG11c3QgY29tZSBsYXN0IGluIGNhc2UgeW91J3ZlIGFsc28gZ290IFtsaW5rIHRlc3RdWzFdXG4gIC8vIG9yIFtsaW5rIHRlc3RdKC9mb28pXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcWyhbXlxcW1xcXV0rKV0oKSgpKCkoKSgpL2csIHdyaXRlQW5jaG9yVGFnKTtcblxuICAvLyBMYXN0bHkgaGFuZGxlIEdpdGh1Yk1lbnRpb25zIGlmIG9wdGlvbiBpcyBlbmFibGVkXG4gIGlmIChvcHRpb25zLmdoTWVudGlvbnMpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oXnxcXHMpKFxcXFwpPyhAKFthLXpcXGRdKyg/OlthLXpcXGQuLV0rP1thLXpcXGRdKykqKSkvZ21pLCBmdW5jdGlvbiAod20sIHN0LCBlc2NhcGUsIG1lbnRpb25zLCB1c2VybmFtZSkge1xuICAgICAgaWYgKGVzY2FwZSA9PT0gJ1xcXFwnKSB7XG4gICAgICAgIHJldHVybiBzdCArIG1lbnRpb25zO1xuICAgICAgfVxuXG4gICAgICAvL2NoZWNrIGlmIG9wdGlvbnMuZ2hNZW50aW9uc0xpbmsgaXMgYSBzdHJpbmdcbiAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG9wdGlvbnMuZ2hNZW50aW9uc0xpbmspKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2hNZW50aW9uc0xpbmsgb3B0aW9uIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICAgIH1cbiAgICAgIHZhciBsbmsgPSBvcHRpb25zLmdoTWVudGlvbnNMaW5rLnJlcGxhY2UoL1xce3V9L2csIHVzZXJuYW1lKSxcbiAgICAgICAgICB0YXJnZXQgPSAnJztcbiAgICAgIGlmIChvcHRpb25zLm9wZW5MaW5rc0luTmV3V2luZG93KSB7XG4gICAgICAgIHRhcmdldCA9ICcgcmVsPVwibm9vcGVuZXIgbm9yZWZlcnJlclwiIHRhcmdldD1cIsKoRTk1RWJsYW5rXCInO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0ICsgJzxhIGhyZWY9XCInICsgbG5rICsgJ1wiJyArIHRhcmdldCArICc+JyArIG1lbnRpb25zICsgJzwvYT4nO1xuICAgIH0pO1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYW5jaG9ycy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8vIHVybCBhbGxvd2VkIGNoYXJzIFthLXpcXGRfLn46Lz8jW11AISQmJygpKissOz0tXVxuXG52YXIgc2ltcGxlVVJMUmVnZXggID0gLyhbKn5fXSt8XFxiKSgoKGh0dHBzP3xmdHB8ZGljdCk6XFwvXFwvfHd3d1xcLilbXidcIj5cXHNdKz9cXC5bXidcIj5cXHNdKz8pKCkoXFwxKT8oPz1cXHN8JCkoPyFbXCI8Pl0pL2dpLFxuICAgIHNpbXBsZVVSTFJlZ2V4MiA9IC8oWyp+X10rfFxcYikoKChodHRwcz98ZnRwfGRpY3QpOlxcL1xcL3x3d3dcXC4pW14nXCI+XFxzXStcXC5bXidcIj5cXHNdKz8pKFsuIT8sKClcXFtcXF1dKT8oXFwxKT8oPz1cXHN8JCkoPyFbXCI8Pl0pL2dpLFxuICAgIGRlbGltVXJsUmVnZXggICA9IC8oKTwoKChodHRwcz98ZnRwfGRpY3QpOlxcL1xcL3x3d3dcXC4pW14nXCI+XFxzXSspKCk+KCkvZ2ksXG4gICAgc2ltcGxlTWFpbFJlZ2V4ID0gLyhefFxccykoPzptYWlsdG86KT8oW0EtWmEtejAtOSEjJCUmJyorLS89P15fYHt8fX4uXStAWy1hLXowLTldKyhcXC5bLWEtejAtOV0rKSpcXC5bYS16XSspKD89JHxcXHMpL2dtaSxcbiAgICBkZWxpbU1haWxSZWdleCAgPSAvPCgpKD86bWFpbHRvOik/KFstLlxcd10rQFstYS16MC05XSsoXFwuWy1hLXowLTldKykqXFwuW2Etel0rKT4vZ2ksXG5cbiAgICByZXBsYWNlTGluayA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAndXNlIHN0cmljdCc7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gKHdtLCBsZWFkaW5nTWFnaWNDaGFycywgbGluaywgbTIsIG0zLCB0cmFpbGluZ1B1bmN0dWF0aW9uLCB0cmFpbGluZ01hZ2ljQ2hhcnMpIHtcbiAgICAgICAgbGluayA9IGxpbmsucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgICAgIHZhciBsbmtUeHQgPSBsaW5rLFxuICAgICAgICAgICAgYXBwZW5kID0gJycsXG4gICAgICAgICAgICB0YXJnZXQgPSAnJyxcbiAgICAgICAgICAgIGxtYyAgICA9IGxlYWRpbmdNYWdpY0NoYXJzIHx8ICcnLFxuICAgICAgICAgICAgdG1jICAgID0gdHJhaWxpbmdNYWdpY0NoYXJzIHx8ICcnO1xuICAgICAgICBpZiAoL153d3dcXC4vaS50ZXN0KGxpbmspKSB7XG4gICAgICAgICAgbGluayA9IGxpbmsucmVwbGFjZSgvXnd3d1xcLi9pLCAnaHR0cDovL3d3dy4nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5leGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzICYmIHRyYWlsaW5nUHVuY3R1YXRpb24pIHtcbiAgICAgICAgICBhcHBlbmQgPSB0cmFpbGluZ1B1bmN0dWF0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLm9wZW5MaW5rc0luTmV3V2luZG93KSB7XG4gICAgICAgICAgdGFyZ2V0ID0gJyByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCIgdGFyZ2V0PVwiwqhFOTVFYmxhbmtcIic7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxtYyArICc8YSBocmVmPVwiJyArIGxpbmsgKyAnXCInICsgdGFyZ2V0ICsgJz4nICsgbG5rVHh0ICsgJzwvYT4nICsgYXBwZW5kICsgdG1jO1xuICAgICAgfTtcbiAgICB9LFxuXG4gICAgcmVwbGFjZU1haWwgPSBmdW5jdGlvbiAob3B0aW9ucywgZ2xvYmFscykge1xuICAgICAgJ3VzZSBzdHJpY3QnO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBiLCBtYWlsKSB7XG4gICAgICAgIHZhciBocmVmID0gJ21haWx0bzonO1xuICAgICAgICBiID0gYiB8fCAnJztcbiAgICAgICAgbWFpbCA9IHNob3dkb3duLnN1YlBhcnNlcigndW5lc2NhcGVTcGVjaWFsQ2hhcnMnKShtYWlsLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgICAgaWYgKG9wdGlvbnMuZW5jb2RlRW1haWxzKSB7XG4gICAgICAgICAgaHJlZiA9IHNob3dkb3duLmhlbHBlci5lbmNvZGVFbWFpbEFkZHJlc3MoaHJlZiArIG1haWwpO1xuICAgICAgICAgIG1haWwgPSBzaG93ZG93bi5oZWxwZXIuZW5jb2RlRW1haWxBZGRyZXNzKG1haWwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGhyZWYgPSBocmVmICsgbWFpbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYiArICc8YSBocmVmPVwiJyArIGhyZWYgKyAnXCI+JyArIG1haWwgKyAnPC9hPic7XG4gICAgICB9O1xuICAgIH07XG5cbnNob3dkb3duLnN1YlBhcnNlcignYXV0b0xpbmtzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2F1dG9MaW5rcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGRlbGltVXJsUmVnZXgsIHJlcGxhY2VMaW5rKG9wdGlvbnMpKTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZShkZWxpbU1haWxSZWdleCwgcmVwbGFjZU1haWwob3B0aW9ucywgZ2xvYmFscykpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2F1dG9MaW5rcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cbnNob3dkb3duLnN1YlBhcnNlcignc2ltcGxpZmllZEF1dG9MaW5rcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMuc2ltcGxpZmllZEF1dG9MaW5rKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdzaW1wbGlmaWVkQXV0b0xpbmtzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIGlmIChvcHRpb25zLmV4Y2x1ZGVUcmFpbGluZ1B1bmN0dWF0aW9uRnJvbVVSTHMpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHNpbXBsZVVSTFJlZ2V4MiwgcmVwbGFjZUxpbmsob3B0aW9ucykpO1xuICB9IGVsc2Uge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2ltcGxlVVJMUmVnZXgsIHJlcGxhY2VMaW5rKG9wdGlvbnMpKTtcbiAgfVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHNpbXBsZU1haWxSZWdleCwgcmVwbGFjZU1haWwob3B0aW9ucywgZ2xvYmFscykpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3NpbXBsaWZpZWRBdXRvTGlua3MuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogVGhlc2UgYXJlIGFsbCB0aGUgdHJhbnNmb3JtYXRpb25zIHRoYXQgZm9ybSBibG9jay1sZXZlbFxuICogdGFncyBsaWtlIHBhcmFncmFwaHMsIGhlYWRlcnMsIGFuZCBsaXN0IGl0ZW1zLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2Jsb2NrR2FtdXQnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYmxvY2tHYW11dC5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyB3ZSBwYXJzZSBibG9ja3F1b3RlcyBmaXJzdCBzbyB0aGF0IHdlIGNhbiBoYXZlIGhlYWRpbmdzIGFuZCBocnNcbiAgLy8gaW5zaWRlIGJsb2NrcXVvdGVzXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2Jsb2NrUXVvdGVzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hlYWRlcnMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBEbyBIb3Jpem9udGFsIFJ1bGVzOlxuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdob3Jpem9udGFsUnVsZScpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2xpc3RzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2NvZGVCbG9ja3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcigndGFibGVzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gV2UgYWxyZWFkeSByYW4gX0hhc2hIVE1MQmxvY2tzKCkgYmVmb3JlLCBpbiBNYXJrZG93bigpLCBidXQgdGhhdFxuICAvLyB3YXMgdG8gZXNjYXBlIHJhdyBIVE1MIGluIHRoZSBvcmlnaW5hbCBNYXJrZG93biBzb3VyY2UuIFRoaXMgdGltZSxcbiAgLy8gd2UncmUgZXNjYXBpbmcgdGhlIG1hcmt1cCB3ZSd2ZSBqdXN0IGNyZWF0ZWQsIHNvIHRoYXQgd2UgZG9uJ3Qgd3JhcFxuICAvLyA8cD4gdGFncyBhcm91bmQgYmxvY2stbGV2ZWwgdGFncy5cbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxCbG9ja3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcigncGFyYWdyYXBocycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2Jsb2NrR2FtdXQuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignYmxvY2tRdW90ZXMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYmxvY2tRdW90ZXMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gYWRkIGEgY291cGxlIGV4dHJhIGxpbmVzIGFmdGVyIHRoZSB0ZXh0IGFuZCBlbmR0ZXh0IG1hcmtcbiAgdGV4dCA9IHRleHQgKyAnXFxuXFxuJztcblxuICB2YXIgcmd4ID0gLyheIHswLDN9PlsgXFx0XT8uK1xcbiguK1xcbikqXFxuKikrL2dtO1xuXG4gIGlmIChvcHRpb25zLnNwbGl0QWRqYWNlbnRCbG9ja3F1b3Rlcykge1xuICAgIHJneCA9IC9eIHswLDN9PltcXHNcXFNdKj8oPzpcXG5cXG4pL2dtO1xuICB9XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZShyZ3gsIGZ1bmN0aW9uIChicSkge1xuICAgIC8vIGF0dGFja2xhYjogaGFjayBhcm91bmQgS29ucXVlcm9yIDMuNS40IGJ1ZzpcbiAgICAvLyBcIi0tLS0tLS0tLS1idWdcIi5yZXBsYWNlKC9eLS9nLFwiXCIpID09IFwiYnVnXCJcbiAgICBicSA9IGJxLnJlcGxhY2UoL15bIFxcdF0qPlsgXFx0XT8vZ20sICcnKTsgLy8gdHJpbSBvbmUgbGV2ZWwgb2YgcXVvdGluZ1xuXG4gICAgLy8gYXR0YWNrbGFiOiBjbGVhbiB1cCBoYWNrXG4gICAgYnEgPSBicS5yZXBsYWNlKC/CqDAvZywgJycpO1xuXG4gICAgYnEgPSBicS5yZXBsYWNlKC9eWyBcXHRdKyQvZ20sICcnKTsgLy8gdHJpbSB3aGl0ZXNwYWNlLW9ubHkgbGluZXNcbiAgICBicSA9IHNob3dkb3duLnN1YlBhcnNlcignZ2l0aHViQ29kZUJsb2NrcycpKGJxLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBicSA9IHNob3dkb3duLnN1YlBhcnNlcignYmxvY2tHYW11dCcpKGJxLCBvcHRpb25zLCBnbG9iYWxzKTsgLy8gcmVjdXJzZVxuXG4gICAgYnEgPSBicS5yZXBsYWNlKC8oXnxcXG4pL2csICckMSAgJyk7XG4gICAgLy8gVGhlc2UgbGVhZGluZyBzcGFjZXMgc2NyZXcgd2l0aCA8cHJlPiBjb250ZW50LCBzbyB3ZSBuZWVkIHRvIGZpeCB0aGF0OlxuICAgIGJxID0gYnEucmVwbGFjZSgvKFxccyo8cHJlPlteXFxyXSs/PFxcL3ByZT4pL2dtLCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEpIHtcbiAgICAgIHZhciBwcmUgPSBtMTtcbiAgICAgIC8vIGF0dGFja2xhYjogaGFjayBhcm91bmQgS29ucXVlcm9yIDMuNS40IGJ1ZzpcbiAgICAgIHByZSA9IHByZS5yZXBsYWNlKC9eICAvbWcsICfCqDAnKTtcbiAgICAgIHByZSA9IHByZS5yZXBsYWNlKC/CqDAvZywgJycpO1xuICAgICAgcmV0dXJuIHByZTtcbiAgICB9KTtcblxuICAgIHJldHVybiBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hCbG9jaycpKCc8YmxvY2txdW90ZT5cXG4nICsgYnEgKyAnXFxuPC9ibG9ja3F1b3RlPicsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB9KTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdibG9ja1F1b3Rlcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogUHJvY2VzcyBNYXJrZG93biBgPHByZT48Y29kZT5gIGJsb2Nrcy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdjb2RlQmxvY2tzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2NvZGVCbG9ja3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gc2VudGluZWwgd29ya2Fyb3VuZHMgZm9yIGxhY2sgb2YgXFxBIGFuZCBcXFosIHNhZmFyaVxca2h0bWwgYnVnXG4gIHRleHQgKz0gJ8KoMCc7XG5cbiAgdmFyIHBhdHRlcm4gPSAvKD86XFxuXFxufF4pKCg/Oig/OlsgXXs0fXxcXHQpLipcXG4rKSspKFxcbipbIF17MCwzfVteIFxcdFxcbl18KD89wqgwKSkvZztcbiAgdGV4dCA9IHRleHQucmVwbGFjZShwYXR0ZXJuLCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEsIG0yKSB7XG4gICAgdmFyIGNvZGVibG9jayA9IG0xLFxuICAgICAgICBuZXh0Q2hhciA9IG0yLFxuICAgICAgICBlbmQgPSAnXFxuJztcblxuICAgIGNvZGVibG9jayA9IHNob3dkb3duLnN1YlBhcnNlcignb3V0ZGVudCcpKGNvZGVibG9jaywgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgY29kZWJsb2NrID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBjb2RlYmxvY2sgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2RldGFiJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBjb2RlYmxvY2sgPSBjb2RlYmxvY2sucmVwbGFjZSgvXlxcbisvZywgJycpOyAvLyB0cmltIGxlYWRpbmcgbmV3bGluZXNcbiAgICBjb2RlYmxvY2sgPSBjb2RlYmxvY2sucmVwbGFjZSgvXFxuKyQvZywgJycpOyAvLyB0cmltIHRyYWlsaW5nIG5ld2xpbmVzXG5cbiAgICBpZiAob3B0aW9ucy5vbWl0RXh0cmFXTEluQ29kZUJsb2Nrcykge1xuICAgICAgZW5kID0gJyc7XG4gICAgfVxuXG4gICAgY29kZWJsb2NrID0gJzxwcmU+PGNvZGU+JyArIGNvZGVibG9jayArIGVuZCArICc8L2NvZGU+PC9wcmU+JztcblxuICAgIHJldHVybiBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hCbG9jaycpKGNvZGVibG9jaywgb3B0aW9ucywgZ2xvYmFscykgKyBuZXh0Q2hhcjtcbiAgfSk7XG5cbiAgLy8gc3RyaXAgc2VudGluZWxcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqgwLywgJycpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2NvZGVCbG9ja3MuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqXG4gKiAgICogIEJhY2t0aWNrIHF1b3RlcyBhcmUgdXNlZCBmb3IgPGNvZGU+PC9jb2RlPiBzcGFucy5cbiAqXG4gKiAgICogIFlvdSBjYW4gdXNlIG11bHRpcGxlIGJhY2t0aWNrcyBhcyB0aGUgZGVsaW1pdGVycyBpZiB5b3Ugd2FudCB0b1xuICogICAgIGluY2x1ZGUgbGl0ZXJhbCBiYWNrdGlja3MgaW4gdGhlIGNvZGUgc3Bhbi4gU28sIHRoaXMgaW5wdXQ6XG4gKlxuICogICAgICAgICBKdXN0IHR5cGUgYGBmb28gYGJhcmAgYmF6YGAgYXQgdGhlIHByb21wdC5cbiAqXG4gKiAgICAgICBXaWxsIHRyYW5zbGF0ZSB0bzpcbiAqXG4gKiAgICAgICAgIDxwPkp1c3QgdHlwZSA8Y29kZT5mb28gYGJhcmAgYmF6PC9jb2RlPiBhdCB0aGUgcHJvbXB0LjwvcD5cbiAqXG4gKiAgICBUaGVyZSdzIG5vIGFyYml0cmFyeSBsaW1pdCB0byB0aGUgbnVtYmVyIG9mIGJhY2t0aWNrcyB5b3VcbiAqICAgIGNhbiB1c2UgYXMgZGVsaW10ZXJzLiBJZiB5b3UgbmVlZCB0aHJlZSBjb25zZWN1dGl2ZSBiYWNrdGlja3NcbiAqICAgIGluIHlvdXIgY29kZSwgdXNlIGZvdXIgZm9yIGRlbGltaXRlcnMsIGV0Yy5cbiAqXG4gKiAgKiAgWW91IGNhbiB1c2Ugc3BhY2VzIHRvIGdldCBsaXRlcmFsIGJhY2t0aWNrcyBhdCB0aGUgZWRnZXM6XG4gKlxuICogICAgICAgICAuLi4gdHlwZSBgYCBgYmFyYCBgYCAuLi5cbiAqXG4gKiAgICAgICBUdXJucyB0bzpcbiAqXG4gKiAgICAgICAgIC4uLiB0eXBlIDxjb2RlPmBiYXJgPC9jb2RlPiAuLi5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdjb2RlU3BhbnMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnY29kZVNwYW5zLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIGlmICh0eXBlb2YgdGV4dCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB0ZXh0ID0gJyc7XG4gIH1cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKF58W15cXFxcXSkoYCspKFteXFxyXSo/W15gXSlcXDIoPyFgKS9nbSxcbiAgICBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEsIG0yLCBtMykge1xuICAgICAgdmFyIGMgPSBtMztcbiAgICAgIGMgPSBjLnJlcGxhY2UoL14oWyBcXHRdKikvZywgJycpO1x0Ly8gbGVhZGluZyB3aGl0ZXNwYWNlXG4gICAgICBjID0gYy5yZXBsYWNlKC9bIFxcdF0qJC9nLCAnJyk7XHQvLyB0cmFpbGluZyB3aGl0ZXNwYWNlXG4gICAgICBjID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJykoYywgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICBjID0gbTEgKyAnPGNvZGU+JyArIGMgKyAnPC9jb2RlPic7XG4gICAgICBjID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoSFRNTFNwYW5zJykoYywgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICByZXR1cm4gYztcbiAgICB9XG4gICk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnY29kZVNwYW5zLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBDcmVhdGUgYSBmdWxsIEhUTUwgZG9jdW1lbnQgZnJvbSB0aGUgcHJvY2Vzc2VkIG1hcmtkb3duXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignY29tcGxldGVIVE1MRG9jdW1lbnQnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFvcHRpb25zLmNvbXBsZXRlSFRNTERvY3VtZW50KSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb21wbGV0ZUhUTUxEb2N1bWVudC5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIgZG9jdHlwZSA9ICdodG1sJyxcbiAgICAgIGRvY3R5cGVQYXJzZWQgPSAnPCFET0NUWVBFIEhUTUw+XFxuJyxcbiAgICAgIHRpdGxlID0gJycsXG4gICAgICBjaGFyc2V0ID0gJzxtZXRhIGNoYXJzZXQ9XCJ1dGYtOFwiPlxcbicsXG4gICAgICBsYW5nID0gJycsXG4gICAgICBtZXRhZGF0YSA9ICcnO1xuXG4gIGlmICh0eXBlb2YgZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWQuZG9jdHlwZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBkb2N0eXBlUGFyc2VkID0gJzwhRE9DVFlQRSAnICsgIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkLmRvY3R5cGUgKyAnPlxcbic7XG4gICAgZG9jdHlwZSA9IGdsb2JhbHMubWV0YWRhdGEucGFyc2VkLmRvY3R5cGUudG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmIChkb2N0eXBlID09PSAnaHRtbCcgfHwgZG9jdHlwZSA9PT0gJ2h0bWw1Jykge1xuICAgICAgY2hhcnNldCA9ICc8bWV0YSBjaGFyc2V0PVwidXRmLThcIj4nO1xuICAgIH1cbiAgfVxuXG4gIGZvciAodmFyIG1ldGEgaW4gZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWQpIHtcbiAgICBpZiAoZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWQuaGFzT3duUHJvcGVydHkobWV0YSkpIHtcbiAgICAgIHN3aXRjaCAobWV0YS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgIGNhc2UgJ2RvY3R5cGUnOlxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3RpdGxlJzpcbiAgICAgICAgICB0aXRsZSA9ICc8dGl0bGU+JyArICBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZC50aXRsZSArICc8L3RpdGxlPlxcbic7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnY2hhcnNldCc6XG4gICAgICAgICAgaWYgKGRvY3R5cGUgPT09ICdodG1sJyB8fCBkb2N0eXBlID09PSAnaHRtbDUnKSB7XG4gICAgICAgICAgICBjaGFyc2V0ID0gJzxtZXRhIGNoYXJzZXQ9XCInICsgZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWQuY2hhcnNldCArICdcIj5cXG4nO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGFyc2V0ID0gJzxtZXRhIG5hbWU9XCJjaGFyc2V0XCIgY29udGVudD1cIicgKyBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZC5jaGFyc2V0ICsgJ1wiPlxcbic7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ2xhbmd1YWdlJzpcbiAgICAgICAgY2FzZSAnbGFuZyc6XG4gICAgICAgICAgbGFuZyA9ICcgbGFuZz1cIicgKyBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZFttZXRhXSArICdcIic7XG4gICAgICAgICAgbWV0YWRhdGEgKz0gJzxtZXRhIG5hbWU9XCInICsgbWV0YSArICdcIiBjb250ZW50PVwiJyArIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkW21ldGFdICsgJ1wiPlxcbic7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBtZXRhZGF0YSArPSAnPG1ldGEgbmFtZT1cIicgKyBtZXRhICsgJ1wiIGNvbnRlbnQ9XCInICsgZ2xvYmFscy5tZXRhZGF0YS5wYXJzZWRbbWV0YV0gKyAnXCI+XFxuJztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB0ZXh0ID0gZG9jdHlwZVBhcnNlZCArICc8aHRtbCcgKyBsYW5nICsgJz5cXG48aGVhZD5cXG4nICsgdGl0bGUgKyBjaGFyc2V0ICsgbWV0YWRhdGEgKyAnPC9oZWFkPlxcbjxib2R5PlxcbicgKyB0ZXh0LnRyaW0oKSArICdcXG48L2JvZHk+XFxuPC9odG1sPic7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnY29tcGxldGVIVE1MRG9jdW1lbnQuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIENvbnZlcnQgYWxsIHRhYnMgdG8gc3BhY2VzXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignZGV0YWInLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2RldGFiLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIGV4cGFuZCBmaXJzdCBuLTEgdGFic1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHQoPz1cXHQpL2csICcgICAgJyk7IC8vIGdfdGFiX3dpZHRoXG5cbiAgLy8gcmVwbGFjZSB0aGUgbnRoIHdpdGggdHdvIHNlbnRpbmVsc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHQvZywgJ8KoQcKoQicpO1xuXG4gIC8vIHVzZSB0aGUgc2VudGluZWwgdG8gYW5jaG9yIG91ciByZWdleCBzbyBpdCBkb2Vzbid0IGV4cGxvZGVcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqhCKC4rPynCqEEvZywgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xKSB7XG4gICAgdmFyIGxlYWRpbmdUZXh0ID0gbTEsXG4gICAgICAgIG51bVNwYWNlcyA9IDQgLSBsZWFkaW5nVGV4dC5sZW5ndGggJSA0OyAgLy8gZ190YWJfd2lkdGhcblxuICAgIC8vIHRoZXJlICptdXN0KiBiZSBhIGJldHRlciB3YXkgdG8gZG8gdGhpczpcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bVNwYWNlczsgaSsrKSB7XG4gICAgICBsZWFkaW5nVGV4dCArPSAnICc7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxlYWRpbmdUZXh0O1xuICB9KTtcblxuICAvLyBjbGVhbiB1cCBzZW50aW5lbHNcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqhBL2csICcgICAgJyk7ICAvLyBnX3RhYl93aWR0aFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqEIvZywgJycpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2RldGFiLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdlbGxpcHNpcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbGxpcHNpcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXC5cXC5cXC4vZywgJ+KApicpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VsbGlwc2lzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFR1cm4gZW1vamkgY29kZXMgaW50byBlbW9qaXNcbiAqXG4gKiBMaXN0IG9mIHN1cHBvcnRlZCBlbW9qaXM6IGh0dHBzOi8vZ2l0aHViLmNvbS9zaG93ZG93bmpzL3Nob3dkb3duL3dpa2kvRW1vamlzXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignZW1vamknLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFvcHRpb25zLmVtb2ppKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbW9qaS5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIgZW1vamlSZ3ggPSAvOihbXFxTXSs/KTovZztcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGVtb2ppUmd4LCBmdW5jdGlvbiAod20sIGVtb2ppQ29kZSkge1xuICAgIGlmIChzaG93ZG93bi5oZWxwZXIuZW1vamlzLmhhc093blByb3BlcnR5KGVtb2ppQ29kZSkpIHtcbiAgICAgIHJldHVybiBzaG93ZG93bi5oZWxwZXIuZW1vamlzW2Vtb2ppQ29kZV07XG4gICAgfVxuICAgIHJldHVybiB3bTtcbiAgfSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZW1vamkuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogU21hcnQgcHJvY2Vzc2luZyBmb3IgYW1wZXJzYW5kcyBhbmQgYW5nbGUgYnJhY2tldHMgdGhhdCBuZWVkIHRvIGJlIGVuY29kZWQuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQW1wc0FuZEFuZ2xlcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZW5jb2RlQW1wc0FuZEFuZ2xlcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBBbXBlcnNhbmQtZW5jb2RpbmcgYmFzZWQgZW50aXJlbHkgb24gTmF0IElyb25zJ3MgQW1wdXRhdG9yIE1UIHBsdWdpbjpcbiAgLy8gaHR0cDovL2J1bXBwby5uZXQvcHJvamVjdHMvYW1wdXRhdG9yL1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8mKD8hIz9beFhdPyg/OlswLTlhLWZBLUZdK3xcXHcrKTspL2csICcmYW1wOycpO1xuXG4gIC8vIEVuY29kZSBuYWtlZCA8J3NcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvPCg/IVthLXpcXC8/JCFdKS9naSwgJyZsdDsnKTtcblxuICAvLyBFbmNvZGUgPFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC88L2csICcmbHQ7Jyk7XG5cbiAgLy8gRW5jb2RlID5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvPi9nLCAnJmd0OycpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VuY29kZUFtcHNBbmRBbmdsZXMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFJldHVybnMgdGhlIHN0cmluZywgd2l0aCBhZnRlciBwcm9jZXNzaW5nIHRoZSBmb2xsb3dpbmcgYmFja3NsYXNoIGVzY2FwZSBzZXF1ZW5jZXMuXG4gKlxuICogYXR0YWNrbGFiOiBUaGUgcG9saXRlIHdheSB0byBkbyB0aGlzIGlzIHdpdGggdGhlIG5ldyBlc2NhcGVDaGFyYWN0ZXJzKCkgZnVuY3Rpb246XG4gKlxuICogICAgdGV4dCA9IGVzY2FwZUNoYXJhY3RlcnModGV4dCxcIlxcXFxcIix0cnVlKTtcbiAqICAgIHRleHQgPSBlc2NhcGVDaGFyYWN0ZXJzKHRleHQsXCJgKl97fVtdKCk+IystLiFcIix0cnVlKTtcbiAqXG4gKiAuLi5idXQgd2UncmUgc2lkZXN0ZXBwaW5nIGl0cyB1c2Ugb2YgdGhlIChzbG93KSBSZWdFeHAgY29uc3RydWN0b3JcbiAqIGFzIGFuIG9wdGltaXphdGlvbiBmb3IgRmlyZWZveC4gIFRoaXMgZnVuY3Rpb24gZ2V0cyBjYWxsZWQgYSBMT1QuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQmFja3NsYXNoRXNjYXBlcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZW5jb2RlQmFja3NsYXNoRXNjYXBlcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFxcKFxcXFwpL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFxcKFtgKl97fVxcW1xcXSgpPiMrLiF+PXwtXSkvZywgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnZW5jb2RlQmFja3NsYXNoRXNjYXBlcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogRW5jb2RlL2VzY2FwZSBjZXJ0YWluIGNoYXJhY3RlcnMgaW5zaWRlIE1hcmtkb3duIGNvZGUgcnVucy5cbiAqIFRoZSBwb2ludCBpcyB0aGF0IGluIGNvZGUsIHRoZXNlIGNoYXJhY3RlcnMgYXJlIGxpdGVyYWxzLFxuICogYW5kIGxvc2UgdGhlaXIgc3BlY2lhbCBNYXJrZG93biBtZWFuaW5ncy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2VuY29kZUNvZGUuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gRW5jb2RlIGFsbCBhbXBlcnNhbmRzOyBIVE1MIGVudGl0aWVzIGFyZSBub3RcbiAgLy8gZW50aXRpZXMgd2l0aGluIGEgTWFya2Rvd24gY29kZSBzcGFuLlxuICB0ZXh0ID0gdGV4dFxuICAgIC5yZXBsYWNlKC8mL2csICcmYW1wOycpXG4gIC8vIERvIHRoZSBhbmdsZSBicmFja2V0IHNvbmcgYW5kIGRhbmNlOlxuICAgIC5yZXBsYWNlKC88L2csICcmbHQ7JylcbiAgICAucmVwbGFjZSgvPi9nLCAnJmd0OycpXG4gIC8vIE5vdywgZXNjYXBlIGNoYXJhY3RlcnMgdGhhdCBhcmUgbWFnaWMgaW4gTWFya2Rvd246XG4gICAgLnJlcGxhY2UoLyhbKl97fVxcW1xcXVxcXFw9fi1dKS9nLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlbmNvZGVDb2RlLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBXaXRoaW4gdGFncyAtLSBtZWFuaW5nIGJldHdlZW4gPCBhbmQgPiAtLSBlbmNvZGUgW1xcIGAgKiBfIH4gPV0gc28gdGhleVxuICogZG9uJ3QgY29uZmxpY3Qgd2l0aCB0aGVpciB1c2UgaW4gTWFya2Rvd24gZm9yIGNvZGUsIGl0YWxpY3MgYW5kIHN0cm9uZy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdlc2NhcGVTcGVjaWFsQ2hhcnNXaXRoaW5UYWdBdHRyaWJ1dGVzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlc2NhcGVTcGVjaWFsQ2hhcnNXaXRoaW5UYWdBdHRyaWJ1dGVzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIEJ1aWxkIGEgcmVnZXggdG8gZmluZCBIVE1MIHRhZ3MuXG4gIHZhciB0YWdzICAgICA9IC88XFwvP1thLXpcXGRfOi1dKyg/OltcXHNdK1tcXHNcXFNdKz8pPz4vZ2ksXG4gICAgICBjb21tZW50cyA9IC88ISgtLSg/Oig/OltePi1dfC1bXj5dKSg/OlteLV18LVteLV0pKiktLSk+L2dpO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UodGFncywgZnVuY3Rpb24gKHdob2xlTWF0Y2gpIHtcbiAgICByZXR1cm4gd2hvbGVNYXRjaFxuICAgICAgLnJlcGxhY2UoLyguKTxcXC8/Y29kZT4oPz0uKS9nLCAnJDFgJylcbiAgICAgIC5yZXBsYWNlKC8oW1xcXFxgKl9+PXxdKS9nLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcbiAgfSk7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZShjb21tZW50cywgZnVuY3Rpb24gKHdob2xlTWF0Y2gpIHtcbiAgICByZXR1cm4gd2hvbGVNYXRjaFxuICAgICAgLnJlcGxhY2UoLyhbXFxcXGAqX349fF0pL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuICB9KTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdlc2NhcGVTcGVjaWFsQ2hhcnNXaXRoaW5UYWdBdHRyaWJ1dGVzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBIYW5kbGUgZ2l0aHViIGNvZGVibG9ja3MgcHJpb3IgdG8gcnVubmluZyBIYXNoSFRNTCBzbyB0aGF0XG4gKiBIVE1MIGNvbnRhaW5lZCB3aXRoaW4gdGhlIGNvZGVibG9jayBnZXRzIGVzY2FwZWQgcHJvcGVybHlcbiAqIEV4YW1wbGU6XG4gKiBgYGBydWJ5XG4gKiAgICAgZGVmIGhlbGxvX3dvcmxkKHgpXG4gKiAgICAgICBwdXRzIFwiSGVsbG8sICN7eH1cIlxuICogICAgIGVuZFxuICogYGBgXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignZ2l0aHViQ29kZUJsb2NrcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvLyBlYXJseSBleGl0IGlmIG9wdGlvbiBpcyBub3QgZW5hYmxlZFxuICBpZiAoIW9wdGlvbnMuZ2hDb2RlQmxvY2tzKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdnaXRodWJDb2RlQmxvY2tzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgKz0gJ8KoMCc7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKD86XnxcXG4pKD86IHswLDN9KShgYGArfH5+fispKD86ICopKFteXFxzYH5dKilcXG4oW1xcc1xcU10qPylcXG4oPzogezAsM30pXFwxL2csIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBkZWxpbSwgbGFuZ3VhZ2UsIGNvZGVibG9jaykge1xuICAgIHZhciBlbmQgPSAob3B0aW9ucy5vbWl0RXh0cmFXTEluQ29kZUJsb2NrcykgPyAnJyA6ICdcXG4nO1xuXG4gICAgLy8gRmlyc3QgcGFyc2UgdGhlIGdpdGh1YiBjb2RlIGJsb2NrXG4gICAgY29kZWJsb2NrID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBjb2RlYmxvY2sgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2RldGFiJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBjb2RlYmxvY2sgPSBjb2RlYmxvY2sucmVwbGFjZSgvXlxcbisvZywgJycpOyAvLyB0cmltIGxlYWRpbmcgbmV3bGluZXNcbiAgICBjb2RlYmxvY2sgPSBjb2RlYmxvY2sucmVwbGFjZSgvXFxuKyQvZywgJycpOyAvLyB0cmltIHRyYWlsaW5nIHdoaXRlc3BhY2VcblxuICAgIGNvZGVibG9jayA9ICc8cHJlPjxjb2RlJyArIChsYW5ndWFnZSA/ICcgY2xhc3M9XCInICsgbGFuZ3VhZ2UgKyAnIGxhbmd1YWdlLScgKyBsYW5ndWFnZSArICdcIicgOiAnJykgKyAnPicgKyBjb2RlYmxvY2sgKyBlbmQgKyAnPC9jb2RlPjwvcHJlPic7XG5cbiAgICBjb2RlYmxvY2sgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hCbG9jaycpKGNvZGVibG9jaywgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgICAvLyBTaW5jZSBHSENvZGVibG9ja3MgY2FuIGJlIGZhbHNlIHBvc2l0aXZlcywgd2UgbmVlZCB0b1xuICAgIC8vIHN0b3JlIHRoZSBwcmltaXRpdmUgdGV4dCBhbmQgdGhlIHBhcnNlZCB0ZXh0IGluIGEgZ2xvYmFsIHZhcixcbiAgICAvLyBhbmQgdGhlbiByZXR1cm4gYSB0b2tlblxuICAgIHJldHVybiAnXFxuXFxuwqhHJyArIChnbG9iYWxzLmdoQ29kZUJsb2Nrcy5wdXNoKHt0ZXh0OiB3aG9sZU1hdGNoLCBjb2RlYmxvY2s6IGNvZGVibG9ja30pIC0gMSkgKyAnR1xcblxcbic7XG4gIH0pO1xuXG4gIC8vIGF0dGFja2xhYjogc3RyaXAgc2VudGluZWxcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqgwLywgJycpO1xuXG4gIHJldHVybiBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2dpdGh1YkNvZGVCbG9ja3MuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdoYXNoQmxvY2suYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyheXFxuK3xcXG4rJCkvZywgJycpO1xuICB0ZXh0ID0gJ1xcblxcbsKoSycgKyAoZ2xvYmFscy5nSHRtbEJsb2Nrcy5wdXNoKHRleHQpIC0gMSkgKyAnS1xcblxcbic7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hCbG9jay5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogSGFzaCBhbmQgZXNjYXBlIDxjb2RlPiBlbGVtZW50cyB0aGF0IHNob3VsZCBub3QgYmUgcGFyc2VkIGFzIG1hcmtkb3duXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignaGFzaENvZGVUYWdzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdoYXNoQ29kZVRhZ3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdmFyIHJlcEZ1bmMgPSBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbWF0Y2gsIGxlZnQsIHJpZ2h0KSB7XG4gICAgdmFyIGNvZGVibG9jayA9IGxlZnQgKyBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnKShtYXRjaCwgb3B0aW9ucywgZ2xvYmFscykgKyByaWdodDtcbiAgICByZXR1cm4gJ8KoQycgKyAoZ2xvYmFscy5nSHRtbFNwYW5zLnB1c2goY29kZWJsb2NrKSAtIDEpICsgJ0MnO1xuICB9O1xuXG4gIC8vIEhhc2ggbmFrZWQgPGNvZGU+XG4gIHRleHQgPSBzaG93ZG93bi5oZWxwZXIucmVwbGFjZVJlY3Vyc2l2ZVJlZ0V4cCh0ZXh0LCByZXBGdW5jLCAnPGNvZGVcXFxcYltePl0qPicsICc8L2NvZGU+JywgJ2dpbScpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hDb2RlVGFncy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignaGFzaEVsZW1lbnQnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSkge1xuICAgIHZhciBibG9ja1RleHQgPSBtMTtcblxuICAgIC8vIFVuZG8gZG91YmxlIGxpbmVzXG4gICAgYmxvY2tUZXh0ID0gYmxvY2tUZXh0LnJlcGxhY2UoL1xcblxcbi9nLCAnXFxuJyk7XG4gICAgYmxvY2tUZXh0ID0gYmxvY2tUZXh0LnJlcGxhY2UoL15cXG4vLCAnJyk7XG5cbiAgICAvLyBzdHJpcCB0cmFpbGluZyBibGFuayBsaW5lc1xuICAgIGJsb2NrVGV4dCA9IGJsb2NrVGV4dC5yZXBsYWNlKC9cXG4rJC9nLCAnJyk7XG5cbiAgICAvLyBSZXBsYWNlIHRoZSBlbGVtZW50IHRleHQgd2l0aCBhIG1hcmtlciAoXCLCqEt4S1wiIHdoZXJlIHggaXMgaXRzIGtleSlcbiAgICBibG9ja1RleHQgPSAnXFxuXFxuwqhLJyArIChnbG9iYWxzLmdIdG1sQmxvY2tzLnB1c2goYmxvY2tUZXh0KSAtIDEpICsgJ0tcXG5cXG4nO1xuXG4gICAgcmV0dXJuIGJsb2NrVGV4dDtcbiAgfTtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxCbG9ja3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hIVE1MQmxvY2tzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciBibG9ja1RhZ3MgPSBbXG4gICAgICAgICdwcmUnLFxuICAgICAgICAnZGl2JyxcbiAgICAgICAgJ2gxJyxcbiAgICAgICAgJ2gyJyxcbiAgICAgICAgJ2gzJyxcbiAgICAgICAgJ2g0JyxcbiAgICAgICAgJ2g1JyxcbiAgICAgICAgJ2g2JyxcbiAgICAgICAgJ2Jsb2NrcXVvdGUnLFxuICAgICAgICAndGFibGUnLFxuICAgICAgICAnZGwnLFxuICAgICAgICAnb2wnLFxuICAgICAgICAndWwnLFxuICAgICAgICAnc2NyaXB0JyxcbiAgICAgICAgJ25vc2NyaXB0JyxcbiAgICAgICAgJ2Zvcm0nLFxuICAgICAgICAnZmllbGRzZXQnLFxuICAgICAgICAnaWZyYW1lJyxcbiAgICAgICAgJ21hdGgnLFxuICAgICAgICAnc3R5bGUnLFxuICAgICAgICAnc2VjdGlvbicsXG4gICAgICAgICdoZWFkZXInLFxuICAgICAgICAnZm9vdGVyJyxcbiAgICAgICAgJ25hdicsXG4gICAgICAgICdhcnRpY2xlJyxcbiAgICAgICAgJ2FzaWRlJyxcbiAgICAgICAgJ2FkZHJlc3MnLFxuICAgICAgICAnYXVkaW8nLFxuICAgICAgICAnY2FudmFzJyxcbiAgICAgICAgJ2ZpZ3VyZScsXG4gICAgICAgICdoZ3JvdXAnLFxuICAgICAgICAnb3V0cHV0JyxcbiAgICAgICAgJ3ZpZGVvJyxcbiAgICAgICAgJ3AnXG4gICAgICBdLFxuICAgICAgcmVwRnVuYyA9IGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtYXRjaCwgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgdmFyIHR4dCA9IHdob2xlTWF0Y2g7XG4gICAgICAgIC8vIGNoZWNrIGlmIHRoaXMgaHRtbCBlbGVtZW50IGlzIG1hcmtlZCBhcyBtYXJrZG93blxuICAgICAgICAvLyBpZiBzbywgaXQncyBjb250ZW50cyBzaG91bGQgYmUgcGFyc2VkIGFzIG1hcmtkb3duXG4gICAgICAgIGlmIChsZWZ0LnNlYXJjaCgvXFxibWFya2Rvd25cXGIvKSAhPT0gLTEpIHtcbiAgICAgICAgICB0eHQgPSBsZWZ0ICsgZ2xvYmFscy5jb252ZXJ0ZXIubWFrZUh0bWwobWF0Y2gpICsgcmlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICdcXG5cXG7CqEsnICsgKGdsb2JhbHMuZ0h0bWxCbG9ja3MucHVzaCh0eHQpIC0gMSkgKyAnS1xcblxcbic7XG4gICAgICB9O1xuXG4gIGlmIChvcHRpb25zLmJhY2tzbGFzaEVzY2FwZXNIVE1MVGFncykge1xuICAgIC8vIGVuY29kZSBiYWNrc2xhc2ggZXNjYXBlZCBIVE1MIHRhZ3NcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFxcPChcXC8/W14+XSs/KT4vZywgZnVuY3Rpb24gKHdtLCBpbnNpZGUpIHtcbiAgICAgIHJldHVybiAnJmx0OycgKyBpbnNpZGUgKyAnJmd0Oyc7XG4gICAgfSk7XG4gIH1cblxuICAvLyBoYXNoIEhUTUwgQmxvY2tzXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tUYWdzLmxlbmd0aDsgKytpKSB7XG5cbiAgICB2YXIgb3BUYWdQb3MsXG4gICAgICAgIHJneDEgICAgID0gbmV3IFJlZ0V4cCgnXiB7MCwzfSg8JyArIGJsb2NrVGFnc1tpXSArICdcXFxcYltePl0qPiknLCAnaW0nKSxcbiAgICAgICAgcGF0TGVmdCAgPSAnPCcgKyBibG9ja1RhZ3NbaV0gKyAnXFxcXGJbXj5dKj4nLFxuICAgICAgICBwYXRSaWdodCA9ICc8LycgKyBibG9ja1RhZ3NbaV0gKyAnPic7XG4gICAgLy8gMS4gTG9vayBmb3IgdGhlIGZpcnN0IHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBvcGVuaW5nIEhUTUwgdGFnIGluIHRoZSB0ZXh0XG4gICAgd2hpbGUgKChvcFRhZ1BvcyA9IHNob3dkb3duLmhlbHBlci5yZWdleEluZGV4T2YodGV4dCwgcmd4MSkpICE9PSAtMSkge1xuXG4gICAgICAvLyBpZiB0aGUgSFRNTCB0YWcgaXMgXFwgZXNjYXBlZCwgd2UgbmVlZCB0byBlc2NhcGUgaXQgYW5kIGJyZWFrXG5cblxuICAgICAgLy8yLiBTcGxpdCB0aGUgdGV4dCBpbiB0aGF0IHBvc2l0aW9uXG4gICAgICB2YXIgc3ViVGV4dHMgPSBzaG93ZG93bi5oZWxwZXIuc3BsaXRBdEluZGV4KHRleHQsIG9wVGFnUG9zKSxcbiAgICAgICAgICAvLzMuIE1hdGNoIHJlY3Vyc2l2ZWx5XG4gICAgICAgICAgbmV3U3ViVGV4dDEgPSBzaG93ZG93bi5oZWxwZXIucmVwbGFjZVJlY3Vyc2l2ZVJlZ0V4cChzdWJUZXh0c1sxXSwgcmVwRnVuYywgcGF0TGVmdCwgcGF0UmlnaHQsICdpbScpO1xuXG4gICAgICAvLyBwcmV2ZW50IGFuIGluZmluaXRlIGxvb3BcbiAgICAgIGlmIChuZXdTdWJUZXh0MSA9PT0gc3ViVGV4dHNbMV0pIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB0ZXh0ID0gc3ViVGV4dHNbMF0uY29uY2F0KG5ld1N1YlRleHQxKTtcbiAgICB9XG4gIH1cbiAgLy8gSFIgU1BFQ0lBTCBDQVNFXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhcXG4gezAsM30oPChocilcXGIoW148Pl0pKj9cXC8/PilbIFxcdF0qKD89XFxuezIsfSkpL2csXG4gICAgc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoRWxlbWVudCcpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpKTtcblxuICAvLyBTcGVjaWFsIGNhc2UgZm9yIHN0YW5kYWxvbmUgSFRNTCBjb21tZW50c1xuICB0ZXh0ID0gc2hvd2Rvd24uaGVscGVyLnJlcGxhY2VSZWN1cnNpdmVSZWdFeHAodGV4dCwgZnVuY3Rpb24gKHR4dCkge1xuICAgIHJldHVybiAnXFxuXFxuwqhLJyArIChnbG9iYWxzLmdIdG1sQmxvY2tzLnB1c2godHh0KSAtIDEpICsgJ0tcXG5cXG4nO1xuICB9LCAnXiB7MCwzfTwhLS0nLCAnLS0+JywgJ2dtJyk7XG5cbiAgLy8gUEhQIGFuZCBBU1Atc3R5bGUgcHJvY2Vzc29yIGluc3RydWN0aW9ucyAoPD8uLi4/PiBhbmQgPCUuLi4lPilcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKD86XFxuXFxuKSggezAsM30oPzo8KFs/JV0pW15cXHJdKj9cXDI+KVsgXFx0XSooPz1cXG57Mix9KSkvZyxcbiAgICBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hFbGVtZW50JykodGV4dCwgb3B0aW9ucywgZ2xvYmFscykpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hIVE1MQmxvY2tzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBIYXNoIHNwYW4gZWxlbWVudHMgdGhhdCBzaG91bGQgbm90IGJlIHBhcnNlZCBhcyBtYXJrZG93blxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hIVE1MU3BhbnMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hIVE1MU3BhbnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgZnVuY3Rpb24gaGFzaEhUTUxTcGFuIChodG1sKSB7XG4gICAgcmV0dXJuICfCqEMnICsgKGdsb2JhbHMuZ0h0bWxTcGFucy5wdXNoKGh0bWwpIC0gMSkgKyAnQyc7XG4gIH1cblxuICAvLyBIYXNoIFNlbGYgQ2xvc2luZyB0YWdzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLzxbXj5dKz9cXC8+L2dpLCBmdW5jdGlvbiAod20pIHtcbiAgICByZXR1cm4gaGFzaEhUTUxTcGFuKHdtKTtcbiAgfSk7XG5cbiAgLy8gSGFzaCB0YWdzIHdpdGhvdXQgcHJvcGVydGllc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC88KFtePl0rPyk+W1xcc1xcU10qPzxcXC9cXDE+L2csIGZ1bmN0aW9uICh3bSkge1xuICAgIHJldHVybiBoYXNoSFRNTFNwYW4od20pO1xuICB9KTtcblxuICAvLyBIYXNoIHRhZ3Mgd2l0aCBwcm9wZXJ0aWVzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLzwoW14+XSs/KVxcc1tePl0rPz5bXFxzXFxTXSo/PFxcL1xcMT4vZywgZnVuY3Rpb24gKHdtKSB7XG4gICAgcmV0dXJuIGhhc2hIVE1MU3Bhbih3bSk7XG4gIH0pO1xuXG4gIC8vIEhhc2ggc2VsZiBjbG9zaW5nIHRhZ3Mgd2l0aG91dCAvPlxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC88W14+XSs/Pi9naSwgZnVuY3Rpb24gKHdtKSB7XG4gICAgcmV0dXJuIGhhc2hIVE1MU3Bhbih3bSk7XG4gIH0pO1xuXG4gIC8qc2hvd2Rvd24uaGVscGVyLm1hdGNoUmVjdXJzaXZlUmVnRXhwKHRleHQsICc8Y29kZVxcXFxiW14+XSo+JywgJzwvY29kZT4nLCAnZ2knKTsqL1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hIVE1MU3BhbnMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxuLyoqXG4gKiBVbmhhc2ggSFRNTCBzcGFuc1xuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3VuaGFzaEhUTUxTcGFucycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgndW5oYXNoSFRNTFNwYW5zLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZ2xvYmFscy5nSHRtbFNwYW5zLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHJlcFRleHQgPSBnbG9iYWxzLmdIdG1sU3BhbnNbaV0sXG4gICAgICAgIC8vIGxpbWl0ZXIgdG8gcHJldmVudCBpbmZpbml0ZSBsb29wIChhc3N1bWUgMTAgYXMgbGltaXQgZm9yIHJlY3Vyc2UpXG4gICAgICAgIGxpbWl0ID0gMDtcblxuICAgIHdoaWxlICgvwqhDKFxcZCspQy8udGVzdChyZXBUZXh0KSkge1xuICAgICAgdmFyIG51bSA9IFJlZ0V4cC4kMTtcbiAgICAgIHJlcFRleHQgPSByZXBUZXh0LnJlcGxhY2UoJ8KoQycgKyBudW0gKyAnQycsIGdsb2JhbHMuZ0h0bWxTcGFuc1tudW1dKTtcbiAgICAgIGlmIChsaW1pdCA9PT0gMTApIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignbWF4aW11bSBuZXN0aW5nIG9mIDEwIHNwYW5zIHJlYWNoZWQhISEnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICArK2xpbWl0O1xuICAgIH1cbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKCfCqEMnICsgaSArICdDJywgcmVwVGV4dCk7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmhhc2hIVE1MU3BhbnMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIEhhc2ggYW5kIGVzY2FwZSA8cHJlPjxjb2RlPiBlbGVtZW50cyB0aGF0IHNob3VsZCBub3QgYmUgcGFyc2VkIGFzIG1hcmtkb3duXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignaGFzaFByZUNvZGVUYWdzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdoYXNoUHJlQ29kZVRhZ3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdmFyIHJlcEZ1bmMgPSBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbWF0Y2gsIGxlZnQsIHJpZ2h0KSB7XG4gICAgLy8gZW5jb2RlIGh0bWwgZW50aXRpZXNcbiAgICB2YXIgY29kZWJsb2NrID0gbGVmdCArIHNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQ29kZScpKG1hdGNoLCBvcHRpb25zLCBnbG9iYWxzKSArIHJpZ2h0O1xuICAgIHJldHVybiAnXFxuXFxuwqhHJyArIChnbG9iYWxzLmdoQ29kZUJsb2Nrcy5wdXNoKHt0ZXh0OiB3aG9sZU1hdGNoLCBjb2RlYmxvY2s6IGNvZGVibG9ja30pIC0gMSkgKyAnR1xcblxcbic7XG4gIH07XG5cbiAgLy8gSGFzaCA8cHJlPjxjb2RlPlxuICB0ZXh0ID0gc2hvd2Rvd24uaGVscGVyLnJlcGxhY2VSZWN1cnNpdmVSZWdFeHAodGV4dCwgcmVwRnVuYywgJ14gezAsM308cHJlXFxcXGJbXj5dKj5cXFxccyo8Y29kZVxcXFxiW14+XSo+JywgJ14gezAsM308L2NvZGU+XFxcXHMqPC9wcmU+JywgJ2dpbScpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hQcmVDb2RlVGFncy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignaGVhZGVycycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdoZWFkZXJzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciBoZWFkZXJMZXZlbFN0YXJ0ID0gKGlzTmFOKHBhcnNlSW50KG9wdGlvbnMuaGVhZGVyTGV2ZWxTdGFydCkpKSA/IDEgOiBwYXJzZUludChvcHRpb25zLmhlYWRlckxldmVsU3RhcnQpLFxuXG4gICAgICAvLyBTZXQgdGV4dC1zdHlsZSBoZWFkZXJzOlxuICAgICAgLy9cdEhlYWRlciAxXG4gICAgICAvL1x0PT09PT09PT1cbiAgICAgIC8vXG4gICAgICAvL1x0SGVhZGVyIDJcbiAgICAgIC8vXHQtLS0tLS0tLVxuICAgICAgLy9cbiAgICAgIHNldGV4dFJlZ2V4SDEgPSAob3B0aW9ucy5zbW9vdGhMaXZlUHJldmlldykgPyAvXiguKylbIFxcdF0qXFxuPXsyLH1bIFxcdF0qXFxuKy9nbSA6IC9eKC4rKVsgXFx0XSpcXG49K1sgXFx0XSpcXG4rL2dtLFxuICAgICAgc2V0ZXh0UmVnZXhIMiA9IChvcHRpb25zLnNtb290aExpdmVQcmV2aWV3KSA/IC9eKC4rKVsgXFx0XSpcXG4tezIsfVsgXFx0XSpcXG4rL2dtIDogL14oLispWyBcXHRdKlxcbi0rWyBcXHRdKlxcbisvZ207XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZShzZXRleHRSZWdleEgxLCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEpIHtcblxuICAgIHZhciBzcGFuR2FtdXQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcpKG0xLCBvcHRpb25zLCBnbG9iYWxzKSxcbiAgICAgICAgaElEID0gKG9wdGlvbnMubm9IZWFkZXJJZCkgPyAnJyA6ICcgaWQ9XCInICsgaGVhZGVySWQobTEpICsgJ1wiJyxcbiAgICAgICAgaExldmVsID0gaGVhZGVyTGV2ZWxTdGFydCxcbiAgICAgICAgaGFzaEJsb2NrID0gJzxoJyArIGhMZXZlbCArIGhJRCArICc+JyArIHNwYW5HYW11dCArICc8L2gnICsgaExldmVsICsgJz4nO1xuICAgIHJldHVybiBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hCbG9jaycpKGhhc2hCbG9jaywgb3B0aW9ucywgZ2xvYmFscyk7XG4gIH0pO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2V0ZXh0UmVnZXhIMiwgZnVuY3Rpb24gKG1hdGNoRm91bmQsIG0xKSB7XG4gICAgdmFyIHNwYW5HYW11dCA9IHNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0JykobTEsIG9wdGlvbnMsIGdsb2JhbHMpLFxuICAgICAgICBoSUQgPSAob3B0aW9ucy5ub0hlYWRlcklkKSA/ICcnIDogJyBpZD1cIicgKyBoZWFkZXJJZChtMSkgKyAnXCInLFxuICAgICAgICBoTGV2ZWwgPSBoZWFkZXJMZXZlbFN0YXJ0ICsgMSxcbiAgICAgICAgaGFzaEJsb2NrID0gJzxoJyArIGhMZXZlbCArIGhJRCArICc+JyArIHNwYW5HYW11dCArICc8L2gnICsgaExldmVsICsgJz4nO1xuICAgIHJldHVybiBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hCbG9jaycpKGhhc2hCbG9jaywgb3B0aW9ucywgZ2xvYmFscyk7XG4gIH0pO1xuXG4gIC8vIGF0eC1zdHlsZSBoZWFkZXJzOlxuICAvLyAgIyBIZWFkZXIgMVxuICAvLyAgIyMgSGVhZGVyIDJcbiAgLy8gICMjIEhlYWRlciAyIHdpdGggY2xvc2luZyBoYXNoZXMgIyNcbiAgLy8gIC4uLlxuICAvLyAgIyMjIyMjIEhlYWRlciA2XG4gIC8vXG4gIHZhciBhdHhTdHlsZSA9IChvcHRpb25zLnJlcXVpcmVTcGFjZUJlZm9yZUhlYWRpbmdUZXh0KSA/IC9eKCN7MSw2fSlbIFxcdF0rKC4rPylbIFxcdF0qIypcXG4rL2dtIDogL14oI3sxLDZ9KVsgXFx0XSooLis/KVsgXFx0XSojKlxcbisvZ207XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZShhdHhTdHlsZSwgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xLCBtMikge1xuICAgIHZhciBoVGV4dCA9IG0yO1xuICAgIGlmIChvcHRpb25zLmN1c3RvbWl6ZWRIZWFkZXJJZCkge1xuICAgICAgaFRleHQgPSBtMi5yZXBsYWNlKC9cXHM/XFx7KFtee10rPyl9XFxzKiQvLCAnJyk7XG4gICAgfVxuXG4gICAgdmFyIHNwYW4gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcpKGhUZXh0LCBvcHRpb25zLCBnbG9iYWxzKSxcbiAgICAgICAgaElEID0gKG9wdGlvbnMubm9IZWFkZXJJZCkgPyAnJyA6ICcgaWQ9XCInICsgaGVhZGVySWQobTIpICsgJ1wiJyxcbiAgICAgICAgaExldmVsID0gaGVhZGVyTGV2ZWxTdGFydCAtIDEgKyBtMS5sZW5ndGgsXG4gICAgICAgIGhlYWRlciA9ICc8aCcgKyBoTGV2ZWwgKyBoSUQgKyAnPicgKyBzcGFuICsgJzwvaCcgKyBoTGV2ZWwgKyAnPic7XG5cbiAgICByZXR1cm4gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQmxvY2snKShoZWFkZXIsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB9KTtcblxuICBmdW5jdGlvbiBoZWFkZXJJZCAobSkge1xuICAgIHZhciB0aXRsZSxcbiAgICAgICAgcHJlZml4O1xuXG4gICAgLy8gSXQgaXMgc2VwYXJhdGUgZnJvbSBvdGhlciBvcHRpb25zIHRvIGFsbG93IGNvbWJpbmluZyBwcmVmaXggYW5kIGN1c3RvbWl6ZWRcbiAgICBpZiAob3B0aW9ucy5jdXN0b21pemVkSGVhZGVySWQpIHtcbiAgICAgIHZhciBtYXRjaCA9IG0ubWF0Y2goL1xceyhbXntdKz8pfVxccyokLyk7XG4gICAgICBpZiAobWF0Y2ggJiYgbWF0Y2hbMV0pIHtcbiAgICAgICAgbSA9IG1hdGNoWzFdO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRpdGxlID0gbTtcblxuICAgIC8vIFByZWZpeCBpZCB0byBwcmV2ZW50IGNhdXNpbmcgaW5hZHZlcnRlbnQgcHJlLWV4aXN0aW5nIHN0eWxlIG1hdGNoZXMuXG4gICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1N0cmluZyhvcHRpb25zLnByZWZpeEhlYWRlcklkKSkge1xuICAgICAgcHJlZml4ID0gb3B0aW9ucy5wcmVmaXhIZWFkZXJJZDtcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMucHJlZml4SGVhZGVySWQgPT09IHRydWUpIHtcbiAgICAgIHByZWZpeCA9ICdzZWN0aW9uLSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByZWZpeCA9ICcnO1xuICAgIH1cblxuICAgIGlmICghb3B0aW9ucy5yYXdQcmVmaXhIZWFkZXJJZCkge1xuICAgICAgdGl0bGUgPSBwcmVmaXggKyB0aXRsZTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5naENvbXBhdGlibGVIZWFkZXJJZCkge1xuICAgICAgdGl0bGUgPSB0aXRsZVxuICAgICAgICAucmVwbGFjZSgvIC9nLCAnLScpXG4gICAgICAgIC8vIHJlcGxhY2UgcHJldmlvdXNseSBlc2NhcGVkIGNoYXJzICgmLCDCqCBhbmQgJClcbiAgICAgICAgLnJlcGxhY2UoLyZhbXA7L2csICcnKVxuICAgICAgICAucmVwbGFjZSgvwqhUL2csICcnKVxuICAgICAgICAucmVwbGFjZSgvwqhEL2csICcnKVxuICAgICAgICAvLyByZXBsYWNlIHJlc3Qgb2YgdGhlIGNoYXJzICgmfiQgYXJlIHJlcGVhdGVkIGFzIHRoZXkgbWlnaHQgaGF2ZSBiZWVuIGVzY2FwZWQpXG4gICAgICAgIC8vIGJvcnJvd2VkIGZyb20gZ2l0aHViJ3MgcmVkY2FycGV0IChzb21lIHRoZXkgc2hvdWxkIHByb2R1Y2Ugc2ltaWxhciByZXN1bHRzKVxuICAgICAgICAucmVwbGFjZSgvWyYrJCxcXC86Oz0/QFwiI3t9fF7CqH5cXFtcXF1gXFxcXCopKCUuISc8Pl0vZywgJycpXG4gICAgICAgIC50b0xvd2VyQ2FzZSgpO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5yYXdIZWFkZXJJZCkge1xuICAgICAgdGl0bGUgPSB0aXRsZVxuICAgICAgICAucmVwbGFjZSgvIC9nLCAnLScpXG4gICAgICAgIC8vIHJlcGxhY2UgcHJldmlvdXNseSBlc2NhcGVkIGNoYXJzICgmLCDCqCBhbmQgJClcbiAgICAgICAgLnJlcGxhY2UoLyZhbXA7L2csICcmJylcbiAgICAgICAgLnJlcGxhY2UoL8KoVC9nLCAnwqgnKVxuICAgICAgICAucmVwbGFjZSgvwqhEL2csICckJylcbiAgICAgICAgLy8gcmVwbGFjZSBcIiBhbmQgJ1xuICAgICAgICAucmVwbGFjZSgvW1wiJ10vZywgJy0nKVxuICAgICAgICAudG9Mb3dlckNhc2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGl0bGUgPSB0aXRsZVxuICAgICAgICAucmVwbGFjZSgvW15cXHddL2csICcnKVxuICAgICAgICAudG9Mb3dlckNhc2UoKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5yYXdQcmVmaXhIZWFkZXJJZCkge1xuICAgICAgdGl0bGUgPSBwcmVmaXggKyB0aXRsZTtcbiAgICB9XG5cbiAgICBpZiAoZ2xvYmFscy5oYXNoTGlua0NvdW50c1t0aXRsZV0pIHtcbiAgICAgIHRpdGxlID0gdGl0bGUgKyAnLScgKyAoZ2xvYmFscy5oYXNoTGlua0NvdW50c1t0aXRsZV0rKyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGdsb2JhbHMuaGFzaExpbmtDb3VudHNbdGl0bGVdID0gMTtcbiAgICB9XG4gICAgcmV0dXJuIHRpdGxlO1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGVhZGVycy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogVHVybiBNYXJrZG93biBsaW5rIHNob3J0Y3V0cyBpbnRvIFhIVE1MIDxhPiB0YWdzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2hvcml6b250YWxSdWxlJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdob3Jpem9udGFsUnVsZS5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIga2V5ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQmxvY2snKSgnPGhyIC8+Jywgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL14gezAsMn0oID8tKXszLH1bIFxcdF0qJC9nbSwga2V5KTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXiB7MCwyfSggP1xcKil7Myx9WyBcXHRdKiQvZ20sIGtleSk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL14gezAsMn0oID9fKXszLH1bIFxcdF0qJC9nbSwga2V5KTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdob3Jpem9udGFsUnVsZS5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogVHVybiBNYXJrZG93biBpbWFnZSBzaG9ydGN1dHMgaW50byA8aW1nPiB0YWdzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2ltYWdlcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdpbWFnZXMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdmFyIGlubGluZVJlZ0V4cCAgICAgID0gLyFcXFsoW15cXF1dKj8pXVsgXFx0XSooKVxcKFsgXFx0XT88PyhbXFxTXSs/KD86XFwoW1xcU10qP1xcKVtcXFNdKj8pPyk+Pyg/OiA9KFsqXFxkXStbQS1aYS16JV17MCw0fSl4KFsqXFxkXStbQS1aYS16JV17MCw0fSkpP1sgXFx0XSooPzooW1wiJ10pKFteXCJdKj8pXFw2KT9bIFxcdF0/XFwpL2csXG4gICAgICBjcmF6eVJlZ0V4cCAgICAgICA9IC8hXFxbKFteXFxdXSo/KV1bIFxcdF0qKClcXChbIFxcdF0/PChbXj5dKik+KD86ID0oWypcXGRdK1tBLVphLXolXXswLDR9KXgoWypcXGRdK1tBLVphLXolXXswLDR9KSk/WyBcXHRdKig/Oig/OihbXCInXSkoW15cIl0qPylcXDYpKT9bIFxcdF0/XFwpL2csXG4gICAgICBiYXNlNjRSZWdFeHAgICAgICA9IC8hXFxbKFteXFxdXSo/KV1bIFxcdF0qKClcXChbIFxcdF0/PD8oZGF0YTouKz9cXC8uKz87YmFzZTY0LFtBLVphLXowLTkrLz1cXG5dKz8pPj8oPzogPShbKlxcZF0rW0EtWmEteiVdezAsNH0peChbKlxcZF0rW0EtWmEteiVdezAsNH0pKT9bIFxcdF0qKD86KFtcIiddKShbXlwiXSo/KVxcNik/WyBcXHRdP1xcKS9nLFxuICAgICAgcmVmZXJlbmNlUmVnRXhwICAgPSAvIVxcWyhbXlxcXV0qPyldID8oPzpcXG4gKik/XFxbKFtcXHNcXFNdKj8pXSgpKCkoKSgpKCkvZyxcbiAgICAgIHJlZlNob3J0Y3V0UmVnRXhwID0gLyFcXFsoW15cXFtcXF1dKyldKCkoKSgpKCkoKS9nO1xuXG4gIGZ1bmN0aW9uIHdyaXRlSW1hZ2VUYWdCYXNlNjQgKHdob2xlTWF0Y2gsIGFsdFRleHQsIGxpbmtJZCwgdXJsLCB3aWR0aCwgaGVpZ2h0LCBtNSwgdGl0bGUpIHtcbiAgICB1cmwgPSB1cmwucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICByZXR1cm4gd3JpdGVJbWFnZVRhZyAod2hvbGVNYXRjaCwgYWx0VGV4dCwgbGlua0lkLCB1cmwsIHdpZHRoLCBoZWlnaHQsIG01LCB0aXRsZSk7XG4gIH1cblxuICBmdW5jdGlvbiB3cml0ZUltYWdlVGFnICh3aG9sZU1hdGNoLCBhbHRUZXh0LCBsaW5rSWQsIHVybCwgd2lkdGgsIGhlaWdodCwgbTUsIHRpdGxlKSB7XG5cbiAgICB2YXIgZ1VybHMgICA9IGdsb2JhbHMuZ1VybHMsXG4gICAgICAgIGdUaXRsZXMgPSBnbG9iYWxzLmdUaXRsZXMsXG4gICAgICAgIGdEaW1zICAgPSBnbG9iYWxzLmdEaW1lbnNpb25zO1xuXG4gICAgbGlua0lkID0gbGlua0lkLnRvTG93ZXJDYXNlKCk7XG5cbiAgICBpZiAoIXRpdGxlKSB7XG4gICAgICB0aXRsZSA9ICcnO1xuICAgIH1cbiAgICAvLyBTcGVjaWFsIGNhc2UgZm9yIGV4cGxpY2l0IGVtcHR5IHVybFxuICAgIGlmICh3aG9sZU1hdGNoLnNlYXJjaCgvXFwoPD9cXHMqPj8gPyhbJ1wiXS4qWydcIl0pP1xcKSQvbSkgPiAtMSkge1xuICAgICAgdXJsID0gJyc7XG5cbiAgICB9IGVsc2UgaWYgKHVybCA9PT0gJycgfHwgdXJsID09PSBudWxsKSB7XG4gICAgICBpZiAobGlua0lkID09PSAnJyB8fCBsaW5rSWQgPT09IG51bGwpIHtcbiAgICAgICAgLy8gbG93ZXItY2FzZSBhbmQgdHVybiBlbWJlZGRlZCBuZXdsaW5lcyBpbnRvIHNwYWNlc1xuICAgICAgICBsaW5rSWQgPSBhbHRUZXh0LnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvID9cXG4vZywgJyAnKTtcbiAgICAgIH1cbiAgICAgIHVybCA9ICcjJyArIGxpbmtJZDtcblxuICAgICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZ1VybHNbbGlua0lkXSkpIHtcbiAgICAgICAgdXJsID0gZ1VybHNbbGlua0lkXTtcbiAgICAgICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZ1RpdGxlc1tsaW5rSWRdKSkge1xuICAgICAgICAgIHRpdGxlID0gZ1RpdGxlc1tsaW5rSWRdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGdEaW1zW2xpbmtJZF0pKSB7XG4gICAgICAgICAgd2lkdGggPSBnRGltc1tsaW5rSWRdLndpZHRoO1xuICAgICAgICAgIGhlaWdodCA9IGdEaW1zW2xpbmtJZF0uaGVpZ2h0O1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gd2hvbGVNYXRjaDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhbHRUZXh0ID0gYWx0VGV4dFxuICAgICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKVxuICAgIC8vYWx0VGV4dCA9IHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzKGFsdFRleHQsICcqXycsIGZhbHNlKTtcbiAgICAgIC5yZXBsYWNlKHNob3dkb3duLmhlbHBlci5yZWdleGVzLmFzdGVyaXNrRGFzaEFuZENvbG9uLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcbiAgICAvL3VybCA9IHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzKHVybCwgJypfJywgZmFsc2UpO1xuICAgIHVybCA9IHVybC5yZXBsYWNlKHNob3dkb3duLmhlbHBlci5yZWdleGVzLmFzdGVyaXNrRGFzaEFuZENvbG9uLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcbiAgICB2YXIgcmVzdWx0ID0gJzxpbWcgc3JjPVwiJyArIHVybCArICdcIiBhbHQ9XCInICsgYWx0VGV4dCArICdcIic7XG5cbiAgICBpZiAodGl0bGUgJiYgc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKHRpdGxlKSkge1xuICAgICAgdGl0bGUgPSB0aXRsZVxuICAgICAgICAucmVwbGFjZSgvXCIvZywgJyZxdW90OycpXG4gICAgICAvL3RpdGxlID0gc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnModGl0bGUsICcqXycsIGZhbHNlKTtcbiAgICAgICAgLnJlcGxhY2Uoc2hvd2Rvd24uaGVscGVyLnJlZ2V4ZXMuYXN0ZXJpc2tEYXNoQW5kQ29sb24sIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuICAgICAgcmVzdWx0ICs9ICcgdGl0bGU9XCInICsgdGl0bGUgKyAnXCInO1xuICAgIH1cblxuICAgIGlmICh3aWR0aCAmJiBoZWlnaHQpIHtcbiAgICAgIHdpZHRoICA9ICh3aWR0aCA9PT0gJyonKSA/ICdhdXRvJyA6IHdpZHRoO1xuICAgICAgaGVpZ2h0ID0gKGhlaWdodCA9PT0gJyonKSA/ICdhdXRvJyA6IGhlaWdodDtcblxuICAgICAgcmVzdWx0ICs9ICcgd2lkdGg9XCInICsgd2lkdGggKyAnXCInO1xuICAgICAgcmVzdWx0ICs9ICcgaGVpZ2h0PVwiJyArIGhlaWdodCArICdcIic7XG4gICAgfVxuXG4gICAgcmVzdWx0ICs9ICcgLz4nO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIEZpcnN0LCBoYW5kbGUgcmVmZXJlbmNlLXN0eWxlIGxhYmVsZWQgaW1hZ2VzOiAhW2FsdCB0ZXh0XVtpZF1cbiAgdGV4dCA9IHRleHQucmVwbGFjZShyZWZlcmVuY2VSZWdFeHAsIHdyaXRlSW1hZ2VUYWcpO1xuXG4gIC8vIE5leHQsIGhhbmRsZSBpbmxpbmUgaW1hZ2VzOiAgIVthbHQgdGV4dF0odXJsID08d2lkdGg+eDxoZWlnaHQ+IFwib3B0aW9uYWwgdGl0bGVcIilcblxuICAvLyBiYXNlNjQgZW5jb2RlZCBpbWFnZXNcbiAgdGV4dCA9IHRleHQucmVwbGFjZShiYXNlNjRSZWdFeHAsIHdyaXRlSW1hZ2VUYWdCYXNlNjQpO1xuXG4gIC8vIGNhc2VzIHdpdGggY3JhenkgdXJscyBsaWtlIC4vaW1hZ2UvY2F0MSkucG5nXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoY3JhenlSZWdFeHAsIHdyaXRlSW1hZ2VUYWcpO1xuXG4gIC8vIG5vcm1hbCBjYXNlc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGlubGluZVJlZ0V4cCwgd3JpdGVJbWFnZVRhZyk7XG5cbiAgLy8gaGFuZGxlIHJlZmVyZW5jZS1zdHlsZSBzaG9ydGN1dHM6ICFbaW1nIHRleHRdXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UocmVmU2hvcnRjdXRSZWdFeHAsIHdyaXRlSW1hZ2VUYWcpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2ltYWdlcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignaXRhbGljc0FuZEJvbGQnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaXRhbGljc0FuZEJvbGQuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gaXQncyBmYXN0ZXIgdG8gaGF2ZSAzIHNlcGFyYXRlIHJlZ2V4ZXMgZm9yIGVhY2ggY2FzZSB0aGFuIGhhdmUganVzdCBvbmVcbiAgLy8gYmVjYXVzZSBvZiBiYWNrdHJhY2luZywgaW4gc29tZSBjYXNlcywgaXQgY291bGQgbGVhZCB0byBhbiBleHBvbmVudGlhbCBlZmZlY3RcbiAgLy8gY2FsbGVkIFwiY2F0YXN0cm9waGljIGJhY2t0cmFjZVwiLiBPbWlub3VzIVxuXG4gIGZ1bmN0aW9uIHBhcnNlSW5zaWRlICh0eHQsIGxlZnQsIHJpZ2h0KSB7XG4gICAgLypcbiAgICBpZiAob3B0aW9ucy5zaW1wbGlmaWVkQXV0b0xpbmspIHtcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignc2ltcGxpZmllZEF1dG9MaW5rcycpKHR4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgfVxuICAgICovXG4gICAgcmV0dXJuIGxlZnQgKyB0eHQgKyByaWdodDtcbiAgfVxuXG4gIC8vIFBhcnNlIHVuZGVyc2NvcmVzXG4gIGlmIChvcHRpb25zLmxpdGVyYWxNaWRXb3JkVW5kZXJzY29yZXMpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXGJfX18oXFxTW1xcc1xcU10qPylfX19cXGIvZywgZnVuY3Rpb24gKHdtLCB0eHQpIHtcbiAgICAgIHJldHVybiBwYXJzZUluc2lkZSAodHh0LCAnPHN0cm9uZz48ZW0+JywgJzwvZW0+PC9zdHJvbmc+Jyk7XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxiX18oXFxTW1xcc1xcU10qPylfX1xcYi9nLCBmdW5jdGlvbiAod20sIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsICc8c3Ryb25nPicsICc8L3N0cm9uZz4nKTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXGJfKFxcU1tcXHNcXFNdKj8pX1xcYi9nLCBmdW5jdGlvbiAod20sIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsICc8ZW0+JywgJzwvZW0+Jyk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvX19fKFxcU1tcXHNcXFNdKj8pX19fL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxzdHJvbmc+PGVtPicsICc8L2VtPjwvc3Ryb25nPicpIDogd207XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvX18oXFxTW1xcc1xcU10qPylfXy9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gcGFyc2VJbnNpZGUgKG0sICc8c3Ryb25nPicsICc8L3N0cm9uZz4nKSA6IHdtO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL18oW15cXHNfXVtcXHNcXFNdKj8pXy9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIC8vICEvXl9bXl9dLy50ZXN0KG0pIC0gdGVzdCBpZiBpdCBkb2Vzbid0IHN0YXJ0IHdpdGggX18gKHNpbmNlIGl0IHNlZW1zIHJlZHVuZGFudCwgd2UgcmVtb3ZlZCBpdClcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gcGFyc2VJbnNpZGUgKG0sICc8ZW0+JywgJzwvZW0+JykgOiB3bTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIE5vdyBwYXJzZSBhc3Rlcmlza3NcbiAgaWYgKG9wdGlvbnMubGl0ZXJhbE1pZFdvcmRBc3Rlcmlza3MpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oW14qXXxeKVxcQlxcKlxcKlxcKihcXFNbXFxzXFxTXSo/KVxcKlxcKlxcKlxcQig/IVxcKikvZywgZnVuY3Rpb24gKHdtLCBsZWFkLCB0eHQpIHtcbiAgICAgIHJldHVybiBwYXJzZUluc2lkZSAodHh0LCBsZWFkICsgJzxzdHJvbmc+PGVtPicsICc8L2VtPjwvc3Ryb25nPicpO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhbXipdfF4pXFxCXFwqXFwqKFxcU1tcXHNcXFNdKj8pXFwqXFwqXFxCKD8hXFwqKS9nLCBmdW5jdGlvbiAod20sIGxlYWQsIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsIGxlYWQgKyAnPHN0cm9uZz4nLCAnPC9zdHJvbmc+Jyk7XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvKFteKl18XilcXEJcXCooXFxTW1xcc1xcU10qPylcXCpcXEIoPyFcXCopL2csIGZ1bmN0aW9uICh3bSwgbGVhZCwgdHh0KSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnNpZGUgKHR4dCwgbGVhZCArICc8ZW0+JywgJzwvZW0+Jyk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFwqXFwqXFwqKFxcU1tcXHNcXFNdKj8pXFwqXFwqXFwqL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxzdHJvbmc+PGVtPicsICc8L2VtPjwvc3Ryb25nPicpIDogd207XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFwqXFwqKFxcU1tcXHNcXFNdKj8pXFwqXFwqL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxzdHJvbmc+JywgJzwvc3Ryb25nPicpIDogd207XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFwqKFteXFxzKl1bXFxzXFxTXSo/KVxcKi9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIC8vICEvXlxcKlteKl0vLnRlc3QobSkgLSB0ZXN0IGlmIGl0IGRvZXNuJ3Qgc3RhcnQgd2l0aCAqKiAoc2luY2UgaXQgc2VlbXMgcmVkdW5kYW50LCB3ZSByZW1vdmVkIGl0KVxuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyBwYXJzZUluc2lkZSAobSwgJzxlbT4nLCAnPC9lbT4nKSA6IHdtO1xuICAgIH0pO1xuICB9XG5cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdpdGFsaWNzQW5kQm9sZC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogRm9ybSBIVE1MIG9yZGVyZWQgKG51bWJlcmVkKSBhbmQgdW5vcmRlcmVkIChidWxsZXRlZCkgbGlzdHMuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignbGlzdHMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLyoqXG4gICAqIFByb2Nlc3MgdGhlIGNvbnRlbnRzIG9mIGEgc2luZ2xlIG9yZGVyZWQgb3IgdW5vcmRlcmVkIGxpc3QsIHNwbGl0dGluZyBpdFxuICAgKiBpbnRvIGluZGl2aWR1YWwgbGlzdCBpdGVtcy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGxpc3RTdHJcbiAgICogQHBhcmFtIHtib29sZWFufSB0cmltVHJhaWxpbmdcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGZ1bmN0aW9uIHByb2Nlc3NMaXN0SXRlbXMgKGxpc3RTdHIsIHRyaW1UcmFpbGluZykge1xuICAgIC8vIFRoZSAkZ19saXN0X2xldmVsIGdsb2JhbCBrZWVwcyB0cmFjayBvZiB3aGVuIHdlJ3JlIGluc2lkZSBhIGxpc3QuXG4gICAgLy8gRWFjaCB0aW1lIHdlIGVudGVyIGEgbGlzdCwgd2UgaW5jcmVtZW50IGl0OyB3aGVuIHdlIGxlYXZlIGEgbGlzdCxcbiAgICAvLyB3ZSBkZWNyZW1lbnQuIElmIGl0J3MgemVybywgd2UncmUgbm90IGluIGEgbGlzdCBhbnltb3JlLlxuICAgIC8vXG4gICAgLy8gV2UgZG8gdGhpcyBiZWNhdXNlIHdoZW4gd2UncmUgbm90IGluc2lkZSBhIGxpc3QsIHdlIHdhbnQgdG8gdHJlYXRcbiAgICAvLyBzb21ldGhpbmcgbGlrZSB0aGlzOlxuICAgIC8vXG4gICAgLy8gICAgSSByZWNvbW1lbmQgdXBncmFkaW5nIHRvIHZlcnNpb25cbiAgICAvLyAgICA4LiBPb3BzLCBub3cgdGhpcyBsaW5lIGlzIHRyZWF0ZWRcbiAgICAvLyAgICBhcyBhIHN1Yi1saXN0LlxuICAgIC8vXG4gICAgLy8gQXMgYSBzaW5nbGUgcGFyYWdyYXBoLCBkZXNwaXRlIHRoZSBmYWN0IHRoYXQgdGhlIHNlY29uZCBsaW5lIHN0YXJ0c1xuICAgIC8vIHdpdGggYSBkaWdpdC1wZXJpb2Qtc3BhY2Ugc2VxdWVuY2UuXG4gICAgLy9cbiAgICAvLyBXaGVyZWFzIHdoZW4gd2UncmUgaW5zaWRlIGEgbGlzdCAob3Igc3ViLWxpc3QpLCB0aGF0IGxpbmUgd2lsbCBiZVxuICAgIC8vIHRyZWF0ZWQgYXMgdGhlIHN0YXJ0IG9mIGEgc3ViLWxpc3QuIFdoYXQgYSBrbHVkZ2UsIGh1aD8gVGhpcyBpc1xuICAgIC8vIGFuIGFzcGVjdCBvZiBNYXJrZG93bidzIHN5bnRheCB0aGF0J3MgaGFyZCB0byBwYXJzZSBwZXJmZWN0bHlcbiAgICAvLyB3aXRob3V0IHJlc29ydGluZyB0byBtaW5kLXJlYWRpbmcuIFBlcmhhcHMgdGhlIHNvbHV0aW9uIGlzIHRvXG4gICAgLy8gY2hhbmdlIHRoZSBzeW50YXggcnVsZXMgc3VjaCB0aGF0IHN1Yi1saXN0cyBtdXN0IHN0YXJ0IHdpdGggYVxuICAgIC8vIHN0YXJ0aW5nIGNhcmRpbmFsIG51bWJlcjsgZS5nLiBcIjEuXCIgb3IgXCJhLlwiLlxuICAgIGdsb2JhbHMuZ0xpc3RMZXZlbCsrO1xuXG4gICAgLy8gdHJpbSB0cmFpbGluZyBibGFuayBsaW5lczpcbiAgICBsaXN0U3RyID0gbGlzdFN0ci5yZXBsYWNlKC9cXG57Mix9JC8sICdcXG4nKTtcblxuICAgIC8vIGF0dGFja2xhYjogYWRkIHNlbnRpbmVsIHRvIGVtdWxhdGUgXFx6XG4gICAgbGlzdFN0ciArPSAnwqgwJztcblxuICAgIHZhciByZ3ggPSAvKFxcbik/KF4gezAsM30pKFsqKy1dfFxcZCtbLl0pWyBcXHRdKygoXFxbKHh8WHwgKT9dKT9bIFxcdF0qW15cXHJdKz8oXFxuezEsMn0pKSg/PVxcbioowqgwfCB7MCwzfShbKistXXxcXGQrWy5dKVsgXFx0XSspKS9nbSxcbiAgICAgICAgaXNQYXJhZ3JhcGhlZCA9ICgvXFxuWyBcXHRdKlxcbig/IcKoMCkvLnRlc3QobGlzdFN0cikpO1xuXG4gICAgLy8gU2luY2UgdmVyc2lvbiAxLjUsIG5lc3Rpbmcgc3VibGlzdHMgcmVxdWlyZXMgNCBzcGFjZXMgKG9yIDEgdGFiKSBpbmRlbnRhdGlvbixcbiAgICAvLyB3aGljaCBpcyBhIHN5bnRheCBicmVha2luZyBjaGFuZ2VcbiAgICAvLyBhY3RpdmF0aW5nIHRoaXMgb3B0aW9uIHJldmVydHMgdG8gb2xkIGJlaGF2aW9yXG4gICAgaWYgKG9wdGlvbnMuZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzKSB7XG4gICAgICByZ3ggPSAvKFxcbik/KF4gezAsM30pKFsqKy1dfFxcZCtbLl0pWyBcXHRdKygoXFxbKHh8WHwgKT9dKT9bIFxcdF0qW15cXHJdKz8oXFxuezEsMn0pKSg/PVxcbioowqgwfFxcMihbKistXXxcXGQrWy5dKVsgXFx0XSspKS9nbTtcbiAgICB9XG5cbiAgICBsaXN0U3RyID0gbGlzdFN0ci5yZXBsYWNlKHJneCwgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xLCBtMiwgbTMsIG00LCB0YXNrYnRuLCBjaGVja2VkKSB7XG4gICAgICBjaGVja2VkID0gKGNoZWNrZWQgJiYgY2hlY2tlZC50cmltKCkgIT09ICcnKTtcblxuICAgICAgdmFyIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ291dGRlbnQnKShtNCwgb3B0aW9ucywgZ2xvYmFscyksXG4gICAgICAgICAgYnVsbGV0U3R5bGUgPSAnJztcblxuICAgICAgLy8gU3VwcG9ydCBmb3IgZ2l0aHViIHRhc2tsaXN0c1xuICAgICAgaWYgKHRhc2tidG4gJiYgb3B0aW9ucy50YXNrbGlzdHMpIHtcbiAgICAgICAgYnVsbGV0U3R5bGUgPSAnIGNsYXNzPVwidGFzay1saXN0LWl0ZW1cIiBzdHlsZT1cImxpc3Qtc3R5bGUtdHlwZTogbm9uZTtcIic7XG4gICAgICAgIGl0ZW0gPSBpdGVtLnJlcGxhY2UoL15bIFxcdF0qXFxbKHh8WHwgKT9dL20sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgb3RwID0gJzxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBkaXNhYmxlZCBzdHlsZT1cIm1hcmdpbjogMHB4IDAuMzVlbSAwLjI1ZW0gLTEuNmVtOyB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1wiJztcbiAgICAgICAgICBpZiAoY2hlY2tlZCkge1xuICAgICAgICAgICAgb3RwICs9ICcgY2hlY2tlZCc7XG4gICAgICAgICAgfVxuICAgICAgICAgIG90cCArPSAnPic7XG4gICAgICAgICAgcmV0dXJuIG90cDtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIElTU1VFICMzMTJcbiAgICAgIC8vIFRoaXMgaW5wdXQ6IC0gLSAtIGFcbiAgICAgIC8vIGNhdXNlcyB0cm91YmxlIHRvIHRoZSBwYXJzZXIsIHNpbmNlIGl0IGludGVycHJldHMgaXQgYXM6XG4gICAgICAvLyA8dWw+PGxpPjxsaT48bGk+YTwvbGk+PC9saT48L2xpPjwvdWw+XG4gICAgICAvLyBpbnN0ZWFkIG9mOlxuICAgICAgLy8gPHVsPjxsaT4tIC0gYTwvbGk+PC91bD5cbiAgICAgIC8vIFNvLCB0byBwcmV2ZW50IGl0LCB3ZSB3aWxsIHB1dCBhIG1hcmtlciAowqhBKWluIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxpbmVcbiAgICAgIC8vIEtpbmQgb2YgaGFja2lzaC9tb25rZXkgcGF0Y2hpbmcsIGJ1dCBzZWVtcyBtb3JlIGVmZmVjdGl2ZSB0aGFuIG92ZXJjb21wbGljYXRpbmcgdGhlIGxpc3QgcGFyc2VyXG4gICAgICBpdGVtID0gaXRlbS5yZXBsYWNlKC9eKFstKitdfFxcZFxcLilbIFxcdF0rW1xcU1xcbiBdKi9nLCBmdW5jdGlvbiAod20yKSB7XG4gICAgICAgIHJldHVybiAnwqhBJyArIHdtMjtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBtMSAtIExlYWRpbmcgbGluZSBvclxuICAgICAgLy8gSGFzIGEgZG91YmxlIHJldHVybiAobXVsdGkgcGFyYWdyYXBoKSBvclxuICAgICAgLy8gSGFzIHN1Ymxpc3RcbiAgICAgIGlmIChtMSB8fCAoaXRlbS5zZWFyY2goL1xcbnsyLH0vKSA+IC0xKSkge1xuICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdnaXRodWJDb2RlQmxvY2tzJykoaXRlbSwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2Jsb2NrR2FtdXQnKShpdGVtLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFJlY3Vyc2lvbiBmb3Igc3ViLWxpc3RzOlxuICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdsaXN0cycpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICBpdGVtID0gaXRlbS5yZXBsYWNlKC9cXG4kLywgJycpOyAvLyBjaG9tcChpdGVtKVxuICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoSFRNTEJsb2NrcycpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gICAgICAgIC8vIENvbGFwc2UgZG91YmxlIGxpbmVicmVha3NcbiAgICAgICAgaXRlbSA9IGl0ZW0ucmVwbGFjZSgvXFxuXFxuKy9nLCAnXFxuXFxuJyk7XG4gICAgICAgIGlmIChpc1BhcmFncmFwaGVkKSB7XG4gICAgICAgICAgaXRlbSA9IHNob3dkb3duLnN1YlBhcnNlcigncGFyYWdyYXBocycpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIG5vdyB3ZSBuZWVkIHRvIHJlbW92ZSB0aGUgbWFya2VyICjCqEEpXG4gICAgICBpdGVtID0gaXRlbS5yZXBsYWNlKCfCqEEnLCAnJyk7XG4gICAgICAvLyB3ZSBjYW4gZmluYWxseSB3cmFwIHRoZSBsaW5lIGluIGxpc3QgaXRlbSB0YWdzXG4gICAgICBpdGVtID0gICc8bGknICsgYnVsbGV0U3R5bGUgKyAnPicgKyBpdGVtICsgJzwvbGk+XFxuJztcblxuICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfSk7XG5cbiAgICAvLyBhdHRhY2tsYWI6IHN0cmlwIHNlbnRpbmVsXG4gICAgbGlzdFN0ciA9IGxpc3RTdHIucmVwbGFjZSgvwqgwL2csICcnKTtcblxuICAgIGdsb2JhbHMuZ0xpc3RMZXZlbC0tO1xuXG4gICAgaWYgKHRyaW1UcmFpbGluZykge1xuICAgICAgbGlzdFN0ciA9IGxpc3RTdHIucmVwbGFjZSgvXFxzKyQvLCAnJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxpc3RTdHI7XG4gIH1cblxuICBmdW5jdGlvbiBzdHlsZVN0YXJ0TnVtYmVyIChsaXN0LCBsaXN0VHlwZSkge1xuICAgIC8vIGNoZWNrIGlmIG9sIGFuZCBzdGFydHMgYnkgYSBudW1iZXIgZGlmZmVyZW50IHRoYW4gMVxuICAgIGlmIChsaXN0VHlwZSA9PT0gJ29sJykge1xuICAgICAgdmFyIHJlcyA9IGxpc3QubWF0Y2goL14gKihcXGQrKVxcLi8pO1xuICAgICAgaWYgKHJlcyAmJiByZXNbMV0gIT09ICcxJykge1xuICAgICAgICByZXR1cm4gJyBzdGFydD1cIicgKyByZXNbMV0gKyAnXCInO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgYW5kIHBhcnNlIGNvbnNlY3V0aXZlIGxpc3RzIChiZXR0ZXIgZml4IGZvciBpc3N1ZSAjMTQyKVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGlzdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGlzdFR5cGVcbiAgICogQHBhcmFtIHtib29sZWFufSB0cmltVHJhaWxpbmdcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlQ29uc2VjdXRpdmVMaXN0cyAobGlzdCwgbGlzdFR5cGUsIHRyaW1UcmFpbGluZykge1xuICAgIC8vIGNoZWNrIGlmIHdlIGNhdWdodCAyIG9yIG1vcmUgY29uc2VjdXRpdmUgbGlzdHMgYnkgbWlzdGFrZVxuICAgIC8vIHdlIHVzZSB0aGUgY291bnRlclJneCwgbWVhbmluZyBpZiBsaXN0VHlwZSBpcyBVTCB3ZSBsb29rIGZvciBPTCBhbmQgdmljZSB2ZXJzYVxuICAgIHZhciBvbFJneCA9IChvcHRpb25zLmRpc2FibGVGb3JjZWQ0U3BhY2VzSW5kZW50ZWRTdWJsaXN0cykgPyAvXiA/XFxkK1xcLlsgXFx0XS9nbSA6IC9eIHswLDN9XFxkK1xcLlsgXFx0XS9nbSxcbiAgICAgICAgdWxSZ3ggPSAob3B0aW9ucy5kaXNhYmxlRm9yY2VkNFNwYWNlc0luZGVudGVkU3VibGlzdHMpID8gL14gP1sqKy1dWyBcXHRdL2dtIDogL14gezAsM31bKistXVsgXFx0XS9nbSxcbiAgICAgICAgY291bnRlclJ4ZyA9IChsaXN0VHlwZSA9PT0gJ3VsJykgPyBvbFJneCA6IHVsUmd4LFxuICAgICAgICByZXN1bHQgPSAnJztcblxuICAgIGlmIChsaXN0LnNlYXJjaChjb3VudGVyUnhnKSAhPT0gLTEpIHtcbiAgICAgIChmdW5jdGlvbiBwYXJzZUNMICh0eHQpIHtcbiAgICAgICAgdmFyIHBvcyA9IHR4dC5zZWFyY2goY291bnRlclJ4ZyksXG4gICAgICAgICAgICBzdHlsZSA9IHN0eWxlU3RhcnROdW1iZXIobGlzdCwgbGlzdFR5cGUpO1xuICAgICAgICBpZiAocG9zICE9PSAtMSkge1xuICAgICAgICAgIC8vIHNsaWNlXG4gICAgICAgICAgcmVzdWx0ICs9ICdcXG5cXG48JyArIGxpc3RUeXBlICsgc3R5bGUgKyAnPlxcbicgKyBwcm9jZXNzTGlzdEl0ZW1zKHR4dC5zbGljZSgwLCBwb3MpLCAhIXRyaW1UcmFpbGluZykgKyAnPC8nICsgbGlzdFR5cGUgKyAnPlxcbic7XG5cbiAgICAgICAgICAvLyBpbnZlcnQgY291bnRlclR5cGUgYW5kIGxpc3RUeXBlXG4gICAgICAgICAgbGlzdFR5cGUgPSAobGlzdFR5cGUgPT09ICd1bCcpID8gJ29sJyA6ICd1bCc7XG4gICAgICAgICAgY291bnRlclJ4ZyA9IChsaXN0VHlwZSA9PT0gJ3VsJykgPyBvbFJneCA6IHVsUmd4O1xuXG4gICAgICAgICAgLy9yZWN1cnNlXG4gICAgICAgICAgcGFyc2VDTCh0eHQuc2xpY2UocG9zKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0ICs9ICdcXG5cXG48JyArIGxpc3RUeXBlICsgc3R5bGUgKyAnPlxcbicgKyBwcm9jZXNzTGlzdEl0ZW1zKHR4dCwgISF0cmltVHJhaWxpbmcpICsgJzwvJyArIGxpc3RUeXBlICsgJz5cXG4nO1xuICAgICAgICB9XG4gICAgICB9KShsaXN0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHN0eWxlID0gc3R5bGVTdGFydE51bWJlcihsaXN0LCBsaXN0VHlwZSk7XG4gICAgICByZXN1bHQgPSAnXFxuXFxuPCcgKyBsaXN0VHlwZSArIHN0eWxlICsgJz5cXG4nICsgcHJvY2Vzc0xpc3RJdGVtcyhsaXN0LCAhIXRyaW1UcmFpbGluZykgKyAnPC8nICsgbGlzdFR5cGUgKyAnPlxcbic7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKiBTdGFydCBvZiBsaXN0IHBhcnNpbmcgKiovXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2xpc3RzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAvLyBhZGQgc2VudGluZWwgdG8gaGFjayBhcm91bmQga2h0bWwvc2FmYXJpIGJ1ZzpcbiAgLy8gaHR0cDovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTEyMzFcbiAgdGV4dCArPSAnwqgwJztcblxuICBpZiAoZ2xvYmFscy5nTGlzdExldmVsKSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXigoIHswLDN9KFsqKy1dfFxcZCtbLl0pWyBcXHRdKylbXlxccl0rPyjCqDB8XFxuezIsfSg/PVxcUykoPyFbIFxcdF0qKD86WyorLV18XFxkK1suXSlbIFxcdF0rKSkpL2dtLFxuICAgICAgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIGxpc3QsIG0yKSB7XG4gICAgICAgIHZhciBsaXN0VHlwZSA9IChtMi5zZWFyY2goL1sqKy1dL2cpID4gLTEpID8gJ3VsJyA6ICdvbCc7XG4gICAgICAgIHJldHVybiBwYXJzZUNvbnNlY3V0aXZlTGlzdHMobGlzdCwgbGlzdFR5cGUsIHRydWUpO1xuICAgICAgfVxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvKFxcblxcbnxeXFxuPykoKCB7MCwzfShbKistXXxcXGQrWy5dKVsgXFx0XSspW15cXHJdKz8owqgwfFxcbnsyLH0oPz1cXFMpKD8hWyBcXHRdKig/OlsqKy1dfFxcZCtbLl0pWyBcXHRdKykpKS9nbSxcbiAgICAgIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSwgbGlzdCwgbTMpIHtcbiAgICAgICAgdmFyIGxpc3RUeXBlID0gKG0zLnNlYXJjaCgvWyorLV0vZykgPiAtMSkgPyAndWwnIDogJ29sJztcbiAgICAgICAgcmV0dXJuIHBhcnNlQ29uc2VjdXRpdmVMaXN0cyhsaXN0LCBsaXN0VHlwZSwgZmFsc2UpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICAvLyBzdHJpcCBzZW50aW5lbFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqDAvLCAnJyk7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2xpc3RzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBQYXJzZSBtZXRhZGF0YSBhdCB0aGUgdG9wIG9mIHRoZSBkb2N1bWVudFxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ldGFkYXRhJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghb3B0aW9ucy5tZXRhZGF0YSkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnbWV0YWRhdGEuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgZnVuY3Rpb24gcGFyc2VNZXRhZGF0YUNvbnRlbnRzIChjb250ZW50KSB7XG4gICAgLy8gcmF3IGlzIHJhdyBzbyBpdCdzIG5vdCBjaGFuZ2VkIGluIGFueSB3YXlcbiAgICBnbG9iYWxzLm1ldGFkYXRhLnJhdyA9IGNvbnRlbnQ7XG5cbiAgICAvLyBlc2NhcGUgY2hhcnMgZm9yYmlkZGVuIGluIGh0bWwgYXR0cmlidXRlc1xuICAgIC8vIGRvdWJsZSBxdW90ZXNcbiAgICBjb250ZW50ID0gY29udGVudFxuICAgICAgLy8gYW1wZXJzYW5kIGZpcnN0XG4gICAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxuICAgICAgLy8gZG91YmxlIHF1b3Rlc1xuICAgICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKTtcblxuICAgIGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoL1xcbiB7NH0vZywgJyAnKTtcbiAgICBjb250ZW50LnJlcGxhY2UoL14oW1xcUyBdKyk6ICsoW1xcc1xcU10rPykkL2dtLCBmdW5jdGlvbiAod20sIGtleSwgdmFsdWUpIHtcbiAgICAgIGdsb2JhbHMubWV0YWRhdGEucGFyc2VkW2tleV0gPSB2YWx1ZTtcbiAgICAgIHJldHVybiAnJztcbiAgICB9KTtcbiAgfVxuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15cXHMqwqvCq8KrKyhcXFMqPylcXG4oW1xcc1xcU10rPylcXG7Cu8K7wrsrXFxuLywgZnVuY3Rpb24gKHdob2xlbWF0Y2gsIGZvcm1hdCwgY29udGVudCkge1xuICAgIHBhcnNlTWV0YWRhdGFDb250ZW50cyhjb250ZW50KTtcbiAgICByZXR1cm4gJ8KoTSc7XG4gIH0pO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15cXHMqLS0tKyhcXFMqPylcXG4oW1xcc1xcU10rPylcXG4tLS0rXFxuLywgZnVuY3Rpb24gKHdob2xlbWF0Y2gsIGZvcm1hdCwgY29udGVudCkge1xuICAgIGlmIChmb3JtYXQpIHtcbiAgICAgIGdsb2JhbHMubWV0YWRhdGEuZm9ybWF0ID0gZm9ybWF0O1xuICAgIH1cbiAgICBwYXJzZU1ldGFkYXRhQ29udGVudHMoY29udGVudCk7XG4gICAgcmV0dXJuICfCqE0nO1xuICB9KTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqE0vZywgJycpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ21ldGFkYXRhLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBSZW1vdmUgb25lIGxldmVsIG9mIGxpbmUtbGVhZGluZyB0YWJzIG9yIHNwYWNlc1xuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ291dGRlbnQnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ291dGRlbnQuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gYXR0YWNrbGFiOiBoYWNrIGFyb3VuZCBLb25xdWVyb3IgMy41LjQgYnVnOlxuICAvLyBcIi0tLS0tLS0tLS1idWdcIi5yZXBsYWNlKC9eLS9nLFwiXCIpID09IFwiYnVnXCJcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXihcXHR8WyBdezEsNH0pL2dtLCAnwqgwJyk7IC8vIGF0dGFja2xhYjogZ190YWJfd2lkdGhcblxuICAvLyBhdHRhY2tsYWI6IGNsZWFuIHVwIGhhY2tcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqgwL2csICcnKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdvdXRkZW50LmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3BhcmFncmFwaHMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgncGFyYWdyYXBocy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgLy8gU3RyaXAgbGVhZGluZyBhbmQgdHJhaWxpbmcgbGluZXM6XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15cXG4rL2csICcnKTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxuKyQvZywgJycpO1xuXG4gIHZhciBncmFmcyA9IHRleHQuc3BsaXQoL1xcbnsyLH0vZyksXG4gICAgICBncmFmc091dCA9IFtdLFxuICAgICAgZW5kID0gZ3JhZnMubGVuZ3RoOyAvLyBXcmFwIDxwPiB0YWdzXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbmQ7IGkrKykge1xuICAgIHZhciBzdHIgPSBncmFmc1tpXTtcbiAgICAvLyBpZiB0aGlzIGlzIGFuIEhUTUwgbWFya2VyLCBjb3B5IGl0XG4gICAgaWYgKHN0ci5zZWFyY2goL8KoKEt8RykoXFxkKylcXDEvZykgPj0gMCkge1xuICAgICAgZ3JhZnNPdXQucHVzaChzdHIpO1xuXG4gICAgLy8gdGVzdCBmb3IgcHJlc2VuY2Ugb2YgY2hhcmFjdGVycyB0byBwcmV2ZW50IGVtcHR5IGxpbmVzIGJlaW5nIHBhcnNlZFxuICAgIC8vIGFzIHBhcmFncmFwaHMgKHJlc3VsdGluZyBpbiB1bmRlc2lyZWQgZXh0cmEgZW1wdHkgcGFyYWdyYXBocylcbiAgICB9IGVsc2UgaWYgKHN0ci5zZWFyY2goL1xcUy8pID49IDApIHtcbiAgICAgIHN0ciA9IHNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0Jykoc3RyLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgIHN0ciA9IHN0ci5yZXBsYWNlKC9eKFsgXFx0XSopL2csICc8cD4nKTtcbiAgICAgIHN0ciArPSAnPC9wPic7XG4gICAgICBncmFmc091dC5wdXNoKHN0cik7XG4gICAgfVxuICB9XG5cbiAgLyoqIFVuaGFzaGlmeSBIVE1MIGJsb2NrcyAqL1xuICBlbmQgPSBncmFmc091dC5sZW5ndGg7XG4gIGZvciAoaSA9IDA7IGkgPCBlbmQ7IGkrKykge1xuICAgIHZhciBibG9ja1RleHQgPSAnJyxcbiAgICAgICAgZ3JhZnNPdXRJdCA9IGdyYWZzT3V0W2ldLFxuICAgICAgICBjb2RlRmxhZyA9IGZhbHNlO1xuICAgIC8vIGlmIHRoaXMgaXMgYSBtYXJrZXIgZm9yIGFuIGh0bWwgYmxvY2suLi5cbiAgICAvLyB1c2UgUmVnRXhwLnRlc3QgaW5zdGVhZCBvZiBzdHJpbmcuc2VhcmNoIGJlY2F1c2Ugb2YgUU1MIGJ1Z1xuICAgIHdoaWxlICgvwqgoS3xHKShcXGQrKVxcMS8udGVzdChncmFmc091dEl0KSkge1xuICAgICAgdmFyIGRlbGltID0gUmVnRXhwLiQxLFxuICAgICAgICAgIG51bSAgID0gUmVnRXhwLiQyO1xuXG4gICAgICBpZiAoZGVsaW0gPT09ICdLJykge1xuICAgICAgICBibG9ja1RleHQgPSBnbG9iYWxzLmdIdG1sQmxvY2tzW251bV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB3ZSBuZWVkIHRvIGNoZWNrIGlmIGdoQmxvY2sgaXMgYSBmYWxzZSBwb3NpdGl2ZVxuICAgICAgICBpZiAoY29kZUZsYWcpIHtcbiAgICAgICAgICAvLyB1c2UgZW5jb2RlZCB2ZXJzaW9uIG9mIGFsbCB0ZXh0XG4gICAgICAgICAgYmxvY2tUZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJykoZ2xvYmFscy5naENvZGVCbG9ja3NbbnVtXS50ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBibG9ja1RleHQgPSBnbG9iYWxzLmdoQ29kZUJsb2Nrc1tudW1dLmNvZGVibG9jaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYmxvY2tUZXh0ID0gYmxvY2tUZXh0LnJlcGxhY2UoL1xcJC9nLCAnJCQkJCcpOyAvLyBFc2NhcGUgYW55IGRvbGxhciBzaWduc1xuXG4gICAgICBncmFmc091dEl0ID0gZ3JhZnNPdXRJdC5yZXBsYWNlKC8oXFxuXFxuKT/CqChLfEcpXFxkK1xcMihcXG5cXG4pPy8sIGJsb2NrVGV4dCk7XG4gICAgICAvLyBDaGVjayBpZiBncmFmc091dEl0IGlzIGEgcHJlLT5jb2RlXG4gICAgICBpZiAoL148cHJlXFxiW14+XSo+XFxzKjxjb2RlXFxiW14+XSo+Ly50ZXN0KGdyYWZzT3V0SXQpKSB7XG4gICAgICAgIGNvZGVGbGFnID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgZ3JhZnNPdXRbaV0gPSBncmFmc091dEl0O1xuICB9XG4gIHRleHQgPSBncmFmc091dC5qb2luKCdcXG4nKTtcbiAgLy8gU3RyaXAgbGVhZGluZyBhbmQgdHJhaWxpbmcgbGluZXM6XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15cXG4rL2csICcnKTtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxuKyQvZywgJycpO1xuICByZXR1cm4gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdwYXJhZ3JhcGhzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG59KTtcblxyXG4vKipcbiAqIFJ1biBleHRlbnNpb25cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdydW5FeHRlbnNpb24nLCBmdW5jdGlvbiAoZXh0LCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoZXh0LmZpbHRlcikge1xuICAgIHRleHQgPSBleHQuZmlsdGVyKHRleHQsIGdsb2JhbHMuY29udmVydGVyLCBvcHRpb25zKTtcblxuICB9IGVsc2UgaWYgKGV4dC5yZWdleCkge1xuICAgIC8vIFRPRE8gcmVtb3ZlIHRoaXMgd2hlbiBvbGQgZXh0ZW5zaW9uIGxvYWRpbmcgbWVjaGFuaXNtIGlzIGRlcHJlY2F0ZWRcbiAgICB2YXIgcmUgPSBleHQucmVnZXg7XG4gICAgaWYgKCEocmUgaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICByZSA9IG5ldyBSZWdFeHAocmUsICdnJyk7XG4gICAgfVxuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UocmUsIGV4dC5yZXBsYWNlKTtcbiAgfVxuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBUaGVzZSBhcmUgYWxsIHRoZSB0cmFuc2Zvcm1hdGlvbnMgdGhhdCBvY2N1ciAqd2l0aGluKiBibG9jay1sZXZlbFxuICogdGFncyBsaWtlIHBhcmFncmFwaHMsIGhlYWRlcnMsIGFuZCBsaXN0IGl0ZW1zLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdzcGFuR2FtdXQuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2NvZGVTcGFucycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlc2NhcGVTcGVjaWFsQ2hhcnNXaXRoaW5UYWdBdHRyaWJ1dGVzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUJhY2tzbGFzaEVzY2FwZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBQcm9jZXNzIGFuY2hvciBhbmQgaW1hZ2UgdGFncy4gSW1hZ2VzIG11c3QgY29tZSBmaXJzdCxcbiAgLy8gYmVjYXVzZSAhW2Zvb11bZl0gbG9va3MgbGlrZSBhbiBhbmNob3IuXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2ltYWdlcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdhbmNob3JzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gTWFrZSBsaW5rcyBvdXQgb2YgdGhpbmdzIGxpa2UgYDxodHRwOi8vZXhhbXBsZS5jb20vPmBcbiAgLy8gTXVzdCBjb21lIGFmdGVyIGFuY2hvcnMsIGJlY2F1c2UgeW91IGNhbiB1c2UgPCBhbmQgPlxuICAvLyBkZWxpbWl0ZXJzIGluIGlubGluZSBsaW5rcyBsaWtlIFt0aGlzXSg8dXJsPikuXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2F1dG9MaW5rcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzaW1wbGlmaWVkQXV0b0xpbmtzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2Vtb2ppJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3VuZGVybGluZScpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdpdGFsaWNzQW5kQm9sZCcpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzdHJpa2V0aHJvdWdoJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VsbGlwc2lzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gd2UgbmVlZCB0byBoYXNoIEhUTUwgdGFncyBpbnNpZGUgc3BhbnNcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxTcGFucycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIG5vdyB3ZSBlbmNvZGUgYW1wcyBhbmQgYW5nbGVzXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUFtcHNBbmRBbmdsZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBEbyBoYXJkIGJyZWFrc1xuICBpZiAob3B0aW9ucy5zaW1wbGVMaW5lQnJlYWtzKSB7XG4gICAgLy8gR0ZNIHN0eWxlIGhhcmQgYnJlYWtzXG4gICAgLy8gb25seSBhZGQgbGluZSBicmVha3MgaWYgdGhlIHRleHQgZG9lcyBub3QgY29udGFpbiBhIGJsb2NrIChzcGVjaWFsIGNhc2UgZm9yIGxpc3RzKVxuICAgIGlmICghL1xcblxcbsKoSy8udGVzdCh0ZXh0KSkge1xuICAgICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxuKy9nLCAnPGJyIC8+XFxuJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIFZhbmlsbGEgaGFyZCBicmVha3NcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8gICtcXG4vZywgJzxiciAvPlxcbicpO1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc3BhbkdhbXV0LmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdzdHJpa2V0aHJvdWdoJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGZ1bmN0aW9uIHBhcnNlSW5zaWRlICh0eHQpIHtcbiAgICBpZiAob3B0aW9ucy5zaW1wbGlmaWVkQXV0b0xpbmspIHtcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignc2ltcGxpZmllZEF1dG9MaW5rcycpKHR4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgfVxuICAgIHJldHVybiAnPGRlbD4nICsgdHh0ICsgJzwvZGVsPic7XG4gIH1cblxuICBpZiAob3B0aW9ucy5zdHJpa2V0aHJvdWdoKSB7XG4gICAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc3RyaWtldGhyb3VnaC5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oPzp+KXsyfShbXFxzXFxTXSs/KSg/On4pezJ9L2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7IHJldHVybiBwYXJzZUluc2lkZSh0eHQpOyB9KTtcbiAgICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdzdHJpa2V0aHJvdWdoLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIH1cblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogU3RyaXBzIGxpbmsgZGVmaW5pdGlvbnMgZnJvbSB0ZXh0LCBzdG9yZXMgdGhlIFVSTHMgYW5kIHRpdGxlcyBpblxuICogaGFzaCByZWZlcmVuY2VzLlxuICogTGluayBkZWZzIGFyZSBpbiB0aGUgZm9ybTogXltpZF06IHVybCBcIm9wdGlvbmFsIHRpdGxlXCJcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdzdHJpcExpbmtEZWZpbml0aW9ucycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgcmVnZXggICAgICAgPSAvXiB7MCwzfVxcWyguKyldOlsgXFx0XSpcXG4/WyBcXHRdKjw/KFtePlxcc10rKT4/KD86ID0oWypcXGRdK1tBLVphLXolXXswLDR9KXgoWypcXGRdK1tBLVphLXolXXswLDR9KSk/WyBcXHRdKlxcbj9bIFxcdF0qKD86KFxcbiopW1wifCcoXSguKz8pW1wifCcpXVsgXFx0XSopPyg/Olxcbit8KD89wqgwKSkvZ20sXG4gICAgICBiYXNlNjRSZWdleCA9IC9eIHswLDN9XFxbKC4rKV06WyBcXHRdKlxcbj9bIFxcdF0qPD8oZGF0YTouKz9cXC8uKz87YmFzZTY0LFtBLVphLXowLTkrLz1cXG5dKz8pPj8oPzogPShbKlxcZF0rW0EtWmEteiVdezAsNH0peChbKlxcZF0rW0EtWmEteiVdezAsNH0pKT9bIFxcdF0qXFxuP1sgXFx0XSooPzooXFxuKilbXCJ8JyhdKC4rPylbXCJ8JyldWyBcXHRdKik/KD86XFxuXFxufCg/PcKoMCl8KD89XFxuXFxbKSkvZ207XG5cbiAgLy8gYXR0YWNrbGFiOiBzZW50aW5lbCB3b3JrYXJvdW5kcyBmb3IgbGFjayBvZiBcXEEgYW5kIFxcWiwgc2FmYXJpXFxraHRtbCBidWdcbiAgdGV4dCArPSAnwqgwJztcblxuICB2YXIgcmVwbGFjZUZ1bmMgPSBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbGlua0lkLCB1cmwsIHdpZHRoLCBoZWlnaHQsIGJsYW5rTGluZXMsIHRpdGxlKSB7XG4gICAgbGlua0lkID0gbGlua0lkLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKHVybC5tYXRjaCgvXmRhdGE6Lis/XFwvLis/O2Jhc2U2NCwvKSkge1xuICAgICAgLy8gcmVtb3ZlIG5ld2xpbmVzXG4gICAgICBnbG9iYWxzLmdVcmxzW2xpbmtJZF0gPSB1cmwucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZ2xvYmFscy5nVXJsc1tsaW5rSWRdID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVBbXBzQW5kQW5nbGVzJykodXJsLCBvcHRpb25zLCBnbG9iYWxzKTsgIC8vIExpbmsgSURzIGFyZSBjYXNlLWluc2Vuc2l0aXZlXG4gICAgfVxuXG4gICAgaWYgKGJsYW5rTGluZXMpIHtcbiAgICAgIC8vIE9vcHMsIGZvdW5kIGJsYW5rIGxpbmVzLCBzbyBpdCdzIG5vdCBhIHRpdGxlLlxuICAgICAgLy8gUHV0IGJhY2sgdGhlIHBhcmVudGhldGljYWwgc3RhdGVtZW50IHdlIHN0b2xlLlxuICAgICAgcmV0dXJuIGJsYW5rTGluZXMgKyB0aXRsZTtcblxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGl0bGUpIHtcbiAgICAgICAgZ2xvYmFscy5nVGl0bGVzW2xpbmtJZF0gPSB0aXRsZS5yZXBsYWNlKC9cInwnL2csICcmcXVvdDsnKTtcbiAgICAgIH1cbiAgICAgIGlmIChvcHRpb25zLnBhcnNlSW1nRGltZW5zaW9ucyAmJiB3aWR0aCAmJiBoZWlnaHQpIHtcbiAgICAgICAgZ2xvYmFscy5nRGltZW5zaW9uc1tsaW5rSWRdID0ge1xuICAgICAgICAgIHdpZHRoOiAgd2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBoZWlnaHRcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQ29tcGxldGVseSByZW1vdmUgdGhlIGRlZmluaXRpb24gZnJvbSB0aGUgdGV4dFxuICAgIHJldHVybiAnJztcbiAgfTtcblxuICAvLyBmaXJzdCB3ZSB0cnkgdG8gZmluZCBiYXNlNjQgbGluayByZWZlcmVuY2VzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoYmFzZTY0UmVnZXgsIHJlcGxhY2VGdW5jKTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlZ2V4LCByZXBsYWNlRnVuYyk7XG5cbiAgLy8gYXR0YWNrbGFiOiBzdHJpcCBzZW50aW5lbFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqDAvLCAnJyk7XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3RhYmxlcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMudGFibGVzKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICB2YXIgdGFibGVSZ3ggICAgICAgPSAvXiB7MCwzfVxcfD8uK1xcfC4rXFxuIHswLDN9XFx8P1sgXFx0XSo6P1sgXFx0XSooPzpbLT1dKXsyLH1bIFxcdF0qOj9bIFxcdF0qXFx8WyBcXHRdKjo/WyBcXHRdKig/OlstPV0pezIsfVtcXHNcXFNdKz8oPzpcXG5cXG58wqgwKS9nbSxcbiAgICAgIC8vc2luZ2VDb2xUYmxSZ3ggPSAvXiB7MCwzfVxcfC4rXFx8XFxuIHswLDN9XFx8WyBcXHRdKjo/WyBcXHRdKig/OlstPV0pezIsfVsgXFx0XSo6P1sgXFx0XSpcXHxbIFxcdF0qXFxuKD86IHswLDN9XFx8LitcXHxcXG4pKyg/OlxcblxcbnzCqDApL2dtO1xuICAgICAgc2luZ2VDb2xUYmxSZ3ggPSAvXiB7MCwzfVxcfC4rXFx8WyBcXHRdKlxcbiB7MCwzfVxcfFsgXFx0XSo6P1sgXFx0XSooPzpbLT1dKXsyLH1bIFxcdF0qOj9bIFxcdF0qXFx8WyBcXHRdKlxcbiggezAsM31cXHwuK1xcfFsgXFx0XSpcXG4pKig/OlxcbnzCqDApL2dtO1xuXG4gIGZ1bmN0aW9uIHBhcnNlU3R5bGVzIChzTGluZSkge1xuICAgIGlmICgvXjpbIFxcdF0qLS0qJC8udGVzdChzTGluZSkpIHtcbiAgICAgIHJldHVybiAnIHN0eWxlPVwidGV4dC1hbGlnbjpsZWZ0O1wiJztcbiAgICB9IGVsc2UgaWYgKC9eLS0qWyBcXHRdKjpbIFxcdF0qJC8udGVzdChzTGluZSkpIHtcbiAgICAgIHJldHVybiAnIHN0eWxlPVwidGV4dC1hbGlnbjpyaWdodDtcIic7XG4gICAgfSBlbHNlIGlmICgvXjpbIFxcdF0qLS0qWyBcXHRdKjokLy50ZXN0KHNMaW5lKSkge1xuICAgICAgcmV0dXJuICcgc3R5bGU9XCJ0ZXh0LWFsaWduOmNlbnRlcjtcIic7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUhlYWRlcnMgKGhlYWRlciwgc3R5bGUpIHtcbiAgICB2YXIgaWQgPSAnJztcbiAgICBoZWFkZXIgPSBoZWFkZXIudHJpbSgpO1xuICAgIC8vIHN1cHBvcnQgYm90aCB0YWJsZXNIZWFkZXJJZCBhbmQgdGFibGVIZWFkZXJJZCBkdWUgdG8gZXJyb3IgaW4gZG9jdW1lbnRhdGlvbiBzbyB3ZSBkb24ndCBicmVhayBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuICAgIGlmIChvcHRpb25zLnRhYmxlc0hlYWRlcklkIHx8IG9wdGlvbnMudGFibGVIZWFkZXJJZCkge1xuICAgICAgaWQgPSAnIGlkPVwiJyArIGhlYWRlci5yZXBsYWNlKC8gL2csICdfJykudG9Mb3dlckNhc2UoKSArICdcIic7XG4gICAgfVxuICAgIGhlYWRlciA9IHNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0JykoaGVhZGVyLCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAgIHJldHVybiAnPHRoJyArIGlkICsgc3R5bGUgKyAnPicgKyBoZWFkZXIgKyAnPC90aD5cXG4nO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VDZWxscyAoY2VsbCwgc3R5bGUpIHtcbiAgICB2YXIgc3ViVGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignc3BhbkdhbXV0JykoY2VsbCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgcmV0dXJuICc8dGQnICsgc3R5bGUgKyAnPicgKyBzdWJUZXh0ICsgJzwvdGQ+XFxuJztcbiAgfVxuXG4gIGZ1bmN0aW9uIGJ1aWxkVGFibGUgKGhlYWRlcnMsIGNlbGxzKSB7XG4gICAgdmFyIHRiID0gJzx0YWJsZT5cXG48dGhlYWQ+XFxuPHRyPlxcbicsXG4gICAgICAgIHRibExnbiA9IGhlYWRlcnMubGVuZ3RoO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0YmxMZ247ICsraSkge1xuICAgICAgdGIgKz0gaGVhZGVyc1tpXTtcbiAgICB9XG4gICAgdGIgKz0gJzwvdHI+XFxuPC90aGVhZD5cXG48dGJvZHk+XFxuJztcblxuICAgIGZvciAoaSA9IDA7IGkgPCBjZWxscy5sZW5ndGg7ICsraSkge1xuICAgICAgdGIgKz0gJzx0cj5cXG4nO1xuICAgICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IHRibExnbjsgKytpaSkge1xuICAgICAgICB0YiArPSBjZWxsc1tpXVtpaV07XG4gICAgICB9XG4gICAgICB0YiArPSAnPC90cj5cXG4nO1xuICAgIH1cbiAgICB0YiArPSAnPC90Ym9keT5cXG48L3RhYmxlPlxcbic7XG4gICAgcmV0dXJuIHRiO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VUYWJsZSAocmF3VGFibGUpIHtcbiAgICB2YXIgaSwgdGFibGVMaW5lcyA9IHJhd1RhYmxlLnNwbGl0KCdcXG4nKTtcblxuICAgIGZvciAoaSA9IDA7IGkgPCB0YWJsZUxpbmVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAvLyBzdHJpcCB3cm9uZyBmaXJzdCBhbmQgbGFzdCBjb2x1bW4gaWYgd3JhcHBlZCB0YWJsZXMgYXJlIHVzZWRcbiAgICAgIGlmICgvXiB7MCwzfVxcfC8udGVzdCh0YWJsZUxpbmVzW2ldKSkge1xuICAgICAgICB0YWJsZUxpbmVzW2ldID0gdGFibGVMaW5lc1tpXS5yZXBsYWNlKC9eIHswLDN9XFx8LywgJycpO1xuICAgICAgfVxuICAgICAgaWYgKC9cXHxbIFxcdF0qJC8udGVzdCh0YWJsZUxpbmVzW2ldKSkge1xuICAgICAgICB0YWJsZUxpbmVzW2ldID0gdGFibGVMaW5lc1tpXS5yZXBsYWNlKC9cXHxbIFxcdF0qJC8sICcnKTtcbiAgICAgIH1cbiAgICAgIC8vIHBhcnNlIGNvZGUgc3BhbnMgZmlyc3QsIGJ1dCB3ZSBvbmx5IHN1cHBvcnQgb25lIGxpbmUgY29kZSBzcGFuc1xuICAgICAgdGFibGVMaW5lc1tpXSA9IHNob3dkb3duLnN1YlBhcnNlcignY29kZVNwYW5zJykodGFibGVMaW5lc1tpXSwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgfVxuXG4gICAgdmFyIHJhd0hlYWRlcnMgPSB0YWJsZUxpbmVzWzBdLnNwbGl0KCd8JykubWFwKGZ1bmN0aW9uIChzKSB7IHJldHVybiBzLnRyaW0oKTt9KSxcbiAgICAgICAgcmF3U3R5bGVzID0gdGFibGVMaW5lc1sxXS5zcGxpdCgnfCcpLm1hcChmdW5jdGlvbiAocykgeyByZXR1cm4gcy50cmltKCk7fSksXG4gICAgICAgIHJhd0NlbGxzID0gW10sXG4gICAgICAgIGhlYWRlcnMgPSBbXSxcbiAgICAgICAgc3R5bGVzID0gW10sXG4gICAgICAgIGNlbGxzID0gW107XG5cbiAgICB0YWJsZUxpbmVzLnNoaWZ0KCk7XG4gICAgdGFibGVMaW5lcy5zaGlmdCgpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IHRhYmxlTGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmICh0YWJsZUxpbmVzW2ldLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICByYXdDZWxscy5wdXNoKFxuICAgICAgICB0YWJsZUxpbmVzW2ldXG4gICAgICAgICAgLnNwbGl0KCd8JylcbiAgICAgICAgICAubWFwKGZ1bmN0aW9uIChzKSB7XG4gICAgICAgICAgICByZXR1cm4gcy50cmltKCk7XG4gICAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHJhd0hlYWRlcnMubGVuZ3RoIDwgcmF3U3R5bGVzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHJhd1RhYmxlO1xuICAgIH1cblxuICAgIGZvciAoaSA9IDA7IGkgPCByYXdTdHlsZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHN0eWxlcy5wdXNoKHBhcnNlU3R5bGVzKHJhd1N0eWxlc1tpXSkpO1xuICAgIH1cblxuICAgIGZvciAoaSA9IDA7IGkgPCByYXdIZWFkZXJzLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKHN0eWxlc1tpXSkpIHtcbiAgICAgICAgc3R5bGVzW2ldID0gJyc7XG4gICAgICB9XG4gICAgICBoZWFkZXJzLnB1c2gocGFyc2VIZWFkZXJzKHJhd0hlYWRlcnNbaV0sIHN0eWxlc1tpXSkpO1xuICAgIH1cblxuICAgIGZvciAoaSA9IDA7IGkgPCByYXdDZWxscy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIHJvdyA9IFtdO1xuICAgICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IGhlYWRlcnMubGVuZ3RoOyArK2lpKSB7XG4gICAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQocmF3Q2VsbHNbaV1baWldKSkge1xuXG4gICAgICAgIH1cbiAgICAgICAgcm93LnB1c2gocGFyc2VDZWxscyhyYXdDZWxsc1tpXVtpaV0sIHN0eWxlc1tpaV0pKTtcbiAgICAgIH1cbiAgICAgIGNlbGxzLnB1c2gocm93KTtcbiAgICB9XG5cbiAgICByZXR1cm4gYnVpbGRUYWJsZShoZWFkZXJzLCBjZWxscyk7XG4gIH1cblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd0YWJsZXMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gZmluZCBlc2NhcGVkIHBpcGUgY2hhcmFjdGVyc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFxcKFxcfCkvZywgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG5cbiAgLy8gcGFyc2UgbXVsdGkgY29sdW1uIHRhYmxlc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHRhYmxlUmd4LCBwYXJzZVRhYmxlKTtcblxuICAvLyBwYXJzZSBvbmUgY29sdW1uIHRhYmxlc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHNpbmdlQ29sVGJsUmd4LCBwYXJzZVRhYmxlKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd0YWJsZXMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcigndW5kZXJsaW5lJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghb3B0aW9ucy51bmRlcmxpbmUpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3VuZGVybGluZS5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICBpZiAob3B0aW9ucy5saXRlcmFsTWlkV29yZFVuZGVyc2NvcmVzKSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxiX19fKFxcU1tcXHNcXFNdKj8pX19fXFxiL2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7XG4gICAgICByZXR1cm4gJzx1PicgKyB0eHQgKyAnPC91Pic7XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxiX18oXFxTW1xcc1xcU10qPylfX1xcYi9nLCBmdW5jdGlvbiAod20sIHR4dCkge1xuICAgICAgcmV0dXJuICc8dT4nICsgdHh0ICsgJzwvdT4nO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL19fXyhcXFNbXFxzXFxTXSo/KV9fXy9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gJzx1PicgKyBtICsgJzwvdT4nIDogd207XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvX18oXFxTW1xcc1xcU10qPylfXy9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gJzx1PicgKyBtICsgJzwvdT4nIDogd207XG4gICAgfSk7XG4gIH1cblxuICAvLyBlc2NhcGUgcmVtYWluaW5nIHVuZGVyc2NvcmVzIHRvIHByZXZlbnQgdGhlbSBiZWluZyBwYXJzZWQgYnkgaXRhbGljIGFuZCBib2xkXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhfKS9nLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmRlcmxpbmUuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogU3dhcCBiYWNrIGluIGFsbCB0aGUgc3BlY2lhbCBjaGFyYWN0ZXJzIHdlJ3ZlIGhpZGRlbi5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmVzY2FwZVNwZWNpYWxDaGFycycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgndW5lc2NhcGVTcGVjaWFsQ2hhcnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqhFKFxcZCspRS9nLCBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEpIHtcbiAgICB2YXIgY2hhckNvZGVUb1JlcGxhY2UgPSBwYXJzZUludChtMSk7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGVUb1JlcGxhY2UpO1xuICB9KTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmVzY2FwZVNwZWNpYWxDaGFycy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmJsb2NrcXVvdGUnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICAgIGNoaWxkcmVuTGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaW5uZXJUeHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMpO1xuXG4gICAgICBpZiAoaW5uZXJUeHQgPT09ICcnKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgdHh0ICs9IGlubmVyVHh0O1xuICAgIH1cbiAgfVxuICAvLyBjbGVhbnVwXG4gIHR4dCA9IHR4dC50cmltKCk7XG4gIHR4dCA9ICc+ICcgKyB0eHQuc3BsaXQoJ1xcbicpLmpvaW4oJ1xcbj4gJyk7XG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5jb2RlQmxvY2snLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIGxhbmcgPSBub2RlLmdldEF0dHJpYnV0ZSgnbGFuZ3VhZ2UnKSxcbiAgICAgIG51bSAgPSBub2RlLmdldEF0dHJpYnV0ZSgncHJlY29kZW51bScpO1xuICByZXR1cm4gJ2BgYCcgKyBsYW5nICsgJ1xcbicgKyBnbG9iYWxzLnByZUxpc3RbbnVtXSArICdcXG5gYGAnO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uY29kZVNwYW4nLCBmdW5jdGlvbiAobm9kZSkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgcmV0dXJuICdgJyArIG5vZGUuaW5uZXJIVE1MICsgJ2AnO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uZW1waGFzaXMnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICB0eHQgKz0gJyonO1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzKTtcbiAgICB9XG4gICAgdHh0ICs9ICcqJztcbiAgfVxuICByZXR1cm4gdHh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMsIGhlYWRlckxldmVsKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgaGVhZGVyTWFyayA9IG5ldyBBcnJheShoZWFkZXJMZXZlbCArIDEpLmpvaW4oJyMnKSxcbiAgICAgIHR4dCA9ICcnO1xuXG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHR4dCA9IGhlYWRlck1hcmsgKyAnICc7XG4gICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZE5vZGVzLFxuICAgICAgICBjaGlsZHJlbkxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5ndGg7ICsraSkge1xuICAgICAgdHh0ICs9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG4gICAgfVxuICB9XG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ocicsIGZ1bmN0aW9uICgpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHJldHVybiAnLS0tJztcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmltYWdlJywgZnVuY3Rpb24gKG5vZGUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJztcbiAgaWYgKG5vZGUuaGFzQXR0cmlidXRlKCdzcmMnKSkge1xuICAgIHR4dCArPSAnIVsnICsgbm9kZS5nZXRBdHRyaWJ1dGUoJ2FsdCcpICsgJ10oJztcbiAgICB0eHQgKz0gJzwnICsgbm9kZS5nZXRBdHRyaWJ1dGUoJ3NyYycpICsgJz4nO1xuICAgIGlmIChub2RlLmhhc0F0dHJpYnV0ZSgnd2lkdGgnKSAmJiBub2RlLmhhc0F0dHJpYnV0ZSgnaGVpZ2h0JykpIHtcbiAgICAgIHR4dCArPSAnID0nICsgbm9kZS5nZXRBdHRyaWJ1dGUoJ3dpZHRoJykgKyAneCcgKyBub2RlLmdldEF0dHJpYnV0ZSgnaGVpZ2h0Jyk7XG4gICAgfVxuXG4gICAgaWYgKG5vZGUuaGFzQXR0cmlidXRlKCd0aXRsZScpKSB7XG4gICAgICB0eHQgKz0gJyBcIicgKyBub2RlLmdldEF0dHJpYnV0ZSgndGl0bGUnKSArICdcIic7XG4gICAgfVxuICAgIHR4dCArPSAnKSc7XG4gIH1cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmxpbmtzJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJztcbiAgaWYgKG5vZGUuaGFzQ2hpbGROb2RlcygpICYmIG5vZGUuaGFzQXR0cmlidXRlKCdocmVmJykpIHtcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICAgIGNoaWxkcmVuTGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgIHR4dCA9ICdbJztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ3RoOyArK2kpIHtcbiAgICAgIHR4dCArPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMpO1xuICAgIH1cbiAgICB0eHQgKz0gJ10oJztcbiAgICB0eHQgKz0gJzwnICsgbm9kZS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKSArICc+JztcbiAgICBpZiAobm9kZS5oYXNBdHRyaWJ1dGUoJ3RpdGxlJykpIHtcbiAgICAgIHR4dCArPSAnIFwiJyArIG5vZGUuZ2V0QXR0cmlidXRlKCd0aXRsZScpICsgJ1wiJztcbiAgICB9XG4gICAgdHh0ICs9ICcpJztcbiAgfVxuICByZXR1cm4gdHh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlzdCcsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzLCB0eXBlKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmICghbm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cbiAgdmFyIGxpc3RJdGVtcyAgICAgICA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgIGxpc3RJdGVtc0xlbmdodCA9IGxpc3RJdGVtcy5sZW5ndGgsXG4gICAgICBsaXN0TnVtID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ3N0YXJ0JykgfHwgMTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RJdGVtc0xlbmdodDsgKytpKSB7XG4gICAgaWYgKHR5cGVvZiBsaXN0SXRlbXNbaV0udGFnTmFtZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbGlzdEl0ZW1zW2ldLnRhZ05hbWUudG9Mb3dlckNhc2UoKSAhPT0gJ2xpJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gZGVmaW5lIHRoZSBidWxsZXQgdG8gdXNlIGluIGxpc3RcbiAgICB2YXIgYnVsbGV0ID0gJyc7XG4gICAgaWYgKHR5cGUgPT09ICdvbCcpIHtcbiAgICAgIGJ1bGxldCA9IGxpc3ROdW0udG9TdHJpbmcoKSArICcuICc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJ1bGxldCA9ICctICc7XG4gICAgfVxuXG4gICAgLy8gcGFyc2UgbGlzdCBpdGVtXG4gICAgdHh0ICs9IGJ1bGxldCArIHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmxpc3RJdGVtJykobGlzdEl0ZW1zW2ldLCBnbG9iYWxzKTtcbiAgICArK2xpc3ROdW07XG4gIH1cblxuICAvLyBhZGQgY29tbWVudCBhdCB0aGUgZW5kIHRvIHByZXZlbnQgY29uc2VjdXRpdmUgbGlzdHMgdG8gYmUgcGFyc2VkIGFzIG9uZVxuICB0eHQgKz0gJ1xcbjwhLS0gLS0+XFxuJztcbiAgcmV0dXJuIHR4dC50cmltKCk7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5saXN0SXRlbScsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgbGlzdEl0ZW1UeHQgPSAnJztcblxuICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICBjaGlsZHJlbkxlbmdodCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ2h0OyArK2kpIHtcbiAgICBsaXN0SXRlbVR4dCArPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMpO1xuICB9XG4gIC8vIGlmIGl0J3Mgb25seSBvbmUgbGluZXIsIHdlIG5lZWQgdG8gYWRkIGEgbmV3bGluZSBhdCB0aGUgZW5kXG4gIGlmICghL1xcbiQvLnRlc3QobGlzdEl0ZW1UeHQpKSB7XG4gICAgbGlzdEl0ZW1UeHQgKz0gJ1xcbic7XG4gIH0gZWxzZSB7XG4gICAgLy8gaXQncyBtdWx0aXBhcmFncmFwaCwgc28gd2UgbmVlZCB0byBpbmRlbnRcbiAgICBsaXN0SXRlbVR4dCA9IGxpc3RJdGVtVHh0XG4gICAgICAuc3BsaXQoJ1xcbicpXG4gICAgICAuam9pbignXFxuICAgICcpXG4gICAgICAucmVwbGFjZSgvXiB7NH0kL2dtLCAnJylcbiAgICAgIC5yZXBsYWNlKC9cXG5cXG4rL2csICdcXG5cXG4nKTtcbiAgfVxuXG4gIHJldHVybiBsaXN0SXRlbVR4dDtcbn0pO1xuXHJcblxuXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMsIHNwYW5zT25seSkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgc3BhbnNPbmx5ID0gc3BhbnNPbmx5IHx8IGZhbHNlO1xuXG4gIHZhciB0eHQgPSAnJztcblxuICAvLyBlZGdlIGNhc2Ugb2YgdGV4dCB3aXRob3V0IHdyYXBwZXIgcGFyYWdyYXBoXG4gIGlmIChub2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgcmV0dXJuIHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnR4dCcpKG5vZGUsIGdsb2JhbHMpO1xuICB9XG5cbiAgLy8gSFRNTCBjb21tZW50XG4gIGlmIChub2RlLm5vZGVUeXBlID09PSA4KSB7XG4gICAgcmV0dXJuICc8IS0tJyArIG5vZGUuZGF0YSArICctLT5cXG5cXG4nO1xuICB9XG5cbiAgLy8gcHJvY2VzcyBvbmx5IG5vZGUgZWxlbWVudHNcbiAgaWYgKG5vZGUubm9kZVR5cGUgIT09IDEpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICB2YXIgdGFnTmFtZSA9IG5vZGUudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gIHN3aXRjaCAodGFnTmFtZSkge1xuXG4gICAgLy9cbiAgICAvLyBCTE9DS1NcbiAgICAvL1xuICAgIGNhc2UgJ2gxJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmhlYWRlcicpKG5vZGUsIGdsb2JhbHMsIDEpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2gyJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmhlYWRlcicpKG5vZGUsIGdsb2JhbHMsIDIpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2gzJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmhlYWRlcicpKG5vZGUsIGdsb2JhbHMsIDMpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2g0JzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmhlYWRlcicpKG5vZGUsIGdsb2JhbHMsIDQpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2g1JzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmhlYWRlcicpKG5vZGUsIGdsb2JhbHMsIDUpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2g2JzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmhlYWRlcicpKG5vZGUsIGdsb2JhbHMsIDYpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAncCc6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5wYXJhZ3JhcGgnKShub2RlLCBnbG9iYWxzKSArICdcXG5cXG4nOyB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2Jsb2NrcXVvdGUnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uYmxvY2txdW90ZScpKG5vZGUsIGdsb2JhbHMpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnaHInOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaHInKShub2RlLCBnbG9iYWxzKSArICdcXG5cXG4nOyB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ29sJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmxpc3QnKShub2RlLCBnbG9iYWxzLCAnb2wnKSArICdcXG5cXG4nOyB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3VsJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmxpc3QnKShub2RlLCBnbG9iYWxzLCAndWwnKSArICdcXG5cXG4nOyB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3ByZWNvZGUnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uY29kZUJsb2NrJykobm9kZSwgZ2xvYmFscykgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdwcmUnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ucHJlJykobm9kZSwgZ2xvYmFscykgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICd0YWJsZSc6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi50YWJsZScpKG5vZGUsIGdsb2JhbHMpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgLy9cbiAgICAvLyBTUEFOU1xuICAgIC8vXG4gICAgY2FzZSAnY29kZSc6XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5jb2RlU3BhbicpKG5vZGUsIGdsb2JhbHMpO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdlbSc6XG4gICAgY2FzZSAnaSc6XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5lbXBoYXNpcycpKG5vZGUsIGdsb2JhbHMpO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdzdHJvbmcnOlxuICAgIGNhc2UgJ2InOlxuICAgICAgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uc3Ryb25nJykobm9kZSwgZ2xvYmFscyk7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2RlbCc6XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5zdHJpa2V0aHJvdWdoJykobm9kZSwgZ2xvYmFscyk7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2EnOlxuICAgICAgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlua3MnKShub2RlLCBnbG9iYWxzKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnaW1nJzpcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmltYWdlJykobm9kZSwgZ2xvYmFscyk7XG4gICAgICBicmVhaztcblxuICAgIGRlZmF1bHQ6XG4gICAgICB0eHQgPSBub2RlLm91dGVySFRNTCArICdcXG5cXG4nO1xuICB9XG5cbiAgLy8gY29tbW9uIG5vcm1hbGl6YXRpb25cbiAgLy8gVE9ETyBldmVudHVhbGx5XG5cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnBhcmFncmFwaCcsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzKTtcbiAgICB9XG4gIH1cblxuICAvLyBzb21lIHRleHQgbm9ybWFsaXphdGlvblxuICB0eHQgPSB0eHQudHJpbSgpO1xuXG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5wcmUnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIG51bSAgPSBub2RlLmdldEF0dHJpYnV0ZSgncHJlbnVtJyk7XG4gIHJldHVybiAnPHByZT4nICsgZ2xvYmFscy5wcmVMaXN0W251bV0gKyAnPC9wcmU+Jztcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnN0cmlrZXRocm91Z2gnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICB0eHQgKz0gJ35+JztcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICAgIGNoaWxkcmVuTGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5ndGg7ICsraSkge1xuICAgICAgdHh0ICs9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG4gICAgfVxuICAgIHR4dCArPSAnfn4nO1xuICB9XG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5zdHJvbmcnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcbiAgICB0eHQgKz0gJyoqJztcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICAgIGNoaWxkcmVuTGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5ndGg7ICsraSkge1xuICAgICAgdHh0ICs9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG4gICAgfVxuICAgIHR4dCArPSAnKionO1xuICB9XG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi50YWJsZScsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJycsXG4gICAgICB0YWJsZUFycmF5ID0gW1tdLCBbXV0sXG4gICAgICBoZWFkaW5ncyAgID0gbm9kZS5xdWVyeVNlbGVjdG9yQWxsKCd0aGVhZD50cj50aCcpLFxuICAgICAgcm93cyAgICAgICA9IG5vZGUucXVlcnlTZWxlY3RvckFsbCgndGJvZHk+dHInKSxcbiAgICAgIGksIGlpO1xuICBmb3IgKGkgPSAwOyBpIDwgaGVhZGluZ3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgaGVhZENvbnRlbnQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi50YWJsZUNlbGwnKShoZWFkaW5nc1tpXSwgZ2xvYmFscyksXG4gICAgICAgIGFsbGlnbiA9ICctLS0nO1xuXG4gICAgaWYgKGhlYWRpbmdzW2ldLmhhc0F0dHJpYnV0ZSgnc3R5bGUnKSkge1xuICAgICAgdmFyIHN0eWxlID0gaGVhZGluZ3NbaV0uZ2V0QXR0cmlidXRlKCdzdHlsZScpLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICAgIHN3aXRjaCAoc3R5bGUpIHtcbiAgICAgICAgY2FzZSAndGV4dC1hbGlnbjpsZWZ0Oyc6XG4gICAgICAgICAgYWxsaWduID0gJzotLS0nO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd0ZXh0LWFsaWduOnJpZ2h0Oyc6XG4gICAgICAgICAgYWxsaWduID0gJy0tLTonO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd0ZXh0LWFsaWduOmNlbnRlcjsnOlxuICAgICAgICAgIGFsbGlnbiA9ICc6LS0tOic7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHRhYmxlQXJyYXlbMF1baV0gPSBoZWFkQ29udGVudC50cmltKCk7XG4gICAgdGFibGVBcnJheVsxXVtpXSA9IGFsbGlnbjtcbiAgfVxuXG4gIGZvciAoaSA9IDA7IGkgPCByb3dzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHIgPSB0YWJsZUFycmF5LnB1c2goW10pIC0gMSxcbiAgICAgICAgY29scyA9IHJvd3NbaV0uZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3RkJyk7XG5cbiAgICBmb3IgKGlpID0gMDsgaWkgPCBoZWFkaW5ncy5sZW5ndGg7ICsraWkpIHtcbiAgICAgIHZhciBjZWxsQ29udGVudCA9ICcgJztcbiAgICAgIGlmICh0eXBlb2YgY29sc1tpaV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNlbGxDb250ZW50ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24udGFibGVDZWxsJykoY29sc1tpaV0sIGdsb2JhbHMpO1xuICAgICAgfVxuICAgICAgdGFibGVBcnJheVtyXS5wdXNoKGNlbGxDb250ZW50KTtcbiAgICB9XG4gIH1cblxuICB2YXIgY2VsbFNwYWNlc0NvdW50ID0gMztcbiAgZm9yIChpID0gMDsgaSA8IHRhYmxlQXJyYXkubGVuZ3RoOyArK2kpIHtcbiAgICBmb3IgKGlpID0gMDsgaWkgPCB0YWJsZUFycmF5W2ldLmxlbmd0aDsgKytpaSkge1xuICAgICAgdmFyIHN0ckxlbiA9IHRhYmxlQXJyYXlbaV1baWldLmxlbmd0aDtcbiAgICAgIGlmIChzdHJMZW4gPiBjZWxsU3BhY2VzQ291bnQpIHtcbiAgICAgICAgY2VsbFNwYWNlc0NvdW50ID0gc3RyTGVuO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZvciAoaSA9IDA7IGkgPCB0YWJsZUFycmF5Lmxlbmd0aDsgKytpKSB7XG4gICAgZm9yIChpaSA9IDA7IGlpIDwgdGFibGVBcnJheVtpXS5sZW5ndGg7ICsraWkpIHtcbiAgICAgIGlmIChpID09PSAxKSB7XG4gICAgICAgIGlmICh0YWJsZUFycmF5W2ldW2lpXS5zbGljZSgtMSkgPT09ICc6Jykge1xuICAgICAgICAgIHRhYmxlQXJyYXlbaV1baWldID0gc2hvd2Rvd24uaGVscGVyLnBhZEVuZCh0YWJsZUFycmF5W2ldW2lpXS5zbGljZSgtMSksIGNlbGxTcGFjZXNDb3VudCAtIDEsICctJykgKyAnOic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGFibGVBcnJheVtpXVtpaV0gPSBzaG93ZG93bi5oZWxwZXIucGFkRW5kKHRhYmxlQXJyYXlbaV1baWldLCBjZWxsU3BhY2VzQ291bnQsICctJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRhYmxlQXJyYXlbaV1baWldID0gc2hvd2Rvd24uaGVscGVyLnBhZEVuZCh0YWJsZUFycmF5W2ldW2lpXSwgY2VsbFNwYWNlc0NvdW50KTtcbiAgICAgIH1cbiAgICB9XG4gICAgdHh0ICs9ICd8ICcgKyB0YWJsZUFycmF5W2ldLmpvaW4oJyB8ICcpICsgJyB8XFxuJztcbiAgfVxuXG4gIHJldHVybiB0eHQudHJpbSgpO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24udGFibGVDZWxsJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJztcbiAgaWYgKCFub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICBjaGlsZHJlbkxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ3RoOyArK2kpIHtcbiAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzLCB0cnVlKTtcbiAgfVxuICByZXR1cm4gdHh0LnRyaW0oKTtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnR4dCcsIGZ1bmN0aW9uIChub2RlKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gbm9kZS5ub2RlVmFsdWU7XG5cbiAgLy8gbXVsdGlwbGUgc3BhY2VzIGFyZSBjb2xsYXBzZWRcbiAgdHh0ID0gdHh0LnJlcGxhY2UoLyArL2csICcgJyk7XG5cbiAgLy8gcmVwbGFjZSB0aGUgY3VzdG9tIMKoTkJTUDsgd2l0aCBhIHNwYWNlXG4gIHR4dCA9IHR4dC5yZXBsYWNlKC/CqE5CU1A7L2csICcgJyk7XG5cbiAgLy8gXCIsIDwsID4gYW5kICYgc2hvdWxkIHJlcGxhY2UgZXNjYXBlZCBodG1sIGVudGl0aWVzXG4gIHR4dCA9IHNob3dkb3duLmhlbHBlci51bmVzY2FwZUhUTUxFbnRpdGllcyh0eHQpO1xuXG4gIC8vIGVzY2FwZSBtYXJrZG93biBtYWdpYyBjaGFyYWN0ZXJzXG4gIC8vIGVtcGhhc2lzLCBzdHJvbmcgYW5kIHN0cmlrZXRocm91Z2ggLSBjYW4gYXBwZWFyIGV2ZXJ5d2hlcmVcbiAgLy8gd2UgYWxzbyBlc2NhcGUgcGlwZSAofCkgYmVjYXVzZSBvZiB0YWJsZXNcbiAgLy8gYW5kIGVzY2FwZSBgIGJlY2F1c2Ugb2YgY29kZSBibG9ja3MgYW5kIHNwYW5zXG4gIHR4dCA9IHR4dC5yZXBsYWNlKC8oWypffnxgXSkvZywgJ1xcXFwkMScpO1xuXG4gIC8vIGVzY2FwZSA+IGJlY2F1c2Ugb2YgYmxvY2txdW90ZXNcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL14oXFxzKik+L2csICdcXFxcJDE+Jyk7XG5cbiAgLy8gaGFzaCBjaGFyYWN0ZXIsIG9ubHkgdHJvdWJsZXNvbWUgYXQgdGhlIGJlZ2lubmluZyBvZiBhIGxpbmUgYmVjYXVzZSBvZiBoZWFkZXJzXG4gIHR4dCA9IHR4dC5yZXBsYWNlKC9eIy9nbSwgJ1xcXFwjJyk7XG5cbiAgLy8gaG9yaXpvbnRhbCBydWxlc1xuICB0eHQgPSB0eHQucmVwbGFjZSgvXihcXHMqKShbLT1dezMsfSkoXFxzKikkLywgJyQxXFxcXCQyJDMnKTtcblxuICAvLyBkb3QsIGJlY2F1c2Ugb2Ygb3JkZXJlZCBsaXN0cywgb25seSB0cm91Ymxlc29tZSBhdCB0aGUgYmVnaW5uaW5nIG9mIGEgbGluZSB3aGVuIHByZWNlZGVkIGJ5IGFuIGludGVnZXJcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL14oIHswLDN9XFxkKylcXC4vZ20sICckMVxcXFwuJyk7XG5cbiAgLy8gKywgKiBhbmQgLSwgYXQgdGhlIGJlZ2lubmluZyBvZiBhIGxpbmUgYmVjb21lcyBhIGxpc3QsIHNvIHdlIG5lZWQgdG8gZXNjYXBlIHRoZW0gYWxzbyAoYXN0ZXJpc2sgd2FzIGFscmVhZHkgZXNjYXBlZClcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL14oIHswLDN9KShbKy1dKS9nbSwgJyQxXFxcXCQyJyk7XG5cbiAgLy8gaW1hZ2VzIGFuZCBsaW5rcywgXSBmb2xsb3dlZCBieSAoIGlzIHByb2JsZW1hdGljLCBzbyB3ZSBlc2NhcGUgaXRcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL10oW1xcc10qKVxcKC9nLCAnXFxcXF0kMVxcXFwoJyk7XG5cbiAgLy8gcmVmZXJlbmNlIFVSSXMgbXVzdCBhbHNvIGJlIGVzY2FwZWRcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL14gezAsM31cXFsoW1xcUyBcXHRdKj8pXTovZ20sICdcXFxcWyQxXTonKTtcblxuICByZXR1cm4gdHh0O1xufSk7XG5cclxudmFyIHJvb3QgPSB0aGlzO1xuXG4vLyBBTUQgTG9hZGVyXG5pZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuICAgIHJldHVybiBzaG93ZG93bjtcbiAgfSk7XG5cbi8vIENvbW1vbkpTL25vZGVKUyBMb2FkZXJcbn0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSBzaG93ZG93bjtcblxuLy8gUmVndWxhciBCcm93c2VyIGxvYWRlclxufSBlbHNlIHtcbiAgcm9vdC5zaG93ZG93biA9IHNob3dkb3duO1xufVxufSkuY2FsbCh0aGlzKTtcclxuXG4vLyMgc291cmNlTWFwcGluZ1VSTD1zaG93ZG93bi5qcy5tYXBcclxuIiwiLy8gUmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAwOS0yMDEwIERvbWluaWMgQmFnZ290dFxuLy8gQ29weXJpZ2h0IChjKSAyMDA5LTIwMTAgQXNoIEJlcmxpblxuLy8gQ29weXJpZ2h0IChjKSAyMDExIENocmlzdG9waCBEb3JuIDxjaHJpc3RvcGhAY2hyaXN0b3BoZG9ybi5jb20+IChodHRwOi8vd3d3LmNocmlzdG9waGRvcm4uY29tKVxuXG4vKmpzaGludCBicm93c2VyOnRydWUsIGRldmVsOnRydWUgKi9cblxuKGZ1bmN0aW9uKCBleHBvc2UgKSB7XG5cbi8qKlxuICogIGNsYXNzIE1hcmtkb3duXG4gKlxuICogIE1hcmtkb3duIHByb2Nlc3NpbmcgaW4gSmF2YXNjcmlwdCBkb25lIHJpZ2h0LiBXZSBoYXZlIHZlcnkgcGFydGljdWxhciB2aWV3c1xuICogIG9uIHdoYXQgY29uc3RpdHV0ZXMgJ3JpZ2h0JyB3aGljaCBpbmNsdWRlOlxuICpcbiAqICAtIHByb2R1Y2VzIHdlbGwtZm9ybWVkIEhUTUwgKHRoaXMgbWVhbnMgdGhhdCBlbSBhbmQgc3Ryb25nIG5lc3RpbmcgaXNcbiAqICAgIGltcG9ydGFudClcbiAqXG4gKiAgLSBoYXMgYW4gaW50ZXJtZWRpYXRlIHJlcHJlc2VudGF0aW9uIHRvIGFsbG93IHByb2Nlc3Npbmcgb2YgcGFyc2VkIGRhdGEgKFdlXG4gKiAgICBpbiBmYWN0IGhhdmUgdHdvLCBib3RoIGFzIFtKc29uTUxdOiBhIG1hcmtkb3duIHRyZWUgYW5kIGFuIEhUTUwgdHJlZSkuXG4gKlxuICogIC0gaXMgZWFzaWx5IGV4dGVuc2libGUgdG8gYWRkIG5ldyBkaWFsZWN0cyB3aXRob3V0IGhhdmluZyB0byByZXdyaXRlIHRoZVxuICogICAgZW50aXJlIHBhcnNpbmcgbWVjaGFuaWNzXG4gKlxuICogIC0gaGFzIGEgZ29vZCB0ZXN0IHN1aXRlXG4gKlxuICogIFRoaXMgaW1wbGVtZW50YXRpb24gZnVsZmlsbHMgYWxsIG9mIHRoZXNlIChleGNlcHQgdGhhdCB0aGUgdGVzdCBzdWl0ZSBjb3VsZFxuICogIGRvIHdpdGggZXhwYW5kaW5nIHRvIGF1dG9tYXRpY2FsbHkgcnVuIGFsbCB0aGUgZml4dHVyZXMgZnJvbSBvdGhlciBNYXJrZG93blxuICogIGltcGxlbWVudGF0aW9ucy4pXG4gKlxuICogICMjIyMjIEludGVybWVkaWF0ZSBSZXByZXNlbnRhdGlvblxuICpcbiAqICAqVE9ETyogVGFsayBhYm91dCB0aGlzIDopIEl0cyBKc29uTUwsIGJ1dCBkb2N1bWVudCB0aGUgbm9kZSBuYW1lcyB3ZSB1c2UuXG4gKlxuICogIFtKc29uTUxdOiBodHRwOi8vanNvbm1sLm9yZy8gXCJKU09OIE1hcmt1cCBMYW5ndWFnZVwiXG4gKiovXG52YXIgTWFya2Rvd24gPSBleHBvc2UuTWFya2Rvd24gPSBmdW5jdGlvbihkaWFsZWN0KSB7XG4gIHN3aXRjaCAodHlwZW9mIGRpYWxlY3QpIHtcbiAgICBjYXNlIFwidW5kZWZpbmVkXCI6XG4gICAgICB0aGlzLmRpYWxlY3QgPSBNYXJrZG93bi5kaWFsZWN0cy5HcnViZXI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICB0aGlzLmRpYWxlY3QgPSBkaWFsZWN0O1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIGlmICggZGlhbGVjdCBpbiBNYXJrZG93bi5kaWFsZWN0cyApIHtcbiAgICAgICAgdGhpcy5kaWFsZWN0ID0gTWFya2Rvd24uZGlhbGVjdHNbZGlhbGVjdF07XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBNYXJrZG93biBkaWFsZWN0ICdcIiArIFN0cmluZyhkaWFsZWN0KSArIFwiJ1wiKTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICB9XG4gIHRoaXMuZW1fc3RhdGUgPSBbXTtcbiAgdGhpcy5zdHJvbmdfc3RhdGUgPSBbXTtcbiAgdGhpcy5kZWJ1Z19pbmRlbnQgPSBcIlwiO1xufTtcblxuLyoqXG4gKiAgcGFyc2UoIG1hcmtkb3duLCBbZGlhbGVjdF0gKSAtPiBKc29uTUxcbiAqICAtIG1hcmtkb3duIChTdHJpbmcpOiBtYXJrZG93biBzdHJpbmcgdG8gcGFyc2VcbiAqICAtIGRpYWxlY3QgKFN0cmluZyB8IERpYWxlY3QpOiB0aGUgZGlhbGVjdCB0byB1c2UsIGRlZmF1bHRzIHRvIGdydWJlclxuICpcbiAqICBQYXJzZSBgbWFya2Rvd25gIGFuZCByZXR1cm4gYSBtYXJrZG93biBkb2N1bWVudCBhcyBhIE1hcmtkb3duLkpzb25NTCB0cmVlLlxuICoqL1xuZXhwb3NlLnBhcnNlID0gZnVuY3Rpb24oIHNvdXJjZSwgZGlhbGVjdCApIHtcbiAgLy8gZGlhbGVjdCB3aWxsIGRlZmF1bHQgaWYgdW5kZWZpbmVkXG4gIHZhciBtZCA9IG5ldyBNYXJrZG93biggZGlhbGVjdCApO1xuICByZXR1cm4gbWQudG9UcmVlKCBzb3VyY2UgKTtcbn07XG5cbi8qKlxuICogIHRvSFRNTCggbWFya2Rvd24sIFtkaWFsZWN0XSAgKSAtPiBTdHJpbmdcbiAqICB0b0hUTUwoIG1kX3RyZWUgKSAtPiBTdHJpbmdcbiAqICAtIG1hcmtkb3duIChTdHJpbmcpOiBtYXJrZG93biBzdHJpbmcgdG8gcGFyc2VcbiAqICAtIG1kX3RyZWUgKE1hcmtkb3duLkpzb25NTCk6IHBhcnNlZCBtYXJrZG93biB0cmVlXG4gKlxuICogIFRha2UgbWFya2Rvd24gKGVpdGhlciBhcyBhIHN0cmluZyBvciBhcyBhIEpzb25NTCB0cmVlKSBhbmQgcnVuIGl0IHRocm91Z2hcbiAqICBbW3RvSFRNTFRyZWVdXSB0aGVuIHR1cm4gaXQgaW50byBhIHdlbGwtZm9ybWF0ZWQgSFRNTCBmcmFnbWVudC5cbiAqKi9cbmV4cG9zZS50b0hUTUwgPSBmdW5jdGlvbiB0b0hUTUwoIHNvdXJjZSAsIGRpYWxlY3QgLCBvcHRpb25zICkge1xuICB2YXIgaW5wdXQgPSBleHBvc2UudG9IVE1MVHJlZSggc291cmNlICwgZGlhbGVjdCAsIG9wdGlvbnMgKTtcblxuICByZXR1cm4gZXhwb3NlLnJlbmRlckpzb25NTCggaW5wdXQgKTtcbn07XG5cbi8qKlxuICogIHRvSFRNTFRyZWUoIG1hcmtkb3duLCBbZGlhbGVjdF0gKSAtPiBKc29uTUxcbiAqICB0b0hUTUxUcmVlKCBtZF90cmVlICkgLT4gSnNvbk1MXG4gKiAgLSBtYXJrZG93biAoU3RyaW5nKTogbWFya2Rvd24gc3RyaW5nIHRvIHBhcnNlXG4gKiAgLSBkaWFsZWN0IChTdHJpbmcgfCBEaWFsZWN0KTogdGhlIGRpYWxlY3QgdG8gdXNlLCBkZWZhdWx0cyB0byBncnViZXJcbiAqICAtIG1kX3RyZWUgKE1hcmtkb3duLkpzb25NTCk6IHBhcnNlZCBtYXJrZG93biB0cmVlXG4gKlxuICogIFR1cm4gbWFya2Rvd24gaW50byBIVE1MLCByZXByZXNlbnRlZCBhcyBhIEpzb25NTCB0cmVlLiBJZiBhIHN0cmluZyBpcyBnaXZlblxuICogIHRvIHRoaXMgZnVuY3Rpb24sIGl0IGlzIGZpcnN0IHBhcnNlZCBpbnRvIGEgbWFya2Rvd24gdHJlZSBieSBjYWxsaW5nXG4gKiAgW1twYXJzZV1dLlxuICoqL1xuZXhwb3NlLnRvSFRNTFRyZWUgPSBmdW5jdGlvbiB0b0hUTUxUcmVlKCBpbnB1dCwgZGlhbGVjdCAsIG9wdGlvbnMgKSB7XG4gIC8vIGNvbnZlcnQgc3RyaW5nIGlucHV0IHRvIGFuIE1EIHRyZWVcbiAgaWYgKCB0eXBlb2YgaW5wdXQgPT09XCJzdHJpbmdcIiApIGlucHV0ID0gdGhpcy5wYXJzZSggaW5wdXQsIGRpYWxlY3QgKTtcblxuICAvLyBOb3cgY29udmVydCB0aGUgTUQgdHJlZSB0byBhbiBIVE1MIHRyZWVcblxuICAvLyByZW1vdmUgcmVmZXJlbmNlcyBmcm9tIHRoZSB0cmVlXG4gIHZhciBhdHRycyA9IGV4dHJhY3RfYXR0ciggaW5wdXQgKSxcbiAgICAgIHJlZnMgPSB7fTtcblxuICBpZiAoIGF0dHJzICYmIGF0dHJzLnJlZmVyZW5jZXMgKSB7XG4gICAgcmVmcyA9IGF0dHJzLnJlZmVyZW5jZXM7XG4gIH1cblxuICB2YXIgaHRtbCA9IGNvbnZlcnRfdHJlZV90b19odG1sKCBpbnB1dCwgcmVmcyAsIG9wdGlvbnMgKTtcbiAgbWVyZ2VfdGV4dF9ub2RlcyggaHRtbCApO1xuICByZXR1cm4gaHRtbDtcbn07XG5cbi8vIEZvciBTcGlkZXJtb25rZXkgYmFzZWQgZW5naW5lc1xuZnVuY3Rpb24gbWtfYmxvY2tfdG9Tb3VyY2UoKSB7XG4gIHJldHVybiBcIk1hcmtkb3duLm1rX2Jsb2NrKCBcIiArXG4gICAgICAgICAgdW5ldmFsKHRoaXMudG9TdHJpbmcoKSkgK1xuICAgICAgICAgIFwiLCBcIiArXG4gICAgICAgICAgdW5ldmFsKHRoaXMudHJhaWxpbmcpICtcbiAgICAgICAgICBcIiwgXCIgK1xuICAgICAgICAgIHVuZXZhbCh0aGlzLmxpbmVOdW1iZXIpICtcbiAgICAgICAgICBcIiApXCI7XG59XG5cbi8vIG5vZGVcbmZ1bmN0aW9uIG1rX2Jsb2NrX2luc3BlY3QoKSB7XG4gIHZhciB1dGlsID0gcmVxdWlyZShcInV0aWxcIik7XG4gIHJldHVybiBcIk1hcmtkb3duLm1rX2Jsb2NrKCBcIiArXG4gICAgICAgICAgdXRpbC5pbnNwZWN0KHRoaXMudG9TdHJpbmcoKSkgK1xuICAgICAgICAgIFwiLCBcIiArXG4gICAgICAgICAgdXRpbC5pbnNwZWN0KHRoaXMudHJhaWxpbmcpICtcbiAgICAgICAgICBcIiwgXCIgK1xuICAgICAgICAgIHV0aWwuaW5zcGVjdCh0aGlzLmxpbmVOdW1iZXIpICtcbiAgICAgICAgICBcIiApXCI7XG5cbn1cblxudmFyIG1rX2Jsb2NrID0gTWFya2Rvd24ubWtfYmxvY2sgPSBmdW5jdGlvbihibG9jaywgdHJhaWwsIGxpbmUpIHtcbiAgLy8gQmUgaGVscGZ1bCBmb3IgZGVmYXVsdCBjYXNlIGluIHRlc3RzLlxuICBpZiAoIGFyZ3VtZW50cy5sZW5ndGggPT0gMSApIHRyYWlsID0gXCJcXG5cXG5cIjtcblxuICB2YXIgcyA9IG5ldyBTdHJpbmcoYmxvY2spO1xuICBzLnRyYWlsaW5nID0gdHJhaWw7XG4gIC8vIFRvIG1ha2UgaXQgY2xlYXIgaXRzIG5vdCBqdXN0IGEgc3RyaW5nXG4gIHMuaW5zcGVjdCA9IG1rX2Jsb2NrX2luc3BlY3Q7XG4gIHMudG9Tb3VyY2UgPSBta19ibG9ja190b1NvdXJjZTtcblxuICBpZiAoIGxpbmUgIT0gdW5kZWZpbmVkIClcbiAgICBzLmxpbmVOdW1iZXIgPSBsaW5lO1xuXG4gIHJldHVybiBzO1xufTtcblxuZnVuY3Rpb24gY291bnRfbGluZXMoIHN0ciApIHtcbiAgdmFyIG4gPSAwLCBpID0gLTE7XG4gIHdoaWxlICggKCBpID0gc3RyLmluZGV4T2YoXCJcXG5cIiwgaSArIDEpICkgIT09IC0xICkgbisrO1xuICByZXR1cm4gbjtcbn1cblxuLy8gSW50ZXJuYWwgLSBzcGxpdCBzb3VyY2UgaW50byByb3VnaCBibG9ja3Ncbk1hcmtkb3duLnByb3RvdHlwZS5zcGxpdF9ibG9ja3MgPSBmdW5jdGlvbiBzcGxpdEJsb2NrcyggaW5wdXQsIHN0YXJ0TGluZSApIHtcbiAgaW5wdXQgPSBpbnB1dC5yZXBsYWNlKC8oXFxyXFxufFxcbnxcXHIpL2csIFwiXFxuXCIpO1xuICAvLyBbXFxzXFxTXSBtYXRjaGVzIF9hbnl0aGluZ18gKG5ld2xpbmUgb3Igc3BhY2UpXG4gIC8vIFteXSBpcyBlcXVpdmFsZW50IGJ1dCBkb2Vzbid0IHdvcmsgaW4gSUVzLlxuICB2YXIgcmUgPSAvKFtcXHNcXFNdKz8pKCR8XFxuI3xcXG4oPzpcXHMqXFxufCQpKykvZyxcbiAgICAgIGJsb2NrcyA9IFtdLFxuICAgICAgbTtcblxuICB2YXIgbGluZV9ubyA9IDE7XG5cbiAgaWYgKCAoIG0gPSAvXihcXHMqXFxuKS8uZXhlYyhpbnB1dCkgKSAhPSBudWxsICkge1xuICAgIC8vIHNraXAgKGJ1dCBjb3VudCkgbGVhZGluZyBibGFuayBsaW5lc1xuICAgIGxpbmVfbm8gKz0gY291bnRfbGluZXMoIG1bMF0gKTtcbiAgICByZS5sYXN0SW5kZXggPSBtWzBdLmxlbmd0aDtcbiAgfVxuXG4gIHdoaWxlICggKCBtID0gcmUuZXhlYyhpbnB1dCkgKSAhPT0gbnVsbCApIHtcbiAgICBpZiAobVsyXSA9PSBcIlxcbiNcIikge1xuICAgICAgbVsyXSA9IFwiXFxuXCI7XG4gICAgICByZS5sYXN0SW5kZXgtLTtcbiAgICB9XG4gICAgYmxvY2tzLnB1c2goIG1rX2Jsb2NrKCBtWzFdLCBtWzJdLCBsaW5lX25vICkgKTtcbiAgICBsaW5lX25vICs9IGNvdW50X2xpbmVzKCBtWzBdICk7XG4gIH1cblxuICByZXR1cm4gYmxvY2tzO1xufTtcblxuLyoqXG4gKiAgTWFya2Rvd24jcHJvY2Vzc0Jsb2NrKCBibG9jaywgbmV4dCApIC0+IHVuZGVmaW5lZCB8IFsgSnNvbk1MLCAuLi4gXVxuICogIC0gYmxvY2sgKFN0cmluZyk6IHRoZSBibG9jayB0byBwcm9jZXNzXG4gKiAgLSBuZXh0IChBcnJheSk6IHRoZSBmb2xsb3dpbmcgYmxvY2tzXG4gKlxuICogUHJvY2VzcyBgYmxvY2tgIGFuZCByZXR1cm4gYW4gYXJyYXkgb2YgSnNvbk1MIG5vZGVzIHJlcHJlc2VudGluZyBgYmxvY2tgLlxuICpcbiAqIEl0IGRvZXMgdGhpcyBieSBhc2tpbmcgZWFjaCBibG9jayBsZXZlbCBmdW5jdGlvbiBpbiB0aGUgZGlhbGVjdCB0byBwcm9jZXNzXG4gKiB0aGUgYmxvY2sgdW50aWwgb25lIGNhbi4gU3VjY2VzZnVsIGhhbmRsaW5nIGlzIGluZGljYXRlZCBieSByZXR1cm5pbmcgYW5cbiAqIGFycmF5ICh3aXRoIHplcm8gb3IgbW9yZSBKc29uTUwgbm9kZXMpLCBmYWlsdXJlIGJ5IGEgZmFsc2UgdmFsdWUuXG4gKlxuICogQmxvY2tzIGhhbmRsZXJzIGFyZSByZXNwb25zaWJsZSBmb3IgY2FsbGluZyBbW01hcmtkb3duI3Byb2Nlc3NJbmxpbmVdXVxuICogdGhlbXNlbHZlcyBhcyBhcHByb3ByaWF0ZS5cbiAqXG4gKiBJZiB0aGUgYmxvY2tzIHdlcmUgc3BsaXQgaW5jb3JyZWN0bHkgb3IgYWRqYWNlbnQgYmxvY2tzIG5lZWQgY29sbGFwc2luZyB5b3VcbiAqIGNhbiBhZGp1c3QgYG5leHRgIGluIHBsYWNlIHVzaW5nIHNoaWZ0L3NwbGljZSBldGMuXG4gKlxuICogSWYgYW55IG9mIHRoaXMgZGVmYXVsdCBiZWhhdmlvdXIgaXMgbm90IHJpZ2h0IGZvciB0aGUgZGlhbGVjdCwgeW91IGNhblxuICogZGVmaW5lIGEgYF9fY2FsbF9fYCBtZXRob2Qgb24gdGhlIGRpYWxlY3QgdGhhdCB3aWxsIGdldCBpbnZva2VkIHRvIGhhbmRsZVxuICogdGhlIGJsb2NrIHByb2Nlc3NpbmcuXG4gKi9cbk1hcmtkb3duLnByb3RvdHlwZS5wcm9jZXNzQmxvY2sgPSBmdW5jdGlvbiBwcm9jZXNzQmxvY2soIGJsb2NrLCBuZXh0ICkge1xuICB2YXIgY2JzID0gdGhpcy5kaWFsZWN0LmJsb2NrLFxuICAgICAgb3JkID0gY2JzLl9fb3JkZXJfXztcblxuICBpZiAoIFwiX19jYWxsX19cIiBpbiBjYnMgKSB7XG4gICAgcmV0dXJuIGNicy5fX2NhbGxfXy5jYWxsKHRoaXMsIGJsb2NrLCBuZXh0KTtcbiAgfVxuXG4gIGZvciAoIHZhciBpID0gMDsgaSA8IG9yZC5sZW5ndGg7IGkrKyApIHtcbiAgICAvL0Q6dGhpcy5kZWJ1ZyggXCJUZXN0aW5nXCIsIG9yZFtpXSApO1xuICAgIHZhciByZXMgPSBjYnNbIG9yZFtpXSBdLmNhbGwoIHRoaXMsIGJsb2NrLCBuZXh0ICk7XG4gICAgaWYgKCByZXMgKSB7XG4gICAgICAvL0Q6dGhpcy5kZWJ1ZyhcIiAgbWF0Y2hlZFwiKTtcbiAgICAgIGlmICggIWlzQXJyYXkocmVzKSB8fCAoIHJlcy5sZW5ndGggPiAwICYmICEoIGlzQXJyYXkocmVzWzBdKSApICkgKVxuICAgICAgICB0aGlzLmRlYnVnKG9yZFtpXSwgXCJkaWRuJ3QgcmV0dXJuIGEgcHJvcGVyIGFycmF5XCIpO1xuICAgICAgLy9EOnRoaXMuZGVidWcoIFwiXCIgKTtcbiAgICAgIHJldHVybiByZXM7XG4gICAgfVxuICB9XG5cbiAgLy8gVWhvaCEgbm8gbWF0Y2ghIFNob3VsZCB3ZSB0aHJvdyBhbiBlcnJvcj9cbiAgcmV0dXJuIFtdO1xufTtcblxuTWFya2Rvd24ucHJvdG90eXBlLnByb2Nlc3NJbmxpbmUgPSBmdW5jdGlvbiBwcm9jZXNzSW5saW5lKCBibG9jayApIHtcbiAgcmV0dXJuIHRoaXMuZGlhbGVjdC5pbmxpbmUuX19jYWxsX18uY2FsbCggdGhpcywgU3RyaW5nKCBibG9jayApICk7XG59O1xuXG4vKipcbiAqICBNYXJrZG93biN0b1RyZWUoIHNvdXJjZSApIC0+IEpzb25NTFxuICogIC0gc291cmNlIChTdHJpbmcpOiBtYXJrZG93biBzb3VyY2UgdG8gcGFyc2VcbiAqXG4gKiAgUGFyc2UgYHNvdXJjZWAgaW50byBhIEpzb25NTCB0cmVlIHJlcHJlc2VudGluZyB0aGUgbWFya2Rvd24gZG9jdW1lbnQuXG4gKiovXG4vLyBjdXN0b21fdHJlZSBtZWFucyBzZXQgdGhpcy50cmVlIHRvIGBjdXN0b21fdHJlZWAgYW5kIHJlc3RvcmUgb2xkIHZhbHVlIG9uIHJldHVyblxuTWFya2Rvd24ucHJvdG90eXBlLnRvVHJlZSA9IGZ1bmN0aW9uIHRvVHJlZSggc291cmNlLCBjdXN0b21fcm9vdCApIHtcbiAgdmFyIGJsb2NrcyA9IHNvdXJjZSBpbnN0YW5jZW9mIEFycmF5ID8gc291cmNlIDogdGhpcy5zcGxpdF9ibG9ja3MoIHNvdXJjZSApO1xuXG4gIC8vIE1ha2UgdHJlZSBhIG1lbWJlciB2YXJpYWJsZSBzbyBpdHMgZWFzaWVyIHRvIG1lc3Mgd2l0aCBpbiBleHRlbnNpb25zXG4gIHZhciBvbGRfdHJlZSA9IHRoaXMudHJlZTtcbiAgdHJ5IHtcbiAgICB0aGlzLnRyZWUgPSBjdXN0b21fcm9vdCB8fCB0aGlzLnRyZWUgfHwgWyBcIm1hcmtkb3duXCIgXTtcblxuICAgIGJsb2NrczpcbiAgICB3aGlsZSAoIGJsb2Nrcy5sZW5ndGggKSB7XG4gICAgICB2YXIgYiA9IHRoaXMucHJvY2Vzc0Jsb2NrKCBibG9ja3Muc2hpZnQoKSwgYmxvY2tzICk7XG5cbiAgICAgIC8vIFJlZmVyZW5jZSBibG9ja3MgYW5kIHRoZSBsaWtlIHdvbid0IHJldHVybiBhbnkgY29udGVudFxuICAgICAgaWYgKCAhYi5sZW5ndGggKSBjb250aW51ZSBibG9ja3M7XG5cbiAgICAgIHRoaXMudHJlZS5wdXNoLmFwcGx5KCB0aGlzLnRyZWUsIGIgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudHJlZTtcbiAgfVxuICBmaW5hbGx5IHtcbiAgICBpZiAoIGN1c3RvbV9yb290ICkge1xuICAgICAgdGhpcy50cmVlID0gb2xkX3RyZWU7XG4gICAgfVxuICB9XG59O1xuXG4vLyBOb29wIGJ5IGRlZmF1bHRcbk1hcmtkb3duLnByb3RvdHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCggYXJndW1lbnRzKTtcbiAgYXJncy51bnNoaWZ0KHRoaXMuZGVidWdfaW5kZW50KTtcbiAgaWYgKCB0eXBlb2YgcHJpbnQgIT09IFwidW5kZWZpbmVkXCIgKVxuICAgICAgcHJpbnQuYXBwbHkoIHByaW50LCBhcmdzICk7XG4gIGlmICggdHlwZW9mIGNvbnNvbGUgIT09IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIGNvbnNvbGUubG9nICE9PSBcInVuZGVmaW5lZFwiIClcbiAgICAgIGNvbnNvbGUubG9nLmFwcGx5KCBudWxsLCBhcmdzICk7XG59XG5cbk1hcmtkb3duLnByb3RvdHlwZS5sb29wX3JlX292ZXJfYmxvY2sgPSBmdW5jdGlvbiggcmUsIGJsb2NrLCBjYiApIHtcbiAgLy8gRG9udCB1c2UgL2cgcmVnZXhwcyB3aXRoIHRoaXNcbiAgdmFyIG0sXG4gICAgICBiID0gYmxvY2sudmFsdWVPZigpO1xuXG4gIHdoaWxlICggYi5sZW5ndGggJiYgKG0gPSByZS5leGVjKGIpICkgIT0gbnVsbCApIHtcbiAgICBiID0gYi5zdWJzdHIoIG1bMF0ubGVuZ3RoICk7XG4gICAgY2IuY2FsbCh0aGlzLCBtKTtcbiAgfVxuICByZXR1cm4gYjtcbn07XG5cbi8qKlxuICogTWFya2Rvd24uZGlhbGVjdHNcbiAqXG4gKiBOYW1lc3BhY2Ugb2YgYnVpbHQtaW4gZGlhbGVjdHMuXG4gKiovXG5NYXJrZG93bi5kaWFsZWN0cyA9IHt9O1xuXG4vKipcbiAqIE1hcmtkb3duLmRpYWxlY3RzLkdydWJlclxuICpcbiAqIFRoZSBkZWZhdWx0IGRpYWxlY3QgdGhhdCBmb2xsb3dzIHRoZSBydWxlcyBzZXQgb3V0IGJ5IEpvaG4gR3J1YmVyJ3NcbiAqIG1hcmtkb3duLnBsIGFzIGNsb3NlbHkgYXMgcG9zc2libGUuIFdlbGwgYWN0dWFsbHkgd2UgZm9sbG93IHRoZSBiZWhhdmlvdXIgb2ZcbiAqIHRoYXQgc2NyaXB0IHdoaWNoIGluIHNvbWUgcGxhY2VzIGlzIG5vdCBleGFjdGx5IHdoYXQgdGhlIHN5bnRheCB3ZWIgcGFnZVxuICogc2F5cy5cbiAqKi9cbk1hcmtkb3duLmRpYWxlY3RzLkdydWJlciA9IHtcbiAgYmxvY2s6IHtcbiAgICBhdHhIZWFkZXI6IGZ1bmN0aW9uIGF0eEhlYWRlciggYmxvY2ssIG5leHQgKSB7XG4gICAgICB2YXIgbSA9IGJsb2NrLm1hdGNoKCAvXigjezEsNn0pXFxzKiguKj8pXFxzKiMqXFxzKig/OlxcbnwkKS8gKTtcblxuICAgICAgaWYgKCAhbSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIHZhciBoZWFkZXIgPSBbIFwiaGVhZGVyXCIsIHsgbGV2ZWw6IG1bIDEgXS5sZW5ndGggfSBdO1xuICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkoaGVhZGVyLCB0aGlzLnByb2Nlc3NJbmxpbmUobVsgMiBdKSk7XG5cbiAgICAgIGlmICggbVswXS5sZW5ndGggPCBibG9jay5sZW5ndGggKVxuICAgICAgICBuZXh0LnVuc2hpZnQoIG1rX2Jsb2NrKCBibG9jay5zdWJzdHIoIG1bMF0ubGVuZ3RoICksIGJsb2NrLnRyYWlsaW5nLCBibG9jay5saW5lTnVtYmVyICsgMiApICk7XG5cbiAgICAgIHJldHVybiBbIGhlYWRlciBdO1xuICAgIH0sXG5cbiAgICBzZXRleHRIZWFkZXI6IGZ1bmN0aW9uIHNldGV4dEhlYWRlciggYmxvY2ssIG5leHQgKSB7XG4gICAgICB2YXIgbSA9IGJsb2NrLm1hdGNoKCAvXiguKilcXG4oWy09XSlcXDJcXDIrKD86XFxufCQpLyApO1xuXG4gICAgICBpZiAoICFtICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgdmFyIGxldmVsID0gKCBtWyAyIF0gPT09IFwiPVwiICkgPyAxIDogMjtcbiAgICAgIHZhciBoZWFkZXIgPSBbIFwiaGVhZGVyXCIsIHsgbGV2ZWwgOiBsZXZlbCB9LCBtWyAxIF0gXTtcblxuICAgICAgaWYgKCBtWzBdLmxlbmd0aCA8IGJsb2NrLmxlbmd0aCApXG4gICAgICAgIG5leHQudW5zaGlmdCggbWtfYmxvY2soIGJsb2NrLnN1YnN0ciggbVswXS5sZW5ndGggKSwgYmxvY2sudHJhaWxpbmcsIGJsb2NrLmxpbmVOdW1iZXIgKyAyICkgKTtcblxuICAgICAgcmV0dXJuIFsgaGVhZGVyIF07XG4gICAgfSxcblxuICAgIGNvZGU6IGZ1bmN0aW9uIGNvZGUoIGJsb2NrLCBuZXh0ICkge1xuICAgICAgLy8gfCAgICBGb29cbiAgICAgIC8vIHxiYXJcbiAgICAgIC8vIHNob3VsZCBiZSBhIGNvZGUgYmxvY2sgZm9sbG93ZWQgYnkgYSBwYXJhZ3JhcGguIEZ1blxuICAgICAgLy9cbiAgICAgIC8vIFRoZXJlIG1pZ2h0IGFsc28gYmUgYWRqYWNlbnQgY29kZSBibG9jayB0byBtZXJnZS5cblxuICAgICAgdmFyIHJldCA9IFtdLFxuICAgICAgICAgIHJlID0gL14oPzogezAsM31cXHR8IHs0fSkoLiopXFxuPy8sXG4gICAgICAgICAgbGluZXM7XG5cbiAgICAgIC8vIDQgc3BhY2VzICsgY29udGVudFxuICAgICAgaWYgKCAhYmxvY2subWF0Y2goIHJlICkgKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICBibG9ja19zZWFyY2g6XG4gICAgICBkbyB7XG4gICAgICAgIC8vIE5vdyBwdWxsIG91dCB0aGUgcmVzdCBvZiB0aGUgbGluZXNcbiAgICAgICAgdmFyIGIgPSB0aGlzLmxvb3BfcmVfb3Zlcl9ibG9jayhcbiAgICAgICAgICAgICAgICAgIHJlLCBibG9jay52YWx1ZU9mKCksIGZ1bmN0aW9uKCBtICkgeyByZXQucHVzaCggbVsxXSApOyB9ICk7XG5cbiAgICAgICAgaWYgKCBiLmxlbmd0aCApIHtcbiAgICAgICAgICAvLyBDYXNlIGFsbHVkZWQgdG8gaW4gZmlyc3QgY29tbWVudC4gcHVzaCBpdCBiYWNrIG9uIGFzIGEgbmV3IGJsb2NrXG4gICAgICAgICAgbmV4dC51bnNoaWZ0KCBta19ibG9jayhiLCBibG9jay50cmFpbGluZykgKTtcbiAgICAgICAgICBicmVhayBibG9ja19zZWFyY2g7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIG5leHQubGVuZ3RoICkge1xuICAgICAgICAgIC8vIENoZWNrIHRoZSBuZXh0IGJsb2NrIC0gaXQgbWlnaHQgYmUgY29kZSB0b29cbiAgICAgICAgICBpZiAoICFuZXh0WzBdLm1hdGNoKCByZSApICkgYnJlYWsgYmxvY2tfc2VhcmNoO1xuXG4gICAgICAgICAgLy8gUHVsbCBob3cgaG93IG1hbnkgYmxhbmtzIGxpbmVzIGZvbGxvdyAtIG1pbnVzIHR3byB0byBhY2NvdW50IGZvciAuam9pblxuICAgICAgICAgIHJldC5wdXNoICggYmxvY2sudHJhaWxpbmcucmVwbGFjZSgvW15cXG5dL2csIFwiXCIpLnN1YnN0cmluZygyKSApO1xuXG4gICAgICAgICAgYmxvY2sgPSBuZXh0LnNoaWZ0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgYnJlYWsgYmxvY2tfc2VhcmNoO1xuICAgICAgICB9XG4gICAgICB9IHdoaWxlICggdHJ1ZSApO1xuXG4gICAgICByZXR1cm4gWyBbIFwiY29kZV9ibG9ja1wiLCByZXQuam9pbihcIlxcblwiKSBdIF07XG4gICAgfSxcblxuICAgIGhvcml6UnVsZTogZnVuY3Rpb24gaG9yaXpSdWxlKCBibG9jaywgbmV4dCApIHtcbiAgICAgIC8vIHRoaXMgbmVlZHMgdG8gZmluZCBhbnkgaHIgaW4gdGhlIGJsb2NrIHRvIGhhbmRsZSBhYnV0dGluZyBibG9ja3NcbiAgICAgIHZhciBtID0gYmxvY2subWF0Y2goIC9eKD86KFtcXHNcXFNdKj8pXFxuKT9bIFxcdF0qKFstXypdKSg/OlsgXFx0XSpcXDIpezIsfVsgXFx0XSooPzpcXG4oW1xcc1xcU10qKSk/JC8gKTtcblxuICAgICAgaWYgKCAhbSApIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgdmFyIGpzb25tbCA9IFsgWyBcImhyXCIgXSBdO1xuXG4gICAgICAvLyBpZiB0aGVyZSdzIGEgbGVhZGluZyBhYnV0dGluZyBibG9jaywgcHJvY2VzcyBpdFxuICAgICAgaWYgKCBtWyAxIF0gKSB7XG4gICAgICAgIGpzb25tbC51bnNoaWZ0LmFwcGx5KCBqc29ubWwsIHRoaXMucHJvY2Vzc0Jsb2NrKCBtWyAxIF0sIFtdICkgKTtcbiAgICAgIH1cblxuICAgICAgLy8gaWYgdGhlcmUncyBhIHRyYWlsaW5nIGFidXR0aW5nIGJsb2NrLCBzdGljayBpdCBpbnRvIG5leHRcbiAgICAgIGlmICggbVsgMyBdICkge1xuICAgICAgICBuZXh0LnVuc2hpZnQoIG1rX2Jsb2NrKCBtWyAzIF0gKSApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ganNvbm1sO1xuICAgIH0sXG5cbiAgICAvLyBUaGVyZSBhcmUgdHdvIHR5cGVzIG9mIGxpc3RzLiBUaWdodCBhbmQgbG9vc2UuIFRpZ2h0IGxpc3RzIGhhdmUgbm8gd2hpdGVzcGFjZVxuICAgIC8vIGJldHdlZW4gdGhlIGl0ZW1zIChhbmQgcmVzdWx0IGluIHRleHQganVzdCBpbiB0aGUgPGxpPikgYW5kIGxvb3NlIGxpc3RzLFxuICAgIC8vIHdoaWNoIGhhdmUgYW4gZW1wdHkgbGluZSBiZXR3ZWVuIGxpc3QgaXRlbXMsIHJlc3VsdGluZyBpbiAob25lIG9yIG1vcmUpXG4gICAgLy8gcGFyYWdyYXBocyBpbnNpZGUgdGhlIDxsaT4uXG4gICAgLy9cbiAgICAvLyBUaGVyZSBhcmUgYWxsIHNvcnRzIHdlaXJkIGVkZ2UgY2FzZXMgYWJvdXQgdGhlIG9yaWdpbmFsIG1hcmtkb3duLnBsJ3NcbiAgICAvLyBoYW5kbGluZyBvZiBsaXN0czpcbiAgICAvL1xuICAgIC8vICogTmVzdGVkIGxpc3RzIGFyZSBzdXBwb3NlZCB0byBiZSBpbmRlbnRlZCBieSBmb3VyIGNoYXJzIHBlciBsZXZlbC4gQnV0XG4gICAgLy8gICBpZiB0aGV5IGFyZW4ndCwgeW91IGNhbiBnZXQgYSBuZXN0ZWQgbGlzdCBieSBpbmRlbnRpbmcgYnkgbGVzcyB0aGFuXG4gICAgLy8gICBmb3VyIHNvIGxvbmcgYXMgdGhlIGluZGVudCBkb2Vzbid0IG1hdGNoIGFuIGluZGVudCBvZiBhbiBleGlzdGluZyBsaXN0XG4gICAgLy8gICBpdGVtIGluIHRoZSAnbmVzdCBzdGFjaycuXG4gICAgLy9cbiAgICAvLyAqIFRoZSB0eXBlIG9mIHRoZSBsaXN0IChidWxsZXQgb3IgbnVtYmVyKSBpcyBjb250cm9sbGVkIGp1c3QgYnkgdGhlXG4gICAgLy8gICAgZmlyc3QgaXRlbSBhdCB0aGUgaW5kZW50LiBTdWJzZXF1ZW50IGNoYW5nZXMgYXJlIGlnbm9yZWQgdW5sZXNzIHRoZXlcbiAgICAvLyAgICBhcmUgZm9yIG5lc3RlZCBsaXN0c1xuICAgIC8vXG4gICAgbGlzdHM6IChmdW5jdGlvbiggKSB7XG4gICAgICAvLyBVc2UgYSBjbG9zdXJlIHRvIGhpZGUgYSBmZXcgdmFyaWFibGVzLlxuICAgICAgdmFyIGFueV9saXN0ID0gXCJbKistXXxcXFxcZCtcXFxcLlwiLFxuICAgICAgICAgIGJ1bGxldF9saXN0ID0gL1sqKy1dLyxcbiAgICAgICAgICBudW1iZXJfbGlzdCA9IC9cXGQrXFwuLyxcbiAgICAgICAgICAvLyBDYXB0dXJlIGxlYWRpbmcgaW5kZW50IGFzIGl0IG1hdHRlcnMgZm9yIGRldGVybWluaW5nIG5lc3RlZCBsaXN0cy5cbiAgICAgICAgICBpc19saXN0X3JlID0gbmV3IFJlZ0V4cCggXCJeKCB7MCwzfSkoXCIgKyBhbnlfbGlzdCArIFwiKVsgXFx0XStcIiApLFxuICAgICAgICAgIGluZGVudF9yZSA9IFwiKD86IHswLDN9XFxcXHR8IHs0fSlcIjtcblxuICAgICAgLy8gVE9ETzogQ2FjaGUgdGhpcyByZWdleHAgZm9yIGNlcnRhaW4gZGVwdGhzLlxuICAgICAgLy8gQ3JlYXRlIGEgcmVnZXhwIHN1aXRhYmxlIGZvciBtYXRjaGluZyBhbiBsaSBmb3IgYSBnaXZlbiBzdGFjayBkZXB0aFxuICAgICAgZnVuY3Rpb24gcmVnZXhfZm9yX2RlcHRoKCBkZXB0aCApIHtcblxuICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cChcbiAgICAgICAgICAvLyBtWzFdID0gaW5kZW50LCBtWzJdID0gbGlzdF90eXBlXG4gICAgICAgICAgXCIoPzpeKFwiICsgaW5kZW50X3JlICsgXCJ7MCxcIiArIGRlcHRoICsgXCJ9IHswLDN9KShcIiArIGFueV9saXN0ICsgXCIpXFxcXHMrKXxcIiArXG4gICAgICAgICAgLy8gbVszXSA9IGNvbnRcbiAgICAgICAgICBcIiheXCIgKyBpbmRlbnRfcmUgKyBcInswLFwiICsgKGRlcHRoLTEpICsgXCJ9WyBdezAsNH0pXCJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGV4cGFuZF90YWIoIGlucHV0ICkge1xuICAgICAgICByZXR1cm4gaW5wdXQucmVwbGFjZSggLyB7MCwzfVxcdC9nLCBcIiAgICBcIiApO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgaW5saW5lIGNvbnRlbnQgYGlubGluZWAgdG8gYGxpYC4gaW5saW5lIGNvbWVzIGZyb20gcHJvY2Vzc0lubGluZVxuICAgICAgLy8gc28gaXMgYW4gYXJyYXkgb2YgY29udGVudFxuICAgICAgZnVuY3Rpb24gYWRkKGxpLCBsb29zZSwgaW5saW5lLCBubCkge1xuICAgICAgICBpZiAoIGxvb3NlICkge1xuICAgICAgICAgIGxpLnB1c2goIFsgXCJwYXJhXCIgXS5jb25jYXQoaW5saW5lKSApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBIbW1tLCBzaG91bGQgdGhpcyBiZSBhbnkgYmxvY2sgbGV2ZWwgZWxlbWVudCBvciBqdXN0IHBhcmFzP1xuICAgICAgICB2YXIgYWRkX3RvID0gbGlbbGkubGVuZ3RoIC0xXSBpbnN0YW5jZW9mIEFycmF5ICYmIGxpW2xpLmxlbmd0aCAtIDFdWzBdID09IFwicGFyYVwiXG4gICAgICAgICAgICAgICAgICAgPyBsaVtsaS5sZW5ndGggLTFdXG4gICAgICAgICAgICAgICAgICAgOiBsaTtcblxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBhbHJlYWR5IHNvbWUgY29udGVudCBpbiB0aGlzIGxpc3QsIGFkZCB0aGUgbmV3IGxpbmUgaW5cbiAgICAgICAgaWYgKCBubCAmJiBsaS5sZW5ndGggPiAxICkgaW5saW5lLnVuc2hpZnQobmwpO1xuXG4gICAgICAgIGZvciAoIHZhciBpID0gMDsgaSA8IGlubGluZS5sZW5ndGg7IGkrKyApIHtcbiAgICAgICAgICB2YXIgd2hhdCA9IGlubGluZVtpXSxcbiAgICAgICAgICAgICAgaXNfc3RyID0gdHlwZW9mIHdoYXQgPT0gXCJzdHJpbmdcIjtcbiAgICAgICAgICBpZiAoIGlzX3N0ciAmJiBhZGRfdG8ubGVuZ3RoID4gMSAmJiB0eXBlb2YgYWRkX3RvW2FkZF90by5sZW5ndGgtMV0gPT0gXCJzdHJpbmdcIiApIHtcbiAgICAgICAgICAgIGFkZF90b1sgYWRkX3RvLmxlbmd0aC0xIF0gKz0gd2hhdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBhZGRfdG8ucHVzaCggd2hhdCApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBjb250YWluZWQgbWVhbnMgaGF2ZSBhbiBpbmRlbnQgZ3JlYXRlciB0aGFuIHRoZSBjdXJyZW50IG9uZS4gT25cbiAgICAgIC8vICpldmVyeSogbGluZSBpbiB0aGUgYmxvY2tcbiAgICAgIGZ1bmN0aW9uIGdldF9jb250YWluZWRfYmxvY2tzKCBkZXB0aCwgYmxvY2tzICkge1xuXG4gICAgICAgIHZhciByZSA9IG5ldyBSZWdFeHAoIFwiXihcIiArIGluZGVudF9yZSArIFwie1wiICsgZGVwdGggKyBcIn0uKj9cXFxcbj8pKiRcIiApLFxuICAgICAgICAgICAgcmVwbGFjZSA9IG5ldyBSZWdFeHAoXCJeXCIgKyBpbmRlbnRfcmUgKyBcIntcIiArIGRlcHRoICsgXCJ9XCIsIFwiZ21cIiksXG4gICAgICAgICAgICByZXQgPSBbXTtcblxuICAgICAgICB3aGlsZSAoIGJsb2Nrcy5sZW5ndGggPiAwICkge1xuICAgICAgICAgIGlmICggcmUuZXhlYyggYmxvY2tzWzBdICkgKSB7XG4gICAgICAgICAgICB2YXIgYiA9IGJsb2Nrcy5zaGlmdCgpLFxuICAgICAgICAgICAgICAgIC8vIE5vdyByZW1vdmUgdGhhdCBpbmRlbnRcbiAgICAgICAgICAgICAgICB4ID0gYi5yZXBsYWNlKCByZXBsYWNlLCBcIlwiKTtcblxuICAgICAgICAgICAgcmV0LnB1c2goIG1rX2Jsb2NrKCB4LCBiLnRyYWlsaW5nLCBiLmxpbmVOdW1iZXIgKSApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfVxuXG4gICAgICAvLyBwYXNzZWQgdG8gc3RhY2suZm9yRWFjaCB0byB0dXJuIGxpc3QgaXRlbXMgdXAgdGhlIHN0YWNrIGludG8gcGFyYXNcbiAgICAgIGZ1bmN0aW9uIHBhcmFncmFwaGlmeShzLCBpLCBzdGFjaykge1xuICAgICAgICB2YXIgbGlzdCA9IHMubGlzdDtcbiAgICAgICAgdmFyIGxhc3RfbGkgPSBsaXN0W2xpc3QubGVuZ3RoLTFdO1xuXG4gICAgICAgIGlmICggbGFzdF9saVsxXSBpbnN0YW5jZW9mIEFycmF5ICYmIGxhc3RfbGlbMV1bMF0gPT0gXCJwYXJhXCIgKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICggaSArIDEgPT0gc3RhY2subGVuZ3RoICkge1xuICAgICAgICAgIC8vIExhc3Qgc3RhY2sgZnJhbWVcbiAgICAgICAgICAvLyBLZWVwIHRoZSBzYW1lIGFycmF5LCBidXQgcmVwbGFjZSB0aGUgY29udGVudHNcbiAgICAgICAgICBsYXN0X2xpLnB1c2goIFtcInBhcmFcIl0uY29uY2F0KCBsYXN0X2xpLnNwbGljZSgxLCBsYXN0X2xpLmxlbmd0aCAtIDEpICkgKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICB2YXIgc3VibGlzdCA9IGxhc3RfbGkucG9wKCk7XG4gICAgICAgICAgbGFzdF9saS5wdXNoKCBbXCJwYXJhXCJdLmNvbmNhdCggbGFzdF9saS5zcGxpY2UoMSwgbGFzdF9saS5sZW5ndGggLSAxKSApLCBzdWJsaXN0ICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVGhlIG1hdGNoZXIgZnVuY3Rpb25cbiAgICAgIHJldHVybiBmdW5jdGlvbiggYmxvY2ssIG5leHQgKSB7XG4gICAgICAgIHZhciBtID0gYmxvY2subWF0Y2goIGlzX2xpc3RfcmUgKTtcbiAgICAgICAgaWYgKCAhbSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgICAgZnVuY3Rpb24gbWFrZV9saXN0KCBtICkge1xuICAgICAgICAgIHZhciBsaXN0ID0gYnVsbGV0X2xpc3QuZXhlYyggbVsyXSApXG4gICAgICAgICAgICAgICAgICAgPyBbXCJidWxsZXRsaXN0XCJdXG4gICAgICAgICAgICAgICAgICAgOiBbXCJudW1iZXJsaXN0XCJdO1xuXG4gICAgICAgICAgc3RhY2sucHVzaCggeyBsaXN0OiBsaXN0LCBpbmRlbnQ6IG1bMV0gfSApO1xuICAgICAgICAgIHJldHVybiBsaXN0O1xuICAgICAgICB9XG5cblxuICAgICAgICB2YXIgc3RhY2sgPSBbXSwgLy8gU3RhY2sgb2YgbGlzdHMgZm9yIG5lc3RpbmcuXG4gICAgICAgICAgICBsaXN0ID0gbWFrZV9saXN0KCBtICksXG4gICAgICAgICAgICBsYXN0X2xpLFxuICAgICAgICAgICAgbG9vc2UgPSBmYWxzZSxcbiAgICAgICAgICAgIHJldCA9IFsgc3RhY2tbMF0ubGlzdCBdLFxuICAgICAgICAgICAgaTtcblxuICAgICAgICAvLyBMb29wIHRvIHNlYXJjaCBvdmVyIGJsb2NrIGxvb2tpbmcgZm9yIGlubmVyIGJsb2NrIGVsZW1lbnRzIGFuZCBsb29zZSBsaXN0c1xuICAgICAgICBsb29zZV9zZWFyY2g6XG4gICAgICAgIHdoaWxlICggdHJ1ZSApIHtcbiAgICAgICAgICAvLyBTcGxpdCBpbnRvIGxpbmVzIHByZXNlcnZpbmcgbmV3IGxpbmVzIGF0IGVuZCBvZiBsaW5lXG4gICAgICAgICAgdmFyIGxpbmVzID0gYmxvY2suc3BsaXQoIC8oPz1cXG4pLyApO1xuXG4gICAgICAgICAgLy8gV2UgaGF2ZSB0byBncmFiIGFsbCBsaW5lcyBmb3IgYSBsaSBhbmQgY2FsbCBwcm9jZXNzSW5saW5lIG9uIHRoZW1cbiAgICAgICAgICAvLyBvbmNlIGFzIHRoZXJlIGFyZSBzb21lIGlubGluZSB0aGluZ3MgdGhhdCBjYW4gc3BhbiBsaW5lcy5cbiAgICAgICAgICB2YXIgbGlfYWNjdW11bGF0ZSA9IFwiXCI7XG5cbiAgICAgICAgICAvLyBMb29wIG92ZXIgdGhlIGxpbmVzIGluIHRoaXMgYmxvY2sgbG9va2luZyBmb3IgdGlnaHQgbGlzdHMuXG4gICAgICAgICAgdGlnaHRfc2VhcmNoOlxuICAgICAgICAgIGZvciAoIHZhciBsaW5lX25vID0gMDsgbGluZV9ubyA8IGxpbmVzLmxlbmd0aDsgbGluZV9ubysrICkge1xuICAgICAgICAgICAgdmFyIG5sID0gXCJcIixcbiAgICAgICAgICAgICAgICBsID0gbGluZXNbbGluZV9ub10ucmVwbGFjZSgvXlxcbi8sIGZ1bmN0aW9uKG4pIHsgbmwgPSBuOyByZXR1cm4gXCJcIjsgfSk7XG5cbiAgICAgICAgICAgIC8vIFRPRE86IHJlYWxseSBzaG91bGQgY2FjaGUgdGhpc1xuICAgICAgICAgICAgdmFyIGxpbmVfcmUgPSByZWdleF9mb3JfZGVwdGgoIHN0YWNrLmxlbmd0aCApO1xuXG4gICAgICAgICAgICBtID0gbC5tYXRjaCggbGluZV9yZSApO1xuICAgICAgICAgICAgLy9wcmludCggXCJsaW5lOlwiLCB1bmV2YWwobCksIFwiXFxubGluZSBtYXRjaDpcIiwgdW5ldmFsKG0pICk7XG5cbiAgICAgICAgICAgIC8vIFdlIGhhdmUgYSBsaXN0IGl0ZW1cbiAgICAgICAgICAgIGlmICggbVsxXSAhPT0gdW5kZWZpbmVkICkge1xuICAgICAgICAgICAgICAvLyBQcm9jZXNzIHRoZSBwcmV2aW91cyBsaXN0IGl0ZW0sIGlmIGFueVxuICAgICAgICAgICAgICBpZiAoIGxpX2FjY3VtdWxhdGUubGVuZ3RoICkge1xuICAgICAgICAgICAgICAgIGFkZCggbGFzdF9saSwgbG9vc2UsIHRoaXMucHJvY2Vzc0lubGluZSggbGlfYWNjdW11bGF0ZSApLCBubCApO1xuICAgICAgICAgICAgICAgIC8vIExvb3NlIG1vZGUgd2lsbCBoYXZlIGJlZW4gZGVhbHQgd2l0aC4gUmVzZXQgaXRcbiAgICAgICAgICAgICAgICBsb29zZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGxpX2FjY3VtdWxhdGUgPSBcIlwiO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgbVsxXSA9IGV4cGFuZF90YWIoIG1bMV0gKTtcbiAgICAgICAgICAgICAgdmFyIHdhbnRlZF9kZXB0aCA9IE1hdGguZmxvb3IobVsxXS5sZW5ndGgvNCkrMTtcbiAgICAgICAgICAgICAgLy9wcmludCggXCJ3YW50OlwiLCB3YW50ZWRfZGVwdGgsIFwic3RhY2s6XCIsIHN0YWNrLmxlbmd0aCk7XG4gICAgICAgICAgICAgIGlmICggd2FudGVkX2RlcHRoID4gc3RhY2subGVuZ3RoICkge1xuICAgICAgICAgICAgICAgIC8vIERlZXAgZW5vdWdoIGZvciBhIG5lc3RlZCBsaXN0IG91dHJpZ2h0XG4gICAgICAgICAgICAgICAgLy9wcmludCAoIFwibmV3IG5lc3RlZCBsaXN0XCIgKTtcbiAgICAgICAgICAgICAgICBsaXN0ID0gbWFrZV9saXN0KCBtICk7XG4gICAgICAgICAgICAgICAgbGFzdF9saS5wdXNoKCBsaXN0ICk7XG4gICAgICAgICAgICAgICAgbGFzdF9saSA9IGxpc3RbMV0gPSBbIFwibGlzdGl0ZW1cIiBdO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFdlIGFyZW4ndCBkZWVwIGVub3VnaCB0byBiZSBzdHJpY3RseSBhIG5ldyBsZXZlbC4gVGhpcyBpc1xuICAgICAgICAgICAgICAgIC8vIHdoZXJlIE1kLnBsIGdvZXMgbnV0cy4gSWYgdGhlIGluZGVudCBtYXRjaGVzIGEgbGV2ZWwgaW4gdGhlXG4gICAgICAgICAgICAgICAgLy8gc3RhY2ssIHB1dCBpdCB0aGVyZSwgZWxzZSBwdXQgaXQgb25lIGRlZXBlciB0aGVuIHRoZVxuICAgICAgICAgICAgICAgIC8vIHdhbnRlZF9kZXB0aCBkZXNlcnZlcy5cbiAgICAgICAgICAgICAgICB2YXIgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBmb3IgKCBpID0gMDsgaSA8IHN0YWNrLmxlbmd0aDsgaSsrICkge1xuICAgICAgICAgICAgICAgICAgaWYgKCBzdGFja1sgaSBdLmluZGVudCAhPSBtWzFdICkgY29udGludWU7XG4gICAgICAgICAgICAgICAgICBsaXN0ID0gc3RhY2tbIGkgXS5saXN0O1xuICAgICAgICAgICAgICAgICAgc3RhY2suc3BsaWNlKCBpKzEsIHN0YWNrLmxlbmd0aCAtIChpKzEpICk7XG4gICAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgICAgICAgICAgICAvL3ByaW50KFwibm90IGZvdW5kLiBsOlwiLCB1bmV2YWwobCkpO1xuICAgICAgICAgICAgICAgICAgd2FudGVkX2RlcHRoKys7XG4gICAgICAgICAgICAgICAgICBpZiAoIHdhbnRlZF9kZXB0aCA8PSBzdGFjay5sZW5ndGggKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YWNrLnNwbGljZSh3YW50ZWRfZGVwdGgsIHN0YWNrLmxlbmd0aCAtIHdhbnRlZF9kZXB0aCk7XG4gICAgICAgICAgICAgICAgICAgIC8vcHJpbnQoXCJEZXNpcmVkIGRlcHRoIG5vd1wiLCB3YW50ZWRfZGVwdGgsIFwic3RhY2s6XCIsIHN0YWNrLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGxpc3QgPSBzdGFja1t3YW50ZWRfZGVwdGgtMV0ubGlzdDtcbiAgICAgICAgICAgICAgICAgICAgLy9wcmludChcImxpc3Q6XCIsIHVuZXZhbChsaXN0KSApO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vcHJpbnQgKFwibWFkZSBuZXcgc3RhY2sgZm9yIG1lc3N5IGluZGVudFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbGlzdCA9IG1ha2VfbGlzdChtKTtcbiAgICAgICAgICAgICAgICAgICAgbGFzdF9saS5wdXNoKGxpc3QpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vcHJpbnQoIHVuZXZhbChsaXN0KSwgXCJsYXN0XCIsIGxpc3QgPT09IHN0YWNrW3N0YWNrLmxlbmd0aC0xXS5saXN0ICk7XG4gICAgICAgICAgICAgICAgbGFzdF9saSA9IFsgXCJsaXN0aXRlbVwiIF07XG4gICAgICAgICAgICAgICAgbGlzdC5wdXNoKGxhc3RfbGkpO1xuICAgICAgICAgICAgICB9IC8vIGVuZCBkZXB0aCBvZiBzaGVuZWdhaW5zXG4gICAgICAgICAgICAgIG5sID0gXCJcIjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWRkIGNvbnRlbnRcbiAgICAgICAgICAgIGlmICggbC5sZW5ndGggPiBtWzBdLmxlbmd0aCApIHtcbiAgICAgICAgICAgICAgbGlfYWNjdW11bGF0ZSArPSBubCArIGwuc3Vic3RyKCBtWzBdLmxlbmd0aCApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gLy8gdGlnaHRfc2VhcmNoXG5cbiAgICAgICAgICBpZiAoIGxpX2FjY3VtdWxhdGUubGVuZ3RoICkge1xuICAgICAgICAgICAgYWRkKCBsYXN0X2xpLCBsb29zZSwgdGhpcy5wcm9jZXNzSW5saW5lKCBsaV9hY2N1bXVsYXRlICksIG5sICk7XG4gICAgICAgICAgICAvLyBMb29zZSBtb2RlIHdpbGwgaGF2ZSBiZWVuIGRlYWx0IHdpdGguIFJlc2V0IGl0XG4gICAgICAgICAgICBsb29zZSA9IGZhbHNlO1xuICAgICAgICAgICAgbGlfYWNjdW11bGF0ZSA9IFwiXCI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gTG9vayBhdCB0aGUgbmV4dCBibG9jayAtIHdlIG1pZ2h0IGhhdmUgYSBsb29zZSBsaXN0LiBPciBhbiBleHRyYVxuICAgICAgICAgIC8vIHBhcmFncmFwaCBmb3IgdGhlIGN1cnJlbnQgbGlcbiAgICAgICAgICB2YXIgY29udGFpbmVkID0gZ2V0X2NvbnRhaW5lZF9ibG9ja3MoIHN0YWNrLmxlbmd0aCwgbmV4dCApO1xuXG4gICAgICAgICAgLy8gRGVhbCB3aXRoIGNvZGUgYmxvY2tzIG9yIHByb3Blcmx5IG5lc3RlZCBsaXN0c1xuICAgICAgICAgIGlmICggY29udGFpbmVkLmxlbmd0aCA+IDAgKSB7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgYWxsIGxpc3RpdGVtcyB1cCB0aGUgc3RhY2sgYXJlIHBhcmFncmFwaHNcbiAgICAgICAgICAgIGZvckVhY2goIHN0YWNrLCBwYXJhZ3JhcGhpZnksIHRoaXMpO1xuXG4gICAgICAgICAgICBsYXN0X2xpLnB1c2guYXBwbHkoIGxhc3RfbGksIHRoaXMudG9UcmVlKCBjb250YWluZWQsIFtdICkgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgbmV4dF9ibG9jayA9IG5leHRbMF0gJiYgbmV4dFswXS52YWx1ZU9mKCkgfHwgXCJcIjtcblxuICAgICAgICAgIGlmICggbmV4dF9ibG9jay5tYXRjaChpc19saXN0X3JlKSB8fCBuZXh0X2Jsb2NrLm1hdGNoKCAvXiAvICkgKSB7XG4gICAgICAgICAgICBibG9jayA9IG5leHQuc2hpZnQoKTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgZm9yIGFuIEhSIGZvbGxvd2luZyBhIGxpc3Q6IGZlYXR1cmVzL2xpc3RzL2hyX2FidXR0aW5nXG4gICAgICAgICAgICB2YXIgaHIgPSB0aGlzLmRpYWxlY3QuYmxvY2suaG9yaXpSdWxlKCBibG9jaywgbmV4dCApO1xuXG4gICAgICAgICAgICBpZiAoIGhyICkge1xuICAgICAgICAgICAgICByZXQucHVzaC5hcHBseShyZXQsIGhyKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBhbGwgbGlzdGl0ZW1zIHVwIHRoZSBzdGFjayBhcmUgcGFyYWdyYXBoc1xuICAgICAgICAgICAgZm9yRWFjaCggc3RhY2ssIHBhcmFncmFwaGlmeSwgdGhpcyk7XG5cbiAgICAgICAgICAgIGxvb3NlID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnRpbnVlIGxvb3NlX3NlYXJjaDtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH0gLy8gbG9vc2Vfc2VhcmNoXG5cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH07XG4gICAgfSkoKSxcblxuICAgIGJsb2NrcXVvdGU6IGZ1bmN0aW9uIGJsb2NrcXVvdGUoIGJsb2NrLCBuZXh0ICkge1xuICAgICAgaWYgKCAhYmxvY2subWF0Y2goIC9ePi9tICkgKVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICB2YXIganNvbm1sID0gW107XG5cbiAgICAgIC8vIHNlcGFyYXRlIG91dCB0aGUgbGVhZGluZyBhYnV0dGluZyBibG9jaywgaWYgYW55LiBJLmUuIGluIHRoaXMgY2FzZTpcbiAgICAgIC8vXG4gICAgICAvLyAgYVxuICAgICAgLy8gID4gYlxuICAgICAgLy9cbiAgICAgIGlmICggYmxvY2tbIDAgXSAhPSBcIj5cIiApIHtcbiAgICAgICAgdmFyIGxpbmVzID0gYmxvY2suc3BsaXQoIC9cXG4vICksXG4gICAgICAgICAgICBwcmV2ID0gW10sXG4gICAgICAgICAgICBsaW5lX25vID0gYmxvY2subGluZU51bWJlcjtcblxuICAgICAgICAvLyBrZWVwIHNoaWZ0aW5nIGxpbmVzIHVudGlsIHlvdSBmaW5kIGEgY3JvdGNoZXRcbiAgICAgICAgd2hpbGUgKCBsaW5lcy5sZW5ndGggJiYgbGluZXNbIDAgXVsgMCBdICE9IFwiPlwiICkge1xuICAgICAgICAgICAgcHJldi5wdXNoKCBsaW5lcy5zaGlmdCgpICk7XG4gICAgICAgICAgICBsaW5lX25vKys7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYWJ1dHRpbmcgPSBta19ibG9jayggcHJldi5qb2luKCBcIlxcblwiICksIFwiXFxuXCIsIGJsb2NrLmxpbmVOdW1iZXIgKTtcbiAgICAgICAganNvbm1sLnB1c2guYXBwbHkoIGpzb25tbCwgdGhpcy5wcm9jZXNzQmxvY2soIGFidXR0aW5nLCBbXSApICk7XG4gICAgICAgIC8vIHJlYXNzZW1ibGUgbmV3IGJsb2NrIG9mIGp1c3QgYmxvY2sgcXVvdGVzIVxuICAgICAgICBibG9jayA9IG1rX2Jsb2NrKCBsaW5lcy5qb2luKCBcIlxcblwiICksIGJsb2NrLnRyYWlsaW5nLCBsaW5lX25vICk7XG4gICAgICB9XG5cblxuICAgICAgLy8gaWYgdGhlIG5leHQgYmxvY2sgaXMgYWxzbyBhIGJsb2NrcXVvdGUgbWVyZ2UgaXQgaW5cbiAgICAgIHdoaWxlICggbmV4dC5sZW5ndGggJiYgbmV4dFsgMCBdWyAwIF0gPT0gXCI+XCIgKSB7XG4gICAgICAgIHZhciBiID0gbmV4dC5zaGlmdCgpO1xuICAgICAgICBibG9jayA9IG1rX2Jsb2NrKCBibG9jayArIGJsb2NrLnRyYWlsaW5nICsgYiwgYi50cmFpbGluZywgYmxvY2subGluZU51bWJlciApO1xuICAgICAgfVxuXG4gICAgICAvLyBTdHJpcCBvZmYgdGhlIGxlYWRpbmcgXCI+IFwiIGFuZCByZS1wcm9jZXNzIGFzIGEgYmxvY2suXG4gICAgICB2YXIgaW5wdXQgPSBibG9jay5yZXBsYWNlKCAvXj4gPy9nbSwgXCJcIiApLFxuICAgICAgICAgIG9sZF90cmVlID0gdGhpcy50cmVlLFxuICAgICAgICAgIHByb2Nlc3NlZEJsb2NrID0gdGhpcy50b1RyZWUoIGlucHV0LCBbIFwiYmxvY2txdW90ZVwiIF0gKSxcbiAgICAgICAgICBhdHRyID0gZXh0cmFjdF9hdHRyKCBwcm9jZXNzZWRCbG9jayApO1xuXG4gICAgICAvLyBJZiBhbnkgbGluayByZWZlcmVuY2VzIHdlcmUgZm91bmQgZ2V0IHJpZCBvZiB0aGVtXG4gICAgICBpZiAoIGF0dHIgJiYgYXR0ci5yZWZlcmVuY2VzICkge1xuICAgICAgICBkZWxldGUgYXR0ci5yZWZlcmVuY2VzO1xuICAgICAgICAvLyBBbmQgdGhlbiByZW1vdmUgdGhlIGF0dHJpYnV0ZSBvYmplY3QgaWYgaXQncyBlbXB0eVxuICAgICAgICBpZiAoIGlzRW1wdHkoIGF0dHIgKSApIHtcbiAgICAgICAgICBwcm9jZXNzZWRCbG9jay5zcGxpY2UoIDEsIDEgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBqc29ubWwucHVzaCggcHJvY2Vzc2VkQmxvY2sgKTtcbiAgICAgIHJldHVybiBqc29ubWw7XG4gICAgfSxcblxuICAgIHJlZmVyZW5jZURlZm46IGZ1bmN0aW9uIHJlZmVyZW5jZURlZm4oIGJsb2NrLCBuZXh0KSB7XG4gICAgICB2YXIgcmUgPSAvXlxccypcXFsoLio/KVxcXTpcXHMqKFxcUyspKD86XFxzKyg/OihbJ1wiXSkoLio/KVxcM3xcXCgoLio/KVxcKSkpP1xcbj8vO1xuICAgICAgLy8gaW50ZXJlc3RpbmcgbWF0Y2hlcyBhcmUgWyAsIHJlZl9pZCwgdXJsLCAsIHRpdGxlLCB0aXRsZSBdXG5cbiAgICAgIGlmICggIWJsb2NrLm1hdGNoKHJlKSApXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIC8vIG1ha2UgYW4gYXR0cmlidXRlIG5vZGUgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgICAgaWYgKCAhZXh0cmFjdF9hdHRyKCB0aGlzLnRyZWUgKSApIHtcbiAgICAgICAgdGhpcy50cmVlLnNwbGljZSggMSwgMCwge30gKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGF0dHJzID0gZXh0cmFjdF9hdHRyKCB0aGlzLnRyZWUgKTtcblxuICAgICAgLy8gbWFrZSBhIHJlZmVyZW5jZXMgaGFzaCBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICBpZiAoIGF0dHJzLnJlZmVyZW5jZXMgPT09IHVuZGVmaW5lZCApIHtcbiAgICAgICAgYXR0cnMucmVmZXJlbmNlcyA9IHt9O1xuICAgICAgfVxuXG4gICAgICB2YXIgYiA9IHRoaXMubG9vcF9yZV9vdmVyX2Jsb2NrKHJlLCBibG9jaywgZnVuY3Rpb24oIG0gKSB7XG5cbiAgICAgICAgaWYgKCBtWzJdICYmIG1bMl1bMF0gPT0gXCI8XCIgJiYgbVsyXVttWzJdLmxlbmd0aC0xXSA9PSBcIj5cIiApXG4gICAgICAgICAgbVsyXSA9IG1bMl0uc3Vic3RyaW5nKCAxLCBtWzJdLmxlbmd0aCAtIDEgKTtcblxuICAgICAgICB2YXIgcmVmID0gYXR0cnMucmVmZXJlbmNlc1sgbVsxXS50b0xvd2VyQ2FzZSgpIF0gPSB7XG4gICAgICAgICAgaHJlZjogbVsyXVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICggbVs0XSAhPT0gdW5kZWZpbmVkIClcbiAgICAgICAgICByZWYudGl0bGUgPSBtWzRdO1xuICAgICAgICBlbHNlIGlmICggbVs1XSAhPT0gdW5kZWZpbmVkIClcbiAgICAgICAgICByZWYudGl0bGUgPSBtWzVdO1xuXG4gICAgICB9ICk7XG5cbiAgICAgIGlmICggYi5sZW5ndGggKVxuICAgICAgICBuZXh0LnVuc2hpZnQoIG1rX2Jsb2NrKCBiLCBibG9jay50cmFpbGluZyApICk7XG5cbiAgICAgIHJldHVybiBbXTtcbiAgICB9LFxuXG4gICAgcGFyYTogZnVuY3Rpb24gcGFyYSggYmxvY2ssIG5leHQgKSB7XG4gICAgICAvLyBldmVyeXRoaW5nJ3MgYSBwYXJhIVxuICAgICAgcmV0dXJuIFsgW1wicGFyYVwiXS5jb25jYXQoIHRoaXMucHJvY2Vzc0lubGluZSggYmxvY2sgKSApIF07XG4gICAgfVxuICB9XG59O1xuXG5NYXJrZG93bi5kaWFsZWN0cy5HcnViZXIuaW5saW5lID0ge1xuXG4gICAgX19vbmVFbGVtZW50X186IGZ1bmN0aW9uIG9uZUVsZW1lbnQoIHRleHQsIHBhdHRlcm5zX29yX3JlLCBwcmV2aW91c19ub2RlcyApIHtcbiAgICAgIHZhciBtLFxuICAgICAgICAgIHJlcyxcbiAgICAgICAgICBsYXN0SW5kZXggPSAwO1xuXG4gICAgICBwYXR0ZXJuc19vcl9yZSA9IHBhdHRlcm5zX29yX3JlIHx8IHRoaXMuZGlhbGVjdC5pbmxpbmUuX19wYXR0ZXJuc19fO1xuICAgICAgdmFyIHJlID0gbmV3IFJlZ0V4cCggXCIoW1xcXFxzXFxcXFNdKj8pKFwiICsgKHBhdHRlcm5zX29yX3JlLnNvdXJjZSB8fCBwYXR0ZXJuc19vcl9yZSkgKyBcIilcIiApO1xuXG4gICAgICBtID0gcmUuZXhlYyggdGV4dCApO1xuICAgICAgaWYgKCFtKSB7XG4gICAgICAgIC8vIEp1c3QgYm9yaW5nIHRleHRcbiAgICAgICAgcmV0dXJuIFsgdGV4dC5sZW5ndGgsIHRleHQgXTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKCBtWzFdICkge1xuICAgICAgICAvLyBTb21lIHVuLWludGVyZXN0aW5nIHRleHQgbWF0Y2hlZC4gUmV0dXJuIHRoYXQgZmlyc3RcbiAgICAgICAgcmV0dXJuIFsgbVsxXS5sZW5ndGgsIG1bMV0gXTtcbiAgICAgIH1cblxuICAgICAgdmFyIHJlcztcbiAgICAgIGlmICggbVsyXSBpbiB0aGlzLmRpYWxlY3QuaW5saW5lICkge1xuICAgICAgICByZXMgPSB0aGlzLmRpYWxlY3QuaW5saW5lWyBtWzJdIF0uY2FsbChcbiAgICAgICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICAgICAgICB0ZXh0LnN1YnN0ciggbS5pbmRleCApLCBtLCBwcmV2aW91c19ub2RlcyB8fCBbXSApO1xuICAgICAgfVxuICAgICAgLy8gRGVmYXVsdCBmb3Igbm93IHRvIG1ha2UgZGV2IGVhc2llci4ganVzdCBzbHVycCBzcGVjaWFsIGFuZCBvdXRwdXQgaXQuXG4gICAgICByZXMgPSByZXMgfHwgWyBtWzJdLmxlbmd0aCwgbVsyXSBdO1xuICAgICAgcmV0dXJuIHJlcztcbiAgICB9LFxuXG4gICAgX19jYWxsX186IGZ1bmN0aW9uIGlubGluZSggdGV4dCwgcGF0dGVybnMgKSB7XG5cbiAgICAgIHZhciBvdXQgPSBbXSxcbiAgICAgICAgICByZXM7XG5cbiAgICAgIGZ1bmN0aW9uIGFkZCh4KSB7XG4gICAgICAgIC8vRDpzZWxmLmRlYnVnKFwiICBhZGRpbmcgb3V0cHV0XCIsIHVuZXZhbCh4KSk7XG4gICAgICAgIGlmICggdHlwZW9mIHggPT0gXCJzdHJpbmdcIiAmJiB0eXBlb2Ygb3V0W291dC5sZW5ndGgtMV0gPT0gXCJzdHJpbmdcIiApXG4gICAgICAgICAgb3V0WyBvdXQubGVuZ3RoLTEgXSArPSB4O1xuICAgICAgICBlbHNlXG4gICAgICAgICAgb3V0LnB1c2goeCk7XG4gICAgICB9XG5cbiAgICAgIHdoaWxlICggdGV4dC5sZW5ndGggPiAwICkge1xuICAgICAgICByZXMgPSB0aGlzLmRpYWxlY3QuaW5saW5lLl9fb25lRWxlbWVudF9fLmNhbGwodGhpcywgdGV4dCwgcGF0dGVybnMsIG91dCApO1xuICAgICAgICB0ZXh0ID0gdGV4dC5zdWJzdHIoIHJlcy5zaGlmdCgpICk7XG4gICAgICAgIGZvckVhY2gocmVzLCBhZGQgKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gb3V0O1xuICAgIH0sXG5cbiAgICAvLyBUaGVzZSBjaGFyYWN0ZXJzIGFyZSBpbnRlcnN0aW5nIGVsc2V3aGVyZSwgc28gaGF2ZSBydWxlcyBmb3IgdGhlbSBzbyB0aGF0XG4gICAgLy8gY2h1bmtzIG9mIHBsYWluIHRleHQgYmxvY2tzIGRvbid0IGluY2x1ZGUgdGhlbVxuICAgIFwiXVwiOiBmdW5jdGlvbiAoKSB7fSxcbiAgICBcIn1cIjogZnVuY3Rpb24gKCkge30sXG5cbiAgICBfX2VzY2FwZV9fIDogL15cXFxcW1xcXFxgXFwqX3t9XFxbXFxdKCkjXFwrLiFcXC1dLyxcblxuICAgIFwiXFxcXFwiOiBmdW5jdGlvbiBlc2NhcGVkKCB0ZXh0ICkge1xuICAgICAgLy8gWyBsZW5ndGggb2YgaW5wdXQgcHJvY2Vzc2VkLCBub2RlL2NoaWxkcmVuIHRvIGFkZC4uLiBdXG4gICAgICAvLyBPbmx5IGVzYWNhcGU6IFxcIGAgKiBfIHsgfSBbIF0gKCApICMgKiArIC0gLiAhXG4gICAgICBpZiAoIHRoaXMuZGlhbGVjdC5pbmxpbmUuX19lc2NhcGVfXy5leGVjKCB0ZXh0ICkgKVxuICAgICAgICByZXR1cm4gWyAyLCB0ZXh0LmNoYXJBdCggMSApIF07XG4gICAgICBlbHNlXG4gICAgICAgIC8vIE5vdCBhbiBlc2FjcGVcbiAgICAgICAgcmV0dXJuIFsgMSwgXCJcXFxcXCIgXTtcbiAgICB9LFxuXG4gICAgXCIhW1wiOiBmdW5jdGlvbiBpbWFnZSggdGV4dCApIHtcblxuICAgICAgLy8gVW5saWtlIGltYWdlcywgYWx0IHRleHQgaXMgcGxhaW4gdGV4dCBvbmx5LiBubyBvdGhlciBlbGVtZW50cyBhcmVcbiAgICAgIC8vIGFsbG93ZWQgaW4gdGhlcmVcblxuICAgICAgLy8gIVtBbHQgdGV4dF0oL3BhdGgvdG8vaW1nLmpwZyBcIk9wdGlvbmFsIHRpdGxlXCIpXG4gICAgICAvLyAgICAgIDEgICAgICAgICAgMiAgICAgICAgICAgIDMgICAgICAgNCAgICAgICAgIDwtLS0gY2FwdHVyZXNcbiAgICAgIHZhciBtID0gdGV4dC5tYXRjaCggL14hXFxbKC4qPylcXF1bIFxcdF0qXFwoWyBcXHRdKihbXlwiKV0qPykoPzpbIFxcdF0rKFtcIiddKSguKj8pXFwzKT9bIFxcdF0qXFwpLyApO1xuXG4gICAgICBpZiAoIG0gKSB7XG4gICAgICAgIGlmICggbVsyXSAmJiBtWzJdWzBdID09IFwiPFwiICYmIG1bMl1bbVsyXS5sZW5ndGgtMV0gPT0gXCI+XCIgKVxuICAgICAgICAgIG1bMl0gPSBtWzJdLnN1YnN0cmluZyggMSwgbVsyXS5sZW5ndGggLSAxICk7XG5cbiAgICAgICAgbVsyXSA9IHRoaXMuZGlhbGVjdC5pbmxpbmUuX19jYWxsX18uY2FsbCggdGhpcywgbVsyXSwgL1xcXFwvIClbMF07XG5cbiAgICAgICAgdmFyIGF0dHJzID0geyBhbHQ6IG1bMV0sIGhyZWY6IG1bMl0gfHwgXCJcIiB9O1xuICAgICAgICBpZiAoIG1bNF0gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICBhdHRycy50aXRsZSA9IG1bNF07XG5cbiAgICAgICAgcmV0dXJuIFsgbVswXS5sZW5ndGgsIFsgXCJpbWdcIiwgYXR0cnMgXSBdO1xuICAgICAgfVxuXG4gICAgICAvLyAhW0FsdCB0ZXh0XVtpZF1cbiAgICAgIG0gPSB0ZXh0Lm1hdGNoKCAvXiFcXFsoLio/KVxcXVsgXFx0XSpcXFsoLio/KVxcXS8gKTtcblxuICAgICAgaWYgKCBtICkge1xuICAgICAgICAvLyBXZSBjYW4ndCBjaGVjayBpZiB0aGUgcmVmZXJlbmNlIGlzIGtub3duIGhlcmUgYXMgaXQgbGlrZWx5IHdvbnQgYmVcbiAgICAgICAgLy8gZm91bmQgdGlsbCBhZnRlci4gQ2hlY2sgaXQgaW4gbWQgdHJlZS0+aG10bCB0cmVlIGNvbnZlcnNpb25cbiAgICAgICAgcmV0dXJuIFsgbVswXS5sZW5ndGgsIFsgXCJpbWdfcmVmXCIsIHsgYWx0OiBtWzFdLCByZWY6IG1bMl0udG9Mb3dlckNhc2UoKSwgb3JpZ2luYWw6IG1bMF0gfSBdIF07XG4gICAgICB9XG5cbiAgICAgIC8vIEp1c3QgY29uc3VtZSB0aGUgJyFbJ1xuICAgICAgcmV0dXJuIFsgMiwgXCIhW1wiIF07XG4gICAgfSxcblxuICAgIFwiW1wiOiBmdW5jdGlvbiBsaW5rKCB0ZXh0ICkge1xuXG4gICAgICB2YXIgb3JpZyA9IFN0cmluZyh0ZXh0KTtcbiAgICAgIC8vIElubGluZSBjb250ZW50IGlzIHBvc3NpYmxlIGluc2lkZSBgbGluayB0ZXh0YFxuICAgICAgdmFyIHJlcyA9IE1hcmtkb3duLkRpYWxlY3RIZWxwZXJzLmlubGluZV91bnRpbF9jaGFyLmNhbGwoIHRoaXMsIHRleHQuc3Vic3RyKDEpLCBcIl1cIiApO1xuXG4gICAgICAvLyBObyBjbG9zaW5nICddJyBmb3VuZC4gSnVzdCBjb25zdW1lIHRoZSBbXG4gICAgICBpZiAoICFyZXMgKSByZXR1cm4gWyAxLCBcIltcIiBdO1xuXG4gICAgICB2YXIgY29uc3VtZWQgPSAxICsgcmVzWyAwIF0sXG4gICAgICAgICAgY2hpbGRyZW4gPSByZXNbIDEgXSxcbiAgICAgICAgICBsaW5rLFxuICAgICAgICAgIGF0dHJzO1xuXG4gICAgICAvLyBBdCB0aGlzIHBvaW50IHRoZSBmaXJzdCBbLi4uXSBoYXMgYmVlbiBwYXJzZWQuIFNlZSB3aGF0IGZvbGxvd3MgdG8gZmluZFxuICAgICAgLy8gb3V0IHdoaWNoIGtpbmQgb2YgbGluayB3ZSBhcmUgKHJlZmVyZW5jZSBvciBkaXJlY3QgdXJsKVxuICAgICAgdGV4dCA9IHRleHQuc3Vic3RyKCBjb25zdW1lZCApO1xuXG4gICAgICAvLyBbbGluayB0ZXh0XSgvcGF0aC90by9pbWcuanBnIFwiT3B0aW9uYWwgdGl0bGVcIilcbiAgICAgIC8vICAgICAgICAgICAgICAgICAxICAgICAgICAgICAgMiAgICAgICAzICAgICAgICAgPC0tLSBjYXB0dXJlc1xuICAgICAgLy8gVGhpcyB3aWxsIGNhcHR1cmUgdXAgdG8gdGhlIGxhc3QgcGFyZW4gaW4gdGhlIGJsb2NrLiBXZSB0aGVuIHB1bGxcbiAgICAgIC8vIGJhY2sgYmFzZWQgb24gaWYgdGhlcmUgYSBtYXRjaGluZyBvbmVzIGluIHRoZSB1cmxcbiAgICAgIC8vICAgIChbaGVyZV0oL3VybC8odGVzdCkpXG4gICAgICAvLyBUaGUgcGFyZW5zIGhhdmUgdG8gYmUgYmFsYW5jZWRcbiAgICAgIHZhciBtID0gdGV4dC5tYXRjaCggL15cXHMqXFwoWyBcXHRdKihbXlwiJ10qKSg/OlsgXFx0XSsoW1wiJ10pKC4qPylcXDIpP1sgXFx0XSpcXCkvICk7XG4gICAgICBpZiAoIG0gKSB7XG4gICAgICAgIHZhciB1cmwgPSBtWzFdO1xuICAgICAgICBjb25zdW1lZCArPSBtWzBdLmxlbmd0aDtcblxuICAgICAgICBpZiAoIHVybCAmJiB1cmxbMF0gPT0gXCI8XCIgJiYgdXJsW3VybC5sZW5ndGgtMV0gPT0gXCI+XCIgKVxuICAgICAgICAgIHVybCA9IHVybC5zdWJzdHJpbmcoIDEsIHVybC5sZW5ndGggLSAxICk7XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgYSB0aXRsZSB3ZSBkb24ndCBoYXZlIHRvIHdvcnJ5IGFib3V0IHBhcmVucyBpbiB0aGUgdXJsXG4gICAgICAgIGlmICggIW1bM10gKSB7XG4gICAgICAgICAgdmFyIG9wZW5fcGFyZW5zID0gMTsgLy8gT25lIG9wZW4gdGhhdCBpc24ndCBpbiB0aGUgY2FwdHVyZVxuICAgICAgICAgIGZvciAoIHZhciBsZW4gPSAwOyBsZW4gPCB1cmwubGVuZ3RoOyBsZW4rKyApIHtcbiAgICAgICAgICAgIHN3aXRjaCAoIHVybFtsZW5dICkge1xuICAgICAgICAgICAgY2FzZSBcIihcIjpcbiAgICAgICAgICAgICAgb3Blbl9wYXJlbnMrKztcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiKVwiOlxuICAgICAgICAgICAgICBpZiAoIC0tb3Blbl9wYXJlbnMgPT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN1bWVkIC09IHVybC5sZW5ndGggLSBsZW47XG4gICAgICAgICAgICAgICAgdXJsID0gdXJsLnN1YnN0cmluZygwLCBsZW4pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByb2Nlc3MgZXNjYXBlcyBvbmx5XG4gICAgICAgIHVybCA9IHRoaXMuZGlhbGVjdC5pbmxpbmUuX19jYWxsX18uY2FsbCggdGhpcywgdXJsLCAvXFxcXC8gKVswXTtcblxuICAgICAgICBhdHRycyA9IHsgaHJlZjogdXJsIHx8IFwiXCIgfTtcbiAgICAgICAgaWYgKCBtWzNdICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgYXR0cnMudGl0bGUgPSBtWzNdO1xuXG4gICAgICAgIGxpbmsgPSBbIFwibGlua1wiLCBhdHRycyBdLmNvbmNhdCggY2hpbGRyZW4gKTtcbiAgICAgICAgcmV0dXJuIFsgY29uc3VtZWQsIGxpbmsgXTtcbiAgICAgIH1cblxuICAgICAgLy8gW0FsdCB0ZXh0XVtpZF1cbiAgICAgIC8vIFtBbHQgdGV4dF0gW2lkXVxuICAgICAgbSA9IHRleHQubWF0Y2goIC9eXFxzKlxcWyguKj8pXFxdLyApO1xuXG4gICAgICBpZiAoIG0gKSB7XG5cbiAgICAgICAgY29uc3VtZWQgKz0gbVsgMCBdLmxlbmd0aDtcblxuICAgICAgICAvLyBbbGlua3NdW10gdXNlcyBsaW5rcyBhcyBpdHMgcmVmZXJlbmNlXG4gICAgICAgIGF0dHJzID0geyByZWY6ICggbVsgMSBdIHx8IFN0cmluZyhjaGlsZHJlbikgKS50b0xvd2VyQ2FzZSgpLCAgb3JpZ2luYWw6IG9yaWcuc3Vic3RyKCAwLCBjb25zdW1lZCApIH07XG5cbiAgICAgICAgbGluayA9IFsgXCJsaW5rX3JlZlwiLCBhdHRycyBdLmNvbmNhdCggY2hpbGRyZW4gKTtcblxuICAgICAgICAvLyBXZSBjYW4ndCBjaGVjayBpZiB0aGUgcmVmZXJlbmNlIGlzIGtub3duIGhlcmUgYXMgaXQgbGlrZWx5IHdvbnQgYmVcbiAgICAgICAgLy8gZm91bmQgdGlsbCBhZnRlci4gQ2hlY2sgaXQgaW4gbWQgdHJlZS0+aG10bCB0cmVlIGNvbnZlcnNpb24uXG4gICAgICAgIC8vIFN0b3JlIHRoZSBvcmlnaW5hbCBzbyB0aGF0IGNvbnZlcnNpb24gY2FuIHJldmVydCBpZiB0aGUgcmVmIGlzbid0IGZvdW5kLlxuICAgICAgICByZXR1cm4gWyBjb25zdW1lZCwgbGluayBdO1xuICAgICAgfVxuXG4gICAgICAvLyBbaWRdXG4gICAgICAvLyBPbmx5IGlmIGlkIGlzIHBsYWluIChubyBmb3JtYXR0aW5nLilcbiAgICAgIGlmICggY2hpbGRyZW4ubGVuZ3RoID09IDEgJiYgdHlwZW9mIGNoaWxkcmVuWzBdID09IFwic3RyaW5nXCIgKSB7XG5cbiAgICAgICAgYXR0cnMgPSB7IHJlZjogY2hpbGRyZW5bMF0udG9Mb3dlckNhc2UoKSwgIG9yaWdpbmFsOiBvcmlnLnN1YnN0ciggMCwgY29uc3VtZWQgKSB9O1xuICAgICAgICBsaW5rID0gWyBcImxpbmtfcmVmXCIsIGF0dHJzLCBjaGlsZHJlblswXSBdO1xuICAgICAgICByZXR1cm4gWyBjb25zdW1lZCwgbGluayBdO1xuICAgICAgfVxuXG4gICAgICAvLyBKdXN0IGNvbnN1bWUgdGhlIFwiW1wiXG4gICAgICByZXR1cm4gWyAxLCBcIltcIiBdO1xuICAgIH0sXG5cblxuICAgIFwiPFwiOiBmdW5jdGlvbiBhdXRvTGluayggdGV4dCApIHtcbiAgICAgIHZhciBtO1xuXG4gICAgICBpZiAoICggbSA9IHRleHQubWF0Y2goIC9ePCg/OigoaHR0cHM/fGZ0cHxtYWlsdG8pOltePl0rKXwoLio/QC4qP1xcLlthLXpBLVpdKykpPi8gKSApICE9IG51bGwgKSB7XG4gICAgICAgIGlmICggbVszXSApIHtcbiAgICAgICAgICByZXR1cm4gWyBtWzBdLmxlbmd0aCwgWyBcImxpbmtcIiwgeyBocmVmOiBcIm1haWx0bzpcIiArIG1bM10gfSwgbVszXSBdIF07XG5cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICggbVsyXSA9PSBcIm1haWx0b1wiICkge1xuICAgICAgICAgIHJldHVybiBbIG1bMF0ubGVuZ3RoLCBbIFwibGlua1wiLCB7IGhyZWY6IG1bMV0gfSwgbVsxXS5zdWJzdHIoXCJtYWlsdG86XCIubGVuZ3RoICkgXSBdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICByZXR1cm4gWyBtWzBdLmxlbmd0aCwgWyBcImxpbmtcIiwgeyBocmVmOiBtWzFdIH0sIG1bMV0gXSBdO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gWyAxLCBcIjxcIiBdO1xuICAgIH0sXG5cbiAgICBcImBcIjogZnVuY3Rpb24gaW5saW5lQ29kZSggdGV4dCApIHtcbiAgICAgIC8vIElubGluZSBjb2RlIGJsb2NrLiBhcyBtYW55IGJhY2t0aWNrcyBhcyB5b3UgbGlrZSB0byBzdGFydCBpdFxuICAgICAgLy8gQWx3YXlzIHNraXAgb3ZlciB0aGUgb3BlbmluZyB0aWNrcy5cbiAgICAgIHZhciBtID0gdGV4dC5tYXRjaCggLyhgKykoKFtcXHNcXFNdKj8pXFwxKS8gKTtcblxuICAgICAgaWYgKCBtICYmIG1bMl0gKVxuICAgICAgICByZXR1cm4gWyBtWzFdLmxlbmd0aCArIG1bMl0ubGVuZ3RoLCBbIFwiaW5saW5lY29kZVwiLCBtWzNdIF0gXTtcbiAgICAgIGVsc2Uge1xuICAgICAgICAvLyBUT0RPOiBObyBtYXRjaGluZyBlbmQgY29kZSBmb3VuZCAtIHdhcm4hXG4gICAgICAgIHJldHVybiBbIDEsIFwiYFwiIF07XG4gICAgICB9XG4gICAgfSxcblxuICAgIFwiICBcXG5cIjogZnVuY3Rpb24gbGluZUJyZWFrKCB0ZXh0ICkge1xuICAgICAgcmV0dXJuIFsgMywgWyBcImxpbmVicmVha1wiIF0gXTtcbiAgICB9XG5cbn07XG5cbi8vIE1ldGEgSGVscGVyL2dlbmVyYXRvciBtZXRob2QgZm9yIGVtIGFuZCBzdHJvbmcgaGFuZGxpbmdcbmZ1bmN0aW9uIHN0cm9uZ19lbSggdGFnLCBtZCApIHtcblxuICB2YXIgc3RhdGVfc2xvdCA9IHRhZyArIFwiX3N0YXRlXCIsXG4gICAgICBvdGhlcl9zbG90ID0gdGFnID09IFwic3Ryb25nXCIgPyBcImVtX3N0YXRlXCIgOiBcInN0cm9uZ19zdGF0ZVwiO1xuXG4gIGZ1bmN0aW9uIENsb3NlVGFnKGxlbikge1xuICAgIHRoaXMubGVuX2FmdGVyID0gbGVuO1xuICAgIHRoaXMubmFtZSA9IFwiY2xvc2VfXCIgKyBtZDtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAoIHRleHQsIG9yaWdfbWF0Y2ggKSB7XG5cbiAgICBpZiAoIHRoaXNbc3RhdGVfc2xvdF1bMF0gPT0gbWQgKSB7XG4gICAgICAvLyBNb3N0IHJlY2VudCBlbSBpcyBvZiB0aGlzIHR5cGVcbiAgICAgIC8vRDp0aGlzLmRlYnVnKFwiY2xvc2luZ1wiLCBtZCk7XG4gICAgICB0aGlzW3N0YXRlX3Nsb3RdLnNoaWZ0KCk7XG5cbiAgICAgIC8vIFwiQ29uc3VtZVwiIGV2ZXJ5dGhpbmcgdG8gZ28gYmFjayB0byB0aGUgcmVjcnVzaW9uIGluIHRoZSBlbHNlLWJsb2NrIGJlbG93XG4gICAgICByZXR1cm5bIHRleHQubGVuZ3RoLCBuZXcgQ2xvc2VUYWcodGV4dC5sZW5ndGgtbWQubGVuZ3RoKSBdO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIC8vIFN0b3JlIGEgY2xvbmUgb2YgdGhlIGVtL3N0cm9uZyBzdGF0ZXNcbiAgICAgIHZhciBvdGhlciA9IHRoaXNbb3RoZXJfc2xvdF0uc2xpY2UoKSxcbiAgICAgICAgICBzdGF0ZSA9IHRoaXNbc3RhdGVfc2xvdF0uc2xpY2UoKTtcblxuICAgICAgdGhpc1tzdGF0ZV9zbG90XS51bnNoaWZ0KG1kKTtcblxuICAgICAgLy9EOnRoaXMuZGVidWdfaW5kZW50ICs9IFwiICBcIjtcblxuICAgICAgLy8gUmVjdXJzZVxuICAgICAgdmFyIHJlcyA9IHRoaXMucHJvY2Vzc0lubGluZSggdGV4dC5zdWJzdHIoIG1kLmxlbmd0aCApICk7XG4gICAgICAvL0Q6dGhpcy5kZWJ1Z19pbmRlbnQgPSB0aGlzLmRlYnVnX2luZGVudC5zdWJzdHIoMik7XG5cbiAgICAgIHZhciBsYXN0ID0gcmVzW3Jlcy5sZW5ndGggLSAxXTtcblxuICAgICAgLy9EOnRoaXMuZGVidWcoXCJwcm9jZXNzSW5saW5lIGZyb21cIiwgdGFnICsgXCI6IFwiLCB1bmV2YWwoIHJlcyApICk7XG5cbiAgICAgIHZhciBjaGVjayA9IHRoaXNbc3RhdGVfc2xvdF0uc2hpZnQoKTtcbiAgICAgIGlmICggbGFzdCBpbnN0YW5jZW9mIENsb3NlVGFnICkge1xuICAgICAgICByZXMucG9wKCk7XG4gICAgICAgIC8vIFdlIG1hdGNoZWQhIEh1enphaC5cbiAgICAgICAgdmFyIGNvbnN1bWVkID0gdGV4dC5sZW5ndGggLSBsYXN0Lmxlbl9hZnRlcjtcbiAgICAgICAgcmV0dXJuIFsgY29uc3VtZWQsIFsgdGFnIF0uY29uY2F0KHJlcykgXTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICAvLyBSZXN0b3JlIHRoZSBzdGF0ZSBvZiB0aGUgb3RoZXIga2luZC4gV2UgbWlnaHQgaGF2ZSBtaXN0YWtlbmx5IGNsb3NlZCBpdC5cbiAgICAgICAgdGhpc1tvdGhlcl9zbG90XSA9IG90aGVyO1xuICAgICAgICB0aGlzW3N0YXRlX3Nsb3RdID0gc3RhdGU7XG5cbiAgICAgICAgLy8gV2UgY2FuJ3QgcmV1c2UgdGhlIHByb2Nlc3NlZCByZXN1bHQgYXMgaXQgY291bGQgaGF2ZSB3cm9uZyBwYXJzaW5nIGNvbnRleHRzIGluIGl0LlxuICAgICAgICByZXR1cm4gWyBtZC5sZW5ndGgsIG1kIF07XG4gICAgICB9XG4gICAgfVxuICB9OyAvLyBFbmQgcmV0dXJuZWQgZnVuY3Rpb25cbn1cblxuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZVtcIioqXCJdID0gc3Ryb25nX2VtKFwic3Ryb25nXCIsIFwiKipcIik7XG5NYXJrZG93bi5kaWFsZWN0cy5HcnViZXIuaW5saW5lW1wiX19cIl0gPSBzdHJvbmdfZW0oXCJzdHJvbmdcIiwgXCJfX1wiKTtcbk1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5pbmxpbmVbXCIqXCJdICA9IHN0cm9uZ19lbShcImVtXCIsIFwiKlwiKTtcbk1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5pbmxpbmVbXCJfXCJdICA9IHN0cm9uZ19lbShcImVtXCIsIFwiX1wiKTtcblxuXG4vLyBCdWlsZCBkZWZhdWx0IG9yZGVyIGZyb20gaW5zZXJ0aW9uIG9yZGVyLlxuTWFya2Rvd24uYnVpbGRCbG9ja09yZGVyID0gZnVuY3Rpb24oZCkge1xuICB2YXIgb3JkID0gW107XG4gIGZvciAoIHZhciBpIGluIGQgKSB7XG4gICAgaWYgKCBpID09IFwiX19vcmRlcl9fXCIgfHwgaSA9PSBcIl9fY2FsbF9fXCIgKSBjb250aW51ZTtcbiAgICBvcmQucHVzaCggaSApO1xuICB9XG4gIGQuX19vcmRlcl9fID0gb3JkO1xufTtcblxuLy8gQnVpbGQgcGF0dGVybnMgZm9yIGlubGluZSBtYXRjaGVyXG5NYXJrZG93bi5idWlsZElubGluZVBhdHRlcm5zID0gZnVuY3Rpb24oZCkge1xuICB2YXIgcGF0dGVybnMgPSBbXTtcblxuICBmb3IgKCB2YXIgaSBpbiBkICkge1xuICAgIC8vIF9fZm9vX18gaXMgcmVzZXJ2ZWQgYW5kIG5vdCBhIHBhdHRlcm5cbiAgICBpZiAoIGkubWF0Y2goIC9eX18uKl9fJC8pICkgY29udGludWU7XG4gICAgdmFyIGwgPSBpLnJlcGxhY2UoIC8oW1xcXFwuKis/fCgpXFxbXFxde31dKS9nLCBcIlxcXFwkMVwiIClcbiAgICAgICAgICAgICAucmVwbGFjZSggL1xcbi8sIFwiXFxcXG5cIiApO1xuICAgIHBhdHRlcm5zLnB1c2goIGkubGVuZ3RoID09IDEgPyBsIDogXCIoPzpcIiArIGwgKyBcIilcIiApO1xuICB9XG5cbiAgcGF0dGVybnMgPSBwYXR0ZXJucy5qb2luKFwifFwiKTtcbiAgZC5fX3BhdHRlcm5zX18gPSBwYXR0ZXJucztcbiAgLy9wcmludChcInBhdHRlcm5zOlwiLCB1bmV2YWwoIHBhdHRlcm5zICkgKTtcblxuICB2YXIgZm4gPSBkLl9fY2FsbF9fO1xuICBkLl9fY2FsbF9fID0gZnVuY3Rpb24odGV4dCwgcGF0dGVybikge1xuICAgIGlmICggcGF0dGVybiAhPSB1bmRlZmluZWQgKSB7XG4gICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCB0ZXh0LCBwYXR0ZXJuKTtcbiAgICB9XG4gICAgZWxzZVxuICAgIHtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoaXMsIHRleHQsIHBhdHRlcm5zKTtcbiAgICB9XG4gIH07XG59O1xuXG5NYXJrZG93bi5EaWFsZWN0SGVscGVycyA9IHt9O1xuTWFya2Rvd24uRGlhbGVjdEhlbHBlcnMuaW5saW5lX3VudGlsX2NoYXIgPSBmdW5jdGlvbiggdGV4dCwgd2FudCApIHtcbiAgdmFyIGNvbnN1bWVkID0gMCxcbiAgICAgIG5vZGVzID0gW107XG5cbiAgd2hpbGUgKCB0cnVlICkge1xuICAgIGlmICggdGV4dC5jaGFyQXQoIGNvbnN1bWVkICkgPT0gd2FudCApIHtcbiAgICAgIC8vIEZvdW5kIHRoZSBjaGFyYWN0ZXIgd2Ugd2VyZSBsb29raW5nIGZvclxuICAgICAgY29uc3VtZWQrKztcbiAgICAgIHJldHVybiBbIGNvbnN1bWVkLCBub2RlcyBdO1xuICAgIH1cblxuICAgIGlmICggY29uc3VtZWQgPj0gdGV4dC5sZW5ndGggKSB7XG4gICAgICAvLyBObyBjbG9zaW5nIGNoYXIgZm91bmQuIEFib3J0LlxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHJlcyA9IHRoaXMuZGlhbGVjdC5pbmxpbmUuX19vbmVFbGVtZW50X18uY2FsbCh0aGlzLCB0ZXh0LnN1YnN0ciggY29uc3VtZWQgKSApO1xuICAgIGNvbnN1bWVkICs9IHJlc1sgMCBdO1xuICAgIC8vIEFkZCBhbnkgcmV0dXJuZWQgbm9kZXMuXG4gICAgbm9kZXMucHVzaC5hcHBseSggbm9kZXMsIHJlcy5zbGljZSggMSApICk7XG4gIH1cbn1cblxuLy8gSGVscGVyIGZ1bmN0aW9uIHRvIG1ha2Ugc3ViLWNsYXNzaW5nIGEgZGlhbGVjdCBlYXNpZXJcbk1hcmtkb3duLnN1YmNsYXNzRGlhbGVjdCA9IGZ1bmN0aW9uKCBkICkge1xuICBmdW5jdGlvbiBCbG9jaygpIHt9XG4gIEJsb2NrLnByb3RvdHlwZSA9IGQuYmxvY2s7XG4gIGZ1bmN0aW9uIElubGluZSgpIHt9XG4gIElubGluZS5wcm90b3R5cGUgPSBkLmlubGluZTtcblxuICByZXR1cm4geyBibG9jazogbmV3IEJsb2NrKCksIGlubGluZTogbmV3IElubGluZSgpIH07XG59O1xuXG5NYXJrZG93bi5idWlsZEJsb2NrT3JkZXIgKCBNYXJrZG93bi5kaWFsZWN0cy5HcnViZXIuYmxvY2sgKTtcbk1hcmtkb3duLmJ1aWxkSW5saW5lUGF0dGVybnMoIE1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5pbmxpbmUgKTtcblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1ID0gTWFya2Rvd24uc3ViY2xhc3NEaWFsZWN0KCBNYXJrZG93bi5kaWFsZWN0cy5HcnViZXIgKTtcblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LnByb2Nlc3NNZXRhSGFzaCA9IGZ1bmN0aW9uIHByb2Nlc3NNZXRhSGFzaCggbWV0YV9zdHJpbmcgKSB7XG4gIHZhciBtZXRhID0gc3BsaXRfbWV0YV9oYXNoKCBtZXRhX3N0cmluZyApLFxuICAgICAgYXR0ciA9IHt9O1xuXG4gIGZvciAoIHZhciBpID0gMDsgaSA8IG1ldGEubGVuZ3RoOyArK2kgKSB7XG4gICAgLy8gaWQ6ICNmb29cbiAgICBpZiAoIC9eIy8udGVzdCggbWV0YVsgaSBdICkgKSB7XG4gICAgICBhdHRyLmlkID0gbWV0YVsgaSBdLnN1YnN0cmluZyggMSApO1xuICAgIH1cbiAgICAvLyBjbGFzczogLmZvb1xuICAgIGVsc2UgaWYgKCAvXlxcLi8udGVzdCggbWV0YVsgaSBdICkgKSB7XG4gICAgICAvLyBpZiBjbGFzcyBhbHJlYWR5IGV4aXN0cywgYXBwZW5kIHRoZSBuZXcgb25lXG4gICAgICBpZiAoIGF0dHJbXCJjbGFzc1wiXSApIHtcbiAgICAgICAgYXR0cltcImNsYXNzXCJdID0gYXR0cltcImNsYXNzXCJdICsgbWV0YVsgaSBdLnJlcGxhY2UoIC8uLywgXCIgXCIgKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBhdHRyW1wiY2xhc3NcIl0gPSBtZXRhWyBpIF0uc3Vic3RyaW5nKCAxICk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIGF0dHJpYnV0ZTogZm9vPWJhclxuICAgIGVsc2UgaWYgKCAvXFw9Ly50ZXN0KCBtZXRhWyBpIF0gKSApIHtcbiAgICAgIHZhciBzID0gbWV0YVsgaSBdLnNwbGl0KCAvXFw9LyApO1xuICAgICAgYXR0clsgc1sgMCBdIF0gPSBzWyAxIF07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGF0dHI7XG59XG5cbmZ1bmN0aW9uIHNwbGl0X21ldGFfaGFzaCggbWV0YV9zdHJpbmcgKSB7XG4gIHZhciBtZXRhID0gbWV0YV9zdHJpbmcuc3BsaXQoIFwiXCIgKSxcbiAgICAgIHBhcnRzID0gWyBcIlwiIF0sXG4gICAgICBpbl9xdW90ZXMgPSBmYWxzZTtcblxuICB3aGlsZSAoIG1ldGEubGVuZ3RoICkge1xuICAgIHZhciBsZXR0ZXIgPSBtZXRhLnNoaWZ0KCk7XG4gICAgc3dpdGNoICggbGV0dGVyICkge1xuICAgICAgY2FzZSBcIiBcIiA6XG4gICAgICAgIC8vIGlmIHdlJ3JlIGluIGEgcXVvdGVkIHNlY3Rpb24sIGtlZXAgaXRcbiAgICAgICAgaWYgKCBpbl9xdW90ZXMgKSB7XG4gICAgICAgICAgcGFydHNbIHBhcnRzLmxlbmd0aCAtIDEgXSArPSBsZXR0ZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gb3RoZXJ3aXNlIG1ha2UgYSBuZXcgcGFydFxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBwYXJ0cy5wdXNoKCBcIlwiICk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwiJ1wiIDpcbiAgICAgIGNhc2UgJ1wiJyA6XG4gICAgICAgIC8vIHJldmVyc2UgdGhlIHF1b3RlcyBhbmQgbW92ZSBzdHJhaWdodCBvblxuICAgICAgICBpbl9xdW90ZXMgPSAhaW5fcXVvdGVzO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJcXFxcXCIgOlxuICAgICAgICAvLyBzaGlmdCBvZmYgdGhlIG5leHQgbGV0dGVyIHRvIGJlIHVzZWQgc3RyYWlnaHQgYXdheS5cbiAgICAgICAgLy8gaXQgd2FzIGVzY2FwZWQgc28gd2UnbGwga2VlcCBpdCB3aGF0ZXZlciBpdCBpc1xuICAgICAgICBsZXR0ZXIgPSBtZXRhLnNoaWZ0KCk7XG4gICAgICBkZWZhdWx0IDpcbiAgICAgICAgcGFydHNbIHBhcnRzLmxlbmd0aCAtIDEgXSArPSBsZXR0ZXI7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwYXJ0cztcbn1cblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmJsb2NrLmRvY3VtZW50X21ldGEgPSBmdW5jdGlvbiBkb2N1bWVudF9tZXRhKCBibG9jaywgbmV4dCApIHtcbiAgLy8gd2UncmUgb25seSBpbnRlcmVzdGVkIGluIHRoZSBmaXJzdCBibG9ja1xuICBpZiAoIGJsb2NrLmxpbmVOdW1iZXIgPiAxICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAvLyBkb2N1bWVudF9tZXRhIGJsb2NrcyBjb25zaXN0IG9mIG9uZSBvciBtb3JlIGxpbmVzIG9mIGBLZXk6IFZhbHVlXFxuYFxuICBpZiAoICEgYmxvY2subWF0Y2goIC9eKD86XFx3KzouKlxcbikqXFx3KzouKiQvICkgKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIC8vIG1ha2UgYW4gYXR0cmlidXRlIG5vZGUgaWYgaXQgZG9lc24ndCBleGlzdFxuICBpZiAoICFleHRyYWN0X2F0dHIoIHRoaXMudHJlZSApICkge1xuICAgIHRoaXMudHJlZS5zcGxpY2UoIDEsIDAsIHt9ICk7XG4gIH1cblxuICB2YXIgcGFpcnMgPSBibG9jay5zcGxpdCggL1xcbi8gKTtcbiAgZm9yICggcCBpbiBwYWlycyApIHtcbiAgICB2YXIgbSA9IHBhaXJzWyBwIF0ubWF0Y2goIC8oXFx3Kyk6XFxzKiguKikkLyApLFxuICAgICAgICBrZXkgPSBtWyAxIF0udG9Mb3dlckNhc2UoKSxcbiAgICAgICAgdmFsdWUgPSBtWyAyIF07XG5cbiAgICB0aGlzLnRyZWVbIDEgXVsga2V5IF0gPSB2YWx1ZTtcbiAgfVxuXG4gIC8vIGRvY3VtZW50X21ldGEgcHJvZHVjZXMgbm8gY29udGVudCFcbiAgcmV0dXJuIFtdO1xufTtcblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmJsb2NrLmJsb2NrX21ldGEgPSBmdW5jdGlvbiBibG9ja19tZXRhKCBibG9jaywgbmV4dCApIHtcbiAgLy8gY2hlY2sgaWYgdGhlIGxhc3QgbGluZSBvZiB0aGUgYmxvY2sgaXMgYW4gbWV0YSBoYXNoXG4gIHZhciBtID0gYmxvY2subWF0Y2goIC8oXnxcXG4pIHswLDN9XFx7OlxccyooKD86XFxcXFxcfXxbXlxcfV0pKilcXHMqXFx9JC8gKTtcbiAgaWYgKCAhbSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgLy8gcHJvY2VzcyB0aGUgbWV0YSBoYXNoXG4gIHZhciBhdHRyID0gdGhpcy5kaWFsZWN0LnByb2Nlc3NNZXRhSGFzaCggbVsgMiBdICk7XG5cbiAgdmFyIGhhc2g7XG5cbiAgLy8gaWYgd2UgbWF0Y2hlZCBeIHRoZW4gd2UgbmVlZCB0byBhcHBseSBtZXRhIHRvIHRoZSBwcmV2aW91cyBibG9ja1xuICBpZiAoIG1bIDEgXSA9PT0gXCJcIiApIHtcbiAgICB2YXIgbm9kZSA9IHRoaXMudHJlZVsgdGhpcy50cmVlLmxlbmd0aCAtIDEgXTtcbiAgICBoYXNoID0gZXh0cmFjdF9hdHRyKCBub2RlICk7XG5cbiAgICAvLyBpZiB0aGUgbm9kZSBpcyBhIHN0cmluZyAocmF0aGVyIHRoYW4gSnNvbk1MKSwgYmFpbFxuICAgIGlmICggdHlwZW9mIG5vZGUgPT09IFwic3RyaW5nXCIgKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgLy8gY3JlYXRlIHRoZSBhdHRyaWJ1dGUgaGFzaCBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgaWYgKCAhaGFzaCApIHtcbiAgICAgIGhhc2ggPSB7fTtcbiAgICAgIG5vZGUuc3BsaWNlKCAxLCAwLCBoYXNoICk7XG4gICAgfVxuXG4gICAgLy8gYWRkIHRoZSBhdHRyaWJ1dGVzIGluXG4gICAgZm9yICggYSBpbiBhdHRyICkge1xuICAgICAgaGFzaFsgYSBdID0gYXR0clsgYSBdO1xuICAgIH1cblxuICAgIC8vIHJldHVybiBub3RoaW5nIHNvIHRoZSBtZXRhIGhhc2ggaXMgcmVtb3ZlZFxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8vIHB1bGwgdGhlIG1ldGEgaGFzaCBvZmYgdGhlIGJsb2NrIGFuZCBwcm9jZXNzIHdoYXQncyBsZWZ0XG4gIHZhciBiID0gYmxvY2sucmVwbGFjZSggL1xcbi4qJC8sIFwiXCIgKSxcbiAgICAgIHJlc3VsdCA9IHRoaXMucHJvY2Vzc0Jsb2NrKCBiLCBbXSApO1xuXG4gIC8vIGdldCBvciBtYWtlIHRoZSBhdHRyaWJ1dGVzIGhhc2hcbiAgaGFzaCA9IGV4dHJhY3RfYXR0ciggcmVzdWx0WyAwIF0gKTtcbiAgaWYgKCAhaGFzaCApIHtcbiAgICBoYXNoID0ge307XG4gICAgcmVzdWx0WyAwIF0uc3BsaWNlKCAxLCAwLCBoYXNoICk7XG4gIH1cblxuICAvLyBhdHRhY2ggdGhlIGF0dHJpYnV0ZXMgdG8gdGhlIGJsb2NrXG4gIGZvciAoIGEgaW4gYXR0ciApIHtcbiAgICBoYXNoWyBhIF0gPSBhdHRyWyBhIF07XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmJsb2NrLmRlZmluaXRpb25fbGlzdCA9IGZ1bmN0aW9uIGRlZmluaXRpb25fbGlzdCggYmxvY2ssIG5leHQgKSB7XG4gIC8vIG9uZSBvciBtb3JlIHRlcm1zIGZvbGxvd2VkIGJ5IG9uZSBvciBtb3JlIGRlZmluaXRpb25zLCBpbiBhIHNpbmdsZSBibG9ja1xuICB2YXIgdGlnaHQgPSAvXigoPzpbXlxcczpdLipcXG4pKyk6XFxzKyhbXFxzXFxTXSspJC8sXG4gICAgICBsaXN0ID0gWyBcImRsXCIgXSxcbiAgICAgIGksIG07XG5cbiAgLy8gc2VlIGlmIHdlJ3JlIGRlYWxpbmcgd2l0aCBhIHRpZ2h0IG9yIGxvb3NlIGJsb2NrXG4gIGlmICggKCBtID0gYmxvY2subWF0Y2goIHRpZ2h0ICkgKSApIHtcbiAgICAvLyBwdWxsIHN1YnNlcXVlbnQgdGlnaHQgREwgYmxvY2tzIG91dCBvZiBgbmV4dGBcbiAgICB2YXIgYmxvY2tzID0gWyBibG9jayBdO1xuICAgIHdoaWxlICggbmV4dC5sZW5ndGggJiYgdGlnaHQuZXhlYyggbmV4dFsgMCBdICkgKSB7XG4gICAgICBibG9ja3MucHVzaCggbmV4dC5zaGlmdCgpICk7XG4gICAgfVxuXG4gICAgZm9yICggdmFyIGIgPSAwOyBiIDwgYmxvY2tzLmxlbmd0aDsgKytiICkge1xuICAgICAgdmFyIG0gPSBibG9ja3NbIGIgXS5tYXRjaCggdGlnaHQgKSxcbiAgICAgICAgICB0ZXJtcyA9IG1bIDEgXS5yZXBsYWNlKCAvXFxuJC8sIFwiXCIgKS5zcGxpdCggL1xcbi8gKSxcbiAgICAgICAgICBkZWZucyA9IG1bIDIgXS5zcGxpdCggL1xcbjpcXHMrLyApO1xuXG4gICAgICAvLyBwcmludCggdW5ldmFsKCBtICkgKTtcblxuICAgICAgZm9yICggaSA9IDA7IGkgPCB0ZXJtcy5sZW5ndGg7ICsraSApIHtcbiAgICAgICAgbGlzdC5wdXNoKCBbIFwiZHRcIiwgdGVybXNbIGkgXSBdICk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoIGkgPSAwOyBpIDwgZGVmbnMubGVuZ3RoOyArK2kgKSB7XG4gICAgICAgIC8vIHJ1biBpbmxpbmUgcHJvY2Vzc2luZyBvdmVyIHRoZSBkZWZpbml0aW9uXG4gICAgICAgIGxpc3QucHVzaCggWyBcImRkXCIgXS5jb25jYXQoIHRoaXMucHJvY2Vzc0lubGluZSggZGVmbnNbIGkgXS5yZXBsYWNlKCAvKFxcbilcXHMrLywgXCIkMVwiICkgKSApICk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICByZXR1cm4gWyBsaXN0IF07XG59O1xuXG4vLyBzcGxpdHMgb24gdW5lc2NhcGVkIGluc3RhbmNlcyBvZiBAY2guIElmIEBjaCBpcyBub3QgYSBjaGFyYWN0ZXIgdGhlIHJlc3VsdFxuLy8gY2FuIGJlIHVucHJlZGljdGFibGVcblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmJsb2NrLnRhYmxlID0gZnVuY3Rpb24gdGFibGUgKGJsb2NrLCBuZXh0KSB7XG5cbiAgICB2YXIgX3NwbGl0X29uX3VuZXNjYXBlZCA9IGZ1bmN0aW9uKHMsIGNoKSB7XG4gICAgICAgIGNoID0gY2ggfHwgJ1xcXFxzJztcbiAgICAgICAgaWYgKGNoLm1hdGNoKC9eW1xcXFx8XFxbXFxde30/Ki4rXiRdJC8pKSB7IGNoID0gJ1xcXFwnICsgY2g7IH1cbiAgICAgICAgdmFyIHJlcyA9IFsgXSxcbiAgICAgICAgICAgIHIgPSBuZXcgUmVnRXhwKCdeKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcJyArIGNoICsgJ10pKiknICsgY2ggKyAnKC4qKScpLFxuICAgICAgICAgICAgbTtcbiAgICAgICAgd2hpbGUobSA9IHMubWF0Y2gocikpIHtcbiAgICAgICAgICAgIHJlcy5wdXNoKG1bMV0pO1xuICAgICAgICAgICAgcyA9IG1bMl07XG4gICAgICAgIH1cbiAgICAgICAgcmVzLnB1c2gocyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgdmFyIGxlYWRpbmdfcGlwZSA9IC9eIHswLDN9XFx8KC4rKVxcbiB7MCwzfVxcfFxccyooW1xcLTpdK1tcXC18IDpdKilcXG4oKD86XFxzKlxcfC4qKD86XFxufCQpKSopKD89XFxufCQpLyxcbiAgICAgICAgLy8gZmluZCBhdCBsZWFzdCBhbiB1bmVzY2FwZWQgcGlwZSBpbiBlYWNoIGxpbmVcbiAgICAgICAgbm9fbGVhZGluZ19waXBlID0gL14gezAsM30oXFxTKD86XFxcXC58W15cXFxcfF0pKlxcfC4qKVxcbiB7MCwzfShbXFwtOl0rXFxzKlxcfFtcXC18IDpdKilcXG4oKD86KD86XFxcXC58W15cXFxcfF0pKlxcfC4qKD86XFxufCQpKSopKD89XFxufCQpLyxcbiAgICAgICAgaSwgbTtcbiAgICBpZiAobSA9IGJsb2NrLm1hdGNoKGxlYWRpbmdfcGlwZSkpIHtcbiAgICAgICAgLy8gcmVtb3ZlIGxlYWRpbmcgcGlwZXMgaW4gY29udGVudHNcbiAgICAgICAgLy8gKGhlYWRlciBhbmQgaG9yaXpvbnRhbCBydWxlIGFscmVhZHkgaGF2ZSB0aGUgbGVhZGluZyBwaXBlIGxlZnQgb3V0KVxuICAgICAgICBtWzNdID0gbVszXS5yZXBsYWNlKC9eXFxzKlxcfC9nbSwgJycpO1xuICAgIH0gZWxzZSBpZiAoISAoIG0gPSBibG9jay5tYXRjaChub19sZWFkaW5nX3BpcGUpKSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHZhciB0YWJsZSA9IFsgXCJ0YWJsZVwiLCBbIFwidGhlYWRcIiwgWyBcInRyXCIgXSBdLCBbIFwidGJvZHlcIiBdIF07XG5cbiAgICAvLyByZW1vdmUgdHJhaWxpbmcgcGlwZXMsIHRoZW4gc3BsaXQgb24gcGlwZXNcbiAgICAvLyAobm8gZXNjYXBlZCBwaXBlcyBhcmUgYWxsb3dlZCBpbiBob3Jpem9udGFsIHJ1bGUpXG4gICAgbVsyXSA9IG1bMl0ucmVwbGFjZSgvXFx8XFxzKiQvLCAnJykuc3BsaXQoJ3wnKTtcblxuICAgIC8vIHByb2Nlc3MgYWxpZ25tZW50XG4gICAgdmFyIGh0bWxfYXR0cnMgPSBbIF07XG4gICAgZm9yRWFjaCAobVsyXSwgZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgaWYgKHMubWF0Y2goL15cXHMqLSs6XFxzKiQvKSkgICAgICAgaHRtbF9hdHRycy5wdXNoKHthbGlnbjogXCJyaWdodFwifSk7XG4gICAgICAgIGVsc2UgaWYgKHMubWF0Y2goL15cXHMqOi0rXFxzKiQvKSkgIGh0bWxfYXR0cnMucHVzaCh7YWxpZ246IFwibGVmdFwifSk7XG4gICAgICAgIGVsc2UgaWYgKHMubWF0Y2goL15cXHMqOi0rOlxccyokLykpIGh0bWxfYXR0cnMucHVzaCh7YWxpZ246IFwiY2VudGVyXCJ9KTtcbiAgICAgICAgZWxzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWxfYXR0cnMucHVzaCh7fSk7XG4gICAgfSk7XG5cbiAgICAvLyBub3cgZm9yIHRoZSBoZWFkZXIsIGF2b2lkIGVzY2FwZWQgcGlwZXNcbiAgICBtWzFdID0gX3NwbGl0X29uX3VuZXNjYXBlZChtWzFdLnJlcGxhY2UoL1xcfFxccyokLywgJycpLCAnfCcpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBtWzFdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRhYmxlWzFdWzFdLnB1c2goWyd0aCcsIGh0bWxfYXR0cnNbaV0gfHwge31dLmNvbmNhdChcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc0lubGluZShtWzFdW2ldLnRyaW0oKSkpKTtcbiAgICB9XG5cbiAgICAvLyBub3cgZm9yIGJvZHkgY29udGVudHNcbiAgICBmb3JFYWNoIChtWzNdLnJlcGxhY2UoL1xcfFxccyokL21nLCAnJykuc3BsaXQoJ1xcbicpLCBmdW5jdGlvbiAocm93KSB7XG4gICAgICAgIHZhciBodG1sX3JvdyA9IFsndHInXTtcbiAgICAgICAgcm93ID0gX3NwbGl0X29uX3VuZXNjYXBlZChyb3csICd8Jyk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCByb3cubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGh0bWxfcm93LnB1c2goWyd0ZCcsIGh0bWxfYXR0cnNbaV0gfHwge31dLmNvbmNhdCh0aGlzLnByb2Nlc3NJbmxpbmUocm93W2ldLnRyaW0oKSkpKTtcbiAgICAgICAgfVxuICAgICAgICB0YWJsZVsyXS5wdXNoKGh0bWxfcm93KTtcbiAgICB9LCB0aGlzKTtcblxuICAgIHJldHVybiBbdGFibGVdO1xufVxuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuaW5saW5lWyBcIns6XCIgXSA9IGZ1bmN0aW9uIGlubGluZV9tZXRhKCB0ZXh0LCBtYXRjaGVzLCBvdXQgKSB7XG4gIGlmICggIW91dC5sZW5ndGggKSB7XG4gICAgcmV0dXJuIFsgMiwgXCJ7OlwiIF07XG4gIH1cblxuICAvLyBnZXQgdGhlIHByZWNlZWRpbmcgZWxlbWVudFxuICB2YXIgYmVmb3JlID0gb3V0WyBvdXQubGVuZ3RoIC0gMSBdO1xuXG4gIGlmICggdHlwZW9mIGJlZm9yZSA9PT0gXCJzdHJpbmdcIiApIHtcbiAgICByZXR1cm4gWyAyLCBcIns6XCIgXTtcbiAgfVxuXG4gIC8vIG1hdGNoIGEgbWV0YSBoYXNoXG4gIHZhciBtID0gdGV4dC5tYXRjaCggL15cXHs6XFxzKigoPzpcXFxcXFx9fFteXFx9XSkqKVxccypcXH0vICk7XG5cbiAgLy8gbm8gbWF0Y2gsIGZhbHNlIGFsYXJtXG4gIGlmICggIW0gKSB7XG4gICAgcmV0dXJuIFsgMiwgXCJ7OlwiIF07XG4gIH1cblxuICAvLyBhdHRhY2ggdGhlIGF0dHJpYnV0ZXMgdG8gdGhlIHByZWNlZWRpbmcgZWxlbWVudFxuICB2YXIgbWV0YSA9IHRoaXMuZGlhbGVjdC5wcm9jZXNzTWV0YUhhc2goIG1bIDEgXSApLFxuICAgICAgYXR0ciA9IGV4dHJhY3RfYXR0ciggYmVmb3JlICk7XG5cbiAgaWYgKCAhYXR0ciApIHtcbiAgICBhdHRyID0ge307XG4gICAgYmVmb3JlLnNwbGljZSggMSwgMCwgYXR0ciApO1xuICB9XG5cbiAgZm9yICggdmFyIGsgaW4gbWV0YSApIHtcbiAgICBhdHRyWyBrIF0gPSBtZXRhWyBrIF07XG4gIH1cblxuICAvLyBjdXQgb3V0IHRoZSBzdHJpbmcgYW5kIHJlcGxhY2UgaXQgd2l0aCBub3RoaW5nXG4gIHJldHVybiBbIG1bIDAgXS5sZW5ndGgsIFwiXCIgXTtcbn07XG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5pbmxpbmUuX19lc2NhcGVfXyA9IC9eXFxcXFtcXFxcYFxcKl97fVxcW1xcXSgpI1xcKy4hXFwtfDpdLztcblxuTWFya2Rvd24uYnVpbGRCbG9ja09yZGVyICggTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmJsb2NrICk7XG5NYXJrZG93bi5idWlsZElubGluZVBhdHRlcm5zKCBNYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuaW5saW5lICk7XG5cbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbihvYmopIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopID09IFwiW29iamVjdCBBcnJheV1cIjtcbn07XG5cbnZhciBmb3JFYWNoO1xuLy8gRG9uJ3QgbWVzcyB3aXRoIEFycmF5LnByb3RvdHlwZS4gSXRzIG5vdCBmcmllbmRseVxuaWYgKCBBcnJheS5wcm90b3R5cGUuZm9yRWFjaCApIHtcbiAgZm9yRWFjaCA9IGZ1bmN0aW9uKCBhcnIsIGNiLCB0aGlzcCApIHtcbiAgICByZXR1cm4gYXJyLmZvckVhY2goIGNiLCB0aGlzcCApO1xuICB9O1xufVxuZWxzZSB7XG4gIGZvckVhY2ggPSBmdW5jdGlvbihhcnIsIGNiLCB0aGlzcCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjYi5jYWxsKHRoaXNwIHx8IGFyciwgYXJyW2ldLCBpLCBhcnIpO1xuICAgIH1cbiAgfVxufVxuXG52YXIgaXNFbXB0eSA9IGZ1bmN0aW9uKCBvYmogKSB7XG4gIGZvciAoIHZhciBrZXkgaW4gb2JqICkge1xuICAgIGlmICggaGFzT3duUHJvcGVydHkuY2FsbCggb2JqLCBrZXkgKSApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdF9hdHRyKCBqc29ubWwgKSB7XG4gIHJldHVybiBpc0FycmF5KGpzb25tbClcbiAgICAgICYmIGpzb25tbC5sZW5ndGggPiAxXG4gICAgICAmJiB0eXBlb2YganNvbm1sWyAxIF0gPT09IFwib2JqZWN0XCJcbiAgICAgICYmICEoIGlzQXJyYXkoanNvbm1sWyAxIF0pIClcbiAgICAgID8ganNvbm1sWyAxIF1cbiAgICAgIDogdW5kZWZpbmVkO1xufVxuXG5cblxuLyoqXG4gKiAgcmVuZGVySnNvbk1MKCBqc29ubWxbLCBvcHRpb25zXSApIC0+IFN0cmluZ1xuICogIC0ganNvbm1sIChBcnJheSk6IEpzb25NTCBhcnJheSB0byByZW5kZXIgdG8gWE1MXG4gKiAgLSBvcHRpb25zIChPYmplY3QpOiBvcHRpb25zXG4gKlxuICogIENvbnZlcnRzIHRoZSBnaXZlbiBKc29uTUwgaW50byB3ZWxsLWZvcm1lZCBYTUwuXG4gKlxuICogIFRoZSBvcHRpb25zIGN1cnJlbnRseSB1bmRlcnN0b29kIGFyZTpcbiAqXG4gKiAgLSByb290IChCb29sZWFuKTogd2V0aGVyIG9yIG5vdCB0aGUgcm9vdCBub2RlIHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGVcbiAqICAgIG91dHB1dCwgb3IganVzdCBpdHMgY2hpbGRyZW4uIFRoZSBkZWZhdWx0IGBmYWxzZWAgaXMgdG8gbm90IGluY2x1ZGUgdGhlXG4gKiAgICByb290IGl0c2VsZi5cbiAqL1xuZXhwb3NlLnJlbmRlckpzb25NTCA9IGZ1bmN0aW9uKCBqc29ubWwsIG9wdGlvbnMgKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAvLyBpbmNsdWRlIHRoZSByb290IGVsZW1lbnQgaW4gdGhlIHJlbmRlcmVkIG91dHB1dD9cbiAgb3B0aW9ucy5yb290ID0gb3B0aW9ucy5yb290IHx8IGZhbHNlO1xuXG4gIHZhciBjb250ZW50ID0gW107XG5cbiAgaWYgKCBvcHRpb25zLnJvb3QgKSB7XG4gICAgY29udGVudC5wdXNoKCByZW5kZXJfdHJlZSgganNvbm1sICkgKTtcbiAgfVxuICBlbHNlIHtcbiAgICBqc29ubWwuc2hpZnQoKTsgLy8gZ2V0IHJpZCBvZiB0aGUgdGFnXG4gICAgaWYgKCBqc29ubWwubGVuZ3RoICYmIHR5cGVvZiBqc29ubWxbIDAgXSA9PT0gXCJvYmplY3RcIiAmJiAhKCBqc29ubWxbIDAgXSBpbnN0YW5jZW9mIEFycmF5ICkgKSB7XG4gICAgICBqc29ubWwuc2hpZnQoKTsgLy8gZ2V0IHJpZCBvZiB0aGUgYXR0cmlidXRlc1xuICAgIH1cblxuICAgIHdoaWxlICgganNvbm1sLmxlbmd0aCApIHtcbiAgICAgIGNvbnRlbnQucHVzaCggcmVuZGVyX3RyZWUoIGpzb25tbC5zaGlmdCgpICkgKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gY29udGVudC5qb2luKCBcIlxcblxcblwiICk7XG59O1xuXG5mdW5jdGlvbiBlc2NhcGVIVE1MKCB0ZXh0ICkge1xuICByZXR1cm4gdGV4dC5yZXBsYWNlKCAvJi9nLCBcIiZhbXA7XCIgKVxuICAgICAgICAgICAgIC5yZXBsYWNlKCAvPC9nLCBcIiZsdDtcIiApXG4gICAgICAgICAgICAgLnJlcGxhY2UoIC8+L2csIFwiJmd0O1wiIClcbiAgICAgICAgICAgICAucmVwbGFjZSggL1wiL2csIFwiJnF1b3Q7XCIgKVxuICAgICAgICAgICAgIC5yZXBsYWNlKCAvJy9nLCBcIiYjMzk7XCIgKTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyX3RyZWUoIGpzb25tbCApIHtcbiAgLy8gYmFzaWMgY2FzZVxuICBpZiAoIHR5cGVvZiBqc29ubWwgPT09IFwic3RyaW5nXCIgKSB7XG4gICAgcmV0dXJuIGVzY2FwZUhUTUwoIGpzb25tbCApO1xuICB9XG5cbiAgdmFyIHRhZyA9IGpzb25tbC5zaGlmdCgpLFxuICAgICAgYXR0cmlidXRlcyA9IHt9LFxuICAgICAgY29udGVudCA9IFtdO1xuXG4gIGlmICgganNvbm1sLmxlbmd0aCAmJiB0eXBlb2YganNvbm1sWyAwIF0gPT09IFwib2JqZWN0XCIgJiYgISgganNvbm1sWyAwIF0gaW5zdGFuY2VvZiBBcnJheSApICkge1xuICAgIGF0dHJpYnV0ZXMgPSBqc29ubWwuc2hpZnQoKTtcbiAgfVxuXG4gIHdoaWxlICgganNvbm1sLmxlbmd0aCApIHtcbiAgICBjb250ZW50LnB1c2goIHJlbmRlcl90cmVlKCBqc29ubWwuc2hpZnQoKSApICk7XG4gIH1cblxuICB2YXIgdGFnX2F0dHJzID0gXCJcIjtcbiAgZm9yICggdmFyIGEgaW4gYXR0cmlidXRlcyApIHtcbiAgICB0YWdfYXR0cnMgKz0gXCIgXCIgKyBhICsgJz1cIicgKyBlc2NhcGVIVE1MKCBhdHRyaWJ1dGVzWyBhIF0gKSArICdcIic7XG4gIH1cblxuICAvLyBiZSBjYXJlZnVsIGFib3V0IGFkZGluZyB3aGl0ZXNwYWNlIGhlcmUgZm9yIGlubGluZSBlbGVtZW50c1xuICBpZiAoIHRhZyA9PSBcImltZ1wiIHx8IHRhZyA9PSBcImJyXCIgfHwgdGFnID09IFwiaHJcIiApIHtcbiAgICByZXR1cm4gXCI8XCIrIHRhZyArIHRhZ19hdHRycyArIFwiLz5cIjtcbiAgfVxuICBlbHNlIHtcbiAgICByZXR1cm4gXCI8XCIrIHRhZyArIHRhZ19hdHRycyArIFwiPlwiICsgY29udGVudC5qb2luKCBcIlwiICkgKyBcIjwvXCIgKyB0YWcgKyBcIj5cIjtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb252ZXJ0X3RyZWVfdG9faHRtbCggdHJlZSwgcmVmZXJlbmNlcywgb3B0aW9ucyApIHtcbiAgdmFyIGk7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIC8vIHNoYWxsb3cgY2xvbmVcbiAgdmFyIGpzb25tbCA9IHRyZWUuc2xpY2UoIDAgKTtcblxuICBpZiAoIHR5cGVvZiBvcHRpb25zLnByZXByb2Nlc3NUcmVlTm9kZSA9PT0gXCJmdW5jdGlvblwiICkge1xuICAgICAganNvbm1sID0gb3B0aW9ucy5wcmVwcm9jZXNzVHJlZU5vZGUoanNvbm1sLCByZWZlcmVuY2VzKTtcbiAgfVxuXG4gIC8vIENsb25lIGF0dHJpYnV0ZXMgaWYgdGhleSBleGlzdFxuICB2YXIgYXR0cnMgPSBleHRyYWN0X2F0dHIoIGpzb25tbCApO1xuICBpZiAoIGF0dHJzICkge1xuICAgIGpzb25tbFsgMSBdID0ge307XG4gICAgZm9yICggaSBpbiBhdHRycyApIHtcbiAgICAgIGpzb25tbFsgMSBdWyBpIF0gPSBhdHRyc1sgaSBdO1xuICAgIH1cbiAgICBhdHRycyA9IGpzb25tbFsgMSBdO1xuICB9XG5cbiAgLy8gYmFzaWMgY2FzZVxuICBpZiAoIHR5cGVvZiBqc29ubWwgPT09IFwic3RyaW5nXCIgKSB7XG4gICAgcmV0dXJuIGpzb25tbDtcbiAgfVxuXG4gIC8vIGNvbnZlcnQgdGhpcyBub2RlXG4gIHN3aXRjaCAoIGpzb25tbFsgMCBdICkge1xuICAgIGNhc2UgXCJoZWFkZXJcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJoXCIgKyBqc29ubWxbIDEgXS5sZXZlbDtcbiAgICAgIGRlbGV0ZSBqc29ubWxbIDEgXS5sZXZlbDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJidWxsZXRsaXN0XCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwidWxcIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJudW1iZXJsaXN0XCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwib2xcIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJsaXN0aXRlbVwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImxpXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwicGFyYVwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcInBcIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJtYXJrZG93blwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImh0bWxcIjtcbiAgICAgIGlmICggYXR0cnMgKSBkZWxldGUgYXR0cnMucmVmZXJlbmNlcztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJjb2RlX2Jsb2NrXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwicHJlXCI7XG4gICAgICBpID0gYXR0cnMgPyAyIDogMTtcbiAgICAgIHZhciBjb2RlID0gWyBcImNvZGVcIiBdO1xuICAgICAgY29kZS5wdXNoLmFwcGx5KCBjb2RlLCBqc29ubWwuc3BsaWNlKCBpLCBqc29ubWwubGVuZ3RoIC0gaSApICk7XG4gICAgICBqc29ubWxbIGkgXSA9IGNvZGU7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwiaW5saW5lY29kZVwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImNvZGVcIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJpbWdcIjpcbiAgICAgIGpzb25tbFsgMSBdLnNyYyA9IGpzb25tbFsgMSBdLmhyZWY7XG4gICAgICBkZWxldGUganNvbm1sWyAxIF0uaHJlZjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJsaW5lYnJlYWtcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJiclwiO1xuICAgIGJyZWFrO1xuICAgIGNhc2UgXCJsaW5rXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiYVwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImxpbmtfcmVmXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiYVwiO1xuXG4gICAgICAvLyBncmFiIHRoaXMgcmVmIGFuZCBjbGVhbiB1cCB0aGUgYXR0cmlidXRlIG5vZGVcbiAgICAgIHZhciByZWYgPSByZWZlcmVuY2VzWyBhdHRycy5yZWYgXTtcblxuICAgICAgLy8gaWYgdGhlIHJlZmVyZW5jZSBleGlzdHMsIG1ha2UgdGhlIGxpbmtcbiAgICAgIGlmICggcmVmICkge1xuICAgICAgICBkZWxldGUgYXR0cnMucmVmO1xuXG4gICAgICAgIC8vIGFkZCBpbiB0aGUgaHJlZiBhbmQgdGl0bGUsIGlmIHByZXNlbnRcbiAgICAgICAgYXR0cnMuaHJlZiA9IHJlZi5ocmVmO1xuICAgICAgICBpZiAoIHJlZi50aXRsZSApIHtcbiAgICAgICAgICBhdHRycy50aXRsZSA9IHJlZi50aXRsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGdldCByaWQgb2YgdGhlIHVubmVlZGVkIG9yaWdpbmFsIHRleHRcbiAgICAgICAgZGVsZXRlIGF0dHJzLm9yaWdpbmFsO1xuICAgICAgfVxuICAgICAgLy8gdGhlIHJlZmVyZW5jZSBkb2Vzbid0IGV4aXN0LCBzbyByZXZlcnQgdG8gcGxhaW4gdGV4dFxuICAgICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBhdHRycy5vcmlnaW5hbDtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJpbWdfcmVmXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiaW1nXCI7XG5cbiAgICAgIC8vIGdyYWIgdGhpcyByZWYgYW5kIGNsZWFuIHVwIHRoZSBhdHRyaWJ1dGUgbm9kZVxuICAgICAgdmFyIHJlZiA9IHJlZmVyZW5jZXNbIGF0dHJzLnJlZiBdO1xuXG4gICAgICAvLyBpZiB0aGUgcmVmZXJlbmNlIGV4aXN0cywgbWFrZSB0aGUgbGlua1xuICAgICAgaWYgKCByZWYgKSB7XG4gICAgICAgIGRlbGV0ZSBhdHRycy5yZWY7XG5cbiAgICAgICAgLy8gYWRkIGluIHRoZSBocmVmIGFuZCB0aXRsZSwgaWYgcHJlc2VudFxuICAgICAgICBhdHRycy5zcmMgPSByZWYuaHJlZjtcbiAgICAgICAgaWYgKCByZWYudGl0bGUgKSB7XG4gICAgICAgICAgYXR0cnMudGl0bGUgPSByZWYudGl0bGU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBnZXQgcmlkIG9mIHRoZSB1bm5lZWRlZCBvcmlnaW5hbCB0ZXh0XG4gICAgICAgIGRlbGV0ZSBhdHRycy5vcmlnaW5hbDtcbiAgICAgIH1cbiAgICAgIC8vIHRoZSByZWZlcmVuY2UgZG9lc24ndCBleGlzdCwgc28gcmV2ZXJ0IHRvIHBsYWluIHRleHRcbiAgICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gYXR0cnMub3JpZ2luYWw7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgfVxuXG4gIC8vIGNvbnZlcnQgYWxsIHRoZSBjaGlsZHJlblxuICBpID0gMTtcblxuICAvLyBkZWFsIHdpdGggdGhlIGF0dHJpYnV0ZSBub2RlLCBpZiBpdCBleGlzdHNcbiAgaWYgKCBhdHRycyApIHtcbiAgICAvLyBpZiB0aGVyZSBhcmUga2V5cywgc2tpcCBvdmVyIGl0XG4gICAgZm9yICggdmFyIGtleSBpbiBqc29ubWxbIDEgXSApIHtcbiAgICAgICAgaSA9IDI7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICAvLyBpZiB0aGVyZSBhcmVuJ3QsIHJlbW92ZSBpdFxuICAgIGlmICggaSA9PT0gMSApIHtcbiAgICAgIGpzb25tbC5zcGxpY2UoIGksIDEgKTtcbiAgICB9XG4gIH1cblxuICBmb3IgKCA7IGkgPCBqc29ubWwubGVuZ3RoOyArK2kgKSB7XG4gICAganNvbm1sWyBpIF0gPSBjb252ZXJ0X3RyZWVfdG9faHRtbCgganNvbm1sWyBpIF0sIHJlZmVyZW5jZXMsIG9wdGlvbnMgKTtcbiAgfVxuXG4gIHJldHVybiBqc29ubWw7XG59XG5cblxuLy8gbWVyZ2VzIGFkamFjZW50IHRleHQgbm9kZXMgaW50byBhIHNpbmdsZSBub2RlXG5mdW5jdGlvbiBtZXJnZV90ZXh0X25vZGVzKCBqc29ubWwgKSB7XG4gIC8vIHNraXAgdGhlIHRhZyBuYW1lIGFuZCBhdHRyaWJ1dGUgaGFzaFxuICB2YXIgaSA9IGV4dHJhY3RfYXR0cigganNvbm1sICkgPyAyIDogMTtcblxuICB3aGlsZSAoIGkgPCBqc29ubWwubGVuZ3RoICkge1xuICAgIC8vIGlmIGl0J3MgYSBzdHJpbmcgY2hlY2sgdGhlIG5leHQgaXRlbSB0b29cbiAgICBpZiAoIHR5cGVvZiBqc29ubWxbIGkgXSA9PT0gXCJzdHJpbmdcIiApIHtcbiAgICAgIGlmICggaSArIDEgPCBqc29ubWwubGVuZ3RoICYmIHR5cGVvZiBqc29ubWxbIGkgKyAxIF0gPT09IFwic3RyaW5nXCIgKSB7XG4gICAgICAgIC8vIG1lcmdlIHRoZSBzZWNvbmQgc3RyaW5nIGludG8gdGhlIGZpcnN0IGFuZCByZW1vdmUgaXRcbiAgICAgICAganNvbm1sWyBpIF0gKz0ganNvbm1sLnNwbGljZSggaSArIDEsIDEgKVsgMCBdO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgICsraTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gaWYgaXQncyBub3QgYSBzdHJpbmcgcmVjdXJzZVxuICAgIGVsc2Uge1xuICAgICAgbWVyZ2VfdGV4dF9ub2RlcygganNvbm1sWyBpIF0gKTtcbiAgICAgICsraTtcbiAgICB9XG4gIH1cbn1cblxufSApKCAoZnVuY3Rpb24oKSB7XG4gIGlmICggdHlwZW9mIGV4cG9ydHMgPT09IFwidW5kZWZpbmVkXCIgKSB7XG4gICAgd2luZG93Lm1hcmtkb3duID0ge307XG4gICAgcmV0dXJuIHdpbmRvdy5tYXJrZG93bjtcbiAgfVxuICBlbHNlIHtcbiAgICByZXR1cm4gZXhwb3J0cztcbiAgfVxufSApKCkgKTtcbiIsIihmdW5jdGlvbihmKXtpZih0eXBlb2YgZXhwb3J0cz09PVwib2JqZWN0XCImJnR5cGVvZiBtb2R1bGUhPT1cInVuZGVmaW5lZFwiKXttb2R1bGUuZXhwb3J0cz1mKCl9ZWxzZSBpZih0eXBlb2YgZGVmaW5lPT09XCJmdW5jdGlvblwiJiZkZWZpbmUuYW1kKXtkZWZpbmUoW10sZil9ZWxzZXt2YXIgZztpZih0eXBlb2Ygd2luZG93IT09XCJ1bmRlZmluZWRcIil7Zz13aW5kb3d9ZWxzZSBpZih0eXBlb2YgZ2xvYmFsIT09XCJ1bmRlZmluZWRcIil7Zz1nbG9iYWx9ZWxzZSBpZih0eXBlb2Ygc2VsZiE9PVwidW5kZWZpbmVkXCIpe2c9c2VsZn1lbHNle2c9dGhpc31nLnRvTWFya2Rvd24gPSBmKCl9fSkoZnVuY3Rpb24oKXt2YXIgZGVmaW5lLG1vZHVsZSxleHBvcnRzO3JldHVybiAoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSh7MTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4vKlxuICogdG8tbWFya2Rvd24gLSBhbiBIVE1MIHRvIE1hcmtkb3duIGNvbnZlcnRlclxuICpcbiAqIENvcHlyaWdodCAyMDExKywgRG9tIENocmlzdGllXG4gKiBMaWNlbmNlZCB1bmRlciB0aGUgTUlUIGxpY2VuY2VcbiAqXG4gKi9cblxuJ3VzZSBzdHJpY3QnXG5cbnZhciB0b01hcmtkb3duXG52YXIgY29udmVydGVyc1xudmFyIG1kQ29udmVydGVycyA9IHJlcXVpcmUoJy4vbGliL21kLWNvbnZlcnRlcnMnKVxudmFyIGdmbUNvbnZlcnRlcnMgPSByZXF1aXJlKCcuL2xpYi9nZm0tY29udmVydGVycycpXG52YXIgSHRtbFBhcnNlciA9IHJlcXVpcmUoJy4vbGliL2h0bWwtcGFyc2VyJylcbnZhciBjb2xsYXBzZSA9IHJlcXVpcmUoJ2NvbGxhcHNlLXdoaXRlc3BhY2UnKVxuXG4vKlxuICogVXRpbGl0aWVzXG4gKi9cblxudmFyIGJsb2NrcyA9IFsnYWRkcmVzcycsICdhcnRpY2xlJywgJ2FzaWRlJywgJ2F1ZGlvJywgJ2Jsb2NrcXVvdGUnLCAnYm9keScsXG4gICdjYW52YXMnLCAnY2VudGVyJywgJ2RkJywgJ2RpcicsICdkaXYnLCAnZGwnLCAnZHQnLCAnZmllbGRzZXQnLCAnZmlnY2FwdGlvbicsXG4gICdmaWd1cmUnLCAnZm9vdGVyJywgJ2Zvcm0nLCAnZnJhbWVzZXQnLCAnaDEnLCAnaDInLCAnaDMnLCAnaDQnLCAnaDUnLCAnaDYnLFxuICAnaGVhZGVyJywgJ2hncm91cCcsICdocicsICdodG1sJywgJ2lzaW5kZXgnLCAnbGknLCAnbWFpbicsICdtZW51JywgJ25hdicsXG4gICdub2ZyYW1lcycsICdub3NjcmlwdCcsICdvbCcsICdvdXRwdXQnLCAncCcsICdwcmUnLCAnc2VjdGlvbicsICd0YWJsZScsXG4gICd0Ym9keScsICd0ZCcsICd0Zm9vdCcsICd0aCcsICd0aGVhZCcsICd0cicsICd1bCdcbl1cblxuZnVuY3Rpb24gaXNCbG9jayAobm9kZSkge1xuICByZXR1cm4gYmxvY2tzLmluZGV4T2Yobm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSAhPT0gLTFcbn1cblxudmFyIHZvaWRzID0gW1xuICAnYXJlYScsICdiYXNlJywgJ2JyJywgJ2NvbCcsICdjb21tYW5kJywgJ2VtYmVkJywgJ2hyJywgJ2ltZycsICdpbnB1dCcsXG4gICdrZXlnZW4nLCAnbGluaycsICdtZXRhJywgJ3BhcmFtJywgJ3NvdXJjZScsICd0cmFjaycsICd3YnInXG5dXG5cbmZ1bmN0aW9uIGlzVm9pZCAobm9kZSkge1xuICByZXR1cm4gdm9pZHMuaW5kZXhPZihub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkpICE9PSAtMVxufVxuXG5mdW5jdGlvbiBodG1sVG9Eb20gKHN0cmluZykge1xuICB2YXIgdHJlZSA9IG5ldyBIdG1sUGFyc2VyKCkucGFyc2VGcm9tU3RyaW5nKHN0cmluZywgJ3RleHQvaHRtbCcpXG4gIGNvbGxhcHNlKHRyZWUuZG9jdW1lbnRFbGVtZW50LCBpc0Jsb2NrKVxuICByZXR1cm4gdHJlZVxufVxuXG4vKlxuICogRmxhdHRlbnMgRE9NIHRyZWUgaW50byBzaW5nbGUgYXJyYXlcbiAqL1xuXG5mdW5jdGlvbiBiZnNPcmRlciAobm9kZSkge1xuICB2YXIgaW5xdWV1ZSA9IFtub2RlXVxuICB2YXIgb3V0cXVldWUgPSBbXVxuICB2YXIgZWxlbVxuICB2YXIgY2hpbGRyZW5cbiAgdmFyIGlcblxuICB3aGlsZSAoaW5xdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgZWxlbSA9IGlucXVldWUuc2hpZnQoKVxuICAgIG91dHF1ZXVlLnB1c2goZWxlbSlcbiAgICBjaGlsZHJlbiA9IGVsZW0uY2hpbGROb2Rlc1xuICAgIGZvciAoaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGNoaWxkcmVuW2ldLm5vZGVUeXBlID09PSAxKSBpbnF1ZXVlLnB1c2goY2hpbGRyZW5baV0pXG4gICAgfVxuICB9XG4gIG91dHF1ZXVlLnNoaWZ0KClcbiAgcmV0dXJuIG91dHF1ZXVlXG59XG5cbi8qXG4gKiBDb250cnVjdHMgYSBNYXJrZG93biBzdHJpbmcgb2YgcmVwbGFjZW1lbnQgdGV4dCBmb3IgYSBnaXZlbiBub2RlXG4gKi9cblxuZnVuY3Rpb24gZ2V0Q29udGVudCAobm9kZSkge1xuICB2YXIgdGV4dCA9ICcnXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKG5vZGUuY2hpbGROb2Rlc1tpXS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgdGV4dCArPSBub2RlLmNoaWxkTm9kZXNbaV0uX3JlcGxhY2VtZW50XG4gICAgfSBlbHNlIGlmIChub2RlLmNoaWxkTm9kZXNbaV0ubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgIHRleHQgKz0gbm9kZS5jaGlsZE5vZGVzW2ldLmRhdGFcbiAgICB9IGVsc2UgY29udGludWVcbiAgfVxuICByZXR1cm4gdGV4dFxufVxuXG4vKlxuICogUmV0dXJucyB0aGUgSFRNTCBzdHJpbmcgb2YgYW4gZWxlbWVudCB3aXRoIGl0cyBjb250ZW50cyBjb252ZXJ0ZWRcbiAqL1xuXG5mdW5jdGlvbiBvdXRlciAobm9kZSwgY29udGVudCkge1xuICByZXR1cm4gbm9kZS5jbG9uZU5vZGUoZmFsc2UpLm91dGVySFRNTC5yZXBsYWNlKCc+PCcsICc+JyArIGNvbnRlbnQgKyAnPCcpXG59XG5cbmZ1bmN0aW9uIGNhbkNvbnZlcnQgKG5vZGUsIGZpbHRlcikge1xuICBpZiAodHlwZW9mIGZpbHRlciA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZmlsdGVyID09PSBub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKClcbiAgfVxuICBpZiAoQXJyYXkuaXNBcnJheShmaWx0ZXIpKSB7XG4gICAgcmV0dXJuIGZpbHRlci5pbmRleE9mKG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSkgIT09IC0xXG4gIH0gZWxzZSBpZiAodHlwZW9mIGZpbHRlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBmaWx0ZXIuY2FsbCh0b01hcmtkb3duLCBub2RlKVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2BmaWx0ZXJgIG5lZWRzIHRvIGJlIGEgc3RyaW5nLCBhcnJheSwgb3IgZnVuY3Rpb24nKVxuICB9XG59XG5cbmZ1bmN0aW9uIGlzRmxhbmtlZEJ5V2hpdGVzcGFjZSAoc2lkZSwgbm9kZSkge1xuICB2YXIgc2libGluZ1xuICB2YXIgcmVnRXhwXG4gIHZhciBpc0ZsYW5rZWRcblxuICBpZiAoc2lkZSA9PT0gJ2xlZnQnKSB7XG4gICAgc2libGluZyA9IG5vZGUucHJldmlvdXNTaWJsaW5nXG4gICAgcmVnRXhwID0gLyAkL1xuICB9IGVsc2Uge1xuICAgIHNpYmxpbmcgPSBub2RlLm5leHRTaWJsaW5nXG4gICAgcmVnRXhwID0gL14gL1xuICB9XG5cbiAgaWYgKHNpYmxpbmcpIHtcbiAgICBpZiAoc2libGluZy5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgaXNGbGFua2VkID0gcmVnRXhwLnRlc3Qoc2libGluZy5ub2RlVmFsdWUpXG4gICAgfSBlbHNlIGlmIChzaWJsaW5nLm5vZGVUeXBlID09PSAxICYmICFpc0Jsb2NrKHNpYmxpbmcpKSB7XG4gICAgICBpc0ZsYW5rZWQgPSByZWdFeHAudGVzdChzaWJsaW5nLnRleHRDb250ZW50KVxuICAgIH1cbiAgfVxuICByZXR1cm4gaXNGbGFua2VkXG59XG5cbmZ1bmN0aW9uIGZsYW5raW5nV2hpdGVzcGFjZSAobm9kZSwgY29udGVudCkge1xuICB2YXIgbGVhZGluZyA9ICcnXG4gIHZhciB0cmFpbGluZyA9ICcnXG5cbiAgaWYgKCFpc0Jsb2NrKG5vZGUpKSB7XG4gICAgdmFyIGhhc0xlYWRpbmcgPSAvXlsgXFxyXFxuXFx0XS8udGVzdChjb250ZW50KVxuICAgIHZhciBoYXNUcmFpbGluZyA9IC9bIFxcclxcblxcdF0kLy50ZXN0KGNvbnRlbnQpXG5cbiAgICBpZiAoaGFzTGVhZGluZyAmJiAhaXNGbGFua2VkQnlXaGl0ZXNwYWNlKCdsZWZ0Jywgbm9kZSkpIHtcbiAgICAgIGxlYWRpbmcgPSAnICdcbiAgICB9XG4gICAgaWYgKGhhc1RyYWlsaW5nICYmICFpc0ZsYW5rZWRCeVdoaXRlc3BhY2UoJ3JpZ2h0Jywgbm9kZSkpIHtcbiAgICAgIHRyYWlsaW5nID0gJyAnXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgbGVhZGluZzogbGVhZGluZywgdHJhaWxpbmc6IHRyYWlsaW5nIH1cbn1cblxuLypcbiAqIEZpbmRzIGEgTWFya2Rvd24gY29udmVydGVyLCBnZXRzIHRoZSByZXBsYWNlbWVudCwgYW5kIHNldHMgaXQgb25cbiAqIGBfcmVwbGFjZW1lbnRgXG4gKi9cblxuZnVuY3Rpb24gcHJvY2VzcyAobm9kZSkge1xuICB2YXIgcmVwbGFjZW1lbnRcbiAgdmFyIGNvbnRlbnQgPSBnZXRDb250ZW50KG5vZGUpXG5cbiAgLy8gUmVtb3ZlIGJsYW5rIG5vZGVzXG4gIGlmICghaXNWb2lkKG5vZGUpICYmICEvQXxUSHxURC8udGVzdChub2RlLm5vZGVOYW1lKSAmJiAvXlxccyokL2kudGVzdChjb250ZW50KSkge1xuICAgIG5vZGUuX3JlcGxhY2VtZW50ID0gJydcbiAgICByZXR1cm5cbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY29udmVydGVycy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBjb252ZXJ0ZXIgPSBjb252ZXJ0ZXJzW2ldXG5cbiAgICBpZiAoY2FuQ29udmVydChub2RlLCBjb252ZXJ0ZXIuZmlsdGVyKSkge1xuICAgICAgaWYgKHR5cGVvZiBjb252ZXJ0ZXIucmVwbGFjZW1lbnQgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICAnYHJlcGxhY2VtZW50YCBuZWVkcyB0byBiZSBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIHN0cmluZydcbiAgICAgICAgKVxuICAgICAgfVxuXG4gICAgICB2YXIgd2hpdGVzcGFjZSA9IGZsYW5raW5nV2hpdGVzcGFjZShub2RlLCBjb250ZW50KVxuXG4gICAgICBpZiAod2hpdGVzcGFjZS5sZWFkaW5nIHx8IHdoaXRlc3BhY2UudHJhaWxpbmcpIHtcbiAgICAgICAgY29udGVudCA9IGNvbnRlbnQudHJpbSgpXG4gICAgICB9XG4gICAgICByZXBsYWNlbWVudCA9IHdoaXRlc3BhY2UubGVhZGluZyArXG4gICAgICAgIGNvbnZlcnRlci5yZXBsYWNlbWVudC5jYWxsKHRvTWFya2Rvd24sIGNvbnRlbnQsIG5vZGUpICtcbiAgICAgICAgd2hpdGVzcGFjZS50cmFpbGluZ1xuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBub2RlLl9yZXBsYWNlbWVudCA9IHJlcGxhY2VtZW50XG59XG5cbnRvTWFya2Rvd24gPSBmdW5jdGlvbiAoaW5wdXQsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cblxuICBpZiAodHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoaW5wdXQgKyAnIGlzIG5vdCBhIHN0cmluZycpXG4gIH1cblxuICBpZiAoaW5wdXQgPT09ICcnKSB7XG4gICAgcmV0dXJuICcnXG4gIH1cblxuICAvLyBFc2NhcGUgcG90ZW50aWFsIG9sIHRyaWdnZXJzXG4gIGlucHV0ID0gaW5wdXQucmVwbGFjZSgvKFxcZCspXFwuIC9nLCAnJDFcXFxcLiAnKVxuXG4gIHZhciBjbG9uZSA9IGh0bWxUb0RvbShpbnB1dCkuYm9keVxuICB2YXIgbm9kZXMgPSBiZnNPcmRlcihjbG9uZSlcbiAgdmFyIG91dHB1dFxuXG4gIGNvbnZlcnRlcnMgPSBtZENvbnZlcnRlcnMuc2xpY2UoMClcbiAgaWYgKG9wdGlvbnMuZ2ZtKSB7XG4gICAgY29udmVydGVycyA9IGdmbUNvbnZlcnRlcnMuY29uY2F0KGNvbnZlcnRlcnMpXG4gIH1cblxuICBpZiAob3B0aW9ucy5jb252ZXJ0ZXJzKSB7XG4gICAgY29udmVydGVycyA9IG9wdGlvbnMuY29udmVydGVycy5jb25jYXQoY29udmVydGVycylcbiAgfVxuXG4gIC8vIFByb2Nlc3MgdGhyb3VnaCBub2RlcyBpbiByZXZlcnNlIChzbyBkZWVwZXN0IGNoaWxkIGVsZW1lbnRzIGFyZSBmaXJzdCkuXG4gIGZvciAodmFyIGkgPSBub2Rlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIHByb2Nlc3Mobm9kZXNbaV0pXG4gIH1cbiAgb3V0cHV0ID0gZ2V0Q29udGVudChjbG9uZSlcblxuICByZXR1cm4gb3V0cHV0LnJlcGxhY2UoL15bXFx0XFxyXFxuXSt8W1xcdFxcclxcblxcc10rJC9nLCAnJylcbiAgICAucmVwbGFjZSgvXFxuXFxzK1xcbi9nLCAnXFxuXFxuJylcbiAgICAucmVwbGFjZSgvXFxuezMsfS9nLCAnXFxuXFxuJylcbn1cblxudG9NYXJrZG93bi5pc0Jsb2NrID0gaXNCbG9ja1xudG9NYXJrZG93bi5pc1ZvaWQgPSBpc1ZvaWRcbnRvTWFya2Rvd24ub3V0ZXIgPSBvdXRlclxuXG5tb2R1bGUuZXhwb3J0cyA9IHRvTWFya2Rvd25cblxufSx7XCIuL2xpYi9nZm0tY29udmVydGVyc1wiOjIsXCIuL2xpYi9odG1sLXBhcnNlclwiOjMsXCIuL2xpYi9tZC1jb252ZXJ0ZXJzXCI6NCxcImNvbGxhcHNlLXdoaXRlc3BhY2VcIjo3fV0sMjpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxuZnVuY3Rpb24gY2VsbCAoY29udGVudCwgbm9kZSkge1xuICB2YXIgaW5kZXggPSBBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKG5vZGUucGFyZW50Tm9kZS5jaGlsZE5vZGVzLCBub2RlKVxuICB2YXIgcHJlZml4ID0gJyAnXG4gIGlmIChpbmRleCA9PT0gMCkgcHJlZml4ID0gJ3wgJ1xuICByZXR1cm4gcHJlZml4ICsgY29udGVudCArICcgfCdcbn1cblxudmFyIGhpZ2hsaWdodFJlZ0V4ID0gL2hpZ2hsaWdodCBoaWdobGlnaHQtKFxcUyspL1xuXG5tb2R1bGUuZXhwb3J0cyA9IFtcbiAge1xuICAgIGZpbHRlcjogJ2JyJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdcXG4nXG4gICAgfVxuICB9LFxuICB7XG4gICAgZmlsdGVyOiBbJ2RlbCcsICdzJywgJ3N0cmlrZSddLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICd+ficgKyBjb250ZW50ICsgJ35+J1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgcmV0dXJuIG5vZGUudHlwZSA9PT0gJ2NoZWNrYm94JyAmJiBub2RlLnBhcmVudE5vZGUubm9kZU5hbWUgPT09ICdMSSdcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgcmV0dXJuIChub2RlLmNoZWNrZWQgPyAnW3hdJyA6ICdbIF0nKSArICcgJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBbJ3RoJywgJ3RkJ10sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gY2VsbChjb250ZW50LCBub2RlKVxuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAndHInLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgdmFyIGJvcmRlckNlbGxzID0gJydcbiAgICAgIHZhciBhbGlnbk1hcCA9IHsgbGVmdDogJzotLScsIHJpZ2h0OiAnLS06JywgY2VudGVyOiAnOi06JyB9XG5cbiAgICAgIGlmIChub2RlLnBhcmVudE5vZGUubm9kZU5hbWUgPT09ICdUSEVBRCcpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgYWxpZ24gPSBub2RlLmNoaWxkTm9kZXNbaV0uYXR0cmlidXRlcy5hbGlnblxuICAgICAgICAgIHZhciBib3JkZXIgPSAnLS0tJ1xuXG4gICAgICAgICAgaWYgKGFsaWduKSBib3JkZXIgPSBhbGlnbk1hcFthbGlnbi52YWx1ZV0gfHwgYm9yZGVyXG5cbiAgICAgICAgICBib3JkZXJDZWxscyArPSBjZWxsKGJvcmRlciwgbm9kZS5jaGlsZE5vZGVzW2ldKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gJ1xcbicgKyBjb250ZW50ICsgKGJvcmRlckNlbGxzID8gJ1xcbicgKyBib3JkZXJDZWxscyA6ICcnKVxuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAndGFibGUnLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICdcXG5cXG4nICsgY29udGVudCArICdcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsndGhlYWQnLCAndGJvZHknLCAndGZvb3QnXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiBjb250ZW50XG4gICAgfVxuICB9LFxuXG4gIC8vIEZlbmNlZCBjb2RlIGJsb2Nrc1xuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgcmV0dXJuIG5vZGUubm9kZU5hbWUgPT09ICdQUkUnICYmXG4gICAgICBub2RlLmZpcnN0Q2hpbGQgJiZcbiAgICAgIG5vZGUuZmlyc3RDaGlsZC5ub2RlTmFtZSA9PT0gJ0NPREUnXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHJldHVybiAnXFxuXFxuYGBgXFxuJyArIG5vZGUuZmlyc3RDaGlsZC50ZXh0Q29udGVudCArICdcXG5gYGBcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIC8vIFN5bnRheC1oaWdobGlnaHRlZCBjb2RlIGJsb2Nrc1xuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgcmV0dXJuIG5vZGUubm9kZU5hbWUgPT09ICdQUkUnICYmXG4gICAgICBub2RlLnBhcmVudE5vZGUubm9kZU5hbWUgPT09ICdESVYnICYmXG4gICAgICBoaWdobGlnaHRSZWdFeC50ZXN0KG5vZGUucGFyZW50Tm9kZS5jbGFzc05hbWUpXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHZhciBsYW5ndWFnZSA9IG5vZGUucGFyZW50Tm9kZS5jbGFzc05hbWUubWF0Y2goaGlnaGxpZ2h0UmVnRXgpWzFdXG4gICAgICByZXR1cm4gJ1xcblxcbmBgYCcgKyBsYW5ndWFnZSArICdcXG4nICsgbm9kZS50ZXh0Q29udGVudCArICdcXG5gYGBcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ0RJVicgJiZcbiAgICAgIGhpZ2hsaWdodFJlZ0V4LnRlc3Qobm9kZS5jbGFzc05hbWUpXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnXFxuXFxuJyArIGNvbnRlbnQgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfVxuXVxuXG59LHt9XSwzOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiBTZXQgdXAgd2luZG93IGZvciBOb2RlLmpzXG4gKi9cblxudmFyIF93aW5kb3cgPSAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzKVxuXG4vKlxuICogUGFyc2luZyBIVE1MIHN0cmluZ3NcbiAqL1xuXG5mdW5jdGlvbiBjYW5QYXJzZUh0bWxOYXRpdmVseSAoKSB7XG4gIHZhciBQYXJzZXIgPSBfd2luZG93LkRPTVBhcnNlclxuICB2YXIgY2FuUGFyc2UgPSBmYWxzZVxuXG4gIC8vIEFkYXB0ZWQgZnJvbSBodHRwczovL2dpc3QuZ2l0aHViLmNvbS8xMTI5MDMxXG4gIC8vIEZpcmVmb3gvT3BlcmEvSUUgdGhyb3cgZXJyb3JzIG9uIHVuc3VwcG9ydGVkIHR5cGVzXG4gIHRyeSB7XG4gICAgLy8gV2ViS2l0IHJldHVybnMgbnVsbCBvbiB1bnN1cHBvcnRlZCB0eXBlc1xuICAgIGlmIChuZXcgUGFyc2VyKCkucGFyc2VGcm9tU3RyaW5nKCcnLCAndGV4dC9odG1sJykpIHtcbiAgICAgIGNhblBhcnNlID0gdHJ1ZVxuICAgIH1cbiAgfSBjYXRjaCAoZSkge31cblxuICByZXR1cm4gY2FuUGFyc2Vcbn1cblxuZnVuY3Rpb24gY3JlYXRlSHRtbFBhcnNlciAoKSB7XG4gIHZhciBQYXJzZXIgPSBmdW5jdGlvbiAoKSB7fVxuXG4gIC8vIEZvciBOb2RlLmpzIGVudmlyb25tZW50c1xuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgIHZhciBqc2RvbSA9IHJlcXVpcmUoJ2pzZG9tJylcbiAgICBQYXJzZXIucHJvdG90eXBlLnBhcnNlRnJvbVN0cmluZyA9IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgIHJldHVybiBqc2RvbS5qc2RvbShzdHJpbmcsIHtcbiAgICAgICAgZmVhdHVyZXM6IHtcbiAgICAgICAgICBGZXRjaEV4dGVybmFsUmVzb3VyY2VzOiBbXSxcbiAgICAgICAgICBQcm9jZXNzRXh0ZXJuYWxSZXNvdXJjZXM6IGZhbHNlXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmICghc2hvdWxkVXNlQWN0aXZlWCgpKSB7XG4gICAgICBQYXJzZXIucHJvdG90eXBlLnBhcnNlRnJvbVN0cmluZyA9IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgdmFyIGRvYyA9IGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCgnJylcbiAgICAgICAgZG9jLm9wZW4oKVxuICAgICAgICBkb2Mud3JpdGUoc3RyaW5nKVxuICAgICAgICBkb2MuY2xvc2UoKVxuICAgICAgICByZXR1cm4gZG9jXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIFBhcnNlci5wcm90b3R5cGUucGFyc2VGcm9tU3RyaW5nID0gZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICB2YXIgZG9jID0gbmV3IHdpbmRvdy5BY3RpdmVYT2JqZWN0KCdodG1sZmlsZScpXG4gICAgICAgIGRvYy5kZXNpZ25Nb2RlID0gJ29uJyAvLyBkaXNhYmxlIG9uLXBhZ2Ugc2NyaXB0c1xuICAgICAgICBkb2Mub3BlbigpXG4gICAgICAgIGRvYy53cml0ZShzdHJpbmcpXG4gICAgICAgIGRvYy5jbG9zZSgpXG4gICAgICAgIHJldHVybiBkb2NcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIFBhcnNlclxufVxuXG5mdW5jdGlvbiBzaG91bGRVc2VBY3RpdmVYICgpIHtcbiAgdmFyIHVzZUFjdGl2ZVggPSBmYWxzZVxuXG4gIHRyeSB7XG4gICAgZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCcnKS5vcGVuKClcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmICh3aW5kb3cuQWN0aXZlWE9iamVjdCkgdXNlQWN0aXZlWCA9IHRydWVcbiAgfVxuXG4gIHJldHVybiB1c2VBY3RpdmVYXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2FuUGFyc2VIdG1sTmF0aXZlbHkoKSA/IF93aW5kb3cuRE9NUGFyc2VyIDogY3JlYXRlSHRtbFBhcnNlcigpXG5cbn0se1wianNkb21cIjo2fV0sNDpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBbXG4gIHtcbiAgICBmaWx0ZXI6ICdwJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnXFxuXFxuJyArIGNvbnRlbnQgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAnYnInLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJyAgXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBbJ2gxJywgJ2gyJywgJ2gzJywgJ2g0JywgJ2g1JywgJ2g2J10sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICB2YXIgaExldmVsID0gbm9kZS5ub2RlTmFtZS5jaGFyQXQoMSlcbiAgICAgIHZhciBoUHJlZml4ID0gJydcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaExldmVsOyBpKyspIHtcbiAgICAgICAgaFByZWZpeCArPSAnIydcbiAgICAgIH1cbiAgICAgIHJldHVybiAnXFxuXFxuJyArIGhQcmVmaXggKyAnICcgKyBjb250ZW50ICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ2hyJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdcXG5cXG4qICogKlxcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogWydlbScsICdpJ10sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJ18nICsgY29udGVudCArICdfJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBbJ3N0cm9uZycsICdiJ10sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJyoqJyArIGNvbnRlbnQgKyAnKionXG4gICAgfVxuICB9LFxuXG4gIC8vIElubGluZSBjb2RlXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICB2YXIgaGFzU2libGluZ3MgPSBub2RlLnByZXZpb3VzU2libGluZyB8fCBub2RlLm5leHRTaWJsaW5nXG4gICAgICB2YXIgaXNDb2RlQmxvY2sgPSBub2RlLnBhcmVudE5vZGUubm9kZU5hbWUgPT09ICdQUkUnICYmICFoYXNTaWJsaW5nc1xuXG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ0NPREUnICYmICFpc0NvZGVCbG9ja1xuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJ2AnICsgY29udGVudCArICdgJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgcmV0dXJuIG5vZGUubm9kZU5hbWUgPT09ICdBJyAmJiBub2RlLmdldEF0dHJpYnV0ZSgnaHJlZicpXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHZhciB0aXRsZVBhcnQgPSBub2RlLnRpdGxlID8gJyBcIicgKyBub2RlLnRpdGxlICsgJ1wiJyA6ICcnXG4gICAgICByZXR1cm4gJ1snICsgY29udGVudCArICddKCcgKyBub2RlLmdldEF0dHJpYnV0ZSgnaHJlZicpICsgdGl0bGVQYXJ0ICsgJyknXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICdpbWcnLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgdmFyIGFsdCA9IG5vZGUuYWx0IHx8ICcnXG4gICAgICB2YXIgc3JjID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ3NyYycpIHx8ICcnXG4gICAgICB2YXIgdGl0bGUgPSBub2RlLnRpdGxlIHx8ICcnXG4gICAgICB2YXIgdGl0bGVQYXJ0ID0gdGl0bGUgPyAnIFwiJyArIHRpdGxlICsgJ1wiJyA6ICcnXG4gICAgICByZXR1cm4gc3JjID8gJyFbJyArIGFsdCArICddJyArICcoJyArIHNyYyArIHRpdGxlUGFydCArICcpJyA6ICcnXG4gICAgfVxuICB9LFxuXG4gIC8vIENvZGUgYmxvY2tzXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ1BSRScgJiYgbm9kZS5maXJzdENoaWxkLm5vZGVOYW1lID09PSAnQ09ERSdcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgcmV0dXJuICdcXG5cXG4gICAgJyArIG5vZGUuZmlyc3RDaGlsZC50ZXh0Q29udGVudC5yZXBsYWNlKC9cXG4vZywgJ1xcbiAgICAnKSArICdcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICdibG9ja3F1b3RlJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIGNvbnRlbnQgPSBjb250ZW50LnRyaW0oKVxuICAgICAgY29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvXFxuezMsfS9nLCAnXFxuXFxuJylcbiAgICAgIGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoL14vZ20sICc+ICcpXG4gICAgICByZXR1cm4gJ1xcblxcbicgKyBjb250ZW50ICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ2xpJyxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoL15cXHMrLywgJycpLnJlcGxhY2UoL1xcbi9nbSwgJ1xcbiAgICAnKVxuICAgICAgdmFyIHByZWZpeCA9ICcqICAgJ1xuICAgICAgdmFyIHBhcmVudCA9IG5vZGUucGFyZW50Tm9kZVxuICAgICAgdmFyIGluZGV4ID0gQXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChwYXJlbnQuY2hpbGRyZW4sIG5vZGUpICsgMVxuXG4gICAgICBwcmVmaXggPSAvb2wvaS50ZXN0KHBhcmVudC5ub2RlTmFtZSkgPyBpbmRleCArICcuICAnIDogJyogICAnXG4gICAgICByZXR1cm4gcHJlZml4ICsgY29udGVudFxuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBbJ3VsJywgJ29sJ10sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICB2YXIgc3RyaW5ncyA9IFtdXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzdHJpbmdzLnB1c2gobm9kZS5jaGlsZE5vZGVzW2ldLl9yZXBsYWNlbWVudClcbiAgICAgIH1cblxuICAgICAgaWYgKC9saS9pLnRlc3Qobm9kZS5wYXJlbnROb2RlLm5vZGVOYW1lKSkge1xuICAgICAgICByZXR1cm4gJ1xcbicgKyBzdHJpbmdzLmpvaW4oJ1xcbicpXG4gICAgICB9XG4gICAgICByZXR1cm4gJ1xcblxcbicgKyBzdHJpbmdzLmpvaW4oJ1xcbicpICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiB0aGlzLmlzQmxvY2sobm9kZSlcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgcmV0dXJuICdcXG5cXG4nICsgdGhpcy5vdXRlcihub2RlLCBjb250ZW50KSArICdcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIC8vIEFueXRoaW5nIGVsc2UhXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHJldHVybiB0aGlzLm91dGVyKG5vZGUsIGNvbnRlbnQpXG4gICAgfVxuICB9XG5dXG5cbn0se31dLDU6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4gKiBUaGlzIGZpbGUgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgZnJvbSBgYnVpbGQuanNgLlxuICogRG8gbm90IG1hbnVhbGx5IGVkaXQuXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBbXG4gIFwiYWRkcmVzc1wiLFxuICBcImFydGljbGVcIixcbiAgXCJhc2lkZVwiLFxuICBcImF1ZGlvXCIsXG4gIFwiYmxvY2txdW90ZVwiLFxuICBcImNhbnZhc1wiLFxuICBcImRkXCIsXG4gIFwiZGl2XCIsXG4gIFwiZGxcIixcbiAgXCJmaWVsZHNldFwiLFxuICBcImZpZ2NhcHRpb25cIixcbiAgXCJmaWd1cmVcIixcbiAgXCJmb290ZXJcIixcbiAgXCJmb3JtXCIsXG4gIFwiaDFcIixcbiAgXCJoMlwiLFxuICBcImgzXCIsXG4gIFwiaDRcIixcbiAgXCJoNVwiLFxuICBcImg2XCIsXG4gIFwiaGVhZGVyXCIsXG4gIFwiaGdyb3VwXCIsXG4gIFwiaHJcIixcbiAgXCJtYWluXCIsXG4gIFwibmF2XCIsXG4gIFwibm9zY3JpcHRcIixcbiAgXCJvbFwiLFxuICBcIm91dHB1dFwiLFxuICBcInBcIixcbiAgXCJwcmVcIixcbiAgXCJzZWN0aW9uXCIsXG4gIFwidGFibGVcIixcbiAgXCJ0Zm9vdFwiLFxuICBcInVsXCIsXG4gIFwidmlkZW9cIlxuXTtcblxufSx7fV0sNjpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG5cbn0se31dLDc6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdm9pZEVsZW1lbnRzID0gcmVxdWlyZSgndm9pZC1lbGVtZW50cycpO1xuT2JqZWN0LmtleXModm9pZEVsZW1lbnRzKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gIHZvaWRFbGVtZW50c1tuYW1lLnRvVXBwZXJDYXNlKCldID0gMTtcbn0pO1xuXG52YXIgYmxvY2tFbGVtZW50cyA9IHt9O1xucmVxdWlyZSgnYmxvY2stZWxlbWVudHMnKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gIGJsb2NrRWxlbWVudHNbbmFtZS50b1VwcGVyQ2FzZSgpXSA9IDE7XG59KTtcblxuLyoqXG4gKiBpc0Jsb2NrRWxlbShub2RlKSBkZXRlcm1pbmVzIGlmIHRoZSBnaXZlbiBub2RlIGlzIGEgYmxvY2sgZWxlbWVudC5cbiAqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGVcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzQmxvY2tFbGVtKG5vZGUpIHtcbiAgcmV0dXJuICEhKG5vZGUgJiYgYmxvY2tFbGVtZW50c1tub2RlLm5vZGVOYW1lXSk7XG59XG5cbi8qKlxuICogaXNWb2lkKG5vZGUpIGRldGVybWluZXMgaWYgdGhlIGdpdmVuIG5vZGUgaXMgYSB2b2lkIGVsZW1lbnQuXG4gKlxuICogQHBhcmFtIHtOb2RlfSBub2RlXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5mdW5jdGlvbiBpc1ZvaWQobm9kZSkge1xuICByZXR1cm4gISEobm9kZSAmJiB2b2lkRWxlbWVudHNbbm9kZS5ub2RlTmFtZV0pO1xufVxuXG4vKipcbiAqIHdoaXRlc3BhY2UoZWxlbSBbLCBpc0Jsb2NrXSkgcmVtb3ZlcyBleHRyYW5lb3VzIHdoaXRlc3BhY2UgZnJvbSBhblxuICogdGhlIGdpdmVuIGVsZW1lbnQuIFRoZSBmdW5jdGlvbiBpc0Jsb2NrIG1heSBvcHRpb25hbGx5IGJlIHBhc3NlZCBpblxuICogdG8gZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IGFuIGVsZW1lbnQgaXMgYSBibG9jayBlbGVtZW50OyBpZiBub25lXG4gKiBpcyBwcm92aWRlZCwgZGVmYXVsdHMgdG8gdXNpbmcgdGhlIGxpc3Qgb2YgYmxvY2sgZWxlbWVudHMgcHJvdmlkZWRcbiAqIGJ5IHRoZSBgYmxvY2stZWxlbWVudHNgIG1vZHVsZS5cbiAqXG4gKiBAcGFyYW0ge05vZGV9IGVsZW1cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGJsb2NrVGVzdFxuICovXG5mdW5jdGlvbiBjb2xsYXBzZVdoaXRlc3BhY2UoZWxlbSwgaXNCbG9jaykge1xuICBpZiAoIWVsZW0uZmlyc3RDaGlsZCB8fCBlbGVtLm5vZGVOYW1lID09PSAnUFJFJykgcmV0dXJuO1xuXG4gIGlmICh0eXBlb2YgaXNCbG9jayAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGlzQmxvY2sgPSBpc0Jsb2NrRWxlbTtcbiAgfVxuXG4gIHZhciBwcmV2VGV4dCA9IG51bGw7XG4gIHZhciBwcmV2Vm9pZCA9IGZhbHNlO1xuXG4gIHZhciBwcmV2ID0gbnVsbDtcbiAgdmFyIG5vZGUgPSBuZXh0KHByZXYsIGVsZW0pO1xuXG4gIHdoaWxlIChub2RlICE9PSBlbGVtKSB7XG4gICAgaWYgKG5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgIC8vIE5vZGUuVEVYVF9OT0RFXG4gICAgICB2YXIgdGV4dCA9IG5vZGUuZGF0YS5yZXBsYWNlKC9bIFxcclxcblxcdF0rL2csICcgJyk7XG5cbiAgICAgIGlmICgoIXByZXZUZXh0IHx8IC8gJC8udGVzdChwcmV2VGV4dC5kYXRhKSkgJiYgIXByZXZWb2lkICYmIHRleHRbMF0gPT09ICcgJykge1xuICAgICAgICB0ZXh0ID0gdGV4dC5zdWJzdHIoMSk7XG4gICAgICB9XG5cbiAgICAgIC8vIGB0ZXh0YCBtaWdodCBiZSBlbXB0eSBhdCB0aGlzIHBvaW50LlxuICAgICAgaWYgKCF0ZXh0KSB7XG4gICAgICAgIG5vZGUgPSByZW1vdmUobm9kZSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBub2RlLmRhdGEgPSB0ZXh0O1xuICAgICAgcHJldlRleHQgPSBub2RlO1xuICAgIH0gZWxzZSBpZiAobm9kZS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgLy8gTm9kZS5FTEVNRU5UX05PREVcbiAgICAgIGlmIChpc0Jsb2NrKG5vZGUpIHx8IG5vZGUubm9kZU5hbWUgPT09ICdCUicpIHtcbiAgICAgICAgaWYgKHByZXZUZXh0KSB7XG4gICAgICAgICAgcHJldlRleHQuZGF0YSA9IHByZXZUZXh0LmRhdGEucmVwbGFjZSgvICQvLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICBwcmV2VGV4dCA9IG51bGw7XG4gICAgICAgIHByZXZWb2lkID0gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKGlzVm9pZChub2RlKSkge1xuICAgICAgICAvLyBBdm9pZCB0cmltbWluZyBzcGFjZSBhcm91bmQgbm9uLWJsb2NrLCBub24tQlIgdm9pZCBlbGVtZW50cy5cbiAgICAgICAgcHJldlRleHQgPSBudWxsO1xuICAgICAgICBwcmV2Vm9pZCA9IHRydWU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIG5vZGUgPSByZW1vdmUobm9kZSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICB2YXIgbmV4dE5vZGUgPSBuZXh0KHByZXYsIG5vZGUpO1xuICAgIHByZXYgPSBub2RlO1xuICAgIG5vZGUgPSBuZXh0Tm9kZTtcbiAgfVxuXG4gIGlmIChwcmV2VGV4dCkge1xuICAgIHByZXZUZXh0LmRhdGEgPSBwcmV2VGV4dC5kYXRhLnJlcGxhY2UoLyAkLywgJycpO1xuICAgIGlmICghcHJldlRleHQuZGF0YSkge1xuICAgICAgcmVtb3ZlKHByZXZUZXh0KTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiByZW1vdmUobm9kZSkgcmVtb3ZlcyB0aGUgZ2l2ZW4gbm9kZSBmcm9tIHRoZSBET00gYW5kIHJldHVybnMgdGhlXG4gKiBuZXh0IG5vZGUgaW4gdGhlIHNlcXVlbmNlLlxuICpcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybiB7Tm9kZX0gbm9kZVxuICovXG5mdW5jdGlvbiByZW1vdmUobm9kZSkge1xuICB2YXIgbmV4dCA9IG5vZGUubmV4dFNpYmxpbmcgfHwgbm9kZS5wYXJlbnROb2RlO1xuXG4gIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcblxuICByZXR1cm4gbmV4dDtcbn1cblxuLyoqXG4gKiBuZXh0KHByZXYsIGN1cnJlbnQpIHJldHVybnMgdGhlIG5leHQgbm9kZSBpbiB0aGUgc2VxdWVuY2UsIGdpdmVuIHRoZVxuICogY3VycmVudCBhbmQgcHJldmlvdXMgbm9kZXMuXG4gKlxuICogQHBhcmFtIHtOb2RlfSBwcmV2XG4gKiBAcGFyYW0ge05vZGV9IGN1cnJlbnRcbiAqIEByZXR1cm4ge05vZGV9XG4gKi9cbmZ1bmN0aW9uIG5leHQocHJldiwgY3VycmVudCkge1xuICBpZiAocHJldiAmJiBwcmV2LnBhcmVudE5vZGUgPT09IGN1cnJlbnQgfHwgY3VycmVudC5ub2RlTmFtZSA9PT0gJ1BSRScpIHtcbiAgICByZXR1cm4gY3VycmVudC5uZXh0U2libGluZyB8fCBjdXJyZW50LnBhcmVudE5vZGU7XG4gIH1cblxuICByZXR1cm4gY3VycmVudC5maXJzdENoaWxkIHx8IGN1cnJlbnQubmV4dFNpYmxpbmcgfHwgY3VycmVudC5wYXJlbnROb2RlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbGxhcHNlV2hpdGVzcGFjZTtcblxufSx7XCJibG9jay1lbGVtZW50c1wiOjUsXCJ2b2lkLWVsZW1lbnRzXCI6OH1dLDg6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4gKiBUaGlzIGZpbGUgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgZnJvbSBgcHJlLXB1Ymxpc2guanNgLlxuICogRG8gbm90IG1hbnVhbGx5IGVkaXQuXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIFwiYXJlYVwiOiB0cnVlLFxuICBcImJhc2VcIjogdHJ1ZSxcbiAgXCJiclwiOiB0cnVlLFxuICBcImNvbFwiOiB0cnVlLFxuICBcImVtYmVkXCI6IHRydWUsXG4gIFwiaHJcIjogdHJ1ZSxcbiAgXCJpbWdcIjogdHJ1ZSxcbiAgXCJpbnB1dFwiOiB0cnVlLFxuICBcImtleWdlblwiOiB0cnVlLFxuICBcImxpbmtcIjogdHJ1ZSxcbiAgXCJtZW51aXRlbVwiOiB0cnVlLFxuICBcIm1ldGFcIjogdHJ1ZSxcbiAgXCJwYXJhbVwiOiB0cnVlLFxuICBcInNvdXJjZVwiOiB0cnVlLFxuICBcInRyYWNrXCI6IHRydWUsXG4gIFwid2JyXCI6IHRydWVcbn07XG5cbn0se31dfSx7fSxbMV0pKDEpXG59KTsiLCIvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIGJvb3RzdHJhcC1tYXJrZG93bi5qcyB2Mi4xMC4wXG4gKiBodHRwOi8vZ2l0aHViLmNvbS90b29wYXkvYm9vdHN0cmFwLW1hcmtkb3duXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDEzLTIwMTYgVGF1ZmFuIEFkaXR5YVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG4oZnVuY3Rpb24oZmFjdG9yeSl7XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIC8vUmVxdWlyZUpTXG4gICAgICAgIGRlZmluZShbXCJqcXVlcnlcIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIC8vQmFja2JvbmUuanNcbiAgICAgICAgZmFjdG9yeShyZXF1aXJlKCdqcXVlcnknKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy9KcXVlcnkgcGx1Z2luXG4gICAgICAgIGZhY3RvcnkoalF1ZXJ5KTtcbiAgICB9XG59KGZ1bmN0aW9uKCQpe1xuICBcInVzZSBzdHJpY3RcIjsgLy8ganNoaW50IDtfO1xuXG4gIC8qIE1BUktET1dOIENMQVNTIERFRklOSVRJT05cbiAgICogPT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuICB2YXIgTWFya2Rvd24gPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIC8vIEBUT0RPIDogcmVtb3ZlIHRoaXMgQkMgb24gbmV4dCBtYWpvciByZWxlYXNlXG4gICAgLy8gQHNlZSA6IGh0dHBzOi8vZ2l0aHViLmNvbS90b29wYXkvYm9vdHN0cmFwLW1hcmtkb3duL2lzc3Vlcy8xMDlcbiAgICB2YXIgb3B0cyA9IFsnYXV0b2ZvY3VzJywgJ3NhdmFibGUnLCAnaGlkZWFibGUnLCAnd2lkdGgnLCBcbiAgICAgICdoZWlnaHQnLCAncmVzaXplJywgJ2ljb25saWJyYXJ5JywgJ2xhbmd1YWdlJywgXG4gICAgICAnZm9vdGVyJywgJ2Z1bGxzY3JlZW4nLCAnaGlkZGVuQnV0dG9ucycsICdkaXNhYmxlZEJ1dHRvbnMnXTtcbiAgICAkLmVhY2gob3B0cyxmdW5jdGlvbihfLCBvcHQpe1xuICAgICAgaWYgKHR5cGVvZiAkKGVsZW1lbnQpLmRhdGEob3B0KSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgb3B0aW9ucyA9IHR5cGVvZiBvcHRpb25zID09ICdvYmplY3QnID8gb3B0aW9ucyA6IHt9XG4gICAgICAgIG9wdGlvbnNbb3B0XSA9ICQoZWxlbWVudCkuZGF0YShvcHQpXG4gICAgICB9XG4gICAgfSk7XG4gICAgLy8gRW5kIEJDXG5cbiAgICAvLyBDbGFzcyBQcm9wZXJ0aWVzXG4gICAgdGhpcy4kbnMgICAgICAgICAgID0gJ2Jvb3RzdHJhcC1tYXJrZG93bic7XG4gICAgdGhpcy4kZWxlbWVudCAgICAgID0gJChlbGVtZW50KTtcbiAgICB0aGlzLiRlZGl0YWJsZSAgICAgPSB7ZWw6bnVsbCwgdHlwZTpudWxsLGF0dHJLZXlzOltdLCBhdHRyVmFsdWVzOltdLCBjb250ZW50Om51bGx9O1xuICAgIHRoaXMuJG9wdGlvbnMgICAgICA9ICQuZXh0ZW5kKHRydWUsIHt9LCAkLmZuLm1hcmtkb3duLmRlZmF1bHRzLCBvcHRpb25zLCB0aGlzLiRlbGVtZW50LmRhdGEoJ29wdGlvbnMnKSk7XG4gICAgdGhpcy4kb2xkQ29udGVudCAgID0gbnVsbDtcbiAgICB0aGlzLiRpc1ByZXZpZXcgICAgPSBmYWxzZTtcbiAgICB0aGlzLiRpc0Z1bGxzY3JlZW4gPSBmYWxzZTtcbiAgICB0aGlzLiRlZGl0b3IgICAgICAgPSBudWxsO1xuICAgIHRoaXMuJHRleHRhcmVhICAgICA9IG51bGw7XG4gICAgdGhpcy4kaGFuZGxlciAgICAgID0gW107XG4gICAgdGhpcy4kY2FsbGJhY2sgICAgID0gW107XG4gICAgdGhpcy4kbmV4dFRhYiAgICAgID0gW107XG5cbiAgICB0aGlzLnNob3dFZGl0b3IoKTtcbiAgfTtcblxuICBNYXJrZG93bi5wcm90b3R5cGUgPSB7XG5cbiAgICBjb25zdHJ1Y3RvcjogTWFya2Rvd25cblxuICAsIF9fYWx0ZXJCdXR0b25zOiBmdW5jdGlvbihuYW1lLGFsdGVyKSB7XG4gICAgICB2YXIgaGFuZGxlciA9IHRoaXMuJGhhbmRsZXIsIGlzQWxsID0gKG5hbWUgPT0gJ2FsbCcpLHRoYXQgPSB0aGlzO1xuXG4gICAgICAkLmVhY2goaGFuZGxlcixmdW5jdGlvbihrLHYpIHtcbiAgICAgICAgdmFyIGhhbHQgPSB0cnVlO1xuICAgICAgICBpZiAoaXNBbGwpIHtcbiAgICAgICAgICBoYWx0ID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaGFsdCA9IHYuaW5kZXhPZihuYW1lKSA8IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFsdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICBhbHRlcih0aGF0LiRlZGl0b3IuZmluZCgnYnV0dG9uW2RhdGEtaGFuZGxlcj1cIicrdisnXCJdJykpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgLCBfX2J1aWxkQnV0dG9uczogZnVuY3Rpb24oYnV0dG9uc0FycmF5LCBjb250YWluZXIpIHtcbiAgICAgIHZhciBpLFxuICAgICAgICAgIG5zID0gdGhpcy4kbnMsXG4gICAgICAgICAgaGFuZGxlciA9IHRoaXMuJGhhbmRsZXIsXG4gICAgICAgICAgY2FsbGJhY2sgPSB0aGlzLiRjYWxsYmFjaztcblxuICAgICAgZm9yIChpPTA7aTxidXR0b25zQXJyYXkubGVuZ3RoO2krKykge1xuICAgICAgICAvLyBCdWlsZCBlYWNoIGdyb3VwIGNvbnRhaW5lclxuICAgICAgICB2YXIgeSwgYnRuR3JvdXBzID0gYnV0dG9uc0FycmF5W2ldO1xuICAgICAgICBmb3IgKHk9MDt5PGJ0bkdyb3Vwcy5sZW5ndGg7eSsrKSB7XG4gICAgICAgICAgLy8gQnVpbGQgZWFjaCBidXR0b24gZ3JvdXBcbiAgICAgICAgICB2YXIgeixcbiAgICAgICAgICAgICAgYnV0dG9ucyA9IGJ0bkdyb3Vwc1t5XS5kYXRhLFxuICAgICAgICAgICAgICBidG5Hcm91cENvbnRhaW5lciA9ICQoJzxkaXYvPicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdidG4tZ3JvdXAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICBmb3IgKHo9MDt6PGJ1dHRvbnMubGVuZ3RoO3orKykge1xuICAgICAgICAgICAgdmFyIGJ1dHRvbiA9IGJ1dHRvbnNbel0sXG4gICAgICAgICAgICAgICAgYnV0dG9uQ29udGFpbmVyLCBidXR0b25JY29uQ29udGFpbmVyLFxuICAgICAgICAgICAgICAgIGJ1dHRvbkhhbmRsZXIgPSBucysnLScrYnV0dG9uLm5hbWUsXG4gICAgICAgICAgICAgICAgYnV0dG9uSWNvbiA9IHRoaXMuX19nZXRJY29uKGJ1dHRvbi5pY29uKSxcbiAgICAgICAgICAgICAgICBidG5UZXh0ID0gYnV0dG9uLmJ0blRleHQgPyBidXR0b24uYnRuVGV4dCA6ICcnLFxuICAgICAgICAgICAgICAgIGJ0bkNsYXNzID0gYnV0dG9uLmJ0bkNsYXNzID8gYnV0dG9uLmJ0bkNsYXNzIDogJ2J0bicsXG4gICAgICAgICAgICAgICAgdGFiSW5kZXggPSBidXR0b24udGFiSW5kZXggPyBidXR0b24udGFiSW5kZXggOiAnLTEnLFxuICAgICAgICAgICAgICAgIGhvdGtleSA9IHR5cGVvZiBidXR0b24uaG90a2V5ICE9PSAndW5kZWZpbmVkJyA/IGJ1dHRvbi5ob3RrZXkgOiAnJyxcbiAgICAgICAgICAgICAgICBob3RrZXlDYXB0aW9uID0gdHlwZW9mIGpRdWVyeS5ob3RrZXlzICE9PSAndW5kZWZpbmVkJyAmJiBob3RrZXkgIT09ICcnID8gJyAoJytob3RrZXkrJyknIDogJyc7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cnVjdCB0aGUgYnV0dG9uIG9iamVjdFxuICAgICAgICAgICAgYnV0dG9uQ29udGFpbmVyID0gJCgnPGJ1dHRvbj48L2J1dHRvbj4nKTtcbiAgICAgICAgICAgIGJ1dHRvbkNvbnRhaW5lci50ZXh0KCcgJyArIHRoaXMuX19sb2NhbGl6ZShidG5UZXh0KSkuYWRkQ2xhc3MoJ2J0bi1kZWZhdWx0IGJ0bi1zbScpLmFkZENsYXNzKGJ0bkNsYXNzKTtcbiAgICAgICAgICAgIGlmKGJ0bkNsYXNzLm1hdGNoKC9idG5cXC0ocHJpbWFyeXxzdWNjZXNzfGluZm98d2FybmluZ3xkYW5nZXJ8bGluaykvKSl7XG4gICAgICAgICAgICAgICAgYnV0dG9uQ29udGFpbmVyLnJlbW92ZUNsYXNzKCdidG4tZGVmYXVsdCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnV0dG9uQ29udGFpbmVyLmF0dHIoe1xuICAgICAgICAgICAgICAgICd0eXBlJzogJ2J1dHRvbicsXG4gICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fX2xvY2FsaXplKGJ1dHRvbi50aXRsZSkgKyBob3RrZXlDYXB0aW9uLFxuICAgICAgICAgICAgICAgICd0YWJpbmRleCc6IHRhYkluZGV4LFxuICAgICAgICAgICAgICAgICdkYXRhLXByb3ZpZGVyJzogbnMsXG4gICAgICAgICAgICAgICAgJ2RhdGEtaGFuZGxlcic6IGJ1dHRvbkhhbmRsZXIsXG4gICAgICAgICAgICAgICAgJ2RhdGEtaG90a2V5JzogaG90a2V5XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChidXR0b24udG9nZ2xlID09PSB0cnVlKXtcbiAgICAgICAgICAgICAgYnV0dG9uQ29udGFpbmVyLmF0dHIoJ2RhdGEtdG9nZ2xlJywgJ2J1dHRvbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnV0dG9uSWNvbkNvbnRhaW5lciA9ICQoJzxzcGFuLz4nKTtcbiAgICAgICAgICAgIGJ1dHRvbkljb25Db250YWluZXIuYWRkQ2xhc3MoYnV0dG9uSWNvbik7XG4gICAgICAgICAgICBidXR0b25JY29uQ29udGFpbmVyLnByZXBlbmRUbyhidXR0b25Db250YWluZXIpO1xuXG4gICAgICAgICAgICAvLyBBdHRhY2ggdGhlIGJ1dHRvbiBvYmplY3RcbiAgICAgICAgICAgIGJ0bkdyb3VwQ29udGFpbmVyLmFwcGVuZChidXR0b25Db250YWluZXIpO1xuXG4gICAgICAgICAgICAvLyBSZWdpc3RlciBoYW5kbGVyIGFuZCBjYWxsYmFja1xuICAgICAgICAgICAgaGFuZGxlci5wdXNoKGJ1dHRvbkhhbmRsZXIpO1xuICAgICAgICAgICAgY2FsbGJhY2sucHVzaChidXR0b24uY2FsbGJhY2spO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIEF0dGFjaCB0aGUgYnV0dG9uIGdyb3VwIGludG8gY29udGFpbmVyIGRvbVxuICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmQoYnRuR3JvdXBDb250YWluZXIpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjb250YWluZXI7XG4gICAgfVxuICAsIF9fc2V0TGlzdGVuZXI6IGZ1bmN0aW9uKCkge1xuICAgICAgLy8gU2V0IHNpemUgYW5kIHJlc2l6YWJsZSBQcm9wZXJ0aWVzXG4gICAgICB2YXIgaGFzUm93cyA9IHR5cGVvZiB0aGlzLiR0ZXh0YXJlYS5hdHRyKCdyb3dzJykgIT09ICd1bmRlZmluZWQnLFxuICAgICAgICAgIG1heFJvd3MgPSB0aGlzLiR0ZXh0YXJlYS52YWwoKS5zcGxpdChcIlxcblwiKS5sZW5ndGggPiA1ID8gdGhpcy4kdGV4dGFyZWEudmFsKCkuc3BsaXQoXCJcXG5cIikubGVuZ3RoIDogJzUnLFxuICAgICAgICAgIHJvd3NWYWwgPSBoYXNSb3dzID8gdGhpcy4kdGV4dGFyZWEuYXR0cigncm93cycpIDogbWF4Um93cztcblxuICAgICAgdGhpcy4kdGV4dGFyZWEuYXR0cigncm93cycscm93c1ZhbCk7XG4gICAgICBpZiAodGhpcy4kb3B0aW9ucy5yZXNpemUpIHtcbiAgICAgICAgdGhpcy4kdGV4dGFyZWEuY3NzKCdyZXNpemUnLHRoaXMuJG9wdGlvbnMucmVzaXplKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy4kdGV4dGFyZWEub24oe1xuICAgICAgICAgICdmb2N1cycgOiAkLnByb3h5KHRoaXMuZm9jdXMsIHRoaXMpLFxuICAgICAgICAgICdrZXl1cCcgOiAkLnByb3h5KHRoaXMua2V5dXAsIHRoaXMpLFxuICAgICAgICAgICdjaGFuZ2UnIDogJC5wcm94eSh0aGlzLmNoYW5nZSwgdGhpcyksXG4gICAgICAgICAgJ3NlbGVjdCcgOiAkLnByb3h5KHRoaXMuc2VsZWN0LCB0aGlzKVxuICAgICAgfSk7XG5cbiAgICAgIGlmICh0aGlzLmV2ZW50U3VwcG9ydGVkKCdrZXlkb3duJykpIHtcbiAgICAgICAgdGhpcy4kdGV4dGFyZWEub24oJ2tleWRvd24nLCAkLnByb3h5KHRoaXMua2V5ZG93biwgdGhpcykpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5ldmVudFN1cHBvcnRlZCgna2V5cHJlc3MnKSkge1xuICAgICAgICB0aGlzLiR0ZXh0YXJlYS5vbigna2V5cHJlc3MnLCAkLnByb3h5KHRoaXMua2V5cHJlc3MsIHRoaXMpKVxuICAgICAgfVxuXG4gICAgICAvLyBSZS1hdHRhY2ggbWFya2Rvd24gZGF0YVxuICAgICAgdGhpcy4kdGV4dGFyZWEuZGF0YSgnbWFya2Rvd24nLHRoaXMpO1xuICAgIH1cblxuICAsIF9faGFuZGxlOiBmdW5jdGlvbihlKSB7XG4gICAgICB2YXIgdGFyZ2V0ID0gJChlLmN1cnJlbnRUYXJnZXQpLFxuICAgICAgICAgIGhhbmRsZXIgPSB0aGlzLiRoYW5kbGVyLFxuICAgICAgICAgIGNhbGxiYWNrID0gdGhpcy4kY2FsbGJhY2ssXG4gICAgICAgICAgaGFuZGxlck5hbWUgPSB0YXJnZXQuYXR0cignZGF0YS1oYW5kbGVyJyksXG4gICAgICAgICAgY2FsbGJhY2tJbmRleCA9IGhhbmRsZXIuaW5kZXhPZihoYW5kbGVyTmFtZSksXG4gICAgICAgICAgY2FsbGJhY2tIYW5kbGVyID0gY2FsbGJhY2tbY2FsbGJhY2tJbmRleF07XG5cbiAgICAgIC8vIFRyaWdnZXIgdGhlIGZvY3VzaW5cbiAgICAgICQoZS5jdXJyZW50VGFyZ2V0KS5mb2N1cygpO1xuXG4gICAgICBjYWxsYmFja0hhbmRsZXIodGhpcyk7XG5cbiAgICAgIC8vIFRyaWdnZXIgb25DaGFuZ2UgZm9yIGVhY2ggYnV0dG9uIGhhbmRsZVxuICAgICAgdGhpcy5jaGFuZ2UodGhpcyk7XG5cbiAgICAgIC8vIFVubGVzcyBpdCB3YXMgdGhlIHNhdmUgaGFuZGxlcixcbiAgICAgIC8vIGZvY3VzaW4gdGhlIHRleHRhcmVhXG4gICAgICBpZiAoaGFuZGxlck5hbWUuaW5kZXhPZignY21kU2F2ZScpIDwgMCkge1xuICAgICAgICB0aGlzLiR0ZXh0YXJlYS5mb2N1cygpO1xuICAgICAgfVxuXG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICwgX19sb2NhbGl6ZTogZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICB2YXIgbWVzc2FnZXMgPSAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLFxuICAgICAgICAgIGxhbmd1YWdlID0gdGhpcy4kb3B0aW9ucy5sYW5ndWFnZTtcbiAgICAgIGlmIChcbiAgICAgICAgdHlwZW9mIG1lc3NhZ2VzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICB0eXBlb2YgbWVzc2FnZXNbbGFuZ3VhZ2VdICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICB0eXBlb2YgbWVzc2FnZXNbbGFuZ3VhZ2VdW3N0cmluZ10gIT09ICd1bmRlZmluZWQnXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIG1lc3NhZ2VzW2xhbmd1YWdlXVtzdHJpbmddO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0cmluZztcbiAgICB9XG5cbiAgLCBfX2dldEljb246IGZ1bmN0aW9uKHNyYykge1xuICAgIHJldHVybiB0eXBlb2Ygc3JjID09ICdvYmplY3QnID8gc3JjW3RoaXMuJG9wdGlvbnMuaWNvbmxpYnJhcnldIDogc3JjO1xuICB9XG5cbiAgLCBzZXRGdWxsc2NyZWVuOiBmdW5jdGlvbihtb2RlKSB7XG4gICAgdmFyICRlZGl0b3IgPSB0aGlzLiRlZGl0b3IsXG4gICAgICAgICR0ZXh0YXJlYSA9IHRoaXMuJHRleHRhcmVhO1xuXG4gICAgaWYgKG1vZGUgPT09IHRydWUpIHtcbiAgICAgICRlZGl0b3IuYWRkQ2xhc3MoJ21kLWZ1bGxzY3JlZW4tbW9kZScpO1xuICAgICAgJCgnYm9keScpLmFkZENsYXNzKCdtZC1ub292ZXJmbG93Jyk7XG4gICAgICB0aGlzLiRvcHRpb25zLm9uRnVsbHNjcmVlbih0aGlzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgJGVkaXRvci5yZW1vdmVDbGFzcygnbWQtZnVsbHNjcmVlbi1tb2RlJyk7XG4gICAgICAkKCdib2R5JykucmVtb3ZlQ2xhc3MoJ21kLW5vb3ZlcmZsb3cnKTtcblxuICAgICAgaWYgKHRoaXMuJGlzUHJldmlldyA9PSB0cnVlKSB0aGlzLmhpZGVQcmV2aWV3KCkuc2hvd1ByZXZpZXcoKVxuICAgIH1cblxuICAgIHRoaXMuJGlzRnVsbHNjcmVlbiA9IG1vZGU7XG4gICAgJHRleHRhcmVhLmZvY3VzKCk7XG4gIH1cblxuICAsIHNob3dFZGl0b3I6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGluc3RhbmNlID0gdGhpcyxcbiAgICAgICAgICB0ZXh0YXJlYSxcbiAgICAgICAgICBucyA9IHRoaXMuJG5zLFxuICAgICAgICAgIGNvbnRhaW5lciA9IHRoaXMuJGVsZW1lbnQsXG4gICAgICAgICAgb3JpZ2luYWxIZWlndGggPSBjb250YWluZXIuY3NzKCdoZWlnaHQnKSxcbiAgICAgICAgICBvcmlnaW5hbFdpZHRoID0gY29udGFpbmVyLmNzcygnd2lkdGgnKSxcbiAgICAgICAgICBlZGl0YWJsZSA9IHRoaXMuJGVkaXRhYmxlLFxuICAgICAgICAgIGhhbmRsZXIgPSB0aGlzLiRoYW5kbGVyLFxuICAgICAgICAgIGNhbGxiYWNrID0gdGhpcy4kY2FsbGJhY2ssXG4gICAgICAgICAgb3B0aW9ucyA9IHRoaXMuJG9wdGlvbnMsXG4gICAgICAgICAgZWRpdG9yID0gJCggJzxkaXYvPicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWQtZWRpdG9yJyxcbiAgICAgICAgICAgICAgICAgICAgICBjbGljazogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZS5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgIC8vIFByZXBhcmUgdGhlIGVkaXRvclxuICAgICAgaWYgKHRoaXMuJGVkaXRvciA9PT0gbnVsbCkge1xuICAgICAgICAvLyBDcmVhdGUgdGhlIHBhbmVsXG4gICAgICAgIHZhciBlZGl0b3JIZWFkZXIgPSAkKCc8ZGl2Lz4nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ21kLWhlYWRlciBidG4tdG9vbGJhcidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBNZXJnZSB0aGUgbWFpbiAmIGFkZGl0aW9uYWwgYnV0dG9uIGdyb3VwcyB0b2dldGhlclxuICAgICAgICB2YXIgYWxsQnRuR3JvdXBzID0gW107XG4gICAgICAgIGlmIChvcHRpb25zLmJ1dHRvbnMubGVuZ3RoID4gMCkgYWxsQnRuR3JvdXBzID0gYWxsQnRuR3JvdXBzLmNvbmNhdChvcHRpb25zLmJ1dHRvbnNbMF0pO1xuICAgICAgICBpZiAob3B0aW9ucy5hZGRpdGlvbmFsQnV0dG9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgLy8gaXRlcmF0ZSB0aGUgYWRkaXRpb25hbCBidXR0b24gZ3JvdXBzXG4gICAgICAgICAgJC5lYWNoKG9wdGlvbnMuYWRkaXRpb25hbEJ1dHRvbnNbMF0sIGZ1bmN0aW9uKGlkeCwgYnV0dG9uR3JvdXApe1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBzZWUgaWYgdGhlIGdyb3VwIG5hbWUgb2YgdGhlIGFkZGlvbmFsIGdyb3VwIG1hdGNoZXMgYW4gZXhpc3RpbmcgZ3JvdXBcbiAgICAgICAgICAgIHZhciBtYXRjaGluZ0dyb3VwcyA9ICQuZ3JlcChhbGxCdG5Hcm91cHMsIGZ1bmN0aW9uKGFsbEJ1dHRvbkdyb3VwLCBhbGxJZHgpe1xuICAgICAgICAgICAgICByZXR1cm4gYWxsQnV0dG9uR3JvdXAubmFtZSA9PT0gYnV0dG9uR3JvdXAubmFtZTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBpZiBpdCBtYXRjaGVzIGFkZCB0aGUgYWRkaW9uYWwgYnV0dG9ucyB0byB0aGF0IGdyb3VwLCBpZiBub3QganVzdCBhZGQgaXQgdG8gdGhlIGFsbCBidXR0b25zIGdyb3VwXG4gICAgICAgICAgICBpZihtYXRjaGluZ0dyb3Vwcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIG1hdGNoaW5nR3JvdXBzWzBdLmRhdGEgPSBtYXRjaGluZ0dyb3Vwc1swXS5kYXRhLmNvbmNhdChidXR0b25Hcm91cC5kYXRhKTtcbiAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgYWxsQnRuR3JvdXBzLnB1c2gob3B0aW9ucy5hZGRpdGlvbmFsQnV0dG9uc1swXVtpZHhdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgIH0pO1xuICAgICAgICB9IFxuXG4gICAgICAgIC8vIFJlZHVjZSBhbmQvb3IgcmVvcmRlciB0aGUgYnV0dG9uIGdyb3Vwc1xuICAgICAgICBpZiAob3B0aW9ucy5yZW9yZGVyQnV0dG9uR3JvdXBzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBhbGxCdG5Hcm91cHMgPSBhbGxCdG5Hcm91cHNcbiAgICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbihidG5Hcm91cCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLnJlb3JkZXJCdXR0b25Hcm91cHMuaW5kZXhPZihidG5Hcm91cC5uYW1lKSA+IC0xO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5pbmRleE9mKGEubmFtZSkgPCBvcHRpb25zLnJlb3JkZXJCdXR0b25Hcm91cHMuaW5kZXhPZihiLm5hbWUpKSByZXR1cm4gLTE7XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5pbmRleE9mKGEubmFtZSkgPiBvcHRpb25zLnJlb3JkZXJCdXR0b25Hcm91cHMuaW5kZXhPZihiLm5hbWUpKSByZXR1cm4gMTtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBCdWlsZCB0aGUgYnV0dG9uc1xuICAgICAgICBpZiAoYWxsQnRuR3JvdXBzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBlZGl0b3JIZWFkZXIgPSB0aGlzLl9fYnVpbGRCdXR0b25zKFthbGxCdG5Hcm91cHNdLCBlZGl0b3JIZWFkZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuZnVsbHNjcmVlbi5lbmFibGUpIHtcbiAgICAgICAgICBlZGl0b3JIZWFkZXIuYXBwZW5kKCc8ZGl2IGNsYXNzPVwibWQtY29udHJvbHNcIj48YSBjbGFzcz1cIm1kLWNvbnRyb2wgbWQtY29udHJvbC1mdWxsc2NyZWVuXCIgaHJlZj1cIiNcIj48c3BhbiBjbGFzcz1cIicrdGhpcy5fX2dldEljb24ob3B0aW9ucy5mdWxsc2NyZWVuLmljb25zLmZ1bGxzY3JlZW5PbikrJ1wiPjwvc3Bhbj48L2E+PC9kaXY+Jykub24oJ2NsaWNrJywgJy5tZC1jb250cm9sLWZ1bGxzY3JlZW4nLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgaW5zdGFuY2Uuc2V0RnVsbHNjcmVlbih0cnVlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVkaXRvci5hcHBlbmQoZWRpdG9ySGVhZGVyKTtcblxuICAgICAgICAvLyBXcmFwIHRoZSB0ZXh0YXJlYVxuICAgICAgICBpZiAoY29udGFpbmVyLmlzKCd0ZXh0YXJlYScpKSB7XG4gICAgICAgICAgY29udGFpbmVyLmJlZm9yZShlZGl0b3IpO1xuICAgICAgICAgIHRleHRhcmVhID0gY29udGFpbmVyO1xuICAgICAgICAgIHRleHRhcmVhLmFkZENsYXNzKCdtZC1pbnB1dCcpO1xuICAgICAgICAgIGVkaXRvci5hcHBlbmQodGV4dGFyZWEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciByYXdDb250ZW50ID0gKHR5cGVvZiB0b01hcmtkb3duID09ICdmdW5jdGlvbicpID8gdG9NYXJrZG93bihjb250YWluZXIuaHRtbCgpKSA6IGNvbnRhaW5lci5odG1sKCksXG4gICAgICAgICAgICAgIGN1cnJlbnRDb250ZW50ID0gJC50cmltKHJhd0NvbnRlbnQpO1xuXG4gICAgICAgICAgLy8gVGhpcyBpcyBzb21lIGFyYml0cmFyeSBjb250ZW50IHRoYXQgY291bGQgYmUgZWRpdGVkXG4gICAgICAgICAgdGV4dGFyZWEgPSAkKCc8dGV4dGFyZWEvPicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ21kLWlucHV0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgJ3ZhbCcgOiBjdXJyZW50Q29udGVudFxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgZWRpdG9yLmFwcGVuZCh0ZXh0YXJlYSk7XG5cbiAgICAgICAgICAvLyBTYXZlIHRoZSBlZGl0YWJsZVxuICAgICAgICAgIGVkaXRhYmxlLmVsID0gY29udGFpbmVyO1xuICAgICAgICAgIGVkaXRhYmxlLnR5cGUgPSBjb250YWluZXIucHJvcCgndGFnTmFtZScpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgZWRpdGFibGUuY29udGVudCA9IGNvbnRhaW5lci5odG1sKCk7XG5cbiAgICAgICAgICAkKGNvbnRhaW5lclswXS5hdHRyaWJ1dGVzKS5lYWNoKGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICBlZGl0YWJsZS5hdHRyS2V5cy5wdXNoKHRoaXMubm9kZU5hbWUpO1xuICAgICAgICAgICAgZWRpdGFibGUuYXR0clZhbHVlcy5wdXNoKHRoaXMubm9kZVZhbHVlKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIFNldCBlZGl0b3IgdG8gYmxvY2tlZCB0aGUgb3JpZ2luYWwgY29udGFpbmVyXG4gICAgICAgICAgY29udGFpbmVyLnJlcGxhY2VXaXRoKGVkaXRvcik7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZWRpdG9yRm9vdGVyID0gJCgnPGRpdi8+Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ21kLWZvb3RlcidcbiAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGNyZWF0ZUZvb3RlciA9IGZhbHNlLFxuICAgICAgICAgICAgZm9vdGVyID0gJyc7XG4gICAgICAgIC8vIENyZWF0ZSB0aGUgZm9vdGVyIGlmIHNhdmFibGVcbiAgICAgICAgaWYgKG9wdGlvbnMuc2F2YWJsZSkge1xuICAgICAgICAgIGNyZWF0ZUZvb3RlciA9IHRydWU7XG4gICAgICAgICAgdmFyIHNhdmVIYW5kbGVyID0gJ2NtZFNhdmUnO1xuXG4gICAgICAgICAgLy8gUmVnaXN0ZXIgaGFuZGxlciBhbmQgY2FsbGJhY2tcbiAgICAgICAgICBoYW5kbGVyLnB1c2goc2F2ZUhhbmRsZXIpO1xuICAgICAgICAgIGNhbGxiYWNrLnB1c2gob3B0aW9ucy5vblNhdmUpO1xuXG4gICAgICAgICAgZWRpdG9yRm9vdGVyLmFwcGVuZCgnPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tc3VjY2Vzc1wiIGRhdGEtcHJvdmlkZXI9XCInXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIG5zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICArICdcIiBkYXRhLWhhbmRsZXI9XCInXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIHNhdmVIYW5kbGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICArICdcIj48aSBjbGFzcz1cImljb24gaWNvbi13aGl0ZSBpY29uLW9rXCI+PC9pPiAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIHRoaXMuX19sb2NhbGl6ZSgnU2F2ZScpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICArICc8L2J1dHRvbj4nKTtcblxuXG4gICAgICAgIH1cblxuICAgICAgICBmb290ZXIgPSB0eXBlb2Ygb3B0aW9ucy5mb290ZXIgPT09ICdmdW5jdGlvbicgPyBvcHRpb25zLmZvb3Rlcih0aGlzKSA6IG9wdGlvbnMuZm9vdGVyO1xuXG4gICAgICAgIGlmICgkLnRyaW0oZm9vdGVyKSAhPT0gJycpIHtcbiAgICAgICAgICBjcmVhdGVGb290ZXIgPSB0cnVlO1xuICAgICAgICAgIGVkaXRvckZvb3Rlci5hcHBlbmQoZm9vdGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjcmVhdGVGb290ZXIpIGVkaXRvci5hcHBlbmQoZWRpdG9yRm9vdGVyKTtcblxuICAgICAgICAvLyBTZXQgd2lkdGhcbiAgICAgICAgaWYgKG9wdGlvbnMud2lkdGggJiYgb3B0aW9ucy53aWR0aCAhPT0gJ2luaGVyaXQnKSB7XG4gICAgICAgICAgaWYgKGpRdWVyeS5pc051bWVyaWMob3B0aW9ucy53aWR0aCkpIHtcbiAgICAgICAgICAgIGVkaXRvci5jc3MoJ2Rpc3BsYXknLCAndGFibGUnKTtcbiAgICAgICAgICAgIHRleHRhcmVhLmNzcygnd2lkdGgnLCBvcHRpb25zLndpZHRoICsgJ3B4Jyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVkaXRvci5hZGRDbGFzcyhvcHRpb25zLndpZHRoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXQgaGVpZ2h0XG4gICAgICAgIGlmIChvcHRpb25zLmhlaWdodCAmJiBvcHRpb25zLmhlaWdodCAhPT0gJ2luaGVyaXQnKSB7XG4gICAgICAgICAgaWYgKGpRdWVyeS5pc051bWVyaWMob3B0aW9ucy5oZWlnaHQpKSB7XG4gICAgICAgICAgICB2YXIgaGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICBpZiAoZWRpdG9ySGVhZGVyKSBoZWlnaHQgPSBNYXRoLm1heCgwLCBoZWlnaHQgLSBlZGl0b3JIZWFkZXIub3V0ZXJIZWlnaHQoKSk7XG4gICAgICAgICAgICBpZiAoZWRpdG9yRm9vdGVyKSBoZWlnaHQgPSBNYXRoLm1heCgwLCBoZWlnaHQgLSBlZGl0b3JGb290ZXIub3V0ZXJIZWlnaHQoKSk7XG4gICAgICAgICAgICB0ZXh0YXJlYS5jc3MoJ2hlaWdodCcsIGhlaWdodCArICdweCcpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlZGl0b3IuYWRkQ2xhc3Mob3B0aW9ucy5oZWlnaHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlZmVyZW5jZVxuICAgICAgICB0aGlzLiRlZGl0b3IgICAgID0gZWRpdG9yO1xuICAgICAgICB0aGlzLiR0ZXh0YXJlYSAgID0gdGV4dGFyZWE7XG4gICAgICAgIHRoaXMuJGVkaXRhYmxlICAgPSBlZGl0YWJsZTtcbiAgICAgICAgdGhpcy4kb2xkQ29udGVudCA9IHRoaXMuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgIHRoaXMuX19zZXRMaXN0ZW5lcigpO1xuXG4gICAgICAgIC8vIFNldCBlZGl0b3IgYXR0cmlidXRlcywgZGF0YSBzaG9ydC1oYW5kIEFQSSBhbmQgbGlzdGVuZXJcbiAgICAgICAgdGhpcy4kZWRpdG9yLmF0dHIoJ2lkJywobmV3IERhdGUoKSkuZ2V0VGltZSgpKTtcbiAgICAgICAgdGhpcy4kZWRpdG9yLm9uKCdjbGljaycsICdbZGF0YS1wcm92aWRlcj1cImJvb3RzdHJhcC1tYXJrZG93blwiXScsICQucHJveHkodGhpcy5fX2hhbmRsZSwgdGhpcykpO1xuXG4gICAgICAgIGlmICh0aGlzLiRlbGVtZW50LmlzKCc6ZGlzYWJsZWQnKSB8fCB0aGlzLiRlbGVtZW50LmlzKCdbcmVhZG9ubHldJykpIHtcbiAgICAgICAgICB0aGlzLiRlZGl0b3IuYWRkQ2xhc3MoJ21kLWVkaXRvci1kaXNhYmxlZCcpO1xuICAgICAgICAgIHRoaXMuZGlzYWJsZUJ1dHRvbnMoJ2FsbCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTdXBwb3J0ZWQoJ2tleWRvd24nKSAmJiB0eXBlb2YgalF1ZXJ5LmhvdGtleXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgZWRpdG9ySGVhZGVyLmZpbmQoJ1tkYXRhLXByb3ZpZGVyPVwiYm9vdHN0cmFwLW1hcmtkb3duXCJdJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciAkYnV0dG9uID0gJCh0aGlzKSxcbiAgICAgICAgICAgICAgICBob3RrZXkgPSAkYnV0dG9uLmF0dHIoJ2RhdGEtaG90a2V5Jyk7XG4gICAgICAgICAgICBpZiAoaG90a2V5LnRvTG93ZXJDYXNlKCkgIT09ICcnKSB7XG4gICAgICAgICAgICAgIHRleHRhcmVhLmJpbmQoJ2tleWRvd24nLCBob3RrZXksIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICRidXR0b24udHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuaW5pdGlhbHN0YXRlID09PSAncHJldmlldycpIHtcbiAgICAgICAgICB0aGlzLnNob3dQcmV2aWV3KCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5pbml0aWFsc3RhdGUgPT09ICdmdWxsc2NyZWVuJyAmJiBvcHRpb25zLmZ1bGxzY3JlZW4uZW5hYmxlKSB7XG4gICAgICAgICAgdGhpcy5zZXRGdWxsc2NyZWVuKHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuJGVkaXRvci5zaG93KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLmF1dG9mb2N1cykge1xuICAgICAgICB0aGlzLiR0ZXh0YXJlYS5mb2N1cygpO1xuICAgICAgICB0aGlzLiRlZGl0b3IuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5mdWxsc2NyZWVuLmVuYWJsZSAmJiBvcHRpb25zLmZ1bGxzY3JlZW4gIT09IGZhbHNlKSB7XG4gICAgICAgIHRoaXMuJGVkaXRvci5hcHBlbmQoJzxkaXYgY2xhc3M9XCJtZC1mdWxsc2NyZWVuLWNvbnRyb2xzXCI+J1xuICAgICAgICAgICAgICAgICAgICAgICAgKyAnPGEgaHJlZj1cIiNcIiBjbGFzcz1cImV4aXQtZnVsbHNjcmVlblwiIHRpdGxlPVwiRXhpdCBmdWxsc2NyZWVuXCI+PHNwYW4gY2xhc3M9XCInICsgdGhpcy5fX2dldEljb24ob3B0aW9ucy5mdWxsc2NyZWVuLmljb25zLmZ1bGxzY3JlZW5PZmYpICsgJ1wiPidcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJzwvc3Bhbj48L2E+J1xuICAgICAgICAgICAgICAgICAgICAgICAgKyAnPC9kaXY+Jyk7XG4gICAgICAgIHRoaXMuJGVkaXRvci5vbignY2xpY2snLCAnLmV4aXQtZnVsbHNjcmVlbicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgaW5zdGFuY2Uuc2V0RnVsbHNjcmVlbihmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyBoaWRlIGhpZGRlbiBidXR0b25zIGZyb20gb3B0aW9uc1xuICAgICAgdGhpcy5oaWRlQnV0dG9ucyhvcHRpb25zLmhpZGRlbkJ1dHRvbnMpO1xuXG4gICAgICAvLyBkaXNhYmxlIGRpc2FibGVkIGJ1dHRvbnMgZnJvbSBvcHRpb25zXG4gICAgICB0aGlzLmRpc2FibGVCdXR0b25zKG9wdGlvbnMuZGlzYWJsZWRCdXR0b25zKTtcblxuICAgICAgLy8gVHJpZ2dlciB0aGUgb25TaG93IGhvb2tcbiAgICAgIG9wdGlvbnMub25TaG93KHRoaXMpO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBwYXJzZUNvbnRlbnQ6IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgdmFyIGNvbnRlbnQ7XG5cbiAgICAgIC8vIHBhcnNlIHdpdGggc3VwcG9ydGVkIG1hcmtkb3duIHBhcnNlclxuICAgICAgdmFyIHZhbCA9IHZhbCB8fCB0aGlzLiR0ZXh0YXJlYS52YWwoKTtcblxuICAgICAgaWYgKHRoaXMuJG9wdGlvbnMucGFyc2VyKSB7XG4gICAgICAgIGNvbnRlbnQgPSB0aGlzLiRvcHRpb25zLnBhcnNlcih2YWwpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbWFya2Rvd24gPT0gJ29iamVjdCcpIHtcbiAgICAgICAgY29udGVudCA9IG1hcmtkb3duLnRvSFRNTCh2YWwpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbWFya2VkID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29udGVudCA9IG1hcmtlZCh2YWwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29udGVudCA9IHZhbDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbnRlbnQ7XG4gICAgfVxuXG4gICwgc2hvd1ByZXZpZXc6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLiRvcHRpb25zLFxuICAgICAgICAgIGNvbnRhaW5lciA9IHRoaXMuJHRleHRhcmVhLFxuICAgICAgICAgIGFmdGVyQ29udGFpbmVyID0gY29udGFpbmVyLm5leHQoKSxcbiAgICAgICAgICByZXBsYWNlbWVudENvbnRhaW5lciA9ICQoJzxkaXYvPicseydjbGFzcyc6J21kLXByZXZpZXcnLCdkYXRhLXByb3ZpZGVyJzonbWFya2Rvd24tcHJldmlldyd9KSxcbiAgICAgICAgICBjb250ZW50LFxuICAgICAgICAgIGNhbGxiYWNrQ29udGVudDtcblxuICAgICAgaWYgKHRoaXMuJGlzUHJldmlldyA9PSB0cnVlKSB7XG4gICAgICAgIC8vIEF2b2lkIHNlcXVlbmNlZCBlbGVtZW50IGNyZWF0aW9uIG9uIG1pc3N1c2VkIHNjZW5hcmlvXG4gICAgICAgIC8vIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3Rvb3BheS9ib290c3RyYXAtbWFya2Rvd24vaXNzdWVzLzE3MFxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gR2l2ZSBmbGFnIHRoYXQgdGVsbCB0aGUgZWRpdG9yIGVudGVyIHByZXZpZXcgbW9kZVxuICAgICAgdGhpcy4kaXNQcmV2aWV3ID0gdHJ1ZTtcbiAgICAgIC8vIERpc2FibGUgYWxsIGJ1dHRvbnNcbiAgICAgIHRoaXMuZGlzYWJsZUJ1dHRvbnMoJ2FsbCcpLmVuYWJsZUJ1dHRvbnMoJ2NtZFByZXZpZXcnKTtcblxuICAgICAgLy8gVHJ5IHRvIGdldCB0aGUgY29udGVudCBmcm9tIGNhbGxiYWNrXG4gICAgICBjYWxsYmFja0NvbnRlbnQgPSBvcHRpb25zLm9uUHJldmlldyh0aGlzKTtcbiAgICAgIC8vIFNldCB0aGUgY29udGVudCBiYXNlZCBmcm9tIHRoZSBjYWxsYmFjayBjb250ZW50IGlmIHN0cmluZyBvdGhlcndpc2UgcGFyc2UgdmFsdWUgZnJvbSB0ZXh0YXJlYVxuICAgICAgY29udGVudCA9IHR5cGVvZiBjYWxsYmFja0NvbnRlbnQgPT0gJ3N0cmluZycgPyBjYWxsYmFja0NvbnRlbnQgOiB0aGlzLnBhcnNlQ29udGVudCgpO1xuXG4gICAgICAvLyBCdWlsZCBwcmV2aWV3IGVsZW1lbnRcbiAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyLmh0bWwoY29udGVudCk7XG5cbiAgICAgIGlmIChhZnRlckNvbnRhaW5lciAmJiBhZnRlckNvbnRhaW5lci5hdHRyKCdjbGFzcycpID09ICdtZC1mb290ZXInKSB7XG4gICAgICAgIC8vIElmIHRoZXJlIGlzIGZvb3RlciBlbGVtZW50LCBpbnNlcnQgdGhlIHByZXZpZXcgY29udGFpbmVyIGJlZm9yZSBpdFxuICAgICAgICByZXBsYWNlbWVudENvbnRhaW5lci5pbnNlcnRCZWZvcmUoYWZ0ZXJDb250YWluZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBqdXN0IGFwcGVuZCBpdCBhZnRlciB0ZXh0YXJlYVxuICAgICAgICBjb250YWluZXIucGFyZW50KCkuYXBwZW5kKHJlcGxhY2VtZW50Q29udGFpbmVyKTtcbiAgICAgIH1cblxuICAgICAgLy8gU2V0IHRoZSBwcmV2aWV3IGVsZW1lbnQgZGltZW5zaW9uc1xuICAgICAgcmVwbGFjZW1lbnRDb250YWluZXIuY3NzKHtcbiAgICAgICAgd2lkdGg6IGNvbnRhaW5lci5vdXRlcldpZHRoKCkgKyAncHgnLFxuICAgICAgICBoZWlnaHQ6IGNvbnRhaW5lci5vdXRlckhlaWdodCgpICsgJ3B4J1xuICAgICAgfSk7XG5cbiAgICAgIGlmICh0aGlzLiRvcHRpb25zLnJlc2l6ZSkge1xuICAgICAgICByZXBsYWNlbWVudENvbnRhaW5lci5jc3MoJ3Jlc2l6ZScsdGhpcy4kb3B0aW9ucy5yZXNpemUpO1xuICAgICAgfVxuXG4gICAgICAvLyBIaWRlIHRoZSBsYXN0LWFjdGl2ZSB0ZXh0YXJlYVxuICAgICAgY29udGFpbmVyLmhpZGUoKTtcblxuICAgICAgLy8gQXR0YWNoIHRoZSBlZGl0b3IgaW5zdGFuY2VzXG4gICAgICByZXBsYWNlbWVudENvbnRhaW5lci5kYXRhKCdtYXJrZG93bicsdGhpcyk7XG5cbiAgICAgIGlmICh0aGlzLiRlbGVtZW50LmlzKCc6ZGlzYWJsZWQnKSB8fCB0aGlzLiRlbGVtZW50LmlzKCdbcmVhZG9ubHldJykpIHtcbiAgICAgICAgdGhpcy4kZWRpdG9yLmFkZENsYXNzKCdtZC1lZGl0b3ItZGlzYWJsZWQnKTtcbiAgICAgICAgdGhpcy5kaXNhYmxlQnV0dG9ucygnYWxsJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGhpZGVQcmV2aWV3OiBmdW5jdGlvbigpIHtcbiAgICAgIC8vIEdpdmUgZmxhZyB0aGF0IHRlbGwgdGhlIGVkaXRvciBxdWl0IHByZXZpZXcgbW9kZVxuICAgICAgdGhpcy4kaXNQcmV2aWV3ID0gZmFsc2U7XG5cbiAgICAgIC8vIE9idGFpbiB0aGUgcHJldmlldyBjb250YWluZXJcbiAgICAgIHZhciBjb250YWluZXIgPSB0aGlzLiRlZGl0b3IuZmluZCgnZGl2W2RhdGEtcHJvdmlkZXI9XCJtYXJrZG93bi1wcmV2aWV3XCJdJyk7XG5cbiAgICAgIC8vIFJlbW92ZSB0aGUgcHJldmlldyBjb250YWluZXJcbiAgICAgIGNvbnRhaW5lci5yZW1vdmUoKTtcblxuICAgICAgLy8gRW5hYmxlIGFsbCBidXR0b25zXG4gICAgICB0aGlzLmVuYWJsZUJ1dHRvbnMoJ2FsbCcpO1xuICAgICAgLy8gRGlzYWJsZSBjb25maWd1cmVkIGRpc2FibGVkIGJ1dHRvbnNcbiAgICAgIHRoaXMuZGlzYWJsZUJ1dHRvbnModGhpcy4kb3B0aW9ucy5kaXNhYmxlZEJ1dHRvbnMpO1xuXG4gICAgICAvLyBCYWNrIHRvIHRoZSBlZGl0b3JcbiAgICAgIHRoaXMuJHRleHRhcmVhLnNob3coKTtcbiAgICAgIHRoaXMuX19zZXRMaXN0ZW5lcigpO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBpc0RpcnR5OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLiRvbGRDb250ZW50ICE9IHRoaXMuZ2V0Q29udGVudCgpO1xuICAgIH1cblxuICAsIGdldENvbnRlbnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuJHRleHRhcmVhLnZhbCgpO1xuICAgIH1cblxuICAsIHNldENvbnRlbnQ6IGZ1bmN0aW9uKGNvbnRlbnQpIHtcbiAgICAgIHRoaXMuJHRleHRhcmVhLnZhbChjb250ZW50KTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgZmluZFNlbGVjdGlvbjogZnVuY3Rpb24oY2h1bmspIHtcbiAgICB2YXIgY29udGVudCA9IHRoaXMuZ2V0Q29udGVudCgpLCBzdGFydENodW5rUG9zaXRpb247XG5cbiAgICBpZiAoc3RhcnRDaHVua1Bvc2l0aW9uID0gY29udGVudC5pbmRleE9mKGNodW5rKSwgc3RhcnRDaHVua1Bvc2l0aW9uID49IDAgJiYgY2h1bmsubGVuZ3RoID4gMCkge1xuICAgICAgdmFyIG9sZFNlbGVjdGlvbiA9IHRoaXMuZ2V0U2VsZWN0aW9uKCksIHNlbGVjdGlvbjtcblxuICAgICAgdGhpcy5zZXRTZWxlY3Rpb24oc3RhcnRDaHVua1Bvc2l0aW9uLHN0YXJ0Q2h1bmtQb3NpdGlvbitjaHVuay5sZW5ndGgpO1xuICAgICAgc2VsZWN0aW9uID0gdGhpcy5nZXRTZWxlY3Rpb24oKTtcblxuICAgICAgdGhpcy5zZXRTZWxlY3Rpb24ob2xkU2VsZWN0aW9uLnN0YXJ0LG9sZFNlbGVjdGlvbi5lbmQpO1xuXG4gICAgICByZXR1cm4gc2VsZWN0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAsIGdldFNlbGVjdGlvbjogZnVuY3Rpb24oKSB7XG5cbiAgICAgIHZhciBlID0gdGhpcy4kdGV4dGFyZWFbMF07XG5cbiAgICAgIHJldHVybiAoXG5cbiAgICAgICAgICAoJ3NlbGVjdGlvblN0YXJ0JyBpbiBlICYmIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICB2YXIgbCA9IGUuc2VsZWN0aW9uRW5kIC0gZS5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IGUuc2VsZWN0aW9uU3RhcnQsIGVuZDogZS5zZWxlY3Rpb25FbmQsIGxlbmd0aDogbCwgdGV4dDogZS52YWx1ZS5zdWJzdHIoZS5zZWxlY3Rpb25TdGFydCwgbCkgfTtcbiAgICAgICAgICB9KSB8fFxuXG4gICAgICAgICAgLyogYnJvd3NlciBub3Qgc3VwcG9ydGVkICovXG4gICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG5cbiAgICAgICkoKTtcblxuICAgIH1cblxuICAsIHNldFNlbGVjdGlvbjogZnVuY3Rpb24oc3RhcnQsZW5kKSB7XG5cbiAgICAgIHZhciBlID0gdGhpcy4kdGV4dGFyZWFbMF07XG5cbiAgICAgIHJldHVybiAoXG5cbiAgICAgICAgICAoJ3NlbGVjdGlvblN0YXJ0JyBpbiBlICYmIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICBlLnNlbGVjdGlvblN0YXJ0ID0gc3RhcnQ7XG4gICAgICAgICAgICAgIGUuc2VsZWN0aW9uRW5kID0gZW5kO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfSkgfHxcblxuICAgICAgICAgIC8qIGJyb3dzZXIgbm90IHN1cHBvcnRlZCAqL1xuICAgICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuXG4gICAgICApKCk7XG5cbiAgICB9XG5cbiAgLCByZXBsYWNlU2VsZWN0aW9uOiBmdW5jdGlvbih0ZXh0KSB7XG5cbiAgICAgIHZhciBlID0gdGhpcy4kdGV4dGFyZWFbMF07XG5cbiAgICAgIHJldHVybiAoXG5cbiAgICAgICAgICAoJ3NlbGVjdGlvblN0YXJ0JyBpbiBlICYmIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICBlLnZhbHVlID0gZS52YWx1ZS5zdWJzdHIoMCwgZS5zZWxlY3Rpb25TdGFydCkgKyB0ZXh0ICsgZS52YWx1ZS5zdWJzdHIoZS5zZWxlY3Rpb25FbmQsIGUudmFsdWUubGVuZ3RoKTtcbiAgICAgICAgICAgICAgLy8gU2V0IGN1cnNvciB0byB0aGUgbGFzdCByZXBsYWNlbWVudCBlbmRcbiAgICAgICAgICAgICAgZS5zZWxlY3Rpb25TdGFydCA9IGUudmFsdWUubGVuZ3RoO1xuICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICB9KSB8fFxuXG4gICAgICAgICAgLyogYnJvd3NlciBub3Qgc3VwcG9ydGVkICovXG4gICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIGUudmFsdWUgKz0gdGV4dDtcbiAgICAgICAgICAgICAgcmV0dXJuIGpRdWVyeShlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICkoKTtcbiAgICB9XG5cbiAgLCBnZXROZXh0VGFiOiBmdW5jdGlvbigpIHtcbiAgICAgIC8vIFNoaWZ0IHRoZSBuZXh0VGFiXG4gICAgICBpZiAodGhpcy4kbmV4dFRhYi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbmV4dFRhYiwgdGFiID0gdGhpcy4kbmV4dFRhYi5zaGlmdCgpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgdGFiID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICBuZXh0VGFiID0gdGFiKCk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRhYiA9PSAnb2JqZWN0JyAmJiB0YWIubGVuZ3RoID4gMCkge1xuICAgICAgICAgIG5leHRUYWIgPSB0YWI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmV4dFRhYjtcbiAgICAgIH1cbiAgICB9XG5cbiAgLCBzZXROZXh0VGFiOiBmdW5jdGlvbihzdGFydCxlbmQpIHtcbiAgICAgIC8vIFB1c2ggbmV3IHNlbGVjdGlvbiBpbnRvIG5leHRUYWIgY29sbGVjdGlvbnNcbiAgICAgIGlmICh0eXBlb2Ygc3RhcnQgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICB0aGlzLiRuZXh0VGFiLnB1c2goZnVuY3Rpb24oKXtcbiAgICAgICAgICByZXR1cm4gdGhhdC5maW5kU2VsZWN0aW9uKHN0YXJ0KTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBzdGFydCA9PSAnbnVtYmVyJyAmJiB0eXBlb2YgZW5kID09ICdudW1iZXInKSB7XG4gICAgICAgIHZhciBvbGRTZWxlY3Rpb24gPSB0aGlzLmdldFNlbGVjdGlvbigpO1xuXG4gICAgICAgIHRoaXMuc2V0U2VsZWN0aW9uKHN0YXJ0LGVuZCk7XG4gICAgICAgIHRoaXMuJG5leHRUYWIucHVzaCh0aGlzLmdldFNlbGVjdGlvbigpKTtcblxuICAgICAgICB0aGlzLnNldFNlbGVjdGlvbihvbGRTZWxlY3Rpb24uc3RhcnQsb2xkU2VsZWN0aW9uLmVuZCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgLCBfX3BhcnNlQnV0dG9uTmFtZVBhcmFtOiBmdW5jdGlvbiAobmFtZXMpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgbmFtZXMgPT0gJ3N0cmluZycgP1xuICAgICAgICAgICAgICAgICAgICAgIG5hbWVzLnNwbGl0KCcgJykgOlxuICAgICAgICAgICAgICAgICAgICAgIG5hbWVzO1xuXG4gICAgfVxuXG4gICwgZW5hYmxlQnV0dG9uczogZnVuY3Rpb24obmFtZSkge1xuICAgICAgdmFyIGJ1dHRvbnMgPSB0aGlzLl9fcGFyc2VCdXR0b25OYW1lUGFyYW0obmFtZSksXG4gICAgICAgIHRoYXQgPSB0aGlzO1xuXG4gICAgICAkLmVhY2goYnV0dG9ucywgZnVuY3Rpb24oaSwgdikge1xuICAgICAgICB0aGF0Ll9fYWx0ZXJCdXR0b25zKGJ1dHRvbnNbaV0sIGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIGVsLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGRpc2FibGVCdXR0b25zOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgICB2YXIgYnV0dG9ucyA9IHRoaXMuX19wYXJzZUJ1dHRvbk5hbWVQYXJhbShuYW1lKSxcbiAgICAgICAgdGhhdCA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChidXR0b25zLCBmdW5jdGlvbihpLCB2KSB7XG4gICAgICAgIHRoYXQuX19hbHRlckJ1dHRvbnMoYnV0dG9uc1tpXSwgZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgZWwuYXR0cignZGlzYWJsZWQnLCdkaXNhYmxlZCcpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBoaWRlQnV0dG9uczogZnVuY3Rpb24obmFtZSkge1xuICAgICAgdmFyIGJ1dHRvbnMgPSB0aGlzLl9fcGFyc2VCdXR0b25OYW1lUGFyYW0obmFtZSksXG4gICAgICAgIHRoYXQgPSB0aGlzO1xuXG4gICAgICAkLmVhY2goYnV0dG9ucywgZnVuY3Rpb24oaSwgdikge1xuICAgICAgICB0aGF0Ll9fYWx0ZXJCdXR0b25zKGJ1dHRvbnNbaV0sIGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIGVsLmFkZENsYXNzKCdoaWRkZW4nKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgc2hvd0J1dHRvbnM6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBidXR0b25zID0gdGhpcy5fX3BhcnNlQnV0dG9uTmFtZVBhcmFtKG5hbWUpLFxuICAgICAgICB0aGF0ID0gdGhpcztcblxuICAgICAgJC5lYWNoKGJ1dHRvbnMsIGZ1bmN0aW9uKGksIHYpIHtcbiAgICAgICAgdGhhdC5fX2FsdGVyQnV0dG9ucyhidXR0b25zW2ldLCBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICBlbC5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGV2ZW50U3VwcG9ydGVkOiBmdW5jdGlvbihldmVudE5hbWUpIHtcbiAgICAgIHZhciBpc1N1cHBvcnRlZCA9IGV2ZW50TmFtZSBpbiB0aGlzLiRlbGVtZW50O1xuICAgICAgaWYgKCFpc1N1cHBvcnRlZCkge1xuICAgICAgICB0aGlzLiRlbGVtZW50LnNldEF0dHJpYnV0ZShldmVudE5hbWUsICdyZXR1cm47Jyk7XG4gICAgICAgIGlzU3VwcG9ydGVkID0gdHlwZW9mIHRoaXMuJGVsZW1lbnRbZXZlbnROYW1lXSA9PT0gJ2Z1bmN0aW9uJztcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc1N1cHBvcnRlZDtcbiAgICB9XG5cbiAgLCBrZXl1cDogZnVuY3Rpb24gKGUpIHtcbiAgICAgIHZhciBibG9ja2VkID0gZmFsc2U7XG4gICAgICBzd2l0Y2goZS5rZXlDb2RlKSB7XG4gICAgICAgIGNhc2UgNDA6IC8vIGRvd24gYXJyb3dcbiAgICAgICAgY2FzZSAzODogLy8gdXAgYXJyb3dcbiAgICAgICAgY2FzZSAxNjogLy8gc2hpZnRcbiAgICAgICAgY2FzZSAxNzogLy8gY3RybFxuICAgICAgICBjYXNlIDE4OiAvLyBhbHRcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIDk6IC8vIHRhYlxuICAgICAgICAgIHZhciBuZXh0VGFiO1xuICAgICAgICAgIGlmIChuZXh0VGFiID0gdGhpcy5nZXROZXh0VGFiKCksbmV4dFRhYiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gR2V0IHRoZSBuZXh0VGFiIGlmIGV4aXN0c1xuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgICAgICAgICB0aGF0LnNldFNlbGVjdGlvbihuZXh0VGFiLnN0YXJ0LG5leHRUYWIuZW5kKTtcbiAgICAgICAgICAgIH0sNTAwKTtcblxuICAgICAgICAgICAgYmxvY2tlZCA9IHRydWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoZSBuZXh0IHRhYiBtZW1vcnkgY29udGFpbnMgbm90aGluZy4uLlxuICAgICAgICAgICAgLy8gY2hlY2sgdGhlIGN1cnNvciBwb3NpdGlvbiB0byBkZXRlcm1pbmUgdGFiIGFjdGlvblxuICAgICAgICAgICAgdmFyIGN1cnNvciA9IHRoaXMuZ2V0U2VsZWN0aW9uKCk7XG5cbiAgICAgICAgICAgIGlmIChjdXJzb3Iuc3RhcnQgPT0gY3Vyc29yLmVuZCAmJiBjdXJzb3IuZW5kID09IHRoaXMuZ2V0Q29udGVudCgpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAvLyBUaGUgY3Vyc29yIGFscmVhZHkgcmVhY2ggdGhlIGVuZCBvZiB0aGUgY29udGVudFxuICAgICAgICAgICAgICBibG9ja2VkID0gZmFsc2U7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBQdXQgdGhlIGN1cnNvciB0byB0aGUgZW5kXG4gICAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0aW9uKHRoaXMuZ2V0Q29udGVudCgpLmxlbmd0aCx0aGlzLmdldENvbnRlbnQoKS5sZW5ndGgpO1xuXG4gICAgICAgICAgICAgIGJsb2NrZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgMTM6IC8vIGVudGVyXG4gICAgICAgICAgYmxvY2tlZCA9IGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI3OiAvLyBlc2NhcGVcbiAgICAgICAgICBpZiAodGhpcy4kaXNGdWxsc2NyZWVuKSB0aGlzLnNldEZ1bGxzY3JlZW4oZmFsc2UpO1xuICAgICAgICAgIGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGJsb2NrZWQpIHtcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLiRvcHRpb25zLm9uQ2hhbmdlKHRoaXMpO1xuICAgIH1cblxuICAsIGNoYW5nZTogZnVuY3Rpb24oZSkge1xuICAgICAgdGhpcy4kb3B0aW9ucy5vbkNoYW5nZSh0aGlzKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgLCBzZWxlY3Q6IGZ1bmN0aW9uIChlKSB7XG4gICAgICB0aGlzLiRvcHRpb25zLm9uU2VsZWN0KHRoaXMpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAsIGZvY3VzOiBmdW5jdGlvbiAoZSkge1xuICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLiRvcHRpb25zLFxuICAgICAgICAgIGlzSGlkZWFibGUgPSBvcHRpb25zLmhpZGVhYmxlLFxuICAgICAgICAgIGVkaXRvciA9IHRoaXMuJGVkaXRvcjtcblxuICAgICAgZWRpdG9yLmFkZENsYXNzKCdhY3RpdmUnKTtcblxuICAgICAgLy8gQmx1ciBvdGhlciBtYXJrZG93bihzKVxuICAgICAgJChkb2N1bWVudCkuZmluZCgnLm1kLWVkaXRvcicpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgICAgaWYgKCQodGhpcykuYXR0cignaWQnKSAhPT0gZWRpdG9yLmF0dHIoJ2lkJykpIHtcbiAgICAgICAgICB2YXIgYXR0YWNoZWRNYXJrZG93bjtcblxuICAgICAgICAgIGlmIChhdHRhY2hlZE1hcmtkb3duID0gJCh0aGlzKS5maW5kKCd0ZXh0YXJlYScpLmRhdGEoJ21hcmtkb3duJyksXG4gICAgICAgICAgICAgIGF0dGFjaGVkTWFya2Rvd24gPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgYXR0YWNoZWRNYXJrZG93biA9ICQodGhpcykuZmluZCgnZGl2W2RhdGEtcHJvdmlkZXI9XCJtYXJrZG93bi1wcmV2aWV3XCJdJykuZGF0YSgnbWFya2Rvd24nKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoYXR0YWNoZWRNYXJrZG93bikge1xuICAgICAgICAgICAgYXR0YWNoZWRNYXJrZG93bi5ibHVyKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLy8gVHJpZ2dlciB0aGUgb25Gb2N1cyBob29rXG4gICAgICBvcHRpb25zLm9uRm9jdXModGhpcyk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGJsdXI6IGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuJG9wdGlvbnMsXG4gICAgICAgICAgaXNIaWRlYWJsZSA9IG9wdGlvbnMuaGlkZWFibGUsXG4gICAgICAgICAgZWRpdG9yID0gdGhpcy4kZWRpdG9yLFxuICAgICAgICAgIGVkaXRhYmxlID0gdGhpcy4kZWRpdGFibGU7XG5cbiAgICAgIGlmIChlZGl0b3IuaGFzQ2xhc3MoJ2FjdGl2ZScpIHx8IHRoaXMuJGVsZW1lbnQucGFyZW50KCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGVkaXRvci5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cbiAgICAgICAgaWYgKGlzSGlkZWFibGUpIHtcbiAgICAgICAgICAvLyBDaGVjayBmb3IgZWRpdGFibGUgZWxlbWVudHNcbiAgICAgICAgICBpZiAoZWRpdGFibGUuZWwgIT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIEJ1aWxkIHRoZSBvcmlnaW5hbCBlbGVtZW50XG4gICAgICAgICAgICB2YXIgb2xkRWxlbWVudCA9ICQoJzwnK2VkaXRhYmxlLnR5cGUrJy8+JyksXG4gICAgICAgICAgICAgICAgY29udGVudCA9IHRoaXMuZ2V0Q29udGVudCgpLFxuICAgICAgICAgICAgICAgIGN1cnJlbnRDb250ZW50ID0gdGhpcy5wYXJzZUNvbnRlbnQoY29udGVudCk7XG5cbiAgICAgICAgICAgICQoZWRpdGFibGUuYXR0cktleXMpLmVhY2goZnVuY3Rpb24oayx2KSB7XG4gICAgICAgICAgICAgIG9sZEVsZW1lbnQuYXR0cihlZGl0YWJsZS5hdHRyS2V5c1trXSxlZGl0YWJsZS5hdHRyVmFsdWVzW2tdKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGVkaXRvciBjb250ZW50XG4gICAgICAgICAgICBvbGRFbGVtZW50Lmh0bWwoY3VycmVudENvbnRlbnQpO1xuXG4gICAgICAgICAgICBlZGl0b3IucmVwbGFjZVdpdGgob2xkRWxlbWVudCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVkaXRvci5oaWRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJpZ2dlciB0aGUgb25CbHVyIGhvb2tcbiAgICAgICAgb3B0aW9ucy5vbkJsdXIodGhpcyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICB9O1xuXG4gLyogTUFSS0RPV04gUExVR0lOIERFRklOSVRJT05cbiAgKiA9PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG4gIHZhciBvbGQgPSAkLmZuLm1hcmtkb3duO1xuXG4gICQuZm4ubWFya2Rvd24gPSBmdW5jdGlvbiAob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG4gICAgICAgICwgZGF0YSA9ICR0aGlzLmRhdGEoJ21hcmtkb3duJylcbiAgICAgICAgLCBvcHRpb25zID0gdHlwZW9mIG9wdGlvbiA9PSAnb2JqZWN0JyAmJiBvcHRpb247XG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ21hcmtkb3duJywgKGRhdGEgPSBuZXcgTWFya2Rvd24odGhpcywgb3B0aW9ucykpKVxuICAgIH0pXG4gIH07XG5cbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcyA9IHt9O1xuXG4gICQuZm4ubWFya2Rvd24uZGVmYXVsdHMgPSB7XG4gICAgLyogRWRpdG9yIFByb3BlcnRpZXMgKi9cbiAgICBhdXRvZm9jdXM6IGZhbHNlLFxuICAgIGhpZGVhYmxlOiBmYWxzZSxcbiAgICBzYXZhYmxlOiBmYWxzZSxcbiAgICB3aWR0aDogJ2luaGVyaXQnLFxuICAgIGhlaWdodDogJ2luaGVyaXQnLFxuICAgIHJlc2l6ZTogJ25vbmUnLFxuICAgIGljb25saWJyYXJ5OiAnZ2x5cGgnLFxuICAgIGxhbmd1YWdlOiAnZW4nLFxuICAgIGluaXRpYWxzdGF0ZTogJ2VkaXRvcicsXG4gICAgcGFyc2VyOiBudWxsLFxuXG4gICAgLyogQnV0dG9ucyBQcm9wZXJ0aWVzICovXG4gICAgYnV0dG9uczogW1xuICAgICAgW3tcbiAgICAgICAgbmFtZTogJ2dyb3VwRm9udCcsXG4gICAgICAgIGRhdGE6IFt7XG4gICAgICAgICAgbmFtZTogJ2NtZEJvbGQnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrQicsXG4gICAgICAgICAgdGl0bGU6ICdCb2xkJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1ib2xkJywgZmE6ICdmYSBmYS1ib2xkJywgJ2ZhLTMnOiAnaWNvbi1ib2xkJyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIC8vIEdpdmUvcmVtb3ZlICoqIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKTtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ3N0cm9uZyB0ZXh0Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtMiwyKSA9PT0gJyoqJ1xuICAgICAgICAgICAgICAgICYmIGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLmVuZCwyKSA9PT0gJyoqJyApIHtcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oc2VsZWN0ZWQuc3RhcnQtMixzZWxlY3RlZC5lbmQrMik7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbihjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0LTI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJyoqJytjaHVuaysnKionKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0se1xuICAgICAgICAgIG5hbWU6ICdjbWRJdGFsaWMnLFxuICAgICAgICAgIHRpdGxlOiAnSXRhbGljJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK0knLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWl0YWxpYycsIGZhOiAnZmEgZmEtaXRhbGljJywgJ2ZhLTMnOiAnaWNvbi1pdGFsaWMnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gR2l2ZS9yZW1vdmUgKiBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdlbXBoYXNpemVkIHRleHQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgIGlmIChjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC0xLDEpID09PSAnXydcbiAgICAgICAgICAgICAgICAmJiBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5lbmQsMSkgPT09ICdfJyApIHtcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oc2VsZWN0ZWQuc3RhcnQtMSxzZWxlY3RlZC5lbmQrMSk7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbihjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0LTE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ18nK2NodW5rKydfJyk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LHtcbiAgICAgICAgICBuYW1lOiAnY21kSGVhZGluZycsXG4gICAgICAgICAgdGl0bGU6ICdIZWFkaW5nJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK0gnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWhlYWRlcicsIGZhOiAnZmEgZmEtaGVhZGVyJywgJ2ZhLTMnOiAnaWNvbi1mb250JyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIC8vIEFwcGVuZC9yZW1vdmUgIyMjIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKSwgcG9pbnRlciwgcHJldkNoYXI7XG5cbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdoZWFkaW5nIHRleHQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dCArICdcXG4nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKChwb2ludGVyID0gNCwgY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtcG9pbnRlcixwb2ludGVyKSA9PT0gJyMjIyAnKVxuICAgICAgICAgICAgICAgIHx8IChwb2ludGVyID0gMywgY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtcG9pbnRlcixwb2ludGVyKSA9PT0gJyMjIycpKSB7XG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKHNlbGVjdGVkLnN0YXJ0LXBvaW50ZXIsc2VsZWN0ZWQuZW5kKTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKGNodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQtcG9pbnRlcjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2VsZWN0ZWQuc3RhcnQgPiAwICYmIChwcmV2Q2hhciA9IGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLnN0YXJ0LTEsMSksICEhcHJldkNoYXIgJiYgcHJldkNoYXIgIT0gJ1xcbicpKSB7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignXFxuXFxuIyMjICcrY2h1bmspO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCs2O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gRW1wdHkgc3RyaW5nIGJlZm9yZSBlbGVtZW50XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignIyMjICcrY2h1bmspO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCs0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfV1cbiAgICAgIH0se1xuICAgICAgICBuYW1lOiAnZ3JvdXBMaW5rJyxcbiAgICAgICAgZGF0YTogW3tcbiAgICAgICAgICBuYW1lOiAnY21kVXJsJyxcbiAgICAgICAgICB0aXRsZTogJ1VSTC9MaW5rJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK0wnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWxpbmsnLCBmYTogJ2ZhIGZhLWxpbmsnLCAnZmEtMyc6ICdpY29uLWxpbmsnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gR2l2ZSBbXSBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uIGFuZCBwcmVwZW5kIHRoZSBsaW5rXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCksIGxpbms7XG5cbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGluayA9IHByb21wdChlLl9fbG9jYWxpemUoJ0luc2VydCBIeXBlcmxpbmsnKSwnaHR0cDovLycpO1xuXG4gICAgICAgICAgICB2YXIgdXJsUmVnZXggPSBuZXcgUmVnRXhwKCdeKChodHRwfGh0dHBzKTovL3wobWFpbHRvOil8KC8vKSlbYS16MC05XScsICdpJyk7XG4gICAgICAgICAgICBpZiAobGluayAhPT0gbnVsbCAmJiBsaW5rICE9PSAnJyAmJiBsaW5rICE9PSAnaHR0cDovLycgJiYgdXJsUmVnZXgudGVzdChsaW5rKSkge1xuICAgICAgICAgICAgICB2YXIgc2FuaXRpemVkTGluayA9ICQoJzxkaXY+JytsaW5rKyc8L2Rpdj4nKS50ZXh0KCk7XG5cbiAgICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdbJytjaHVuaysnXSgnK3Nhbml0aXplZExpbmsrJyknKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMTtcblxuICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LHtcbiAgICAgICAgICBuYW1lOiAnY21kSW1hZ2UnLFxuICAgICAgICAgIHRpdGxlOiAnSW1hZ2UnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrRycsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tcGljdHVyZScsIGZhOiAnZmEgZmEtcGljdHVyZS1vJywgJ2ZhLTMnOiAnaWNvbi1waWN0dXJlJyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIC8vIEdpdmUgIVtdIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb24gYW5kIHByZXBlbmQgdGhlIGltYWdlIGxpbmtcbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKSwgbGluaztcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGluayA9IHByb21wdChlLl9fbG9jYWxpemUoJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnKSwnaHR0cDovLycpO1xuXG4gICAgICAgICAgICB2YXIgdXJsUmVnZXggPSBuZXcgUmVnRXhwKCdeKChodHRwfGh0dHBzKTovL3woLy8pKVthLXowLTldJywgJ2knKTtcbiAgICAgICAgICAgIGlmIChsaW5rICE9PSBudWxsICYmIGxpbmsgIT09ICcnICYmIGxpbmsgIT09ICdodHRwOi8vJyAmJiB1cmxSZWdleC50ZXN0KGxpbmspKSB7XG4gICAgICAgICAgICAgIHZhciBzYW5pdGl6ZWRMaW5rID0gJCgnPGRpdj4nK2xpbmsrJzwvZGl2PicpLnRleHQoKTtcblxuICAgICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJyFbJytjaHVuaysnXSgnK3Nhbml0aXplZExpbmsrJyBcIicrZS5fX2xvY2FsaXplKCdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJykrJ1wiKScpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuXG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgbmV4dCB0YWJcbiAgICAgICAgICAgICAgZS5zZXROZXh0VGFiKGUuX19sb2NhbGl6ZSgnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZScpKTtcblxuICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XVxuICAgICAgfSx7XG4gICAgICAgIG5hbWU6ICdncm91cE1pc2MnLFxuICAgICAgICBkYXRhOiBbe1xuICAgICAgICAgIG5hbWU6ICdjbWRMaXN0JyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK1UnLFxuICAgICAgICAgIHRpdGxlOiAnVW5vcmRlcmVkIExpc3QnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWxpc3QnLCBmYTogJ2ZhIGZhLWxpc3QnLCAnZmEtMyc6ICdpY29uLWxpc3QtdWwnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gUHJlcGVuZC9HaXZlIC0gc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2xpc3QgdGV4dCBoZXJlJyk7XG5cbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCctICcrY2h1bmspO1xuICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkLnRleHQuaW5kZXhPZignXFxuJykgPCAwKSB7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuXG4gICAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCctICcrY2h1bmspO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ID0gW107XG5cbiAgICAgICAgICAgICAgICBsaXN0ID0gc2VsZWN0ZWQudGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBsaXN0WzBdO1xuXG4gICAgICAgICAgICAgICAgJC5lYWNoKGxpc3QsZnVuY3Rpb24oayx2KSB7XG4gICAgICAgICAgICAgICAgICBsaXN0W2tdID0gJy0gJyt2O1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdcXG5cXG4nK2xpc3Quam9pbignXFxuJykpO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCs0O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ2NtZExpc3RPJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK08nLFxuICAgICAgICAgIHRpdGxlOiAnT3JkZXJlZCBMaXN0JyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi10aC1saXN0JywgZmE6ICdmYSBmYS1saXN0LW9sJywgJ2ZhLTMnOiAnaWNvbi1saXN0LW9sJyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKSB7XG5cbiAgICAgICAgICAgIC8vIFByZXBlbmQvR2l2ZSAtIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKTtcblxuICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdsaXN0IHRleHQgaGVyZScpO1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJzEuICcrY2h1bmspO1xuICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCszO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkLnRleHQuaW5kZXhPZignXFxuJykgPCAwKSB7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuXG4gICAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCcxLiAnK2NodW5rKTtcblxuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgbGlzdCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgbGlzdCA9IHNlbGVjdGVkLnRleHQuc3BsaXQoJ1xcbicpO1xuICAgICAgICAgICAgICAgIGNodW5rID0gbGlzdFswXTtcblxuICAgICAgICAgICAgICAgICQuZWFjaChsaXN0LGZ1bmN0aW9uKGssdikge1xuICAgICAgICAgICAgICAgICAgbGlzdFtrXSA9ICcxLiAnK3Y7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ1xcblxcbicrbGlzdC5qb2luKCdcXG4nKSk7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnY21kQ29kZScsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtLJyxcbiAgICAgICAgICB0aXRsZTogJ0NvZGUnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWFzdGVyaXNrJywgZmE6ICdmYSBmYS1jb2RlJywgJ2ZhLTMnOiAnaWNvbi1jb2RlJyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAvLyBHaXZlL3JlbW92ZSAqKiBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBleHRyYSB3b3JkXG4gICAgICAgICAgICAgIGNodW5rID0gZS5fX2xvY2FsaXplKCdjb2RlIHRleHQgaGVyZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLnN0YXJ0LTQsNCkgPT09ICdgYGBcXG4nXG4gICAgICAgICAgICAgICAgJiYgY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuZW5kLDQpID09PSAnXFxuYGBgJykge1xuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihzZWxlY3RlZC5zdGFydC00LCBzZWxlY3RlZC5lbmQrNCk7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbihjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0LTQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLnN0YXJ0LTEsMSkgPT09ICdgJ1xuICAgICAgICAgICAgICAgICYmIGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLmVuZCwxKSA9PT0gJ2AnKSB7XG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKHNlbGVjdGVkLnN0YXJ0LTEsc2VsZWN0ZWQuZW5kKzEpO1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oY2h1bmspO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydC0xO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb250ZW50LmluZGV4T2YoJ1xcbicpID4gLTEpIHtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdgYGBcXG4nK2NodW5rKydcXG5gYGAnKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrNDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignYCcrY2h1bmsrJ2AnKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnY21kUXVvdGUnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrUScsXG4gICAgICAgICAgdGl0bGU6ICdRdW90ZScsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tY29tbWVudCcsIGZhOiAnZmEgZmEtcXVvdGUtbGVmdCcsICdmYS0zJzogJ2ljb24tcXVvdGUtbGVmdCcgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgLy8gUHJlcGVuZC9HaXZlIC0gc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ3F1b3RlIGhlcmUnKTtcblxuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJz4gJytjaHVuayk7XG5cbiAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChzZWxlY3RlZC50ZXh0LmluZGV4T2YoJ1xcbicpIDwgMCkge1xuICAgICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcblxuICAgICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignPiAnK2NodW5rKTtcblxuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgbGlzdCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgbGlzdCA9IHNlbGVjdGVkLnRleHQuc3BsaXQoJ1xcbicpO1xuICAgICAgICAgICAgICAgIGNodW5rID0gbGlzdFswXTtcblxuICAgICAgICAgICAgICAgICQuZWFjaChsaXN0LGZ1bmN0aW9uKGssdikge1xuICAgICAgICAgICAgICAgICAgbGlzdFtrXSA9ICc+ICcrdjtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignXFxuXFxuJytsaXN0LmpvaW4oJ1xcbicpKTtcblxuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrNDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfV1cbiAgICAgIH0se1xuICAgICAgICBuYW1lOiAnZ3JvdXBVdGlsJyxcbiAgICAgICAgZGF0YTogW3tcbiAgICAgICAgICBuYW1lOiAnY21kUHJldmlldycsXG4gICAgICAgICAgdG9nZ2xlOiB0cnVlLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrUCcsXG4gICAgICAgICAgdGl0bGU6ICdQcmV2aWV3JyxcbiAgICAgICAgICBidG5UZXh0OiAnUHJldmlldycsXG4gICAgICAgICAgYnRuQ2xhc3M6ICdidG4gYnRuLXByaW1hcnkgYnRuLXNtJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1zZWFyY2gnLCBmYTogJ2ZhIGZhLXNlYXJjaCcsICdmYS0zJzogJ2ljb24tc2VhcmNoJyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSBwcmV2aWV3IG1vZGUgYW5kIHRvZ2dsZSBiYXNlZCBvbiB0aGlzIGZsYWdcbiAgICAgICAgICAgIHZhciBpc1ByZXZpZXcgPSBlLiRpc1ByZXZpZXcsY29udGVudDtcblxuICAgICAgICAgICAgaWYgKGlzUHJldmlldyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgLy8gR2l2ZSBmbGFnIHRoYXQgdGVsbCB0aGUgZWRpdG9yIGVudGVyIHByZXZpZXcgbW9kZVxuICAgICAgICAgICAgICBlLnNob3dQcmV2aWV3KCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBlLmhpZGVQcmV2aWV3KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XVxuICAgICAgfV1cbiAgICBdLFxuICAgIGFkZGl0aW9uYWxCdXR0b25zOltdLCAvLyBQbGFjZSB0byBob29rIG1vcmUgYnV0dG9ucyBieSBjb2RlXG4gICAgcmVvcmRlckJ1dHRvbkdyb3VwczpbXSxcbiAgICBoaWRkZW5CdXR0b25zOltdLCAvLyBEZWZhdWx0IGhpZGRlbiBidXR0b25zXG4gICAgZGlzYWJsZWRCdXR0b25zOltdLCAvLyBEZWZhdWx0IGRpc2FibGVkIGJ1dHRvbnNcbiAgICBmb290ZXI6ICcnLFxuICAgIGZ1bGxzY3JlZW46IHtcbiAgICAgIGVuYWJsZTogdHJ1ZSxcbiAgICAgIGljb25zOiB7XG4gICAgICAgIGZ1bGxzY3JlZW5Pbjoge1xuICAgICAgICAgIGZhOiAnZmEgZmEtZXhwYW5kJyxcbiAgICAgICAgICBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tZnVsbHNjcmVlbicsXG4gICAgICAgICAgJ2ZhLTMnOiAnaWNvbi1yZXNpemUtZnVsbCdcbiAgICAgICAgfSxcbiAgICAgICAgZnVsbHNjcmVlbk9mZjoge1xuICAgICAgICAgIGZhOiAnZmEgZmEtY29tcHJlc3MnLFxuICAgICAgICAgIGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1mdWxsc2NyZWVuJyxcbiAgICAgICAgICAnZmEtMyc6ICdpY29uLXJlc2l6ZS1zbWFsbCdcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKiBFdmVudHMgaG9vayAqL1xuICAgIG9uU2hvdzogZnVuY3Rpb24gKGUpIHt9LFxuICAgIG9uUHJldmlldzogZnVuY3Rpb24gKGUpIHt9LFxuICAgIG9uU2F2ZTogZnVuY3Rpb24gKGUpIHt9LFxuICAgIG9uQmx1cjogZnVuY3Rpb24gKGUpIHt9LFxuICAgIG9uRm9jdXM6IGZ1bmN0aW9uIChlKSB7fSxcbiAgICBvbkNoYW5nZTogZnVuY3Rpb24oZSkge30sXG4gICAgb25GdWxsc2NyZWVuOiBmdW5jdGlvbihlKSB7fSxcbiAgICBvblNlbGVjdDogZnVuY3Rpb24gKGUpIHt9XG4gIH07XG5cbiAgJC5mbi5tYXJrZG93bi5Db25zdHJ1Y3RvciA9IE1hcmtkb3duO1xuXG5cbiAvKiBNQVJLRE9XTiBOTyBDT05GTElDVFxuICAqID09PT09PT09PT09PT09PT09PT09ICovXG5cbiAgJC5mbi5tYXJrZG93bi5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4ubWFya2Rvd24gPSBvbGQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLyogTUFSS0RPV04gR0xPQkFMIEZVTkNUSU9OICYgREFUQS1BUElcbiAgKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cbiAgdmFyIGluaXRNYXJrZG93biA9IGZ1bmN0aW9uKGVsKSB7XG4gICAgdmFyICR0aGlzID0gZWw7XG5cbiAgICBpZiAoJHRoaXMuZGF0YSgnbWFya2Rvd24nKSkge1xuICAgICAgJHRoaXMuZGF0YSgnbWFya2Rvd24nKS5zaG93RWRpdG9yKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgJHRoaXMubWFya2Rvd24oKVxuICB9O1xuXG4gIHZhciBibHVyTm9uRm9jdXNlZCA9IGZ1bmN0aW9uKGUpIHtcbiAgICB2YXIgJGFjdGl2ZUVsZW1lbnQgPSAkKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpO1xuXG4gICAgLy8gQmx1ciBldmVudFxuICAgICQoZG9jdW1lbnQpLmZpbmQoJy5tZC1lZGl0b3InKS5lYWNoKGZ1bmN0aW9uKCl7XG4gICAgICB2YXIgJHRoaXMgICAgICAgICAgICA9ICQodGhpcyksXG4gICAgICAgICAgZm9jdXNlZCAgICAgICAgICA9ICRhY3RpdmVFbGVtZW50LmNsb3Nlc3QoJy5tZC1lZGl0b3InKVswXSA9PT0gdGhpcyxcbiAgICAgICAgICBhdHRhY2hlZE1hcmtkb3duID0gJHRoaXMuZmluZCgndGV4dGFyZWEnKS5kYXRhKCdtYXJrZG93bicpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLmZpbmQoJ2RpdltkYXRhLXByb3ZpZGVyPVwibWFya2Rvd24tcHJldmlld1wiXScpLmRhdGEoJ21hcmtkb3duJyk7XG5cbiAgICAgIGlmIChhdHRhY2hlZE1hcmtkb3duICYmICFmb2N1c2VkKSB7XG4gICAgICAgIGF0dGFjaGVkTWFya2Rvd24uYmx1cigpO1xuICAgICAgfVxuICAgIH0pXG4gIH07XG5cbiAgJChkb2N1bWVudClcbiAgICAub24oJ2NsaWNrLm1hcmtkb3duLmRhdGEtYXBpJywgJ1tkYXRhLXByb3ZpZGU9XCJtYXJrZG93bi1lZGl0YWJsZVwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBpbml0TWFya2Rvd24oJCh0aGlzKSk7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSlcbiAgICAub24oJ2NsaWNrIGZvY3VzaW4nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgYmx1ck5vbkZvY3VzZWQoZSk7XG4gICAgfSlcbiAgICAucmVhZHkoZnVuY3Rpb24oKXtcbiAgICAgICQoJ3RleHRhcmVhW2RhdGEtcHJvdmlkZT1cIm1hcmtkb3duXCJdJykuZWFjaChmdW5jdGlvbigpe1xuICAgICAgICBpbml0TWFya2Rvd24oJCh0aGlzKSk7XG4gICAgICB9KVxuICAgIH0pO1xuXG59KSk7XG4iLCIvKlxuICogQXJhYmljIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIEdlb3JnZSBBamFtIDxnZW9yZ2UuZWphYW1AZ21haWwuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5ubCA9IHtcbiAgICAnQm9sZCc6IFwi2LrYp9mF2YJcIixcbiAgICAnSXRhbGljJzogXCLZhdin2KbZhFwiLFxuICAgICdIZWFkaW5nJzogXCLYudmG2YjYp9mGXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJVUkwv2LHYp9io2LdcIixcbiAgICAnSW1hZ2UnOiBcIti12YjYsdipXCIsXG4gICAgJ0xpc3QnOiBcItmC2KfYptmF2KlcIixcbiAgICAnUHJldmlldyc6IFwi2KfYs9iq2LnYsdin2LZcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcItmG2LUg2LrYp9mF2YJcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCLZhti1INmH2KfZhVwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcItin2YTYudmG2YjYp9mGXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwi2KfYr9iu2YQg2YjYtdmBINin2YTYsdin2KjYtyDZh9mG2KdcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwi2KfYr9iu2YQg2KfZhNix2KfYqNi3INmH2YbYp1wiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCLYp9iv2K7ZhCDZiNi12YEg2KfZhNi12YjYsdipINmH2YbYp1wiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCLYp9iv2K7ZhCDYsdin2KjYtyDYp9mE2LXZiNix2Kkg2YfZhtinXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcItin2K/YrtmEINi52YbZiNin2YYg2KfZhNi12YjYsdipINmH2YbYp1wiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwi2KfZg9iq2Kgg2KfZhNmG2LUg2YfZhtinXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIEN6ZWNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIFbDrXQgS2FiZWxlIDx2aXRAa2FiZWxlLm1lPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5jcyA9IHtcbiAgICAnQm9sZCc6IFwiVHXEjW7Em1wiLFxuICAgICdJdGFsaWMnOiBcIkt1cnrDrXZhXCIsXG4gICAgJ0hlYWRpbmcnOiBcIk5hZHBpc1wiLFxuICAgICdVUkwvTGluayc6IFwiVVJML09ka2F6XCIsXG4gICAgJ0ltYWdlJzogXCJPYnLDoXpla1wiLFxuICAgICdVbm9yZGVyZWQgTGlzdCc6IFwiU2V6bmFtXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwiU2XFmWF6ZW7DvSBzZXpuYW1cIixcbiAgICAnQ29kZSc6IFwiw5pzZWsga8OzZHVcIixcbiAgICAnUXVvdGUnOiBcIkNpdGFjZVwiLFxuICAgICdQcmV2aWV3JzogXCJOw6FobGVkXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJ0dcSNbsO9IHRleHRcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJ6ZMWvcmF6bsSbbsO9IHRleHRcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJ0ZXh0IG5hZHBpc3VcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJzZW0gdmxvxb4gcG9waXMgb2RrYXp1XCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIlZsb8W+aXQgSHlwZXJsaW5rXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcInNlbSB2bG/FviBwb3BpcyBvYnLDoXprdVwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJWbG/FviBhZHJlc3Ugb2Jyw6F6a3VcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwic2VtIHZsb8W+IHBvcGlzIG9icsOhemt1XCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJwb2xvxb5rYSBzZXpuYW11XCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIERhbmlzaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBEYW4gU3Rvcm0gPHN0b3JtQGNhdGFseXN0Y29kZS5uZXQ+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLm5iID0ge1xuICAgICdCb2xkJzogJ0ZlZCcsXG4gICAgJ0l0YWxpYyc6ICdLdXJzaXYnLFxuICAgICdIZWFkaW5nJzogJ092ZXJza3JpZnQnLFxuICAgICdVUkwvTGluayc6ICdVUkwvTGluaycsXG4gICAgJ0ltYWdlJzogJ0JpbGxlZGUnLFxuICAgICdMaXN0JzogJ0xpc3RlJyxcbiAgICAnUHJldmlldyc6ICdGb3Jow6VuZHN2aXNuaW5nJyxcbiAgICAnc3Ryb25nIHRleHQnOiAnc3TDpnJrIHRla3N0JyxcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogJ2ZyZW1ow6Z2ZXQgdGVrc3QnLFxuICAgICdoZWFkaW5nIHRleHQnOiAnb3ZlcnNrcmlmdCB0ZWtzdCcsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6ICdTa3JpdiBsaW5rIGJlc2tyaXZlbHNlIGhlcicsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiAnSW5kc8OmdCBsaW5rJyxcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6ICdJbmRzw6Z0IGJpbGxlZGUgYmVza3JpdmVsc2UgaGVyJyxcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6ICdJbmRzw6Z0IGJpbGxlZGUgbGluaycsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiAnSW5kc8OmdCBiaWxsZWRlIHRpdGVsJyxcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiAnSW5kc8OmdCBsaXN0ZSB0ZWtzdCBoZXInLFxuICAgICdxdW90ZSBoZXJlJzogJ0luZHPDpnQgY2l0YXQgaGVyJyxcbiAgICAnY29kZSB0ZXh0IGhlcmUnOiAnSW5kc8OmdCBrb2RlIGhlcidcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIEdlcm1hbiB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBUb2JpYXMgTml0c2NoZSA8dG9iaWFzLW5pdHNjaGVAZ214Lm5ldD5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMuZGUgPSB7XG4gICAgJ0JvbGQnOiBcIkZldHRcIixcbiAgICAnSXRhbGljJzogXCJLdXJzaXZcIixcbiAgICAnSGVhZGluZyc6IFwiw5xiZXJzY2hyaWZ0XCIsXG4gICAgJ1VSTC9MaW5rJzogXCJMaW5rIGhpbnp1ZsO8Z2VuXCIsXG4gICAgJ0ltYWdlJzogXCJCaWxkIGhpbnp1ZsO8Z2VuXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJVbm51bW1lcmllcnRlIExpc3RlXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwiTnVtbWVyaWVydGUgTGlzdGVcIixcbiAgICAnQ29kZSc6IFwiUXVlbGx0ZXh0XCIsXG4gICAgJ1F1b3RlJzogXCJaaXRhdFwiLFxuICAgICdQcmV2aWV3JzogXCJWb3JzY2hhdVwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwiU2VociBiZXRvbnRlciBUZXh0XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwiQmV0b250ZXIgVGV4dFwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIsOcYmVyc2NocmlmdCBUZXh0XCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwiTGlua2Jlc2NocmVpYnVuZ1wiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJVUkxcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwiQmlsZGJlc2NocmVpYnVuZ1wiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJCaWxkLVVSTFwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJUaXRlbCBkZXMgQmlsZGVzXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJBdWZ6w6RobHVuZ3MtVGV4dFwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBTcGFuaXNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIGJ5IExlYW5kcm8gUG9ibGV0IDxsZWFuZHJvZHJob3VzZUBnbWFpbC5jb20+XG4gKi9cbjsoZnVuY3Rpb24oJCl7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXNbJ2VzJ10gPSB7XG4gICAgJ0JvbGQnOiBcIk5lZ3JpdGFcIixcbiAgICAnSXRhbGljJzogXCJJdMOhbGljYVwiLFxuICAgICdIZWFkaW5nJzogXCJUw610dWxvXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJJbnNlcnRlIHVuIGxpbmtcIixcbiAgICAnSW1hZ2UnOiBcIkluc2VydGUgdW5hIGltYWdlblwiLFxuICAgICdMaXN0JzogXCJMaXN0YSBkZSBpdGVtc1wiLFxuICAgICdQcmV2aWV3JzogXCJQcmV2aXN1YWxpemFyXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJ0ZXh0byBpbXBvcnRhbnRlXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwidGV4dG8gY29uIMOpbmZhc2lzXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwidGV4dG8gdGl0dWxhclwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcImRlc2NyaXBjacOzbiBkZWwgbGlua1wiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJJbnNlcnRlIHVuIGhpcGVydsOtbmN1bG9cIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwiZGVzY3JpcGNpw7NuIGRlIGxhIGltYWdlblwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJJbnNlcnRlIHVuYSBpbWFnZW4gY29uIHVuIGhpcGVydsOtbmN1bG9cIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwiSW5zZXJ0ZSB1bmEgaW1hZ2VuIGNvbiB0w610dWxvXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJsaXN0YSBjb24gdGV4dG9cIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogUGVyc2lhbihGYXJzaSkgdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogU2FqYWQgRGVoc2hpcmkgPFBlbGFrd2ViLmlyPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5mYSA9IHtcbiAgICAnQm9sZCc6IFwi2KrZiNm+2LFcIixcbiAgICAnSXRhbGljJzogXCLZhdmI2LHYqFwiLFxuICAgICdIZWFkaW5nJzogXCLYudmG2YjYp9mGXCIsXG4gICAgJ1VSTC9MaW5rJzogXCLZvtuM2YjZhtivXCIsXG4gICAgJ0ltYWdlJzogXCLYqti12YjbjNixXCIsXG4gICAgJ0xpc3QnOiBcItmB2YfYsdiz2KpcIixcbiAgICAnUHJldmlldyc6IFwi2b7bjNi0INmG2YXYp9uM2LRcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcItmF2KrZhiDYttiu24zZhVwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcItmG2YjYtNiq2Ycg2KrYp9qp24zYr9uMXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwi2LnZhtmI2KfZhlwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcItiq2YjYttuM2K3Yp9iqINm+24zZiNmG2K8g2LHYpyDYqNmG2YjbjNiz24zYry5cIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwi2b7bjNmI2YbYryDYsdinINiv2LHYrCDZhtmF2KfbjNuM2K86XCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcItiq2YjYttuM2K3bjCDYqNix2KfbjCDYqti12YjbjCDYqNmG2YjbjNiz24zYry5cIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwi2KLYr9ix2LMg2KrYtdmI24zYsSDYsdinINio2YbZiNuM2LPbjNivLlwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCLYudmG2YjYp9mGINiq2LXZiNuM2LEg2LHYpyDYp9uM2YbYrNinINio2YbZiNuM2LPbjNivXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCLZhdit2YQg2YXYqtmGINmB2YfYsdiz2KpcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogRnJlbmNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIEJlbm/DrnQgQm91cmdlb2lzIDxiaWVyZG9rQGdtYWlsLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMuZnIgPSB7XG4gICAgJ0JvbGQnOiBcIkdyYXNcIixcbiAgICAnSXRhbGljJzogXCJJdGFsaXF1ZVwiLFxuICAgICdIZWFkaW5nJzogXCJUaXRyZVwiLFxuICAgICdVUkwvTGluayc6IFwiSW5zw6lyZXIgdW4gbGllbiBIVFRQXCIsXG4gICAgJ0ltYWdlJzogXCJJbnPDqXJlciB1bmUgaW1hZ2VcIixcbiAgICAnTGlzdCc6IFwiTGlzdGUgw6AgcHVjZXNcIixcbiAgICAnUHJldmlldyc6IFwiUHLDqXZpc3VhbGlzZXJcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcInRleHRlIGltcG9ydGFudFwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcInRleHRlIGVuIGl0YWxpcXVlXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwidGV4dGUgZCdlbnTDqnRlXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwiZW50cmV6IGxhIGRlc2NyaXB0aW9uIGR1IGxpZW4gaWNpXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIkluc8OpcmV6IGxlIGxpZW4gaHlwZXJ0ZXh0ZVwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJlbnRyZXogbGEgZGVzY3JpcHRpb24gZGUgbCdpbWFnZSBpY2lcIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiSW5zw6lyZXogbGUgbGllbiBoeXBlcnRleHRlIGRlIGwnaW1hZ2VcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwiZW50cmV6IGxlIHRpdHJlIGRlIGwnaW1hZ2UgaWNpXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJ0ZXh0ZSDDoCBwdWNlIGljaVwiLFxuICAgICdTYXZlJzogXCJTYXV2ZWdhcmRlclwiLFxuICAgICdPcmRlcmVkIExpc3QnOiBcIkxpc3RlIG9yZG9ubsOpZVwiLFxuICAgICdVbm9yZGVyZWQgTGlzdCc6IFwiTGlzdGUgZMOpc29yZG9ubsOpZVwiLFxuICAgICdRdW90ZSc6IFwiQ2l0YXRpb25cIixcbiAgICAncXVvdGUgaGVyZSc6IFwiVm90cmUgY2l0YXRpb25cIixcbiAgICAnQ29kZSc6IFwiQ29kZVwiLFxuICAgICdjb2RlIHRleHQgaGVyZSc6IFwiw6ljcmlyZSBkdSBjb2RlIGljaVwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBKYXBhbmVzZSB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBLZW50YSBNdXJha2FtaSA8a250bXJrbUBnbWFpbC5jb20+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzWydqYSddID0ge1xuICAgICdCb2xkJzogXCLlpKrlrZdcIixcbiAgICAnSXRhbGljJzogXCLmlpzkvZNcIixcbiAgICAnSGVhZGluZyc6IFwi6KaL5Ye644GXXCIsXG4gICAgJ1VSTC9MaW5rJzogXCLjg6rjg7Pjgq9cIixcbiAgICAnSW1hZ2UnOiBcIueUu+WDj1wiLFxuICAgICdVbm9yZGVyZWQgTGlzdCc6IFwi44Oq44K544OIXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwi5pWw5a2X44Oq44K544OIXCIsXG4gICAgJ0NvZGUnOiBcIuOCs+ODvOODiVwiLFxuICAgICdRdW90ZSc6IFwi5byV55SoXCIsXG4gICAgJ1ByZXZpZXcnOiBcIuODl+ODrOODk+ODpeODvFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwi5aSq5a2XXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwi5by36Kq/XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwi6KaL5Ye644GXXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwi44Oq44Oz44Kv6Kqs5piOXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIuODquODs+OCr+aMv+WFpVwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCLnlLvlg4/oqqzmmI5cIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwi55S75YOP5oy/5YWlXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIueUu+WDj+OCv+OCpOODiOODq1wiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwi44Oq44K544OI5oy/5YWlXCIsXG4gICAgJ2NvZGUgdGV4dCBoZXJlJzogXCLjgrPjg7zjg4lcIixcbiAgICAncXVvdGUgaGVyZSc6IFwi5byV55So5oy/5YWlXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiArICogS29yZWFuIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiArICogV29vbmdCaSBLaW0gPHNzaW5zc0BnbWFpbC5jb20+XG4gKyAqL1xuOyhmdW5jdGlvbigkKXtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlc1sna3InXSA9IHtcbiAgICAnQm9sZCc6IFwi7KeE7ZWY6rKMXCIsXG4gICAgJ0l0YWxpYyc6IFwi7J207YOk66at7LK0XCIsXG4gICAgJ0hlYWRpbmcnOiBcIuuouOumrOq4gFwiLFxuICAgICdVUkwvTGluayc6IFwi66eB7YGs7KO87IaMXCIsXG4gICAgJ0ltYWdlJzogXCLsnbTrr7jsp4BcIixcbiAgICAnTGlzdCc6IFwi66as7Iqk7Yq4XCIsXG4gICAgJ1ByZXZpZXcnOiBcIuuvuOumrOuztOq4sFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwi6rCV7ZWcIOqwleyhsCDthY3siqTtirhcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCLqsJXsobAg7YWN7Iqk7Yq4XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwi66i466as6riAIO2FjeyKpO2KuFwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIuyXrOq4sOyXkCDrp4HtgazsnZgg7ISk66qF7J2EIOyggeycvOyEuOyalFwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCLtlZjsnbTtjbzrp4Htgawg7IK97J6FXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcIuyXrOq4sOyEuCDsnbTrr7jsp4Ag7ISk66qF7J2EIOyggeycvOyEuOyalFwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCLsnbTrr7jsp4Ag66eB7YGsIOyCveyehVwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCLsl6zquLDsl5Ag7J2066+47KeAIOygnOuqqeydhCDsoIHsnLzshLjsmpRcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcIuumrOyKpO2KuCDthY3siqTtirhcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogTm9yd2VnaWFuIGJva23DpWwgdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogVG9iaWFzIEJvaHdhbGxpIDxoaUBmdXRoci5pbz5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMubmIgPSB7XG4gICAgJ0JvbGQnOiAnRmV0JyxcbiAgICAnSXRhbGljJzogJ0t1cnNpdicsXG4gICAgJ0hlYWRpbmcnOiAnT3ZlcnNrcmlmdCcsXG4gICAgJ1VSTC9MaW5rJzogJ1VSTC9MZW5rZScsXG4gICAgJ0ltYWdlJzogJ0JpbGRlJyxcbiAgICAnTGlzdCc6ICdMaXN0ZScsXG4gICAgJ1ByZXZpZXcnOiAnRm9yaMOlbmRzdmlzbmluZycsXG4gICAgJ3N0cm9uZyB0ZXh0JzogJ3N0ZXJrIHRla3N0JyxcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogJ3N0cmVrZXQgdGVrc3QnLFxuICAgICdoZWFkaW5nIHRleHQnOiAnb3ZlcnNrcmlmdGVuIHRla3N0JyxcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogJ1Nrcml2IGxpbmtlbiBiZXNrcml2ZWxzZSBoZXInLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogJ1NldHQgaW5uIGxlbmtlJyxcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6ICdBbmdpIGJpbGRlYmVza3JpdmVsc2UgaGVyJyxcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6ICdTZXR0IGlubiBsZW5rZSBmb3IgYmlsZGUnLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogJ0FuZ2kgYmlsZGV0aXR0ZWwgaGVyJyxcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiAnbGlzdGUgdGVrc3QgaGVyJ1xuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogRHV0Y2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogSmVyb2VuIFRob3JhIDxqZXJvZW50aG9yYUBnbWFpbC5jb20+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLm5sID0ge1xuICAgICdCb2xkJzogXCJWZXRcIixcbiAgICAnSXRhbGljJzogXCJDdXJzaWVmXCIsXG4gICAgJ0hlYWRpbmcnOiBcIlRpdGVsXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJVUkwvTGlua1wiLFxuICAgICdJbWFnZSc6IFwiQWZiZWVsZGluZ1wiLFxuICAgICdMaXN0JzogXCJMaWpzdFwiLFxuICAgICdQcmV2aWV3JzogXCJWb29yYmVlbGRcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcInZldCBnZWRydWt0ZSB0ZWtzdFwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcInNjaHVpbiBnZWRydWt0ZSB0ZWtzdFwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIlRpdGVsXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwiVm9lciBlZW4gbGluayBiZXNjaHJpanZpbmcgaW5cIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiVm9lciBlZW4gaHR0cCBsaW5rIGluXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcIlZvZXIgZWVuIGFmYmVlbGRpbmcgYmVzY2hyaWp2aW5nIGluXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIlZvZXIgZWVuIGFmYmVlbGRpbmcgbGluayBpblwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJWb2VyIGRlIGFmYmVlbGRpbmcgdGl0ZWwgaW5cIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcImxpanN0IGl0ZW1cIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogUG9saXNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIE1hcmVrIEthcHV0XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLnBsID0ge1xuICAgICdCb2xkJzogXCJQb2dydWJpZW5pZVwiLFxuICAgICdJdGFsaWMnOiBcIkt1cnN5d2FcIixcbiAgICAnSGVhZGluZyc6IFwiTmFnxYLDs3dla1wiLFxuICAgICdVUkwvTGluayc6IFwiV3N0YXcgbGlua1wiLFxuICAgICdJbWFnZSc6IFwiV3N0YXcgb2JyYXpla1wiLFxuICAgICdVbm9yZGVyZWQgTGlzdCc6IFwiTGlzdGEgcHVua3Rvd2FuYVwiLFxuICAgICdPcmRlcmVkIExpc3QnOiBcIkxpc3RhIG51bWVyb3dhbmFcIixcbiAgICAnQ29kZSc6IFwiS29kIMW6csOzZMWCb3d5XCIsXG4gICAgJ1F1b3RlJzogXCJDeXRhdFwiLFxuICAgICdQcmV2aWV3JzogXCJQb2RnbMSFZFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwicG9ncnViaW9ueSB0ZWtzdFwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcInBvY2h5bG9ueSB0ZWtzdFwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIm5hZ8WCw7N3ZWtcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJvcGlzIGxpbmthXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIldzdGF3IGxpbmtcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwib3BpcyBvYnJhemthXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIldzdGF3IG9icmF6ZWtcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwidHl0dcWCIG9icmF6a2FcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcImxpc3RhXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIFNsb3ZlbmlhbiB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBEYXZvciBQYWRvdmFuIDxkYXZvci5wYWRvdmFuQGdtYWlsLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMuc2wgPSB7XG4gICAgJ0JvbGQnOiBcIk9kZWJlbGplbm9cIixcbiAgICAnSXRhbGljJzogXCJQb8WhZXZub1wiLFxuICAgICdIZWFkaW5nJzogXCJOYXNsb3ZcIixcbiAgICAnVVJML0xpbmsnOiBcIlBvdmV6YXZhXCIsXG4gICAgJ0ltYWdlJzogXCJTbGlrYVwiLFxuICAgICdVbm9yZGVyZWQgTGlzdCc6IFwiTmV1cmVqZW4gc2V6bmFtXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwiVXJlamVuIHNlem5hbVwiLFxuICAgICdDb2RlJzogXCJLb2RhXCIsXG4gICAgJ1F1b3RlJzogXCJDaXRhdFwiLFxuICAgICdQcmV2aWV3JzogXCJQcmVkb2dsZWRcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcIm9kZWJlbGplbm8gYmVzZWRpbG9cIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJwb8WhZXZubyBiZXNlZGlsb1wiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIm5hc2xvdlwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIm9waXMgcG92ZXphdmVcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiVnN0YXZpIHBvdmV6YXZvXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcIm9waXMgc2xpa2VcIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiVnN0YXZpIHBvdmV6YXZvIGRvIHNsaWtlXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIm5hc2xvdiBzbGlrZVwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwic2V6bmFtXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIFN3ZWRpc2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogVG9iaWFzIEJvaHdhbGxpIDxoaUBmdXRoci5pbz5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMuc3YgPSB7XG4gICAgJ0JvbGQnOiAnRmV0JyxcbiAgICAnSXRhbGljJzogJ0t1cnNpdicsXG4gICAgJ0hlYWRpbmcnOiAnUnVicmlrJyxcbiAgICAnVVJML0xpbmsnOiAnVVJML0zDpG5rJyxcbiAgICAnSW1hZ2UnOiAnQmlsZCcsXG4gICAgJ0xpc3QnOiAnTGlzdGEnLFxuICAgICdQcmV2aWV3JzogJ0bDtnJoYW5kc2dyYW5za2EnLFxuICAgICdzdHJvbmcgdGV4dCc6ICdmZXQgdGV4dCcsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6ICfDtnZlcnN0cnVrZW4gdGV4dCcsXG4gICAgJ2hlYWRpbmcgdGV4dCc6ICdSdWJyaWsnLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiAnQW5nZSBsw6RuayBiZXNrcml2bmluZyBow6RyJyxcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6ICdTw6R0dCBpbiBsw6RuaycsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiAnQW5nZSBiaWxkIGJlc2tyaXZuaW5nIGjDpHInLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogJ1PDpHR0IGluIGzDpG5rIGbDtnIgYmlsZCcsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiAnQW5nZSBiaWxkIHJ1YnJpayBow6RyJyxcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiAnbGlzdCB0ZXh0J1xuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogVHVya2lzaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBTZXJrYW4gQWxndXIgPGluZm9Ad3BhZGFtaS5jb20+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLnRyID0ge1xuICAgICdCb2xkJzogXCJLYWzEsW5cIixcbiAgICAnSXRhbGljJzogXCLEsHRhbGlrXCIsXG4gICAgJ0hlYWRpbmcnOiBcIkJhxZ9sxLFrXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJMaW5rIGVrbGVcIixcbiAgICAnSW1hZ2UnOiBcIlJlc2ltIGVrbGVcIixcbiAgICAnTGlzdCc6IFwiTGlzdGUgT2x1xZ90dXJ1blwiLFxuICAgICdQcmV2aWV3JzogXCLDlm5pemxlbWVcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcImthbMSxbiB5YXrEsVwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcIml0YWxpayB5YXrEsVwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIkJhxZ9sxLFrIFlhesSxc8SxXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwiTGluayBhw6fEsWtsYW1hc8SxbsSxIGJ1cmF5YSBnaXJpblwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCLEsG50ZXJuZXQgYWRyZXNpIGdpcmluXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcInJlc2ltIGHDp8Sxa2xhbWFzxLFuxLEgYnVyYXlhIGVrbGV5aW5cIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiUmVzaW0gbGlua2luaSBla2xleWluXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcInJlc2ltIGJhxZ9sxLHEn8SxbsSxIGJ1cmF5YSBla2xleWluXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJsaXN0ZSB5YXrEsXPEsVwiLFxuICAgICdTYXZlJyA6IFwiS2F5ZGV0XCIsXG4gICAgJ09yZGVyZWQgTGlzdCcgOiBcIk51bWFyYWzEsSBMaXN0ZVwiLFxuICAgICdVbm9yZGVyZWQgTGlzdCcgOiBcIk1hZGRlIGltbGkgbGlzdGVcIixcbiAgICAnUXVvdGUnIDogXCJBbMSxbnTEsVwiLFxuICAgICdxdW90ZSBoZXJlJyA6IFwiYWzEsW50xLF5xLEgYnVyYXlhIGVrbGV5aW5cIixcbiAgICAnQ29kZScgOiBcIktvZFwiLFxuICAgICdjb2RlIHRleHQgaGVyZScgOiBcImtvZHUgYnVyYXlhIGVrbGV5aW5cIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogQ2hpbmVzZSB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBiZW5oYWlsZSA8ZGVuZ2hhaWVyQDE2My5jb20+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLnpoID0ge1xuICAgICdCb2xkJzogXCLnspfkvZNcIixcbiAgICAnSXRhbGljJzogXCLmlpzkvZNcIixcbiAgICAnSGVhZGluZyc6IFwi5qCH6aKYXCIsXG4gICAgJ1VSTC9MaW5rJzogXCLpk77mjqVcIixcbiAgICAnSW1hZ2UnOiBcIuWbvueJh1wiLFxuICAgICdMaXN0JzogXCLliJfooahcIixcbiAgICAnVW5vcmRlcmVkIExpc3QnOiBcIuaXoOW6j+WIl+ihqFwiLFxuICAgICdPcmRlcmVkIExpc3QnOiBcIuacieW6j+WIl+ihqFwiLFxuICAgICdDb2RlJzogXCLku6PnoIFcIixcbiAgICAnUXVvdGUnOiBcIuW8leeUqFwiLFxuICAgICdQcmV2aWV3JzogXCLpooTop4hcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcIueyl+S9k1wiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcIuW8uuiwg1wiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcIuagh+mimFwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIui+k+WFpemTvuaOpeivtOaYjlwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJVUkzlnLDlnYBcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwi6L6T5YWl5Zu+54mH6K+05piOXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIuWbvueJh1VSTOWcsOWdgFwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCLlnKjov5nph4zovpPlhaXlm77niYfmoIfpophcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcIui/memHjOaYr+WIl+ihqOaWh+acrFwiLFxuICAgICdjb2RlIHRleHQgaGVyZSc6IFwi6L+Z6YeM6L6T5YWl5Luj56CBXCIsXG4gICAgJ3F1b3RlIGhlcmUnOiBcIui/memHjOi+k+WFpeW8leeUqOaWh+acrFwiXG5cblxuICB9O1xufShqUXVlcnkpKTtcbiIsIihmdW5jdGlvbiBkZWZpbmVNdXN0YWNoZShnbG9iYWwsZmFjdG9yeSl7aWYodHlwZW9mIGV4cG9ydHM9PT1cIm9iamVjdFwiJiZleHBvcnRzJiZ0eXBlb2YgZXhwb3J0cy5ub2RlTmFtZSE9PVwic3RyaW5nXCIpe2ZhY3RvcnkoZXhwb3J0cyl9ZWxzZSBpZih0eXBlb2YgZGVmaW5lPT09XCJmdW5jdGlvblwiJiZkZWZpbmUuYW1kKXtkZWZpbmUoW1wiZXhwb3J0c1wiXSxmYWN0b3J5KX1lbHNle2dsb2JhbC5NdXN0YWNoZT17fTtmYWN0b3J5KGdsb2JhbC5NdXN0YWNoZSl9fSkodGhpcyxmdW5jdGlvbiBtdXN0YWNoZUZhY3RvcnkobXVzdGFjaGUpe3ZhciBvYmplY3RUb1N0cmluZz1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO3ZhciBpc0FycmF5PUFycmF5LmlzQXJyYXl8fGZ1bmN0aW9uIGlzQXJyYXlQb2x5ZmlsbChvYmplY3Qpe3JldHVybiBvYmplY3RUb1N0cmluZy5jYWxsKG9iamVjdCk9PT1cIltvYmplY3QgQXJyYXldXCJ9O2Z1bmN0aW9uIGlzRnVuY3Rpb24ob2JqZWN0KXtyZXR1cm4gdHlwZW9mIG9iamVjdD09PVwiZnVuY3Rpb25cIn1mdW5jdGlvbiB0eXBlU3RyKG9iail7cmV0dXJuIGlzQXJyYXkob2JqKT9cImFycmF5XCI6dHlwZW9mIG9ian1mdW5jdGlvbiBlc2NhcGVSZWdFeHAoc3RyaW5nKXtyZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1tcXC1cXFtcXF17fSgpKis/LixcXFxcXFxeJHwjXFxzXS9nLFwiXFxcXCQmXCIpfWZ1bmN0aW9uIGhhc1Byb3BlcnR5KG9iaixwcm9wTmFtZSl7cmV0dXJuIG9iaiE9bnVsbCYmdHlwZW9mIG9iaj09PVwib2JqZWN0XCImJnByb3BOYW1lIGluIG9ian1mdW5jdGlvbiBwcmltaXRpdmVIYXNPd25Qcm9wZXJ0eShwcmltaXRpdmUscHJvcE5hbWUpe3JldHVybiBwcmltaXRpdmUhPW51bGwmJnR5cGVvZiBwcmltaXRpdmUhPT1cIm9iamVjdFwiJiZwcmltaXRpdmUuaGFzT3duUHJvcGVydHkmJnByaW1pdGl2ZS5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSl9dmFyIHJlZ0V4cFRlc3Q9UmVnRXhwLnByb3RvdHlwZS50ZXN0O2Z1bmN0aW9uIHRlc3RSZWdFeHAocmUsc3RyaW5nKXtyZXR1cm4gcmVnRXhwVGVzdC5jYWxsKHJlLHN0cmluZyl9dmFyIG5vblNwYWNlUmU9L1xcUy87ZnVuY3Rpb24gaXNXaGl0ZXNwYWNlKHN0cmluZyl7cmV0dXJuIXRlc3RSZWdFeHAobm9uU3BhY2VSZSxzdHJpbmcpfXZhciBlbnRpdHlNYXA9e1wiJlwiOlwiJmFtcDtcIixcIjxcIjpcIiZsdDtcIixcIj5cIjpcIiZndDtcIiwnXCInOlwiJnF1b3Q7XCIsXCInXCI6XCImIzM5O1wiLFwiL1wiOlwiJiN4MkY7XCIsXCJgXCI6XCImI3g2MDtcIixcIj1cIjpcIiYjeDNEO1wifTtmdW5jdGlvbiBlc2NhcGVIdG1sKHN0cmluZyl7cmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoL1smPD5cIidgPVxcL10vZyxmdW5jdGlvbiBmcm9tRW50aXR5TWFwKHMpe3JldHVybiBlbnRpdHlNYXBbc119KX12YXIgd2hpdGVSZT0vXFxzKi87dmFyIHNwYWNlUmU9L1xccysvO3ZhciBlcXVhbHNSZT0vXFxzKj0vO3ZhciBjdXJseVJlPS9cXHMqXFx9Lzt2YXIgdGFnUmU9LyN8XFxefFxcL3w+fFxce3wmfD18IS87ZnVuY3Rpb24gcGFyc2VUZW1wbGF0ZSh0ZW1wbGF0ZSx0YWdzKXtpZighdGVtcGxhdGUpcmV0dXJuW107dmFyIGxpbmVIYXNOb25TcGFjZT1mYWxzZTt2YXIgc2VjdGlvbnM9W107dmFyIHRva2Vucz1bXTt2YXIgc3BhY2VzPVtdO3ZhciBoYXNUYWc9ZmFsc2U7dmFyIG5vblNwYWNlPWZhbHNlO3ZhciBpbmRlbnRhdGlvbj1cIlwiO3ZhciB0YWdJbmRleD0wO2Z1bmN0aW9uIHN0cmlwU3BhY2UoKXtpZihoYXNUYWcmJiFub25TcGFjZSl7d2hpbGUoc3BhY2VzLmxlbmd0aClkZWxldGUgdG9rZW5zW3NwYWNlcy5wb3AoKV19ZWxzZXtzcGFjZXM9W119aGFzVGFnPWZhbHNlO25vblNwYWNlPWZhbHNlfXZhciBvcGVuaW5nVGFnUmUsY2xvc2luZ1RhZ1JlLGNsb3NpbmdDdXJseVJlO2Z1bmN0aW9uIGNvbXBpbGVUYWdzKHRhZ3NUb0NvbXBpbGUpe2lmKHR5cGVvZiB0YWdzVG9Db21waWxlPT09XCJzdHJpbmdcIil0YWdzVG9Db21waWxlPXRhZ3NUb0NvbXBpbGUuc3BsaXQoc3BhY2VSZSwyKTtpZighaXNBcnJheSh0YWdzVG9Db21waWxlKXx8dGFnc1RvQ29tcGlsZS5sZW5ndGghPT0yKXRocm93IG5ldyBFcnJvcihcIkludmFsaWQgdGFnczogXCIrdGFnc1RvQ29tcGlsZSk7b3BlbmluZ1RhZ1JlPW5ldyBSZWdFeHAoZXNjYXBlUmVnRXhwKHRhZ3NUb0NvbXBpbGVbMF0pK1wiXFxcXHMqXCIpO2Nsb3NpbmdUYWdSZT1uZXcgUmVnRXhwKFwiXFxcXHMqXCIrZXNjYXBlUmVnRXhwKHRhZ3NUb0NvbXBpbGVbMV0pKTtjbG9zaW5nQ3VybHlSZT1uZXcgUmVnRXhwKFwiXFxcXHMqXCIrZXNjYXBlUmVnRXhwKFwifVwiK3RhZ3NUb0NvbXBpbGVbMV0pKX1jb21waWxlVGFncyh0YWdzfHxtdXN0YWNoZS50YWdzKTt2YXIgc2Nhbm5lcj1uZXcgU2Nhbm5lcih0ZW1wbGF0ZSk7dmFyIHN0YXJ0LHR5cGUsdmFsdWUsY2hyLHRva2VuLG9wZW5TZWN0aW9uO3doaWxlKCFzY2FubmVyLmVvcygpKXtzdGFydD1zY2FubmVyLnBvczt2YWx1ZT1zY2FubmVyLnNjYW5VbnRpbChvcGVuaW5nVGFnUmUpO2lmKHZhbHVlKXtmb3IodmFyIGk9MCx2YWx1ZUxlbmd0aD12YWx1ZS5sZW5ndGg7aTx2YWx1ZUxlbmd0aDsrK2kpe2Nocj12YWx1ZS5jaGFyQXQoaSk7aWYoaXNXaGl0ZXNwYWNlKGNocikpe3NwYWNlcy5wdXNoKHRva2Vucy5sZW5ndGgpO2luZGVudGF0aW9uKz1jaHJ9ZWxzZXtub25TcGFjZT10cnVlO2xpbmVIYXNOb25TcGFjZT10cnVlO2luZGVudGF0aW9uKz1cIiBcIn10b2tlbnMucHVzaChbXCJ0ZXh0XCIsY2hyLHN0YXJ0LHN0YXJ0KzFdKTtzdGFydCs9MTtpZihjaHI9PT1cIlxcblwiKXtzdHJpcFNwYWNlKCk7aW5kZW50YXRpb249XCJcIjt0YWdJbmRleD0wO2xpbmVIYXNOb25TcGFjZT1mYWxzZX19fWlmKCFzY2FubmVyLnNjYW4ob3BlbmluZ1RhZ1JlKSlicmVhaztoYXNUYWc9dHJ1ZTt0eXBlPXNjYW5uZXIuc2Nhbih0YWdSZSl8fFwibmFtZVwiO3NjYW5uZXIuc2Nhbih3aGl0ZVJlKTtpZih0eXBlPT09XCI9XCIpe3ZhbHVlPXNjYW5uZXIuc2NhblVudGlsKGVxdWFsc1JlKTtzY2FubmVyLnNjYW4oZXF1YWxzUmUpO3NjYW5uZXIuc2NhblVudGlsKGNsb3NpbmdUYWdSZSl9ZWxzZSBpZih0eXBlPT09XCJ7XCIpe3ZhbHVlPXNjYW5uZXIuc2NhblVudGlsKGNsb3NpbmdDdXJseVJlKTtzY2FubmVyLnNjYW4oY3VybHlSZSk7c2Nhbm5lci5zY2FuVW50aWwoY2xvc2luZ1RhZ1JlKTt0eXBlPVwiJlwifWVsc2V7dmFsdWU9c2Nhbm5lci5zY2FuVW50aWwoY2xvc2luZ1RhZ1JlKX1pZighc2Nhbm5lci5zY2FuKGNsb3NpbmdUYWdSZSkpdGhyb3cgbmV3IEVycm9yKFwiVW5jbG9zZWQgdGFnIGF0IFwiK3NjYW5uZXIucG9zKTtpZih0eXBlPT1cIj5cIil7dG9rZW49W3R5cGUsdmFsdWUsc3RhcnQsc2Nhbm5lci5wb3MsaW5kZW50YXRpb24sdGFnSW5kZXgsbGluZUhhc05vblNwYWNlXX1lbHNle3Rva2VuPVt0eXBlLHZhbHVlLHN0YXJ0LHNjYW5uZXIucG9zXX10YWdJbmRleCsrO3Rva2Vucy5wdXNoKHRva2VuKTtpZih0eXBlPT09XCIjXCJ8fHR5cGU9PT1cIl5cIil7c2VjdGlvbnMucHVzaCh0b2tlbil9ZWxzZSBpZih0eXBlPT09XCIvXCIpe29wZW5TZWN0aW9uPXNlY3Rpb25zLnBvcCgpO2lmKCFvcGVuU2VjdGlvbil0aHJvdyBuZXcgRXJyb3IoJ1Vub3BlbmVkIHNlY3Rpb24gXCInK3ZhbHVlKydcIiBhdCAnK3N0YXJ0KTtpZihvcGVuU2VjdGlvblsxXSE9PXZhbHVlKXRocm93IG5ldyBFcnJvcignVW5jbG9zZWQgc2VjdGlvbiBcIicrb3BlblNlY3Rpb25bMV0rJ1wiIGF0ICcrc3RhcnQpfWVsc2UgaWYodHlwZT09PVwibmFtZVwifHx0eXBlPT09XCJ7XCJ8fHR5cGU9PT1cIiZcIil7bm9uU3BhY2U9dHJ1ZX1lbHNlIGlmKHR5cGU9PT1cIj1cIil7Y29tcGlsZVRhZ3ModmFsdWUpfX1zdHJpcFNwYWNlKCk7b3BlblNlY3Rpb249c2VjdGlvbnMucG9wKCk7aWYob3BlblNlY3Rpb24pdGhyb3cgbmV3IEVycm9yKCdVbmNsb3NlZCBzZWN0aW9uIFwiJytvcGVuU2VjdGlvblsxXSsnXCIgYXQgJytzY2FubmVyLnBvcyk7cmV0dXJuIG5lc3RUb2tlbnMoc3F1YXNoVG9rZW5zKHRva2VucykpfWZ1bmN0aW9uIHNxdWFzaFRva2Vucyh0b2tlbnMpe3ZhciBzcXVhc2hlZFRva2Vucz1bXTt2YXIgdG9rZW4sbGFzdFRva2VuO2Zvcih2YXIgaT0wLG51bVRva2Vucz10b2tlbnMubGVuZ3RoO2k8bnVtVG9rZW5zOysraSl7dG9rZW49dG9rZW5zW2ldO2lmKHRva2VuKXtpZih0b2tlblswXT09PVwidGV4dFwiJiZsYXN0VG9rZW4mJmxhc3RUb2tlblswXT09PVwidGV4dFwiKXtsYXN0VG9rZW5bMV0rPXRva2VuWzFdO2xhc3RUb2tlblszXT10b2tlblszXX1lbHNle3NxdWFzaGVkVG9rZW5zLnB1c2godG9rZW4pO2xhc3RUb2tlbj10b2tlbn19fXJldHVybiBzcXVhc2hlZFRva2Vuc31mdW5jdGlvbiBuZXN0VG9rZW5zKHRva2Vucyl7dmFyIG5lc3RlZFRva2Vucz1bXTt2YXIgY29sbGVjdG9yPW5lc3RlZFRva2Vuczt2YXIgc2VjdGlvbnM9W107dmFyIHRva2VuLHNlY3Rpb247Zm9yKHZhciBpPTAsbnVtVG9rZW5zPXRva2Vucy5sZW5ndGg7aTxudW1Ub2tlbnM7KytpKXt0b2tlbj10b2tlbnNbaV07c3dpdGNoKHRva2VuWzBdKXtjYXNlXCIjXCI6Y2FzZVwiXlwiOmNvbGxlY3Rvci5wdXNoKHRva2VuKTtzZWN0aW9ucy5wdXNoKHRva2VuKTtjb2xsZWN0b3I9dG9rZW5bNF09W107YnJlYWs7Y2FzZVwiL1wiOnNlY3Rpb249c2VjdGlvbnMucG9wKCk7c2VjdGlvbls1XT10b2tlblsyXTtjb2xsZWN0b3I9c2VjdGlvbnMubGVuZ3RoPjA/c2VjdGlvbnNbc2VjdGlvbnMubGVuZ3RoLTFdWzRdOm5lc3RlZFRva2VuczticmVhaztkZWZhdWx0OmNvbGxlY3Rvci5wdXNoKHRva2VuKX19cmV0dXJuIG5lc3RlZFRva2Vuc31mdW5jdGlvbiBTY2FubmVyKHN0cmluZyl7dGhpcy5zdHJpbmc9c3RyaW5nO3RoaXMudGFpbD1zdHJpbmc7dGhpcy5wb3M9MH1TY2FubmVyLnByb3RvdHlwZS5lb3M9ZnVuY3Rpb24gZW9zKCl7cmV0dXJuIHRoaXMudGFpbD09PVwiXCJ9O1NjYW5uZXIucHJvdG90eXBlLnNjYW49ZnVuY3Rpb24gc2NhbihyZSl7dmFyIG1hdGNoPXRoaXMudGFpbC5tYXRjaChyZSk7aWYoIW1hdGNofHxtYXRjaC5pbmRleCE9PTApcmV0dXJuXCJcIjt2YXIgc3RyaW5nPW1hdGNoWzBdO3RoaXMudGFpbD10aGlzLnRhaWwuc3Vic3RyaW5nKHN0cmluZy5sZW5ndGgpO3RoaXMucG9zKz1zdHJpbmcubGVuZ3RoO3JldHVybiBzdHJpbmd9O1NjYW5uZXIucHJvdG90eXBlLnNjYW5VbnRpbD1mdW5jdGlvbiBzY2FuVW50aWwocmUpe3ZhciBpbmRleD10aGlzLnRhaWwuc2VhcmNoKHJlKSxtYXRjaDtzd2l0Y2goaW5kZXgpe2Nhc2UtMTptYXRjaD10aGlzLnRhaWw7dGhpcy50YWlsPVwiXCI7YnJlYWs7Y2FzZSAwOm1hdGNoPVwiXCI7YnJlYWs7ZGVmYXVsdDptYXRjaD10aGlzLnRhaWwuc3Vic3RyaW5nKDAsaW5kZXgpO3RoaXMudGFpbD10aGlzLnRhaWwuc3Vic3RyaW5nKGluZGV4KX10aGlzLnBvcys9bWF0Y2gubGVuZ3RoO3JldHVybiBtYXRjaH07ZnVuY3Rpb24gQ29udGV4dCh2aWV3LHBhcmVudENvbnRleHQpe3RoaXMudmlldz12aWV3O3RoaXMuY2FjaGU9e1wiLlwiOnRoaXMudmlld307dGhpcy5wYXJlbnQ9cGFyZW50Q29udGV4dH1Db250ZXh0LnByb3RvdHlwZS5wdXNoPWZ1bmN0aW9uIHB1c2godmlldyl7cmV0dXJuIG5ldyBDb250ZXh0KHZpZXcsdGhpcyl9O0NvbnRleHQucHJvdG90eXBlLmxvb2t1cD1mdW5jdGlvbiBsb29rdXAobmFtZSl7dmFyIGNhY2hlPXRoaXMuY2FjaGU7dmFyIHZhbHVlO2lmKGNhY2hlLmhhc093blByb3BlcnR5KG5hbWUpKXt2YWx1ZT1jYWNoZVtuYW1lXX1lbHNle3ZhciBjb250ZXh0PXRoaXMsaW50ZXJtZWRpYXRlVmFsdWUsbmFtZXMsaW5kZXgsbG9va3VwSGl0PWZhbHNlO3doaWxlKGNvbnRleHQpe2lmKG5hbWUuaW5kZXhPZihcIi5cIik+MCl7aW50ZXJtZWRpYXRlVmFsdWU9Y29udGV4dC52aWV3O25hbWVzPW5hbWUuc3BsaXQoXCIuXCIpO2luZGV4PTA7d2hpbGUoaW50ZXJtZWRpYXRlVmFsdWUhPW51bGwmJmluZGV4PG5hbWVzLmxlbmd0aCl7aWYoaW5kZXg9PT1uYW1lcy5sZW5ndGgtMSlsb29rdXBIaXQ9aGFzUHJvcGVydHkoaW50ZXJtZWRpYXRlVmFsdWUsbmFtZXNbaW5kZXhdKXx8cHJpbWl0aXZlSGFzT3duUHJvcGVydHkoaW50ZXJtZWRpYXRlVmFsdWUsbmFtZXNbaW5kZXhdKTtpbnRlcm1lZGlhdGVWYWx1ZT1pbnRlcm1lZGlhdGVWYWx1ZVtuYW1lc1tpbmRleCsrXV19fWVsc2V7aW50ZXJtZWRpYXRlVmFsdWU9Y29udGV4dC52aWV3W25hbWVdO2xvb2t1cEhpdD1oYXNQcm9wZXJ0eShjb250ZXh0LnZpZXcsbmFtZSl9aWYobG9va3VwSGl0KXt2YWx1ZT1pbnRlcm1lZGlhdGVWYWx1ZTticmVha31jb250ZXh0PWNvbnRleHQucGFyZW50fWNhY2hlW25hbWVdPXZhbHVlfWlmKGlzRnVuY3Rpb24odmFsdWUpKXZhbHVlPXZhbHVlLmNhbGwodGhpcy52aWV3KTtyZXR1cm4gdmFsdWV9O2Z1bmN0aW9uIFdyaXRlcigpe3RoaXMuY2FjaGU9e319V3JpdGVyLnByb3RvdHlwZS5jbGVhckNhY2hlPWZ1bmN0aW9uIGNsZWFyQ2FjaGUoKXt0aGlzLmNhY2hlPXt9fTtXcml0ZXIucHJvdG90eXBlLnBhcnNlPWZ1bmN0aW9uIHBhcnNlKHRlbXBsYXRlLHRhZ3Mpe3ZhciBjYWNoZT10aGlzLmNhY2hlO3ZhciBjYWNoZUtleT10ZW1wbGF0ZStcIjpcIisodGFnc3x8bXVzdGFjaGUudGFncykuam9pbihcIjpcIik7dmFyIHRva2Vucz1jYWNoZVtjYWNoZUtleV07aWYodG9rZW5zPT1udWxsKXRva2Vucz1jYWNoZVtjYWNoZUtleV09cGFyc2VUZW1wbGF0ZSh0ZW1wbGF0ZSx0YWdzKTtyZXR1cm4gdG9rZW5zfTtXcml0ZXIucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbiByZW5kZXIodGVtcGxhdGUsdmlldyxwYXJ0aWFscyx0YWdzKXt2YXIgdG9rZW5zPXRoaXMucGFyc2UodGVtcGxhdGUsdGFncyk7dmFyIGNvbnRleHQ9dmlldyBpbnN0YW5jZW9mIENvbnRleHQ/dmlldzpuZXcgQ29udGV4dCh2aWV3KTtyZXR1cm4gdGhpcy5yZW5kZXJUb2tlbnModG9rZW5zLGNvbnRleHQscGFydGlhbHMsdGVtcGxhdGUsdGFncyl9O1dyaXRlci5wcm90b3R5cGUucmVuZGVyVG9rZW5zPWZ1bmN0aW9uIHJlbmRlclRva2Vucyh0b2tlbnMsY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlLHRhZ3Mpe3ZhciBidWZmZXI9XCJcIjt2YXIgdG9rZW4sc3ltYm9sLHZhbHVlO2Zvcih2YXIgaT0wLG51bVRva2Vucz10b2tlbnMubGVuZ3RoO2k8bnVtVG9rZW5zOysraSl7dmFsdWU9dW5kZWZpbmVkO3Rva2VuPXRva2Vuc1tpXTtzeW1ib2w9dG9rZW5bMF07aWYoc3ltYm9sPT09XCIjXCIpdmFsdWU9dGhpcy5yZW5kZXJTZWN0aW9uKHRva2VuLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSk7ZWxzZSBpZihzeW1ib2w9PT1cIl5cIil2YWx1ZT10aGlzLnJlbmRlckludmVydGVkKHRva2VuLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSk7ZWxzZSBpZihzeW1ib2w9PT1cIj5cIil2YWx1ZT10aGlzLnJlbmRlclBhcnRpYWwodG9rZW4sY29udGV4dCxwYXJ0aWFscyx0YWdzKTtlbHNlIGlmKHN5bWJvbD09PVwiJlwiKXZhbHVlPXRoaXMudW5lc2NhcGVkVmFsdWUodG9rZW4sY29udGV4dCk7ZWxzZSBpZihzeW1ib2w9PT1cIm5hbWVcIil2YWx1ZT10aGlzLmVzY2FwZWRWYWx1ZSh0b2tlbixjb250ZXh0KTtlbHNlIGlmKHN5bWJvbD09PVwidGV4dFwiKXZhbHVlPXRoaXMucmF3VmFsdWUodG9rZW4pO2lmKHZhbHVlIT09dW5kZWZpbmVkKWJ1ZmZlcis9dmFsdWV9cmV0dXJuIGJ1ZmZlcn07V3JpdGVyLnByb3RvdHlwZS5yZW5kZXJTZWN0aW9uPWZ1bmN0aW9uIHJlbmRlclNlY3Rpb24odG9rZW4sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKXt2YXIgc2VsZj10aGlzO3ZhciBidWZmZXI9XCJcIjt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2Z1bmN0aW9uIHN1YlJlbmRlcih0ZW1wbGF0ZSl7cmV0dXJuIHNlbGYucmVuZGVyKHRlbXBsYXRlLGNvbnRleHQscGFydGlhbHMpfWlmKCF2YWx1ZSlyZXR1cm47aWYoaXNBcnJheSh2YWx1ZSkpe2Zvcih2YXIgaj0wLHZhbHVlTGVuZ3RoPXZhbHVlLmxlbmd0aDtqPHZhbHVlTGVuZ3RoOysrail7YnVmZmVyKz10aGlzLnJlbmRlclRva2Vucyh0b2tlbls0XSxjb250ZXh0LnB1c2godmFsdWVbal0pLHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUpfX1lbHNlIGlmKHR5cGVvZiB2YWx1ZT09PVwib2JqZWN0XCJ8fHR5cGVvZiB2YWx1ZT09PVwic3RyaW5nXCJ8fHR5cGVvZiB2YWx1ZT09PVwibnVtYmVyXCIpe2J1ZmZlcis9dGhpcy5yZW5kZXJUb2tlbnModG9rZW5bNF0sY29udGV4dC5wdXNoKHZhbHVlKSxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKX1lbHNlIGlmKGlzRnVuY3Rpb24odmFsdWUpKXtpZih0eXBlb2Ygb3JpZ2luYWxUZW1wbGF0ZSE9PVwic3RyaW5nXCIpdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IHVzZSBoaWdoZXItb3JkZXIgc2VjdGlvbnMgd2l0aG91dCB0aGUgb3JpZ2luYWwgdGVtcGxhdGVcIik7dmFsdWU9dmFsdWUuY2FsbChjb250ZXh0LnZpZXcsb3JpZ2luYWxUZW1wbGF0ZS5zbGljZSh0b2tlblszXSx0b2tlbls1XSksc3ViUmVuZGVyKTtpZih2YWx1ZSE9bnVsbClidWZmZXIrPXZhbHVlfWVsc2V7YnVmZmVyKz10aGlzLnJlbmRlclRva2Vucyh0b2tlbls0XSxjb250ZXh0LHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUpfXJldHVybiBidWZmZXJ9O1dyaXRlci5wcm90b3R5cGUucmVuZGVySW52ZXJ0ZWQ9ZnVuY3Rpb24gcmVuZGVySW52ZXJ0ZWQodG9rZW4sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKXt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2lmKCF2YWx1ZXx8aXNBcnJheSh2YWx1ZSkmJnZhbHVlLmxlbmd0aD09PTApcmV0dXJuIHRoaXMucmVuZGVyVG9rZW5zKHRva2VuWzRdLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSl9O1dyaXRlci5wcm90b3R5cGUuaW5kZW50UGFydGlhbD1mdW5jdGlvbiBpbmRlbnRQYXJ0aWFsKHBhcnRpYWwsaW5kZW50YXRpb24sbGluZUhhc05vblNwYWNlKXt2YXIgZmlsdGVyZWRJbmRlbnRhdGlvbj1pbmRlbnRhdGlvbi5yZXBsYWNlKC9bXiBcXHRdL2csXCJcIik7dmFyIHBhcnRpYWxCeU5sPXBhcnRpYWwuc3BsaXQoXCJcXG5cIik7Zm9yKHZhciBpPTA7aTxwYXJ0aWFsQnlObC5sZW5ndGg7aSsrKXtpZihwYXJ0aWFsQnlObFtpXS5sZW5ndGgmJihpPjB8fCFsaW5lSGFzTm9uU3BhY2UpKXtwYXJ0aWFsQnlObFtpXT1maWx0ZXJlZEluZGVudGF0aW9uK3BhcnRpYWxCeU5sW2ldfX1yZXR1cm4gcGFydGlhbEJ5Tmwuam9pbihcIlxcblwiKX07V3JpdGVyLnByb3RvdHlwZS5yZW5kZXJQYXJ0aWFsPWZ1bmN0aW9uIHJlbmRlclBhcnRpYWwodG9rZW4sY29udGV4dCxwYXJ0aWFscyx0YWdzKXtpZighcGFydGlhbHMpcmV0dXJuO3ZhciB2YWx1ZT1pc0Z1bmN0aW9uKHBhcnRpYWxzKT9wYXJ0aWFscyh0b2tlblsxXSk6cGFydGlhbHNbdG9rZW5bMV1dO2lmKHZhbHVlIT1udWxsKXt2YXIgbGluZUhhc05vblNwYWNlPXRva2VuWzZdO3ZhciB0YWdJbmRleD10b2tlbls1XTt2YXIgaW5kZW50YXRpb249dG9rZW5bNF07dmFyIGluZGVudGVkVmFsdWU9dmFsdWU7aWYodGFnSW5kZXg9PTAmJmluZGVudGF0aW9uKXtpbmRlbnRlZFZhbHVlPXRoaXMuaW5kZW50UGFydGlhbCh2YWx1ZSxpbmRlbnRhdGlvbixsaW5lSGFzTm9uU3BhY2UpfXJldHVybiB0aGlzLnJlbmRlclRva2Vucyh0aGlzLnBhcnNlKGluZGVudGVkVmFsdWUsdGFncyksY29udGV4dCxwYXJ0aWFscyxpbmRlbnRlZFZhbHVlKX19O1dyaXRlci5wcm90b3R5cGUudW5lc2NhcGVkVmFsdWU9ZnVuY3Rpb24gdW5lc2NhcGVkVmFsdWUodG9rZW4sY29udGV4dCl7dmFyIHZhbHVlPWNvbnRleHQubG9va3VwKHRva2VuWzFdKTtpZih2YWx1ZSE9bnVsbClyZXR1cm4gdmFsdWV9O1dyaXRlci5wcm90b3R5cGUuZXNjYXBlZFZhbHVlPWZ1bmN0aW9uIGVzY2FwZWRWYWx1ZSh0b2tlbixjb250ZXh0KXt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2lmKHZhbHVlIT1udWxsKXJldHVybiBtdXN0YWNoZS5lc2NhcGUodmFsdWUpfTtXcml0ZXIucHJvdG90eXBlLnJhd1ZhbHVlPWZ1bmN0aW9uIHJhd1ZhbHVlKHRva2VuKXtyZXR1cm4gdG9rZW5bMV19O211c3RhY2hlLm5hbWU9XCJtdXN0YWNoZS5qc1wiO211c3RhY2hlLnZlcnNpb249XCIzLjEuMFwiO211c3RhY2hlLnRhZ3M9W1wie3tcIixcIn19XCJdO3ZhciBkZWZhdWx0V3JpdGVyPW5ldyBXcml0ZXI7bXVzdGFjaGUuY2xlYXJDYWNoZT1mdW5jdGlvbiBjbGVhckNhY2hlKCl7cmV0dXJuIGRlZmF1bHRXcml0ZXIuY2xlYXJDYWNoZSgpfTttdXN0YWNoZS5wYXJzZT1mdW5jdGlvbiBwYXJzZSh0ZW1wbGF0ZSx0YWdzKXtyZXR1cm4gZGVmYXVsdFdyaXRlci5wYXJzZSh0ZW1wbGF0ZSx0YWdzKX07bXVzdGFjaGUucmVuZGVyPWZ1bmN0aW9uIHJlbmRlcih0ZW1wbGF0ZSx2aWV3LHBhcnRpYWxzLHRhZ3Mpe2lmKHR5cGVvZiB0ZW1wbGF0ZSE9PVwic3RyaW5nXCIpe3Rocm93IG5ldyBUeXBlRXJyb3IoJ0ludmFsaWQgdGVtcGxhdGUhIFRlbXBsYXRlIHNob3VsZCBiZSBhIFwic3RyaW5nXCIgJysnYnV0IFwiJyt0eXBlU3RyKHRlbXBsYXRlKSsnXCIgd2FzIGdpdmVuIGFzIHRoZSBmaXJzdCAnK1wiYXJndW1lbnQgZm9yIG11c3RhY2hlI3JlbmRlcih0ZW1wbGF0ZSwgdmlldywgcGFydGlhbHMpXCIpfXJldHVybiBkZWZhdWx0V3JpdGVyLnJlbmRlcih0ZW1wbGF0ZSx2aWV3LHBhcnRpYWxzLHRhZ3MpfTttdXN0YWNoZS50b19odG1sPWZ1bmN0aW9uIHRvX2h0bWwodGVtcGxhdGUsdmlldyxwYXJ0aWFscyxzZW5kKXt2YXIgcmVzdWx0PW11c3RhY2hlLnJlbmRlcih0ZW1wbGF0ZSx2aWV3LHBhcnRpYWxzKTtpZihpc0Z1bmN0aW9uKHNlbmQpKXtzZW5kKHJlc3VsdCl9ZWxzZXtyZXR1cm4gcmVzdWx0fX07bXVzdGFjaGUuZXNjYXBlPWVzY2FwZUh0bWw7bXVzdGFjaGUuU2Nhbm5lcj1TY2FubmVyO211c3RhY2hlLkNvbnRleHQ9Q29udGV4dDttdXN0YWNoZS5Xcml0ZXI9V3JpdGVyO3JldHVybiBtdXN0YWNoZX0pO1xuIiwiLyohXG4qXG4qICBDb3B5cmlnaHQgMjAxNiBZYW5uIE1hc3NhcmQgKGh0dHBzOi8vZ2l0aHViLmNvbS95YW1hc3MpIGFuZCBvdGhlciBjb250cmlidXRvcnNcbipcbiogIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4qICB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4qICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbipcbiogIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuKlxuKiAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuKiAgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuKiAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4qICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4qICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbipcbiovXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcImxldmVuc2h0ZWluXCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIExldmVuc2h0ZWluID0gcmVxdWlyZShcImxldmVuc2h0ZWluXCIpO1xuICAgIGV4cG9ydHMua2V5Q29kZXMgPSB7XG4gICAgICAgIGJhY2tzcGFjZTogOCxcbiAgICAgICAgdGFiOiA5LFxuICAgICAgICBlbnRlcjogMTMsXG4gICAgICAgIHNoaWZ0OiAxNixcbiAgICAgICAgY3RybDogMTcsXG4gICAgICAgIGFsdDogMTgsXG4gICAgICAgIHBhdXNlOiAxOSxcbiAgICAgICAgY2Fwc19sb2NrOiAyMCxcbiAgICAgICAgZXNjYXBlOiAyNyxcbiAgICAgICAgc3BhY2U6IDMyLFxuICAgICAgICBwYWdlX3VwOiAzMyxcbiAgICAgICAgcGFnZV9kb3duOiAzNCxcbiAgICAgICAgZW5kOiAzNSxcbiAgICAgICAgaG9tZTogMzYsXG4gICAgICAgIGxlZnRfYXJyb3c6IDM3LFxuICAgICAgICB1cF9hcnJvdzogMzgsXG4gICAgICAgIHJpZ2h0X2Fycm93OiAzOSxcbiAgICAgICAgZG93bl9hcnJvdzogNDAsXG4gICAgICAgIGluc2VydDogNDUsXG4gICAgICAgIFwiZGVsZXRlXCI6IDQ2LFxuICAgICAgICBsZWZ0X3dpbmRvd19rZXk6IDkxLFxuICAgICAgICByaWdodF93aW5kb3dfa2V5OiA5MixcbiAgICAgICAgc2VsZWN0X2tleTogOTMsXG4gICAgICAgIG51bV9sb2NrOiAxNDQsXG4gICAgICAgIHNjcm9sbF9sb2NrOiAxNDUsXG4gICAgICAgIHNwZWNpYWxLZXlzOiBbOCwgOSwgMTMsIDE2LCAxNywgMTgsIDE5LCAyMCwgMjcsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDUsIDQ2LCA5MSwgOTIsIDkzLCAxNDQsIDE0NV0sXG4gICAgICAgIG51bWJlcktleXM6IFs0OCwgNDksIDUwLCA1MSwgNTIsIDUzLCA1NCwgNTUsIDU2LCA1NywgOTYsIDk3LCA5OCwgOTksIDEwMCwgMTAxLCAxMDIsIDEwMywgMTA0LCAxMDVdLFxuICAgICAgICBpc1NwZWNpYWxLZXk6IGZ1bmN0aW9uIChrZXlDb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zcGVjaWFsS2V5cy5pbmRleE9mKGtleUNvZGUpICE9IC0xO1xuICAgICAgICB9LFxuICAgICAgICBpc0RpZ2l0S2V5OiBmdW5jdGlvbiAoa2V5Q29kZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtYmVyS2V5cy5pbmRleE9mKGtleUNvZGUpICE9IC0xO1xuICAgICAgICB9LFxuICAgICAgICBpc01vZGlmaWVyS2V5OiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIFtleHBvcnRzLmtleUNvZGVzLnNoaWZ0LCBleHBvcnRzLmtleUNvZGVzLmNhcHNfbG9jaywgZXhwb3J0cy5rZXlDb2Rlcy5hbHQsIGV4cG9ydHMua2V5Q29kZXMuY3RybCwgZXhwb3J0cy5rZXlDb2Rlcy5sZWZ0X3dpbmRvd19rZXksIGV4cG9ydHMua2V5Q29kZXMucmlnaHRfd2luZG93X2tleV1cbiAgICAgICAgICAgICAgICAuaW5kZXhPZihlLndoaWNoKSAhPSAtMTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgZXhwb3J0cy5ERUZBVUxUX1RFTVBMQVRFUyA9IHtcbiAgICAgICAgaW1hZ2UyTGluZXNUZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJ0ci10ZW1wbGF0ZS1pbWFnZS0yLWxpbmVzXCI+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>
    </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>