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

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


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

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

* Usage:

    *
  1. include this source file in an html page via * {@code } *
  2. define style rules. See the example page for examples. *
  3. mark the {@code
    } and {@code } tags in your source with
     *    {@code class=prettyprint.}
     *    You can also use the (html deprecated) {@code } tag, but the pretty
     *    printer needs to do more substantial DOM manipulations to support that, so
     *    some css styles may not be preserved.
     * </ol>
     * That's it.  I wanted to keep the API as simple as possible, so there's no
     * need to specify which language the code is in, but if you wish, you can add
     * another class to the {@code <pre>} or {@code <code>} element to specify the
     * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
     * starts with "lang-" followed by a file extension, specifies the file type.
     * See the "lang-*.js" files in this directory for code that implements
     * per-language file handlers.
     * <p>
     * Change log:<br>
     * cbeust, 2006/08/22
     * <blockquote>
     *   Java annotations (start with "@") are now captured as literals ("lit")
     * </blockquote>
     * @requires console
     */
    
    // JSLint declarations
    /*global console, document, navigator, setTimeout, window, define */
    
    /** @define {boolean} */
    var IN_GLOBAL_SCOPE = true;
    
    /**
     * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
     * UI events.
     * If set to {@code false}, {@code prettyPrint()} is synchronous.
     */
    window['PR_SHOULD_USE_CONTINUATION'] = true;
    
    /**
     * Pretty print a chunk of code.
     * @param {string} sourceCodeHtml The HTML to pretty print.
     * @param {string} opt_langExtension The language name to use.
     *     Typically, a filename extension like 'cpp' or 'java'.
     * @param {number|boolean} opt_numberLines True to number lines,
     *     or the 1-indexed number of the first line in sourceCodeHtml.
     * @return {string} code as html, but prettier
     */
    var prettyPrintOne;
    /**
     * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
     * {@code class=prettyprint} and prettify them.
     *
     * @param {Function} opt_whenDone called when prettifying is done.
     * @param {HTMLElement|HTMLDocument} opt_root an element or document
     *   containing all the elements to pretty print.
     *   Defaults to {@code document.body}.
     */
    var prettyPrint;
    
    
    (function () {
      var win = window;
      // Keyword lists for various languages.
      // We use things that coerce to strings to make them compact when minified
      // and to defeat aggressive optimizers that fold large string constants.
      var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"];
      var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," + 
          "double,enum,extern,float,goto,inline,int,long,register,short,signed," +
          "sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];
      var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," +
          "new,operator,private,protected,public,this,throw,true,try,typeof"];
      var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool," +
          "concept,concept_map,const_cast,constexpr,decltype,delegate," +
          "dynamic_cast,explicit,export,friend,generic,late_check," +
          "mutable,namespace,nullptr,property,reinterpret_cast,static_assert," +
          "static_cast,template,typeid,typename,using,virtual,where"];
      var JAVA_KEYWORDS = [COMMON_KEYWORDS,
          "abstract,assert,boolean,byte,extends,final,finally,implements,import," +
          "instanceof,interface,null,native,package,strictfp,super,synchronized," +
          "throws,transient"];
      var CSHARP_KEYWORDS = [JAVA_KEYWORDS,
          "as,base,by,checked,decimal,delegate,descending,dynamic,event," +
          "fixed,foreach,from,group,implicit,in,internal,into,is,let," +
          "lock,object,out,override,orderby,params,partial,readonly,ref,sbyte," +
          "sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort," +
          "var,virtual,where"];
      var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," +
          "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," +
          "throw,true,try,unless,until,when,while,yes";
      var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,
          "debugger,eval,export,function,get,null,set,undefined,var,with," +
          "Infinity,NaN"];
      var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," +
          "goto,if,import,last,local,my,next,no,our,print,package,redo,require," +
          "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
      var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," +
          "elif,except,exec,finally,from,global,import,in,is,lambda," +
          "nonlocal,not,or,pass,print,raise,try,with,yield," +
          "False,True,None"];
      var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," +
          "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," +
          "rescue,retry,self,super,then,true,undef,unless,until,when,yield," +
          "BEGIN,END"];
       var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "as,assert,const,copy,drop," +
          "enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv," +
          "pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"];
      var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
          "function,in,local,set,then,until"];
      var ALL_KEYWORDS = [
          CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,
          PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
      var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;
    
      // token style names.  correspond to css classes
      /**
       * token style for a string literal
       * @const
       */
      var PR_STRING = 'str';
      /**
       * token style for a keyword
       * @const
       */
      var PR_KEYWORD = 'kwd';
      /**
       * token style for a comment
       * @const
       */
      var PR_COMMENT = 'com';
      /**
       * token style for a type
       * @const
       */
      var PR_TYPE = 'typ';
      /**
       * token style for a literal value.  e.g. 1, null, true.
       * @const
       */
      var PR_LITERAL = 'lit';
      /**
       * token style for a punctuation string.
       * @const
       */
      var PR_PUNCTUATION = 'pun';
      /**
       * token style for plain text.
       * @const
       */
      var PR_PLAIN = 'pln';
    
      /**
       * token style for an sgml tag.
       * @const
       */
      var PR_TAG = 'tag';
      /**
       * token style for a markup declaration such as a DOCTYPE.
       * @const
       */
      var PR_DECLARATION = 'dec';
      /**
       * token style for embedded source.
       * @const
       */
      var PR_SOURCE = 'src';
      /**
       * token style for an sgml attribute name.
       * @const
       */
      var PR_ATTRIB_NAME = 'atn';
      /**
       * token style for an sgml attribute value.
       * @const
       */
      var PR_ATTRIB_VALUE = 'atv';
    
      /**
       * A class that indicates a section of markup that is not code, e.g. to allow
       * embedding of line numbers within code listings.
       * @const
       */
      var PR_NOCODE = 'nocode';
    
      
      
      /**
       * A set of tokens that can precede a regular expression literal in
       * javascript
       * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html
       * has the full list, but I've removed ones that might be problematic when
       * seen in languages that don't support regular expression literals.
       *
       * <p>Specifically, I've removed any keywords that can't precede a regexp
       * literal in a syntactically legal javascript program, and I've removed the
       * "in" keyword since it's not a keyword in many languages, and might be used
       * as a count of inches.
       *
       * <p>The link above does not accurately describe EcmaScript rules since
       * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
       * very well in practice.
       *
       * @private
       * @const
       */
      var REGEXP_PRECEDER_PATTERN = '(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';
      
      // CAVEAT: this does not properly handle the case where a regular
      // expression immediately follows another since a regular expression may
      // have flags for case-sensitivity and the like.  Having regexp tokens
      // adjacent is not valid in any language I'm aware of, so I'm punting.
      // TODO: maybe style special characters inside a regexp as punctuation.
    
      /**
       * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
       * matches the union of the sets of strings matched by the input RegExp.
       * Since it matches globally, if the input strings have a start-of-input
       * anchor (/^.../), it is ignored for the purposes of unioning.
       * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
       * @return {RegExp} a global regex.
       */
      function combinePrefixPatterns(regexs) {
        var capturedGroupIndex = 0;
      
        var needToFoldCase = false;
        var ignoreCase = false;
        for (var i = 0, n = regexs.length; i < n; ++i) {
          var regex = regexs[i];
          if (regex.ignoreCase) {
            ignoreCase = true;
          } else if (/[a-z]/i.test(regex.source.replace(
                         /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
            needToFoldCase = true;
            ignoreCase = false;
            break;
          }
        }
      
        var escapeCharToCodeUnit = {
          'b': 8,
          't': 9,
          'n': 0xa,
          'v': 0xb,
          'f': 0xc,
          'r': 0xd
        };
      
        function decodeEscape(charsetPart) {
          var cc0 = charsetPart.charCodeAt(0);
          if (cc0 !== 92 /* \\ */) {
            return cc0;
          }
          var c1 = charsetPart.charAt(1);
          cc0 = escapeCharToCodeUnit[c1];
          if (cc0) {
            return cc0;
          } else if ('0' <= c1 && c1 <= '7') {
            return parseInt(charsetPart.substring(1), 8);
          } else if (c1 === 'u' || c1 === 'x') {
            return parseInt(charsetPart.substring(2), 16);
          } else {
            return charsetPart.charCodeAt(1);
          }
        }
      
        function encodeEscape(charCode) {
          if (charCode < 0x20) {
            return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
          }
          var ch = String.fromCharCode(charCode);
          return (ch === '\\' || ch === '-' || ch === ']' || ch === '^')
              ? "\\" + ch : ch;
        }
      
        function caseFoldCharset(charSet) {
          var charsetParts = charSet.substring(1, charSet.length - 1).match(
              new RegExp(
                  '\\\\u[0-9A-Fa-f]{4}'
                  + '|\\\\x[0-9A-Fa-f]{2}'
                  + '|\\\\[0-3][0-7]{0,2}'
                  + '|\\\\[0-7]{1,2}'
                  + '|\\\\[\\s\\S]'
                  + '|-'
                  + '|[^-\\\\]',
                  'g'));
          var ranges = [];
          var inverse = charsetParts[0] === '^';
      
          var out = ['['];
          if (inverse) { out.push('^'); }
      
          for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
            var p = charsetParts[i];
            if (/\\[bdsw]/i.test(p)) {  // Don't muck with named groups.
              out.push(p);
            } else {
              var start = decodeEscape(p);
              var end;
              if (i + 2 < n && '-' === charsetParts[i + 1]) {
                end = decodeEscape(charsetParts[i + 2]);
                i += 2;
              } else {
                end = start;
              }
              ranges.push([start, end]);
              // If the range might intersect letters, then expand it.
              // This case handling is too simplistic.
              // It does not deal with non-latin case folding.
              // It works for latin source code identifiers though.
              if (!(end < 65 || start > 122)) {
                if (!(end < 65 || start > 90)) {
                  ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
                }
                if (!(end < 97 || start > 122)) {
                  ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
                }
              }
            }
          }
      
          // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
          // -> [[1, 12], [14, 14], [16, 17]]
          ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });
          var consolidatedRanges = [];
          var lastRange = [];
          for (var i = 0; i < ranges.length; ++i) {
            var range = ranges[i];
            if (range[0] <= lastRange[1] + 1) {
              lastRange[1] = Math.max(lastRange[1], range[1]);
            } else {
              consolidatedRanges.push(lastRange = range);
            }
          }
      
          for (var i = 0; i < consolidatedRanges.length; ++i) {
            var range = consolidatedRanges[i];
            out.push(encodeEscape(range[0]));
            if (range[1] > range[0]) {
              if (range[1] + 1 > range[0]) { out.push('-'); }
              out.push(encodeEscape(range[1]));
            }
          }
          out.push(']');
          return out.join('');
        }
      
        function allowAnywhereFoldCaseAndRenumberGroups(regex) {
          // Split into character sets, escape sequences, punctuation strings
          // like ('(', '(?:', ')', '^'), and runs of characters that do not
          // include any of the above.
          var parts = regex.source.match(
              new RegExp(
                  '(?:'
                  + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]'  // a character set
                  + '|\\\\u[A-Fa-f0-9]{4}'  // a unicode escape
                  + '|\\\\x[A-Fa-f0-9]{2}'  // a hex escape
                  + '|\\\\[0-9]+'  // a back-reference or octal escape
                  + '|\\\\[^ux0-9]'  // other escape sequence
                  + '|\\(\\?[:!=]'  // start of a non-capturing group
                  + '|[\\(\\)\\^]'  // start/end of a group, or line start
                  + '|[^\\x5B\\x5C\\(\\)\\^]+'  // run of other characters
                  + ')',
                  'g'));
          var n = parts.length;
      
          // Maps captured group numbers to the number they will occupy in
          // the output or to -1 if that has not been determined, or to
          // undefined if they need not be capturing in the output.
          var capturedGroups = [];
      
          // Walk over and identify back references to build the capturedGroups
          // mapping.
          for (var i = 0, groupIndex = 0; i < n; ++i) {
            var p = parts[i];
            if (p === '(') {
              // groups are 1-indexed, so max group index is count of '('
              ++groupIndex;
            } else if ('\\' === p.charAt(0)) {
              var decimalValue = +p.substring(1);
              if (decimalValue) {
                if (decimalValue <= groupIndex) {
                  capturedGroups[decimalValue] = -1;
                } else {
                  // Replace with an unambiguous escape sequence so that
                  // an octal escape sequence does not turn into a backreference
                  // to a capturing group from an earlier regex.
                  parts[i] = encodeEscape(decimalValue);
                }
              }
            }
          }
      
          // Renumber groups and reduce capturing groups to non-capturing groups
          // where possible.
          for (var i = 1; i < capturedGroups.length; ++i) {
            if (-1 === capturedGroups[i]) {
              capturedGroups[i] = ++capturedGroupIndex;
            }
          }
          for (var i = 0, groupIndex = 0; i < n; ++i) {
            var p = parts[i];
            if (p === '(') {
              ++groupIndex;
              if (!capturedGroups[groupIndex]) {
                parts[i] = '(?:';
              }
            } else if ('\\' === p.charAt(0)) {
              var decimalValue = +p.substring(1);
              if (decimalValue && decimalValue <= groupIndex) {
                parts[i] = '\\' + capturedGroups[decimalValue];
              }
            }
          }
      
          // Remove any prefix anchors so that the output will match anywhere.
          // ^^ really does mean an anchored match though.
          for (var i = 0; i < n; ++i) {
            if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
          }
      
          // Expand letters to groups to handle mixing of case-sensitive and
          // case-insensitive patterns if necessary.
          if (regex.ignoreCase && needToFoldCase) {
            for (var i = 0; i < n; ++i) {
              var p = parts[i];
              var ch0 = p.charAt(0);
              if (p.length >= 2 && ch0 === '[') {
                parts[i] = caseFoldCharset(p);
              } else if (ch0 !== '\\') {
                // TODO: handle letters in numeric escapes.
                parts[i] = p.replace(
                    /[a-zA-Z]/g,
                    function (ch) {
                      var cc = ch.charCodeAt(0);
                      return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
                    });
              }
            }
          }
      
          return parts.join('');
        }
      
        var rewritten = [];
        for (var i = 0, n = regexs.length; i < n; ++i) {
          var regex = regexs[i];
          if (regex.global || regex.multiline) { throw new Error('' + regex); }
          rewritten.push(
              '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
        }
      
        return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
      }
    
      /**
       * Split markup into a string of source code and an array mapping ranges in
       * that string to the text nodes in which they appear.
       *
       * <p>
       * The HTML DOM structure:</p>
       * <pre>
       * (Element   "p"
       *   (Element "b"
       *     (Text  "print "))       ; #1
       *   (Text    "'Hello '")      ; #2
       *   (Element "br")            ; #3
       *   (Text    "  + 'World';")) ; #4
       * </pre>
       * <p>
       * corresponds to the HTML
       * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>
       *
       * <p>
       * It will produce the output:</p>
       * <pre>
       * {
       *   sourceCode: "print 'Hello '\n  + 'World';",
       *   //                     1          2
       *   //           012345678901234 5678901234567
       *   spans: [0, #1, 6, #2, 14, #3, 15, #4]
       * }
       * </pre>
       * <p>
       * where #1 is a reference to the {@code "print "} text node above, and so
       * on for the other text nodes.
       * </p>
       *
       * <p>
       * The {@code} spans array is an array of pairs.  Even elements are the start
       * indices of substrings, and odd elements are the text nodes (or BR elements)
       * that contain the text for those substrings.
       * Substrings continue until the next index or the end of the source.
       * </p>
       *
       * @param {Node} node an HTML DOM subtree containing source-code.
       * @param {boolean} isPreformatted true if white-space in text nodes should
       *    be considered significant.
       * @return {Object} source code and the text nodes in which they occur.
       */
      function extractSourceSpans(node, isPreformatted) {
        var nocode = /(?:^|\s)nocode(?:\s|$)/;
      
        var chunks = [];
        var length = 0;
        var spans = [];
        var k = 0;
      
        function walk(node) {
          var type = node.nodeType;
          if (type == 1) {  // Element
            if (nocode.test(node.className)) { return; }
            for (var child = node.firstChild; child; child = child.nextSibling) {
              walk(child);
            }
            var nodeName = node.nodeName.toLowerCase();
            if ('br' === nodeName || 'li' === nodeName) {
              chunks[k] = '\n';
              spans[k << 1] = length++;
              spans[(k++ << 1) | 1] = node;
            }
          } else if (type == 3 || type == 4) {  // Text
            var text = node.nodeValue;
            if (text.length) {
              if (!isPreformatted) {
                text = text.replace(/[ \t\r\n]+/g, ' ');
              } else {
                text = text.replace(/\r\n?/g, '\n');  // Normalize newlines.
              }
              // TODO: handle tabs here?
              chunks[k] = text;
              spans[k << 1] = length;
              length += text.length;
              spans[(k++ << 1) | 1] = node;
            }
          }
        }
      
        walk(node);
      
        return {
          sourceCode: chunks.join('').replace(/\n$/, ''),
          spans: spans
        };
      }
    
      /**
       * Apply the given language handler to sourceCode and add the resulting
       * decorations to out.
       * @param {number} basePos the index of sourceCode within the chunk of source
       *    whose decorations are already present on out.
       */
      function appendDecorations(basePos, sourceCode, langHandler, out) {
        if (!sourceCode) { return; }
        var job = {
          sourceCode: sourceCode,
          basePos: basePos
        };
        langHandler(job);
        out.push.apply(out, job.decorations);
      }
    
      var notWs = /\S/;
    
      /**
       * Given an element, if it contains only one child element and any text nodes
       * it contains contain only space characters, return the sole child element.
       * Otherwise returns undefined.
       * <p>
       * This is meant to return the CODE element in {@code <pre><code ...>} when
       * there is a single child element that contains all the non-space textual
       * content, but not to return anything where there are multiple child elements
       * as in {@code <pre><code>...</code><code>...</code></pre>} or when there
       * is textual content.
       */
      function childContentWrapper(element) {
        var wrapper = undefined;
        for (var c = element.firstChild; c; c = c.nextSibling) {
          var type = c.nodeType;
          wrapper = (type === 1)  // Element Node
              ? (wrapper ? element : c)
              : (type === 3)  // Text Node
              ? (notWs.test(c.nodeValue) ? element : wrapper)
              : wrapper;
        }
        return wrapper === element ? undefined : wrapper;
      }
    
      /** Given triples of [style, pattern, context] returns a lexing function,
        * The lexing function interprets the patterns to find token boundaries and
        * returns a decoration list of the form
        * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
        * where index_n is an index into the sourceCode, and style_n is a style
        * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
        * all characters in sourceCode[index_n-1:index_n].
        *
        * The stylePatterns is a list whose elements have the form
        * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
        *
        * Style is a style constant like PR_PLAIN, or can be a string of the
        * form 'lang-FOO', where FOO is a language extension describing the
        * language of the portion of the token in $1 after pattern executes.
        * E.g., if style is 'lang-lisp', and group 1 contains the text
        * '(hello (world))', then that portion of the token will be passed to the
        * registered lisp handler for formatting.
        * The text before and after group 1 will be restyled using this decorator
        * so decorators should take care that this doesn't result in infinite
        * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
        * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
        * '<script>foo()<\/script>', which would cause the current decorator to
        * be called with '<script>' which would not match the same rule since
        * group 1 must not be empty, so it would be instead styled as PR_TAG by
        * the generic tag rule.  The handler registered for the 'js' extension would
        * then be called with 'foo()', and finally, the current decorator would
        * be called with '<\/script>' which would not match the original rule and
        * so the generic tag rule would identify it as a tag.
        *
        * Pattern must only match prefixes, and if it matches a prefix, then that
        * match is considered a token with the same style.
        *
        * Context is applied to the last non-whitespace, non-comment token
        * recognized.
        *
        * Shortcut is an optional string of characters, any of which, if the first
        * character, gurantee that this pattern and only this pattern matches.
        *
        * @param {Array} shortcutStylePatterns patterns that always start with
        *   a known character.  Must have a shortcut string.
        * @param {Array} fallthroughStylePatterns patterns that will be tried in
        *   order if the shortcut ones fail.  May have shortcuts.
        *
        * @return {function (Object)} a
        *   function that takes source code and returns a list of decorations.
        */
      function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
        var shortcuts = {};
        var tokenizer;
        (function () {
          var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
          var allRegexs = [];
          var regexKeys = {};
          for (var i = 0, n = allPatterns.length; i < n; ++i) {
            var patternParts = allPatterns[i];
            var shortcutChars = patternParts[3];
            if (shortcutChars) {
              for (var c = shortcutChars.length; --c >= 0;) {
                shortcuts[shortcutChars.charAt(c)] = patternParts;
              }
            }
            var regex = patternParts[1];
            var k = '' + regex;
            if (!regexKeys.hasOwnProperty(k)) {
              allRegexs.push(regex);
              regexKeys[k] = null;
            }
          }
          allRegexs.push(/[\0-\uffff]/);
          tokenizer = combinePrefixPatterns(allRegexs);
        })();
    
        var nPatterns = fallthroughStylePatterns.length;
    
        /**
         * Lexes job.sourceCode and produces an output array job.decorations of
         * style classes preceded by the position at which they start in
         * job.sourceCode in order.
         *
         * @param {Object} job an object like <pre>{
         *    sourceCode: {string} sourceText plain text,
         *    basePos: {int} position of job.sourceCode in the larger chunk of
         *        sourceCode.
         * }</pre>
         */
        var decorate = function (job) {
          var sourceCode = job.sourceCode, basePos = job.basePos;
          /** Even entries are positions in source in ascending order.  Odd enties
            * are style markers (e.g., PR_COMMENT) that run from that position until
            * the end.
            * @type {Array.<number|string>}
            */
          var decorations = [basePos, PR_PLAIN];
          var pos = 0;  // index into sourceCode
          var tokens = sourceCode.match(tokenizer) || [];
          var styleCache = {};
    
          for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
            var token = tokens[ti];
            var style = styleCache[token];
            var match = void 0;
    
            var isEmbedded;
            if (typeof style === 'string') {
              isEmbedded = false;
            } else {
              var patternParts = shortcuts[token.charAt(0)];
              if (patternParts) {
                match = token.match(patternParts[1]);
                style = patternParts[0];
              } else {
                for (var i = 0; i < nPatterns; ++i) {
                  patternParts = fallthroughStylePatterns[i];
                  match = token.match(patternParts[1]);
                  if (match) {
                    style = patternParts[0];
                    break;
                  }
                }
    
                if (!match) {  // make sure that we make progress
                  style = PR_PLAIN;
                }
              }
    
              isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
              if (isEmbedded && !(match && typeof match[1] === 'string')) {
                isEmbedded = false;
                style = PR_SOURCE;
              }
    
              if (!isEmbedded) { styleCache[token] = style; }
            }
    
            var tokenStart = pos;
            pos += token.length;
    
            if (!isEmbedded) {
              decorations.push(basePos + tokenStart, style);
            } else {  // Treat group 1 as an embedded block of source code.
              var embeddedSource = match[1];
              var embeddedSourceStart = token.indexOf(embeddedSource);
              var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
              if (match[2]) {
                // If embeddedSource can be blank, then it would match at the
                // beginning which would cause us to infinitely recurse on the
                // entire token, so we catch the right context in match[2].
                embeddedSourceEnd = token.length - match[2].length;
                embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
              }
              var lang = style.substring(5);
              // Decorate the left of the embedded source
              appendDecorations(
                  basePos + tokenStart,
                  token.substring(0, embeddedSourceStart),
                  decorate, decorations);
              // Decorate the embedded source
              appendDecorations(
                  basePos + tokenStart + embeddedSourceStart,
                  embeddedSource,
                  langHandlerForExtension(lang, embeddedSource),
                  decorations);
              // Decorate the right of the embedded section
              appendDecorations(
                  basePos + tokenStart + embeddedSourceEnd,
                  token.substring(embeddedSourceEnd),
                  decorate, decorations);
            }
          }
          job.decorations = decorations;
        };
        return decorate;
      }
    
      /** returns a function that produces a list of decorations from source text.
        *
        * This code treats ", ', and ` as string delimiters, and \ as a string
        * escape.  It does not recognize perl's qq() style strings.
        * It has no special handling for double delimiter escapes as in basic, or
        * the tripled delimiters used in python, but should work on those regardless
        * although in those cases a single string literal may be broken up into
        * multiple adjacent string literals.
        *
        * It recognizes C, C++, and shell style comments.
        *
        * @param {Object} options a set of optional parameters.
        * @return {function (Object)} a function that examines the source code
        *     in the input job and builds the decoration list.
        */
      function sourceDecorator(options) {
        var shortcutStylePatterns = [], fallthroughStylePatterns = [];
        if (options['tripleQuotedStrings']) {
          // '''multi-line-string''', 'single-line-string', and double-quoted
          shortcutStylePatterns.push(
              [PR_STRING,  /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
               null, '\'"']);
        } else if (options['multiLineStrings']) {
          // 'multi-line-string', "multi-line-string"
          shortcutStylePatterns.push(
              [PR_STRING,  /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
               null, '\'"`']);
        } else {
          // 'single-line-string', "single-line-string"
          shortcutStylePatterns.push(
              [PR_STRING,
               /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
               null, '"\'']);
        }
        if (options['verbatimStrings']) {
          // verbatim-string-literal production from the C# grammar.  See issue 93.
          fallthroughStylePatterns.push(
              [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
        }
        var hc = options['hashComments'];
        if (hc) {
          if (options['cStyleComments']) {
            if (hc > 1) {  // multiline hash comments
              shortcutStylePatterns.push(
                  [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
            } else {
              // Stop C preprocessor declarations at an unclosed open comment
              shortcutStylePatterns.push(
                  [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
                   null, '#']);
            }
            // #include <stdio.h>
            fallthroughStylePatterns.push(
                [PR_STRING,
                 /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,
                 null]);
          } else {
            shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
          }
        }
        if (options['cStyleComments']) {
          fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
          fallthroughStylePatterns.push(
              [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
        }
        var regexLiterals = options['regexLiterals'];
        if (regexLiterals) {
          /**
           * @const
           */
          var regexExcls = regexLiterals > 1
            ? ''  // Multiline regex literals
            : '\n\r';
          /**
           * @const
           */
          var regexAny = regexExcls ? '.' : '[\\S\\s]';
          /**
           * @const
           */
          var REGEX_LITERAL = (
              // A regular expression literal starts with a slash that is
              // not followed by * or / so that it is not confused with
              // comments.
              '/(?=[^/*' + regexExcls + '])'
              // and then contains any number of raw characters,
              + '(?:[^/\\x5B\\x5C' + regexExcls + ']'
              // escape sequences (\x5C),
              +    '|\\x5C' + regexAny
              // or non-nesting character sets (\x5B\x5D);
              +    '|\\x5B(?:[^\\x5C\\x5D' + regexExcls + ']'
              +             '|\\x5C' + regexAny + ')*(?:\\x5D|$))+'
              // finally closed by a /.
              + '/');
          fallthroughStylePatterns.push(
              ['lang-regex',
               RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
               ]);
        }
    
        var types = options['types'];
        if (types) {
          fallthroughStylePatterns.push([PR_TYPE, types]);
        }
    
        var keywords = ("" + options['keywords']).replace(/^ | $/g, '');
        if (keywords.length) {
          fallthroughStylePatterns.push(
              [PR_KEYWORD,
               new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'),
               null]);
        }
    
        shortcutStylePatterns.push([PR_PLAIN,       /^\s+/, null, ' \r\n\t\xA0']);
    
        var punctuation =
          // The Bash man page says
    
          // A word is a sequence of characters considered as a single
          // unit by GRUB. Words are separated by metacharacters,
          // which are the following plus space, tab, and newline: { }
          // | & $ ; < >
          // ...
          
          // A word beginning with # causes that word and all remaining
          // characters on that line to be ignored.
    
          // which means that only a '#' after /(?:^|[{}|&$;<>\s])/ starts a
          // comment but empirically
          // $ echo {#}
          // {#}
          // $ echo \$#
          // $#
          // $ echo }#
          // }#
    
          // so /(?:^|[|&;<>\s])/ is more appropriate.
    
          // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3
          // suggests that this definition is compatible with a
          // default mode that tries to use a single token definition
          // to recognize both bash/python style comments and C
          // preprocessor directives.
    
          // This definition of punctuation does not include # in the list of
          // follow-on exclusions, so # will not be broken before if preceeded
          // by a punctuation character.  We could try to exclude # after
          // [|&;<>] but that doesn't seem to cause many major problems.
          // If that does turn out to be a problem, we should change the below
          // when hc is truthy to include # in the run of punctuation characters
          // only when not followint [|&;<>].
          '^.[^\\s\\w.$@\'"`/\\\\]*';
        if (options['regexLiterals']) {
          punctuation += '(?!\s*\/)';
        }
    
        fallthroughStylePatterns.push(
            // TODO(mikesamuel): recognize non-latin letters and numerals in idents
            [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],
            [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
            [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],
            [PR_LITERAL,
             new RegExp(
                 '^(?:'
                 // A hex number
                 + '0x[a-f0-9]+'
                 // or an octal or decimal number,
                 + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
                 // possibly in scientific notation
                 + '(?:e[+\\-]?\\d+)?'
                 + ')'
                 // with an optional modifier like UL for unsigned long
                 + '[a-z]*', 'i'),
             null, '0123456789'],
            // Don't treat escaped quotes in bash as starting strings.
            // See issue 144.
            [PR_PLAIN,       /^\\[\s\S]?/, null],
            [PR_PUNCTUATION, new RegExp(punctuation), null]);
    
        return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
      }
    
      var decorateSource = sourceDecorator({
            'keywords': ALL_KEYWORDS,
            'hashComments': true,
            'cStyleComments': true,
            'multiLineStrings': true,
            'regexLiterals': true
          });
    
      /**
       * Given a DOM subtree, wraps it in a list, and puts each line into its own
       * list item.
       *
       * @param {Node} node modified in place.  Its content is pulled into an
       *     HTMLOListElement, and each line is moved into a separate list item.
       *     This requires cloning elements, so the input might not have unique
       *     IDs after numbering.
       * @param {boolean} isPreformatted true iff white-space in text nodes should
       *     be treated as significant.
       */
      function numberLines(node, opt_startLineNum, isPreformatted) {
        var nocode = /(?:^|\s)nocode(?:\s|$)/;
        var lineBreak = /\r\n?|\n/;
      
        var document = node.ownerDocument;
      
        var li = document.createElement('li');
        while (node.firstChild) {
          li.appendChild(node.firstChild);
        }
        // An array of lines.  We split below, so this is initialized to one
        // un-split line.
        var listItems = [li];
      
        function walk(node) {
          var type = node.nodeType;
          if (type == 1 && !nocode.test(node.className)) {  // Element
            if ('br' === node.nodeName) {
              breakAfter(node);
              // Discard the <BR> since it is now flush against a </LI>.
              if (node.parentNode) {
                node.parentNode.removeChild(node);
              }
            } else {
              for (var child = node.firstChild; child; child = child.nextSibling) {
                walk(child);
              }
            }
          } else if ((type == 3 || type == 4) && isPreformatted) {  // Text
            var text = node.nodeValue;
            var match = text.match(lineBreak);
            if (match) {
              var firstLine = text.substring(0, match.index);
              node.nodeValue = firstLine;
              var tail = text.substring(match.index + match[0].length);
              if (tail) {
                var parent = node.parentNode;
                parent.insertBefore(
                  document.createTextNode(tail), node.nextSibling);
              }
              breakAfter(node);
              if (!firstLine) {
                // Don't leave blank text nodes in the DOM.
                node.parentNode.removeChild(node);
              }
            }
          }
        }
      
        // Split a line after the given node.
        function breakAfter(lineEndNode) {
          // If there's nothing to the right, then we can skip ending the line
          // here, and move root-wards since splitting just before an end-tag
          // would require us to create a bunch of empty copies.
          while (!lineEndNode.nextSibling) {
            lineEndNode = lineEndNode.parentNode;
            if (!lineEndNode) { return; }
          }
      
          function breakLeftOf(limit, copy) {
            // Clone shallowly if this node needs to be on both sides of the break.
            var rightSide = copy ? limit.cloneNode(false) : limit;
            var parent = limit.parentNode;
            if (parent) {
              // We clone the parent chain.
              // This helps us resurrect important styling elements that cross lines.
              // E.g. in <i>Foo<br>Bar</i>
              // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.
              var parentClone = breakLeftOf(parent, 1);
              // Move the clone and everything to the right of the original
              // onto the cloned parent.
              var next = limit.nextSibling;
              parentClone.appendChild(rightSide);
              for (var sibling = next; sibling; sibling = next) {
                next = sibling.nextSibling;
                parentClone.appendChild(sibling);
              }
            }
            return rightSide;
          }
      
          var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);
      
          // Walk the parent chain until we reach an unattached LI.
          for (var parent;
               // Check nodeType since IE invents document fragments.
               (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {
            copiedListItem = parent;
          }
          // Put it on the list of lines for later processing.
          listItems.push(copiedListItem);
        }
      
        // Split lines while there are lines left to split.
        for (var i = 0;  // Number of lines that have been split so far.
             i < listItems.length;  // length updated by breakAfter calls.
             ++i) {
          walk(listItems[i]);
        }
      
        // Make sure numeric indices show correctly.
        if (opt_startLineNum === (opt_startLineNum|0)) {
          listItems[0].setAttribute('value', opt_startLineNum);
        }
      
        var ol = document.createElement('ol');
        ol.className = 'linenums';
        var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
        for (var i = 0, n = listItems.length; i < n; ++i) {
          li = listItems[i];
          // Stick a class on the LIs so that stylesheets can
          // color odd/even rows, or any other row pattern that
          // is co-prime with 10.
          li.className = 'L' + ((i + offset) % 10);
          if (!li.firstChild) {
            li.appendChild(document.createTextNode('\xA0'));
          }
          ol.appendChild(li);
        }
      
        node.appendChild(ol);
      }
      /**
       * Breaks {@code job.sourceCode} around style boundaries in
       * {@code job.decorations} and modifies {@code job.sourceNode} in place.
       * @param {Object} job like <pre>{
       *    sourceCode: {string} source as plain text,
       *    sourceNode: {HTMLElement} the element containing the source,
       *    spans: {Array.<number|Node>} alternating span start indices into source
       *       and the text node or element (e.g. {@code <BR>}) corresponding to that
       *       span.
       *    decorations: {Array.<number|string} an array of style classes preceded
       *       by the position at which they start in job.sourceCode in order
       * }</pre>
       * @private
       */
      function recombineTagsAndDecorations(job) {
        var isIE8OrEarlier = /\bMSIE\s(\d+)/.exec(navigator.userAgent);
        isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;
        var newlineRe = /\n/g;
      
        var source = job.sourceCode;
        var sourceLength = source.length;
        // Index into source after the last code-unit recombined.
        var sourceIndex = 0;
      
        var spans = job.spans;
        var nSpans = spans.length;
        // Index into spans after the last span which ends at or before sourceIndex.
        var spanIndex = 0;
      
        var decorations = job.decorations;
        var nDecorations = decorations.length;
        // Index into decorations after the last decoration which ends at or before
        // sourceIndex.
        var decorationIndex = 0;
      
        // Remove all zero-length decorations.
        decorations[nDecorations] = sourceLength;
        var decPos, i;
        for (i = decPos = 0; i < nDecorations;) {
          if (decorations[i] !== decorations[i + 2]) {
            decorations[decPos++] = decorations[i++];
            decorations[decPos++] = decorations[i++];
          } else {
            i += 2;
          }
        }
        nDecorations = decPos;
      
        // Simplify decorations.
        for (i = decPos = 0; i < nDecorations;) {
          var startPos = decorations[i];
          // Conflate all adjacent decorations that use the same style.
          var startDec = decorations[i + 1];
          var end = i + 2;
          while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {
            end += 2;
          }
          decorations[decPos++] = startPos;
          decorations[decPos++] = startDec;
          i = end;
        }
      
        nDecorations = decorations.length = decPos;
      
        var sourceNode = job.sourceNode;
        var oldDisplay;
        if (sourceNode) {
          oldDisplay = sourceNode.style.display;
          sourceNode.style.display = 'none';
        }
        try {
          var decoration = null;
          while (spanIndex < nSpans) {
            var spanStart = spans[spanIndex];
            var spanEnd = spans[spanIndex + 2] || sourceLength;
      
            var decEnd = decorations[decorationIndex + 2] || sourceLength;
      
            var end = Math.min(spanEnd, decEnd);
      
            var textNode = spans[spanIndex + 1];
            var styledText;
            if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s
                // Don't introduce spans around empty text nodes.
                && (styledText = source.substring(sourceIndex, end))) {
              // This may seem bizarre, and it is.  Emitting LF on IE causes the
              // code to display with spaces instead of line breaks.
              // Emitting Windows standard issue linebreaks (CRLF) causes a blank
              // space to appear at the beginning of every line but the first.
              // Emitting an old Mac OS 9 line separator makes everything spiffy.
              if (isIE8OrEarlier) {
                styledText = styledText.replace(newlineRe, '\r');
              }
              textNode.nodeValue = styledText;
              var document = textNode.ownerDocument;
              var span = document.createElement('span');
              span.className = decorations[decorationIndex + 1];
              var parentNode = textNode.parentNode;
              parentNode.replaceChild(span, textNode);
              span.appendChild(textNode);
              if (sourceIndex < spanEnd) {  // Split off a text node.
                spans[spanIndex + 1] = textNode
                    // TODO: Possibly optimize by using '' if there's no flicker.
                    = document.createTextNode(source.substring(end, spanEnd));
                parentNode.insertBefore(textNode, span.nextSibling);
              }
            }
      
            sourceIndex = end;
      
            if (sourceIndex >= spanEnd) {
              spanIndex += 2;
            }
            if (sourceIndex >= decEnd) {
              decorationIndex += 2;
            }
          }
        } finally {
          if (sourceNode) {
            sourceNode.style.display = oldDisplay;
          }
        }
      }
    
      /** Maps language-specific file extensions to handlers. */
      var langHandlerRegistry = {};
      /** Register a language handler for the given file extensions.
        * @param {function (Object)} handler a function from source code to a list
        *      of decorations.  Takes a single argument job which describes the
        *      state of the computation.   The single parameter has the form
        *      {@code {
        *        sourceCode: {string} as plain text.
        *        decorations: {Array.<number|string>} an array of style classes
        *                     preceded by the position at which they start in
        *                     job.sourceCode in order.
        *                     The language handler should assigned this field.
        *        basePos: {int} the position of source in the larger source chunk.
        *                 All positions in the output decorations array are relative
        *                 to the larger source chunk.
        *      } }
        * @param {Array.<string>} fileExtensions
        */
      function registerLangHandler(handler, fileExtensions) {
        for (var i = fileExtensions.length; --i >= 0;) {
          var ext = fileExtensions[i];
          if (!langHandlerRegistry.hasOwnProperty(ext)) {
            langHandlerRegistry[ext] = handler;
          } else if (win['console']) {
            console['warn']('cannot override language handler %s', ext);
          }
        }
      }
      function langHandlerForExtension(extension, source) {
        if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
          // Treat it as markup if the first non whitespace character is a < and
          // the last non-whitespace character is a >.
          extension = /^\s*</.test(source)
              ? 'default-markup'
              : 'default-code';
        }
        return langHandlerRegistry[extension];
      }
      registerLangHandler(decorateSource, ['default-code']);
      registerLangHandler(
          createSimpleLexer(
              [],
              [
               [PR_PLAIN,       /^[^<?]+/],
               [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
               [PR_COMMENT,     /^<\!--[\s\S]*?(?:-\->|$)/],
               // Unescaped content in an unknown language
               ['lang-',        /^<\?([\s\S]+?)(?:\?>|$)/],
               ['lang-',        /^<%([\s\S]+?)(?:%>|$)/],
               [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
               ['lang-',        /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
               // Unescaped content in javascript.  (Or possibly vbscript).
               ['lang-js',      /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
               // Contains unescaped stylesheet content
               ['lang-css',     /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
               ['lang-in.tag',  /^(<\/?[a-z][^<>]*>)/i]
              ]),
          ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
      registerLangHandler(
          createSimpleLexer(
              [
               [PR_PLAIN,        /^[\s]+/, null, ' \t\r\n'],
               [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
               ],
              [
               [PR_TAG,          /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
               [PR_ATTRIB_NAME,  /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
               ['lang-uq.val',   /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
               [PR_PUNCTUATION,  /^[=<>\/]+/],
               ['lang-js',       /^on\w+\s*=\s*\"([^\"]+)\"/i],
               ['lang-js',       /^on\w+\s*=\s*\'([^\']+)\'/i],
               ['lang-js',       /^on\w+\s*=\s*([^\"\'>\s]+)/i],
               ['lang-css',      /^style\s*=\s*\"([^\"]+)\"/i],
               ['lang-css',      /^style\s*=\s*\'([^\']+)\'/i],
               ['lang-css',      /^style\s*=\s*([^\"\'>\s]+)/i]
               ]),
          ['in.tag']);
      registerLangHandler(
          createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
      registerLangHandler(sourceDecorator({
              'keywords': CPP_KEYWORDS,
              'hashComments': true,
              'cStyleComments': true,
              'types': C_TYPES
            }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
      registerLangHandler(sourceDecorator({
              'keywords': 'null,true,false'
            }), ['json']);
      registerLangHandler(sourceDecorator({
              'keywords': CSHARP_KEYWORDS,
              'hashComments': true,
              'cStyleComments': true,
              'verbatimStrings': true,
              'types': C_TYPES
            }), ['cs']);
      registerLangHandler(sourceDecorator({
              'keywords': JAVA_KEYWORDS,
              'cStyleComments': true
            }), ['java']);
      registerLangHandler(sourceDecorator({
              'keywords': SH_KEYWORDS,
              'hashComments': true,
              'multiLineStrings': true
            }), ['bash', 'bsh', 'csh', 'sh']);
      registerLangHandler(sourceDecorator({
              'keywords': PYTHON_KEYWORDS,
              'hashComments': true,
              'multiLineStrings': true,
              'tripleQuotedStrings': true
            }), ['cv', 'py', 'python']);
      registerLangHandler(sourceDecorator({
              'keywords': PERL_KEYWORDS,
              'hashComments': true,
              'multiLineStrings': true,
              'regexLiterals': 2  // multiline regex literals
            }), ['perl', 'pl', 'pm']);
      registerLangHandler(sourceDecorator({
              'keywords': RUBY_KEYWORDS,
              'hashComments': true,
              'multiLineStrings': true,
              'regexLiterals': true
            }), ['rb', 'ruby']);
      registerLangHandler(sourceDecorator({
              'keywords': JSCRIPT_KEYWORDS,
              'cStyleComments': true,
              'regexLiterals': true
            }), ['javascript', 'js']);
      registerLangHandler(sourceDecorator({
              'keywords': COFFEE_KEYWORDS,
              'hashComments': 3,  // ### style block comments
              'cStyleComments': true,
              'multilineStrings': true,
              'tripleQuotedStrings': true,
              'regexLiterals': true
            }), ['coffee']);
      registerLangHandler(sourceDecorator({
              'keywords': RUST_KEYWORDS,
              'cStyleComments': true,
              'multilineStrings': true
            }), ['rc', 'rs', 'rust']);
      registerLangHandler(
          createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
    
      function applyDecorator(job) {
        var opt_langExtension = job.langExtension;
    
        try {
          // Extract tags, and convert the source code to plain text.
          var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);
          /** Plain text. @type {string} */
          var source = sourceAndSpans.sourceCode;
          job.sourceCode = source;
          job.spans = sourceAndSpans.spans;
          job.basePos = 0;
    
          // Apply the appropriate language handler
          langHandlerForExtension(opt_langExtension, source)(job);
    
          // Integrate the decorations and tags back into the source code,
          // modifying the sourceNode in place.
          recombineTagsAndDecorations(job);
        } catch (e) {
          if (win['console']) {
            console['log'](e && e['stack'] || e);
          }
        }
      }
    
      /**
       * Pretty print a chunk of code.
       * @param sourceCodeHtml {string} The HTML to pretty print.
       * @param opt_langExtension {string} The language name to use.
       *     Typically, a filename extension like 'cpp' or 'java'.
       * @param opt_numberLines {number|boolean} True to number lines,
       *     or the 1-indexed number of the first line in sourceCodeHtml.
       */
      function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
        var container = document.createElement('div');
        // This could cause images to load and onload listeners to fire.
        // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
        // We assume that the inner HTML is from a trusted source.
        // The pre-tag is required for IE8 which strips newlines from innerHTML
        // when it is injected into a <pre> tag.
        // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie
        // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript
        container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';
        container = container.firstChild;
        if (opt_numberLines) {
          numberLines(container, opt_numberLines, true);
        }
    
        var job = {
          langExtension: opt_langExtension,
          numberLines: opt_numberLines,
          sourceNode: container,
          pre: 1
        };
        applyDecorator(job);
        return container.innerHTML;
      }
    
       /**
        * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
        * {@code class=prettyprint} and prettify them.
        *
        * @param {Function} opt_whenDone called when prettifying is done.
        * @param {HTMLElement|HTMLDocument} opt_root an element or document
        *   containing all the elements to pretty print.
        *   Defaults to {@code document.body}.
        */
      function $prettyPrint(opt_whenDone, opt_root) {
        var root = opt_root || document.body;
        var doc = root.ownerDocument || document;
        function byTagName(tn) { return root.getElementsByTagName(tn); }
        // fetch a list of nodes to rewrite
        var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
        var elements = [];
        for (var i = 0; i < codeSegments.length; ++i) {
          for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
            elements.push(codeSegments[i][j]);
          }
        }
        codeSegments = null;
    
        var clock = Date;
        if (!clock['now']) {
          clock = { 'now': function () { return +(new Date); } };
        }
    
        // The loop is broken into a series of continuations to make sure that we
        // don't make the browser unresponsive when rewriting a large page.
        var k = 0;
        var prettyPrintingJob;
    
        var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/;
        var prettyPrintRe = /\bprettyprint\b/;
        var prettyPrintedRe = /\bprettyprinted\b/;
        var preformattedTagNameRe = /pre|xmp/i;
        var codeRe = /^code$/i;
        var preCodeXmpRe = /^(?:pre|code|xmp)$/i;
        var EMPTY = {};
    
        function doWork() {
          var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?
                         clock['now']() + 250 /* ms */ :
                         Infinity);
          for (; k < elements.length && clock['now']() < endTime; k++) {
            var cs = elements[k];
    
            // Look for a preceding comment like
            // <?prettify lang="..." linenums="..."?>
            var attrs = EMPTY;
            {
              for (var preceder = cs; (preceder = preceder.previousSibling);) {
                var nt = preceder.nodeType;
                // <?foo?> is parsed by HTML 5 to a comment node (8)
                // like <!--?foo?-->, but in XML is a processing instruction
                var value = (nt === 7 || nt === 8) && preceder.nodeValue;
                if (value
                    ? !/^\??prettify\b/.test(value)
                    : (nt !== 3 || /\S/.test(preceder.nodeValue))) {
                  // Skip over white-space text nodes but not others.
                  break;
                }
                if (value) {
                  attrs = {};
                  value.replace(
                      /\b(\w+)=([\w:.%+-]+)/g,
                    function (_, name, value) { attrs[name] = value; });
                  break;
                }
              }
            }
    
            var className = cs.className;
            if ((attrs !== EMPTY || prettyPrintRe.test(className))
                // Don't redo this if we've already done it.
                // This allows recalling pretty print to just prettyprint elements
                // that have been added to the page since last call.
                && !prettyPrintedRe.test(className)) {
    
              // make sure this is not nested in an already prettified element
              var nested = false;
              for (var p = cs.parentNode; p; p = p.parentNode) {
                var tn = p.tagName;
                if (preCodeXmpRe.test(tn)
                    && p.className && prettyPrintRe.test(p.className)) {
                  nested = true;
                  break;
                }
              }
              if (!nested) {
                // Mark done.  If we fail to prettyprint for whatever reason,
                // we shouldn't try again.
                cs.className += ' prettyprinted';
    
                // If the classes includes a language extensions, use it.
                // Language extensions can be specified like
                //     <pre class="prettyprint lang-cpp">
                // the language extension "cpp" is used to find a language handler
                // as passed to PR.registerLangHandler.
                // HTML5 recommends that a language be specified using "language-"
                // as the prefix instead.  Google Code Prettify supports both.
                // http://dev.w3.org/html5/spec-author-view/the-code-element.html
                var langExtension = attrs['lang'];
                if (!langExtension) {
                  langExtension = className.match(langExtensionRe);
                  // Support <pre class="prettyprint"><code class="language-c">
                  var wrapper;
                  if (!langExtension && (wrapper = childContentWrapper(cs))
                      && codeRe.test(wrapper.tagName)) {
                    langExtension = wrapper.className.match(langExtensionRe);
                  }
    
                  if (langExtension) { langExtension = langExtension[1]; }
                }
    
                var preformatted;
                if (preformattedTagNameRe.test(cs.tagName)) {
                  preformatted = 1;
                } else {
                  var currentStyle = cs['currentStyle'];
                  var defaultView = doc.defaultView;
                  var whitespace = (
                      currentStyle
                      ? currentStyle['whiteSpace']
                      : (defaultView
                         && defaultView.getComputedStyle)
                      ? defaultView.getComputedStyle(cs, null)
                      .getPropertyValue('white-space')
                      : 0);
                  preformatted = whitespace
                      && 'pre' === whitespace.substring(0, 3);
                }
    
                // Look for a class like linenums or linenums:<n> where <n> is the
                // 1-indexed number of the first line.
                var lineNums = attrs['linenums'];
                if (!(lineNums = lineNums === 'true' || +lineNums)) {
                  lineNums = className.match(/\blinenums\b(?::(\d+))?/);
                  lineNums =
                    lineNums
                    ? lineNums[1] && lineNums[1].length
                      ? +lineNums[1] : true
                    : false;
                }
                if (lineNums) { numberLines(cs, lineNums, preformatted); }
    
                // do the pretty printing
                prettyPrintingJob = {
                  langExtension: langExtension,
                  sourceNode: cs,
                  numberLines: lineNums,
                  pre: preformatted
                };
                applyDecorator(prettyPrintingJob);
              }
            }
          }
          if (k < elements.length) {
            // finish up in a continuation
            setTimeout(doWork, 250);
          } else if ('function' === typeof opt_whenDone) {
            opt_whenDone();
          }
        }
    
        doWork();
      }
    
      /**
       * Contains functions for creating and registering new language handlers.
       * @type {Object}
       */
      var PR = win['PR'] = {
            'createSimpleLexer': createSimpleLexer,
            'registerLangHandler': registerLangHandler,
            'sourceDecorator': sourceDecorator,
            'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
            'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
            'PR_COMMENT': PR_COMMENT,
            'PR_DECLARATION': PR_DECLARATION,
            'PR_KEYWORD': PR_KEYWORD,
            'PR_LITERAL': PR_LITERAL,
            'PR_NOCODE': PR_NOCODE,
            'PR_PLAIN': PR_PLAIN,
            'PR_PUNCTUATION': PR_PUNCTUATION,
            'PR_SOURCE': PR_SOURCE,
            'PR_STRING': PR_STRING,
            'PR_TAG': PR_TAG,
            'PR_TYPE': PR_TYPE,
            'prettyPrintOne':
               IN_GLOBAL_SCOPE
                 ? (win['prettyPrintOne'] = $prettyPrintOne)
                 : (prettyPrintOne = $prettyPrintOne),
            'prettyPrint': prettyPrint =
               IN_GLOBAL_SCOPE
                 ? (win['prettyPrint'] = $prettyPrint)
                 : (prettyPrint = $prettyPrint)
          };
    
      // Make PR available via the Asynchronous Module Definition (AMD) API.
      // Per https://github.com/amdjs/amdjs-api/wiki/AMD:
      // The Asynchronous Module Definition (AMD) API specifies a
      // mechanism for defining modules such that the module and its
      // dependencies can be asynchronously loaded.
      // ...
      // To allow a clear indicator that a global define function (as
      // needed for script src browser loading) conforms to the AMD API,
      // any global define function SHOULD have a property called "amd"
      // whose value is an object. This helps avoid conflict with any
      // other existing JavaScript code that could have defined a define()
      // function that does not conform to the AMD API.
      if (typeof define === "function" && define['amd']) {
        define("google-code-prettify", [], function () {
          return PR; 
        });
      }
    })();
    
    ;(function (global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
        typeof define === 'function' && define.amd ? define(factory) :
        global.moment = factory()
    }(this, (function () { 'use strict';
    
        var hookCallback;
    
        function hooks () {
            return hookCallback.apply(null, arguments);
        }
    
        // This is done to register the method called with moment()
        // without creating circular dependencies.
        function setHookCallback (callback) {
            hookCallback = callback;
        }
    
        function isArray(input) {
            return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
        }
    
        function isObject(input) {
            // IE8 will treat undefined and null as object if it wasn't for
            // input != null
            return input != null && Object.prototype.toString.call(input) === '[object Object]';
        }
    
        function 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 h(t){for(var e=0;e<t.length;e++)t[e]=r(t[e])}function l(t,e){var n,o=[];for(n=0;n<e.length;n++)o[n]=t[e[n]];return o}function m(t){var e=t.split("|"),n=e[2].split(" "),o=e[3].split(""),r=e[4].split(" ");return h(n),h(o),h(r),function(t,e){for(var n=0;n<e;n++)t[n]=Math.round((t[n-1]||0)+6e4*t[n]);t[e-1]=1/0}(r,o.length),{name:e[0],abbrs:l(e[1].split(" "),o),offsets:l(n,o),untils:r,population:0|e[5]}}function p(t){t&&this._set(m(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 v(t){this.zone=t,this.offsetScore=0,this.abbrScore=0}function z(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:e.zone.population-t.zone.population}function g(t,e){var n,o;for(h(e),n=0;n<e.length;n++)o=e[n],c[o]=c[o]||{},c[o][t]=!0}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=z(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 v(S(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 S(t,e){t=w(t);var n,o=i[t];return o instanceof p?o:"string"==typeof o?(o=new p(o),i[t]=o):f[t]&&e!==S&&(n=S(f[t],S))?((o=i[t]=new p)._set(n),o.name=u[t],o):null}function O(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=S(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"),p.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)]}},v.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.23",j.dataVersion="",j._zones=i,j._links=f,j._names=u,j.add=y,j.link=O,j.load=function(t){y(t.zones),O(t.links),j.dataVersion=t.version},j.zone=S,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+"')")),!!S(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=p,j.unpack=m,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)}}s.tz=j,s.defaultZone=null,s.updateOffset=function(t,e){var n,o=s.defaultZone;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&&(n=t._z.utcOffset(t),Math.abs(n)<16&&(n/=60),void 0!==t.utcOffset?t.utcOffset(-n,e):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=S(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=(T=D.utc,function(){return 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?S(t):null,s};var Z=s.momentProperties;return"[object Array]"===Object.prototype.toString.call(Z)?(Z.push("_z"),Z.push("_a")):Z&&(Z._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.8
    */
    
    (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.0 - 10-11-2018 */
    (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 += ' 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 = ' 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 = ' 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 sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;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)}else{nonSpace=true}tokens.push(["text",chr,start,start+1]);start+=1;if(chr==="\n")stripSpace()}}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);token=[type,value,start,scanner.pos];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)}}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.renderPartial=function renderPartial(token,context,partials,tags){if(!partials)return;var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null)return this.renderTokens(this.parse(value,tags),context,partials,value)};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.0.1";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/dC04Nzo2NDx0P3QtMjk6dC00OH1mdW5jdGlvbiByKHQpe3ZhciBlPTAsbj10LnNwbGl0KFwiLlwiKSxvPW5bMF0scj1uWzFdfHxcIlwiLHM9MSxpPTAsZj0xO2Zvcig0NT09PXQuY2hhckNvZGVBdCgwKSYmKGY9LShlPTEpKTtlPG8ubGVuZ3RoO2UrKylpPTYwKmkrYShvLmNoYXJDb2RlQXQoZSkpO2ZvcihlPTA7ZTxyLmxlbmd0aDtlKyspcy89NjAsaSs9YShyLmNoYXJDb2RlQXQoZSkpKnM7cmV0dXJuIGkqZn1mdW5jdGlvbiBoKHQpe2Zvcih2YXIgZT0wO2U8dC5sZW5ndGg7ZSsrKXRbZV09cih0W2VdKX1mdW5jdGlvbiBsKHQsZSl7dmFyIG4sbz1bXTtmb3Iobj0wO248ZS5sZW5ndGg7bisrKW9bbl09dFtlW25dXTtyZXR1cm4gb31mdW5jdGlvbiBtKHQpe3ZhciBlPXQuc3BsaXQoXCJ8XCIpLG49ZVsyXS5zcGxpdChcIiBcIiksbz1lWzNdLnNwbGl0KFwiXCIpLHI9ZVs0XS5zcGxpdChcIiBcIik7cmV0dXJuIGgobiksaChvKSxoKHIpLGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciBuPTA7bjxlO24rKyl0W25dPU1hdGgucm91bmQoKHRbbi0xXXx8MCkrNmU0KnRbbl0pO3RbZS0xXT0xLzB9KHIsby5sZW5ndGgpLHtuYW1lOmVbMF0sYWJicnM6bChlWzFdLnNwbGl0KFwiIFwiKSxvKSxvZmZzZXRzOmwobixvKSx1bnRpbHM6cixwb3B1bGF0aW9uOjB8ZVs1XX19ZnVuY3Rpb24gcCh0KXt0JiZ0aGlzLl9zZXQobSh0KSl9ZnVuY3Rpb24gZCh0KXt2YXIgZT10LnRvVGltZVN0cmluZygpLG49ZS5tYXRjaCgvXFwoW2EteiBdK1xcKS9pKTtcIkdNVFwiPT09KG49biYmblswXT8obj1uWzBdLm1hdGNoKC9bQS1aXS9nKSk/bi5qb2luKFwiXCIpOnZvaWQgMDoobj1lLm1hdGNoKC9bQS1aXXszLDV9L2cpKT9uWzBdOnZvaWQgMCkmJihuPXZvaWQgMCksdGhpcy5hdD0rdCx0aGlzLmFiYnI9bix0aGlzLm9mZnNldD10LmdldFRpbWV6b25lT2Zmc2V0KCl9ZnVuY3Rpb24gdih0KXt0aGlzLnpvbmU9dCx0aGlzLm9mZnNldFNjb3JlPTAsdGhpcy5hYmJyU2NvcmU9MH1mdW5jdGlvbiB6KHQsZSl7Zm9yKHZhciBuLG87bz02ZTQqKChlLmF0LXQuYXQpLzEyZTR8MCk7KShuPW5ldyBkKG5ldyBEYXRlKHQuYXQrbykpKS5vZmZzZXQ9PT10Lm9mZnNldD90PW46ZT1uO3JldHVybiB0fWZ1bmN0aW9uIGIodCxlKXtyZXR1cm4gdC5vZmZzZXRTY29yZSE9PWUub2Zmc2V0U2NvcmU/dC5vZmZzZXRTY29yZS1lLm9mZnNldFNjb3JlOnQuYWJiclNjb3JlIT09ZS5hYmJyU2NvcmU/dC5hYmJyU2NvcmUtZS5hYmJyU2NvcmU6ZS56b25lLnBvcHVsYXRpb24tdC56b25lLnBvcHVsYXRpb259ZnVuY3Rpb24gZyh0LGUpe3ZhciBuLG87Zm9yKGgoZSksbj0wO248ZS5sZW5ndGg7bisrKW89ZVtuXSxjW29dPWNbb118fHt9LGNbb11bdF09ITB9ZnVuY3Rpb24gXygpe3RyeXt2YXIgdD1JbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7aWYodCYmMzx0Lmxlbmd0aCl7dmFyIGU9dVt3KHQpXTtpZihlKXJldHVybiBlO0EoXCJNb21lbnQgVGltZXpvbmUgZm91bmQgXCIrdCtcIiBmcm9tIHRoZSBJbnRsIGFwaSwgYnV0IGRpZCBub3QgaGF2ZSB0aGF0IGRhdGEgbG9hZGVkLlwiKX19Y2F0Y2godCl7fXZhciBuLG8scixzPWZ1bmN0aW9uKCl7dmFyIHQsZSxuLG89KG5ldyBEYXRlKS5nZXRGdWxsWWVhcigpLTIscj1uZXcgZChuZXcgRGF0ZShvLDAsMSkpLHM9W3JdO2ZvcihuPTE7bjw0ODtuKyspKGU9bmV3IGQobmV3IERhdGUobyxuLDEpKSkub2Zmc2V0IT09ci5vZmZzZXQmJih0PXoocixlKSxzLnB1c2godCkscy5wdXNoKG5ldyBkKG5ldyBEYXRlKHQuYXQrNmU0KSkpKSxyPWU7Zm9yKG49MDtuPDQ7bisrKXMucHVzaChuZXcgZChuZXcgRGF0ZShvK24sMCwxKSkpLHMucHVzaChuZXcgZChuZXcgRGF0ZShvK24sNiwxKSkpO3JldHVybiBzfSgpLGk9cy5sZW5ndGgsZj1mdW5jdGlvbih0KXt2YXIgZSxuLG8scj10Lmxlbmd0aCxzPXt9LGk9W107Zm9yKGU9MDtlPHI7ZSsrKWZvcihuIGluIG89Y1t0W2VdLm9mZnNldF18fHt9KW8uaGFzT3duUHJvcGVydHkobikmJihzW25dPSEwKTtmb3IoZSBpbiBzKXMuaGFzT3duUHJvcGVydHkoZSkmJmkucHVzaCh1W2VdKTtyZXR1cm4gaX0ocyksYT1bXTtmb3Iobz0wO288Zi5sZW5ndGg7bysrKXtmb3Iobj1uZXcgdihTKGZbb10pLGkpLHI9MDtyPGk7cisrKW4uc2NvcmVPZmZzZXRBdChzW3JdKTthLnB1c2gobil9cmV0dXJuIGEuc29ydChiKSwwPGEubGVuZ3RoP2FbMF0uem9uZS5uYW1lOnZvaWQgMH1mdW5jdGlvbiB3KHQpe3JldHVybih0fHxcIlwiKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xcLy9nLFwiX1wiKX1mdW5jdGlvbiB5KHQpe3ZhciBlLG4sbyxyO2ZvcihcInN0cmluZ1wiPT10eXBlb2YgdCYmKHQ9W3RdKSxlPTA7ZTx0Lmxlbmd0aDtlKyspcj13KG49KG89dFtlXS5zcGxpdChcInxcIikpWzBdKSxpW3JdPXRbZV0sdVtyXT1uLGcocixvWzJdLnNwbGl0KFwiIFwiKSl9ZnVuY3Rpb24gUyh0LGUpe3Q9dyh0KTt2YXIgbixvPWlbdF07cmV0dXJuIG8gaW5zdGFuY2VvZiBwP286XCJzdHJpbmdcIj09dHlwZW9mIG8/KG89bmV3IHAobyksaVt0XT1vKTpmW3RdJiZlIT09UyYmKG49UyhmW3RdLFMpKT8oKG89aVt0XT1uZXcgcCkuX3NldChuKSxvLm5hbWU9dVt0XSxvKTpudWxsfWZ1bmN0aW9uIE8odCl7dmFyIGUsbixvLHI7Zm9yKFwic3RyaW5nXCI9PXR5cGVvZiB0JiYodD1bdF0pLGU9MDtlPHQubGVuZ3RoO2UrKylvPXcoKG49dFtlXS5zcGxpdChcInxcIikpWzBdKSxyPXcoblsxXSksZltvXT1yLHVbb109blswXSxmW3JdPW8sdVtyXT1uWzFdfWZ1bmN0aW9uIE0odCl7dmFyIGU9XCJYXCI9PT10Ll9mfHxcInhcIj09PXQuX2Y7cmV0dXJuISghdC5fYXx8dm9pZCAwIT09dC5fdHptfHxlKX1mdW5jdGlvbiBBKHQpe1widW5kZWZpbmVkXCIhPXR5cGVvZiBjb25zb2xlJiZcImZ1bmN0aW9uXCI9PXR5cGVvZiBjb25zb2xlLmVycm9yJiZjb25zb2xlLmVycm9yKHQpfWZ1bmN0aW9uIGoodCl7dmFyIGU9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLDAsLTEpLG49YXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGgtMV0sbz1TKG4pLHI9cy51dGMuYXBwbHkobnVsbCxlKTtyZXR1cm4gbyYmIXMuaXNNb21lbnQodCkmJk0ocikmJnIuYWRkKG8ucGFyc2UociksXCJtaW51dGVzXCIpLHIudHoobikscn0objwyfHwyPT09biYmbzw2KSYmQShcIk1vbWVudCBUaW1lem9uZSByZXF1aXJlcyBNb21lbnQuanMgPj0gMi42LjAuIFlvdSBhcmUgdXNpbmcgTW9tZW50LmpzIFwiK3MudmVyc2lvbitcIi4gU2VlIG1vbWVudGpzLmNvbVwiKSxwLnByb3RvdHlwZT17X3NldDpmdW5jdGlvbih0KXt0aGlzLm5hbWU9dC5uYW1lLHRoaXMuYWJicnM9dC5hYmJycyx0aGlzLnVudGlscz10LnVudGlscyx0aGlzLm9mZnNldHM9dC5vZmZzZXRzLHRoaXMucG9wdWxhdGlvbj10LnBvcHVsYXRpb259LF9pbmRleDpmdW5jdGlvbih0KXt2YXIgZSxuPSt0LG89dGhpcy51bnRpbHM7Zm9yKGU9MDtlPG8ubGVuZ3RoO2UrKylpZihuPG9bZV0pcmV0dXJuIGV9LHBhcnNlOmZ1bmN0aW9uKHQpe3ZhciBlLG4sbyxyLHM9K3QsaT10aGlzLm9mZnNldHMsZj10aGlzLnVudGlscyxhPWYubGVuZ3RoLTE7Zm9yKHI9MDtyPGE7cisrKWlmKGU9aVtyXSxuPWlbcisxXSxvPWlbcj9yLTE6cl0sZTxuJiZqLm1vdmVBbWJpZ3VvdXNGb3J3YXJkP2U9bjpvPGUmJmoubW92ZUludmFsaWRGb3J3YXJkJiYoZT1vKSxzPGZbcl0tNmU0KmUpcmV0dXJuIGlbcl07cmV0dXJuIGlbYV19LGFiYnI6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuYWJicnNbdGhpcy5faW5kZXgodCldfSxvZmZzZXQ6ZnVuY3Rpb24odCl7cmV0dXJuIEEoXCJ6b25lLm9mZnNldCBoYXMgYmVlbiBkZXByZWNhdGVkIGluIGZhdm9yIG9mIHpvbmUudXRjT2Zmc2V0XCIpLHRoaXMub2Zmc2V0c1t0aGlzLl9pbmRleCh0KV19LHV0Y09mZnNldDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5vZmZzZXRzW3RoaXMuX2luZGV4KHQpXX19LHYucHJvdG90eXBlLnNjb3JlT2Zmc2V0QXQ9ZnVuY3Rpb24odCl7dGhpcy5vZmZzZXRTY29yZSs9TWF0aC5hYnModGhpcy56b25lLnV0Y09mZnNldCh0LmF0KS10Lm9mZnNldCksdGhpcy56b25lLmFiYnIodC5hdCkucmVwbGFjZSgvW15BLVpdL2csXCJcIikhPT10LmFiYnImJnRoaXMuYWJiclNjb3JlKyt9LGoudmVyc2lvbj1cIjAuNS4yM1wiLGouZGF0YVZlcnNpb249XCJcIixqLl96b25lcz1pLGouX2xpbmtzPWYsai5fbmFtZXM9dSxqLmFkZD15LGoubGluaz1PLGoubG9hZD1mdW5jdGlvbih0KXt5KHQuem9uZXMpLE8odC5saW5rcyksai5kYXRhVmVyc2lvbj10LnZlcnNpb259LGouem9uZT1TLGouem9uZUV4aXN0cz1mdW5jdGlvbiB0KGUpe3JldHVybiB0LmRpZFNob3dFcnJvcnx8KHQuZGlkU2hvd0Vycm9yPSEwLEEoXCJtb21lbnQudHouem9uZUV4aXN0cygnXCIrZStcIicpIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgIW1vbWVudC50ei56b25lKCdcIitlK1wiJylcIikpLCEhUyhlKX0sai5ndWVzcz1mdW5jdGlvbih0KXtyZXR1cm4gZSYmIXR8fChlPV8oKSksZX0sai5uYW1lcz1mdW5jdGlvbigpe3ZhciB0LGU9W107Zm9yKHQgaW4gdSl1Lmhhc093blByb3BlcnR5KHQpJiYoaVt0XXx8aVtmW3RdXSkmJnVbdF0mJmUucHVzaCh1W3RdKTtyZXR1cm4gZS5zb3J0KCl9LGouWm9uZT1wLGoudW5wYWNrPW0sai51bnBhY2tCYXNlNjA9cixqLm5lZWRzT2Zmc2V0PU0sai5tb3ZlSW52YWxpZEZvcndhcmQ9ITAsai5tb3ZlQW1iaWd1b3VzRm9yd2FyZD0hMTt2YXIgVCxEPXMuZm47ZnVuY3Rpb24geCh0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fej90aGlzLl96LmFiYnIodGhpcyk6dC5jYWxsKHRoaXMpfX1zLnR6PWoscy5kZWZhdWx0Wm9uZT1udWxsLHMudXBkYXRlT2Zmc2V0PWZ1bmN0aW9uKHQsZSl7dmFyIG4sbz1zLmRlZmF1bHRab25lO3ZvaWQgMD09PXQuX3omJihvJiZNKHQpJiYhdC5faXNVVEMmJih0Ll9kPXMudXRjKHQuX2EpLl9kLHQudXRjKCkuYWRkKG8ucGFyc2UodCksXCJtaW51dGVzXCIpKSx0Ll96PW8pLHQuX3omJihuPXQuX3oudXRjT2Zmc2V0KHQpLE1hdGguYWJzKG4pPDE2JiYobi89NjApLHZvaWQgMCE9PXQudXRjT2Zmc2V0P3QudXRjT2Zmc2V0KC1uLGUpOnQuem9uZShuLGUpKX0sRC50ej1mdW5jdGlvbih0LGUpe2lmKHQpe2lmKFwic3RyaW5nXCIhPXR5cGVvZiB0KXRocm93IG5ldyBFcnJvcihcIlRpbWUgem9uZSBuYW1lIG11c3QgYmUgYSBzdHJpbmcsIGdvdCBcIit0K1wiIFtcIit0eXBlb2YgdCtcIl1cIik7cmV0dXJuIHRoaXMuX3o9Uyh0KSx0aGlzLl96P3MudXBkYXRlT2Zmc2V0KHRoaXMsZSk6QShcIk1vbWVudCBUaW1lem9uZSBoYXMgbm8gZGF0YSBmb3IgXCIrdCtcIi4gU2VlIGh0dHA6Ly9tb21lbnRqcy5jb20vdGltZXpvbmUvZG9jcy8jL2RhdGEtbG9hZGluZy8uXCIpLHRoaXN9aWYodGhpcy5feilyZXR1cm4gdGhpcy5fei5uYW1lfSxELnpvbmVOYW1lPXgoRC56b25lTmFtZSksRC56b25lQWJicj14KEQuem9uZUFiYnIpLEQudXRjPShUPUQudXRjLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3o9bnVsbCxULmFwcGx5KHRoaXMsYXJndW1lbnRzKX0pLHMudHouc2V0RGVmYXVsdD1mdW5jdGlvbih0KXtyZXR1cm4objwyfHwyPT09biYmbzw5KSYmQShcIk1vbWVudCBUaW1lem9uZSBzZXREZWZhdWx0KCkgcmVxdWlyZXMgTW9tZW50LmpzID49IDIuOS4wLiBZb3UgYXJlIHVzaW5nIE1vbWVudC5qcyBcIitzLnZlcnNpb24rXCIuXCIpLHMuZGVmYXVsdFpvbmU9dD9TKHQpOm51bGwsc307dmFyIFo9cy5tb21lbnRQcm9wZXJ0aWVzO3JldHVyblwiW29iamVjdCBBcnJheV1cIj09PU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChaKT8oWi5wdXNoKFwiX3pcIiksWi5wdXNoKFwiX2FcIikpOlomJihaLl96PW51bGwpLHN9KTsiLCJ2YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG4vLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIEluY29uc2lzdGVudE5hbWluZ1xudmFyIERhdGVUaW1lUGlja2VyID0gZnVuY3Rpb24gKCQsIG1vbWVudCkge1xuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIEluY29uc2lzdGVudE5hbWluZ1xuICAgIHZhciBOQU1FID0gJ2RhdGV0aW1lcGlja2VyJyxcbiAgICAgICAgREFUQV9LRVkgPSAnJyArIE5BTUUsXG4gICAgICAgIEVWRU5UX0tFWSA9ICcuJyArIERBVEFfS0VZLFxuICAgICAgICBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJyxcbiAgICAgICAgU2VsZWN0b3IgPSB7XG4gICAgICAgIERBVEFfVE9HR0xFOiAnW2RhdGEtdG9nZ2xlPVwiJyArIERBVEFfS0VZICsgJ1wiXSdcbiAgICB9LFxuICAgICAgICBDbGFzc05hbWUgPSB7XG4gICAgICAgIElOUFVUOiBOQU1FICsgJy1pbnB1dCdcbiAgICB9LFxuICAgICAgICBFdmVudCA9IHtcbiAgICAgICAgQ0hBTkdFOiAnY2hhbmdlJyArIEVWRU5UX0tFWSxcbiAgICAgICAgQkxVUjogJ2JsdXInICsgRVZFTlRfS0VZLFxuICAgICAgICBLRVlVUDogJ2tleXVwJyArIEVWRU5UX0tFWSxcbiAgICAgICAgS0VZRE9XTjogJ2tleWRvd24nICsgRVZFTlRfS0VZLFxuICAgICAgICBGT0NVUzogJ2ZvY3VzJyArIEVWRU5UX0tFWSxcbiAgICAgICAgQ0xJQ0tfREFUQV9BUEk6ICdjbGljaycgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVksXG4gICAgICAgIC8vZW1pdHRlZFxuICAgICAgICBVUERBVEU6ICd1cGRhdGUnICsgRVZFTlRfS0VZLFxuICAgICAgICBFUlJPUjogJ2Vycm9yJyArIEVWRU5UX0tFWSxcbiAgICAgICAgSElERTogJ2hpZGUnICsgRVZFTlRfS0VZLFxuICAgICAgICBTSE9XOiAnc2hvdycgKyBFVkVOVF9LRVlcbiAgICB9LFxuICAgICAgICBEYXRlUGlja2VyTW9kZXMgPSBbe1xuICAgICAgICBDTEFTU19OQU1FOiAnZGF5cycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ00nLFxuICAgICAgICBOQVZfU1RFUDogMVxuICAgIH0sIHtcbiAgICAgICAgQ0xBU1NfTkFNRTogJ21vbnRocycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ3knLFxuICAgICAgICBOQVZfU1RFUDogMVxuICAgIH0sIHtcbiAgICAgICAgQ0xBU1NfTkFNRTogJ3llYXJzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAneScsXG4gICAgICAgIE5BVl9TVEVQOiAxMFxuICAgIH0sIHtcbiAgICAgICAgQ0xBU1NfTkFNRTogJ2RlY2FkZXMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICAgICAgTkFWX1NURVA6IDEwMFxuICAgIH1dLFxuICAgICAgICBLZXlNYXAgPSB7XG4gICAgICAgICd1cCc6IDM4LFxuICAgICAgICAzODogJ3VwJyxcbiAgICAgICAgJ2Rvd24nOiA0MCxcbiAgICAgICAgNDA6ICdkb3duJyxcbiAgICAgICAgJ2xlZnQnOiAzNyxcbiAgICAgICAgMzc6ICdsZWZ0JyxcbiAgICAgICAgJ3JpZ2h0JzogMzksXG4gICAgICAgIDM5OiAncmlnaHQnLFxuICAgICAgICAndGFiJzogOSxcbiAgICAgICAgOTogJ3RhYicsXG4gICAgICAgICdlc2NhcGUnOiAyNyxcbiAgICAgICAgMjc6ICdlc2NhcGUnLFxuICAgICAgICAnZW50ZXInOiAxMyxcbiAgICAgICAgMTM6ICdlbnRlcicsXG4gICAgICAgICdwYWdlVXAnOiAzMyxcbiAgICAgICAgMzM6ICdwYWdlVXAnLFxuICAgICAgICAncGFnZURvd24nOiAzNCxcbiAgICAgICAgMzQ6ICdwYWdlRG93bicsXG4gICAgICAgICdzaGlmdCc6IDE2LFxuICAgICAgICAxNjogJ3NoaWZ0JyxcbiAgICAgICAgJ2NvbnRyb2wnOiAxNyxcbiAgICAgICAgMTc6ICdjb250cm9sJyxcbiAgICAgICAgJ3NwYWNlJzogMzIsXG4gICAgICAgIDMyOiAnc3BhY2UnLFxuICAgICAgICAndCc6IDg0LFxuICAgICAgICA4NDogJ3QnLFxuICAgICAgICAnZGVsZXRlJzogNDYsXG4gICAgICAgIDQ2OiAnZGVsZXRlJ1xuICAgIH0sXG4gICAgICAgIFZpZXdNb2RlcyA9IFsndGltZXMnLCAnZGF5cycsICdtb250aHMnLCAneWVhcnMnLCAnZGVjYWRlcyddLFxuICAgICAgICBrZXlTdGF0ZSA9IHt9LFxuICAgICAgICBrZXlQcmVzc0hhbmRsZWQgPSB7fTtcblxuICAgIHZhciBEZWZhdWx0ID0ge1xuICAgICAgICB0aW1lWm9uZTogJycsXG4gICAgICAgIGZvcm1hdDogZmFsc2UsXG4gICAgICAgIGRheVZpZXdIZWFkZXJGb3JtYXQ6ICdNTU1NIFlZWVknLFxuICAgICAgICBleHRyYUZvcm1hdHM6IGZhbHNlLFxuICAgICAgICBzdGVwcGluZzogMSxcbiAgICAgICAgbWluRGF0ZTogZmFsc2UsXG4gICAgICAgIG1heERhdGU6IGZhbHNlLFxuICAgICAgICB1c2VDdXJyZW50OiB0cnVlLFxuICAgICAgICBjb2xsYXBzZTogdHJ1ZSxcbiAgICAgICAgbG9jYWxlOiBtb21lbnQubG9jYWxlKCksXG4gICAgICAgIGRlZmF1bHREYXRlOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWREYXRlczogZmFsc2UsXG4gICAgICAgIGVuYWJsZWREYXRlczogZmFsc2UsXG4gICAgICAgIGljb25zOiB7XG4gICAgICAgICAgICB0aW1lOiAnZmEgZmEtY2xvY2stbycsXG4gICAgICAgICAgICBkYXRlOiAnZmEgZmEtY2FsZW5kYXInLFxuICAgICAgICAgICAgdXA6ICdmYSBmYS1hcnJvdy11cCcsXG4gICAgICAgICAgICBkb3duOiAnZmEgZmEtYXJyb3ctZG93bicsXG4gICAgICAgICAgICBwcmV2aW91czogJ2ZhIGZhLWNoZXZyb24tbGVmdCcsXG4gICAgICAgICAgICBuZXh0OiAnZmEgZmEtY2hldnJvbi1yaWdodCcsXG4gICAgICAgICAgICB0b2RheTogJ2ZhIGZhLWNhbGVuZGFyLWNoZWNrLW8nLFxuICAgICAgICAgICAgY2xlYXI6ICdmYSBmYS1kZWxldGUnLFxuICAgICAgICAgICAgY2xvc2U6ICdmYSBmYS10aW1lcydcbiAgICAgICAgfSxcbiAgICAgICAgdG9vbHRpcHM6IHtcbiAgICAgICAgICAgIHRvZGF5OiAnR28gdG8gdG9kYXknLFxuICAgICAgICAgICAgY2xlYXI6ICdDbGVhciBzZWxlY3Rpb24nLFxuICAgICAgICAgICAgY2xvc2U6ICdDbG9zZSB0aGUgcGlja2VyJyxcbiAgICAgICAgICAgIHNlbGVjdE1vbnRoOiAnU2VsZWN0IE1vbnRoJyxcbiAgICAgICAgICAgIHByZXZNb250aDogJ1ByZXZpb3VzIE1vbnRoJyxcbiAgICAgICAgICAgIG5leHRNb250aDogJ05leHQgTW9udGgnLFxuICAgICAgICAgICAgc2VsZWN0WWVhcjogJ1NlbGVjdCBZZWFyJyxcbiAgICAgICAgICAgIHByZXZZZWFyOiAnUHJldmlvdXMgWWVhcicsXG4gICAgICAgICAgICBuZXh0WWVhcjogJ05leHQgWWVhcicsXG4gICAgICAgICAgICBzZWxlY3REZWNhZGU6ICdTZWxlY3QgRGVjYWRlJyxcbiAgICAgICAgICAgIHByZXZEZWNhZGU6ICdQcmV2aW91cyBEZWNhZGUnLFxuICAgICAgICAgICAgbmV4dERlY2FkZTogJ05leHQgRGVjYWRlJyxcbiAgICAgICAgICAgIHByZXZDZW50dXJ5OiAnUHJldmlvdXMgQ2VudHVyeScsXG4gICAgICAgICAgICBuZXh0Q2VudHVyeTogJ05leHQgQ2VudHVyeScsXG4gICAgICAgICAgICBwaWNrSG91cjogJ1BpY2sgSG91cicsXG4gICAgICAgICAgICBpbmNyZW1lbnRIb3VyOiAnSW5jcmVtZW50IEhvdXInLFxuICAgICAgICAgICAgZGVjcmVtZW50SG91cjogJ0RlY3JlbWVudCBIb3VyJyxcbiAgICAgICAgICAgIHBpY2tNaW51dGU6ICdQaWNrIE1pbnV0ZScsXG4gICAgICAgICAgICBpbmNyZW1lbnRNaW51dGU6ICdJbmNyZW1lbnQgTWludXRlJyxcbiAgICAgICAgICAgIGRlY3JlbWVudE1pbnV0ZTogJ0RlY3JlbWVudCBNaW51dGUnLFxuICAgICAgICAgICAgcGlja1NlY29uZDogJ1BpY2sgU2Vjb25kJyxcbiAgICAgICAgICAgIGluY3JlbWVudFNlY29uZDogJ0luY3JlbWVudCBTZWNvbmQnLFxuICAgICAgICAgICAgZGVjcmVtZW50U2Vjb25kOiAnRGVjcmVtZW50IFNlY29uZCcsXG4gICAgICAgICAgICB0b2dnbGVQZXJpb2Q6ICdUb2dnbGUgUGVyaW9kJyxcbiAgICAgICAgICAgIHNlbGVjdFRpbWU6ICdTZWxlY3QgVGltZScsXG4gICAgICAgICAgICBzZWxlY3REYXRlOiAnU2VsZWN0IERhdGUnXG4gICAgICAgIH0sXG4gICAgICAgIHVzZVN0cmljdDogZmFsc2UsXG4gICAgICAgIHNpZGVCeVNpZGU6IGZhbHNlLFxuICAgICAgICBkYXlzT2ZXZWVrRGlzYWJsZWQ6IGZhbHNlLFxuICAgICAgICBjYWxlbmRhcldlZWtzOiBmYWxzZSxcbiAgICAgICAgdmlld01vZGU6ICdkYXlzJyxcbiAgICAgICAgdG9vbGJhclBsYWNlbWVudDogJ2RlZmF1bHQnLFxuICAgICAgICBidXR0b25zOiB7XG4gICAgICAgICAgICBzaG93VG9kYXk6IGZhbHNlLFxuICAgICAgICAgICAgc2hvd0NsZWFyOiBmYWxzZSxcbiAgICAgICAgICAgIHNob3dDbG9zZTogZmFsc2VcbiAgICAgICAgfSxcbiAgICAgICAgd2lkZ2V0UG9zaXRpb25pbmc6IHtcbiAgICAgICAgICAgIGhvcml6b250YWw6ICdhdXRvJyxcbiAgICAgICAgICAgIHZlcnRpY2FsOiAnYXV0bydcbiAgICAgICAgfSxcbiAgICAgICAgd2lkZ2V0UGFyZW50OiBudWxsLFxuICAgICAgICBpZ25vcmVSZWFkb25seTogZmFsc2UsXG4gICAgICAgIGtlZXBPcGVuOiBmYWxzZSxcbiAgICAgICAgZm9jdXNPblNob3c6IHRydWUsXG4gICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgIGtlZXBJbnZhbGlkOiBmYWxzZSxcbiAgICAgICAga2V5QmluZHM6IHtcbiAgICAgICAgICAgIHVwOiBmdW5jdGlvbiB1cCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoNywgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQodGhpcy5zdGVwcGluZygpLCAnbScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZG93bjogZnVuY3Rpb24gZG93bigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCg3LCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuc3RlcHBpbmcoKSwgJ20nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdjb250cm9sIHVwJzogZnVuY3Rpb24gY29udHJvbFVwKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAneScpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnaCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2NvbnRyb2wgZG93bic6IGZ1bmN0aW9uIGNvbnRyb2xEb3duKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ3knKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnaCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGVmdDogZnVuY3Rpb24gbGVmdCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJpZ2h0OiBmdW5jdGlvbiByaWdodCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICdkJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYWdlVXA6IGZ1bmN0aW9uIHBhZ2VVcCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ00nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhZ2VEb3duOiBmdW5jdGlvbiBwYWdlRG93bigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICdNJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlbnRlcjogZnVuY3Rpb24gZW50ZXIoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVzY2FwZTogZnVuY3Rpb24gZXNjYXBlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnY29udHJvbCBzcGFjZSc6IGZ1bmN0aW9uIGNvbnRyb2xTcGFjZSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmJ0bltkYXRhLWFjdGlvbj1cInRvZ2dsZVBlcmlvZFwiXScpLmNsaWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHQ6IGZ1bmN0aW9uIHQoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZSh0aGlzLmdldE1vbWVudCgpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnZGVsZXRlJzogZnVuY3Rpb24gX2RlbGV0ZSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBkZWJ1ZzogZmFsc2UsXG4gICAgICAgIGFsbG93SW5wdXRUb2dnbGU6IGZhbHNlLFxuICAgICAgICBkaXNhYmxlZFRpbWVJbnRlcnZhbHM6IGZhbHNlLFxuICAgICAgICBkaXNhYmxlZEhvdXJzOiBmYWxzZSxcbiAgICAgICAgZW5hYmxlZEhvdXJzOiBmYWxzZSxcbiAgICAgICAgdmlld0RhdGU6IGZhbHNlLFxuICAgICAgICBhbGxvd011bHRpZGF0ZTogZmFsc2UsXG4gICAgICAgIG11bHRpZGF0ZVNlcGFyYXRvcjogJywnXG4gICAgfTtcblxuICAgIC8vIFJlU2hhcnBlciByZXN0b3JlIEluY29uc2lzdGVudE5hbWluZ1xuXG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBEZWNsYXJhdGlvbkhpZGVzXG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBJbmNvbnNpc3RlbnROYW1pbmdcblxuICAgIHZhciBEYXRlVGltZVBpY2tlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLyoqIEBuYW1lc3BhY2UgZURhdGEuZGF0ZU9wdGlvbnMgKi9cbiAgICAgICAgLyoqIEBuYW1lc3BhY2UgbW9tZW50LnR6ICovXG5cbiAgICAgICAgZnVuY3Rpb24gRGF0ZVRpbWVQaWNrZXIoZWxlbWVudCwgb3B0aW9ucykge1xuICAgICAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIERhdGVUaW1lUGlja2VyKTtcblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucyA9IHRoaXMuX2dldE9wdGlvbnMob3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZCA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy51bnNldCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMudXNlMjRIb3VycyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmFjdHVhbEZvcm1hdCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnBhcnNlRm9ybWF0cyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRWaWV3TW9kZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLk1pblZpZXdNb2RlTnVtYmVyID0gMDtcblxuICAgICAgICAgICAgdGhpcy5faW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICAvKipcclxuICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XHJcbiAgICAgICAgICovXG5cblxuICAgICAgICAvL3ByaXZhdGVcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2ludCA9IGZ1bmN0aW9uIF9pbnQoKSB7XG4gICAgICAgICAgICB2YXIgdGFyZ2V0SW5wdXQgPSB0aGlzLl9lbGVtZW50LmRhdGEoJ3RhcmdldC1pbnB1dCcpO1xuICAgICAgICAgICAgaWYgKHRoaXMuX2VsZW1lbnQuaXMoJ2lucHV0JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0ID0gdGhpcy5fZWxlbWVudDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0SW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmICh0YXJnZXRJbnB1dCA9PT0gJ25lYXJlc3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQgPSB0aGlzLl9lbGVtZW50LmZpbmQoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dCA9ICQodGFyZ2V0SW5wdXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fZGF0ZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGVzWzBdID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gdGhpcy5nZXRNb21lbnQoKS5jbG9uZSgpO1xuXG4gICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCB0aGlzLl9vcHRpb25zLCB0aGlzLl9kYXRhVG9PcHRpb25zKCkpO1xuXG4gICAgICAgICAgICB0aGlzLm9wdGlvbnModGhpcy5fb3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC5pcygnaW5wdXQnKSAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9wYXJzZUlucHV0RGF0ZSh0aGlzLmlucHV0LnZhbCgpLnRyaW0oKSksIDApO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlICYmIHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LmF0dHIoJ3BsYWNlaG9sZGVyJykgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbiBfdXBkYXRlKCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2ZpbGxEYXRlKCk7XG4gICAgICAgICAgICB0aGlzLl9maWxsVGltZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fc2V0VmFsdWUgPSBmdW5jdGlvbiBfc2V0VmFsdWUodGFyZ2V0TW9tZW50LCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIG9sZERhdGUgPSB0aGlzLnVuc2V0ID8gbnVsbCA6IHRoaXMuX2RhdGVzW2luZGV4XTtcbiAgICAgICAgICAgIHZhciBvdXRwVmFsdWUgPSAnJztcbiAgICAgICAgICAgIC8vIGNhc2Ugb2YgY2FsbGluZyBzZXRWYWx1ZShudWxsIG9yIGZhbHNlKVxuICAgICAgICAgICAgaWYgKCF0YXJnZXRNb21lbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgfHwgdGhpcy5fZGF0ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudW5zZXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZCA9IFtdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSA9IHRoaXMuX2VsZW1lbnQuZGF0YSgnZGF0ZScpICsgJywnO1xuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSBvdXRwVmFsdWUucmVwbGFjZShvbGREYXRlLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkgKyAnLCcsICcnKS5yZXBsYWNlKCcsLCcsICcnKS5yZXBsYWNlKC8sXFxzKiQvLCAnJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwob3V0cFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC50cmlnZ2VyKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnLCBvdXRwVmFsdWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLFxuICAgICAgICAgICAgICAgICAgICBkYXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGFyZ2V0TW9tZW50ID0gdGFyZ2V0TW9tZW50LmNsb25lKCkubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRNb21lbnQudHoodGhpcy5fb3B0aW9ucy50aW1lWm9uZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0TW9tZW50Lm1pbnV0ZXMoTWF0aC5yb3VuZCh0YXJnZXRNb21lbnQubWludXRlcygpIC8gdGhpcy5fb3B0aW9ucy5zdGVwcGluZykgKiB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nKS5zZWNvbmRzKDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZCh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaW5kZXhdID0gdGFyZ2V0TW9tZW50O1xuICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzRm9ybWF0dGVkW2luZGV4XSA9IHRhcmdldE1vbWVudC5mb3JtYXQoJ1lZWVktTU0tREQnKTtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRhcmdldE1vbWVudC5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlICYmIHRoaXMuX2RhdGVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlICs9ICcnICsgdGhpcy5fZGF0ZXNbaV0uZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSArIHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSA9IG91dHBWYWx1ZS5yZXBsYWNlKC8sXFxzKiQvLCAnJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gdGhpcy5fZGF0ZXNbaW5kZXhdLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwob3V0cFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC50cmlnZ2VyKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnLCBvdXRwVmFsdWUpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy51bnNldCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLFxuICAgICAgICAgICAgICAgICAgICBkYXRlOiB0aGlzLl9kYXRlc1tpbmRleF0uY2xvbmUoKSxcbiAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dC52YWwoJycgKyAodGhpcy51bnNldCA/ICcnIDogdGhpcy5fZGF0ZXNbaW5kZXhdLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IHRhcmdldE1vbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuRVJST1IsXG4gICAgICAgICAgICAgICAgICAgIGRhdGU6IHRhcmdldE1vbWVudCxcbiAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fY2hhbmdlID0gZnVuY3Rpb24gX2NoYW5nZShlKSB7XG4gICAgICAgICAgICB2YXIgdmFsID0gJChlLnRhcmdldCkudmFsKCkudHJpbSgpLFxuICAgICAgICAgICAgICAgIHBhcnNlZERhdGUgPSB2YWwgPyB0aGlzLl9wYXJzZUlucHV0RGF0ZSh2YWwpIDogbnVsbDtcbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHBhcnNlZERhdGUpO1xuICAgICAgICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvL25vaW5zcGVjdGlvbiBKU01ldGhvZENhbkJlU3RhdGljXG5cblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2dldE9wdGlvbnMgPSBmdW5jdGlvbiBfZ2V0T3B0aW9ucyhvcHRpb25zKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gJC5leHRlbmQodHJ1ZSwge30sIERlZmF1bHQsIG9wdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNUaW1lWm9uZSA9IGZ1bmN0aW9uIF9oYXNUaW1lWm9uZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBtb21lbnQudHogIT09IHVuZGVmaW5lZCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gbnVsbCAmJiB0aGlzLl9vcHRpb25zLnRpbWVab25lICE9PSAnJztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzRW5hYmxlZCA9IGZ1bmN0aW9uIF9pc0VuYWJsZWQoZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZ3JhbnVsYXJpdHkgIT09ICdzdHJpbmcnIHx8IGdyYW51bGFyaXR5Lmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpc0VuYWJsZWQgZXhwZWN0cyBhIHNpbmdsZSBjaGFyYWN0ZXIgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3dpdGNoIChncmFudWxhcml0eSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZignWScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ00nKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2QnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnSCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2gnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC5pbmRleE9mKCdtJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZigncycpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdhJzpcbiAgICAgICAgICAgICAgICBjYXNlICdBJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignYScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNUaW1lID0gZnVuY3Rpb24gX2hhc1RpbWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNFbmFibGVkKCdoJykgfHwgdGhpcy5faXNFbmFibGVkKCdtJykgfHwgdGhpcy5faXNFbmFibGVkKCdzJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9oYXNEYXRlID0gZnVuY3Rpb24gX2hhc0RhdGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNFbmFibGVkKCd5JykgfHwgdGhpcy5faXNFbmFibGVkKCdNJykgfHwgdGhpcy5faXNFbmFibGVkKCdkJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9kYXRhVG9PcHRpb25zID0gZnVuY3Rpb24gX2RhdGFUb09wdGlvbnMoKSB7XG4gICAgICAgICAgICB2YXIgZURhdGEgPSB0aGlzLl9lbGVtZW50LmRhdGEoKTtcbiAgICAgICAgICAgIHZhciBkYXRhT3B0aW9ucyA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoZURhdGEuZGF0ZU9wdGlvbnMgJiYgZURhdGEuZGF0ZU9wdGlvbnMgaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgICAgICAgICBkYXRhT3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIGRhdGFPcHRpb25zLCBlRGF0YS5kYXRlT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQuZWFjaCh0aGlzLl9vcHRpb25zLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGF0dHJpYnV0ZU5hbWUgPSAnZGF0ZScgKyBrZXkuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBrZXkuc2xpY2UoMSk7IC8vdG9kbyBkYXRhIGFwaSBrZXlcbiAgICAgICAgICAgICAgICBpZiAoZURhdGFbYXR0cmlidXRlTmFtZV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhT3B0aW9uc1trZXldID0gZURhdGFbYXR0cmlidXRlTmFtZV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGRhdGFPcHRpb25zW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gZGF0YU9wdGlvbnM7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9ub3RpZnlFdmVudCA9IGZ1bmN0aW9uIF9ub3RpZnlFdmVudChlKSB7XG4gICAgICAgICAgICBpZiAoZS50eXBlID09PSBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UgJiYgKGUuZGF0ZSAmJiBlLmRhdGUuaXNTYW1lKGUub2xkRGF0ZSkpIHx8ICFlLmRhdGUgJiYgIWUub2xkRGF0ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQudHJpZ2dlcihlKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3ZpZXdVcGRhdGUgPSBmdW5jdGlvbiBfdmlld1VwZGF0ZShlKSB7XG4gICAgICAgICAgICBpZiAoZSA9PT0gJ3knKSB7XG4gICAgICAgICAgICAgICAgZSA9ICdZWVlZJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX25vdGlmeUV2ZW50KHtcbiAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5VUERBVEUsXG4gICAgICAgICAgICAgICAgY2hhbmdlOiBlLFxuICAgICAgICAgICAgICAgIHZpZXdEYXRlOiB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3Nob3dNb2RlID0gZnVuY3Rpb24gX3Nob3dNb2RlKGRpcikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkaXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRWaWV3TW9kZSA9IE1hdGgubWF4KHRoaXMuTWluVmlld01vZGVOdW1iZXIsIE1hdGgubWluKDMsIHRoaXMuY3VycmVudFZpZXdNb2RlICsgZGlyKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlciA+IGRpdicpLmhpZGUoKS5maWx0ZXIoJy5kYXRlcGlja2VyLScgKyBEYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLkNMQVNTX05BTUUpLnNob3coKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzSW5EaXNhYmxlZERhdGVzID0gZnVuY3Rpb24gX2lzSW5EaXNhYmxlZERhdGVzKHRlc3REYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzW3Rlc3REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpXSA9PT0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzSW5FbmFibGVkRGF0ZXMgPSBmdW5jdGlvbiBfaXNJbkVuYWJsZWREYXRlcyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzW3Rlc3REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpXSA9PT0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzSW5EaXNhYmxlZEhvdXJzID0gZnVuY3Rpb24gX2lzSW5EaXNhYmxlZEhvdXJzKHRlc3REYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzW3Rlc3REYXRlLmZvcm1hdCgnSCcpXSA9PT0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzSW5FbmFibGVkSG91cnMgPSBmdW5jdGlvbiBfaXNJbkVuYWJsZWRIb3Vycyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzW3Rlc3REYXRlLmZvcm1hdCgnSCcpXSA9PT0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2lzVmFsaWQgPSBmdW5jdGlvbiBfaXNWYWxpZCh0YXJnZXRNb21lbnQsIGdyYW51bGFyaXR5KSB7XG4gICAgICAgICAgICBpZiAoIXRhcmdldE1vbWVudC5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgdGhpcy5faXNJbkRpc2FibGVkRGF0ZXModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmICF0aGlzLl9pc0luRW5hYmxlZERhdGVzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHRhcmdldE1vbWVudC5pc0JlZm9yZSh0aGlzLl9vcHRpb25zLm1pbkRhdGUsIGdyYW51bGFyaXR5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgdGFyZ2V0TW9tZW50LmlzQWZ0ZXIodGhpcy5fb3B0aW9ucy5tYXhEYXRlLCBncmFudWxhcml0eSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZC5pbmRleE9mKHRhcmdldE1vbWVudC5kYXkoKSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpICYmIHRoaXMuX2lzSW5EaXNhYmxlZEhvdXJzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSAmJiAhdGhpcy5faXNJbkVuYWJsZWRIb3Vycyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykpIHtcbiAgICAgICAgICAgICAgICB2YXIgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRhcmdldE1vbWVudC5pc0JldHdlZW4odGhpc1swXSwgdGhpc1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChmb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9wYXJzZUlucHV0RGF0ZSA9IGZ1bmN0aW9uIF9wYXJzZUlucHV0RGF0ZShpbnB1dERhdGUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIW1vbWVudC5pc01vbWVudChpbnB1dERhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KGlucHV0RGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnB1dERhdGUgPSB0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlKGlucHV0RGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvL2lucHV0RGF0ZS5sb2NhbGUodGhpcy5vcHRpb25zLmxvY2FsZSk7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXREYXRlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fa2V5ZG93biA9IGZ1bmN0aW9uIF9rZXlkb3duKGUpIHtcbiAgICAgICAgICAgIHZhciBoYW5kbGVyID0gbnVsbCxcbiAgICAgICAgICAgICAgICBpbmRleCA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBpbmRleDIgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAga2V5QmluZEtleXMgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IHZvaWQgMDtcbiAgICAgICAgICAgIHZhciBwcmVzc2VkS2V5cyA9IFtdLFxuICAgICAgICAgICAgICAgIHByZXNzZWRNb2RpZmllcnMgPSB7fSxcbiAgICAgICAgICAgICAgICBjdXJyZW50S2V5ID0gZS53aGljaCxcbiAgICAgICAgICAgICAgICBwcmVzc2VkID0gJ3AnO1xuXG4gICAgICAgICAgICBrZXlTdGF0ZVtjdXJyZW50S2V5XSA9IHByZXNzZWQ7XG5cbiAgICAgICAgICAgIGZvciAoaW5kZXggaW4ga2V5U3RhdGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoa2V5U3RhdGUuaGFzT3duUHJvcGVydHkoaW5kZXgpICYmIGtleVN0YXRlW2luZGV4XSA9PT0gcHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5cy5wdXNoKGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcnNlSW50KGluZGV4LCAxMCkgIT09IGN1cnJlbnRLZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXNzZWRNb2RpZmllcnNbaW5kZXhdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChpbmRleCBpbiB0aGlzLl9vcHRpb25zLmtleUJpbmRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMua2V5QmluZHMuaGFzT3duUHJvcGVydHkoaW5kZXgpICYmIHR5cGVvZiB0aGlzLl9vcHRpb25zLmtleUJpbmRzW2luZGV4XSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBrZXlCaW5kS2V5cyA9IGluZGV4LnNwbGl0KCcgJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXlCaW5kS2V5cy5sZW5ndGggPT09IHByZXNzZWRLZXlzLmxlbmd0aCAmJiBLZXlNYXBbY3VycmVudEtleV0gPT09IGtleUJpbmRLZXlzW2tleUJpbmRLZXlzLmxlbmd0aCAtIDFdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaW5kZXgyID0ga2V5QmluZEtleXMubGVuZ3RoIC0gMjsgaW5kZXgyID49IDA7IGluZGV4Mi0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEoS2V5TWFwW2tleUJpbmRLZXlzW2luZGV4Ml1dIGluIHByZXNzZWRNb2RpZmllcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbE1vZGlmaWVyc1ByZXNzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsbE1vZGlmaWVyc1ByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVyID0gdGhpcy5fb3B0aW9ucy5rZXlCaW5kc1tpbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZXIuY2FsbCh0aGlzKSkge1xuICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTTWV0aG9kQ2FuQmVTdGF0aWMsU3BlbGxDaGVja2luZ0luc3BlY3Rpb25cblxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fa2V5dXAgPSBmdW5jdGlvbiBfa2V5dXAoZSkge1xuICAgICAgICAgICAga2V5U3RhdGVbZS53aGljaF0gPSAncic7XG4gICAgICAgICAgICBpZiAoa2V5UHJlc3NIYW5kbGVkW2Uud2hpY2hdKSB7XG4gICAgICAgICAgICAgICAga2V5UHJlc3NIYW5kbGVkW2Uud2hpY2hdID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbmRleEdpdmVuRGF0ZXMgPSBmdW5jdGlvbiBfaW5kZXhHaXZlbkRhdGVzKGdpdmVuRGF0ZXNBcnJheSkge1xuICAgICAgICAgICAgLy8gU3RvcmUgZ2l2ZW4gZW5hYmxlZERhdGVzIGFuZCBkaXNhYmxlZERhdGVzIGFzIGtleXMuXG4gICAgICAgICAgICAvLyBUaGlzIHdheSB3ZSBjYW4gY2hlY2sgdGhlaXIgZXhpc3RlbmNlIGluIE8oMSkgdGltZSBpbnN0ZWFkIG9mIGxvb3BpbmcgdGhyb3VnaCB3aG9sZSBhcnJheS5cbiAgICAgICAgICAgIC8vIChmb3IgZXhhbXBsZTogb3B0aW9ucy5lbmFibGVkRGF0ZXNbJzIwMTQtMDItMjcnXSA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIHZhciBnaXZlbkRhdGVzSW5kZXhlZCA9IHt9LFxuICAgICAgICAgICAgICAgIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgJC5lYWNoKGdpdmVuRGF0ZXNBcnJheSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBkRGF0ZSA9IHNlbGYuX3BhcnNlSW5wdXREYXRlKHRoaXMpO1xuICAgICAgICAgICAgICAgIGlmIChkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2l2ZW5EYXRlc0luZGV4ZWRbZERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhnaXZlbkRhdGVzSW5kZXhlZCkubGVuZ3RoID8gZ2l2ZW5EYXRlc0luZGV4ZWQgOiBmYWxzZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2luZGV4R2l2ZW5Ib3VycyA9IGZ1bmN0aW9uIF9pbmRleEdpdmVuSG91cnMoZ2l2ZW5Ib3Vyc0FycmF5KSB7XG4gICAgICAgICAgICAvLyBTdG9yZSBnaXZlbiBlbmFibGVkSG91cnMgYW5kIGRpc2FibGVkSG91cnMgYXMga2V5cy5cbiAgICAgICAgICAgIC8vIFRoaXMgd2F5IHdlIGNhbiBjaGVjayB0aGVpciBleGlzdGVuY2UgaW4gTygxKSB0aW1lIGluc3RlYWQgb2YgbG9vcGluZyB0aHJvdWdoIHdob2xlIGFycmF5LlxuICAgICAgICAgICAgLy8gKGZvciBleGFtcGxlOiBvcHRpb25zLmVuYWJsZWRIb3Vyc1snMjAxNC0wMi0yNyddID09PSB0cnVlKVxuICAgICAgICAgICAgdmFyIGdpdmVuSG91cnNJbmRleGVkID0ge307XG4gICAgICAgICAgICAkLmVhY2goZ2l2ZW5Ib3Vyc0FycmF5LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZ2l2ZW5Ib3Vyc0luZGV4ZWRbdGhpc10gPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoZ2l2ZW5Ib3Vyc0luZGV4ZWQpLmxlbmd0aCA/IGdpdmVuSG91cnNJbmRleGVkIDogZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbml0Rm9ybWF0dGluZyA9IGZ1bmN0aW9uIF9pbml0Rm9ybWF0dGluZygpIHtcbiAgICAgICAgICAgIHZhciBmb3JtYXQgPSB0aGlzLl9vcHRpb25zLmZvcm1hdCB8fCAnTCBMVCcsXG4gICAgICAgICAgICAgICAgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgICAgIHRoaXMuYWN0dWFsRm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoLyhcXFtbXlxcW10qXSl8KFxcXFwpPyhMVFN8TFR8TEw/TD9MP3xsezEsNH0pL2csIGZ1bmN0aW9uIChmb3JtYXRJbnB1dCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmLl9kYXRlc1swXS5sb2NhbGVEYXRhKCkubG9uZ0RhdGVGb3JtYXQoZm9ybWF0SW5wdXQpIHx8IGZvcm1hdElucHV0OyAvL3RvZG8gdGFraW5nIHRoZSBmaXJzdCBkYXRlIHNob3VsZCBiZSBva1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMucGFyc2VGb3JtYXRzID0gdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMgPyB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cy5zbGljZSgpIDogW107XG4gICAgICAgICAgICBpZiAodGhpcy5wYXJzZUZvcm1hdHMuaW5kZXhPZihmb3JtYXQpIDwgMCAmJiB0aGlzLnBhcnNlRm9ybWF0cy5pbmRleE9mKHRoaXMuYWN0dWFsRm9ybWF0KSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlRm9ybWF0cy5wdXNoKHRoaXMuYWN0dWFsRm9ybWF0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy51c2UyNEhvdXJzID0gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdhJykgPCAxICYmIHRoaXMuYWN0dWFsRm9ybWF0LnJlcGxhY2UoL1xcWy4qP10vZywgJycpLmluZGV4T2YoJ2gnKSA8IDE7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ3knKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuTWluVmlld01vZGVOdW1iZXIgPSAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnTScpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdkJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLk1pblZpZXdNb2RlTnVtYmVyID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heCh0aGlzLk1pblZpZXdNb2RlTnVtYmVyLCB0aGlzLmN1cnJlbnRWaWV3TW9kZSk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy51bnNldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzWzBdLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2dldExhc3RQaWNrZWREYXRlID0gZnVuY3Rpb24gX2dldExhc3RQaWNrZWREYXRlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzW3RoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKV07XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4ID0gZnVuY3Rpb24gX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgfTtcblxuICAgICAgICAvL3B1YmxpY1xuXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmdldE1vbWVudCA9IGZ1bmN0aW9uIGdldE1vbWVudChkKSB7XG4gICAgICAgICAgICB2YXIgcmV0dXJuTW9tZW50ID0gdm9pZCAwO1xuXG4gICAgICAgICAgICBpZiAoZCA9PT0gdW5kZWZpbmVkIHx8IGQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQgPSBtb21lbnQoKTsgLy9UT0RPIHNob3VsZCB0aGlzIHVzZSBmb3JtYXQ/IGFuZCBsb2NhbGU/XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2hhc1RpbWVab25lKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGVyZSBpcyBhIHN0cmluZyB0byBwYXJzZSBhbmQgYSBkZWZhdWx0IHRpbWUgem9uZVxuICAgICAgICAgICAgICAgIC8vIHBhcnNlIHdpdGggdGhlIHR6IGZ1bmN0aW9uIHdoaWNoIHRha2VzIGEgZGVmYXVsdCB0aW1lIHpvbmUgaWYgaXQgaXMgbm90IGluIHRoZSBmb3JtYXQgc3RyaW5nXG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50LnR6KGQsIHRoaXMucGFyc2VGb3JtYXRzLCB0aGlzLl9vcHRpb25zLmxvY2FsZSwgdGhpcy5fb3B0aW9ucy51c2VTdHJpY3QsIHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQgPSBtb21lbnQoZCwgdGhpcy5wYXJzZUZvcm1hdHMsIHRoaXMuX29wdGlvbnMubG9jYWxlLCB0aGlzLl9vcHRpb25zLnVzZVN0cmljdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50LnR6KHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmV0dXJuTW9tZW50O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS50b2dnbGUgPSBmdW5jdGlvbiB0b2dnbGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWRnZXQgPyB0aGlzLmhpZGUoKSA6IHRoaXMuc2hvdygpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5pZ25vcmVSZWFkb25seSA9IGZ1bmN0aW9uIGlnbm9yZVJlYWRvbmx5KF9pZ25vcmVSZWFkb25seSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5pZ25vcmVSZWFkb25seTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2lnbm9yZVJlYWRvbmx5ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpZ25vcmVSZWFkb25seSAoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuaWdub3JlUmVhZG9ubHkgPSBfaWdub3JlUmVhZG9ubHk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm9wdGlvbnMgPSBmdW5jdGlvbiBvcHRpb25zKG5ld09wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHRydWUsIHt9LCB0aGlzLl9vcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEobmV3T3B0aW9ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb25zKCkgdGhpcy5vcHRpb25zIHBhcmFtZXRlciBzaG91bGQgYmUgYW4gb2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCB0aGlzLl9vcHRpb25zLCBuZXdPcHRpb25zKTtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgICQuZWFjaCh0aGlzLl9vcHRpb25zLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChzZWxmW2tleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmW2tleV0odmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kYXRlID0gZnVuY3Rpb24gZGF0ZShuZXdEYXRlLCBpbmRleCkge1xuICAgICAgICAgICAgaW5kZXggPSBpbmRleCB8fCAwO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy51bnNldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzLmpvaW4odGhpcy5fb3B0aW9ucy5tdWx0aWRhdGVTZXBhcmF0b3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlc1tpbmRleF0uY2xvbmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChuZXdEYXRlICE9PSBudWxsICYmIHR5cGVvZiBuZXdEYXRlICE9PSAnc3RyaW5nJyAmJiAhbW9tZW50LmlzTW9tZW50KG5ld0RhdGUpICYmICEobmV3RGF0ZSBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF0ZSgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiBbbnVsbCwgc3RyaW5nLCBtb21lbnQgb3IgRGF0ZV0nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUobmV3RGF0ZSA9PT0gbnVsbCA/IG51bGwgOiB0aGlzLl9wYXJzZUlucHV0RGF0ZShuZXdEYXRlKSwgaW5kZXgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbiBmb3JtYXQobmV3Rm9ybWF0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmZvcm1hdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdGb3JtYXQgIT09ICdzdHJpbmcnICYmICh0eXBlb2YgbmV3Rm9ybWF0ICE9PSAnYm9vbGVhbicgfHwgbmV3Rm9ybWF0ICE9PSBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdmb3JtYXQoKSBleHBlY3RzIGEgc3RyaW5nIG9yIGJvb2xlYW46ZmFsc2UgcGFyYW1ldGVyICcgKyBuZXdGb3JtYXQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmZvcm1hdCA9IG5ld0Zvcm1hdDtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjdHVhbEZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7IC8vIHJlaW5pdGlhbGl6ZSBmb3JtYXR0aW5nXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnRpbWVab25lID0gZnVuY3Rpb24gdGltZVpvbmUobmV3Wm9uZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy50aW1lWm9uZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdab25lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ25ld1pvbmUoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnRpbWVab25lID0gbmV3Wm9uZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGF5Vmlld0hlYWRlckZvcm1hdCA9IGZ1bmN0aW9uIGRheVZpZXdIZWFkZXJGb3JtYXQobmV3Rm9ybWF0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3Rm9ybWF0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RheVZpZXdIZWFkZXJGb3JtYXQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQgPSBuZXdGb3JtYXQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmV4dHJhRm9ybWF0cyA9IGZ1bmN0aW9uIGV4dHJhRm9ybWF0cyhmb3JtYXRzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGZvcm1hdHMgIT09IGZhbHNlICYmICEoZm9ybWF0cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2V4dHJhRm9ybWF0cygpIGV4cGVjdHMgYW4gYXJyYXkgb3IgZmFsc2UgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzID0gZm9ybWF0cztcbiAgICAgICAgICAgIGlmICh0aGlzLnBhcnNlRm9ybWF0cykge1xuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7IC8vIHJlaW5pdCBmb3JtYXR0aW5nXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRpc2FibGVkRGF0ZXMgPSBmdW5jdGlvbiBkaXNhYmxlZERhdGVzKGRhdGVzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzKSA6IHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFkYXRlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoZGF0ZXMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZERhdGVzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA9IHRoaXMuX2luZGV4R2l2ZW5EYXRlcyhkYXRlcyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmVuYWJsZWREYXRlcyA9IGZ1bmN0aW9uIGVuYWJsZWREYXRlcyhkYXRlcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMpIDogdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghZGF0ZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoZGF0ZXMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmFibGVkRGF0ZXMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSB0aGlzLl9pbmRleEdpdmVuRGF0ZXMoZGF0ZXMpO1xuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGF5c09mV2Vla0Rpc2FibGVkID0gZnVuY3Rpb24gZGF5c09mV2Vla0Rpc2FibGVkKF9kYXlzT2ZXZWVrRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkLnNwbGljZSgwKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGF5c09mV2Vla0Rpc2FibGVkID09PSAnYm9vbGVhbicgJiYgIV9kYXlzT2ZXZWVrRGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfZGF5c09mV2Vla0Rpc2FibGVkIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF5c09mV2Vla0Rpc2FibGVkKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkID0gX2RheXNPZldlZWtEaXNhYmxlZC5yZWR1Y2UoZnVuY3Rpb24gKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSA9IHBhcnNlSW50KGN1cnJlbnRWYWx1ZSwgMTApO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50VmFsdWUgPiA2IHx8IGN1cnJlbnRWYWx1ZSA8IDAgfHwgaXNOYU4oY3VycmVudFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUuaW5kZXhPZihjdXJyZW50VmFsdWUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnB1c2goY3VycmVudFZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XG4gICAgICAgICAgICB9LCBbXSkuc29ydCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX2RhdGVzW2ldLCAnZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpXS5hZGQoMSwgJ2QnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmllcyA9PT0gMzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAnVHJpZWQgMzEgdGltZXMgdG8gZmluZCBhIHZhbGlkIGRhdGUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdHJpZXMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1tpXSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm1heERhdGUgPSBmdW5jdGlvbiBtYXhEYXRlKF9tYXhEYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm1heERhdGUgPyB0aGlzLl9vcHRpb25zLm1heERhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMubWF4RGF0ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWF4RGF0ZSA9PT0gJ2Jvb2xlYW4nICYmIF9tYXhEYXRlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWF4RGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9tYXhEYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlmIChfbWF4RGF0ZSA9PT0gJ25vdycgfHwgX21heERhdGUgPT09ICdtb21lbnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIF9tYXhEYXRlID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwYXJzZWREYXRlID0gdGhpcy5fcGFyc2VJbnB1dERhdGUoX21heERhdGUpO1xuXG4gICAgICAgICAgICBpZiAoIXBhcnNlZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWF4RGF0ZSgpIENvdWxkIG5vdCBwYXJzZSBkYXRlIHBhcmFtZXRlcjogJyArIF9tYXhEYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgcGFyc2VkRGF0ZS5pc0JlZm9yZSh0aGlzLl9vcHRpb25zLm1pbkRhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWF4RGF0ZSgpIGRhdGUgcGFyYW1ldGVyIGlzIGJlZm9yZSB0aGlzLm9wdGlvbnMubWluRGF0ZTogJyArIHBhcnNlZERhdGUuZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1heERhdGUgPSBwYXJzZWREYXRlO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQgJiYgdGhpcy5fZGF0ZXNbaV0uaXNBZnRlcihfbWF4RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5tYXhEYXRlLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fdmlld0RhdGUuaXNBZnRlcihwYXJzZWREYXRlKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gcGFyc2VkRGF0ZS5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX29wdGlvbnMuc3RlcHBpbmcsICdtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubWluRGF0ZSA9IGZ1bmN0aW9uIG1pbkRhdGUoX21pbkRhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubWluRGF0ZSA/IHRoaXMuX29wdGlvbnMubWluRGF0ZS5jbG9uZSgpIDogdGhpcy5fb3B0aW9ucy5taW5EYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9taW5EYXRlID09PSAnYm9vbGVhbicgJiYgX21pbkRhdGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5taW5EYXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21pbkRhdGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9taW5EYXRlID09PSAnbm93JyB8fCBfbWluRGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICAgICAgICAgICAgX21pbkRhdGUgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfbWluRGF0ZSk7XG5cbiAgICAgICAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtaW5EYXRlKCkgQ291bGQgbm90IHBhcnNlIGRhdGUgcGFyYW1ldGVyOiAnICsgX21pbkRhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWF4RGF0ZSAmJiBwYXJzZWREYXRlLmlzQWZ0ZXIodGhpcy5fb3B0aW9ucy5tYXhEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21pbkRhdGUoKSBkYXRlIHBhcmFtZXRlciBpcyBhZnRlciB0aGlzLm9wdGlvbnMubWF4RGF0ZTogJyArIHBhcnNlZERhdGUuZm9ybWF0KHRoaXMuYWN0dWFsRm9ybWF0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPSBwYXJzZWREYXRlO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQgJiYgdGhpcy5fZGF0ZXNbaV0uaXNCZWZvcmUoX21pbkRhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMubWluRGF0ZSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX3ZpZXdEYXRlLmlzQmVmb3JlKHBhcnNlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSBwYXJzZWREYXRlLmNsb25lKCkuYWRkKHRoaXMuX29wdGlvbnMuc3RlcHBpbmcsICdtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGVmYXVsdERhdGUgPSBmdW5jdGlvbiBkZWZhdWx0RGF0ZShfZGVmYXVsdERhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPyB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlLmNsb25lKCkgOiB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFfZGVmYXVsdERhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RlZmF1bHREYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlmIChfZGVmYXVsdERhdGUgPT09ICdub3cnIHx8IF9kZWZhdWx0RGF0ZSA9PT0gJ21vbWVudCcpIHtcbiAgICAgICAgICAgICAgICAgICAgX2RlZmF1bHREYXRlID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfZGVmYXVsdERhdGUgPSB0aGlzLmdldE1vbWVudChfZGVmYXVsdERhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhcnNlZERhdGUgPSB0aGlzLl9wYXJzZUlucHV0RGF0ZShfZGVmYXVsdERhdGUpO1xuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlZmF1bHREYXRlKCkgQ291bGQgbm90IHBhcnNlIGRhdGUgcGFyYW1ldGVyOiAnICsgX2RlZmF1bHREYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNWYWxpZChwYXJzZWREYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlZmF1bHREYXRlKCkgZGF0ZSBwYXNzZWQgaXMgaW52YWxpZCBhY2NvcmRpbmcgdG8gY29tcG9uZW50IHNldHVwIHZhbGlkYXRpb25zJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgPSBwYXJzZWREYXRlO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiB0aGlzLl9vcHRpb25zLmlubGluZSB8fCB0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC52YWwoKS50cmltKCkgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmxvY2FsZSA9IGZ1bmN0aW9uIGxvY2FsZShfbG9jYWxlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmxvY2FsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFtb21lbnQubG9jYWxlRGF0YShfbG9jYWxlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xvY2FsZSgpIGxvY2FsZSAnICsgX2xvY2FsZSArICcgaXMgbm90IGxvYWRlZCBmcm9tIG1vbWVudCBsb2NhbGVzIScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmxvY2FsZSA9IF9sb2NhbGU7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpXS5sb2NhbGUodGhpcy5fb3B0aW9ucy5sb2NhbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuYWN0dWFsRm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0aWFsaXplIGZvcm1hdHRpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5zdGVwcGluZyA9IGZ1bmN0aW9uIHN0ZXBwaW5nKF9zdGVwcGluZykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5zdGVwcGluZztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgX3N0ZXBwaW5nID0gcGFyc2VJbnQoX3N0ZXBwaW5nLCAxMCk7XG4gICAgICAgICAgICBpZiAoaXNOYU4oX3N0ZXBwaW5nKSB8fCBfc3RlcHBpbmcgPCAxKSB7XG4gICAgICAgICAgICAgICAgX3N0ZXBwaW5nID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuc3RlcHBpbmcgPSBfc3RlcHBpbmc7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnVzZUN1cnJlbnQgPSBmdW5jdGlvbiB1c2VDdXJyZW50KF91c2VDdXJyZW50KSB7XG4gICAgICAgICAgICB2YXIgdXNlQ3VycmVudE9wdGlvbnMgPSBbJ3llYXInLCAnbW9udGgnLCAnZGF5JywgJ2hvdXInLCAnbWludXRlJ107XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3VzZUN1cnJlbnQgIT09ICdib29sZWFuJyAmJiB0eXBlb2YgX3VzZUN1cnJlbnQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlQ3VycmVudCgpIGV4cGVjdHMgYSBib29sZWFuIG9yIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3VzZUN1cnJlbnQgPT09ICdzdHJpbmcnICYmIHVzZUN1cnJlbnRPcHRpb25zLmluZGV4T2YoX3VzZUN1cnJlbnQudG9Mb3dlckNhc2UoKSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlQ3VycmVudCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyIG9mICcgKyB1c2VDdXJyZW50T3B0aW9ucy5qb2luKCcsICcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCA9IF91c2VDdXJyZW50O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5jb2xsYXBzZSA9IGZ1bmN0aW9uIGNvbGxhcHNlKF9jb2xsYXBzZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5jb2xsYXBzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfY29sbGFwc2UgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2NvbGxhcHNlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5jb2xsYXBzZSA9PT0gX2NvbGxhcHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmNvbGxhcHNlID0gX2NvbGxhcHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmljb25zID0gZnVuY3Rpb24gaWNvbnMoX2ljb25zKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5pY29ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF9pY29ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpY29ucygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkLmV4dGVuZCh0aGlzLl9vcHRpb25zLmljb25zLCBfaWNvbnMpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudG9vbHRpcHMgPSBmdW5jdGlvbiB0b29sdGlwcyhfdG9vbHRpcHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX3Rvb2x0aXBzIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Rvb2x0aXBzKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYW4gT2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmV4dGVuZCh0aGlzLl9vcHRpb25zLnRvb2x0aXBzLCBfdG9vbHRpcHMpO1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnVzZVN0cmljdCA9IGZ1bmN0aW9uIHVzZVN0cmljdChfdXNlU3RyaWN0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnVzZVN0cmljdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfdXNlU3RyaWN0ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1c2VTdHJpY3QoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0ID0gX3VzZVN0cmljdDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuc2lkZUJ5U2lkZSA9IGZ1bmN0aW9uIHNpZGVCeVNpZGUoX3NpZGVCeVNpZGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfc2lkZUJ5U2lkZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc2lkZUJ5U2lkZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5zaWRlQnlTaWRlID0gX3NpZGVCeVNpZGU7XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudmlld01vZGUgPSBmdW5jdGlvbiB2aWV3TW9kZShfdmlld01vZGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudmlld01vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3ZpZXdNb2RlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdNb2RlKCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKERhdGVUaW1lUGlja2VyLlZpZXdNb2Rlcy5pbmRleE9mKF92aWV3TW9kZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmlld01vZGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgKCcgKyBEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuam9pbignLCAnKSArICcpIHZhbHVlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMudmlld01vZGUgPSBfdmlld01vZGU7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRWaWV3TW9kZSA9IE1hdGgubWF4KERhdGVUaW1lUGlja2VyLlZpZXdNb2Rlcy5pbmRleE9mKF92aWV3TW9kZSkgLSAxLCB0aGlzLk1pblZpZXdNb2RlTnVtYmVyKTtcblxuICAgICAgICAgICAgdGhpcy5fc2hvd01vZGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuY2FsZW5kYXJXZWVrcyA9IGZ1bmN0aW9uIGNhbGVuZGFyV2Vla3MoX2NhbGVuZGFyV2Vla3MpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfY2FsZW5kYXJXZWVrcyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignY2FsZW5kYXJXZWVrcygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGEgYm9vbGVhbiB2YWx1ZScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3MgPSBfY2FsZW5kYXJXZWVrcztcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5idXR0b25zID0gZnVuY3Rpb24gYnV0dG9ucyhfYnV0dG9ucykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuYnV0dG9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF9idXR0b25zIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy5idXR0b25zLCBfYnV0dG9ucyk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dUb2RheSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucy5zaG93VG9kYXkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93Q2xlYXIgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMuc2hvd0NsZWFyIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd0Nsb3NlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zLnNob3dDbG9zZSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmtlZXBPcGVuID0gZnVuY3Rpb24ga2VlcE9wZW4oX2tlZXBPcGVuKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmtlZXBPcGVuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9rZWVwT3BlbiAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigna2VlcE9wZW4oKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiA9IF9rZWVwT3BlbjtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZm9jdXNPblNob3cgPSBmdW5jdGlvbiBmb2N1c09uU2hvdyhfZm9jdXNPblNob3cpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZm9jdXNPblNob3c7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2ZvY3VzT25TaG93ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdmb2N1c09uU2hvdygpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmZvY3VzT25TaG93ID0gX2ZvY3VzT25TaG93O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5pbmxpbmUgPSBmdW5jdGlvbiBpbmxpbmUoX2lubGluZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5pbmxpbmU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2lubGluZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaW5saW5lKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuaW5saW5lID0gX2lubGluZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiBjbGVhcigpIHtcbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKG51bGwpOyAvL3RvZG9cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUua2V5QmluZHMgPSBmdW5jdGlvbiBrZXlCaW5kcyhfa2V5QmluZHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMua2V5QmluZHM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMua2V5QmluZHMgPSBfa2V5QmluZHM7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRlYnVnID0gZnVuY3Rpb24gZGVidWcoX2RlYnVnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIF9kZWJ1ZyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVidWcoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kZWJ1ZyA9IF9kZWJ1ZztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuYWxsb3dJbnB1dFRvZ2dsZSA9IGZ1bmN0aW9uIGFsbG93SW5wdXRUb2dnbGUoX2FsbG93SW5wdXRUb2dnbGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuYWxsb3dJbnB1dFRvZ2dsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfYWxsb3dJbnB1dFRvZ2dsZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYWxsb3dJbnB1dFRvZ2dsZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmFsbG93SW5wdXRUb2dnbGUgPSBfYWxsb3dJbnB1dFRvZ2dsZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUua2VlcEludmFsaWQgPSBmdW5jdGlvbiBrZWVwSW52YWxpZChfa2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMua2VlcEludmFsaWQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2tlZXBJbnZhbGlkICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdrZWVwSW52YWxpZCgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCA9IF9rZWVwSW52YWxpZDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGF0ZXBpY2tlcklucHV0ID0gZnVuY3Rpb24gZGF0ZXBpY2tlcklucHV0KF9kYXRlcGlja2VySW5wdXQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGF0ZXBpY2tlcklucHV0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9kYXRlcGlja2VySW5wdXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF0ZXBpY2tlcklucHV0KCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXRlcGlja2VySW5wdXQgPSBfZGF0ZXBpY2tlcklucHV0O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5wYXJzZUlucHV0RGF0ZSA9IGZ1bmN0aW9uIHBhcnNlSW5wdXREYXRlKF9wYXJzZUlucHV0RGF0ZTIpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3BhcnNlSW5wdXREYXRlMiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3BhcnNlSW5wdXREYXRlKCkgc2hvdWxkIGJlIGFzIGZ1bmN0aW9uJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMucGFyc2VJbnB1dERhdGUgPSBfcGFyc2VJbnB1dERhdGUyO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBmdW5jdGlvbiBkaXNhYmxlZFRpbWVJbnRlcnZhbHMoX2Rpc2FibGVkVGltZUludGVydmFscykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPyAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMpIDogdGhpcy5fb3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghX2Rpc2FibGVkVGltZUludGVydmFscykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShfZGlzYWJsZWRUaW1lSW50ZXJ2YWxzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gX2Rpc2FibGVkVGltZUludGVydmFscztcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kaXNhYmxlZEhvdXJzID0gZnVuY3Rpb24gZGlzYWJsZWRIb3Vycyhob3Vycykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaG91cnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKGhvdXJzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGlzYWJsZWRIb3VycygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPSB0aGlzLl9pbmRleEdpdmVuSG91cnMoaG91cnMpO1xuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmllcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICghdGhpcy5faXNWYWxpZCh0aGlzLl9kYXRlc1tpXSwgJ2gnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0uYWRkKDEsICdoJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDI0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgJ1RyaWVkIDI0IHRpbWVzIHRvIGZpbmQgYSB2YWxpZCBkYXRlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbaV0sIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5lbmFibGVkSG91cnMgPSBmdW5jdGlvbiBlbmFibGVkSG91cnMoaG91cnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzKSA6IHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkSG91cnMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKGhvdXJzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZW5hYmxlZEhvdXJzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzID0gdGhpcy5faW5kZXhHaXZlbkhvdXJzKGhvdXJzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX2RhdGVzW2ldLCAnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc1tpXS5hZGQoMSwgJ2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmllcyA9PT0gMjQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAnVHJpZWQgMjQgdGltZXMgdG8gZmluZCBhIHZhbGlkIGRhdGUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdHJpZXMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1tpXSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnZpZXdEYXRlID0gZnVuY3Rpb24gdmlld0RhdGUobmV3RGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdmlld0RhdGUuY2xvbmUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFuZXdEYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSAodGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKSkuY2xvbmUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdEYXRlICE9PSAnc3RyaW5nJyAmJiAhbW9tZW50LmlzTW9tZW50KG5ld0RhdGUpICYmICEobmV3RGF0ZSBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmlld0RhdGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgW3N0cmluZywgbW9tZW50IG9yIERhdGVdJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gdGhpcy5fcGFyc2VJbnB1dERhdGUobmV3RGF0ZSk7XG4gICAgICAgICAgICB0aGlzLl92aWV3VXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmFsbG93TXVsdGlkYXRlID0gZnVuY3Rpb24gYWxsb3dNdWx0aWRhdGUoX2FsbG93TXVsdGlkYXRlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIF9hbGxvd011bHRpZGF0ZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYWxsb3dNdWx0aWRhdGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSA9IF9hbGxvd011bHRpZGF0ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUubXVsdGlkYXRlU2VwYXJhdG9yID0gZnVuY3Rpb24gbXVsdGlkYXRlU2VwYXJhdG9yKF9tdWx0aWRhdGVTZXBhcmF0b3IpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9tdWx0aWRhdGVTZXBhcmF0b3IgIT09ICdzdHJpbmcnIHx8IF9tdWx0aWRhdGVTZXBhcmF0b3IubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ211bHRpZGF0ZVNlcGFyYXRvciBleHBlY3RzIGEgc2luZ2xlIGNoYXJhY3RlciBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yID0gX211bHRpZGF0ZVNlcGFyYXRvcjtcbiAgICAgICAgfTtcblxuICAgICAgICBfY3JlYXRlQ2xhc3MoRGF0ZVRpbWVQaWNrZXIsIG51bGwsIFt7XG4gICAgICAgICAgICBrZXk6ICdOQU1FJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOQU1FO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdEQVRBX0tFWScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gREFUQV9LRVk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9XHJcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0VWRU5UX0tFWScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRVZFTlRfS0VZO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdEQVRBX0FQSV9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERBVEFfQVBJX0tFWTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnRGF0ZVBpY2tlck1vZGVzJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEYXRlUGlja2VyTW9kZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ1ZpZXdNb2RlcycsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gVmlld01vZGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdFdmVudCcsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRXZlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ1NlbGVjdG9yJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBTZWxlY3RvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnRGVmYXVsdCcsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIERlZmF1bHQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnQ2xhc3NOYW1lJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBDbGFzc05hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1dKTtcblxuICAgICAgICByZXR1cm4gRGF0ZVRpbWVQaWNrZXI7XG4gICAgfSgpO1xuXG4gICAgcmV0dXJuIERhdGVUaW1lUGlja2VyO1xufShqUXVlcnksIG1vbWVudCk7XG4iLCIvKkBwcmVzZXJ2ZVxyXG4gKiBUZW1wdXMgRG9taW51cyBCb290c3RyYXA0IHY1LjEuMiAoaHR0cHM6Ly90ZW1wdXNkb21pbnVzLmdpdGh1Yi5pby9ib290c3RyYXAtNC8pXHJcbiAqIENvcHlyaWdodCAyMDE2LTIwMTggSm9uYXRoYW4gUGV0ZXJzb25cclxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdGVtcHVzZG9taW51cy9ib290c3RyYXAtMy9ibG9iL21hc3Rlci9MSUNFTlNFKVxyXG4gKi9cclxuXHJcbmlmICh0eXBlb2YgalF1ZXJ5ID09PSAndW5kZWZpbmVkJykge1xyXG4gIHRocm93IG5ldyBFcnJvcignVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgcmVxdWlyZXMgalF1ZXJ5LiBqUXVlcnkgbXVzdCBiZSBpbmNsdWRlZCBiZWZvcmUgVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgSmF2YVNjcmlwdC4nKTtcclxufVxyXG5cclxuK2Z1bmN0aW9uICgkKSB7XHJcbiAgdmFyIHZlcnNpb24gPSAkLmZuLmpxdWVyeS5zcGxpdCgnICcpWzBdLnNwbGl0KCcuJyk7XHJcbiAgaWYgKCh2ZXJzaW9uWzBdIDwgMiAmJiB2ZXJzaW9uWzFdIDwgOSkgfHwgKHZlcnNpb25bMF0gPT09IDEgJiYgdmVyc2lvblsxXSA9PT0gOSAmJiB2ZXJzaW9uWzJdIDwgMSkgfHwgKHZlcnNpb25bMF0gPj0gNCkpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcignVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgcmVxdWlyZXMgYXQgbGVhc3QgalF1ZXJ5IHYzLjAuMCBidXQgbGVzcyB0aGFuIHY0LjAuMCcpO1xyXG4gIH1cclxufShqUXVlcnkpO1xyXG5cclxuXHJcbmlmICh0eXBlb2YgbW9tZW50ID09PSAndW5kZWZpbmVkJykge1xyXG4gIHRocm93IG5ldyBFcnJvcignVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgcmVxdWlyZXMgbW9tZW50LmpzLiBNb21lbnQuanMgbXVzdCBiZSBpbmNsdWRlZCBiZWZvcmUgVGVtcHVzIERvbWludXMgQm9vdHN0cmFwNFxcJ3MgSmF2YVNjcmlwdC4nKTtcclxufVxyXG5cclxudmFyIHZlcnNpb24gPSBtb21lbnQudmVyc2lvbi5zcGxpdCgnLicpXHJcbmlmICgodmVyc2lvblswXSA8PSAyICYmIHZlcnNpb25bMV0gPCAxNykgfHwgKHZlcnNpb25bMF0gPj0gMykpIHtcclxuICB0aHJvdyBuZXcgRXJyb3IoJ1RlbXB1cyBEb21pbnVzIEJvb3RzdHJhcDRcXCdzIHJlcXVpcmVzIGF0IGxlYXN0IG1vbWVudC5qcyB2Mi4xNy4wIGJ1dCBsZXNzIHRoYW4gdjMuMC4wJyk7XHJcbn1cclxuXHJcbitmdW5jdGlvbiAoKSB7XHJcblxyXG52YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gdHlwZW9mIG9iajsgfSA6IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7IH07XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBJbmNvbnNpc3RlbnROYW1pbmdcbnZhciBEYXRlVGltZVBpY2tlciA9IGZ1bmN0aW9uICgkLCBtb21lbnQpIHtcbiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBJbmNvbnNpc3RlbnROYW1pbmdcbiAgICB2YXIgTkFNRSA9ICdkYXRldGltZXBpY2tlcicsXG4gICAgICAgIERBVEFfS0VZID0gJycgKyBOQU1FLFxuICAgICAgICBFVkVOVF9LRVkgPSAnLicgKyBEQVRBX0tFWSxcbiAgICAgICAgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaScsXG4gICAgICAgIFNlbGVjdG9yID0ge1xuICAgICAgICBEQVRBX1RPR0dMRTogJ1tkYXRhLXRvZ2dsZT1cIicgKyBEQVRBX0tFWSArICdcIl0nXG4gICAgfSxcbiAgICAgICAgQ2xhc3NOYW1lID0ge1xuICAgICAgICBJTlBVVDogTkFNRSArICctaW5wdXQnXG4gICAgfSxcbiAgICAgICAgRXZlbnQgPSB7XG4gICAgICAgIENIQU5HRTogJ2NoYW5nZScgKyBFVkVOVF9LRVksXG4gICAgICAgIEJMVVI6ICdibHVyJyArIEVWRU5UX0tFWSxcbiAgICAgICAgS0VZVVA6ICdrZXl1cCcgKyBFVkVOVF9LRVksXG4gICAgICAgIEtFWURPV046ICdrZXlkb3duJyArIEVWRU5UX0tFWSxcbiAgICAgICAgRk9DVVM6ICdmb2N1cycgKyBFVkVOVF9LRVksXG4gICAgICAgIENMSUNLX0RBVEFfQVBJOiAnY2xpY2snICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZLFxuICAgICAgICAvL2VtaXR0ZWRcbiAgICAgICAgVVBEQVRFOiAndXBkYXRlJyArIEVWRU5UX0tFWSxcbiAgICAgICAgRVJST1I6ICdlcnJvcicgKyBFVkVOVF9LRVksXG4gICAgICAgIEhJREU6ICdoaWRlJyArIEVWRU5UX0tFWSxcbiAgICAgICAgU0hPVzogJ3Nob3cnICsgRVZFTlRfS0VZXG4gICAgfSxcbiAgICAgICAgRGF0ZVBpY2tlck1vZGVzID0gW3tcbiAgICAgICAgQ0xBU1NfTkFNRTogJ2RheXMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICdNJyxcbiAgICAgICAgTkFWX1NURVA6IDFcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICdtb250aHMnLFxuICAgICAgICBOQVZfRlVOQ1RJT046ICd5JyxcbiAgICAgICAgTkFWX1NURVA6IDFcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICd5ZWFycycsXG4gICAgICAgIE5BVl9GVU5DVElPTjogJ3knLFxuICAgICAgICBOQVZfU1RFUDogMTBcbiAgICB9LCB7XG4gICAgICAgIENMQVNTX05BTUU6ICdkZWNhZGVzJyxcbiAgICAgICAgTkFWX0ZVTkNUSU9OOiAneScsXG4gICAgICAgIE5BVl9TVEVQOiAxMDBcbiAgICB9XSxcbiAgICAgICAgS2V5TWFwID0ge1xuICAgICAgICAndXAnOiAzOCxcbiAgICAgICAgMzg6ICd1cCcsXG4gICAgICAgICdkb3duJzogNDAsXG4gICAgICAgIDQwOiAnZG93bicsXG4gICAgICAgICdsZWZ0JzogMzcsXG4gICAgICAgIDM3OiAnbGVmdCcsXG4gICAgICAgICdyaWdodCc6IDM5LFxuICAgICAgICAzOTogJ3JpZ2h0JyxcbiAgICAgICAgJ3RhYic6IDksXG4gICAgICAgIDk6ICd0YWInLFxuICAgICAgICAnZXNjYXBlJzogMjcsXG4gICAgICAgIDI3OiAnZXNjYXBlJyxcbiAgICAgICAgJ2VudGVyJzogMTMsXG4gICAgICAgIDEzOiAnZW50ZXInLFxuICAgICAgICAncGFnZVVwJzogMzMsXG4gICAgICAgIDMzOiAncGFnZVVwJyxcbiAgICAgICAgJ3BhZ2VEb3duJzogMzQsXG4gICAgICAgIDM0OiAncGFnZURvd24nLFxuICAgICAgICAnc2hpZnQnOiAxNixcbiAgICAgICAgMTY6ICdzaGlmdCcsXG4gICAgICAgICdjb250cm9sJzogMTcsXG4gICAgICAgIDE3OiAnY29udHJvbCcsXG4gICAgICAgICdzcGFjZSc6IDMyLFxuICAgICAgICAzMjogJ3NwYWNlJyxcbiAgICAgICAgJ3QnOiA4NCxcbiAgICAgICAgODQ6ICd0JyxcbiAgICAgICAgJ2RlbGV0ZSc6IDQ2LFxuICAgICAgICA0NjogJ2RlbGV0ZSdcbiAgICB9LFxuICAgICAgICBWaWV3TW9kZXMgPSBbJ3RpbWVzJywgJ2RheXMnLCAnbW9udGhzJywgJ3llYXJzJywgJ2RlY2FkZXMnXSxcbiAgICAgICAga2V5U3RhdGUgPSB7fSxcbiAgICAgICAga2V5UHJlc3NIYW5kbGVkID0ge307XG5cbiAgICB2YXIgRGVmYXVsdCA9IHtcbiAgICAgICAgdGltZVpvbmU6ICcnLFxuICAgICAgICBmb3JtYXQ6IGZhbHNlLFxuICAgICAgICBkYXlWaWV3SGVhZGVyRm9ybWF0OiAnTU1NTSBZWVlZJyxcbiAgICAgICAgZXh0cmFGb3JtYXRzOiBmYWxzZSxcbiAgICAgICAgc3RlcHBpbmc6IDEsXG4gICAgICAgIG1pbkRhdGU6IGZhbHNlLFxuICAgICAgICBtYXhEYXRlOiBmYWxzZSxcbiAgICAgICAgdXNlQ3VycmVudDogdHJ1ZSxcbiAgICAgICAgY29sbGFwc2U6IHRydWUsXG4gICAgICAgIGxvY2FsZTogbW9tZW50LmxvY2FsZSgpLFxuICAgICAgICBkZWZhdWx0RGF0ZTogZmFsc2UsXG4gICAgICAgIGRpc2FibGVkRGF0ZXM6IGZhbHNlLFxuICAgICAgICBlbmFibGVkRGF0ZXM6IGZhbHNlLFxuICAgICAgICBpY29uczoge1xuICAgICAgICAgICAgdGltZTogJ2ZhIGZhLWNsb2NrLW8nLFxuICAgICAgICAgICAgZGF0ZTogJ2ZhIGZhLWNhbGVuZGFyJyxcbiAgICAgICAgICAgIHVwOiAnZmEgZmEtYXJyb3ctdXAnLFxuICAgICAgICAgICAgZG93bjogJ2ZhIGZhLWFycm93LWRvd24nLFxuICAgICAgICAgICAgcHJldmlvdXM6ICdmYSBmYS1jaGV2cm9uLWxlZnQnLFxuICAgICAgICAgICAgbmV4dDogJ2ZhIGZhLWNoZXZyb24tcmlnaHQnLFxuICAgICAgICAgICAgdG9kYXk6ICdmYSBmYS1jYWxlbmRhci1jaGVjay1vJyxcbiAgICAgICAgICAgIGNsZWFyOiAnZmEgZmEtZGVsZXRlJyxcbiAgICAgICAgICAgIGNsb3NlOiAnZmEgZmEtdGltZXMnXG4gICAgICAgIH0sXG4gICAgICAgIHRvb2x0aXBzOiB7XG4gICAgICAgICAgICB0b2RheTogJ0dvIHRvIHRvZGF5JyxcbiAgICAgICAgICAgIGNsZWFyOiAnQ2xlYXIgc2VsZWN0aW9uJyxcbiAgICAgICAgICAgIGNsb3NlOiAnQ2xvc2UgdGhlIHBpY2tlcicsXG4gICAgICAgICAgICBzZWxlY3RNb250aDogJ1NlbGVjdCBNb250aCcsXG4gICAgICAgICAgICBwcmV2TW9udGg6ICdQcmV2aW91cyBNb250aCcsXG4gICAgICAgICAgICBuZXh0TW9udGg6ICdOZXh0IE1vbnRoJyxcbiAgICAgICAgICAgIHNlbGVjdFllYXI6ICdTZWxlY3QgWWVhcicsXG4gICAgICAgICAgICBwcmV2WWVhcjogJ1ByZXZpb3VzIFllYXInLFxuICAgICAgICAgICAgbmV4dFllYXI6ICdOZXh0IFllYXInLFxuICAgICAgICAgICAgc2VsZWN0RGVjYWRlOiAnU2VsZWN0IERlY2FkZScsXG4gICAgICAgICAgICBwcmV2RGVjYWRlOiAnUHJldmlvdXMgRGVjYWRlJyxcbiAgICAgICAgICAgIG5leHREZWNhZGU6ICdOZXh0IERlY2FkZScsXG4gICAgICAgICAgICBwcmV2Q2VudHVyeTogJ1ByZXZpb3VzIENlbnR1cnknLFxuICAgICAgICAgICAgbmV4dENlbnR1cnk6ICdOZXh0IENlbnR1cnknLFxuICAgICAgICAgICAgcGlja0hvdXI6ICdQaWNrIEhvdXInLFxuICAgICAgICAgICAgaW5jcmVtZW50SG91cjogJ0luY3JlbWVudCBIb3VyJyxcbiAgICAgICAgICAgIGRlY3JlbWVudEhvdXI6ICdEZWNyZW1lbnQgSG91cicsXG4gICAgICAgICAgICBwaWNrTWludXRlOiAnUGljayBNaW51dGUnLFxuICAgICAgICAgICAgaW5jcmVtZW50TWludXRlOiAnSW5jcmVtZW50IE1pbnV0ZScsXG4gICAgICAgICAgICBkZWNyZW1lbnRNaW51dGU6ICdEZWNyZW1lbnQgTWludXRlJyxcbiAgICAgICAgICAgIHBpY2tTZWNvbmQ6ICdQaWNrIFNlY29uZCcsXG4gICAgICAgICAgICBpbmNyZW1lbnRTZWNvbmQ6ICdJbmNyZW1lbnQgU2Vjb25kJyxcbiAgICAgICAgICAgIGRlY3JlbWVudFNlY29uZDogJ0RlY3JlbWVudCBTZWNvbmQnLFxuICAgICAgICAgICAgdG9nZ2xlUGVyaW9kOiAnVG9nZ2xlIFBlcmlvZCcsXG4gICAgICAgICAgICBzZWxlY3RUaW1lOiAnU2VsZWN0IFRpbWUnLFxuICAgICAgICAgICAgc2VsZWN0RGF0ZTogJ1NlbGVjdCBEYXRlJ1xuICAgICAgICB9LFxuICAgICAgICB1c2VTdHJpY3Q6IGZhbHNlLFxuICAgICAgICBzaWRlQnlTaWRlOiBmYWxzZSxcbiAgICAgICAgZGF5c09mV2Vla0Rpc2FibGVkOiBmYWxzZSxcbiAgICAgICAgY2FsZW5kYXJXZWVrczogZmFsc2UsXG4gICAgICAgIHZpZXdNb2RlOiAnZGF5cycsXG4gICAgICAgIHRvb2xiYXJQbGFjZW1lbnQ6ICdkZWZhdWx0JyxcbiAgICAgICAgYnV0dG9uczoge1xuICAgICAgICAgICAgc2hvd1RvZGF5OiBmYWxzZSxcbiAgICAgICAgICAgIHNob3dDbGVhcjogZmFsc2UsXG4gICAgICAgICAgICBzaG93Q2xvc2U6IGZhbHNlXG4gICAgICAgIH0sXG4gICAgICAgIHdpZGdldFBvc2l0aW9uaW5nOiB7XG4gICAgICAgICAgICBob3Jpem9udGFsOiAnYXV0bycsXG4gICAgICAgICAgICB2ZXJ0aWNhbDogJ2F1dG8nXG4gICAgICAgIH0sXG4gICAgICAgIHdpZGdldFBhcmVudDogbnVsbCxcbiAgICAgICAgaWdub3JlUmVhZG9ubHk6IGZhbHNlLFxuICAgICAgICBrZWVwT3BlbjogZmFsc2UsXG4gICAgICAgIGZvY3VzT25TaG93OiB0cnVlLFxuICAgICAgICBpbmxpbmU6IGZhbHNlLFxuICAgICAgICBrZWVwSW52YWxpZDogZmFsc2UsXG4gICAgICAgIGtleUJpbmRzOiB7XG4gICAgICAgICAgICB1cDogZnVuY3Rpb24gdXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDcsICdkJykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKHRoaXMuc3RlcHBpbmcoKSwgJ20nKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRvd246IGZ1bmN0aW9uIGRvd24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoNywgJ2QnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLnN0ZXBwaW5nKCksICdtJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAnY29udHJvbCB1cCc6IGZ1bmN0aW9uIGNvbnRyb2xVcCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ3knKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ2gnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdjb250cm9sIGRvd24nOiBmdW5jdGlvbiBjb250cm9sRG93bigpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLl9kYXRlc1swXSB8fCB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDEsICd5JykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ2gnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxlZnQ6IGZ1bmN0aW9uIGxlZnQoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdkJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByaWdodDogZnVuY3Rpb24gcmlnaHQoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnZCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFnZVVwOiBmdW5jdGlvbiBwYWdlVXAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdNJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYWdlRG93bjogZnVuY3Rpb24gcGFnZURvd24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5fZGF0ZXNbMF0gfHwgdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnTScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uIGVudGVyKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlc2NhcGU6IGZ1bmN0aW9uIGVzY2FwZSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2NvbnRyb2wgc3BhY2UnOiBmdW5jdGlvbiBjb250cm9sU3BhY2UoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5idG5bZGF0YS1hY3Rpb249XCJ0b2dnbGVQZXJpb2RcIl0nKS5jbGljaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0OiBmdW5jdGlvbiB0KCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmRhdGUodGhpcy5nZXRNb21lbnQoKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgJ2RlbGV0ZSc6IGZ1bmN0aW9uIF9kZWxldGUoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGVidWc6IGZhbHNlLFxuICAgICAgICBhbGxvd0lucHV0VG9nZ2xlOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWRUaW1lSW50ZXJ2YWxzOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZWRIb3VyczogZmFsc2UsXG4gICAgICAgIGVuYWJsZWRIb3VyczogZmFsc2UsXG4gICAgICAgIHZpZXdEYXRlOiBmYWxzZSxcbiAgICAgICAgYWxsb3dNdWx0aWRhdGU6IGZhbHNlLFxuICAgICAgICBtdWx0aWRhdGVTZXBhcmF0b3I6ICcsJ1xuICAgIH07XG5cbiAgICAvLyBSZVNoYXJwZXIgcmVzdG9yZSBJbmNvbnNpc3RlbnROYW1pbmdcblxuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgRGVjbGFyYXRpb25IaWRlc1xuICAgIC8vIFJlU2hhcnBlciBkaXNhYmxlIG9uY2UgSW5jb25zaXN0ZW50TmFtaW5nXG5cbiAgICB2YXIgRGF0ZVRpbWVQaWNrZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8qKiBAbmFtZXNwYWNlIGVEYXRhLmRhdGVPcHRpb25zICovXG4gICAgICAgIC8qKiBAbmFtZXNwYWNlIG1vbWVudC50eiAqL1xuXG4gICAgICAgIGZ1bmN0aW9uIERhdGVUaW1lUGlja2VyKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBEYXRlVGltZVBpY2tlcik7XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMgPSB0aGlzLl9nZXRPcHRpb25zKG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgICAgICB0aGlzLl9kYXRlcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWQgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudW5zZXQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnVzZTI0SG91cnMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5hY3R1YWxGb3JtYXQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wYXJzZUZvcm1hdHMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDA7XG5cbiAgICAgICAgICAgIHRoaXMuX2ludCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAqL1xuXG5cbiAgICAgICAgLy9wcml2YXRlXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbnQgPSBmdW5jdGlvbiBfaW50KCkge1xuICAgICAgICAgICAgdmFyIHRhcmdldElucHV0ID0gdGhpcy5fZWxlbWVudC5kYXRhKCd0YXJnZXQtaW5wdXQnKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9lbGVtZW50LmlzKCdpbnB1dCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dCA9IHRoaXMuX2VsZW1lbnQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldElucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0SW5wdXQgPT09ICduZWFyZXN0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0ID0gdGhpcy5fZWxlbWVudC5maW5kKCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQgPSAkKHRhcmdldElucHV0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX2RhdGVzID0gW107XG4gICAgICAgICAgICB0aGlzLl9kYXRlc1swXSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCkuY2xvbmUoKTtcblxuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgdGhpcy5fb3B0aW9ucywgdGhpcy5fZGF0YVRvT3B0aW9ucygpKTtcblxuICAgICAgICAgICAgdGhpcy5vcHRpb25zKHRoaXMuX29wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQuaXMoJ2lucHV0JykgJiYgdGhpcy5pbnB1dC52YWwoKS50cmltKCkubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fcGFyc2VJbnB1dERhdGUodGhpcy5pbnB1dC52YWwoKS50cmltKCkpLCAwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiB0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnB1dC5hdHRyKCdwbGFjZWhvbGRlcicpID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fdXBkYXRlID0gZnVuY3Rpb24gX3VwZGF0ZSgpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fZmlsbFRpbWUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX3NldFZhbHVlID0gZnVuY3Rpb24gX3NldFZhbHVlKHRhcmdldE1vbWVudCwgaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBvbGREYXRlID0gdGhpcy51bnNldCA/IG51bGwgOiB0aGlzLl9kYXRlc1tpbmRleF07XG4gICAgICAgICAgICB2YXIgb3V0cFZhbHVlID0gJyc7XG4gICAgICAgICAgICAvLyBjYXNlIG9mIGNhbGxpbmcgc2V0VmFsdWUobnVsbCBvciBmYWxzZSlcbiAgICAgICAgICAgIGlmICghdGFyZ2V0TW9tZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlIHx8IHRoaXMuX2RhdGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVuc2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNGb3JtYXR0ZWQgPSBbXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSB0aGlzLl9lbGVtZW50LmRhdGEoJ2RhdGUnKSArICcsJztcbiAgICAgICAgICAgICAgICAgICAgb3V0cFZhbHVlID0gb3V0cFZhbHVlLnJlcGxhY2Uob2xkRGF0ZS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpICsgJywnLCAnJykucmVwbGFjZSgnLCwnLCAnJykucmVwbGFjZSgvLFxccyokLywgJycpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5kYXRhKCdkYXRlJywgb3V0cFZhbHVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRhcmdldE1vbWVudCA9IHRhcmdldE1vbWVudC5jbG9uZSgpLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0TW9tZW50LnR6KHRoaXMuX29wdGlvbnMudGltZVpvbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5zdGVwcGluZyAhPT0gMSkge1xuICAgICAgICAgICAgICAgIHRhcmdldE1vbWVudC5taW51dGVzKE1hdGgucm91bmQodGFyZ2V0TW9tZW50Lm1pbnV0ZXMoKSAvIHRoaXMuX29wdGlvbnMuc3RlcHBpbmcpICogdGhpcy5fb3B0aW9ucy5zdGVwcGluZykuc2Vjb25kcygwKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQodGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2luZGV4XSA9IHRhcmdldE1vbWVudDtcbiAgICAgICAgICAgICAgICB0aGlzLl9kYXRlc0Zvcm1hdHRlZFtpbmRleF0gPSB0YXJnZXRNb21lbnQuZm9ybWF0KCdZWVlZLU1NLUREJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUgPSB0YXJnZXRNb21lbnQuY2xvbmUoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSAmJiB0aGlzLl9kYXRlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSArPSAnJyArIHRoaXMuX2RhdGVzW2ldLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkgKyB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBvdXRwVmFsdWUgPSBvdXRwVmFsdWUucmVwbGFjZSgvLFxccyokLywgJycpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dHBWYWx1ZSA9IHRoaXMuX2RhdGVzW2luZGV4XS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKG91dHBWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudHJpZ2dlcignaW5wdXQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5kYXRhKCdkYXRlJywgb3V0cFZhbHVlKTtcblxuICAgICAgICAgICAgICAgIHRoaXMudW5zZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkNIQU5HRSxcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogdGhpcy5fZGF0ZXNbaW5kZXhdLmNsb25lKCksXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQudmFsKCcnICsgKHRoaXMudW5zZXQgPyAnJyA6IHRoaXMuX2RhdGVzW2luZGV4XS5mb3JtYXQodGhpcy5hY3R1YWxGb3JtYXQpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnRyaWdnZXIoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlVGltZVBpY2tlci5FdmVudC5DSEFOR0UsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVUaW1lUGlja2VyLkV2ZW50LkVSUk9SLFxuICAgICAgICAgICAgICAgICAgICBkYXRlOiB0YXJnZXRNb21lbnQsXG4gICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2NoYW5nZSA9IGZ1bmN0aW9uIF9jaGFuZ2UoZSkge1xuICAgICAgICAgICAgdmFyIHZhbCA9ICQoZS50YXJnZXQpLnZhbCgpLnRyaW0oKSxcbiAgICAgICAgICAgICAgICBwYXJzZWREYXRlID0gdmFsID8gdGhpcy5fcGFyc2VJbnB1dERhdGUodmFsKSA6IG51bGw7XG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShwYXJzZWREYXRlKTtcbiAgICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNNZXRob2RDYW5CZVN0YXRpY1xuXG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9nZXRPcHRpb25zID0gZnVuY3Rpb24gX2dldE9wdGlvbnMob3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIHt9LCBEZWZhdWx0LCBvcHRpb25zKTtcbiAgICAgICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzVGltZVpvbmUgPSBmdW5jdGlvbiBfaGFzVGltZVpvbmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9tZW50LnR6ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuX29wdGlvbnMudGltZVpvbmUgIT09IG51bGwgJiYgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSAhPT0gJyc7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0VuYWJsZWQgPSBmdW5jdGlvbiBfaXNFbmFibGVkKGdyYW51bGFyaXR5KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGdyYW51bGFyaXR5ICE9PSAnc3RyaW5nJyB8fCBncmFudWxhcml0eS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaXNFbmFibGVkIGV4cGVjdHMgYSBzaW5nbGUgY2hhcmFjdGVyIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN3aXRjaCAoZ3JhbnVsYXJpdHkpIHtcbiAgICAgICAgICAgICAgICBjYXNlICd5JzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ1knKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC5pbmRleE9mKCdNJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdkJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ0gnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdoJykgIT09IC0xO1xuICAgICAgICAgICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3R1YWxGb3JtYXQuaW5kZXhPZignbScpICE9PSAtMTtcbiAgICAgICAgICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0dWFsRm9ybWF0LmluZGV4T2YoJ3MnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgY2FzZSAnYSc6XG4gICAgICAgICAgICAgICAgY2FzZSAnQSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2EnKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzVGltZSA9IGZ1bmN0aW9uIF9oYXNUaW1lKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzRW5hYmxlZCgnaCcpIHx8IHRoaXMuX2lzRW5hYmxlZCgnbScpIHx8IHRoaXMuX2lzRW5hYmxlZCgncycpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faGFzRGF0ZSA9IGZ1bmN0aW9uIF9oYXNEYXRlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzRW5hYmxlZCgneScpIHx8IHRoaXMuX2lzRW5hYmxlZCgnTScpIHx8IHRoaXMuX2lzRW5hYmxlZCgnZCcpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZGF0YVRvT3B0aW9ucyA9IGZ1bmN0aW9uIF9kYXRhVG9PcHRpb25zKCkge1xuICAgICAgICAgICAgdmFyIGVEYXRhID0gdGhpcy5fZWxlbWVudC5kYXRhKCk7XG4gICAgICAgICAgICB2YXIgZGF0YU9wdGlvbnMgPSB7fTtcblxuICAgICAgICAgICAgaWYgKGVEYXRhLmRhdGVPcHRpb25zICYmIGVEYXRhLmRhdGVPcHRpb25zIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgZGF0YU9wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCBkYXRhT3B0aW9ucywgZURhdGEuZGF0ZU9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucywgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgICAgIHZhciBhdHRyaWJ1dGVOYW1lID0gJ2RhdGUnICsga2V5LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsga2V5LnNsaWNlKDEpOyAvL3RvZG8gZGF0YSBhcGkga2V5XG4gICAgICAgICAgICAgICAgaWYgKGVEYXRhW2F0dHJpYnV0ZU5hbWVdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YU9wdGlvbnNba2V5XSA9IGVEYXRhW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBkYXRhT3B0aW9uc1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGRhdGFPcHRpb25zO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fbm90aWZ5RXZlbnQgPSBmdW5jdGlvbiBfbm90aWZ5RXZlbnQoZSkge1xuICAgICAgICAgICAgaWYgKGUudHlwZSA9PT0gRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFICYmIChlLmRhdGUgJiYgZS5kYXRlLmlzU2FtZShlLm9sZERhdGUpKSB8fCAhZS5kYXRlICYmICFlLm9sZERhdGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50LnRyaWdnZXIoZSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl92aWV3VXBkYXRlID0gZnVuY3Rpb24gX3ZpZXdVcGRhdGUoZSkge1xuICAgICAgICAgICAgaWYgKGUgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgIGUgPSAnWVlZWSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuVVBEQVRFLFxuICAgICAgICAgICAgICAgIGNoYW5nZTogZSxcbiAgICAgICAgICAgICAgICB2aWV3RGF0ZTogdGhpcy5fdmlld0RhdGUuY2xvbmUoKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9zaG93TW9kZSA9IGZ1bmN0aW9uIF9zaG93TW9kZShkaXIpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGlyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heCh0aGlzLk1pblZpZXdNb2RlTnVtYmVyLCBNYXRoLm1pbigzLCB0aGlzLmN1cnJlbnRWaWV3TW9kZSArIGRpcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmRhdGVwaWNrZXIgPiBkaXYnKS5oaWRlKCkuZmlsdGVyKCcuZGF0ZXBpY2tlci0nICsgRGF0ZVBpY2tlck1vZGVzW3RoaXMuY3VycmVudFZpZXdNb2RlXS5DTEFTU19OQU1FKS5zaG93KCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRGlzYWJsZWREYXRlcyA9IGZ1bmN0aW9uIF9pc0luRGlzYWJsZWREYXRlcyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlc1t0ZXN0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRW5hYmxlZERhdGVzID0gZnVuY3Rpb24gX2lzSW5FbmFibGVkRGF0ZXModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWREYXRlc1t0ZXN0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRGlzYWJsZWRIb3VycyA9IGZ1bmN0aW9uIF9pc0luRGlzYWJsZWRIb3Vycyh0ZXN0RGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3Vyc1t0ZXN0RGF0ZS5mb3JtYXQoJ0gnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc0luRW5hYmxlZEhvdXJzID0gZnVuY3Rpb24gX2lzSW5FbmFibGVkSG91cnModGVzdERhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3Vyc1t0ZXN0RGF0ZS5mb3JtYXQoJ0gnKV0gPT09IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pc1ZhbGlkID0gZnVuY3Rpb24gX2lzVmFsaWQodGFyZ2V0TW9tZW50LCBncmFudWxhcml0eSkge1xuICAgICAgICAgICAgaWYgKCF0YXJnZXRNb21lbnQuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmIHRoaXMuX2lzSW5EaXNhYmxlZERhdGVzKHRhcmdldE1vbWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiAhdGhpcy5faXNJbkVuYWJsZWREYXRlcyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiB0YXJnZXRNb21lbnQuaXNCZWZvcmUodGhpcy5fb3B0aW9ucy5taW5EYXRlLCBncmFudWxhcml0eSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5tYXhEYXRlICYmIHRhcmdldE1vbWVudC5pc0FmdGVyKHRoaXMuX29wdGlvbnMubWF4RGF0ZSwgZ3JhbnVsYXJpdHkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQuaW5kZXhPZih0YXJnZXRNb21lbnQuZGF5KCkpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSAmJiB0aGlzLl9pc0luRGlzYWJsZWRIb3Vycyh0YXJnZXRNb21lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykgJiYgIXRoaXMuX2lzSW5FbmFibGVkSG91cnModGFyZ2V0TW9tZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgJC5lYWNoKHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0YXJnZXRNb21lbnQuaXNCZXR3ZWVuKHRoaXNbMF0sIHRoaXNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoZm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fcGFyc2VJbnB1dERhdGUgPSBmdW5jdGlvbiBfcGFyc2VJbnB1dERhdGUoaW5wdXREYXRlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFtb21lbnQuaXNNb21lbnQoaW5wdXREYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dERhdGUgPSB0aGlzLmdldE1vbWVudChpbnB1dERhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaW5wdXREYXRlID0gdGhpcy5fb3B0aW9ucy5wYXJzZUlucHV0RGF0ZShpbnB1dERhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy9pbnB1dERhdGUubG9jYWxlKHRoaXMub3B0aW9ucy5sb2NhbGUpO1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0RGF0ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2tleWRvd24gPSBmdW5jdGlvbiBfa2V5ZG93bihlKSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlciA9IG51bGwsXG4gICAgICAgICAgICAgICAgaW5kZXggPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgaW5kZXgyID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGtleUJpbmRLZXlzID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGFsbE1vZGlmaWVyc1ByZXNzZWQgPSB2b2lkIDA7XG4gICAgICAgICAgICB2YXIgcHJlc3NlZEtleXMgPSBbXSxcbiAgICAgICAgICAgICAgICBwcmVzc2VkTW9kaWZpZXJzID0ge30sXG4gICAgICAgICAgICAgICAgY3VycmVudEtleSA9IGUud2hpY2gsXG4gICAgICAgICAgICAgICAgcHJlc3NlZCA9ICdwJztcblxuICAgICAgICAgICAga2V5U3RhdGVbY3VycmVudEtleV0gPSBwcmVzc2VkO1xuXG4gICAgICAgICAgICBmb3IgKGluZGV4IGluIGtleVN0YXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleVN0YXRlLmhhc093blByb3BlcnR5KGluZGV4KSAmJiBrZXlTdGF0ZVtpbmRleF0gPT09IHByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJlc3NlZEtleXMucHVzaChpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJzZUludChpbmRleCwgMTApICE9PSBjdXJyZW50S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmVzc2VkTW9kaWZpZXJzW2luZGV4XSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoaW5kZXggaW4gdGhpcy5fb3B0aW9ucy5rZXlCaW5kcykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmtleUJpbmRzLmhhc093blByb3BlcnR5KGluZGV4KSAmJiB0eXBlb2YgdGhpcy5fb3B0aW9ucy5rZXlCaW5kc1tpbmRleF0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5QmluZEtleXMgPSBpbmRleC5zcGxpdCgnICcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5QmluZEtleXMubGVuZ3RoID09PSBwcmVzc2VkS2V5cy5sZW5ndGggJiYgS2V5TWFwW2N1cnJlbnRLZXldID09PSBrZXlCaW5kS2V5c1trZXlCaW5kS2V5cy5sZW5ndGggLSAxXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGluZGV4MiA9IGtleUJpbmRLZXlzLmxlbmd0aCAtIDI7IGluZGV4MiA+PSAwOyBpbmRleDItLSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghKEtleU1hcFtrZXlCaW5kS2V5c1tpbmRleDJdXSBpbiBwcmVzc2VkTW9kaWZpZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbGxNb2RpZmllcnNQcmVzc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlciA9IHRoaXMuX29wdGlvbnMua2V5QmluZHNbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaGFuZGxlcikge1xuICAgICAgICAgICAgICAgIGlmIChoYW5kbGVyLmNhbGwodGhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvL25vaW5zcGVjdGlvbiBKU01ldGhvZENhbkJlU3RhdGljLFNwZWxsQ2hlY2tpbmdJbnNwZWN0aW9uXG5cblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuX2tleXVwID0gZnVuY3Rpb24gX2tleXVwKGUpIHtcbiAgICAgICAgICAgIGtleVN0YXRlW2Uud2hpY2hdID0gJ3InO1xuICAgICAgICAgICAgaWYgKGtleVByZXNzSGFuZGxlZFtlLndoaWNoXSkge1xuICAgICAgICAgICAgICAgIGtleVByZXNzSGFuZGxlZFtlLndoaWNoXSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW5kZXhHaXZlbkRhdGVzID0gZnVuY3Rpb24gX2luZGV4R2l2ZW5EYXRlcyhnaXZlbkRhdGVzQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIFN0b3JlIGdpdmVuIGVuYWJsZWREYXRlcyBhbmQgZGlzYWJsZWREYXRlcyBhcyBrZXlzLlxuICAgICAgICAgICAgLy8gVGhpcyB3YXkgd2UgY2FuIGNoZWNrIHRoZWlyIGV4aXN0ZW5jZSBpbiBPKDEpIHRpbWUgaW5zdGVhZCBvZiBsb29waW5nIHRocm91Z2ggd2hvbGUgYXJyYXkuXG4gICAgICAgICAgICAvLyAoZm9yIGV4YW1wbGU6IG9wdGlvbnMuZW5hYmxlZERhdGVzWycyMDE0LTAyLTI3J10gPT09IHRydWUpXG4gICAgICAgICAgICB2YXIgZ2l2ZW5EYXRlc0luZGV4ZWQgPSB7fSxcbiAgICAgICAgICAgICAgICBzZWxmID0gdGhpcztcbiAgICAgICAgICAgICQuZWFjaChnaXZlbkRhdGVzQXJyYXksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZERhdGUgPSBzZWxmLl9wYXJzZUlucHV0RGF0ZSh0aGlzKTtcbiAgICAgICAgICAgICAgICBpZiAoZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGdpdmVuRGF0ZXNJbmRleGVkW2REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoZ2l2ZW5EYXRlc0luZGV4ZWQpLmxlbmd0aCA/IGdpdmVuRGF0ZXNJbmRleGVkIDogZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9pbmRleEdpdmVuSG91cnMgPSBmdW5jdGlvbiBfaW5kZXhHaXZlbkhvdXJzKGdpdmVuSG91cnNBcnJheSkge1xuICAgICAgICAgICAgLy8gU3RvcmUgZ2l2ZW4gZW5hYmxlZEhvdXJzIGFuZCBkaXNhYmxlZEhvdXJzIGFzIGtleXMuXG4gICAgICAgICAgICAvLyBUaGlzIHdheSB3ZSBjYW4gY2hlY2sgdGhlaXIgZXhpc3RlbmNlIGluIE8oMSkgdGltZSBpbnN0ZWFkIG9mIGxvb3BpbmcgdGhyb3VnaCB3aG9sZSBhcnJheS5cbiAgICAgICAgICAgIC8vIChmb3IgZXhhbXBsZTogb3B0aW9ucy5lbmFibGVkSG91cnNbJzIwMTQtMDItMjcnXSA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIHZhciBnaXZlbkhvdXJzSW5kZXhlZCA9IHt9O1xuICAgICAgICAgICAgJC5lYWNoKGdpdmVuSG91cnNBcnJheSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGdpdmVuSG91cnNJbmRleGVkW3RoaXNdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGdpdmVuSG91cnNJbmRleGVkKS5sZW5ndGggPyBnaXZlbkhvdXJzSW5kZXhlZCA6IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5faW5pdEZvcm1hdHRpbmcgPSBmdW5jdGlvbiBfaW5pdEZvcm1hdHRpbmcoKSB7XG4gICAgICAgICAgICB2YXIgZm9ybWF0ID0gdGhpcy5fb3B0aW9ucy5mb3JtYXQgfHwgJ0wgTFQnLFxuICAgICAgICAgICAgICAgIHNlbGYgPSB0aGlzO1xuXG4gICAgICAgICAgICB0aGlzLmFjdHVhbEZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKC8oXFxbW15cXFtdKl0pfChcXFxcKT8oTFRTfExUfExMP0w/TD98bHsxLDR9KS9nLCBmdW5jdGlvbiAoZm9ybWF0SW5wdXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5fZGF0ZXNbMF0ubG9jYWxlRGF0YSgpLmxvbmdEYXRlRm9ybWF0KGZvcm1hdElucHV0KSB8fCBmb3JtYXRJbnB1dDsgLy90b2RvIHRha2luZyB0aGUgZmlyc3QgZGF0ZSBzaG91bGQgYmUgb2tcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0aGlzLnBhcnNlRm9ybWF0cyA9IHRoaXMuX29wdGlvbnMuZXh0cmFGb3JtYXRzID8gdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHMuc2xpY2UoKSA6IFtdO1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VGb3JtYXRzLmluZGV4T2YoZm9ybWF0KSA8IDAgJiYgdGhpcy5wYXJzZUZvcm1hdHMuaW5kZXhPZih0aGlzLmFjdHVhbEZvcm1hdCkgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJzZUZvcm1hdHMucHVzaCh0aGlzLmFjdHVhbEZvcm1hdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudXNlMjRIb3VycyA9IHRoaXMuYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignYScpIDwgMSAmJiB0aGlzLmFjdHVhbEZvcm1hdC5yZXBsYWNlKC9cXFsuKj9dL2csICcnKS5pbmRleE9mKCdoJykgPCAxO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCd5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLk1pblZpZXdNb2RlTnVtYmVyID0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ00nKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuTWluVmlld01vZGVOdW1iZXIgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnZCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5NaW5WaWV3TW9kZU51bWJlciA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgodGhpcy5NaW5WaWV3TW9kZU51bWJlciwgdGhpcy5jdXJyZW50Vmlld01vZGUpO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9kYXRlc1swXSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLl9nZXRMYXN0UGlja2VkRGF0ZSA9IGZ1bmN0aW9uIF9nZXRMYXN0UGlja2VkRGF0ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlc1t0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCldO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCA9IGZ1bmN0aW9uIF9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVzLmxlbmd0aCAtIDE7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9wdWJsaWNcblxuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5nZXRNb21lbnQgPSBmdW5jdGlvbiBnZXRNb21lbnQoZCkge1xuICAgICAgICAgICAgdmFyIHJldHVybk1vbWVudCA9IHZvaWQgMDtcblxuICAgICAgICAgICAgaWYgKGQgPT09IHVuZGVmaW5lZCB8fCBkID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50KCk7IC8vVE9ETyBzaG91bGQgdGhpcyB1c2UgZm9ybWF0PyBhbmQgbG9jYWxlP1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9oYXNUaW1lWm9uZSgpKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgaXMgYSBzdHJpbmcgdG8gcGFyc2UgYW5kIGEgZGVmYXVsdCB0aW1lIHpvbmVcbiAgICAgICAgICAgICAgICAvLyBwYXJzZSB3aXRoIHRoZSB0eiBmdW5jdGlvbiB3aGljaCB0YWtlcyBhIGRlZmF1bHQgdGltZSB6b25lIGlmIGl0IGlzIG5vdCBpbiB0aGUgZm9ybWF0IHN0cmluZ1xuICAgICAgICAgICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudC50eihkLCB0aGlzLnBhcnNlRm9ybWF0cywgdGhpcy5fb3B0aW9ucy5sb2NhbGUsIHRoaXMuX29wdGlvbnMudXNlU3RyaWN0LCB0aGlzLl9vcHRpb25zLnRpbWVab25lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50KGQsIHRoaXMucGFyc2VGb3JtYXRzLCB0aGlzLl9vcHRpb25zLmxvY2FsZSwgdGhpcy5fb3B0aW9ucy51c2VTdHJpY3QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5faGFzVGltZVpvbmUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybk1vbWVudC50eih0aGlzLl9vcHRpb25zLnRpbWVab25lKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJldHVybk1vbWVudDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUudG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lkZ2V0ID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3coKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuaWdub3JlUmVhZG9ubHkgPSBmdW5jdGlvbiBpZ25vcmVSZWFkb25seShfaWdub3JlUmVhZG9ubHkpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuaWdub3JlUmVhZG9ubHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIF9pZ25vcmVSZWFkb25seSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaWdub3JlUmVhZG9ubHkgKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmlnbm9yZVJlYWRvbmx5ID0gX2lnbm9yZVJlYWRvbmx5O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5vcHRpb25zID0gZnVuY3Rpb24gb3B0aW9ucyhuZXdPcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh0cnVlLCB7fSwgdGhpcy5fb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKG5ld09wdGlvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb3B0aW9ucygpIHRoaXMub3B0aW9ucyBwYXJhbWV0ZXIgc2hvdWxkIGJlIGFuIG9iamVjdCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgdGhpcy5fb3B0aW9ucywgbmV3T3B0aW9ucyk7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICAkLmVhY2godGhpcy5fb3B0aW9ucywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZltrZXldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZltrZXldKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGF0ZSA9IGZ1bmN0aW9uIGRhdGUobmV3RGF0ZSwgaW5kZXgpIHtcbiAgICAgICAgICAgIGluZGV4ID0gaW5kZXggfHwgMDtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmFsbG93TXVsdGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRlcy5qb2luKHRoaXMuX29wdGlvbnMubXVsdGlkYXRlU2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZXNbaW5kZXhdLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobmV3RGF0ZSAhPT0gbnVsbCAmJiB0eXBlb2YgbmV3RGF0ZSAhPT0gJ3N0cmluZycgJiYgIW1vbWVudC5pc01vbWVudChuZXdEYXRlKSAmJiAhKG5ld0RhdGUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgW251bGwsIHN0cmluZywgbW9tZW50IG9yIERhdGVdJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKG5ld0RhdGUgPT09IG51bGwgPyBudWxsIDogdGhpcy5fcGFyc2VJbnB1dERhdGUobmV3RGF0ZSksIGluZGV4KTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZm9ybWF0ID0gZnVuY3Rpb24gZm9ybWF0KG5ld0Zvcm1hdCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5mb3JtYXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3Rm9ybWF0ICE9PSAnc3RyaW5nJyAmJiAodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ2Jvb2xlYW4nIHx8IG5ld0Zvcm1hdCAhPT0gZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZm9ybWF0KCkgZXhwZWN0cyBhIHN0cmluZyBvciBib29sZWFuOmZhbHNlIHBhcmFtZXRlciAnICsgbmV3Rm9ybWF0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5mb3JtYXQgPSBuZXdGb3JtYXQ7XG4gICAgICAgICAgICBpZiAodGhpcy5hY3R1YWxGb3JtYXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXRpYWxpemUgZm9ybWF0dGluZ1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS50aW1lWm9uZSA9IGZ1bmN0aW9uIHRpbWVab25lKG5ld1pvbmUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMudGltZVpvbmU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3Wm9uZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCduZXdab25lKCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy50aW1lWm9uZSA9IG5ld1pvbmU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRheVZpZXdIZWFkZXJGb3JtYXQgPSBmdW5jdGlvbiBkYXlWaWV3SGVhZGVyRm9ybWF0KG5ld0Zvcm1hdCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kYXlWaWV3SGVhZGVyRm9ybWF0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXlWaWV3SGVhZGVyRm9ybWF0KCkgZXhwZWN0cyBhIHN0cmluZyBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXlWaWV3SGVhZGVyRm9ybWF0ID0gbmV3Rm9ybWF0O1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5leHRyYUZvcm1hdHMgPSBmdW5jdGlvbiBleHRyYUZvcm1hdHMoZm9ybWF0cykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5leHRyYUZvcm1hdHM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChmb3JtYXRzICE9PSBmYWxzZSAmJiAhKGZvcm1hdHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdleHRyYUZvcm1hdHMoKSBleHBlY3RzIGFuIGFycmF5IG9yIGZhbHNlIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmV4dHJhRm9ybWF0cyA9IGZvcm1hdHM7XG4gICAgICAgICAgICBpZiAodGhpcy5wYXJzZUZvcm1hdHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXQgZm9ybWF0dGluZ1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kaXNhYmxlZERhdGVzID0gZnVuY3Rpb24gZGlzYWJsZWREYXRlcyhkYXRlcykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5kaXNhYmxlZERhdGVzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcykgOiB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghZGF0ZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKGRhdGVzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGlzYWJsZWREYXRlcygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkRGF0ZXMgPSB0aGlzLl9pbmRleEdpdmVuRGF0ZXMoZGF0ZXMpO1xuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5lbmFibGVkRGF0ZXMgPSBmdW5jdGlvbiBlbmFibGVkRGF0ZXMoZGF0ZXMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzKSA6IHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWRhdGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKGRhdGVzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZW5hYmxlZERhdGVzKCkgZXhwZWN0cyBhbiBhcnJheSBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZERhdGVzID0gdGhpcy5faW5kZXhHaXZlbkRhdGVzKGRhdGVzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGlzYWJsZWREYXRlcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRheXNPZldlZWtEaXNhYmxlZCA9IGZ1bmN0aW9uIGRheXNPZldlZWtEaXNhYmxlZChfZGF5c09mV2Vla0Rpc2FibGVkKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZC5zcGxpY2UoMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2RheXNPZldlZWtEaXNhYmxlZCA9PT0gJ2Jvb2xlYW4nICYmICFfZGF5c09mV2Vla0Rpc2FibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoX2RheXNPZldlZWtEaXNhYmxlZCBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RheXNPZldlZWtEaXNhYmxlZCgpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCA9IF9kYXlzT2ZXZWVrRGlzYWJsZWQucmVkdWNlKGZ1bmN0aW9uIChwcmV2aW91c1ZhbHVlLCBjdXJyZW50VmFsdWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBwYXJzZUludChjdXJyZW50VmFsdWUsIDEwKTtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudFZhbHVlID4gNiB8fCBjdXJyZW50VmFsdWUgPCAwIHx8IGlzTmFOKGN1cnJlbnRWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlLmluZGV4T2YoY3VycmVudFZhbHVlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS5wdXNoKGN1cnJlbnRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xuICAgICAgICAgICAgfSwgW10pLnNvcnQoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmllcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICghdGhpcy5faXNWYWxpZCh0aGlzLl9kYXRlc1tpXSwgJ2QnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0uYWRkKDEsICdkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDMxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgJ1RyaWVkIDMxIHRpbWVzIHRvIGZpbmQgYSB2YWxpZCBkYXRlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbaV0sIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5tYXhEYXRlID0gZnVuY3Rpb24gbWF4RGF0ZShfbWF4RGF0ZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5tYXhEYXRlID8gdGhpcy5fb3B0aW9ucy5tYXhEYXRlLmNsb25lKCkgOiB0aGlzLl9vcHRpb25zLm1heERhdGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX21heERhdGUgPT09ICdib29sZWFuJyAmJiBfbWF4RGF0ZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLm1heERhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWF4RGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoX21heERhdGUgPT09ICdub3cnIHx8IF9tYXhEYXRlID09PSAnbW9tZW50Jykge1xuICAgICAgICAgICAgICAgICAgICBfbWF4RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKF9tYXhEYXRlKTtcblxuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21heERhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBfbWF4RGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5taW5EYXRlICYmIHBhcnNlZERhdGUuaXNCZWZvcmUodGhpcy5fb3B0aW9ucy5taW5EYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21heERhdGUoKSBkYXRlIHBhcmFtZXRlciBpcyBiZWZvcmUgdGhpcy5vcHRpb25zLm1pbkRhdGU6ICcgKyBwYXJzZWREYXRlLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5tYXhEYXRlID0gcGFyc2VkRGF0ZTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkICYmIHRoaXMuX2RhdGVzW2ldLmlzQWZ0ZXIoX21heERhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMubWF4RGF0ZSwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX3ZpZXdEYXRlLmlzQWZ0ZXIocGFyc2VkRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHBhcnNlZERhdGUuY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm1pbkRhdGUgPSBmdW5jdGlvbiBtaW5EYXRlKF9taW5EYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm1pbkRhdGUgPyB0aGlzLl9vcHRpb25zLm1pbkRhdGUuY2xvbmUoKSA6IHRoaXMuX29wdGlvbnMubWluRGF0ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbWluRGF0ZSA9PT0gJ2Jvb2xlYW4nICYmIF9taW5EYXRlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMubWluRGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9taW5EYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGlmIChfbWluRGF0ZSA9PT0gJ25vdycgfHwgX21pbkRhdGUgPT09ICdtb21lbnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIF9taW5EYXRlID0gdGhpcy5nZXRNb21lbnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwYXJzZWREYXRlID0gdGhpcy5fcGFyc2VJbnB1dERhdGUoX21pbkRhdGUpO1xuXG4gICAgICAgICAgICBpZiAoIXBhcnNlZERhdGUuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWluRGF0ZSgpIENvdWxkIG5vdCBwYXJzZSBkYXRlIHBhcmFtZXRlcjogJyArIF9taW5EYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgcGFyc2VkRGF0ZS5pc0FmdGVyKHRoaXMuX29wdGlvbnMubWF4RGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtaW5EYXRlKCkgZGF0ZSBwYXJhbWV0ZXIgaXMgYWZ0ZXIgdGhpcy5vcHRpb25zLm1heERhdGU6ICcgKyBwYXJzZWREYXRlLmZvcm1hdCh0aGlzLmFjdHVhbEZvcm1hdCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5taW5EYXRlID0gcGFyc2VkRGF0ZTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZGF0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkICYmIHRoaXMuX2RhdGVzW2ldLmlzQmVmb3JlKF9taW5EYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLm1pbkRhdGUsIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl92aWV3RGF0ZS5pc0JlZm9yZShwYXJzZWREYXRlKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gcGFyc2VkRGF0ZS5jbG9uZSgpLmFkZCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRlZmF1bHREYXRlID0gZnVuY3Rpb24gZGVmYXVsdERhdGUoX2RlZmF1bHREYXRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlID8gdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZS5jbG9uZSgpIDogdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghX2RlZmF1bHREYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kZWZhdWx0RGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9kZWZhdWx0RGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoX2RlZmF1bHREYXRlID09PSAnbm93JyB8fCBfZGVmYXVsdERhdGUgPT09ICdtb21lbnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIF9kZWZhdWx0RGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX2RlZmF1bHREYXRlID0gdGhpcy5nZXRNb21lbnQoX2RlZmF1bHREYXRlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwYXJzZWREYXRlID0gdGhpcy5fcGFyc2VJbnB1dERhdGUoX2RlZmF1bHREYXRlKTtcbiAgICAgICAgICAgIGlmICghcGFyc2VkRGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWZhdWx0RGF0ZSgpIENvdWxkIG5vdCBwYXJzZSBkYXRlIHBhcmFtZXRlcjogJyArIF9kZWZhdWx0RGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzVmFsaWQocGFyc2VkRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWZhdWx0RGF0ZSgpIGRhdGUgcGFzc2VkIGlzIGludmFsaWQgYWNjb3JkaW5nIHRvIGNvbXBvbmVudCBzZXR1cCB2YWxpZGF0aW9ucycpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRlZmF1bHREYXRlID0gcGFyc2VkRGF0ZTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUgJiYgdGhpcy5fb3B0aW9ucy5pbmxpbmUgfHwgdGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuaW5wdXQudmFsKCkudHJpbSgpID09PSAnJykge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX29wdGlvbnMuZGVmYXVsdERhdGUsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5sb2NhbGUgPSBmdW5jdGlvbiBsb2NhbGUoX2xvY2FsZSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5sb2NhbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghbW9tZW50LmxvY2FsZURhdGEoX2xvY2FsZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsb2NhbGUoKSBsb2NhbGUgJyArIF9sb2NhbGUgKyAnIGlzIG5vdCBsb2FkZWQgZnJvbSBtb21lbnQgbG9jYWxlcyEnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5sb2NhbGUgPSBfbG9jYWxlO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0ubG9jYWxlKHRoaXMuX29wdGlvbnMubG9jYWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlLmxvY2FsZSh0aGlzLl9vcHRpb25zLmxvY2FsZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmFjdHVhbEZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRGb3JtYXR0aW5nKCk7IC8vIHJlaW5pdGlhbGl6ZSBmb3JtYXR0aW5nXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy53aWRnZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuc3RlcHBpbmcgPSBmdW5jdGlvbiBzdGVwcGluZyhfc3RlcHBpbmcpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuc3RlcHBpbmc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIF9zdGVwcGluZyA9IHBhcnNlSW50KF9zdGVwcGluZywgMTApO1xuICAgICAgICAgICAgaWYgKGlzTmFOKF9zdGVwcGluZykgfHwgX3N0ZXBwaW5nIDwgMSkge1xuICAgICAgICAgICAgICAgIF9zdGVwcGluZyA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnN0ZXBwaW5nID0gX3N0ZXBwaW5nO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS51c2VDdXJyZW50ID0gZnVuY3Rpb24gdXNlQ3VycmVudChfdXNlQ3VycmVudCkge1xuICAgICAgICAgICAgdmFyIHVzZUN1cnJlbnRPcHRpb25zID0gWyd5ZWFyJywgJ21vbnRoJywgJ2RheScsICdob3VyJywgJ21pbnV0ZSddO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF91c2VDdXJyZW50ICE9PSAnYm9vbGVhbicgJiYgdHlwZW9mIF91c2VDdXJyZW50ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VzZUN1cnJlbnQoKSBleHBlY3RzIGEgYm9vbGVhbiBvciBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIF91c2VDdXJyZW50ID09PSAnc3RyaW5nJyAmJiB1c2VDdXJyZW50T3B0aW9ucy5pbmRleE9mKF91c2VDdXJyZW50LnRvTG93ZXJDYXNlKCkpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VzZUN1cnJlbnQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlciBvZiAnICsgdXNlQ3VycmVudE9wdGlvbnMuam9pbignLCAnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgPSBfdXNlQ3VycmVudDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuY29sbGFwc2UgPSBmdW5jdGlvbiBjb2xsYXBzZShfY29sbGFwc2UpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuY29sbGFwc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2NvbGxhcHNlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjb2xsYXBzZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgPT09IF9jb2xsYXBzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5jb2xsYXBzZSA9IF9jb2xsYXBzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5pY29ucyA9IGZ1bmN0aW9uIGljb25zKF9pY29ucykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuaWNvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfaWNvbnMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaWNvbnMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy5pY29ucywgX2ljb25zKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnRvb2x0aXBzID0gZnVuY3Rpb24gdG9vbHRpcHMoX3Rvb2x0aXBzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgdGhpcy5fb3B0aW9ucy50b29sdGlwcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKF90b29sdGlwcyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0b29sdGlwcygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJC5leHRlbmQodGhpcy5fb3B0aW9ucy50b29sdGlwcywgX3Rvb2x0aXBzKTtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS51c2VTdHJpY3QgPSBmdW5jdGlvbiB1c2VTdHJpY3QoX3VzZVN0cmljdCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy51c2VTdHJpY3Q7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3VzZVN0cmljdCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlU3RyaWN0KCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnVzZVN0cmljdCA9IF91c2VTdHJpY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnNpZGVCeVNpZGUgPSBmdW5jdGlvbiBzaWRlQnlTaWRlKF9zaWRlQnlTaWRlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnNpZGVCeVNpZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3NpZGVCeVNpZGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3NpZGVCeVNpZGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuc2lkZUJ5U2lkZSA9IF9zaWRlQnlTaWRlO1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLnZpZXdNb2RlID0gZnVuY3Rpb24gdmlld01vZGUoX3ZpZXdNb2RlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnZpZXdNb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF92aWV3TW9kZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aWV3TW9kZSgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuaW5kZXhPZihfdmlld01vZGUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdNb2RlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mICgnICsgRGF0ZVRpbWVQaWNrZXIuVmlld01vZGVzLmpvaW4oJywgJykgKyAnKSB2YWx1ZScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnZpZXdNb2RlID0gX3ZpZXdNb2RlO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Vmlld01vZGUgPSBNYXRoLm1heChEYXRlVGltZVBpY2tlci5WaWV3TW9kZXMuaW5kZXhPZihfdmlld01vZGUpIC0gMSwgdGhpcy5NaW5WaWV3TW9kZU51bWJlcik7XG5cbiAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmNhbGVuZGFyV2Vla3MgPSBmdW5jdGlvbiBjYWxlbmRhcldlZWtzKF9jYWxlbmRhcldlZWtzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmNhbGVuZGFyV2Vla3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2NhbGVuZGFyV2Vla3MgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2NhbGVuZGFyV2Vla3MoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhIGJvb2xlYW4gdmFsdWUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzID0gX2NhbGVuZGFyV2Vla3M7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuYnV0dG9ucyA9IGZ1bmN0aW9uIGJ1dHRvbnMoX2J1dHRvbnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmJ1dHRvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIShfYnV0dG9ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYW4gT2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQuZXh0ZW5kKHRoaXMuX29wdGlvbnMuYnV0dG9ucywgX2J1dHRvbnMpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuYnV0dG9ucy5zaG93VG9kYXkgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1dHRvbnMuc2hvd1RvZGF5IGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd0NsZWFyICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdidXR0b25zLnNob3dDbGVhciBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5idXR0b25zLnNob3dDbG9zZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYnV0dG9ucy5zaG93Q2xvc2UgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5rZWVwT3BlbiA9IGZ1bmN0aW9uIGtlZXBPcGVuKF9rZWVwT3Blbikge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5rZWVwT3BlbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfa2VlcE9wZW4gIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2tlZXBPcGVuKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMua2VlcE9wZW4gPSBfa2VlcE9wZW47XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmZvY3VzT25TaG93ID0gZnVuY3Rpb24gZm9jdXNPblNob3coX2ZvY3VzT25TaG93KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmZvY3VzT25TaG93O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9mb2N1c09uU2hvdyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZm9jdXNPblNob3coKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5mb2N1c09uU2hvdyA9IF9mb2N1c09uU2hvdztcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuaW5saW5lID0gZnVuY3Rpb24gaW5saW5lKF9pbmxpbmUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuaW5saW5lO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9pbmxpbmUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lubGluZSgpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmlubGluZSA9IF9pbmxpbmU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShudWxsKTsgLy90b2RvXG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmtleUJpbmRzID0gZnVuY3Rpb24ga2V5QmluZHMoX2tleUJpbmRzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmtleUJpbmRzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmtleUJpbmRzID0gX2tleUJpbmRzO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5kZWJ1ZyA9IGZ1bmN0aW9uIGRlYnVnKF9kZWJ1Zykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGVidWcgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlYnVnKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGVidWcgPSBfZGVidWc7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmFsbG93SW5wdXRUb2dnbGUgPSBmdW5jdGlvbiBhbGxvd0lucHV0VG9nZ2xlKF9hbGxvd0lucHV0VG9nZ2xlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmFsbG93SW5wdXRUb2dnbGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2FsbG93SW5wdXRUb2dnbGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93SW5wdXRUb2dnbGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5hbGxvd0lucHV0VG9nZ2xlID0gX2FsbG93SW5wdXRUb2dnbGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmtlZXBJbnZhbGlkID0gZnVuY3Rpb24ga2VlcEludmFsaWQoX2tlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9rZWVwSW52YWxpZCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigna2VlcEludmFsaWQoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMua2VlcEludmFsaWQgPSBfa2VlcEludmFsaWQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLmRhdGVwaWNrZXJJbnB1dCA9IGZ1bmN0aW9uIGRhdGVwaWNrZXJJbnB1dChfZGF0ZXBpY2tlcklucHV0KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmRhdGVwaWNrZXJJbnB1dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfZGF0ZXBpY2tlcklucHV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGVwaWNrZXJJbnB1dCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZGF0ZXBpY2tlcklucHV0ID0gX2RhdGVwaWNrZXJJbnB1dDtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUucGFyc2VJbnB1dERhdGUgPSBmdW5jdGlvbiBwYXJzZUlucHV0RGF0ZShfcGFyc2VJbnB1dERhdGUyKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9wYXJzZUlucHV0RGF0ZTIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwYXJzZUlucHV0RGF0ZSgpIHNob3VsZCBiZSBhcyBmdW5jdGlvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLnBhcnNlSW5wdXREYXRlID0gX3BhcnNlSW5wdXREYXRlMjtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gZnVuY3Rpb24gZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKF9kaXNhYmxlZFRpbWVJbnRlcnZhbHMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID8gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSA6IHRoaXMuX29wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIV9kaXNhYmxlZFRpbWVJbnRlcnZhbHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoX2Rpc2FibGVkVGltZUludGVydmFscyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkVGltZUludGVydmFscygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscyA9IF9kaXNhYmxlZFRpbWVJbnRlcnZhbHM7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZGlzYWJsZWRIb3VycyA9IGZ1bmN0aW9uIGRpc2FibGVkSG91cnMoaG91cnMpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuZGlzYWJsZWRIb3VycyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMpIDogdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShob3VycyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Rpc2FibGVkSG91cnMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gdGhpcy5faW5kZXhHaXZlbkhvdXJzKGhvdXJzKTtcbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy51c2VDdXJyZW50ICYmICF0aGlzLl9vcHRpb25zLmtlZXBJbnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9kYXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoIXRoaXMuX2lzVmFsaWQodGhpcy5fZGF0ZXNbaV0sICdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGVzW2ldLmFkZCgxLCAnaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWVzID09PSAyNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAyNCB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKHRoaXMuX2RhdGVzW2ldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBEYXRlVGltZVBpY2tlci5wcm90b3R5cGUuZW5hYmxlZEhvdXJzID0gZnVuY3Rpb24gZW5hYmxlZEhvdXJzKGhvdXJzKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA/ICQuZXh0ZW5kKHt9LCB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycykgOiB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFob3Vycykge1xuICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuZW5hYmxlZEhvdXJzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIShob3VycyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuYWJsZWRIb3VycygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmVuYWJsZWRIb3VycyA9IHRoaXMuX2luZGV4R2l2ZW5Ib3Vycyhob3Vycyk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLmRpc2FibGVkSG91cnMgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgJiYgIXRoaXMuX29wdGlvbnMua2VlcEludmFsaWQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2RhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmllcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICghdGhpcy5faXNWYWxpZCh0aGlzLl9kYXRlc1tpXSwgJ2gnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0ZXNbaV0uYWRkKDEsICdoJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDI0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgJ1RyaWVkIDI0IHRpbWVzIHRvIGZpbmQgYSB2YWxpZCBkYXRlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fZGF0ZXNbaV0sIGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS52aWV3RGF0ZSA9IGZ1bmN0aW9uIHZpZXdEYXRlKG5ld0RhdGUpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3ZpZXdEYXRlLmNsb25lKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghbmV3RGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gKHRoaXMuX2RhdGVzWzBdIHx8IHRoaXMuZ2V0TW9tZW50KCkpLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3RGF0ZSAhPT0gJ3N0cmluZycgJiYgIW1vbWVudC5pc01vbWVudChuZXdEYXRlKSAmJiAhKG5ld0RhdGUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdEYXRlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mIFtzdHJpbmcsIG1vbWVudCBvciBEYXRlXScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl92aWV3RGF0ZSA9IHRoaXMuX3BhcnNlSW5wdXREYXRlKG5ld0RhdGUpO1xuICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIERhdGVUaW1lUGlja2VyLnByb3RvdHlwZS5hbGxvd011bHRpZGF0ZSA9IGZ1bmN0aW9uIGFsbG93TXVsdGlkYXRlKF9hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBfYWxsb3dNdWx0aWRhdGUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FsbG93TXVsdGlkYXRlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUgPSBfYWxsb3dNdWx0aWRhdGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgRGF0ZVRpbWVQaWNrZXIucHJvdG90eXBlLm11bHRpZGF0ZVNlcGFyYXRvciA9IGZ1bmN0aW9uIG11bHRpZGF0ZVNlcGFyYXRvcihfbXVsdGlkYXRlU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfbXVsdGlkYXRlU2VwYXJhdG9yICE9PSAnc3RyaW5nJyB8fCBfbXVsdGlkYXRlU2VwYXJhdG9yLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtdWx0aWRhdGVTZXBhcmF0b3IgZXhwZWN0cyBhIHNpbmdsZSBjaGFyYWN0ZXIgc3RyaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25zLm11bHRpZGF0ZVNlcGFyYXRvciA9IF9tdWx0aWRhdGVTZXBhcmF0b3I7XG4gICAgICAgIH07XG5cbiAgICAgICAgX2NyZWF0ZUNsYXNzKERhdGVUaW1lUGlja2VyLCBudWxsLCBbe1xuICAgICAgICAgICAga2V5OiAnTkFNRScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTkFNRTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERBVEFfS0VZO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdFVkVOVF9LRVknLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVWRU5UX0tFWTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnREFUQV9BUElfS0VZJyxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBEQVRBX0FQSV9LRVk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RhdGVQaWNrZXJNb2RlcycsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGF0ZVBpY2tlck1vZGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdWaWV3TW9kZXMnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFZpZXdNb2RlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnRXZlbnQnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBrZXk6ICdTZWxlY3RvcicsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU2VsZWN0b3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0RlZmF1bHQnLFxuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBEZWZhdWx0ID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ0NsYXNzTmFtZScsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gQ2xhc3NOYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XSk7XG5cbiAgICAgICAgcmV0dXJuIERhdGVUaW1lUGlja2VyO1xuICAgIH0oKTtcblxuICAgIHJldHVybiBEYXRlVGltZVBpY2tlcjtcbn0oalF1ZXJ5LCBtb21lbnQpO1xuXG4vL25vaW5zcGVjdGlvbiBKU1VudXNlZEdsb2JhbFN5bWJvbHNcbi8qIGdsb2JhbCBEYXRlVGltZVBpY2tlciAqL1xudmFyIFRlbXB1c0RvbWludXNCb290c3RyYXA0ID0gZnVuY3Rpb24gKCQpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgLy8gUmVTaGFycGVyIGRpc2FibGUgb25jZSBJbmNvbnNpc3RlbnROYW1pbmdcbiAgICB2YXIgSlFVRVJZX05PX0NPTkZMSUNUID0gJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXSxcbiAgICAgICAgdmVydGljYWxNb2RlcyA9IFsndG9wJywgJ2JvdHRvbScsICdhdXRvJ10sXG4gICAgICAgIGhvcml6b250YWxNb2RlcyA9IFsnbGVmdCcsICdyaWdodCcsICdhdXRvJ10sXG4gICAgICAgIHRvb2xiYXJQbGFjZW1lbnRzID0gWydkZWZhdWx0JywgJ3RvcCcsICdib3R0b20nXSxcbiAgICAgICAgZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCA9IGZ1bmN0aW9uIGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHNlbGVjdG9yID0gJGVsZW1lbnQuZGF0YSgndGFyZ2V0JyksXG4gICAgICAgICAgICAkc2VsZWN0b3IgPSB2b2lkIDA7XG5cbiAgICAgICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgICAgICAgc2VsZWN0b3IgPSAkZWxlbWVudC5hdHRyKCdocmVmJykgfHwgJyc7XG4gICAgICAgICAgICBzZWxlY3RvciA9IC9eI1thLXpdL2kudGVzdChzZWxlY3RvcikgPyBzZWxlY3RvciA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgJHNlbGVjdG9yID0gJChzZWxlY3Rvcik7XG4gICAgICAgIGlmICgkc2VsZWN0b3IubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gJHNlbGVjdG9yO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEkc2VsZWN0b3IuZGF0YShEYXRlVGltZVBpY2tlci5EQVRBX0tFWSkpIHtcbiAgICAgICAgICAgICQuZXh0ZW5kKHt9LCAkc2VsZWN0b3IuZGF0YSgpLCAkKHRoaXMpLmRhdGEoKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gJHNlbGVjdG9yO1xuICAgIH07XG5cbiAgICAvLyBSZVNoYXJwZXIgZGlzYWJsZSBvbmNlIEluY29uc2lzdGVudE5hbWluZ1xuXG4gICAgdmFyIFRlbXB1c0RvbWludXNCb290c3RyYXA0ID0gZnVuY3Rpb24gKF9EYXRlVGltZVBpY2tlcikge1xuICAgICAgICBfaW5oZXJpdHMoVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQsIF9EYXRlVGltZVBpY2tlcik7XG5cbiAgICAgICAgZnVuY3Rpb24gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQoZWxlbWVudCwgb3B0aW9ucykge1xuICAgICAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFRlbXB1c0RvbWludXNCb290c3RyYXA0KTtcblxuICAgICAgICAgICAgdmFyIF90aGlzID0gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4odGhpcywgX0RhdGVUaW1lUGlja2VyLmNhbGwodGhpcywgZWxlbWVudCwgb3B0aW9ucykpO1xuXG4gICAgICAgICAgICBfdGhpcy5faW5pdCgpO1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9pbml0ID0gZnVuY3Rpb24gX2luaXQoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fZWxlbWVudC5oYXNDbGFzcygnaW5wdXQtZ3JvdXAnKSkge1xuICAgICAgICAgICAgICAgIHZhciBkYXRlcGlja2VyQnV0dG9uID0gdGhpcy5fZWxlbWVudC5maW5kKCcuZGF0ZXBpY2tlcmJ1dHRvbicpO1xuICAgICAgICAgICAgICAgIGlmIChkYXRlcGlja2VyQnV0dG9uLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudCA9IHRoaXMuX2VsZW1lbnQuZmluZCgnW2RhdGEtdG9nZ2xlPVwiZGF0ZXRpbWVwaWNrZXJcIl0nKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudCA9IGRhdGVwaWNrZXJCdXR0b247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZ2V0RGF0ZVBpY2tlclRlbXBsYXRlID0gZnVuY3Rpb24gX2dldERhdGVQaWNrZXJUZW1wbGF0ZSgpIHtcbiAgICAgICAgICAgIHZhciBoZWFkVGVtcGxhdGUgPSAkKCc8dGhlYWQ+JykuYXBwZW5kKCQoJzx0cj4nKS5hcHBlbmQoJCgnPHRoPicpLmFkZENsYXNzKCdwcmV2JykuYXR0cignZGF0YS1hY3Rpb24nLCAncHJldmlvdXMnKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy5wcmV2aW91cykpKS5hcHBlbmQoJCgnPHRoPicpLmFkZENsYXNzKCdwaWNrZXItc3dpdGNoJykuYXR0cignZGF0YS1hY3Rpb24nLCAncGlja2VyU3dpdGNoJykuYXR0cignY29sc3BhbicsICcnICsgKHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcyA/ICc2JyA6ICc1JykpKS5hcHBlbmQoJCgnPHRoPicpLmFkZENsYXNzKCduZXh0JykuYXR0cignZGF0YS1hY3Rpb24nLCAnbmV4dCcpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLm5leHQpKSkpLFxuICAgICAgICAgICAgICAgIGNvbnRUZW1wbGF0ZSA9ICQoJzx0Ym9keT4nKS5hcHBlbmQoJCgnPHRyPicpLmFwcGVuZCgkKCc8dGQ+JykuYXR0cignY29sc3BhbicsICcnICsgKHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcyA/ICc4JyA6ICc3JykpKSk7XG5cbiAgICAgICAgICAgIHJldHVybiBbJCgnPGRpdj4nKS5hZGRDbGFzcygnZGF0ZXBpY2tlci1kYXlzJykuYXBwZW5kKCQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUgdGFibGUtc20nKS5hcHBlbmQoaGVhZFRlbXBsYXRlKS5hcHBlbmQoJCgnPHRib2R5PicpKSksICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXItbW9udGhzJykuYXBwZW5kKCQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJykuYXBwZW5kKGhlYWRUZW1wbGF0ZS5jbG9uZSgpKS5hcHBlbmQoY29udFRlbXBsYXRlLmNsb25lKCkpKSwgJCgnPGRpdj4nKS5hZGRDbGFzcygnZGF0ZXBpY2tlci15ZWFycycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpLmFwcGVuZChoZWFkVGVtcGxhdGUuY2xvbmUoKSkuYXBwZW5kKGNvbnRUZW1wbGF0ZS5jbG9uZSgpKSksICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXItZGVjYWRlcycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpLmFwcGVuZChoZWFkVGVtcGxhdGUuY2xvbmUoKSkuYXBwZW5kKGNvbnRUZW1wbGF0ZS5jbG9uZSgpKSldO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZ2V0VGltZVBpY2tlck1haW5UZW1wbGF0ZSA9IGZ1bmN0aW9uIF9nZXRUaW1lUGlja2VyTWFpblRlbXBsYXRlKCkge1xuICAgICAgICAgICAgdmFyIHRvcFJvdyA9ICQoJzx0cj4nKSxcbiAgICAgICAgICAgICAgICBtaWRkbGVSb3cgPSAkKCc8dHI+JyksXG4gICAgICAgICAgICAgICAgYm90dG9tUm93ID0gJCgnPHRyPicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdoJykpIHtcbiAgICAgICAgICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMuaW5jcmVtZW50SG91clxuICAgICAgICAgICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdpbmNyZW1lbnRIb3VycycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLnVwKSkpKTtcbiAgICAgICAgICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItaG91cicpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnZGF0YS10aW1lLWNvbXBvbmVudCc6ICdob3VycycsXG4gICAgICAgICAgICAgICAgICAgICd0aXRsZSc6IHRoaXMuX29wdGlvbnMudG9vbHRpcHMucGlja0hvdXJcbiAgICAgICAgICAgICAgICB9KS5hdHRyKCdkYXRhLWFjdGlvbicsICdzaG93SG91cnMnKSkpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5kZWNyZW1lbnRIb3VyXG4gICAgICAgICAgICAgICAgfSkuYWRkQ2xhc3MoJ2J0bicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ2RlY3JlbWVudEhvdXJzJykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuaWNvbnMuZG93bikpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdtJykpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdG9wUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpKTtcbiAgICAgICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpLmh0bWwoJzonKSk7XG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5pbmNyZW1lbnRNaW51dGVcbiAgICAgICAgICAgICAgICB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnaW5jcmVtZW50TWludXRlcycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLnVwKSkpKTtcbiAgICAgICAgICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItbWludXRlJykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdkYXRhLXRpbWUtY29tcG9uZW50JzogJ21pbnV0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnBpY2tNaW51dGVcbiAgICAgICAgICAgICAgICB9KS5hdHRyKCdkYXRhLWFjdGlvbicsICdzaG93TWludXRlcycpKSk7XG4gICAgICAgICAgICAgICAgYm90dG9tUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLmRlY3JlbWVudE1pbnV0ZVxuICAgICAgICAgICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdkZWNyZW1lbnRNaW51dGVzJykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuaWNvbnMuZG93bikpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdzJykpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdtJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdG9wUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpKTtcbiAgICAgICAgICAgICAgICAgICAgbWlkZGxlUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpLmh0bWwoJzonKSk7XG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5pbmNyZW1lbnRTZWNvbmRcbiAgICAgICAgICAgICAgICB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnaW5jcmVtZW50U2Vjb25kcycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLnVwKSkpKTtcbiAgICAgICAgICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItc2Vjb25kJykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdkYXRhLXRpbWUtY29tcG9uZW50JzogJ3NlY29uZHMnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnBpY2tTZWNvbmRcbiAgICAgICAgICAgICAgICB9KS5hdHRyKCdkYXRhLWFjdGlvbicsICdzaG93U2Vjb25kcycpKSk7XG4gICAgICAgICAgICAgICAgYm90dG9tUm93LmFwcGVuZCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBocmVmOiAnIycsXG4gICAgICAgICAgICAgICAgICAgIHRhYmluZGV4OiAnLTEnLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLmRlY3JlbWVudFNlY29uZFxuICAgICAgICAgICAgICAgIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdkZWNyZW1lbnRTZWNvbmRzJykuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKHRoaXMuX29wdGlvbnMuaWNvbnMuZG93bikpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghdGhpcy51c2UyNEhvdXJzKSB7XG4gICAgICAgICAgICAgICAgdG9wUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpKTtcbiAgICAgICAgICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGJ1dHRvbj4nKS5hZGRDbGFzcygnYnRuIGJ0bi1wcmltYXJ5JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdkYXRhLWFjdGlvbic6ICd0b2dnbGVQZXJpb2QnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy50b2dnbGVQZXJpb2RcbiAgICAgICAgICAgICAgICB9KSkpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyLXBpY2tlcicpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpLmFwcGVuZChbdG9wUm93LCBtaWRkbGVSb3csIGJvdHRvbVJvd10pKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2dldFRpbWVQaWNrZXJUZW1wbGF0ZSA9IGZ1bmN0aW9uIF9nZXRUaW1lUGlja2VyVGVtcGxhdGUoKSB7XG4gICAgICAgICAgICB2YXIgaG91cnNWaWV3ID0gJCgnPGRpdj4nKS5hZGRDbGFzcygndGltZXBpY2tlci1ob3VycycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpKSxcbiAgICAgICAgICAgICAgICBtaW51dGVzVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItbWludXRlcycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpKSxcbiAgICAgICAgICAgICAgICBzZWNvbmRzVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItc2Vjb25kcycpLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpKSxcbiAgICAgICAgICAgICAgICByZXQgPSBbdGhpcy5fZ2V0VGltZVBpY2tlck1haW5UZW1wbGF0ZSgpXTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzRW5hYmxlZCgnaCcpKSB7XG4gICAgICAgICAgICAgICAgcmV0LnB1c2goaG91cnNWaWV3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ20nKSkge1xuICAgICAgICAgICAgICAgIHJldC5wdXNoKG1pbnV0ZXNWaWV3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0VuYWJsZWQoJ3MnKSkge1xuICAgICAgICAgICAgICAgIHJldC5wdXNoKHNlY29uZHNWaWV3KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2dldFRvb2xiYXIgPSBmdW5jdGlvbiBfZ2V0VG9vbGJhcigpIHtcbiAgICAgICAgICAgIHZhciByb3cgPSBbXTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd1RvZGF5KSB7XG4gICAgICAgICAgICAgICAgcm93LnB1c2goJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGEtYWN0aW9uJzogJ3RvZGF5JyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy50b2RheVxuICAgICAgICAgICAgICAgIH0pLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLnRvZGF5KSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5zaWRlQnlTaWRlICYmIHRoaXMuX2hhc0RhdGUoKSAmJiB0aGlzLl9oYXNUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGl0bGUgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgICAgIGljb24gPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMudmlld01vZGUgPT09ICd0aW1lcycpIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnNlbGVjdERhdGU7XG4gICAgICAgICAgICAgICAgICAgIGljb24gPSB0aGlzLl9vcHRpb25zLmljb25zLmRhdGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnNlbGVjdFRpbWU7XG4gICAgICAgICAgICAgICAgICAgIGljb24gPSB0aGlzLl9vcHRpb25zLmljb25zLnRpbWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGhyZWY6ICcjJyxcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg6ICctMScsXG4gICAgICAgICAgICAgICAgICAgICdkYXRhLWFjdGlvbic6ICd0b2dnbGVQaWNrZXInLFxuICAgICAgICAgICAgICAgICAgICAndGl0bGUnOiB0aXRsZVxuICAgICAgICAgICAgICAgIH0pLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyhpY29uKSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd0NsZWFyKSB7XG4gICAgICAgICAgICAgICAgcm93LnB1c2goJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGEtYWN0aW9uJzogJ2NsZWFyJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5jbGVhclxuICAgICAgICAgICAgICAgIH0pLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmNsZWFyKSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLmJ1dHRvbnMuc2hvd0Nsb3NlKSB7XG4gICAgICAgICAgICAgICAgcm93LnB1c2goJCgnPHRkPicpLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogJyMnLFxuICAgICAgICAgICAgICAgICAgICB0YWJpbmRleDogJy0xJyxcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGEtYWN0aW9uJzogJ2Nsb3NlJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RpdGxlJzogdGhpcy5fb3B0aW9ucy50b29sdGlwcy5jbG9zZVxuICAgICAgICAgICAgICAgIH0pLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmNsb3NlKSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByb3cubGVuZ3RoID09PSAwID8gJycgOiAkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpLmFwcGVuZCgkKCc8dGJvZHk+JykuYXBwZW5kKCQoJzx0cj4nKS5hcHBlbmQocm93KSkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZ2V0VGVtcGxhdGUgPSBmdW5jdGlvbiBfZ2V0VGVtcGxhdGUoKSB7XG4gICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCdib290c3RyYXAtZGF0ZXRpbWVwaWNrZXItd2lkZ2V0IGRyb3Bkb3duLW1lbnUnKSxcbiAgICAgICAgICAgICAgICBkYXRlVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXInKS5hcHBlbmQodGhpcy5fZ2V0RGF0ZVBpY2tlclRlbXBsYXRlKCkpLFxuICAgICAgICAgICAgICAgIHRpbWVWaWV3ID0gJCgnPGRpdj4nKS5hZGRDbGFzcygndGltZXBpY2tlcicpLmFwcGVuZCh0aGlzLl9nZXRUaW1lUGlja2VyVGVtcGxhdGUoKSksXG4gICAgICAgICAgICAgICAgY29udGVudCA9ICQoJzx1bD4nKS5hZGRDbGFzcygnbGlzdC11bnN0eWxlZCcpLFxuICAgICAgICAgICAgICAgIHRvb2xiYXIgPSAkKCc8bGk+JykuYWRkQ2xhc3MoJ3BpY2tlci1zd2l0Y2gnICsgKHRoaXMuX29wdGlvbnMuY29sbGFwc2UgPyAnIGFjY29yZGlvbi10b2dnbGUnIDogJycpKS5hcHBlbmQodGhpcy5fZ2V0VG9vbGJhcigpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuaW5saW5lKSB7XG4gICAgICAgICAgICAgICAgdGVtcGxhdGUucmVtb3ZlQ2xhc3MoJ2Ryb3Bkb3duLW1lbnUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFkZENsYXNzKCd1c2V0d2VudHlmb3VyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5faXNFbmFibGVkKCdzJykgJiYgIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFkZENsYXNzKCd3aWRlcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5zaWRlQnlTaWRlICYmIHRoaXMuX2hhc0RhdGUoKSAmJiB0aGlzLl9oYXNUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5hZGRDbGFzcygndGltZXBpY2tlci1zYnMnKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5hcHBlbmQodG9vbGJhcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFwcGVuZCgkKCc8ZGl2PicpLmFkZENsYXNzKCdyb3cnKS5hcHBlbmQoZGF0ZVZpZXcuYWRkQ2xhc3MoJ2NvbC1tZC02JykpLmFwcGVuZCh0aW1lVmlldy5hZGRDbGFzcygnY29sLW1kLTYnKSkpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICdib3R0b20nIHx8IHRoaXMuX29wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9PT0gJ2RlZmF1bHQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFwcGVuZCh0b29sYmFyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKHRvb2xiYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2hhc0RhdGUoKSkge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKCQoJzxsaT4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmNvbGxhcHNlICYmIHRoaXMuX2hhc1RpbWUoKSA/ICdjb2xsYXBzZScgOiAnJykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5jb2xsYXBzZSAmJiB0aGlzLl9oYXNUaW1lKCkgJiYgdGhpcy5fb3B0aW9ucy52aWV3TW9kZSA9PT0gJ3RpbWVzJyA/ICcnIDogJ3Nob3cnKS5hcHBlbmQoZGF0ZVZpZXcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICdkZWZhdWx0Jykge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKHRvb2xiYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX2hhc1RpbWUoKSkge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKCQoJzxsaT4nKS5hZGRDbGFzcyh0aGlzLl9vcHRpb25zLmNvbGxhcHNlICYmIHRoaXMuX2hhc0RhdGUoKSA/ICdjb2xsYXBzZScgOiAnJykuYWRkQ2xhc3ModGhpcy5fb3B0aW9ucy5jb2xsYXBzZSAmJiB0aGlzLl9oYXNEYXRlKCkgJiYgdGhpcy5fb3B0aW9ucy52aWV3TW9kZSA9PT0gJ3RpbWVzJyA/ICdzaG93JyA6ICcnKS5hcHBlbmQodGltZVZpZXcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmQodG9vbGJhcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGVtcGxhdGUuYXBwZW5kKGNvbnRlbnQpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fcGxhY2UgPSBmdW5jdGlvbiBfcGxhY2UoZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSBlICYmIGUuZGF0YSAmJiBlLmRhdGEucGlja2VyIHx8IHRoaXMsXG4gICAgICAgICAgICAgICAgdmVydGljYWwgPSBzZWxmLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsLFxuICAgICAgICAgICAgICAgIGhvcml6b250YWwgPSBzZWxmLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwsXG4gICAgICAgICAgICAgICAgcGFyZW50ID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIHBvc2l0aW9uID0gKHNlbGYuY29tcG9uZW50ICYmIHNlbGYuY29tcG9uZW50Lmxlbmd0aCA/IHNlbGYuY29tcG9uZW50IDogc2VsZi5fZWxlbWVudCkucG9zaXRpb24oKSxcbiAgICAgICAgICAgICAgICBvZmZzZXQgPSAoc2VsZi5jb21wb25lbnQgJiYgc2VsZi5jb21wb25lbnQubGVuZ3RoID8gc2VsZi5jb21wb25lbnQgOiBzZWxmLl9lbGVtZW50KS5vZmZzZXQoKTtcbiAgICAgICAgICAgIGlmIChzZWxmLl9vcHRpb25zLndpZGdldFBhcmVudCkge1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IHNlbGYuX29wdGlvbnMud2lkZ2V0UGFyZW50LmFwcGVuZChzZWxmLndpZGdldCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHNlbGYuX2VsZW1lbnQuaXMoJ2lucHV0JykpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBzZWxmLl9lbGVtZW50LmFmdGVyKHNlbGYud2lkZ2V0KS5wYXJlbnQoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2VsZi5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBzZWxmLl9lbGVtZW50LmFwcGVuZChzZWxmLndpZGdldCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBzZWxmLl9lbGVtZW50O1xuICAgICAgICAgICAgICAgIHNlbGYuX2VsZW1lbnQuY2hpbGRyZW4oKS5maXJzdCgpLmFmdGVyKHNlbGYud2lkZ2V0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVG9wIGFuZCBib3R0b20gbG9naWNcbiAgICAgICAgICAgIGlmICh2ZXJ0aWNhbCA9PT0gJ2F1dG8nKSB7XG4gICAgICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNWYWxpZGF0ZVR5cGVzXG4gICAgICAgICAgICAgICAgaWYgKG9mZnNldC50b3AgKyBzZWxmLndpZGdldC5oZWlnaHQoKSAqIDEuNSA+PSAkKHdpbmRvdykuaGVpZ2h0KCkgKyAkKHdpbmRvdykuc2Nyb2xsVG9wKCkgJiYgc2VsZi53aWRnZXQuaGVpZ2h0KCkgKyBzZWxmLl9lbGVtZW50Lm91dGVySGVpZ2h0KCkgPCBvZmZzZXQudG9wKSB7XG4gICAgICAgICAgICAgICAgICAgIHZlcnRpY2FsID0gJ3RvcCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmVydGljYWwgPSAnYm90dG9tJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExlZnQgYW5kIHJpZ2h0IGxvZ2ljXG4gICAgICAgICAgICBpZiAoaG9yaXpvbnRhbCA9PT0gJ2F1dG8nKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudC53aWR0aCgpIDwgb2Zmc2V0LmxlZnQgKyBzZWxmLndpZGdldC5vdXRlcldpZHRoKCkgLyAyICYmIG9mZnNldC5sZWZ0ICsgc2VsZi53aWRnZXQub3V0ZXJXaWR0aCgpID4gJCh3aW5kb3cpLndpZHRoKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaG9yaXpvbnRhbCA9ICdyaWdodCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaG9yaXpvbnRhbCA9ICdsZWZ0JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh2ZXJ0aWNhbCA9PT0gJ3RvcCcpIHtcbiAgICAgICAgICAgICAgICBzZWxmLndpZGdldC5hZGRDbGFzcygndG9wJykucmVtb3ZlQ2xhc3MoJ2JvdHRvbScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLndpZGdldC5hZGRDbGFzcygnYm90dG9tJykucmVtb3ZlQ2xhc3MoJ3RvcCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaG9yaXpvbnRhbCA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgICAgIHNlbGYud2lkZ2V0LmFkZENsYXNzKCdmbG9hdC1yaWdodCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLndpZGdldC5yZW1vdmVDbGFzcygnZmxvYXQtcmlnaHQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gZmluZCB0aGUgZmlyc3QgcGFyZW50IGVsZW1lbnQgdGhhdCBoYXMgYSByZWxhdGl2ZSBjc3MgcG9zaXRpb25pbmdcbiAgICAgICAgICAgIGlmIChwYXJlbnQuY3NzKCdwb3NpdGlvbicpICE9PSAncmVsYXRpdmUnKSB7XG4gICAgICAgICAgICAgICAgcGFyZW50ID0gcGFyZW50LnBhcmVudHMoKS5maWx0ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJCh0aGlzKS5jc3MoJ3Bvc2l0aW9uJykgPT09ICdyZWxhdGl2ZSc7XG4gICAgICAgICAgICAgICAgfSkuZmlyc3QoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHBhcmVudC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RhdGV0aW1lcGlja2VyIGNvbXBvbmVudCBzaG91bGQgYmUgcGxhY2VkIHdpdGhpbiBhIHJlbGF0aXZlIHBvc2l0aW9uZWQgY29udGFpbmVyJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNlbGYud2lkZ2V0LmNzcyh7XG4gICAgICAgICAgICAgICAgdG9wOiB2ZXJ0aWNhbCA9PT0gJ3RvcCcgPyAnYXV0bycgOiBwb3NpdGlvbi50b3AgKyBzZWxmLl9lbGVtZW50Lm91dGVySGVpZ2h0KCkgKyAncHgnLFxuICAgICAgICAgICAgICAgIGJvdHRvbTogdmVydGljYWwgPT09ICd0b3AnID8gcGFyZW50Lm91dGVySGVpZ2h0KCkgLSAocGFyZW50ID09PSBzZWxmLl9lbGVtZW50ID8gMCA6IHBvc2l0aW9uLnRvcCkgKyAncHgnIDogJ2F1dG8nLFxuICAgICAgICAgICAgICAgIGxlZnQ6IGhvcml6b250YWwgPT09ICdsZWZ0JyA/IChwYXJlbnQgPT09IHNlbGYuX2VsZW1lbnQgPyAwIDogcG9zaXRpb24ubGVmdCkgKyAncHgnIDogJ2F1dG8nLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiBob3Jpem9udGFsID09PSAnbGVmdCcgPyAnYXV0bycgOiBwYXJlbnQub3V0ZXJXaWR0aCgpIC0gc2VsZi5fZWxlbWVudC5vdXRlcldpZHRoKCkgLSAocGFyZW50ID09PSBzZWxmLl9lbGVtZW50ID8gMCA6IHBvc2l0aW9uLmxlZnQpICsgJ3B4J1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsRG93ID0gZnVuY3Rpb24gX2ZpbGxEb3coKSB7XG4gICAgICAgICAgICB2YXIgcm93ID0gJCgnPHRyPicpLFxuICAgICAgICAgICAgICAgIGN1cnJlbnREYXRlID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCd3Jykuc3RhcnRPZignZCcpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5jYWxlbmRhcldlZWtzID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgcm93LmFwcGVuZCgkKCc8dGg+JykuYWRkQ2xhc3MoJ2N3JykudGV4dCgnIycpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgd2hpbGUgKGN1cnJlbnREYXRlLmlzQmVmb3JlKHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuZW5kT2YoJ3cnKSkpIHtcbiAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygnZG93JykudGV4dChjdXJyZW50RGF0ZS5mb3JtYXQoJ2RkJykpKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50RGF0ZS5hZGQoMSwgJ2QnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyLWRheXMgdGhlYWQnKS5hcHBlbmQocm93KTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2ZpbGxNb250aHMgPSBmdW5jdGlvbiBfZmlsbE1vbnRocygpIHtcbiAgICAgICAgICAgIHZhciBzcGFucyA9IFtdLFxuICAgICAgICAgICAgICAgIG1vbnRoc1Nob3J0ID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCd5Jykuc3RhcnRPZignZCcpO1xuICAgICAgICAgICAgd2hpbGUgKG1vbnRoc1Nob3J0LmlzU2FtZSh0aGlzLl92aWV3RGF0ZSwgJ3knKSkge1xuICAgICAgICAgICAgICAgIHNwYW5zLnB1c2goJCgnPHNwYW4+JykuYXR0cignZGF0YS1hY3Rpb24nLCAnc2VsZWN0TW9udGgnKS5hZGRDbGFzcygnbW9udGgnKS50ZXh0KG1vbnRoc1Nob3J0LmZvcm1hdCgnTU1NJykpKTtcbiAgICAgICAgICAgICAgICBtb250aHNTaG9ydC5hZGQoMSwgJ00nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyLW1vbnRocyB0ZCcpLmVtcHR5KCkuYXBwZW5kKHNwYW5zKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX3VwZGF0ZU1vbnRocyA9IGZ1bmN0aW9uIF91cGRhdGVNb250aHMoKSB7XG4gICAgICAgICAgICB2YXIgbW9udGhzVmlldyA9IHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyLW1vbnRocycpLFxuICAgICAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIgPSBtb250aHNWaWV3LmZpbmQoJ3RoJyksXG4gICAgICAgICAgICAgICAgbW9udGhzID0gbW9udGhzVmlldy5maW5kKCd0Ym9keScpLmZpbmQoJ3NwYW4nKSxcbiAgICAgICAgICAgICAgICBzZWxmID0gdGhpcztcblxuICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgwKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnByZXZZZWFyKTtcbiAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMSkuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnNlbGVjdFllYXIpO1xuICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLm5leHRZZWFyKTtcblxuICAgICAgICAgICAgbW9udGhzVmlldy5maW5kKCcuZGlzYWJsZWQnKS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuc3VidHJhY3QoMSwgJ3knKSwgJ3knKSkge1xuICAgICAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMCkuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMSkudGV4dCh0aGlzLl92aWV3RGF0ZS55ZWFyKCkpO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzVmFsaWQodGhpcy5fdmlld0RhdGUuY2xvbmUoKS5hZGQoMSwgJ3knKSwgJ3knKSkge1xuICAgICAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG1vbnRocy5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgICAgICBpZiAodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5pc1NhbWUodGhpcy5fdmlld0RhdGUsICd5JykgJiYgIXRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICBtb250aHMuZXEodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5tb250aCgpKS5hZGRDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG1vbnRocy5lYWNoKGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmICghc2VsZi5faXNWYWxpZChzZWxmLl92aWV3RGF0ZS5jbG9uZSgpLm1vbnRoKGluZGV4KSwgJ00nKSkge1xuICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZ2V0U3RhcnRFbmRZZWFyID0gZnVuY3Rpb24gX2dldFN0YXJ0RW5kWWVhcihmYWN0b3IsIHllYXIpIHtcbiAgICAgICAgICAgIHZhciBzdGVwID0gZmFjdG9yIC8gMTAsXG4gICAgICAgICAgICAgICAgc3RhcnRZZWFyID0gTWF0aC5mbG9vcih5ZWFyIC8gZmFjdG9yKSAqIGZhY3RvcixcbiAgICAgICAgICAgICAgICBlbmRZZWFyID0gc3RhcnRZZWFyICsgc3RlcCAqIDksXG4gICAgICAgICAgICAgICAgZm9jdXNWYWx1ZSA9IE1hdGguZmxvb3IoeWVhciAvIHN0ZXApICogc3RlcDtcbiAgICAgICAgICAgIHJldHVybiBbc3RhcnRZZWFyLCBlbmRZZWFyLCBmb2N1c1ZhbHVlXTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX3VwZGF0ZVllYXJzID0gZnVuY3Rpb24gX3VwZGF0ZVllYXJzKCkge1xuICAgICAgICAgICAgdmFyIHllYXJzVmlldyA9IHRoaXMud2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyLXllYXJzJyksXG4gICAgICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyID0geWVhcnNWaWV3LmZpbmQoJ3RoJyksXG4gICAgICAgICAgICAgICAgeWVhckNhcHMgPSB0aGlzLl9nZXRTdGFydEVuZFllYXIoMTAsIHRoaXMuX3ZpZXdEYXRlLnllYXIoKSksXG4gICAgICAgICAgICAgICAgc3RhcnRZZWFyID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS55ZWFyKHllYXJDYXBzWzBdKSxcbiAgICAgICAgICAgICAgICBlbmRZZWFyID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS55ZWFyKHllYXJDYXBzWzFdKTtcbiAgICAgICAgICAgIHZhciBodG1sID0gJyc7XG5cbiAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgwKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnByZXZEZWNhZGUpO1xuICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDEpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3REZWNhZGUpO1xuICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDIpLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMubmV4dERlY2FkZSk7XG5cbiAgICAgICAgICAgIHllYXJzVmlldy5maW5kKCcuZGlzYWJsZWQnKS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiB0aGlzLl9vcHRpb25zLm1pbkRhdGUuaXNBZnRlcihzdGFydFllYXIsICd5JykpIHtcbiAgICAgICAgICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMCkuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgxKS50ZXh0KHN0YXJ0WWVhci55ZWFyKCkgKyAnLScgKyBlbmRZZWFyLnllYXIoKSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9vcHRpb25zLm1heERhdGUgJiYgdGhpcy5fb3B0aW9ucy5tYXhEYXRlLmlzQmVmb3JlKGVuZFllYXIsICd5JykpIHtcbiAgICAgICAgICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGh0bWwgKz0gJzxzcGFuIGRhdGEtYWN0aW9uPVwic2VsZWN0WWVhclwiIGNsYXNzPVwieWVhciBvbGQnICsgKCF0aGlzLl9pc1ZhbGlkKHN0YXJ0WWVhciwgJ3knKSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiPicgKyAoc3RhcnRZZWFyLnllYXIoKSAtIDEpICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgd2hpbGUgKCFzdGFydFllYXIuaXNBZnRlcihlbmRZZWFyLCAneScpKSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3RZZWFyXCIgY2xhc3M9XCJ5ZWFyJyArIChzdGFydFllYXIuaXNTYW1lKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCksICd5JykgJiYgIXRoaXMudW5zZXQgPyAnIGFjdGl2ZScgOiAnJykgKyAoIXRoaXMuX2lzVmFsaWQoc3RhcnRZZWFyLCAneScpID8gJyBkaXNhYmxlZCcgOiAnJykgKyAnXCI+JyArIHN0YXJ0WWVhci55ZWFyKCkgKyAnPC9zcGFuPic7XG4gICAgICAgICAgICAgICAgc3RhcnRZZWFyLmFkZCgxLCAneScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3RZZWFyXCIgY2xhc3M9XCJ5ZWFyIG9sZCcgKyAoIXRoaXMuX2lzVmFsaWQoc3RhcnRZZWFyLCAneScpID8gJyBkaXNhYmxlZCcgOiAnJykgKyAnXCI+JyArIHN0YXJ0WWVhci55ZWFyKCkgKyAnPC9zcGFuPic7XG5cbiAgICAgICAgICAgIHllYXJzVmlldy5maW5kKCd0ZCcpLmh0bWwoaHRtbCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl91cGRhdGVEZWNhZGVzID0gZnVuY3Rpb24gX3VwZGF0ZURlY2FkZXMoKSB7XG4gICAgICAgICAgICB2YXIgZGVjYWRlc1ZpZXcgPSB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci1kZWNhZGVzJyksXG4gICAgICAgICAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIgPSBkZWNhZGVzVmlldy5maW5kKCd0aCcpLFxuICAgICAgICAgICAgICAgIHllYXJDYXBzID0gdGhpcy5fZ2V0U3RhcnRFbmRZZWFyKDEwMCwgdGhpcy5fdmlld0RhdGUueWVhcigpKSxcbiAgICAgICAgICAgICAgICBzdGFydERlY2FkZSA9IHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkueWVhcih5ZWFyQ2Fwc1swXSksXG4gICAgICAgICAgICAgICAgZW5kRGVjYWRlID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS55ZWFyKHllYXJDYXBzWzFdKTtcbiAgICAgICAgICAgIHZhciBtaW5EYXRlRGVjYWRlID0gZmFsc2UsXG4gICAgICAgICAgICAgICAgbWF4RGF0ZURlY2FkZSA9IGZhbHNlLFxuICAgICAgICAgICAgICAgIGVuZERlY2FkZVllYXIgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgaHRtbCA9ICcnO1xuXG4gICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgwKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnByZXZDZW50dXJ5KTtcbiAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyLmVxKDIpLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMubmV4dENlbnR1cnkpO1xuXG4gICAgICAgICAgICBkZWNhZGVzVmlldy5maW5kKCcuZGlzYWJsZWQnKS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcblxuICAgICAgICAgICAgaWYgKHN0YXJ0RGVjYWRlLnllYXIoKSA9PT0gMCB8fCB0aGlzLl9vcHRpb25zLm1pbkRhdGUgJiYgdGhpcy5fb3B0aW9ucy5taW5EYXRlLmlzQWZ0ZXIoc3RhcnREZWNhZGUsICd5JykpIHtcbiAgICAgICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMSkudGV4dChzdGFydERlY2FkZS55ZWFyKCkgKyAnLScgKyBlbmREZWNhZGUueWVhcigpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubWF4RGF0ZSAmJiB0aGlzLl9vcHRpb25zLm1heERhdGUuaXNCZWZvcmUoZW5kRGVjYWRlLCAneScpKSB7XG4gICAgICAgICAgICAgICAgZGVjYWRlc1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzdGFydERlY2FkZS55ZWFyKCkgLSAxMCA8IDApIHtcbiAgICAgICAgICAgICAgICBodG1sICs9ICc8c3Bhbj4mbmJzcDs8L3NwYW4+JztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3REZWNhZGVcIiBjbGFzcz1cImRlY2FkZSBvbGRcIiBkYXRhLXNlbGVjdGlvbj1cIicgKyAoc3RhcnREZWNhZGUueWVhcigpICsgNikgKyAnXCI+JyArIChzdGFydERlY2FkZS55ZWFyKCkgLSAxMCkgKyAnPC9zcGFuPic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHdoaWxlICghc3RhcnREZWNhZGUuaXNBZnRlcihlbmREZWNhZGUsICd5JykpIHtcbiAgICAgICAgICAgICAgICBlbmREZWNhZGVZZWFyID0gc3RhcnREZWNhZGUueWVhcigpICsgMTE7XG4gICAgICAgICAgICAgICAgbWluRGF0ZURlY2FkZSA9IHRoaXMuX29wdGlvbnMubWluRGF0ZSAmJiB0aGlzLl9vcHRpb25zLm1pbkRhdGUuaXNBZnRlcihzdGFydERlY2FkZSwgJ3knKSAmJiB0aGlzLl9vcHRpb25zLm1pbkRhdGUueWVhcigpIDw9IGVuZERlY2FkZVllYXI7XG4gICAgICAgICAgICAgICAgbWF4RGF0ZURlY2FkZSA9IHRoaXMuX29wdGlvbnMubWF4RGF0ZSAmJiB0aGlzLl9vcHRpb25zLm1heERhdGUuaXNBZnRlcihzdGFydERlY2FkZSwgJ3knKSAmJiB0aGlzLl9vcHRpb25zLm1heERhdGUueWVhcigpIDw9IGVuZERlY2FkZVllYXI7XG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3REZWNhZGVcIiBjbGFzcz1cImRlY2FkZScgKyAodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5pc0FmdGVyKHN0YXJ0RGVjYWRlKSAmJiB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLnllYXIoKSA8PSBlbmREZWNhZGVZZWFyID8gJyBhY3RpdmUnIDogJycpICsgKCF0aGlzLl9pc1ZhbGlkKHN0YXJ0RGVjYWRlLCAneScpICYmICFtaW5EYXRlRGVjYWRlICYmICFtYXhEYXRlRGVjYWRlID8gJyBkaXNhYmxlZCcgOiAnJykgKyAnXCIgZGF0YS1zZWxlY3Rpb249XCInICsgKHN0YXJ0RGVjYWRlLnllYXIoKSArIDYpICsgJ1wiPicgKyBzdGFydERlY2FkZS55ZWFyKCkgKyAnPC9zcGFuPic7XG4gICAgICAgICAgICAgICAgc3RhcnREZWNhZGUuYWRkKDEwLCAneScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3REZWNhZGVcIiBjbGFzcz1cImRlY2FkZSBvbGRcIiBkYXRhLXNlbGVjdGlvbj1cIicgKyAoc3RhcnREZWNhZGUueWVhcigpICsgNikgKyAnXCI+JyArIHN0YXJ0RGVjYWRlLnllYXIoKSArICc8L3NwYW4+JztcblxuICAgICAgICAgICAgZGVjYWRlc1ZpZXcuZmluZCgndGQnKS5odG1sKGh0bWwpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZmlsbERhdGUgPSBmdW5jdGlvbiBfZmlsbERhdGUoKSB7XG4gICAgICAgICAgICB2YXIgZGF5c1ZpZXcgPSB0aGlzLndpZGdldC5maW5kKCcuZGF0ZXBpY2tlci1kYXlzJyksXG4gICAgICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIgPSBkYXlzVmlldy5maW5kKCd0aCcpLFxuICAgICAgICAgICAgICAgIGh0bWwgPSBbXTtcbiAgICAgICAgICAgIHZhciBjdXJyZW50RGF0ZSA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICByb3cgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgY2xzTmFtZSA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBpID0gdm9pZCAwO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuX2hhc0RhdGUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMCkuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5wcmV2TW9udGgpO1xuICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMSkuYXR0cigndGl0bGUnLCB0aGlzLl9vcHRpb25zLnRvb2x0aXBzLnNlbGVjdE1vbnRoKTtcbiAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDIpLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMubmV4dE1vbnRoKTtcblxuICAgICAgICAgICAgZGF5c1ZpZXcuZmluZCgnLmRpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgxKS50ZXh0KHRoaXMuX3ZpZXdEYXRlLmZvcm1hdCh0aGlzLl9vcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQpKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuc3VidHJhY3QoMSwgJ00nKSwgJ00nKSkge1xuICAgICAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDApLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKHRoaXMuX3ZpZXdEYXRlLmNsb25lKCkuYWRkKDEsICdNJyksICdNJykpIHtcbiAgICAgICAgICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgyKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY3VycmVudERhdGUgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ00nKS5zdGFydE9mKCd3Jykuc3RhcnRPZignZCcpO1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNDI7IGkrKykge1xuICAgICAgICAgICAgICAgIC8vYWx3YXlzIGRpc3BsYXkgNDIgZGF5cyAoc2hvdWxkIHNob3cgNiB3ZWVrcylcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUud2Vla2RheSgpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9ICQoJzx0cj4nKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuY2FsZW5kYXJXZWVrcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGNsYXNzPVwiY3dcIj4nICsgY3VycmVudERhdGUud2VlaygpICsgJzwvdGQ+Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaHRtbC5wdXNoKHJvdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNsc05hbWUgPSAnJztcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuaXNCZWZvcmUodGhpcy5fdmlld0RhdGUsICdNJykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xzTmFtZSArPSAnIG9sZCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc0FmdGVyKHRoaXMuX3ZpZXdEYXRlLCAnTScpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsc05hbWUgKz0gJyBuZXcnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGxvd011bHRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSB0aGlzLl9kYXRlc0Zvcm1hdHRlZC5pbmRleE9mKGN1cnJlbnREYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmlzU2FtZSh0aGlzLl9kYXRlc0Zvcm1hdHRlZFtpbmRleF0sICdkJykgJiYgIXRoaXMudW5zZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHNOYW1lICs9ICcgYWN0aXZlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc1NhbWUodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKSwgJ2QnKSAmJiAhdGhpcy51bnNldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzTmFtZSArPSAnIGFjdGl2ZSc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1ZhbGlkKGN1cnJlbnREYXRlLCAnZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsc05hbWUgKz0gJyBkaXNhYmxlZCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc1NhbWUodGhpcy5nZXRNb21lbnQoKSwgJ2QnKSkge1xuICAgICAgICAgICAgICAgICAgICBjbHNOYW1lICs9ICcgdG9kYXknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuZGF5KCkgPT09IDAgfHwgY3VycmVudERhdGUuZGF5KCkgPT09IDYpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xzTmFtZSArPSAnIHdlZWtlbmQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCc8dGQgZGF0YS1hY3Rpb249XCJzZWxlY3REYXlcIiBkYXRhLWRheT1cIicgKyBjdXJyZW50RGF0ZS5mb3JtYXQoJ0wnKSArICdcIiBjbGFzcz1cImRheScgKyBjbHNOYW1lICsgJ1wiPicgKyBjdXJyZW50RGF0ZS5kYXRlKCkgKyAnPC90ZD4nKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50RGF0ZS5hZGQoMSwgJ2QnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGF5c1ZpZXcuZmluZCgndGJvZHknKS5lbXB0eSgpLmFwcGVuZChodG1sKTtcblxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlTW9udGhzKCk7XG5cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVllYXJzKCk7XG5cbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZURlY2FkZXMoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2ZpbGxIb3VycyA9IGZ1bmN0aW9uIF9maWxsSG91cnMoKSB7XG4gICAgICAgICAgICB2YXIgdGFibGUgPSB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlci1ob3VycyB0YWJsZScpLFxuICAgICAgICAgICAgICAgIGN1cnJlbnRIb3VyID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdkJyksXG4gICAgICAgICAgICAgICAgaHRtbCA9IFtdO1xuICAgICAgICAgICAgdmFyIHJvdyA9ICQoJzx0cj4nKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX3ZpZXdEYXRlLmhvdXIoKSA+IDExICYmICF0aGlzLnVzZTI0SG91cnMpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50SG91ci5ob3VyKDEyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChjdXJyZW50SG91ci5pc1NhbWUodGhpcy5fdmlld0RhdGUsICdkJykgJiYgKHRoaXMudXNlMjRIb3VycyB8fCB0aGlzLl92aWV3RGF0ZS5ob3VyKCkgPCAxMiAmJiBjdXJyZW50SG91ci5ob3VyKCkgPCAxMiB8fCB0aGlzLl92aWV3RGF0ZS5ob3VyKCkgPiAxMSkpIHtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudEhvdXIuaG91cigpICUgNCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSAkKCc8dHI+Jyk7XG4gICAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChyb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCc8dGQgZGF0YS1hY3Rpb249XCJzZWxlY3RIb3VyXCIgY2xhc3M9XCJob3VyJyArICghdGhpcy5faXNWYWxpZChjdXJyZW50SG91ciwgJ2gnKSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiPicgKyBjdXJyZW50SG91ci5mb3JtYXQodGhpcy51c2UyNEhvdXJzID8gJ0hIJyA6ICdoaCcpICsgJzwvdGQ+Jyk7XG4gICAgICAgICAgICAgICAgY3VycmVudEhvdXIuYWRkKDEsICdoJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YWJsZS5lbXB0eSgpLmFwcGVuZChodG1sKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2ZpbGxNaW51dGVzID0gZnVuY3Rpb24gX2ZpbGxNaW51dGVzKCkge1xuICAgICAgICAgICAgdmFyIHRhYmxlID0gdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItbWludXRlcyB0YWJsZScpLFxuICAgICAgICAgICAgICAgIGN1cnJlbnRNaW51dGUgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ2gnKSxcbiAgICAgICAgICAgICAgICBodG1sID0gW10sXG4gICAgICAgICAgICAgICAgc3RlcCA9IHRoaXMuX29wdGlvbnMuc3RlcHBpbmcgPT09IDEgPyA1IDogdGhpcy5fb3B0aW9ucy5zdGVwcGluZztcbiAgICAgICAgICAgIHZhciByb3cgPSAkKCc8dHI+Jyk7XG5cbiAgICAgICAgICAgIHdoaWxlICh0aGlzLl92aWV3RGF0ZS5pc1NhbWUoY3VycmVudE1pbnV0ZSwgJ2gnKSkge1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50TWludXRlLm1pbnV0ZSgpICUgKHN0ZXAgKiA0KSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSAkKCc8dHI+Jyk7XG4gICAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChyb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCc8dGQgZGF0YS1hY3Rpb249XCJzZWxlY3RNaW51dGVcIiBjbGFzcz1cIm1pbnV0ZScgKyAoIXRoaXMuX2lzVmFsaWQoY3VycmVudE1pbnV0ZSwgJ20nKSA/ICcgZGlzYWJsZWQnIDogJycpICsgJ1wiPicgKyBjdXJyZW50TWludXRlLmZvcm1hdCgnbW0nKSArICc8L3RkPicpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRNaW51dGUuYWRkKHN0ZXAsICdtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YWJsZS5lbXB0eSgpLmFwcGVuZChodG1sKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuX2ZpbGxTZWNvbmRzID0gZnVuY3Rpb24gX2ZpbGxTZWNvbmRzKCkge1xuICAgICAgICAgICAgdmFyIHRhYmxlID0gdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItc2Vjb25kcyB0YWJsZScpLFxuICAgICAgICAgICAgICAgIGN1cnJlbnRTZWNvbmQgPSB0aGlzLl92aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ20nKSxcbiAgICAgICAgICAgICAgICBodG1sID0gW107XG4gICAgICAgICAgICB2YXIgcm93ID0gJCgnPHRyPicpO1xuXG4gICAgICAgICAgICB3aGlsZSAodGhpcy5fdmlld0RhdGUuaXNTYW1lKGN1cnJlbnRTZWNvbmQsICdtJykpIHtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudFNlY29uZC5zZWNvbmQoKSAlIDIwID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9ICQoJzx0cj4nKTtcbiAgICAgICAgICAgICAgICAgICAgaHRtbC5wdXNoKHJvdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJvdy5hcHBlbmQoJzx0ZCBkYXRhLWFjdGlvbj1cInNlbGVjdFNlY29uZFwiIGNsYXNzPVwic2Vjb25kJyArICghdGhpcy5faXNWYWxpZChjdXJyZW50U2Vjb25kLCAncycpID8gJyBkaXNhYmxlZCcgOiAnJykgKyAnXCI+JyArIGN1cnJlbnRTZWNvbmQuZm9ybWF0KCdzcycpICsgJzwvdGQ+Jyk7XG4gICAgICAgICAgICAgICAgY3VycmVudFNlY29uZC5hZGQoNSwgJ3MnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGFibGUuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLl9maWxsVGltZSA9IGZ1bmN0aW9uIF9maWxsVGltZSgpIHtcbiAgICAgICAgICAgIHZhciB0b2dnbGUgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgbmV3RGF0ZSA9IHZvaWQgMDtcbiAgICAgICAgICAgIHZhciB0aW1lQ29tcG9uZW50cyA9IHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIHNwYW5bZGF0YS10aW1lLWNvbXBvbmVudF0nKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnVzZTI0SG91cnMpIHtcbiAgICAgICAgICAgICAgICB0b2dnbGUgPSB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciBbZGF0YS1hY3Rpb249dG9nZ2xlUGVyaW9kXScpO1xuICAgICAgICAgICAgICAgIG5ld0RhdGUgPSB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLmNsb25lKCkuYWRkKHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuaG91cnMoKSA+PSAxMiA/IC0xMiA6IDEyLCAnaCcpO1xuXG4gICAgICAgICAgICAgICAgdG9nZ2xlLnRleHQodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5mb3JtYXQoJ0EnKSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZChuZXdEYXRlLCAnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvZ2dsZS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0b2dnbGUuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGltZUNvbXBvbmVudHMuZmlsdGVyKCdbZGF0YS10aW1lLWNvbXBvbmVudD1ob3Vyc10nKS50ZXh0KHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCkuZm9ybWF0KCcnICsgKHRoaXMudXNlMjRIb3VycyA/ICdISCcgOiAnaGgnKSkpO1xuICAgICAgICAgICAgdGltZUNvbXBvbmVudHMuZmlsdGVyKCdbZGF0YS10aW1lLWNvbXBvbmVudD1taW51dGVzXScpLnRleHQodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5mb3JtYXQoJ21tJykpO1xuICAgICAgICAgICAgdGltZUNvbXBvbmVudHMuZmlsdGVyKCdbZGF0YS10aW1lLWNvbXBvbmVudD1zZWNvbmRzXScpLnRleHQodGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5mb3JtYXQoJ3NzJykpO1xuXG4gICAgICAgICAgICB0aGlzLl9maWxsSG91cnMoKTtcbiAgICAgICAgICAgIHRoaXMuX2ZpbGxNaW51dGVzKCk7XG4gICAgICAgICAgICB0aGlzLl9maWxsU2Vjb25kcygpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5fZG9BY3Rpb24gPSBmdW5jdGlvbiBfZG9BY3Rpb24oZSwgYWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgbGFzdFBpY2tlZCA9IHRoaXMuX2dldExhc3RQaWNrZWREYXRlKCk7XG4gICAgICAgICAgICBpZiAoJChlLmN1cnJlbnRUYXJnZXQpLmlzKCcuZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFjdGlvbiA9IGFjdGlvbiB8fCAkKGUuY3VycmVudFRhcmdldCkuZGF0YSgnYWN0aW9uJyk7XG4gICAgICAgICAgICBzd2l0Y2ggKGFjdGlvbikge1xuICAgICAgICAgICAgICAgIGNhc2UgJ25leHQnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmF2Rm5jID0gRGF0ZVRpbWVQaWNrZXIuRGF0ZVBpY2tlck1vZGVzW3RoaXMuY3VycmVudFZpZXdNb2RlXS5OQVZfRlVOQ1RJT047XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS5hZGQoRGF0ZVRpbWVQaWNrZXIuRGF0ZVBpY2tlck1vZGVzW3RoaXMuY3VycmVudFZpZXdNb2RlXS5OQVZfU1RFUCwgbmF2Rm5jKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpbGxEYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3VXBkYXRlKG5hdkZuYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ3ByZXZpb3VzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uYXZGbmMgPSBEYXRlVGltZVBpY2tlci5EYXRlUGlja2VyTW9kZXNbdGhpcy5jdXJyZW50Vmlld01vZGVdLk5BVl9GVU5DVElPTjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlLnN1YnRyYWN0KERhdGVUaW1lUGlja2VyLkRhdGVQaWNrZXJNb2Rlc1t0aGlzLmN1cnJlbnRWaWV3TW9kZV0uTkFWX1NURVAsIF9uYXZGbmMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZmlsbERhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdVcGRhdGUoX25hdkZuYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ3BpY2tlclN3aXRjaCc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKDEpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3RNb250aCc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtb250aCA9ICQoZS50YXJnZXQpLmNsb3Nlc3QoJ3Rib2R5JykuZmluZCgnc3BhbicpLmluZGV4KCQoZS50YXJnZXQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlLm1vbnRoKG1vbnRoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRWaWV3TW9kZSA9PT0gdGhpcy5NaW5WaWV3TW9kZU51bWJlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS55ZWFyKHRoaXMuX3ZpZXdEYXRlLnllYXIoKSkubW9udGgodGhpcy5fdmlld0RhdGUubW9udGgoKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKC0xKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZSgnTScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3RZZWFyJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHllYXIgPSBwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSB8fCAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld0RhdGUueWVhcih5ZWFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRWaWV3TW9kZSA9PT0gdGhpcy5NaW5WaWV3TW9kZU51bWJlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS55ZWFyKHRoaXMuX3ZpZXdEYXRlLnllYXIoKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKC0xKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZSgnWVlZWScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3REZWNhZGUnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3llYXIgPSBwYXJzZUludCgkKGUudGFyZ2V0KS5kYXRhKCdzZWxlY3Rpb24nKSwgMTApIHx8IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl92aWV3RGF0ZS55ZWFyKF95ZWFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRWaWV3TW9kZSA9PT0gdGhpcy5NaW5WaWV3TW9kZU51bWJlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS55ZWFyKHRoaXMuX3ZpZXdEYXRlLnllYXIoKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKC0xKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxsRGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlld1VwZGF0ZSgnWVlZWScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3REYXknOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGF5ID0gdGhpcy5fdmlld0RhdGUuY2xvbmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkKGUudGFyZ2V0KS5pcygnLm9sZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF5LnN1YnRyYWN0KDEsICdNJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJChlLnRhcmdldCkuaXMoJy5uZXcnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheS5hZGQoMSwgJ00nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHNlbGVjdERhdGUgPSBkYXkuZGF0ZShwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9IHRoaXMuX2RhdGVzRm9ybWF0dGVkLmluZGV4T2Yoc2VsZWN0RGF0ZS5mb3JtYXQoJ1lZWVktTU0tREQnKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShudWxsLCBpbmRleCk7IC8vZGVzZWxlY3QgbXVsdGlkYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoc2VsZWN0RGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShzZWxlY3REYXRlLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2hhc1RpbWUoKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUgJiYgIXRoaXMuX29wdGlvbnMuYWxsb3dNdWx0aWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnaW5jcmVtZW50SG91cnMnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3RGF0ZSA9IGxhc3RQaWNrZWQuY2xvbmUoKS5hZGQoMSwgJ2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1ZhbGlkKG5ld0RhdGUsICdoJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShuZXdEYXRlLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdpbmNyZW1lbnRNaW51dGVzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uZXdEYXRlID0gbGFzdFBpY2tlZC5jbG9uZSgpLmFkZCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGUsICdtJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShfbmV3RGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAnaW5jcmVtZW50U2Vjb25kcyc6XG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmV3RGF0ZTIgPSBsYXN0UGlja2VkLmNsb25lKCkuYWRkKDEsICdzJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZChfbmV3RGF0ZTIsICdzJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShfbmV3RGF0ZTIsIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ2RlY3JlbWVudEhvdXJzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uZXdEYXRlMyA9IGxhc3RQaWNrZWQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGUzLCAnaCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGUzLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdkZWNyZW1lbnRNaW51dGVzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uZXdEYXRlNCA9IGxhc3RQaWNrZWQuY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLl9vcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGU0LCAnbScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGU0LCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdkZWNyZW1lbnRTZWNvbmRzJzpcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9uZXdEYXRlNSA9IGxhc3RQaWNrZWQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAncycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzVmFsaWQoX25ld0RhdGU1LCAncycpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoX25ld0RhdGU1LCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGVQZXJpb2QnOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkuYWRkKGxhc3RQaWNrZWQuaG91cnMoKSA+PSAxMiA/IC0xMiA6IDEyLCAnaCcpLCB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZUluZGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGVQaWNrZXInOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkKGUudGFyZ2V0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbGluayA9ICR0aGlzLmNsb3Nlc3QoJ2EnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGFyZW50ID0gJHRoaXMuY2xvc2VzdCgndWwnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBhbmRlZCA9ICRwYXJlbnQuZmluZCgnLnNob3cnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9zZWQgPSAkcGFyZW50LmZpbmQoJy5jb2xsYXBzZTpub3QoLnNob3cpJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNwYW4gPSAkdGhpcy5pcygnc3BhbicpID8gJHRoaXMgOiAkdGhpcy5maW5kKCdzcGFuJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29sbGFwc2VEYXRhID0gdm9pZCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXhwYW5kZWQgJiYgZXhwYW5kZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2VEYXRhID0gZXhwYW5kZWQuZGF0YSgnY29sbGFwc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29sbGFwc2VEYXRhICYmIGNvbGxhcHNlRGF0YS50cmFuc2l0aW9uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXhwYW5kZWQuY29sbGFwc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgY29sbGFwc2UgcGx1Z2luIGlzIGF2YWlsYWJsZSB0aHJvdWdoIGJvb3RzdHJhcC5qcyB0aGVuIHVzZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBhbmRlZC5jb2xsYXBzZSgnaGlkZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9zZWQuY29sbGFwc2UoJ3Nob3cnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UganVzdCB0b2dnbGUgaW4gY2xhc3Mgb24gdGhlIHR3byB2aWV3c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBhbmRlZC5yZW1vdmVDbGFzcygnc2hvdycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9zZWQuYWRkQ2xhc3MoJ3Nob3cnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNwYW4udG9nZ2xlQ2xhc3ModGhpcy5fb3B0aW9ucy5pY29ucy50aW1lICsgJyAnICsgdGhpcy5fb3B0aW9ucy5pY29ucy5kYXRlKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkc3Bhbi5oYXNDbGFzcyh0aGlzLl9vcHRpb25zLmljb25zLmRhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRsaW5rLmF0dHIoJ3RpdGxlJywgdGhpcy5fb3B0aW9ucy50b29sdGlwcy5zZWxlY3REYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbGluay5hdHRyKCd0aXRsZScsIHRoaXMuX29wdGlvbnMudG9vbHRpcHMuc2VsZWN0VGltZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3Nob3dQaWNrZXInOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciA+IGRpdjpub3QoLnRpbWVwaWNrZXItcGlja2VyKScpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzaG93SG91cnMnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1waWNrZXInKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLWhvdXJzJykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzaG93TWludXRlcyc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLXBpY2tlcicpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItbWludXRlcycpLnNob3coKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc2hvd1NlY29uZHMnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1waWNrZXInKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLXNlY29uZHMnKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdEhvdXInOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaG91ciA9IHBhcnNlSW50KCQoZS50YXJnZXQpLnRleHQoKSwgMTApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMudXNlMjRIb3Vycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0UGlja2VkLmhvdXJzKCkgPj0gMTIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhvdXIgIT09IDEyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyICs9IDEyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS5ob3Vycyhob3VyKSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5faXNFbmFibGVkKCdhJykgJiYgIXRoaXMuX2lzRW5hYmxlZCgnbScpICYmICF0aGlzLl9vcHRpb25zLmtlZXBPcGVuICYmICF0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb0FjdGlvbihlLCAnc2hvd1BpY2tlcicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdzZWxlY3RNaW51dGUnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShsYXN0UGlja2VkLmNsb25lKCkubWludXRlcyhwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSksIHRoaXMuX2dldExhc3RQaWNrZWREYXRlSW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5faXNFbmFibGVkKCdhJykgJiYgIXRoaXMuX2lzRW5hYmxlZCgncycpICYmICF0aGlzLl9vcHRpb25zLmtlZXBPcGVuICYmICF0aGlzLl9vcHRpb25zLmlubGluZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb0FjdGlvbihlLCAnc2hvd1BpY2tlcicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdFNlY29uZCc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlKGxhc3RQaWNrZWQuY2xvbmUoKS5zZWNvbmRzKHBhcnNlSW50KCQoZS50YXJnZXQpLnRleHQoKSwgMTApKSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0VuYWJsZWQoJ2EnKSAmJiAhdGhpcy5fb3B0aW9ucy5rZWVwT3BlbiAmJiAhdGhpcy5fb3B0aW9ucy5pbmxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9BY3Rpb24oZSwgJ3Nob3dQaWNrZXInKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjbGVhcic6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xvc2UnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAndG9kYXknOlxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG9kYXlzRGF0ZSA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNWYWxpZCh0b2RheXNEYXRlLCAnZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodG9kYXlzRGF0ZSwgdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGVJbmRleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9wdWJsaWNcblxuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gaGlkZSgpIHtcbiAgICAgICAgICAgIHZhciB0cmFuc2l0aW9uaW5nID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoIXRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWdub3JlIGV2ZW50IGlmIGluIHRoZSBtaWRkbGUgb2YgYSBwaWNrZXIgdHJhbnNpdGlvblxuICAgICAgICAgICAgdGhpcy53aWRnZXQuZmluZCgnLmNvbGxhcHNlJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbGxhcHNlRGF0YSA9ICQodGhpcykuZGF0YSgnY29sbGFwc2UnKTtcbiAgICAgICAgICAgICAgICBpZiAoY29sbGFwc2VEYXRhICYmIGNvbGxhcHNlRGF0YS50cmFuc2l0aW9uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb25pbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodHJhbnNpdGlvbmluZykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudC50b2dnbGVDbGFzcygnYWN0aXZlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpZGdldC5oaWRlKCk7XG5cbiAgICAgICAgICAgICQod2luZG93KS5vZmYoJ3Jlc2l6ZScsIHRoaXMuX3BsYWNlKCkpO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQub2ZmKCdjbGljaycsICdbZGF0YS1hY3Rpb25dJyk7XG4gICAgICAgICAgICB0aGlzLndpZGdldC5vZmYoJ21vdXNlZG93bicsIGZhbHNlKTtcblxuICAgICAgICAgICAgdGhpcy53aWRnZXQucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLndpZGdldCA9IGZhbHNlO1xuXG4gICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuSElERSxcbiAgICAgICAgICAgICAgICBkYXRlOiB0aGlzLl9nZXRMYXN0UGlja2VkRGF0ZSgpLmNsb25lKClcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dC5ibHVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3ZpZXdEYXRlID0gdGhpcy5fZ2V0TGFzdFBpY2tlZERhdGUoKS5jbG9uZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gc2hvdygpIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50TW9tZW50ID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIHVzZUN1cnJlbnRHcmFudWxhcml0eSA9IHtcbiAgICAgICAgICAgICAgICAneWVhcic6IGZ1bmN0aW9uIHllYXIobSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbS5tb250aCgwKS5kYXRlKDEpLmhvdXJzKDApLnNlY29uZHMoMCkubWludXRlcygwKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICdtb250aCc6IGZ1bmN0aW9uIG1vbnRoKG0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0uZGF0ZSgxKS5ob3VycygwKS5zZWNvbmRzKDApLm1pbnV0ZXMoMCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAnZGF5JzogZnVuY3Rpb24gZGF5KG0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0uaG91cnMoMCkuc2Vjb25kcygwKS5taW51dGVzKDApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ2hvdXInOiBmdW5jdGlvbiBob3VyKG0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0uc2Vjb25kcygwKS5taW51dGVzKDApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ21pbnV0ZSc6IGZ1bmN0aW9uIG1pbnV0ZShtKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtLnNlY29uZHMoMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0LnByb3AoJ2Rpc2FibGVkJykgfHwgIXRoaXMuX29wdGlvbnMuaWdub3JlUmVhZG9ubHkgJiYgdGhpcy5pbnB1dC5wcm9wKCdyZWFkb25seScpIHx8IHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXQudmFsKCkgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmlucHV0LnZhbCgpLnRyaW0oKS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUodGhpcy5fcGFyc2VJbnB1dERhdGUodGhpcy5pbnB1dC52YWwoKS50cmltKCkpLCAwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudW5zZXQgJiYgdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNb21lbnQgPSB0aGlzLmdldE1vbWVudCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMudXNlQ3VycmVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNb21lbnQgPSB1c2VDdXJyZW50R3JhbnVsYXJpdHlbdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50XShjdXJyZW50TW9tZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZShjdXJyZW50TW9tZW50LCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudW5zZXQgJiYgdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgY3VycmVudE1vbWVudCA9IHRoaXMuZ2V0TW9tZW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9vcHRpb25zLnVzZUN1cnJlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNb21lbnQgPSB1c2VDdXJyZW50R3JhbnVsYXJpdHlbdGhpcy5fb3B0aW9ucy51c2VDdXJyZW50XShjdXJyZW50TW9tZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWUoY3VycmVudE1vbWVudCwgMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMud2lkZ2V0ID0gdGhpcy5fZ2V0VGVtcGxhdGUoKTtcblxuICAgICAgICAgICAgdGhpcy5fZmlsbERvdygpO1xuICAgICAgICAgICAgdGhpcy5fZmlsbE1vbnRocygpO1xuXG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlci1ob3VycycpLmhpZGUoKTtcbiAgICAgICAgICAgIHRoaXMud2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyLW1pbnV0ZXMnKS5oaWRlKCk7XG4gICAgICAgICAgICB0aGlzLndpZGdldC5maW5kKCcudGltZXBpY2tlci1zZWNvbmRzJykuaGlkZSgpO1xuXG4gICAgICAgICAgICB0aGlzLl91cGRhdGUoKTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3dNb2RlKCk7XG5cbiAgICAgICAgICAgICQod2luZG93KS5vbigncmVzaXplJywgeyBwaWNrZXI6IHRoaXMgfSwgdGhpcy5fcGxhY2UpO1xuICAgICAgICAgICAgdGhpcy53aWRnZXQub24oJ2NsaWNrJywgJ1tkYXRhLWFjdGlvbl0nLCAkLnByb3h5KHRoaXMuX2RvQWN0aW9uLCB0aGlzKSk7IC8vIHRoaXMgaGFuZGxlcyBjbGlja3Mgb24gdGhlIHdpZGdldFxuICAgICAgICAgICAgdGhpcy53aWRnZXQub24oJ21vdXNlZG93bicsIGZhbHNlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuY29tcG9uZW50ICYmIHRoaXMuY29tcG9uZW50Lmhhc0NsYXNzKCdidG4nKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29tcG9uZW50LnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3BsYWNlKCk7XG4gICAgICAgICAgICB0aGlzLndpZGdldC5zaG93KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dCAhPT0gdW5kZWZpbmVkICYmIHRoaXMuX29wdGlvbnMuZm9jdXNPblNob3cgJiYgIXRoaXMuaW5wdXQuaXMoJzpmb2N1cycpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dC5mb2N1cygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9ub3RpZnlFdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogRGF0ZVRpbWVQaWNrZXIuRXZlbnQuU0hPV1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAvL3RvZG8gZG9jIG9mZj9cbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQucmVtb3ZlRGF0YShEYXRlVGltZVBpY2tlci5EQVRBX0tFWSk7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50LnJlbW92ZURhdGEoJ2RhdGUnKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5wcm90b3R5cGUuZGlzYWJsZSA9IGZ1bmN0aW9uIGRpc2FibGUoKSB7XG4gICAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudC5hZGRDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnByb3AoJ2Rpc2FibGVkJywgdHJ1ZSk7IC8vdG9kbyBkaXNhYmxlIHRoaXMvY29tcCBpZiBpbnB1dCBpcyBudWxsXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uIGVuYWJsZSgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudCAmJiB0aGlzLmNvbXBvbmVudC5oYXNDbGFzcygnYnRuJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXBvbmVudC5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnByb3AoJ2Rpc2FibGVkJywgZmFsc2UpOyAvL3RvZG8gZW5hYmxlIGNvbXAvdGhpcyBpZiBpbnB1dCBpcyBudWxsXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLnRvb2xiYXJQbGFjZW1lbnQgPSBmdW5jdGlvbiB0b29sYmFyUGxhY2VtZW50KF90b29sYmFyUGxhY2VtZW50KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3Rvb2xiYXJQbGFjZW1lbnQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndG9vbGJhclBsYWNlbWVudCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodG9vbGJhclBsYWNlbWVudHMuaW5kZXhPZihfdG9vbGJhclBsYWNlbWVudCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndG9vbGJhclBsYWNlbWVudCgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiAoJyArIHRvb2xiYXJQbGFjZW1lbnRzLmpvaW4oJywgJykgKyAnKSB2YWx1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID0gX3Rvb2xiYXJQbGFjZW1lbnQ7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLndpZGdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0LnByb3RvdHlwZS53aWRnZXRQb3NpdGlvbmluZyA9IGZ1bmN0aW9uIHdpZGdldFBvc2l0aW9uaW5nKF93aWRnZXRQb3NpdGlvbmluZykge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQoe30sIHRoaXMuX29wdGlvbnMud2lkZ2V0UG9zaXRpb25pbmcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoe30udG9TdHJpbmcuY2FsbChfd2lkZ2V0UG9zaXRpb25pbmcpICE9PSAnW29iamVjdCBPYmplY3RdJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBvc2l0aW9uaW5nKCkgZXhwZWN0cyBhbiBvYmplY3QgdmFyaWFibGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBvc2l0aW9uaW5nKCkgaG9yaXpvbnRhbCB2YXJpYWJsZSBtdXN0IGJlIGEgc3RyaW5nJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF93aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsID0gX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICBpZiAoaG9yaXpvbnRhbE1vZGVzLmluZGV4T2YoX3dpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd3aWRnZXRQb3NpdGlvbmluZygpIGV4cGVjdHMgaG9yaXpvbnRhbCBwYXJhbWV0ZXIgdG8gYmUgb25lIG9mICgnICsgaG9yaXpvbnRhbE1vZGVzLmpvaW4oJywgJykgKyAnKScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwgPSBfd2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfd2lkZ2V0UG9zaXRpb25pbmcudmVydGljYWwpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSB2ZXJ0aWNhbCB2YXJpYWJsZSBtdXN0IGJlIGEgc3RyaW5nJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCA9IF93aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbC50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGlmICh2ZXJ0aWNhbE1vZGVzLmluZGV4T2YoX3dpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSBleHBlY3RzIHZlcnRpY2FsIHBhcmFtZXRlciB0byBiZSBvbmUgb2YgKCcgKyB2ZXJ0aWNhbE1vZGVzLmpvaW4oJywgJykgKyAnKScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsID0gX3dpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQucHJvdG90eXBlLndpZGdldFBhcmVudCA9IGZ1bmN0aW9uIHdpZGdldFBhcmVudChfd2lkZ2V0UGFyZW50KSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLndpZGdldFBhcmVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBfd2lkZ2V0UGFyZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIF93aWRnZXRQYXJlbnQgPSAkKF93aWRnZXRQYXJlbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoX3dpZGdldFBhcmVudCAhPT0gbnVsbCAmJiB0eXBlb2YgX3dpZGdldFBhcmVudCAhPT0gJ3N0cmluZycgJiYgIShfd2lkZ2V0UGFyZW50IGluc3RhbmNlb2YgJCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd3aWRnZXRQYXJlbnQoKSBleHBlY3RzIGEgc3RyaW5nIG9yIGEgalF1ZXJ5IG9iamVjdCBwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy53aWRnZXRQYXJlbnQgPSBfd2lkZ2V0UGFyZW50O1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy9zdGF0aWNcblxuXG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlIYW5kbGVUaGlzID0gZnVuY3Rpb24gX2pRdWVyeUhhbmRsZVRoaXMobWUsIG9wdGlvbiwgYXJndW1lbnQpIHtcbiAgICAgICAgICAgIHZhciBkYXRhID0gJChtZSkuZGF0YShEYXRlVGltZVBpY2tlci5EQVRBX0tFWSk7XG4gICAgICAgICAgICBpZiAoKHR5cGVvZiBvcHRpb24gPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKG9wdGlvbikpID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICQuZXh0ZW5kKHt9LCBEYXRlVGltZVBpY2tlci5EZWZhdWx0LCBvcHRpb24pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gbmV3IFRlbXB1c0RvbWludXNCb290c3RyYXA0KCQobWUpLCBvcHRpb24pO1xuICAgICAgICAgICAgICAgICQobWUpLmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YVtvcHRpb25dID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBtZXRob2QgbmFtZWQgXCInICsgb3B0aW9uICsgJ1wiJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRhW29wdGlvbl0oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YVtvcHRpb25dKGFyZ3VtZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2Uob3B0aW9uLCBhcmd1bWVudCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlIYW5kbGVUaGlzKHRoaXNbMF0sIG9wdGlvbiwgYXJndW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUhhbmRsZVRoaXModGhpcywgb3B0aW9uLCBhcmd1bWVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQ7XG4gICAgfShEYXRlVGltZVBpY2tlcik7XG5cbiAgICAvKipcclxuICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICAqIGpRdWVyeVxyXG4gICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgICovXG5cblxuICAgICQoZG9jdW1lbnQpLm9uKERhdGVUaW1lUGlja2VyLkV2ZW50LkNMSUNLX0RBVEFfQVBJLCBEYXRlVGltZVBpY2tlci5TZWxlY3Rvci5EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSk7XG4gICAgICAgIGlmICgkdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkdGFyZ2V0LCAndG9nZ2xlJyk7XG4gICAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuQ0hBTkdFLCAnLicgKyBEYXRlVGltZVBpY2tlci5DbGFzc05hbWUuSU5QVVQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSk7XG4gICAgICAgIGlmICgkdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkdGFyZ2V0LCAnX2NoYW5nZScsIGV2ZW50KTtcbiAgICB9KS5vbihEYXRlVGltZVBpY2tlci5FdmVudC5CTFVSLCAnLicgKyBEYXRlVGltZVBpY2tlci5DbGFzc05hbWUuSU5QVVQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSksXG4gICAgICAgICAgICBjb25maWcgPSAkdGFyZ2V0LmRhdGEoRGF0ZVRpbWVQaWNrZXIuREFUQV9LRVkpO1xuICAgICAgICBpZiAoJHRhcmdldC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29uZmlnLl9vcHRpb25zLmRlYnVnIHx8IHdpbmRvdy5kZWJ1Zykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkdGFyZ2V0LCAnaGlkZScsIGV2ZW50KTtcbiAgICB9KS5vbihEYXRlVGltZVBpY2tlci5FdmVudC5LRVlET1dOLCAnLicgKyBEYXRlVGltZVBpY2tlci5DbGFzc05hbWUuSU5QVVQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoJCh0aGlzKSk7XG4gICAgICAgIGlmICgkdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIFRlbXB1c0RvbWludXNCb290c3RyYXA0Ll9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkdGFyZ2V0LCAnX2tleWRvd24nLCBldmVudCk7XG4gICAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuS0VZVVAsICcuJyArIERhdGVUaW1lUGlja2VyLkNsYXNzTmFtZS5JTlBVVCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciAkdGFyZ2V0ID0gZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCgkKHRoaXMpKTtcbiAgICAgICAgaWYgKCR0YXJnZXQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZS5jYWxsKCR0YXJnZXQsICdfa2V5dXAnLCBldmVudCk7XG4gICAgfSkub24oRGF0ZVRpbWVQaWNrZXIuRXZlbnQuRk9DVVMsICcuJyArIERhdGVUaW1lUGlja2VyLkNsYXNzTmFtZS5JTlBVVCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciAkdGFyZ2V0ID0gZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCgkKHRoaXMpKSxcbiAgICAgICAgICAgIGNvbmZpZyA9ICR0YXJnZXQuZGF0YShEYXRlVGltZVBpY2tlci5EQVRBX0tFWSk7XG4gICAgICAgIGlmICgkdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY29uZmlnLl9vcHRpb25zLmFsbG93SW5wdXRUb2dnbGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBUZW1wdXNEb21pbnVzQm9vdHN0cmFwNC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgJ3Nob3cnLCBldmVudCk7XG4gICAgfSk7XG5cbiAgICAkLmZuW0RhdGVUaW1lUGlja2VyLk5BTUVdID0gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZTtcbiAgICAkLmZuW0RhdGVUaW1lUGlja2VyLk5BTUVdLkNvbnN0cnVjdG9yID0gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQ7XG4gICAgJC5mbltEYXRlVGltZVBpY2tlci5OQU1FXS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAkLmZuW0RhdGVUaW1lUGlja2VyLk5BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgICAgICByZXR1cm4gVGVtcHVzRG9taW51c0Jvb3RzdHJhcDQuX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFRlbXB1c0RvbWludXNCb290c3RyYXA0O1xufShqUXVlcnkpO1xyXG5cclxufSgpO1xyXG4iLCIvKiFcbioganF1ZXJ5LmlucHV0bWFzay5idW5kbGUuanNcbiogaHR0cHM6Ly9naXRodWIuY29tL1JvYmluSGVyYm90cy9JbnB1dG1hc2tcbiogQ29weXJpZ2h0IChjKSAyMDEwIC0gMjAxOSBSb2JpbiBIZXJib3RzXG4qIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSAoaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZS5waHApXG4qIFZlcnNpb246IDQuMC44XG4qL1xuXG4oZnVuY3Rpb24obW9kdWxlcykge1xuICAgIHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG4gICAgZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuICAgICAgICBpZiAoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiAgICAgICAgICAgIHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiAgICAgICAgICAgIGk6IG1vZHVsZUlkLFxuICAgICAgICAgICAgbDogZmFsc2UsXG4gICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICB9O1xuICAgICAgICBtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcbiAgICAgICAgbW9kdWxlLmwgPSB0cnVlO1xuICAgICAgICByZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gICAgfVxuICAgIF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiAgICAgICAgaWYgKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBnZXQ6IGdldHRlclxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBTeW1ib2wgIT09IFwidW5kZWZpbmVkXCIgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7XG4gICAgICAgICAgICAgICAgdmFsdWU6IFwiTW9kdWxlXCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICAgICAgICAgICAgdmFsdWU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fLnQgPSBmdW5jdGlvbih2YWx1ZSwgbW9kZSkge1xuICAgICAgICBpZiAobW9kZSAmIDEpIHZhbHVlID0gX193ZWJwYWNrX3JlcXVpcmVfXyh2YWx1ZSk7XG4gICAgICAgIGlmIChtb2RlICYgOCkgcmV0dXJuIHZhbHVlO1xuICAgICAgICBpZiAobW9kZSAmIDQgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmIHZhbHVlICYmIHZhbHVlLl9fZXNNb2R1bGUpIHJldHVybiB2YWx1ZTtcbiAgICAgICAgdmFyIG5zID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgX193ZWJwYWNrX3JlcXVpcmVfXy5yKG5zKTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG5zLCBcImRlZmF1bHRcIiwge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG1vZGUgJiAyICYmIHR5cGVvZiB2YWx1ZSAhPSBcInN0cmluZ1wiKSBmb3IgKHZhciBrZXkgaW4gdmFsdWUpIF9fd2VicGFja19yZXF1aXJlX18uZChucywga2V5LCBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZVtrZXldO1xuICAgICAgICB9LmJpbmQobnVsbCwga2V5KSk7XG4gICAgICAgIHJldHVybiBucztcbiAgICB9O1xuICAgIF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuICAgICAgICB2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID8gZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHtcbiAgICAgICAgICAgIHJldHVybiBtb2R1bGVbXCJkZWZhdWx0XCJdO1xuICAgICAgICB9IDogZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHtcbiAgICAgICAgICAgIHJldHVybiBtb2R1bGU7XG4gICAgICAgIH07XG4gICAgICAgIF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsIFwiYVwiLCBnZXR0ZXIpO1xuICAgICAgICByZXR1cm4gZ2V0dGVyO1xuICAgIH07XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpO1xuICAgIH07XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcbiAgICByZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSAwKTtcbn0pKFsgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgX193ZWJwYWNrX3JlcXVpcmVfXygxKTtcbiAgICBfX3dlYnBhY2tfcmVxdWlyZV9fKDYpO1xuICAgIF9fd2VicGFja19yZXF1aXJlX18oNyk7XG4gICAgdmFyIF9pbnB1dG1hc2sgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIpO1xuICAgIHZhciBfaW5wdXRtYXNrMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2lucHV0bWFzayk7XG4gICAgdmFyIF9pbnB1dG1hc2szID0gX193ZWJwYWNrX3JlcXVpcmVfXygzKTtcbiAgICB2YXIgX2lucHV0bWFzazQgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9pbnB1dG1hc2szKTtcbiAgICB2YXIgX2pxdWVyeSA9IF9fd2VicGFja19yZXF1aXJlX18oNCk7XG4gICAgdmFyIF9qcXVlcnkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfanF1ZXJ5KTtcbiAgICBmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDoge1xuICAgICAgICAgICAgZGVmYXVsdDogb2JqXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChfaW5wdXRtYXNrNC5kZWZhdWx0ID09PSBfanF1ZXJ5Mi5kZWZhdWx0KSB7XG4gICAgICAgIF9fd2VicGFja19yZXF1aXJlX18oOCk7XG4gICAgfVxuICAgIHdpbmRvdy5JbnB1dG1hc2sgPSBfaW5wdXRtYXNrMi5kZWZhdWx0O1xufSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX187XG4gICAgdmFyIF90eXBlb2YgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIiA/IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9iajtcbiAgICB9IDogZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xuICAgIH07XG4gICAgKGZ1bmN0aW9uKGZhY3RvcnkpIHtcbiAgICAgICAgaWYgKHRydWUpIHtcbiAgICAgICAgICAgICEoX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXyA9IFsgX193ZWJwYWNrX3JlcXVpcmVfXygyKSBdLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5LCBcbiAgICAgICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fID0gdHlwZW9mIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9PT0gXCJmdW5jdGlvblwiID8gX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLmFwcGx5KGV4cG9ydHMsIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18pIDogX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBcbiAgICAgICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fICE9PSB1bmRlZmluZWQgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pKTtcbiAgICAgICAgfSBlbHNlIHt9XG4gICAgfSkoZnVuY3Rpb24oSW5wdXRtYXNrKSB7XG4gICAgICAgIElucHV0bWFzay5leHRlbmREZWZpbml0aW9ucyh7XG4gICAgICAgICAgICBBOiB7XG4gICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIltBLVphLXpcXHUwNDEwLVxcdTA0NGZcXHUwNDAxXFx1MDQ1MVxceGMwLVxceGZmXFx4YjVdXCIsXG4gICAgICAgICAgICAgICAgY2FzaW5nOiBcInVwcGVyXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcIiZcIjoge1xuICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbMC05QS1aYS16XFx1MDQxMC1cXHUwNDRmXFx1MDQwMVxcdTA0NTFcXHhjMC1cXHhmZlxceGI1XVwiLFxuICAgICAgICAgICAgICAgIGNhc2luZzogXCJ1cHBlclwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCIjXCI6IHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOUEtRmEtZl1cIixcbiAgICAgICAgICAgICAgICBjYXNpbmc6IFwidXBwZXJcIlxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgSW5wdXRtYXNrLmV4dGVuZEFsaWFzZXMoe1xuICAgICAgICAgICAgY3NzdW5pdDoge1xuICAgICAgICAgICAgICAgIHJlZ2V4OiBcIlsrLV0/WzAtOV0rXFxcXC4/KFswLTldKyk/KHB4fGVtfHJlbXxleHwlfGlufGNtfG1tfHB0fHBjKVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdXJsOiB7XG4gICAgICAgICAgICAgICAgcmVnZXg6IFwiKGh0dHBzP3xmdHApLy8uKlwiLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6IGZhbHNlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXA6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcImlbaVtpXV0uaVtpW2ldXS5pW2lbaV1dLmlbaVtpXV1cIixcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBpOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwb3MgLSAxID4gLTEgJiYgbWFza3NldC5idWZmZXJbcG9zIC0gMV0gIT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNocnMgPSBtYXNrc2V0LmJ1ZmZlcltwb3MgLSAxXSArIGNocnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwb3MgLSAyID4gLTEgJiYgbWFza3NldC5idWZmZXJbcG9zIC0gMl0gIT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaHJzID0gbWFza3NldC5idWZmZXJbcG9zIC0gMl0gKyBjaHJzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgY2hycyA9IFwiMFwiICsgY2hycztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgY2hycyA9IFwiMDBcIiArIGNocnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAoXCIyNVswLTVdfDJbMC00XVswLTldfFswMV1bMC05XVswLTldXCIpLnRlc3QoY2hycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uVW5NYXNrOiBmdW5jdGlvbiBvblVuTWFzayhtYXNrZWRWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza2VkVmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwibnVtZXJpY1wiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW1haWw6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBcIip7MSw2NH1bLip7MSw2NH1dWy4qezEsNjR9XVsuKnsxLDYzfV1ALXsxLDYzfS4tezEsNjN9Wy4tezEsNjN9XVsuLXsxLDYzfV1cIixcbiAgICAgICAgICAgICAgICBncmVlZHk6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNhc2luZzogXCJsb3dlclwiLFxuICAgICAgICAgICAgICAgIG9uQmVmb3JlUGFzdGU6IGZ1bmN0aW9uIG9uQmVmb3JlUGFzdGUocGFzdGVkVmFsdWUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFzdGVkVmFsdWUgPSBwYXN0ZWRWYWx1ZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFzdGVkVmFsdWUucmVwbGFjZShcIm1haWx0bzpcIiwgXCJcIik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBcIipcIjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTlcXHVmZjExLVxcdWZmMTlBLVphLXpcXHUwNDEwLVxcdTA0NGZcXHUwNDAxXFx1MDQ1MVxceGMwLVxceGZmXFx4YjUhIyQlJicqKy89P15fYHt8fX4tXVwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiLVwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiWzAtOUEtWmEtei1dXCJcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25Vbk1hc2s6IGZ1bmN0aW9uIG9uVW5NYXNrKG1hc2tlZFZhbHVlLCB1bm1hc2tlZFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXNrZWRWYWx1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGlucHV0bW9kZTogXCJlbWFpbFwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWFjOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCIjIzojIzojIzojIzojIzojI1wiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmluOiB7XG4gICAgICAgICAgICAgICAgbWFzazogXCJWezEzfTl7NH1cIixcbiAgICAgICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBWOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IFwiW0EtSEotTlBSLVphLWhqLW5wci16XFxcXGRdXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IFwidXBwZXJcIlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjbGVhckluY29tcGxldGU6IHRydWUsXG4gICAgICAgICAgICAgICAgYXV0b1VubWFzazogdHJ1ZVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIElucHV0bWFzaztcbiAgICB9KTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fO1xuICAgIHZhciBfdHlwZW9mID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgfSA6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICB9O1xuICAgIChmdW5jdGlvbihmYWN0b3J5KSB7XG4gICAgICAgIGlmICh0cnVlKSB7XG4gICAgICAgICAgICAhKF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18gPSBbIF9fd2VicGFja19yZXF1aXJlX18oMyksIF9fd2VicGFja19yZXF1aXJlX18oNSkgXSwgXG4gICAgICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5LCBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyA9IHR5cGVvZiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPT09IFwiZnVuY3Rpb25cIiA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgXG4gICAgICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyAhPT0gdW5kZWZpbmVkICYmIChtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fKSk7XG4gICAgICAgIH0gZWxzZSB7fVxuICAgIH0pKGZ1bmN0aW9uKCQsIHdpbmRvdywgdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciBkb2N1bWVudCA9IHdpbmRvdy5kb2N1bWVudCwgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50LCBpZSA9IHVhLmluZGV4T2YoXCJNU0lFIFwiKSA+IDAgfHwgdWEuaW5kZXhPZihcIlRyaWRlbnQvXCIpID4gMCwgbW9iaWxlID0gaXNJbnB1dEV2ZW50U3VwcG9ydGVkKFwidG91Y2hzdGFydFwiKSwgaWVtb2JpbGUgPSAvaWVtb2JpbGUvaS50ZXN0KHVhKSwgaXBob25lID0gL2lwaG9uZS9pLnRlc3QodWEpICYmICFpZW1vYmlsZTtcbiAgICAgICAgZnVuY3Rpb24gSW5wdXRtYXNrKGFsaWFzLCBvcHRpb25zLCBpbnRlcm5hbCkge1xuICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIElucHV0bWFzaykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IElucHV0bWFzayhhbGlhcywgb3B0aW9ucywgaW50ZXJuYWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRzID0ge307XG4gICAgICAgICAgICB0aGlzLm1hc2tzZXQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hWYWx1ZSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGludGVybmFsICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCQuaXNQbGFpbk9iamVjdChhbGlhcykpIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IGFsaWFzO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICBpZiAoYWxpYXMpIG9wdGlvbnMuYWxpYXMgPSBhbGlhcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5vcHRzID0gJC5leHRlbmQodHJ1ZSwge30sIHRoaXMuZGVmYXVsdHMsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIHRoaXMubm9NYXNrc0NhY2hlID0gb3B0aW9ucyAmJiBvcHRpb25zLmRlZmluaXRpb25zICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy51c2VyT3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgdGhpcy5pc1JUTCA9IHRoaXMub3B0cy5udW1lcmljSW5wdXQ7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZUFsaWFzKHRoaXMub3B0cy5hbGlhcywgb3B0aW9ucywgdGhpcy5vcHRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBJbnB1dG1hc2sucHJvdG90eXBlID0ge1xuICAgICAgICAgICAgZGF0YUF0dHJpYnV0ZTogXCJkYXRhLWlucHV0bWFza1wiLFxuICAgICAgICAgICAgZGVmYXVsdHM6IHtcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJfXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWxtYXJrZXI6IFsgXCJbXCIsIFwiXVwiIF0sXG4gICAgICAgICAgICAgICAgcXVhbnRpZmllcm1hcmtlcjogWyBcIntcIiwgXCJ9XCIgXSxcbiAgICAgICAgICAgICAgICBncm91cG1hcmtlcjogWyBcIihcIiwgXCIpXCIgXSxcbiAgICAgICAgICAgICAgICBhbHRlcm5hdG9ybWFya2VyOiBcInxcIixcbiAgICAgICAgICAgICAgICBlc2NhcGVDaGFyOiBcIlxcXFxcIixcbiAgICAgICAgICAgICAgICBtYXNrOiBudWxsLFxuICAgICAgICAgICAgICAgIHJlZ2V4OiBudWxsLFxuICAgICAgICAgICAgICAgIG9uY29tcGxldGU6ICQubm9vcCxcbiAgICAgICAgICAgICAgICBvbmluY29tcGxldGU6ICQubm9vcCxcbiAgICAgICAgICAgICAgICBvbmNsZWFyZWQ6ICQubm9vcCxcbiAgICAgICAgICAgICAgICByZXBlYXQ6IDAsXG4gICAgICAgICAgICAgICAgZ3JlZWR5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhdXRvVW5tYXNrOiBmYWxzZSxcbiAgICAgICAgICAgICAgICByZW1vdmVNYXNrT25TdWJtaXQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNsZWFyTWFza09uTG9zdEZvY3VzOiB0cnVlLFxuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2xlYXJJbmNvbXBsZXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhbGlhczogbnVsbCxcbiAgICAgICAgICAgICAgICBvbktleURvd246ICQubm9vcCxcbiAgICAgICAgICAgICAgICBvbkJlZm9yZU1hc2s6IG51bGwsXG4gICAgICAgICAgICAgICAgb25CZWZvcmVQYXN0ZTogZnVuY3Rpb24gb25CZWZvcmVQYXN0ZShwYXN0ZWRWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVNYXNrKSA/IG9wdHMub25CZWZvcmVNYXNrLmNhbGwodGhpcywgcGFzdGVkVmFsdWUsIG9wdHMpIDogcGFzdGVkVmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkJlZm9yZVdyaXRlOiBudWxsLFxuICAgICAgICAgICAgICAgIG9uVW5NYXNrOiBudWxsLFxuICAgICAgICAgICAgICAgIHNob3dNYXNrT25Gb2N1czogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzaG93TWFza09uSG92ZXI6IHRydWUsXG4gICAgICAgICAgICAgICAgb25LZXlWYWxpZGF0aW9uOiAkLm5vb3AsXG4gICAgICAgICAgICAgICAgc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlcjogXCIgXCIsXG4gICAgICAgICAgICAgICAgbnVtZXJpY0lucHV0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICByaWdodEFsaWduOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB1bmRvT25Fc2NhcGU6IHRydWUsXG4gICAgICAgICAgICAgICAgcmFkaXhQb2ludDogXCJcIixcbiAgICAgICAgICAgICAgICBfcmFkaXhEYW5jZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgZ3JvdXBTZXBhcmF0b3I6IFwiXCIsXG4gICAgICAgICAgICAgICAga2VlcFN0YXRpYzogbnVsbCxcbiAgICAgICAgICAgICAgICBwb3NpdGlvbkNhcmV0T25UYWI6IHRydWUsXG4gICAgICAgICAgICAgICAgdGFiVGhyb3VnaDogZmFsc2UsXG4gICAgICAgICAgICAgICAgc3VwcG9ydHNJbnB1dFR5cGU6IFsgXCJ0ZXh0XCIsIFwidGVsXCIsIFwidXJsXCIsIFwicGFzc3dvcmRcIiwgXCJzZWFyY2hcIiBdLFxuICAgICAgICAgICAgICAgIGlnbm9yYWJsZXM6IFsgOCwgOSwgMTMsIDE5LCAyNywgMzMsIDM0LCAzNSwgMzYsIDM3LCAzOCwgMzksIDQwLCA0NSwgNDYsIDkzLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAwLCAyMjkgXSxcbiAgICAgICAgICAgICAgICBpc0NvbXBsZXRlOiBudWxsLFxuICAgICAgICAgICAgICAgIHByZVZhbGlkYXRpb246IG51bGwsXG4gICAgICAgICAgICAgICAgcG9zdFZhbGlkYXRpb246IG51bGwsXG4gICAgICAgICAgICAgICAgc3RhdGljRGVmaW5pdGlvblN5bWJvbDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIGppdE1hc2tpbmc6IGZhbHNlLFxuICAgICAgICAgICAgICAgIG51bGxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGlucHV0RXZlbnRPbmx5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBub1ZhbHVlUGF0Y2hpbmc6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uQ2FyZXRPbkNsaWNrOiBcImx2cFwiLFxuICAgICAgICAgICAgICAgIGNhc2luZzogbnVsbCxcbiAgICAgICAgICAgICAgICBpbnB1dG1vZGU6IFwidmVyYmF0aW1cIixcbiAgICAgICAgICAgICAgICBjb2xvck1hc2s6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGRpc2FibGVQcmVkaWN0aXZlVGV4dDogZmFsc2UsXG4gICAgICAgICAgICAgICAgaW1wb3J0RGF0YUF0dHJpYnV0ZXM6IHRydWUsXG4gICAgICAgICAgICAgICAgc2hpZnRQb3NpdGlvbnM6IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWZpbml0aW9uczoge1xuICAgICAgICAgICAgICAgIDk6IHtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTlcXHVmZjExLVxcdWZmMTldXCIsXG4gICAgICAgICAgICAgICAgICAgIGRlZmluaXRpb25TeW1ib2w6IFwiKlwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhOiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogXCJbQS1aYS16XFx1MDQxMC1cXHUwNDRmXFx1MDQwMVxcdTA0NTFcXHhjMC1cXHhmZlxceGI1XVwiLFxuICAgICAgICAgICAgICAgICAgICBkZWZpbml0aW9uU3ltYm9sOiBcIipcIlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXCIqXCI6IHtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTlcXHVmZjExLVxcdWZmMTlBLVphLXpcXHUwNDEwLVxcdTA0NGZcXHUwNDAxXFx1MDQ1MVxceGMwLVxceGZmXFx4YjVdXCJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWxpYXNlczoge30sXG4gICAgICAgICAgICBtYXNrc0NhY2hlOiB7fSxcbiAgICAgICAgICAgIG1hc2s6IGZ1bmN0aW9uIG1hc2soZWxlbXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gaW1wb3J0QXR0cmlidXRlT3B0aW9ucyhucHQsIG9wdHMsIHVzZXJPcHRpb25zLCBkYXRhQXR0cmlidXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmltcG9ydERhdGFBdHRyaWJ1dGVzID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0ck9wdGlvbnMgPSBucHQuZ2V0QXR0cmlidXRlKGRhdGFBdHRyaWJ1dGUpLCBvcHRpb24sIGRhdGFvcHRpb25zLCBvcHRpb25EYXRhLCBwO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGltcG9ydE9wdGlvbiA9IGZ1bmN0aW9uIGltcG9ydE9wdGlvbihvcHRpb24sIG9wdGlvbkRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25EYXRhID0gb3B0aW9uRGF0YSAhPT0gdW5kZWZpbmVkID8gb3B0aW9uRGF0YSA6IG5wdC5nZXRBdHRyaWJ1dGUoZGF0YUF0dHJpYnV0ZSArIFwiLVwiICsgb3B0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9uRGF0YSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbkRhdGEgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb24uaW5kZXhPZihcIm9uXCIpID09PSAwKSBvcHRpb25EYXRhID0gd2luZG93W29wdGlvbkRhdGFdOyBlbHNlIGlmIChvcHRpb25EYXRhID09PSBcImZhbHNlXCIpIG9wdGlvbkRhdGEgPSBmYWxzZTsgZWxzZSBpZiAob3B0aW9uRGF0YSA9PT0gXCJ0cnVlXCIpIG9wdGlvbkRhdGEgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJPcHRpb25zW29wdGlvbl0gPSBvcHRpb25EYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0ck9wdGlvbnMgJiYgYXR0ck9wdGlvbnMgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyT3B0aW9ucyA9IGF0dHJPcHRpb25zLnJlcGxhY2UoLycvZywgJ1wiJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YW9wdGlvbnMgPSBKU09OLnBhcnNlKFwie1wiICsgYXR0ck9wdGlvbnMgKyBcIn1cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YW9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25EYXRhID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAocCBpbiBkYXRhb3B0aW9ucykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocC50b0xvd2VyQ2FzZSgpID09PSBcImFsaWFzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbkRhdGEgPSBkYXRhb3B0aW9uc1twXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaW1wb3J0T3B0aW9uKFwiYWxpYXNcIiwgb3B0aW9uRGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodXNlck9wdGlvbnMuYWxpYXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlQWxpYXModXNlck9wdGlvbnMuYWxpYXMsIHVzZXJPcHRpb25zLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAob3B0aW9uIGluIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YW9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uRGF0YSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwIGluIGRhdGFvcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocC50b0xvd2VyQ2FzZSgpID09PSBvcHRpb24udG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbkRhdGEgPSBkYXRhb3B0aW9uc1twXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbXBvcnRPcHRpb24ob3B0aW9uLCBvcHRpb25EYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCBvcHRzLCB1c2VyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChucHQuZGlyID09PSBcInJ0bFwiIHx8IG9wdHMucmlnaHRBbGlnbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbnB0LnN0eWxlLnRleHRBbGlnbiA9IFwicmlnaHRcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobnB0LmRpciA9PT0gXCJydGxcIiB8fCBvcHRzLm51bWVyaWNJbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbnB0LmRpciA9IFwibHRyXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBucHQucmVtb3ZlQXR0cmlidXRlKFwiZGlyXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5pc1JUTCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHVzZXJPcHRpb25zKS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZWxlbXMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbXMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtcykgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChlbGVtcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsZW1zID0gZWxlbXMubm9kZU5hbWUgPyBbIGVsZW1zIF0gOiBlbGVtcztcbiAgICAgICAgICAgICAgICAkLmVhY2goZWxlbXMsIGZ1bmN0aW9uKG5keCwgZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNjb3BlZE9wdHMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgdGhhdC5vcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltcG9ydEF0dHJpYnV0ZU9wdGlvbnMoZWwsIHNjb3BlZE9wdHMsICQuZXh0ZW5kKHRydWUsIHt9LCB0aGF0LnVzZXJPcHRpb25zKSwgdGhhdC5kYXRhQXR0cmlidXRlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1hc2tzZXQgPSBnZW5lcmF0ZU1hc2tTZXQoc2NvcGVkT3B0cywgdGhhdC5ub01hc2tzQ2FjaGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tzZXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbC5pbnB1dG1hc2sgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2sub3B0cy5hdXRvVW5tYXNrID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2sgPSBuZXcgSW5wdXRtYXNrKHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2sub3B0cyA9IHNjb3BlZE9wdHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaW5wdXRtYXNrLm5vTWFza3NDYWNoZSA9IHRoYXQubm9NYXNrc0NhY2hlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay51c2VyT3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIHt9LCB0aGF0LnVzZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2suaXNSVEwgPSBzY29wZWRPcHRzLmlzUlRMIHx8IHNjb3BlZE9wdHMubnVtZXJpY0lucHV0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5lbCA9IGVsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5tYXNrc2V0ID0gbWFza3NldDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmRhdGEoZWwsIFwiX2lucHV0bWFza19vcHRzXCIsIHNjb3BlZE9wdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tTY29wZS5jYWxsKGVsLmlucHV0bWFzaywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwibWFza1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZWxlbXMgJiYgZWxlbXNbMF0gPyBlbGVtc1swXS5pbnB1dG1hc2sgfHwgdGhpcyA6IHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9uOiBmdW5jdGlvbiBvcHRpb24ob3B0aW9ucywgbm9yZW1hc2spIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMub3B0c1tvcHRpb25zXTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCh0eXBlb2Ygb3B0aW9ucyA9PT0gXCJ1bmRlZmluZWRcIiA/IFwidW5kZWZpbmVkXCIgOiBfdHlwZW9mKG9wdGlvbnMpKSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICAkLmV4dGVuZCh0aGlzLnVzZXJPcHRpb25zLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZWwgJiYgbm9yZW1hc2sgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWFzayh0aGlzLmVsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdW5tYXNrZWR2YWx1ZTogZnVuY3Rpb24gdW5tYXNrZWR2YWx1ZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCBnZW5lcmF0ZU1hc2tTZXQodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcInVubWFza2VkdmFsdWVcIixcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVtb3ZlOiBmdW5jdGlvbiByZW1vdmUoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcInJlbW92ZVwiXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0ZW1wdHltYXNrOiBmdW5jdGlvbiBnZXRlbXB0eW1hc2soKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tYXNrc2V0ID0gdGhpcy5tYXNrc2V0IHx8IGdlbmVyYXRlTWFza1NldCh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWFza1Njb3BlLmNhbGwodGhpcywge1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwiZ2V0ZW1wdHltYXNrXCJcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoYXNNYXNrZWRWYWx1ZTogZnVuY3Rpb24gaGFzTWFza2VkVmFsdWUoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLm9wdHMuYXV0b1VubWFzaztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiBmdW5jdGlvbiBpc0NvbXBsZXRlKCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCBnZW5lcmF0ZU1hc2tTZXQodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcImlzQ29tcGxldGVcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldG1ldGFkYXRhOiBmdW5jdGlvbiBnZXRtZXRhZGF0YSgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1hc2tzZXQgPSB0aGlzLm1hc2tzZXQgfHwgZ2VuZXJhdGVNYXNrU2V0KHRoaXMub3B0cywgdGhpcy5ub01hc2tzQ2FjaGUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrU2NvcGUuY2FsbCh0aGlzLCB7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogXCJnZXRtZXRhZGF0YVwiXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXNWYWxpZDogZnVuY3Rpb24gaXNWYWxpZCh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubWFza3NldCA9IHRoaXMubWFza3NldCB8fCBnZW5lcmF0ZU1hc2tTZXQodGhpcy5vcHRzLCB0aGlzLm5vTWFza3NDYWNoZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcImlzVmFsaWRcIixcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9ybWF0OiBmdW5jdGlvbiBmb3JtYXQodmFsdWUsIG1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tYXNrc2V0ID0gdGhpcy5tYXNrc2V0IHx8IGdlbmVyYXRlTWFza1NldCh0aGlzLm9wdHMsIHRoaXMubm9NYXNrc0NhY2hlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWFza1Njb3BlLmNhbGwodGhpcywge1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwiZm9ybWF0XCIsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IG1ldGFkYXRhXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0VmFsdWU6IGZ1bmN0aW9uIHNldFZhbHVlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzLmVsKS50cmlnZ2VyKFwic2V0dmFsdWVcIiwgWyB2YWx1ZSBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYW5hbHlzZU1hc2s6IGZ1bmN0aW9uIGFuYWx5c2VNYXNrKG1hc2ssIHJlZ2V4TWFzaywgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciB0b2tlbml6ZXIgPSAvKD86Wz8qK118XFx7WzAtOVxcK1xcKl0rKD86LFswLTlcXCtcXCpdKik/KD86XFx8WzAtOVxcK1xcKl0qKT9cXH0pfFteLj8qK14ke1tdKCl8XFxcXF0rfC4vZywgcmVnZXhUb2tlbml6ZXIgPSAvXFxbXFxeP10/KD86W15cXFxcXFxdXSt8XFxcXFtcXFNcXHNdPykqXT98XFxcXCg/OjAoPzpbMC0zXVswLTddezAsMn18WzQtN11bMC03XT8pP3xbMS05XVswLTldKnx4WzAtOUEtRmEtZl17Mn18dVswLTlBLUZhLWZdezR9fGNbQS1aYS16XXxbXFxTXFxzXT8pfFxcKCg/OlxcP1s6PSFdPyk/fCg/Ols/KitdfFxce1swLTldKyg/OixbMC05XSopP1xcfSlcXD8/fFteLj8qK14ke1soKXxcXFxcXSt8Li9nLCBlc2NhcGVkID0gZmFsc2UsIGN1cnJlbnRUb2tlbiA9IG5ldyBNYXNrVG9rZW4oKSwgbWF0Y2gsIG0sIG9wZW5lbmluZ3MgPSBbXSwgbWFza1Rva2VucyA9IFtdLCBvcGVuaW5nVG9rZW4sIGN1cnJlbnRPcGVuaW5nVG9rZW4sIGFsdGVybmF0b3IsIGxhc3RNYXRjaCwgZ3JvdXBUb2tlbjtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBNYXNrVG9rZW4oaXNHcm91cCwgaXNPcHRpb25hbCwgaXNRdWFudGlmaWVyLCBpc0FsdGVybmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXRjaGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3Blbkdyb3VwID0gaXNHcm91cCB8fCBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hbHRlcm5hdG9yR3JvdXAgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0dyb3VwID0gaXNHcm91cCB8fCBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc09wdGlvbmFsID0gaXNPcHRpb25hbCB8fCBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc1F1YW50aWZpZXIgPSBpc1F1YW50aWZpZXIgfHwgZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNBbHRlcm5hdG9yID0gaXNBbHRlcm5hdG9yIHx8IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnF1YW50aWZpZXIgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW46IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXg6IDFcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0VGVzdERlZmluaXRpb24obXRva2VuLCBlbGVtZW50LCBwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uICE9PSB1bmRlZmluZWQgPyBwb3NpdGlvbiA6IG10b2tlbi5tYXRjaGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZNYXRjaCA9IG10b2tlbi5tYXRjaGVzW3Bvc2l0aW9uIC0gMV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZWdleE1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmluZGV4T2YoXCJbXCIpID09PSAwIHx8IGVzY2FwZWQgJiYgL1xcXFxkfFxcXFxzfFxcXFx3XS9pLnRlc3QoZWxlbWVudCkgfHwgZWxlbWVudCA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdG9rZW4ubWF0Y2hlcy5zcGxpY2UocG9zaXRpb24rKywgMCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbjogbmV3IFJlZ0V4cChlbGVtZW50LCBvcHRzLmNhc2luZyA/IFwiaVwiIDogXCJcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsaXR5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3QmxvY2tNYXJrZXI6IHByZXZNYXRjaCA9PT0gdW5kZWZpbmVkID8gXCJtYXN0ZXJcIiA6IHByZXZNYXRjaC5kZWYgIT09IGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVEZWY6IGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVzY2FwZWQpIGVsZW1lbnQgPSBlbGVtZW50W2VsZW1lbnQubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKGVsZW1lbnQuc3BsaXQoXCJcIiksIGZ1bmN0aW9uKG5keCwgbG1udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2TWF0Y2ggPSBtdG9rZW4ubWF0Y2hlc1twb3NpdGlvbiAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdG9rZW4ubWF0Y2hlcy5zcGxpY2UocG9zaXRpb24rKywgMCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm46IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbGl0eTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja01hcmtlcjogcHJldk1hdGNoID09PSB1bmRlZmluZWQgPyBcIm1hc3RlclwiIDogcHJldk1hdGNoLmRlZiAhPT0gbG1udCAmJiBwcmV2TWF0Y2guZm4gIT09IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNpbmc6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWY6IG9wdHMuc3RhdGljRGVmaW5pdGlvblN5bWJvbCB8fCBsbW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IG9wdHMuc3RhdGljRGVmaW5pdGlvblN5bWJvbCAhPT0gdW5kZWZpbmVkID8gbG1udCA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdGl2ZURlZjogKGVzY2FwZWQgPyBcIidcIiA6IFwiXCIpICsgbG1udFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVzY2FwZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXNrZGVmID0gKG9wdHMuZGVmaW5pdGlvbnMgPyBvcHRzLmRlZmluaXRpb25zW2VsZW1lbnRdIDogdW5kZWZpbmVkKSB8fCBJbnB1dG1hc2sucHJvdG90eXBlLmRlZmluaXRpb25zW2VsZW1lbnRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tkZWYgJiYgIWVzY2FwZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdG9rZW4ubWF0Y2hlcy5zcGxpY2UocG9zaXRpb24rKywgMCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbjogbWFza2RlZi52YWxpZGF0b3IgPyB0eXBlb2YgbWFza2RlZi52YWxpZGF0b3IgPT0gXCJzdHJpbmdcIiA/IG5ldyBSZWdFeHAobWFza2RlZi52YWxpZGF0b3IsIG9wdHMuY2FzaW5nID8gXCJpXCIgOiBcIlwiKSA6IG5ldyBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGVzdCA9IG1hc2tkZWYudmFsaWRhdG9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KCkgOiBuZXcgUmVnRXhwKFwiLlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxpdHk6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja01hcmtlcjogcHJldk1hdGNoID09PSB1bmRlZmluZWQgPyBcIm1hc3RlclwiIDogcHJldk1hdGNoLmRlZiAhPT0gKG1hc2tkZWYuZGVmaW5pdGlvblN5bWJvbCB8fCBlbGVtZW50KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBtYXNrZGVmLmNhc2luZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBtYXNrZGVmLmRlZmluaXRpb25TeW1ib2wgfHwgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IG1hc2tkZWYucGxhY2Vob2xkZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdGl2ZURlZjogZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdG9rZW4ubWF0Y2hlcy5zcGxpY2UocG9zaXRpb24rKywgMCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbjogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxpdHk6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdCbG9ja01hcmtlcjogcHJldk1hdGNoID09PSB1bmRlZmluZWQgPyBcIm1hc3RlclwiIDogcHJldk1hdGNoLmRlZiAhPT0gZWxlbWVudCAmJiBwcmV2TWF0Y2guZm4gIT09IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2luZzogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmOiBvcHRzLnN0YXRpY0RlZmluaXRpb25TeW1ib2wgfHwgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IG9wdHMuc3RhdGljRGVmaW5pdGlvblN5bWJvbCAhPT0gdW5kZWZpbmVkID8gZWxlbWVudCA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF0aXZlRGVmOiAoZXNjYXBlZCA/IFwiJ1wiIDogXCJcIikgKyBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXNjYXBlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHZlcmlmeUdyb3VwTWFya2VyKG1hc2tUb2tlbikge1xuICAgICAgICAgICAgICAgICAgICBpZiAobWFza1Rva2VuICYmIG1hc2tUb2tlbi5tYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2gobWFza1Rva2VuLm1hdGNoZXMsIGZ1bmN0aW9uKG5keCwgdG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dFRva2VuID0gbWFza1Rva2VuLm1hdGNoZXNbbmR4ICsgMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChuZXh0VG9rZW4gPT09IHVuZGVmaW5lZCB8fCBuZXh0VG9rZW4ubWF0Y2hlcyA9PT0gdW5kZWZpbmVkIHx8IG5leHRUb2tlbi5pc1F1YW50aWZpZXIgPT09IGZhbHNlKSAmJiB0b2tlbiAmJiB0b2tlbi5pc0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuLmlzR3JvdXAgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFyZWdleE1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydFRlc3REZWZpbml0aW9uKHRva2VuLCBvcHRzLmdyb3VwbWFya2VyWzBdLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0b2tlbi5vcGVuR3JvdXAgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRUZXN0RGVmaW5pdGlvbih0b2tlbiwgb3B0cy5ncm91cG1hcmtlclsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyaWZ5R3JvdXBNYXJrZXIodG9rZW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gZGVmYXVsdENhc2UoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVuZW5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRPcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzW29wZW5lbmluZ3MubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRUZXN0RGVmaW5pdGlvbihjdXJyZW50T3BlbmluZ1Rva2VuLCBtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50T3BlbmluZ1Rva2VuLmlzQWx0ZXJuYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IgPSBvcGVuZW5pbmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG1uZHggPSAwOyBtbmR4IDwgYWx0ZXJuYXRvci5tYXRjaGVzLmxlbmd0aDsgbW5keCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHRlcm5hdG9yLm1hdGNoZXNbbW5keF0uaXNHcm91cCkgYWx0ZXJuYXRvci5tYXRjaGVzW21uZHhdLmlzR3JvdXAgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wZW5lbmluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuID0gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuLm1hdGNoZXMucHVzaChhbHRlcm5hdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wdXNoKGFsdGVybmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydFRlc3REZWZpbml0aW9uKGN1cnJlbnRUb2tlbiwgbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gcmV2ZXJzZVRva2VucyhtYXNrVG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gcmV2ZXJzZVN0YXRpYyhzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0ID09PSBvcHRzLm9wdGlvbmFsbWFya2VyWzBdKSBzdCA9IG9wdHMub3B0aW9uYWxtYXJrZXJbMV07IGVsc2UgaWYgKHN0ID09PSBvcHRzLm9wdGlvbmFsbWFya2VyWzFdKSBzdCA9IG9wdHMub3B0aW9uYWxtYXJrZXJbMF07IGVsc2UgaWYgKHN0ID09PSBvcHRzLmdyb3VwbWFya2VyWzBdKSBzdCA9IG9wdHMuZ3JvdXBtYXJrZXJbMV07IGVsc2UgaWYgKHN0ID09PSBvcHRzLmdyb3VwbWFya2VyWzFdKSBzdCA9IG9wdHMuZ3JvdXBtYXJrZXJbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3Q7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuLm1hdGNoZXMgPSBtYXNrVG9rZW4ubWF0Y2hlcy5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG1hdGNoIGluIG1hc2tUb2tlbi5tYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFza1Rva2VuLm1hdGNoZXMuaGFzT3duUHJvcGVydHkobWF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGludE1hdGNoID0gcGFyc2VJbnQobWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF0uaXNRdWFudGlmaWVyICYmIG1hc2tUb2tlbi5tYXRjaGVzW2ludE1hdGNoICsgMV0gJiYgbWFza1Rva2VuLm1hdGNoZXNbaW50TWF0Y2ggKyAxXS5pc0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBxdCA9IG1hc2tUb2tlbi5tYXRjaGVzW21hdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuLm1hdGNoZXMuc3BsaWNlKG1hdGNoLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuLm1hdGNoZXMuc3BsaWNlKGludE1hdGNoICsgMSwgMCwgcXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdLm1hdGNoZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF0gPSByZXZlcnNlVG9rZW5zKG1hc2tUb2tlbi5tYXRjaGVzW21hdGNoXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza1Rva2VuLm1hdGNoZXNbbWF0Y2hdID0gcmV2ZXJzZVN0YXRpYyhtYXNrVG9rZW4ubWF0Y2hlc1ttYXRjaF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFza1Rva2VuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBncm91cGlmeShtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBncm91cFRva2VuID0gbmV3IE1hc2tUb2tlbih0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBUb2tlbi5vcGVuR3JvdXAgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBUb2tlbi5tYXRjaGVzID0gbWF0Y2hlcztcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdyb3VwVG9rZW47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyZWdleE1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5vcHRpb25hbG1hcmtlclswXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5vcHRpb25hbG1hcmtlclsxXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gcmVnZXhNYXNrID8gcmVnZXhUb2tlbml6ZXIuZXhlYyhtYXNrKSA6IHRva2VuaXplci5leGVjKG1hc2spKSB7XG4gICAgICAgICAgICAgICAgICAgIG0gPSBtYXRjaFswXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlZ2V4TWFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtLmNoYXJBdCgwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiP1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG0gPSBcInswLDF9XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIitcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIipcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtID0gXCJ7XCIgKyBtICsgXCJ9XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGVzY2FwZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKG0uY2hhckF0KDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIig/PVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiKD8hXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCIoPzw9XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCIoPzwhXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5lc2NhcGVDaGFyOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXNjYXBlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVnZXhNYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdENhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBvcHRzLm9wdGlvbmFsbWFya2VyWzFdOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5ncm91cG1hcmtlclsxXTpcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wZW5pbmdUb2tlbiA9IG9wZW5lbmluZ3MucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcGVuaW5nVG9rZW4ub3Blbkdyb3VwID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3BlbmluZ1Rva2VuICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3BlbmVuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRPcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzW29wZW5lbmluZ3MubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRPcGVuaW5nVG9rZW4ubWF0Y2hlcy5wdXNoKG9wZW5pbmdUb2tlbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50T3BlbmluZ1Rva2VuLmlzQWx0ZXJuYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRvciA9IG9wZW5lbmluZ3MucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBtbmR4ID0gMDsgbW5keCA8IGFsdGVybmF0b3IubWF0Y2hlcy5sZW5ndGg7IG1uZHgrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IubWF0Y2hlc1ttbmR4XS5pc0dyb3VwID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRvci5tYXRjaGVzW21uZHhdLmFsdGVybmF0b3JHcm91cCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wZW5lbmluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRPcGVuaW5nVG9rZW4gPSBvcGVuZW5pbmdzW29wZW5lbmluZ3MubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudE9wZW5pbmdUb2tlbi5tYXRjaGVzLnB1c2goYWx0ZXJuYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRUb2tlbi5tYXRjaGVzLnB1c2goYWx0ZXJuYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50VG9rZW4ubWF0Y2hlcy5wdXNoKG9wZW5pbmdUb2tlbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGRlZmF1bHRDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5vcHRpb25hbG1hcmtlclswXTpcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wZW5lbmluZ3MucHVzaChuZXcgTWFza1Rva2VuKGZhbHNlLCB0cnVlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2Ugb3B0cy5ncm91cG1hcmtlclswXTpcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wZW5lbmluZ3MucHVzaChuZXcgTWFza1Rva2VuKHRydWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBvcHRzLnF1YW50aWZpZXJtYXJrZXJbMF06XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcXVhbnRpZmllciA9IG5ldyBNYXNrVG9rZW4oZmFsc2UsIGZhbHNlLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG0gPSBtLnJlcGxhY2UoL1t7fV0vZywgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbXFqID0gbS5zcGxpdChcInxcIiksIG1xID0gbXFqWzBdLnNwbGl0KFwiLFwiKSwgbXEwID0gaXNOYU4obXFbMF0pID8gbXFbMF0gOiBwYXJzZUludChtcVswXSksIG1xMSA9IG1xLmxlbmd0aCA9PT0gMSA/IG1xMCA6IGlzTmFOKG1xWzFdKSA/IG1xWzFdIDogcGFyc2VJbnQobXFbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1xMCA9PT0gXCIqXCIgfHwgbXEwID09PSBcIitcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1xMCA9IG1xMSA9PT0gXCIqXCIgPyAwIDogMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHF1YW50aWZpZXIucXVhbnRpZmllciA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW46IG1xMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXg6IG1xMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXQ6IG1xalsxXVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gb3BlbmVuaW5ncy5sZW5ndGggPiAwID8gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdLm1hdGNoZXMgOiBjdXJyZW50VG9rZW4ubWF0Y2hlcztcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gbWF0Y2hlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5pc0FsdGVybmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2gobWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMgPSBtYXRjaC5tYXRjaGVzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBncm91cFRva2VuID0gbmV3IE1hc2tUb2tlbih0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG1wTWF0Y2ggPSBtYXRjaGVzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMucHVzaChncm91cFRva2VuKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzID0gZ3JvdXBUb2tlbi5tYXRjaGVzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gdG1wTWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW1hdGNoLmlzR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IGdyb3VwaWZ5KFsgbWF0Y2ggXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2gobWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKHF1YW50aWZpZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIG9wdHMuYWx0ZXJuYXRvcm1hcmtlcjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBncm91cFF1YW50aWZpZXIgPSBmdW5jdGlvbiBncm91cFF1YW50aWZpZXIobWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsYXN0TWF0Y2ggPSBtYXRjaGVzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TWF0Y2guaXNRdWFudGlmaWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RNYXRjaCA9IGdyb3VwaWZ5KFsgbWF0Y2hlcy5wb3AoKSwgbGFzdE1hdGNoIF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbGFzdE1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcGVuZW5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T3BlbmluZ1Rva2VuID0gb3BlbmVuaW5nc1tvcGVuZW5pbmdzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzdWJUb2tlbiA9IGN1cnJlbnRPcGVuaW5nVG9rZW4ubWF0Y2hlc1tjdXJyZW50T3BlbmluZ1Rva2VuLm1hdGNoZXMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRPcGVuaW5nVG9rZW4ub3Blbkdyb3VwICYmIChzdWJUb2tlbi5tYXRjaGVzID09PSB1bmRlZmluZWQgfHwgc3ViVG9rZW4uaXNHcm91cCA9PT0gZmFsc2UgJiYgc3ViVG9rZW4uaXNBbHRlcm5hdG9yID09PSBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdE1hdGNoID0gb3BlbmVuaW5ncy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TWF0Y2ggPSBncm91cFF1YW50aWZpZXIoY3VycmVudE9wZW5pbmdUb2tlbi5tYXRjaGVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RNYXRjaCA9IGdyb3VwUXVhbnRpZmllcihjdXJyZW50VG9rZW4ubWF0Y2hlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdE1hdGNoLmlzQWx0ZXJuYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wZW5lbmluZ3MucHVzaChsYXN0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdE1hdGNoLmFsdGVybmF0b3JHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdG9yID0gb3BlbmVuaW5ncy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdE1hdGNoLmFsdGVybmF0b3JHcm91cCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0b3IgPSBuZXcgTWFza1Rva2VuKGZhbHNlLCBmYWxzZSwgZmFsc2UsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdG9yLm1hdGNoZXMucHVzaChsYXN0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wZW5lbmluZ3MucHVzaChhbHRlcm5hdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdE1hdGNoLm9wZW5Hcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TWF0Y2gub3Blbkdyb3VwID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRlcm5hdG9yR3JvdXAgPSBuZXcgTWFza1Rva2VuKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdG9yR3JvdXAuYWx0ZXJuYXRvckdyb3VwID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BlbmVuaW5ncy5wdXNoKGFsdGVybmF0b3JHcm91cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdENhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3aGlsZSAob3BlbmVuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wZW5pbmdUb2tlbiA9IG9wZW5lbmluZ3MucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRUb2tlbi5tYXRjaGVzLnB1c2gob3BlbmluZ1Rva2VuKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRUb2tlbi5tYXRjaGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmVyaWZ5R3JvdXBNYXJrZXIoY3VycmVudFRva2VuKTtcbiAgICAgICAgICAgICAgICAgICAgbWFza1Rva2Vucy5wdXNoKGN1cnJlbnRUb2tlbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChvcHRzLm51bWVyaWNJbnB1dCB8fCBvcHRzLmlzUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldmVyc2VUb2tlbnMobWFza1Rva2Vuc1swXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrVG9rZW5zO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBvc2l0aW9uQ29sb3JNYXNrOiBmdW5jdGlvbiBwb3NpdGlvbkNvbG9yTWFzayhpbnB1dCwgdGVtcGxhdGUpIHtcbiAgICAgICAgICAgICAgICBpbnB1dC5zdHlsZS5sZWZ0ID0gdGVtcGxhdGUub2Zmc2V0TGVmdCArIFwicHhcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLmV4dGVuZERlZmF1bHRzID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgSW5wdXRtYXNrLnByb3RvdHlwZS5kZWZhdWx0cywgb3B0aW9ucyk7XG4gICAgICAgIH07XG4gICAgICAgIElucHV0bWFzay5leHRlbmREZWZpbml0aW9ucyA9IGZ1bmN0aW9uKGRlZmluaXRpb24pIHtcbiAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIElucHV0bWFzay5wcm90b3R5cGUuZGVmaW5pdGlvbnMsIGRlZmluaXRpb24pO1xuICAgICAgICB9O1xuICAgICAgICBJbnB1dG1hc2suZXh0ZW5kQWxpYXNlcyA9IGZ1bmN0aW9uKGFsaWFzKSB7XG4gICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCBJbnB1dG1hc2sucHJvdG90eXBlLmFsaWFzZXMsIGFsaWFzKTtcbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLmZvcm1hdCA9IGZ1bmN0aW9uKHZhbHVlLCBvcHRpb25zLCBtZXRhZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIElucHV0bWFzayhvcHRpb25zKS5mb3JtYXQodmFsdWUsIG1ldGFkYXRhKTtcbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLnVubWFzayA9IGZ1bmN0aW9uKHZhbHVlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gSW5wdXRtYXNrKG9wdGlvbnMpLnVubWFza2VkdmFsdWUodmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICBJbnB1dG1hc2suaXNWYWxpZCA9IGZ1bmN0aW9uKHZhbHVlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gSW5wdXRtYXNrKG9wdGlvbnMpLmlzVmFsaWQodmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICBJbnB1dG1hc2sucmVtb3ZlID0gZnVuY3Rpb24oZWxlbXMpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZWxlbXMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBlbGVtcyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1zKSB8fCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGVsZW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsZW1zID0gZWxlbXMubm9kZU5hbWUgPyBbIGVsZW1zIF0gOiBlbGVtcztcbiAgICAgICAgICAgICQuZWFjaChlbGVtcywgZnVuY3Rpb24obmR4LCBlbCkge1xuICAgICAgICAgICAgICAgIGlmIChlbC5pbnB1dG1hc2spIGVsLmlucHV0bWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBJbnB1dG1hc2suc2V0VmFsdWUgPSBmdW5jdGlvbihlbGVtcywgdmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZWxlbXMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBlbGVtcyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1zKSB8fCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGVsZW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsZW1zID0gZWxlbXMubm9kZU5hbWUgPyBbIGVsZW1zIF0gOiBlbGVtcztcbiAgICAgICAgICAgICQuZWFjaChlbGVtcywgZnVuY3Rpb24obmR4LCBlbCkge1xuICAgICAgICAgICAgICAgIGlmIChlbC5pbnB1dG1hc2spIGVsLmlucHV0bWFzay5zZXRWYWx1ZSh2YWx1ZSk7IGVsc2UgJChlbCkudHJpZ2dlcihcInNldHZhbHVlXCIsIFsgdmFsdWUgXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4ID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgICAgICAgICB2YXIgc3BlY2lhbHMgPSBbIFwiL1wiLCBcIi5cIiwgXCIqXCIsIFwiK1wiLCBcIj9cIiwgXCJ8XCIsIFwiKFwiLCBcIilcIiwgXCJbXCIsIFwiXVwiLCBcIntcIiwgXCJ9XCIsIFwiXFxcXFwiLCBcIiRcIiwgXCJeXCIgXTtcbiAgICAgICAgICAgIHJldHVybiBzdHIucmVwbGFjZShuZXcgUmVnRXhwKFwiKFxcXFxcIiArIHNwZWNpYWxzLmpvaW4oXCJ8XFxcXFwiKSArIFwiKVwiLCBcImdpbVwiKSwgXCJcXFxcJDFcIik7XG4gICAgICAgIH07XG4gICAgICAgIElucHV0bWFzay5rZXlDb2RlID0ge1xuICAgICAgICAgICAgQkFDS1NQQUNFOiA4LFxuICAgICAgICAgICAgQkFDS1NQQUNFX1NBRkFSSTogMTI3LFxuICAgICAgICAgICAgREVMRVRFOiA0NixcbiAgICAgICAgICAgIERPV046IDQwLFxuICAgICAgICAgICAgRU5EOiAzNSxcbiAgICAgICAgICAgIEVOVEVSOiAxMyxcbiAgICAgICAgICAgIEVTQ0FQRTogMjcsXG4gICAgICAgICAgICBIT01FOiAzNixcbiAgICAgICAgICAgIElOU0VSVDogNDUsXG4gICAgICAgICAgICBMRUZUOiAzNyxcbiAgICAgICAgICAgIFBBR0VfRE9XTjogMzQsXG4gICAgICAgICAgICBQQUdFX1VQOiAzMyxcbiAgICAgICAgICAgIFJJR0hUOiAzOSxcbiAgICAgICAgICAgIFNQQUNFOiAzMixcbiAgICAgICAgICAgIFRBQjogOSxcbiAgICAgICAgICAgIFVQOiAzOCxcbiAgICAgICAgICAgIFg6IDg4LFxuICAgICAgICAgICAgQ09OVFJPTDogMTdcbiAgICAgICAgfTtcbiAgICAgICAgSW5wdXRtYXNrLmRlcGVuZGVuY3lMaWIgPSAkO1xuICAgICAgICBmdW5jdGlvbiByZXNvbHZlQWxpYXMoYWxpYXNTdHIsIG9wdGlvbnMsIG9wdHMpIHtcbiAgICAgICAgICAgIHZhciBhbGlhc0RlZmluaXRpb24gPSBJbnB1dG1hc2sucHJvdG90eXBlLmFsaWFzZXNbYWxpYXNTdHJdO1xuICAgICAgICAgICAgaWYgKGFsaWFzRGVmaW5pdGlvbikge1xuICAgICAgICAgICAgICAgIGlmIChhbGlhc0RlZmluaXRpb24uYWxpYXMpIHJlc29sdmVBbGlhcyhhbGlhc0RlZmluaXRpb24uYWxpYXMsIHVuZGVmaW5lZCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgb3B0cywgYWxpYXNEZWZpbml0aW9uKTtcbiAgICAgICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCBvcHRzLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0cy5tYXNrID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgb3B0cy5tYXNrID0gYWxpYXNTdHI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2VuZXJhdGVNYXNrU2V0KG9wdHMsIG5vY2FjaGUpIHtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGdlbmVyYXRlTWFzayhtYXNrLCBtZXRhZGF0YSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciByZWdleE1hc2sgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAobWFzayA9PT0gbnVsbCB8fCBtYXNrID09PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlZ2V4TWFzayA9IG9wdHMucmVnZXggIT09IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZWdleE1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgPSBvcHRzLnJlZ2V4O1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFzayA9IG1hc2sucmVwbGFjZSgvXihcXF4pKC4qKShcXCQpJC8sIFwiJDJcIik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWdleE1hc2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFzayA9IFwiLipcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWFzay5sZW5ndGggPT09IDEgJiYgb3B0cy5ncmVlZHkgPT09IGZhbHNlICYmIG9wdHMucmVwZWF0ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMucGxhY2Vob2xkZXIgPSBcIlwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAob3B0cy5yZXBlYXQgPiAwIHx8IG9wdHMucmVwZWF0ID09PSBcIipcIiB8fCBvcHRzLnJlcGVhdCA9PT0gXCIrXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlcGVhdFN0YXJ0ID0gb3B0cy5yZXBlYXQgPT09IFwiKlwiID8gMCA6IG9wdHMucmVwZWF0ID09PSBcIitcIiA/IDEgOiBvcHRzLnJlcGVhdDtcbiAgICAgICAgICAgICAgICAgICAgbWFzayA9IG9wdHMuZ3JvdXBtYXJrZXJbMF0gKyBtYXNrICsgb3B0cy5ncm91cG1hcmtlclsxXSArIG9wdHMucXVhbnRpZmllcm1hcmtlclswXSArIHJlcGVhdFN0YXJ0ICsgXCIsXCIgKyBvcHRzLnJlcGVhdCArIG9wdHMucXVhbnRpZmllcm1hcmtlclsxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIG1hc2tzZXREZWZpbml0aW9uLCBtYXNrZGVmS2V5ID0gcmVnZXhNYXNrID8gXCJyZWdleF9cIiArIG9wdHMucmVnZXggOiBvcHRzLm51bWVyaWNJbnB1dCA/IG1hc2suc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBtYXNrO1xuICAgICAgICAgICAgICAgIGlmIChJbnB1dG1hc2sucHJvdG90eXBlLm1hc2tzQ2FjaGVbbWFza2RlZktleV0gPT09IHVuZGVmaW5lZCB8fCBub2NhY2hlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tzZXREZWZpbml0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFzazogbWFzayxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUb2tlbjogSW5wdXRtYXNrLnByb3RvdHlwZS5hbmFseXNlTWFzayhtYXNrLCByZWdleE1hc2ssIG9wdHMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRQb3NpdGlvbnM6IHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgX2J1ZmZlcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXN0czoge30sXG4gICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlczoge30sXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogbWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrTGVuZ3RoOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBqaXRPZmZzZXQ6IHt9XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlmIChub2NhY2hlICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBJbnB1dG1hc2sucHJvdG90eXBlLm1hc2tzQ2FjaGVbbWFza2RlZktleV0gPSBtYXNrc2V0RGVmaW5pdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tzZXREZWZpbml0aW9uID0gJC5leHRlbmQodHJ1ZSwge30sIElucHV0bWFzay5wcm90b3R5cGUubWFza3NDYWNoZVttYXNrZGVmS2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgbWFza3NldERlZmluaXRpb24gPSAkLmV4dGVuZCh0cnVlLCB7fSwgSW5wdXRtYXNrLnByb3RvdHlwZS5tYXNrc0NhY2hlW21hc2tkZWZLZXldKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWFza3NldERlZmluaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbXM7XG4gICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMubWFzaykpIHtcbiAgICAgICAgICAgICAgICBvcHRzLm1hc2sgPSBvcHRzLm1hc2sob3B0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJC5pc0FycmF5KG9wdHMubWFzaykpIHtcbiAgICAgICAgICAgICAgICBpZiAob3B0cy5tYXNrLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMua2VlcFN0YXRpYyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5rZWVwU3RhdGljID0gXCJhdXRvXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9wdHMubWFzay5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm1hc2tbaV0uY2hhckF0KDApICE9PSBvcHRzLm1hc2tbMF0uY2hhckF0KDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMua2VlcFN0YXRpYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgYWx0TWFzayA9IG9wdHMuZ3JvdXBtYXJrZXJbMF07XG4gICAgICAgICAgICAgICAgICAgICQuZWFjaChvcHRzLmlzUlRMID8gb3B0cy5tYXNrLnJldmVyc2UoKSA6IG9wdHMubWFzaywgZnVuY3Rpb24obmR4LCBtc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHRNYXNrLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRNYXNrICs9IG9wdHMuZ3JvdXBtYXJrZXJbMV0gKyBvcHRzLmFsdGVybmF0b3JtYXJrZXIgKyBvcHRzLmdyb3VwbWFya2VyWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1zay5tYXNrICE9PSB1bmRlZmluZWQgJiYgISQuaXNGdW5jdGlvbihtc2subWFzaykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRNYXNrICs9IG1zay5tYXNrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRNYXNrICs9IG1zaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGFsdE1hc2sgKz0gb3B0cy5ncm91cG1hcmtlclsxXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdlbmVyYXRlTWFzayhhbHRNYXNrLCBvcHRzLm1hc2ssIG9wdHMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBvcHRzLm1hc2sgPSBvcHRzLm1hc2sucG9wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3B0cy5tYXNrICYmIG9wdHMubWFzay5tYXNrICE9PSB1bmRlZmluZWQgJiYgISQuaXNGdW5jdGlvbihvcHRzLm1hc2subWFzaykpIHtcbiAgICAgICAgICAgICAgICBtcyA9IGdlbmVyYXRlTWFzayhvcHRzLm1hc2subWFzaywgb3B0cy5tYXNrLCBvcHRzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbXMgPSBnZW5lcmF0ZU1hc2sob3B0cy5tYXNrLCBvcHRzLm1hc2ssIG9wdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1zO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGlzSW5wdXRFdmVudFN1cHBvcnRlZChldmVudE5hbWUpIHtcbiAgICAgICAgICAgIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiKSwgZXZOYW1lID0gXCJvblwiICsgZXZlbnROYW1lLCBpc1N1cHBvcnRlZCA9IGV2TmFtZSBpbiBlbDtcbiAgICAgICAgICAgIGlmICghaXNTdXBwb3J0ZWQpIHtcbiAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoZXZOYW1lLCBcInJldHVybjtcIik7XG4gICAgICAgICAgICAgICAgaXNTdXBwb3J0ZWQgPSB0eXBlb2YgZWxbZXZOYW1lXSA9PT0gXCJmdW5jdGlvblwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWwgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGlzU3VwcG9ydGVkO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIG1hc2tTY29wZShhY3Rpb25PYmosIG1hc2tzZXQsIG9wdHMpIHtcbiAgICAgICAgICAgIG1hc2tzZXQgPSBtYXNrc2V0IHx8IHRoaXMubWFza3NldDtcbiAgICAgICAgICAgIG9wdHMgPSBvcHRzIHx8IHRoaXMub3B0cztcbiAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzLCBlbCA9IHRoaXMuZWwsIGlzUlRMID0gdGhpcy5pc1JUTCwgdW5kb1ZhbHVlLCAkZWwsIHNraXBLZXlQcmVzc0V2ZW50ID0gZmFsc2UsIHNraXBJbnB1dEV2ZW50ID0gZmFsc2UsIGlnbm9yYWJsZSA9IGZhbHNlLCBtYXhMZW5ndGgsIG1vdXNlRW50ZXIgPSBmYWxzZSwgY29sb3JNYXNrLCBvcmlnaW5hbFBsYWNlaG9sZGVyO1xuICAgICAgICAgICAgdmFyIGdldE1hc2tUZW1wbGF0ZSA9IGZ1bmN0aW9uIGdldE1hc2tUZW1wbGF0ZShiYXNlT25JbnB1dCwgbWluaW1hbFBvcywgaW5jbHVkZU1vZGUsIG5vSml0LCBjbGVhck9wdGlvbmFsVGFpbCkge1xuICAgICAgICAgICAgICAgIHZhciBncmVlZHkgPSBvcHRzLmdyZWVkeTtcbiAgICAgICAgICAgICAgICBpZiAoY2xlYXJPcHRpb25hbFRhaWwpIG9wdHMuZ3JlZWR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgbWluaW1hbFBvcyA9IG1pbmltYWxQb3MgfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgbWFza1RlbXBsYXRlID0gW10sIG5keEludGx6ciwgcG9zID0gMCwgdGVzdCwgdGVzdFBvcywgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24oKTtcbiAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChiYXNlT25JbnB1dCA9PT0gdHJ1ZSAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IGNsZWFyT3B0aW9uYWxUYWlsICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdLm1hdGNoLm9wdGlvbmFsaXR5ID09PSB0cnVlICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MgKyAxXSA9PT0gdW5kZWZpbmVkICYmIChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXS5nZW5lcmF0ZWRJbnB1dCA9PT0gdHJ1ZSB8fCBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXS5pbnB1dCA9PSBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIgJiYgcG9zID4gMCkgPyBkZXRlcm1pbmVUZXN0VGVtcGxhdGUocG9zLCBnZXRUZXN0cyhwb3MsIG5keEludGx6ciwgcG9zIC0gMSkpIDogZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc107XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gdGVzdFBvcy5tYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5keEludGx6ciA9IHRlc3RQb3MubG9jYXRvci5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFza1RlbXBsYXRlLnB1c2goaW5jbHVkZU1vZGUgPT09IHRydWUgPyB0ZXN0UG9zLmlucHV0IDogaW5jbHVkZU1vZGUgPT09IGZhbHNlID8gdGVzdC5uYXRpdmVEZWYgOiBnZXRQbGFjZWhvbGRlcihwb3MsIHRlc3QpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RQb3MgPSBnZXRUZXN0VGVtcGxhdGUocG9zLCBuZHhJbnRsenIsIHBvcyAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9IHRlc3RQb3MubWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBqaXRNYXNraW5nID0gbm9KaXQgPT09IHRydWUgPyBmYWxzZSA6IG9wdHMuaml0TWFza2luZyAhPT0gZmFsc2UgPyBvcHRzLmppdE1hc2tpbmcgOiB0ZXN0LmppdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChqaXRNYXNraW5nID09PSBmYWxzZSB8fCBqaXRNYXNraW5nID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIGppdE1hc2tpbmcgPT09IFwibnVtYmVyXCIgJiYgaXNGaW5pdGUoaml0TWFza2luZykgJiYgaml0TWFza2luZyA+IHBvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUZW1wbGF0ZS5wdXNoKGluY2x1ZGVNb2RlID09PSBmYWxzZSA/IHRlc3QubmF0aXZlRGVmIDogZ2V0UGxhY2Vob2xkZXIocG9zLCB0ZXN0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMua2VlcFN0YXRpYyA9PT0gXCJhdXRvXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0Lm5ld0Jsb2NrTWFya2VyICYmIHRlc3QuZm4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmtlZXBTdGF0aWMgPSBwb3MgLSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHBvcysrO1xuICAgICAgICAgICAgICAgIH0gd2hpbGUgKChtYXhMZW5ndGggPT09IHVuZGVmaW5lZCB8fCBwb3MgPCBtYXhMZW5ndGgpICYmICh0ZXN0LmZuICE9PSBudWxsIHx8IHRlc3QuZGVmICE9PSBcIlwiKSB8fCBtaW5pbWFsUG9zID4gcG9zKTtcbiAgICAgICAgICAgICAgICBpZiAobWFza1RlbXBsYXRlW21hc2tUZW1wbGF0ZS5sZW5ndGggLSAxXSA9PT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICBtYXNrVGVtcGxhdGUucG9wKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpbmNsdWRlTW9kZSAhPT0gZmFsc2UgfHwgZ2V0TWFza1NldCgpLm1hc2tMZW5ndGggPT09IHVuZGVmaW5lZCkgZ2V0TWFza1NldCgpLm1hc2tMZW5ndGggPSBwb3MgLSAxO1xuICAgICAgICAgICAgICAgIG9wdHMuZ3JlZWR5ID0gZ3JlZWR5O1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXNrVGVtcGxhdGU7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0TWFza1NldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWFza3NldDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlc2V0TWFza1NldChzb2Z0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hc2tzZXQgPSBnZXRNYXNrU2V0KCk7XG4gICAgICAgICAgICAgICAgbWFza3NldC5idWZmZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgaWYgKHNvZnQgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbWFza3NldC52YWxpZFBvc2l0aW9ucyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBtYXNrc2V0LnAgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldExhc3RWYWxpZFBvc2l0aW9uKGNsb3Nlc3RUbywgc3RyaWN0LCB2YWxpZFBvc2l0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBiZWZvcmUgPSAtMSwgYWZ0ZXIgPSAtMSwgdmFsaWRzID0gdmFsaWRQb3NpdGlvbnMgfHwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zO1xuICAgICAgICAgICAgICAgIGlmIChjbG9zZXN0VG8gPT09IHVuZGVmaW5lZCkgY2xvc2VzdFRvID0gLTE7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcG9zTmR4IGluIHZhbGlkcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHNOZHggPSBwYXJzZUludChwb3NOZHgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsaWRzW3BzTmR4XSAmJiAoc3RyaWN0IHx8IHZhbGlkc1twc05keF0uZ2VuZXJhdGVkSW5wdXQgIT09IHRydWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHNOZHggPD0gY2xvc2VzdFRvKSBiZWZvcmUgPSBwc05keDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwc05keCA+PSBjbG9zZXN0VG8pIGFmdGVyID0gcHNOZHg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJlZm9yZSA9PT0gLTEgfHwgYmVmb3JlID09IGNsb3Nlc3RUbyA/IGFmdGVyIDogYWZ0ZXIgPT0gLTEgPyBiZWZvcmUgOiBjbG9zZXN0VG8gLSBiZWZvcmUgPCBhZnRlciAtIGNsb3Nlc3RUbyA/IGJlZm9yZSA6IGFmdGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0RGVjaXNpb25UYWtlcih0c3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGVjaXNpb25UYWtlciA9IHRzdC5sb2NhdG9yW3RzdC5hbHRlcm5hdGlvbl07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkZWNpc2lvblRha2VyID09IFwic3RyaW5nXCIgJiYgZGVjaXNpb25UYWtlci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlY2lzaW9uVGFrZXIgPSBkZWNpc2lvblRha2VyLnNwbGl0KFwiLFwiKVswXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRlY2lzaW9uVGFrZXIgIT09IHVuZGVmaW5lZCA/IGRlY2lzaW9uVGFrZXIudG9TdHJpbmcoKSA6IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRMb2NhdG9yKHRzdCwgYWxpZ24pIHtcbiAgICAgICAgICAgICAgICB2YXIgbG9jYXRvciA9ICh0c3QuYWx0ZXJuYXRpb24gIT0gdW5kZWZpbmVkID8gdHN0Lm1sb2NbZ2V0RGVjaXNpb25UYWtlcih0c3QpXSA6IHRzdC5sb2NhdG9yKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgIGlmIChsb2NhdG9yICE9PSBcIlwiKSB3aGlsZSAobG9jYXRvci5sZW5ndGggPCBhbGlnbikge1xuICAgICAgICAgICAgICAgICAgICBsb2NhdG9yICs9IFwiMFwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbG9jYXRvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRldGVybWluZVRlc3RUZW1wbGF0ZShwb3MsIHRlc3RzKSB7XG4gICAgICAgICAgICAgICAgcG9zID0gcG9zID4gMCA/IHBvcyAtIDEgOiAwO1xuICAgICAgICAgICAgICAgIHZhciBhbHRUZXN0ID0gZ2V0VGVzdChwb3MpLCB0YXJnZXRMb2NhdG9yID0gZ2V0TG9jYXRvcihhbHRUZXN0KSwgdHN0TG9jYXRvciwgY2xvc2VzdCwgYmVzdE1hdGNoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIG5keCA9IDA7IG5keCA8IHRlc3RzLmxlbmd0aDsgbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRzdCA9IHRlc3RzW25keF07XG4gICAgICAgICAgICAgICAgICAgIHRzdExvY2F0b3IgPSBnZXRMb2NhdG9yKHRzdCwgdGFyZ2V0TG9jYXRvci5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGlzdGFuY2UgPSBNYXRoLmFicyh0c3RMb2NhdG9yIC0gdGFyZ2V0TG9jYXRvcik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjbG9zZXN0ID09PSB1bmRlZmluZWQgfHwgdHN0TG9jYXRvciAhPT0gXCJcIiAmJiBkaXN0YW5jZSA8IGNsb3Nlc3QgfHwgYmVzdE1hdGNoICYmICFvcHRzLmdyZWVkeSAmJiBiZXN0TWF0Y2gubWF0Y2gub3B0aW9uYWxpdHkgJiYgYmVzdE1hdGNoLm1hdGNoLm5ld0Jsb2NrTWFya2VyID09PSBcIm1hc3RlclwiICYmICghdHN0Lm1hdGNoLm9wdGlvbmFsaXR5IHx8ICF0c3QubWF0Y2gubmV3QmxvY2tNYXJrZXIpIHx8IGJlc3RNYXRjaCAmJiBiZXN0TWF0Y2gubWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyICYmICF0c3QubWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9zZXN0ID0gZGlzdGFuY2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSB0c3Q7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJlc3RNYXRjaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFRlc3RUZW1wbGF0ZShwb3MsIG5keEludGx6ciwgdHN0UHMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10gfHwgZGV0ZXJtaW5lVGVzdFRlbXBsYXRlKHBvcywgZ2V0VGVzdHMocG9zLCBuZHhJbnRsenIgPyBuZHhJbnRsenIuc2xpY2UoKSA6IG5keEludGx6ciwgdHN0UHMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFRlc3QocG9zLCB0ZXN0cykge1xuICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiAodGVzdHMgfHwgZ2V0VGVzdHMocG9zKSlbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBwb3NpdGlvbkNhbk1hdGNoRGVmaW5pdGlvbihwb3MsIGRlZikge1xuICAgICAgICAgICAgICAgIHZhciB2YWxpZCA9IGZhbHNlLCB0ZXN0cyA9IGdldFRlc3RzKHBvcyk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgdG5keCA9IDA7IHRuZHggPCB0ZXN0cy5sZW5ndGg7IHRuZHgrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGVzdHNbdG5keF0ubWF0Y2ggJiYgdGVzdHNbdG5keF0ubWF0Y2guZGVmID09PSBkZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB2YWxpZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFRlc3RzKHBvcywgbmR4SW50bHpyLCB0c3RQcykge1xuICAgICAgICAgICAgICAgIHZhciBtYXNrVG9rZW5zID0gZ2V0TWFza1NldCgpLm1hc2tUb2tlbiwgdGVzdFBvcyA9IG5keEludGx6ciA/IHRzdFBzIDogMCwgbmR4SW5pdGlhbGl6ZXIgPSBuZHhJbnRsenIgPyBuZHhJbnRsenIuc2xpY2UoKSA6IFsgMCBdLCBtYXRjaGVzID0gW10sIGluc2VydFN0b3AgPSBmYWxzZSwgbGF0ZXN0TWF0Y2gsIGNhY2hlRGVwZW5kZW5jeSA9IG5keEludGx6ciA/IG5keEludGx6ci5qb2luKFwiXCIpIDogXCJcIjtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiByZXNvbHZlVGVzdEZyb21Ub2tlbihtYXNrVG9rZW4sIG5keEluaXRpYWxpemVyLCBsb29wTmR4LCBxdWFudGlmaWVyUmVjdXJzZSkge1xuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVNYXRjaChtYXRjaCwgbG9vcE5keCwgcXVhbnRpZmllclJlY3Vyc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzRmlyc3RNYXRjaChsYXRlc3RNYXRjaCwgdG9rZW5Hcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBmaXJzdE1hdGNoID0gJC5pbkFycmF5KGxhdGVzdE1hdGNoLCB0b2tlbkdyb3VwLm1hdGNoZXMpID09PSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZmlyc3RNYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2godG9rZW5Hcm91cC5tYXRjaGVzLCBmdW5jdGlvbihuZHgsIG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2guaXNRdWFudGlmaWVyID09PSB0cnVlKSBmaXJzdE1hdGNoID0gaXNGaXJzdE1hdGNoKGxhdGVzdE1hdGNoLCB0b2tlbkdyb3VwLm1hdGNoZXNbbmR4IC0gMV0pOyBlbHNlIGlmIChtYXRjaC5oYXNPd25Qcm9wZXJ0eShcIm1hdGNoZXNcIikpIGZpcnN0TWF0Y2ggPSBpc0ZpcnN0TWF0Y2gobGF0ZXN0TWF0Y2gsIG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaXJzdE1hdGNoKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmlyc3RNYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJlc29sdmVOZHhJbml0aWFsaXplcihwb3MsIGFsdGVybmF0ZU5keCwgdGFyZ2V0QWx0ZXJuYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYmVzdE1hdGNoLCBpbmRleFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnRlc3RzW3Bvc10gfHwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKGdldE1hc2tTZXQoKS50ZXN0c1twb3NdIHx8IFsgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10gXSwgZnVuY3Rpb24obmR4LCBsbW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobG1udC5tbG9jW2FsdGVybmF0ZU5keF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSBsbW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhbHRlcm5hdGlvbiA9IHRhcmdldEFsdGVybmF0aW9uICE9PSB1bmRlZmluZWQgPyB0YXJnZXRBbHRlcm5hdGlvbiA6IGxtbnQuYWx0ZXJuYXRpb24sIG5keFBvcyA9IGxtbnQubG9jYXRvclthbHRlcm5hdGlvbl0gIT09IHVuZGVmaW5lZCA/IGxtbnQubG9jYXRvclthbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5pbmRleE9mKGFsdGVybmF0ZU5keCkgOiAtMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoaW5kZXhQb3MgPT09IHVuZGVmaW5lZCB8fCBuZHhQb3MgPCBpbmRleFBvcykgJiYgbmR4UG9zICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlc3RNYXRjaCA9IGxtbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhQb3MgPSBuZHhQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmVzdE1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBiZXN0TWF0Y2hBbHRJbmRleCA9IGJlc3RNYXRjaC5sb2NhdG9yW2Jlc3RNYXRjaC5hbHRlcm5hdGlvbl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsb2NhdG9yID0gYmVzdE1hdGNoLm1sb2NbYWx0ZXJuYXRlTmR4XSB8fCBiZXN0TWF0Y2gubWxvY1tiZXN0TWF0Y2hBbHRJbmRleF0gfHwgYmVzdE1hdGNoLmxvY2F0b3I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBsb2NhdG9yLnNsaWNlKCh0YXJnZXRBbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkID8gdGFyZ2V0QWx0ZXJuYXRpb24gOiBiZXN0TWF0Y2guYWx0ZXJuYXRpb24pICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldEFsdGVybmF0aW9uICE9PSB1bmRlZmluZWQgPyByZXNvbHZlTmR4SW5pdGlhbGl6ZXIocG9zLCBhbHRlcm5hdGVOZHgpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzU3Vic2V0T2Yoc291cmNlLCB0YXJnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBleHBhbmQocGF0dGVybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXhwYW5kZWQgPSBbXSwgc3RhcnQsIGVuZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBwYXR0ZXJuLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhdHRlcm4uY2hhckF0KGkpID09PSBcIi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IHBhdHRlcm4uY2hhckNvZGVBdChpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCsrc3RhcnQgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWQucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKHN0YXJ0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IHBhdHRlcm4uY2hhckNvZGVBdChpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBhbmRlZC5wdXNoKHBhdHRlcm4uY2hhckF0KGkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXhwYW5kZWQuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmVnZXggJiYgc291cmNlLm1hdGNoLmZuICE9PSBudWxsICYmIHRhcmdldC5tYXRjaC5mbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXhwYW5kKHRhcmdldC5tYXRjaC5kZWYucmVwbGFjZSgvW1xcW1xcXV0vZywgXCJcIikpLmluZGV4T2YoZXhwYW5kKHNvdXJjZS5tYXRjaC5kZWYucmVwbGFjZSgvW1xcW1xcXV0vZywgXCJcIikpKSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzb3VyY2UubWF0Y2guZGVmID09PSB0YXJnZXQubWF0Y2gubmF0aXZlRGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gc3RhdGljQ2FuTWF0Y2hEZWZpbml0aW9uKHNvdXJjZSwgdGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHNsb2MgPSBzb3VyY2UubG9jYXRvci5zbGljZShzb3VyY2UuYWx0ZXJuYXRpb24pLmpvaW4oXCJcIiksIHRsb2MgPSB0YXJnZXQubG9jYXRvci5zbGljZSh0YXJnZXQuYWx0ZXJuYXRpb24pLmpvaW4oXCJcIiksIGNhbk1hdGNoID0gc2xvYyA9PSB0bG9jO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbk1hdGNoID0gY2FuTWF0Y2ggJiYgc291cmNlLm1hdGNoLmZuID09PSBudWxsICYmIHRhcmdldC5tYXRjaC5mbiAhPT0gbnVsbCA/IHRhcmdldC5tYXRjaC5mbi50ZXN0KHNvdXJjZS5tYXRjaC5kZWYsIGdldE1hc2tTZXQoKSwgcG9zLCBmYWxzZSwgb3B0cywgZmFsc2UpIDogZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbk1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gc2V0TWVyZ2VMb2NhdG9ycyh0YXJnZXRNYXRjaCwgYWx0TWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWx0TWF0Y2ggPT09IHVuZGVmaW5lZCB8fCB0YXJnZXRNYXRjaC5hbHRlcm5hdGlvbiA9PT0gYWx0TWF0Y2guYWx0ZXJuYXRpb24gJiYgdGFyZ2V0TWF0Y2gubG9jYXRvclt0YXJnZXRNYXRjaC5hbHRlcm5hdGlvbl0udG9TdHJpbmcoKS5pbmRleE9mKGFsdE1hdGNoLmxvY2F0b3JbYWx0TWF0Y2guYWx0ZXJuYXRpb25dKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TWF0Y2gubWxvYyA9IHRhcmdldE1hdGNoLm1sb2MgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsb2NOZHggPSB0YXJnZXRNYXRjaC5sb2NhdG9yW3RhcmdldE1hdGNoLmFsdGVybmF0aW9uXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxvY05keCA9PT0gdW5kZWZpbmVkKSB0YXJnZXRNYXRjaC5hbHRlcm5hdGlvbiA9IHVuZGVmaW5lZDsgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGxvY05keCA9PT0gXCJzdHJpbmdcIikgbG9jTmR4ID0gbG9jTmR4LnNwbGl0KFwiLFwiKVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0YXJnZXRNYXRjaC5tbG9jW2xvY05keF0gPT09IHVuZGVmaW5lZCkgdGFyZ2V0TWF0Y2gubWxvY1tsb2NOZHhdID0gdGFyZ2V0TWF0Y2gubG9jYXRvci5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsdE1hdGNoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBuZHggaW4gYWx0TWF0Y2gubWxvYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG5keCA9PT0gXCJzdHJpbmdcIikgbmR4ID0gbmR4LnNwbGl0KFwiLFwiKVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRhcmdldE1hdGNoLm1sb2NbbmR4XSA9PT0gdW5kZWZpbmVkKSB0YXJnZXRNYXRjaC5tbG9jW25keF0gPSBhbHRNYXRjaC5tbG9jW25keF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldE1hdGNoLmxvY2F0b3JbdGFyZ2V0TWF0Y2guYWx0ZXJuYXRpb25dID0gT2JqZWN0LmtleXModGFyZ2V0TWF0Y2gubWxvYykuam9pbihcIixcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVzdFBvcyA+IDUwMCAmJiBxdWFudGlmaWVyUmVjdXJzZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJJbnB1dG1hc2s6IFRoZXJlIGlzIHByb2JhYmx5IGFuIGVycm9yIGluIHlvdXIgbWFzayBkZWZpbml0aW9uIG9yIGluIHRoZSBjb2RlLiBDcmVhdGUgYW4gaXNzdWUgb24gZ2l0aHViIHdpdGggYW4gZXhhbXBsZSBvZiB0aGUgbWFzayB5b3UgYXJlIHVzaW5nLiBcIiArIGdldE1hc2tTZXQoKS5tYXNrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RQb3MgPT09IHBvcyAmJiBtYXRjaC5tYXRjaGVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaDogbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2F0b3I6IGxvb3BOZHgucmV2ZXJzZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZDogY2FjaGVEZXBlbmRlbmN5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtbG9jOiB7fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaC5tYXRjaGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2guaXNHcm91cCAmJiBxdWFudGlmaWVyUmVjdXJzZSAhPT0gbWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBoYW5kbGVNYXRjaChtYXNrVG9rZW4ubWF0Y2hlc1skLmluQXJyYXkobWF0Y2gsIG1hc2tUb2tlbi5tYXRjaGVzKSArIDFdLCBsb29wTmR4LCBxdWFudGlmaWVyUmVjdXJzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaC5pc09wdGlvbmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvcHRpb25hbFRva2VuID0gbWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gcmVzb2x2ZVRlc3RGcm9tVG9rZW4obWF0Y2gsIG5keEluaXRpYWxpemVyLCBsb29wTmR4LCBxdWFudGlmaWVyUmVjdXJzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKG1hdGNoZXMsIGZ1bmN0aW9uKG5keCwgbXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG10Y2gubWF0Y2gub3B0aW9uYWxpdHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRlc3RNYXRjaCA9IG1hdGNoZXNbbWF0Y2hlcy5sZW5ndGggLSAxXS5tYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChxdWFudGlmaWVyUmVjdXJzZSA9PT0gdW5kZWZpbmVkICYmIGlzRmlyc3RNYXRjaChsYXRlc3RNYXRjaCwgb3B0aW9uYWxUb2tlbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRTdG9wID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0UG9zID0gcG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXRjaC5pc0FsdGVybmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdGVybmF0ZVRva2VuID0gbWF0Y2gsIG1hbHRlcm5hdGVNYXRjaGVzID0gW10sIG1hbHRNYXRjaGVzLCBjdXJyZW50TWF0Y2hlcyA9IG1hdGNoZXMuc2xpY2UoKSwgbG9vcE5keENudCA9IGxvb3BOZHgubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWx0SW5kZXggPSBuZHhJbml0aWFsaXplci5sZW5ndGggPiAwID8gbmR4SW5pdGlhbGl6ZXIuc2hpZnQoKSA6IC0xO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWx0SW5kZXggPT09IC0xIHx8IHR5cGVvZiBhbHRJbmRleCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRQb3MgPSB0ZXN0UG9zLCBuZHhJbml0aWFsaXplckNsb25lID0gbmR4SW5pdGlhbGl6ZXIuc2xpY2UoKSwgYWx0SW5kZXhBcnIgPSBbXSwgYW1uZHg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFsdEluZGV4ID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRJbmRleEFyciA9IGFsdEluZGV4LnNwbGl0KFwiLFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChhbW5keCA9IDA7IGFtbmR4IDwgYWx0ZXJuYXRlVG9rZW4ubWF0Y2hlcy5sZW5ndGg7IGFtbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0SW5kZXhBcnIucHVzaChhbW5keC50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW3Bvc10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWx0SW5kZXhBcnJDbG9uZSA9IGFsdEluZGV4QXJyLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGVsID0gZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW3Bvc10ubGVuZ3RoOyBpIDwgZWw7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRJbmRleEFyci5zcGxpY2UoYWx0SW5kZXhBcnIuaW5kZXhPZihnZXRNYXNrU2V0KCkuZXhjbHVkZXNbcG9zXVtpXS50b1N0cmluZygpKSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHRJbmRleEFyci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW3Bvc10gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdEluZGV4QXJyID0gYWx0SW5kZXhBcnJDbG9uZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5rZWVwU3RhdGljID09PSB0cnVlIHx8IGlzRmluaXRlKHBhcnNlSW50KG9wdHMua2VlcFN0YXRpYykpICYmIGN1cnJlbnRQb3MgPj0gb3B0cy5rZWVwU3RhdGljKSBhbHRJbmRleEFyciA9IGFsdEluZGV4QXJyLnNsaWNlKDAsIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHVuTWF0Y2hlZEFsdGVybmF0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBuZHggPSAwOyBuZHggPCBhbHRJbmRleEFyci5sZW5ndGg7IG5keCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW1uZHggPSBwYXJzZUludChhbHRJbmRleEFycltuZHhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmR4SW5pdGlhbGl6ZXIgPSB0eXBlb2YgYWx0SW5kZXggPT09IFwic3RyaW5nXCIgPyByZXNvbHZlTmR4SW5pdGlhbGl6ZXIodGVzdFBvcywgYW1uZHgsIGxvb3BOZHhDbnQpIHx8IG5keEluaXRpYWxpemVyQ2xvbmUuc2xpY2UoKSA6IG5keEluaXRpYWxpemVyQ2xvbmUuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWx0ZXJuYXRlVG9rZW4ubWF0Y2hlc1thbW5keF0gJiYgaGFuZGxlTWF0Y2goYWx0ZXJuYXRlVG9rZW4ubWF0Y2hlc1thbW5keF0sIFsgYW1uZHggXS5jb25jYXQobG9vcE5keCksIHF1YW50aWZpZXJSZWN1cnNlKSkgbWF0Y2ggPSB0cnVlOyBlbHNlIGlmIChuZHggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5NYXRjaGVkQWx0ZXJuYXRpb24gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWx0TWF0Y2hlcyA9IG1hdGNoZXMuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0UG9zID0gY3VycmVudFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbmR4MSA9IDA7IG5keDEgPCBtYWx0TWF0Y2hlcy5sZW5ndGg7IG5keDErKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWx0TWF0Y2ggPSBtYWx0TWF0Y2hlc1tuZHgxXSwgZHJvcE1hdGNoID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdE1hdGNoLm1hdGNoLmppdCA9IGFsdE1hdGNoLm1hdGNoLmppdCB8fCB1bk1hdGNoZWRBbHRlcm5hdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0TWF0Y2guYWx0ZXJuYXRpb24gPSBhbHRNYXRjaC5hbHRlcm5hdGlvbiB8fCBsb29wTmR4Q250O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRNZXJnZUxvY2F0b3JzKGFsdE1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbmR4MiA9IDA7IG5keDIgPCBtYWx0ZXJuYXRlTWF0Y2hlcy5sZW5ndGg7IG5keDIrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFsdE1hdGNoMiA9IG1hbHRlcm5hdGVNYXRjaGVzW25keDJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhbHRJbmRleCAhPT0gXCJzdHJpbmdcIiB8fCBhbHRNYXRjaC5hbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkICYmICQuaW5BcnJheShhbHRNYXRjaC5sb2NhdG9yW2FsdE1hdGNoLmFsdGVybmF0aW9uXS50b1N0cmluZygpLCBhbHRJbmRleEFycikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsdE1hdGNoLm1hdGNoLm5hdGl2ZURlZiA9PT0gYWx0TWF0Y2gyLm1hdGNoLm5hdGl2ZURlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wTWF0Y2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRNZXJnZUxvY2F0b3JzKGFsdE1hdGNoMiwgYWx0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzU3Vic2V0T2YoYWx0TWF0Y2gsIGFsdE1hdGNoMikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNldE1lcmdlTG9jYXRvcnMoYWx0TWF0Y2gsIGFsdE1hdGNoMikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BNYXRjaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWx0ZXJuYXRlTWF0Y2hlcy5zcGxpY2UobWFsdGVybmF0ZU1hdGNoZXMuaW5kZXhPZihhbHRNYXRjaDIpLCAwLCBhbHRNYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1N1YnNldE9mKGFsdE1hdGNoMiwgYWx0TWF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldE1lcmdlTG9jYXRvcnMoYWx0TWF0Y2gyLCBhbHRNYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdGljQ2FuTWF0Y2hEZWZpbml0aW9uKGFsdE1hdGNoLCBhbHRNYXRjaDIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXRNZXJnZUxvY2F0b3JzKGFsdE1hdGNoLCBhbHRNYXRjaDIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wTWF0Y2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsdGVybmF0ZU1hdGNoZXMuc3BsaWNlKG1hbHRlcm5hdGVNYXRjaGVzLmluZGV4T2YoYWx0TWF0Y2gyKSwgMCwgYWx0TWF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRyb3BNYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsdGVybmF0ZU1hdGNoZXMucHVzaChhbHRNYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzID0gY3VycmVudE1hdGNoZXMuY29uY2F0KG1hbHRlcm5hdGVNYXRjaGVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RQb3MgPSBwb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRTdG9wID0gbWF0Y2hlcy5sZW5ndGggPiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBtYWx0ZXJuYXRlTWF0Y2hlcy5sZW5ndGggPiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmR4SW5pdGlhbGl6ZXIgPSBuZHhJbml0aWFsaXplckNsb25lLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBtYXRjaCA9IGhhbmRsZU1hdGNoKGFsdGVybmF0ZVRva2VuLm1hdGNoZXNbYWx0SW5kZXhdIHx8IG1hc2tUb2tlbi5tYXRjaGVzW2FsdEluZGV4XSwgWyBhbHRJbmRleCBdLmNvbmNhdChsb29wTmR4KSwgcXVhbnRpZmllclJlY3Vyc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2guaXNRdWFudGlmaWVyICYmIHF1YW50aWZpZXJSZWN1cnNlICE9PSBtYXNrVG9rZW4ubWF0Y2hlc1skLmluQXJyYXkobWF0Y2gsIG1hc2tUb2tlbi5tYXRjaGVzKSAtIDFdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBxdCA9IG1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBxbmR4ID0gbmR4SW5pdGlhbGl6ZXIubGVuZ3RoID4gMCA/IG5keEluaXRpYWxpemVyLnNoaWZ0KCkgOiAwOyBxbmR4IDwgKGlzTmFOKHF0LnF1YW50aWZpZXIubWF4KSA/IHFuZHggKyAxIDogcXQucXVhbnRpZmllci5tYXgpICYmIHRlc3RQb3MgPD0gcG9zOyBxbmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0b2tlbkdyb3VwID0gbWFza1Rva2VuLm1hdGNoZXNbJC5pbkFycmF5KHF0LCBtYXNrVG9rZW4ubWF0Y2hlcykgLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gaGFuZGxlTWF0Y2godG9rZW5Hcm91cCwgWyBxbmR4IF0uY29uY2F0KGxvb3BOZHgpLCB0b2tlbkdyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdGVzdE1hdGNoID0gbWF0Y2hlc1ttYXRjaGVzLmxlbmd0aCAtIDFdLm1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdGVzdE1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciA9IHFuZHggPj0gcXQucXVhbnRpZmllci5taW47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0ZXN0TWF0Y2guaml0ID0gKHFuZHggfHwgMSkgKiB0b2tlbkdyb3VwLm1hdGNoZXMuaW5kZXhPZihsYXRlc3RNYXRjaCkgPj0gcXQucXVhbnRpZmllci5qaXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhdGVzdE1hdGNoLm9wdGlvbmFsUXVhbnRpZmllciAmJiBpc0ZpcnN0TWF0Y2gobGF0ZXN0TWF0Y2gsIHRva2VuR3JvdXApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydFN0b3AgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0UG9zID0gcG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhdGVzdE1hdGNoLmppdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkuaml0T2Zmc2V0W3Bvc10gPSB0b2tlbkdyb3VwLm1hdGNoZXMuaW5kZXhPZihsYXRlc3RNYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSByZXNvbHZlVGVzdEZyb21Ub2tlbihtYXRjaCwgbmR4SW5pdGlhbGl6ZXIsIGxvb3BOZHgsIHF1YW50aWZpZXJSZWN1cnNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RQb3MrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciB0bmR4ID0gbmR4SW5pdGlhbGl6ZXIubGVuZ3RoID4gMCA/IG5keEluaXRpYWxpemVyLnNoaWZ0KCkgOiAwOyB0bmR4IDwgbWFza1Rva2VuLm1hdGNoZXMubGVuZ3RoOyB0bmR4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrVG9rZW4ubWF0Y2hlc1t0bmR4XS5pc1F1YW50aWZpZXIgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2ggPSBoYW5kbGVNYXRjaChtYXNrVG9rZW4ubWF0Y2hlc1t0bmR4XSwgWyB0bmR4IF0uY29uY2F0KGxvb3BOZHgpLCBxdWFudGlmaWVyUmVjdXJzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoICYmIHRlc3RQb3MgPT09IHBvcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0ZXN0UG9zID4gcG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBtZXJnZUxvY2F0b3JzKHBvcywgdGVzdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxvY2F0b3IgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkLmlzQXJyYXkodGVzdHMpKSB0ZXN0cyA9IFsgdGVzdHMgXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0c1swXS5hbHRlcm5hdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYXRvciA9IGRldGVybWluZVRlc3RUZW1wbGF0ZShwb3MsIHRlc3RzLnNsaWNlKCkpLmxvY2F0b3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobG9jYXRvci5sZW5ndGggPT09IDApIGxvY2F0b3IgPSB0ZXN0c1swXS5sb2NhdG9yLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaCh0ZXN0cywgZnVuY3Rpb24obmR4LCB0c3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRzdC5kZWYgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsb2NhdG9yLmxlbmd0aCA9PT0gMCkgbG9jYXRvciA9IHRzdC5sb2NhdG9yLnNsaWNlKCk7IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9jYXRvci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHN0LmxvY2F0b3JbaV0gJiYgbG9jYXRvcltpXS50b1N0cmluZygpLmluZGV4T2YodHN0LmxvY2F0b3JbaV0pID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYXRvcltpXSArPSBcIixcIiArIHRzdC5sb2NhdG9yW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxvY2F0b3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwb3MgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobmR4SW50bHpyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1BvcyA9IHBvcyAtIDEsIHRlc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoKHRlc3QgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcHJldmlvdXNQb3NdIHx8IGdldE1hc2tTZXQoKS50ZXN0c1twcmV2aW91c1Bvc10pID09PSB1bmRlZmluZWQgJiYgcHJldmlvdXNQb3MgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzUG9zLS07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVzdCAhPT0gdW5kZWZpbmVkICYmIHByZXZpb3VzUG9zID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZHhJbml0aWFsaXplciA9IG1lcmdlTG9jYXRvcnMocHJldmlvdXNQb3MsIHRlc3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlRGVwZW5kZW5jeSA9IG5keEluaXRpYWxpemVyLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IHByZXZpb3VzUG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkudGVzdHNbcG9zXSAmJiBnZXRNYXNrU2V0KCkudGVzdHNbcG9zXVswXS5jZCA9PT0gY2FjaGVEZXBlbmRlbmN5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TWFza1NldCgpLnRlc3RzW3Bvc107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbXRuZHggPSBuZHhJbml0aWFsaXplci5zaGlmdCgpOyBtdG5keCA8IG1hc2tUb2tlbnMubGVuZ3RoOyBtdG5keCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2ggPSByZXNvbHZlVGVzdEZyb21Ub2tlbihtYXNrVG9rZW5zW210bmR4XSwgbmR4SW5pdGlhbGl6ZXIsIFsgbXRuZHggXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2ggJiYgdGVzdFBvcyA9PT0gcG9zIHx8IHRlc3RQb3MgPiBwb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWF0Y2hlcy5sZW5ndGggPT09IDAgfHwgaW5zZXJ0U3RvcCkge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2g6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbjogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbGl0eTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzaW5nOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZjogXCJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvY2F0b3I6IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWxvYzoge30sXG4gICAgICAgICAgICAgICAgICAgICAgICBjZDogY2FjaGVEZXBlbmRlbmN5XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobmR4SW50bHpyICE9PSB1bmRlZmluZWQgJiYgZ2V0TWFza1NldCgpLnRlc3RzW3Bvc10pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHRydWUsIFtdLCBtYXRjaGVzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnRlc3RzW3Bvc10gPSAkLmV4dGVuZCh0cnVlLCBbXSwgbWF0Y2hlcyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldE1hc2tTZXQoKS50ZXN0c1twb3NdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0QnVmZmVyVGVtcGxhdGUoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS5fYnVmZmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLl9idWZmZXIgPSBnZXRNYXNrVGVtcGxhdGUoZmFsc2UsIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLmJ1ZmZlciA9PT0gdW5kZWZpbmVkKSBnZXRNYXNrU2V0KCkuYnVmZmVyID0gZ2V0TWFza1NldCgpLl9idWZmZXIuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldE1hc2tTZXQoKS5fYnVmZmVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0QnVmZmVyKG5vQ2FjaGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLmJ1ZmZlciA9PT0gdW5kZWZpbmVkIHx8IG5vQ2FjaGUgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLmJ1ZmZlciA9IGdldE1hc2tUZW1wbGF0ZSh0cnVlLCBnZXRMYXN0VmFsaWRQb3NpdGlvbigpLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS5fYnVmZmVyID09PSB1bmRlZmluZWQpIGdldE1hc2tTZXQoKS5fYnVmZmVyID0gZ2V0TWFza1NldCgpLmJ1ZmZlci5zbGljZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TWFza1NldCgpLmJ1ZmZlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlZnJlc2hGcm9tQnVmZmVyKHN0YXJ0LCBlbmQsIGJ1ZmZlcikge1xuICAgICAgICAgICAgICAgIHZhciBpLCBwO1xuICAgICAgICAgICAgICAgIGlmIChzdGFydCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBlbmQgPSBidWZmZXIubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcCA9IHN0YXJ0O1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzZXRNYXNrU2V0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYnVmZmVyW2ldICE9PSBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWxSZXN1bHQgPSBpc1ZhbGlkKHAsIGJ1ZmZlcltpXSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsUmVzdWx0ICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwID0gdmFsUmVzdWx0LmNhcmV0ICE9PSB1bmRlZmluZWQgPyB2YWxSZXN1bHQuY2FyZXQgOiB2YWxSZXN1bHQucG9zICsgMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNhc2luZyhlbGVtLCB0ZXN0LCBwb3MpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKG9wdHMuY2FzaW5nIHx8IHRlc3QuY2FzaW5nKSB7XG4gICAgICAgICAgICAgICAgICBjYXNlIFwidXBwZXJcIjpcbiAgICAgICAgICAgICAgICAgICAgZWxlbSA9IGVsZW0udG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJsb3dlclwiOlxuICAgICAgICAgICAgICAgICAgICBlbGVtID0gZWxlbS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcInRpdGxlXCI6XG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3NCZWZvcmUgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zIC0gMV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChwb3MgPT09IDAgfHwgcG9zQmVmb3JlICYmIHBvc0JlZm9yZS5pbnB1dCA9PT0gU3RyaW5nLmZyb21DaGFyQ29kZShJbnB1dG1hc2sua2V5Q29kZS5TUEFDRSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0gPSBlbGVtLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtID0gZWxlbS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMuY2FzaW5nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJncy5wdXNoKGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtID0gb3B0cy5jYXNpbmcuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja0FsdGVybmF0aW9uTWF0Y2goYWx0QXJyMSwgYWx0QXJyMiwgbmEpIHtcbiAgICAgICAgICAgICAgICB2YXIgYWx0QXJyQyA9IG9wdHMuZ3JlZWR5ID8gYWx0QXJyMiA6IGFsdEFycjIuc2xpY2UoMCwgMSksIGlzTWF0Y2ggPSBmYWxzZSwgbmFBcnIgPSBuYSAhPT0gdW5kZWZpbmVkID8gbmEuc3BsaXQoXCIsXCIpIDogW10sIG5hTmR4O1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFBcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChuYU5keCA9IGFsdEFycjEuaW5kZXhPZihuYUFycltpXSkpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWx0QXJyMS5zcGxpY2UobmFOZHgsIDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFsbmR4ID0gMDsgYWxuZHggPCBhbHRBcnIxLmxlbmd0aDsgYWxuZHgrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoJC5pbkFycmF5KGFsdEFycjFbYWxuZHhdLCBhbHRBcnJDKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzTWF0Y2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzTWF0Y2g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBhbHRlcm5hdGUocG9zLCBjLCBzdHJpY3QsIGZyb21TZXRWYWxpZCwgckFsdFBvcykge1xuICAgICAgICAgICAgICAgIHZhciB2YWxpZFBzQ2xvbmUgPSAkLmV4dGVuZCh0cnVlLCB7fSwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zKSwgbGFzdEFsdCwgYWx0ZXJuYXRpb24sIGlzVmFsaWRSc2x0ID0gZmFsc2UsIGFsdFBvcywgcHJldkFsdFBvcywgaSwgdmFsaWRQb3MsIGRlY2lzaW9uUG9zLCBsQWx0UG9zID0gckFsdFBvcyAhPT0gdW5kZWZpbmVkID8gckFsdFBvcyA6IGdldExhc3RWYWxpZFBvc2l0aW9uKCk7XG4gICAgICAgICAgICAgICAgaWYgKGxBbHRQb3MgPT09IC0xICYmIHJBbHRQb3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBsYXN0QWx0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgcHJldkFsdFBvcyA9IGdldFRlc3QobGFzdEFsdCk7XG4gICAgICAgICAgICAgICAgICAgIGFsdGVybmF0aW9uID0gcHJldkFsdFBvcy5hbHRlcm5hdGlvbjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKDtsQWx0UG9zID49IDA7IGxBbHRQb3MtLSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWx0UG9zID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2xBbHRQb3NdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsdFBvcyAmJiBhbHRQb3MuYWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcmV2QWx0UG9zICYmIHByZXZBbHRQb3MubG9jYXRvclthbHRQb3MuYWx0ZXJuYXRpb25dICE9PSBhbHRQb3MubG9jYXRvclthbHRQb3MuYWx0ZXJuYXRpb25dKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0QWx0ID0gbEFsdFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdGlvbiA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tsYXN0QWx0XS5hbHRlcm5hdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2QWx0UG9zID0gYWx0UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhbHRlcm5hdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlY2lzaW9uUG9zID0gcGFyc2VJbnQobGFzdEFsdCk7XG4gICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5leGNsdWRlc1tkZWNpc2lvblBvc10gPSBnZXRNYXNrU2V0KCkuZXhjbHVkZXNbZGVjaXNpb25Qb3NdIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocG9zICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkuZXhjbHVkZXNbZGVjaXNpb25Qb3NdLnB1c2goZ2V0RGVjaXNpb25UYWtlcihwcmV2QWx0UG9zKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbGlkSW5wdXRzQ2xvbmUgPSBbXSwgc3RhdGljSW5wdXRzQmVmb3JlUG9zID0gMDtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gZGVjaXNpb25Qb3M7IGkgPCBnZXRMYXN0VmFsaWRQb3NpdGlvbih1bmRlZmluZWQsIHRydWUpICsgMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZFBvcyA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxpZFBvcyAmJiB2YWxpZFBvcy5nZW5lcmF0ZWRJbnB1dCAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkSW5wdXRzQ2xvbmUucHVzaCh2YWxpZFBvcy5pbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGkgPCBwb3MpIHN0YXRpY0lucHV0c0JlZm9yZVBvcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXSAmJiBnZXRNYXNrU2V0KCkuZXhjbHVkZXNbZGVjaXNpb25Qb3NdLmxlbmd0aCA8IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcG9zT2Zmc2V0ID0gc3RhdGljSW5wdXRzQmVmb3JlUG9zICogLTEsIHZhbGlkSW5wdXRzID0gdmFsaWRJbnB1dHNDbG9uZS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnRlc3RzW2RlY2lzaW9uUG9zXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWRSc2x0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlICh2YWxpZElucHV0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdmFsaWRJbnB1dHMuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShpc1ZhbGlkUnNsdCA9IGlzVmFsaWQoZ2V0TGFzdFZhbGlkUG9zaXRpb24odW5kZWZpbmVkLCB0cnVlKSArIDEsIGlucHV0LCBmYWxzZSwgZnJvbVNldFZhbGlkLCB0cnVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRSc2x0ICYmIGMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0YXJnZXRMdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbihwb3MpICsgMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSBkZWNpc2lvblBvczsgaSA8IGdldExhc3RWYWxpZFBvc2l0aW9uKCkgKyAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRQb3MgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodmFsaWRQb3MgPT09IHVuZGVmaW5lZCB8fCB2YWxpZFBvcy5tYXRjaC5mbiA9PSBudWxsKSAmJiBpIDwgcG9zICsgcG9zT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NPZmZzZXQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MgPSBwb3MgKyBwb3NPZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZFJzbHQgPSBpc1ZhbGlkKHBvcyA+IHRhcmdldEx2cCA/IHRhcmdldEx2cCA6IHBvcywgYywgc3RyaWN0LCBmcm9tU2V0VmFsaWQsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkUnNsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZBbHRQb3MgPSBnZXRUZXN0KGRlY2lzaW9uUG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgdmFsaWRQc0Nsb25lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGVjaXNpb25UYWtlciA9IGdldERlY2lzaW9uVGFrZXIocHJldkFsdFBvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkuZXhjbHVkZXNbZGVjaXNpb25Qb3NdLmluZGV4T2YoZGVjaXNpb25UYWtlcikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkUnNsdCA9IGFsdGVybmF0ZShwb3MsIGMsIHN0cmljdCwgZnJvbVNldFZhbGlkLCBkZWNpc2lvblBvcyAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXS5wdXNoKGRlY2lzaW9uVGFrZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSBkZWNpc2lvblBvczsgaSA8IGdldExhc3RWYWxpZFBvc2l0aW9uKHVuZGVmaW5lZCwgdHJ1ZSkgKyAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkUnNsdCA9IGFsdGVybmF0ZShwb3MsIGMsIHN0cmljdCwgZnJvbVNldFZhbGlkLCBkZWNpc2lvblBvcyAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLmV4Y2x1ZGVzW2RlY2lzaW9uUG9zXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWYWxpZFJzbHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZhbGlkKHBvcywgYywgc3RyaWN0LCBmcm9tU2V0VmFsaWQsIGZyb21BbHRlcm5hdGUsIHZhbGlkYXRlT25seSkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzU2VsZWN0aW9uKHBvc09iaikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNSVEwgPyBwb3NPYmouYmVnaW4gLSBwb3NPYmouZW5kID4gMSB8fCBwb3NPYmouYmVnaW4gLSBwb3NPYmouZW5kID09PSAxIDogcG9zT2JqLmVuZCAtIHBvc09iai5iZWdpbiA+IDEgfHwgcG9zT2JqLmVuZCAtIHBvc09iai5iZWdpbiA9PT0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3RyaWN0ID0gc3RyaWN0ID09PSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBtYXNrUG9zID0gcG9zO1xuICAgICAgICAgICAgICAgIGlmIChwb3MuYmVnaW4gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBtYXNrUG9zID0gaXNSVEwgPyBwb3MuZW5kIDogcG9zLmJlZ2luO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfaXNWYWxpZChwb3NpdGlvbiwgYywgc3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByc2x0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICQuZWFjaChnZXRUZXN0cyhwb3NpdGlvbiksIGZ1bmN0aW9uKG5keCwgdHN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdCA9IHRzdC5tYXRjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldEJ1ZmZlcih0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJzbHQgPSB0ZXN0LmZuICE9IG51bGwgPyB0ZXN0LmZuLnRlc3QoYywgZ2V0TWFza1NldCgpLCBwb3NpdGlvbiwgc3RyaWN0LCBvcHRzLCBpc1NlbGVjdGlvbihwb3MpKSA6IChjID09PSB0ZXN0LmRlZiB8fCBjID09PSBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIpICYmIHRlc3QuZGVmICE9PSBcIlwiID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IGdldFBsYWNlaG9sZGVyKHBvc2l0aW9uLCB0ZXN0LCB0cnVlKSB8fCB0ZXN0LmRlZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB9IDogZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocnNsdCAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZWxlbSA9IHJzbHQuYyAhPT0gdW5kZWZpbmVkID8gcnNsdC5jIDogYywgdmFsaWRhdGVkUG9zID0gcG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbSA9IGVsZW0gPT09IG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlciAmJiB0ZXN0LmZuID09PSBudWxsID8gZ2V0UGxhY2Vob2xkZXIocG9zaXRpb24sIHRlc3QsIHRydWUpIHx8IHRlc3QuZGVmIDogZWxlbTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocnNsdC5yZW1vdmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISQuaXNBcnJheShyc2x0LnJlbW92ZSkpIHJzbHQucmVtb3ZlID0gWyByc2x0LnJlbW92ZSBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2gocnNsdC5yZW1vdmUuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYiAtIGE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLCBmdW5jdGlvbihuZHgsIGxtbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldmFsaWRhdGVNYXNrKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogbG1udCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IGxtbnQgKyAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyc2x0Lmluc2VydCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghJC5pc0FycmF5KHJzbHQuaW5zZXJ0KSkgcnNsdC5pbnNlcnQgPSBbIHJzbHQuaW5zZXJ0IF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChyc2x0Lmluc2VydC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhIC0gYjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksIGZ1bmN0aW9uKG5keCwgbG1udCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZChsbW50LnBvcywgbG1udC5jLCB0cnVlLCBmcm9tU2V0VmFsaWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJzbHQgIT09IHRydWUgJiYgcnNsdC5wb3MgIT09IHVuZGVmaW5lZCAmJiByc2x0LnBvcyAhPT0gcG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGVkUG9zID0gcnNsdC5wb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyc2x0ICE9PSB0cnVlICYmIHJzbHQucG9zID09PSB1bmRlZmluZWQgJiYgcnNsdC5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXJldmFsaWRhdGVNYXNrKHBvcywgJC5leHRlbmQoe30sIHRzdCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dDogY2FzaW5nKGVsZW0sIHRlc3QsIHZhbGlkYXRlZFBvcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgZnJvbVNldFZhbGlkLCB2YWxpZGF0ZWRQb3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJzbHQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJzbHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB0cnVlLCBwb3NpdGlvbnNDbG9uZSA9ICQuZXh0ZW5kKHRydWUsIHt9LCBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnMpO1xuICAgICAgICAgICAgICAgIGlmICgkLmlzRnVuY3Rpb24ob3B0cy5wcmVWYWxpZGF0aW9uKSAmJiAhc3RyaWN0ICYmIGZyb21TZXRWYWxpZCAhPT0gdHJ1ZSAmJiB2YWxpZGF0ZU9ubHkgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gb3B0cy5wcmVWYWxpZGF0aW9uKGdldEJ1ZmZlcigpLCBtYXNrUG9zLCBjLCBpc1NlbGVjdGlvbihwb3MpLCBvcHRzLCBnZXRNYXNrU2V0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNrYmFja1Bvc2l0aW9ucyh1bmRlZmluZWQsIG1hc2tQb3MsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWF4TGVuZ3RoID09PSB1bmRlZmluZWQgfHwgbWFza1BvcyA8IG1heExlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gX2lzVmFsaWQobWFza1BvcywgYywgc3RyaWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoIXN0cmljdCB8fCBmcm9tU2V0VmFsaWQgPT09IHRydWUpICYmIHJlc3VsdCA9PT0gZmFsc2UgJiYgdmFsaWRhdGVPbmx5ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRQb3NWYWxpZCA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1ttYXNrUG9zXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudFBvc1ZhbGlkICYmIGN1cnJlbnRQb3NWYWxpZC5tYXRjaC5mbiA9PT0gbnVsbCAmJiAoY3VycmVudFBvc1ZhbGlkLm1hdGNoLmRlZiA9PT0gYyB8fCBjID09PSBvcHRzLnNraXBPcHRpb25hbFBhcnRDaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBzZWVrTmV4dChtYXNrUG9zKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgob3B0cy5pbnNlcnRNb2RlIHx8IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tzZWVrTmV4dChtYXNrUG9zKV0gPT09IHVuZGVmaW5lZCkgJiYgKCFpc01hc2sobWFza1BvcywgdHJ1ZSkgfHwgZ2V0TWFza1NldCgpLmppdE9mZnNldFttYXNrUG9zXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkuaml0T2Zmc2V0W21hc2tQb3NdICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tzZWVrTmV4dChtYXNrUG9zKV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGlzVmFsaWQobWFza1BvcyArIGdldE1hc2tTZXQoKS5qaXRPZmZzZXRbbWFza1Bvc10sIGMsIHN0cmljdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gZmFsc2UpIHJlc3VsdC5jYXJldCA9IG1hc2tQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgZm9yICh2YXIgblBvcyA9IG1hc2tQb3MgKyAxLCBzblBvcyA9IHNlZWtOZXh0KG1hc2tQb3MpOyBuUG9zIDw9IHNuUG9zOyBuUG9zKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBfaXNWYWxpZChuUG9zLCBjLCBzdHJpY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRyYWNrYmFja1Bvc2l0aW9ucyhtYXNrUG9zLCByZXN1bHQucG9zICE9PSB1bmRlZmluZWQgPyByZXN1bHQucG9zIDogblBvcykgfHwgcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrUG9zID0gblBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IGZhbHNlICYmIG9wdHMua2VlcFN0YXRpYyAhPT0gZmFsc2UgJiYgKG9wdHMucmVnZXggPT0gbnVsbCB8fCBpc0NvbXBsZXRlKGdldEJ1ZmZlcigpKSkgJiYgIXN0cmljdCAmJiBmcm9tQWx0ZXJuYXRlICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBhbHRlcm5hdGUobWFza1BvcywgYywgc3RyaWN0LCBmcm9tU2V0VmFsaWQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IG1hc2tQb3NcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCQuaXNGdW5jdGlvbihvcHRzLnBvc3RWYWxpZGF0aW9uKSAmJiByZXN1bHQgIT09IGZhbHNlICYmICFzdHJpY3QgJiYgZnJvbVNldFZhbGlkICE9PSB0cnVlICYmIHZhbGlkYXRlT25seSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcG9zdFJlc3VsdCA9IG9wdHMucG9zdFZhbGlkYXRpb24oZ2V0QnVmZmVyKHRydWUpLCBwb3MuYmVnaW4gIT09IHVuZGVmaW5lZCA/IGlzUlRMID8gcG9zLmVuZCA6IHBvcy5iZWdpbiA6IHBvcywgcmVzdWx0LCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvc3RSZXN1bHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvc3RSZXN1bHQucmVmcmVzaEZyb21CdWZmZXIgJiYgcG9zdFJlc3VsdC5idWZmZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVmcmVzaCA9IHBvc3RSZXN1bHQucmVmcmVzaEZyb21CdWZmZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXIocmVmcmVzaCA9PT0gdHJ1ZSA/IHJlZnJlc2ggOiByZWZyZXNoLnN0YXJ0LCByZWZyZXNoLmVuZCwgcG9zdFJlc3VsdC5idWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcG9zdFJlc3VsdCA9PT0gdHJ1ZSA/IHJlc3VsdCA6IHBvc3RSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAmJiByZXN1bHQucG9zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnBvcyA9IG1hc2tQb3M7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IGZhbHNlIHx8IHZhbGlkYXRlT25seSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXNldE1hc2tTZXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIHt9LCBwb3NpdGlvbnNDbG9uZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFja2JhY2tQb3NpdGlvbnMob3JpZ2luYWxQb3MsIG5ld1BvcywgZmlsbE9ubHkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0O1xuICAgICAgICAgICAgICAgIGlmIChvcmlnaW5hbFBvcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAob3JpZ2luYWxQb3MgPSBuZXdQb3MgLSAxOyBvcmlnaW5hbFBvcyA+IDA7IG9yaWdpbmFsUG9zLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbb3JpZ2luYWxQb3NdKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcyA9IG9yaWdpbmFsUG9zOyBwcyA8IG5ld1BvczsgcHMrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3BzXSA9PT0gdW5kZWZpbmVkICYmICFpc01hc2socHMsIHRydWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdnAgPSBwcyA9PSAwID8gZ2V0VGVzdChwcykgOiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcHMgLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ZXN0cyA9IGdldFRlc3RzKHBzKS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0c1t0ZXN0cy5sZW5ndGggLSAxXS5tYXRjaC5kZWYgPT09IFwiXCIpIHRlc3RzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBiZXN0TWF0Y2ggPSBkZXRlcm1pbmVUZXN0VGVtcGxhdGUocHMsIHRlc3RzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSAkLmV4dGVuZCh7fSwgYmVzdE1hdGNoLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0OiBnZXRQbGFjZWhvbGRlcihwcywgYmVzdE1hdGNoLm1hdGNoLCB0cnVlKSB8fCBiZXN0TWF0Y2gubWF0Y2guZGVmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVzdE1hdGNoLmdlbmVyYXRlZElucHV0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXZhbGlkYXRlTWFzayhwcywgYmVzdE1hdGNoLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmlsbE9ubHkgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN2cElucHV0ID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW25ld1Bvc10uaW5wdXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tuZXdQb3NdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBpc1ZhbGlkKG5ld1BvcywgY3ZwSW5wdXQsIHRydWUsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gcmV2YWxpZGF0ZU1hc2socG9zLCB2YWxpZFRlc3QsIGZyb21TZXRWYWxpZCwgdmFsaWRhdGVkUG9zKSB7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSXNFbmNsb3NlZFN0YXRpYyhwb3MsIHZhbGlkcywgc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3NNYXRjaCA9IHZhbGlkc1twb3NdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocG9zTWF0Y2ggIT09IHVuZGVmaW5lZCAmJiAocG9zTWF0Y2gubWF0Y2guZm4gPT09IG51bGwgJiYgcG9zTWF0Y2gubWF0Y2gub3B0aW9uYWxpdHkgIT09IHRydWUgfHwgcG9zTWF0Y2guaW5wdXQgPT09IG9wdHMucmFkaXhQb2ludCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcmV2TWF0Y2ggPSBzZWxlY3Rpb24uYmVnaW4gPD0gcG9zIC0gMSA/IHZhbGlkc1twb3MgLSAxXSAmJiB2YWxpZHNbcG9zIC0gMV0ubWF0Y2guZm4gPT09IG51bGwgJiYgdmFsaWRzW3BvcyAtIDFdIDogdmFsaWRzW3BvcyAtIDFdLCBuZXh0TWF0Y2ggPSBzZWxlY3Rpb24uZW5kID4gcG9zICsgMSA/IHZhbGlkc1twb3MgKyAxXSAmJiB2YWxpZHNbcG9zICsgMV0ubWF0Y2guZm4gPT09IG51bGwgJiYgdmFsaWRzW3BvcyArIDFdIDogdmFsaWRzW3BvcyArIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByZXZNYXRjaCAmJiBuZXh0TWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgYmVnaW4gPSBwb3MuYmVnaW4gIT09IHVuZGVmaW5lZCA/IHBvcy5iZWdpbiA6IHBvcywgZW5kID0gcG9zLmVuZCAhPT0gdW5kZWZpbmVkID8gcG9zLmVuZCA6IHBvcztcbiAgICAgICAgICAgICAgICBpZiAocG9zLmJlZ2luID4gcG9zLmVuZCkge1xuICAgICAgICAgICAgICAgICAgICBiZWdpbiA9IHBvcy5lbmQ7XG4gICAgICAgICAgICAgICAgICAgIGVuZCA9IHBvcy5iZWdpbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFsaWRhdGVkUG9zID0gdmFsaWRhdGVkUG9zICE9PSB1bmRlZmluZWQgPyB2YWxpZGF0ZWRQb3MgOiBiZWdpbjtcbiAgICAgICAgICAgICAgICBpZiAoYmVnaW4gIT09IGVuZCB8fCBvcHRzLmluc2VydE1vZGUgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3ZhbGlkYXRlZFBvc10gIT09IHVuZGVmaW5lZCAmJiBmcm9tU2V0VmFsaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcG9zaXRpb25zQ2xvbmUgPSAkLmV4dGVuZCh0cnVlLCB7fSwgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zKSwgbHZwID0gZ2V0TGFzdFZhbGlkUG9zaXRpb24odW5kZWZpbmVkLCB0cnVlKSwgaTtcbiAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnAgPSBiZWdpbjtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gbHZwOyBpID49IGJlZ2luOyBpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV0gJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW2ldLm1hdGNoLm5hdGl2ZURlZiA9PT0gXCIrXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmlzTmVnYXRpdmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbGlkID0gdHJ1ZSwgaiA9IHZhbGlkYXRlZFBvcywgdnBzID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zLCBuZWVkc1ZhbGlkYXRpb24gPSBmYWxzZSwgcG9zTWF0Y2ggPSBqLCBpID0gajtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbGlkVGVzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3ZhbGlkYXRlZFBvc10gPSAkLmV4dGVuZCh0cnVlLCB7fSwgdmFsaWRUZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc01hdGNoKys7XG4gICAgICAgICAgICAgICAgICAgICAgICBqKys7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmVnaW4gPCBlbmQpIGkrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3IgKDtpIDw9IGx2cDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdCA9IHBvc2l0aW9uc0Nsb25lW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHQgIT09IHVuZGVmaW5lZCAmJiAoaSA+PSBlbmQgfHwgaSA+PSBiZWdpbiAmJiB0LmdlbmVyYXRlZElucHV0ICE9PSB0cnVlICYmIElzRW5jbG9zZWRTdGF0aWMoaSwgcG9zaXRpb25zQ2xvbmUsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogYmVnaW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBlbmRcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChnZXRUZXN0KHBvc01hdGNoKS5tYXRjaC5kZWYgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5lZWRzVmFsaWRhdGlvbiA9PT0gZmFsc2UgJiYgcG9zaXRpb25zQ2xvbmVbcG9zTWF0Y2hdICYmIHBvc2l0aW9uc0Nsb25lW3Bvc01hdGNoXS5tYXRjaC5uYXRpdmVEZWYgPT09IHQubWF0Y2gubmF0aXZlRGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zTWF0Y2hdID0gJC5leHRlbmQodHJ1ZSwge30sIHBvc2l0aW9uc0Nsb25lW3Bvc01hdGNoXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zTWF0Y2hdLmlucHV0ID0gdC5pbnB1dDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrYmFja1Bvc2l0aW9ucyh1bmRlZmluZWQsIHBvc01hdGNoLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGogPSBwb3NNYXRjaCArIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0cy5zaGlmdFBvc2l0aW9ucyAmJiBwb3NpdGlvbkNhbk1hdGNoRGVmaW5pdGlvbihwb3NNYXRjaCwgdC5tYXRjaC5kZWYpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gaXNWYWxpZChwb3NNYXRjaCwgdC5pbnB1dCwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZCA9IHJlc3VsdCAhPT0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqID0gcmVzdWx0LmNhcmV0IHx8IHJlc3VsdC5pbnNlcnQgPyBnZXRMYXN0VmFsaWRQb3NpdGlvbigpIDogcG9zTWF0Y2ggKyAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmVlZHNWYWxpZGF0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkID0gdC5nZW5lcmF0ZWRJbnB1dCA9PT0gdHJ1ZSB8fCB0LmlucHV0ID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgb3B0cy5udW1lcmljSW5wdXQgPT09IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbGlkKSBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF2YWxpZCAmJiBwb3NNYXRjaCA+IGVuZCAmJiBpc01hc2socG9zTWF0Y2gsIHRydWUpICYmICh0Lm1hdGNoLmZuICE9PSBudWxsIHx8IHBvc01hdGNoID4gZ2V0TWFza1NldCgpLm1hc2tMZW5ndGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NNYXRjaCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0VGVzdChwb3NNYXRjaCkubWF0Y2guZGVmID09IFwiXCIpIHZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zTWF0Y2ggPSBqO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF2YWxpZCkgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF2YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zID0gJC5leHRlbmQodHJ1ZSwge30sIHBvc2l0aW9uc0Nsb25lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsaWRUZXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1t2YWxpZGF0ZWRQb3NdID0gJC5leHRlbmQodHJ1ZSwge30sIHZhbGlkVGVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCh0cnVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzTWFzayhwb3MsIHN0cmljdCkge1xuICAgICAgICAgICAgICAgIHZhciB0ZXN0ID0gZ2V0VGVzdFRlbXBsYXRlKHBvcykubWF0Y2g7XG4gICAgICAgICAgICAgICAgaWYgKHRlc3QuZGVmID09PSBcIlwiKSB0ZXN0ID0gZ2V0VGVzdChwb3MpLm1hdGNoO1xuICAgICAgICAgICAgICAgIGlmICh0ZXN0LmZuICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRlc3QuZm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzdHJpY3QgIT09IHRydWUgJiYgcG9zID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRlc3RzID0gZ2V0VGVzdHMocG9zKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRlc3RzLmxlbmd0aCA+IDEgKyAodGVzdHNbdGVzdHMubGVuZ3RoIC0gMV0ubWF0Y2guZGVmID09PSBcIlwiID8gMSA6IDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBzZWVrTmV4dChwb3MsIG5ld0Jsb2NrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBvc2l0aW9uID0gcG9zICsgMTtcbiAgICAgICAgICAgICAgICB3aGlsZSAoZ2V0VGVzdChwb3NpdGlvbikubWF0Y2guZGVmICE9PSBcIlwiICYmIChuZXdCbG9jayA9PT0gdHJ1ZSAmJiAoZ2V0VGVzdChwb3NpdGlvbikubWF0Y2gubmV3QmxvY2tNYXJrZXIgIT09IHRydWUgfHwgIWlzTWFzayhwb3NpdGlvbikpIHx8IG5ld0Jsb2NrICE9PSB0cnVlICYmICFpc01hc2socG9zaXRpb24pKSkge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcG9zaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBzZWVrUHJldmlvdXMocG9zLCBuZXdCbG9jaykge1xuICAgICAgICAgICAgICAgIHZhciBwb3NpdGlvbiA9IHBvcywgdGVzdHM7XG4gICAgICAgICAgICAgICAgaWYgKHBvc2l0aW9uIDw9IDApIHJldHVybiAwO1xuICAgICAgICAgICAgICAgIHdoaWxlICgtLXBvc2l0aW9uID4gMCAmJiAobmV3QmxvY2sgPT09IHRydWUgJiYgZ2V0VGVzdChwb3NpdGlvbikubWF0Y2gubmV3QmxvY2tNYXJrZXIgIT09IHRydWUgfHwgbmV3QmxvY2sgIT09IHRydWUgJiYgIWlzTWFzayhwb3NpdGlvbikgJiYgKHRlc3RzID0gZ2V0VGVzdHMocG9zaXRpb24pLCBcbiAgICAgICAgICAgICAgICB0ZXN0cy5sZW5ndGggPCAyIHx8IHRlc3RzLmxlbmd0aCA9PT0gMiAmJiB0ZXN0c1sxXS5tYXRjaC5kZWYgPT09IFwiXCIpKSkge31cbiAgICAgICAgICAgICAgICByZXR1cm4gcG9zaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiB3cml0ZUJ1ZmZlcihpbnB1dCwgYnVmZmVyLCBjYXJldFBvcywgZXZlbnQsIHRyaWdnZXJFdmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQgJiYgJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVXcml0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IG9wdHMub25CZWZvcmVXcml0ZS5jYWxsKGlucHV0bWFzaywgZXZlbnQsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LnJlZnJlc2hGcm9tQnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlZnJlc2ggPSByZXN1bHQucmVmcmVzaEZyb21CdWZmZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaEZyb21CdWZmZXIocmVmcmVzaCA9PT0gdHJ1ZSA/IHJlZnJlc2ggOiByZWZyZXNoLnN0YXJ0LCByZWZyZXNoLmVuZCwgcmVzdWx0LmJ1ZmZlciB8fCBidWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IGdldEJ1ZmZlcih0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYXJldFBvcyAhPT0gdW5kZWZpbmVkKSBjYXJldFBvcyA9IHJlc3VsdC5jYXJldCAhPT0gdW5kZWZpbmVkID8gcmVzdWx0LmNhcmV0IDogY2FyZXRQb3M7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLl92YWx1ZVNldChidWZmZXIuam9pbihcIlwiKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjYXJldFBvcyAhPT0gdW5kZWZpbmVkICYmIChldmVudCA9PT0gdW5kZWZpbmVkIHx8IGV2ZW50LnR5cGUgIT09IFwiYmx1clwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIGNhcmV0UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHJlbmRlckNvbG9yTWFzayhpbnB1dCwgY2FyZXRQb3MsIGJ1ZmZlci5sZW5ndGggPT09IDApO1xuICAgICAgICAgICAgICAgICAgICBpZiAodHJpZ2dlckV2ZW50cyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQoaW5wdXQpLCBucHRWYWwgPSBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBza2lwSW5wdXRFdmVudCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcImlucHV0XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobnB0VmFsID09PSBnZXRCdWZmZXJUZW1wbGF0ZSgpLmpvaW4oXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJjbGVhcmVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDb21wbGV0ZShidWZmZXIpID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC50cmlnZ2VyKFwiY29tcGxldGVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQbGFjZWhvbGRlcihwb3MsIHRlc3QsIHJldHVyblBMKSB7XG4gICAgICAgICAgICAgICAgdGVzdCA9IHRlc3QgfHwgZ2V0VGVzdChwb3MpLm1hdGNoO1xuICAgICAgICAgICAgICAgIGlmICh0ZXN0LnBsYWNlaG9sZGVyICE9PSB1bmRlZmluZWQgfHwgcmV0dXJuUEwgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICQuaXNGdW5jdGlvbih0ZXN0LnBsYWNlaG9sZGVyKSA/IHRlc3QucGxhY2Vob2xkZXIob3B0cykgOiB0ZXN0LnBsYWNlaG9sZGVyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGVzdC5mbiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocG9zID4gLTEgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvc10gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRlc3RzID0gZ2V0VGVzdHMocG9zKSwgc3RhdGljQWx0ZXJuYXRpb25zID0gW10sIHByZXZUZXN0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RzLmxlbmd0aCA+IDEgKyAodGVzdHNbdGVzdHMubGVuZ3RoIC0gMV0ubWF0Y2guZGVmID09PSBcIlwiID8gMSA6IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXN0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVzdHNbaV0ubWF0Y2gub3B0aW9uYWxpdHkgIT09IHRydWUgJiYgdGVzdHNbaV0ubWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyICE9PSB0cnVlICYmICh0ZXN0c1tpXS5tYXRjaC5mbiA9PT0gbnVsbCB8fCBwcmV2VGVzdCA9PT0gdW5kZWZpbmVkIHx8IHRlc3RzW2ldLm1hdGNoLmZuLnRlc3QocHJldlRlc3QubWF0Y2guZGVmLCBnZXRNYXNrU2V0KCksIHBvcywgdHJ1ZSwgb3B0cykgIT09IGZhbHNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGljQWx0ZXJuYXRpb25zLnB1c2godGVzdHNbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RzW2ldLm1hdGNoLmZuID09PSBudWxsKSBwcmV2VGVzdCA9IHRlc3RzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRpY0FsdGVybmF0aW9ucy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKC9bMC05YS1iQS1aXS8udGVzdChzdGF0aWNBbHRlcm5hdGlvbnNbMF0ubWF0Y2guZGVmKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQocG9zICUgb3B0cy5wbGFjZWhvbGRlci5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGVzdC5kZWY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLnBsYWNlaG9sZGVyLmNoYXJBdChwb3MgJSBvcHRzLnBsYWNlaG9sZGVyLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBIYW5kbGVOYXRpdmVQbGFjZWhvbGRlcihucHQsIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGllKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChucHQuaW5wdXRtYXNrLl92YWx1ZUdldCgpICE9PSB2YWx1ZSAmJiAobnB0LnBsYWNlaG9sZGVyICE9PSB2YWx1ZSB8fCBucHQucGxhY2Vob2xkZXIgPT09IFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gZ2V0QnVmZmVyKCkuc2xpY2UoKSwgbnB0VmFsdWUgPSBucHQuaW5wdXRtYXNrLl92YWx1ZUdldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5wdFZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsdnAgPT09IC0xICYmIG5wdFZhbHVlID09PSBnZXRCdWZmZXJUZW1wbGF0ZSgpLmpvaW4oXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChsdnAgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyT3B0aW9uYWxUYWlsKGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKG5wdCwgYnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnB0LnBsYWNlaG9sZGVyICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBucHQucGxhY2Vob2xkZXIgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5wdC5wbGFjZWhvbGRlciA9PT0gXCJcIikgbnB0LnJlbW92ZUF0dHJpYnV0ZShcInBsYWNlaG9sZGVyXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBFdmVudFJ1bGVyID0ge1xuICAgICAgICAgICAgICAgIG9uOiBmdW5jdGlvbiBvbihpbnB1dCwgZXZlbnROYW1lLCBldmVudEhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGV2ID0gZnVuY3Rpb24gZXYoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoYXQuaW5wdXRtYXNrID09PSB1bmRlZmluZWQgJiYgdGhpcy5ub2RlTmFtZSAhPT0gXCJGT1JNXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW1PcHRzID0gJC5kYXRhKHRoYXQsIFwiX2lucHV0bWFza19vcHRzXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbU9wdHMpIG5ldyBJbnB1dG1hc2soaW1PcHRzKS5tYXNrKHRoYXQpOyBlbHNlIEV2ZW50UnVsZXIub2ZmKHRoYXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLnR5cGUgIT09IFwic2V0dmFsdWVcIiAmJiB0aGlzLm5vZGVOYW1lICE9PSBcIkZPUk1cIiAmJiAodGhhdC5kaXNhYmxlZCB8fCB0aGF0LnJlYWRPbmx5ICYmICEoZS50eXBlID09PSBcImtleWRvd25cIiAmJiBlLmN0cmxLZXkgJiYgZS5rZXlDb2RlID09PSA2NyB8fCBvcHRzLnRhYlRocm91Z2ggPT09IGZhbHNlICYmIGUua2V5Q29kZSA9PT0gSW5wdXRtYXNrLmtleUNvZGUuVEFCKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZS50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaW5wdXRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNraXBJbnB1dEV2ZW50ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwSW5wdXRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobW9iaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRIYW5kbGVyLmFwcGx5KHRoYXQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0KHRoYXQsIHRoYXQuaW5wdXRtYXNrLmNhcmV0UG9zLCB1bmRlZmluZWQsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJrZXlkb3duXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXBLZXlQcmVzc0V2ZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXBJbnB1dEV2ZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwia2V5cHJlc3NcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNraXBLZXlQcmVzc0V2ZW50ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXBLZXlQcmVzc0V2ZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJjbGlja1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaWVtb2JpbGUgfHwgaXBob25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRIYW5kbGVyLmFwcGx5KHRoYXQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXR1cm5WYWwgPSBldmVudEhhbmRsZXIuYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmV0dXJuVmFsID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXR1cm5WYWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlucHV0LmlucHV0bWFzay5ldmVudHNbZXZlbnROYW1lXSA9IGlucHV0LmlucHV0bWFzay5ldmVudHNbZXZlbnROYW1lXSB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLmV2ZW50c1tldmVudE5hbWVdLnB1c2goZXYpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoJC5pbkFycmF5KGV2ZW50TmFtZSwgWyBcInN1Ym1pdFwiLCBcInJlc2V0XCIgXSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuZm9ybSAhPT0gbnVsbCkgJChpbnB1dC5mb3JtKS5vbihldmVudE5hbWUsIGV2KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICQoaW5wdXQpLm9uKGV2ZW50TmFtZSwgZXYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvZmY6IGZ1bmN0aW9uIG9mZihpbnB1dCwgZXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmlucHV0bWFzayAmJiBpbnB1dC5pbnB1dG1hc2suZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZXZlbnRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzW2V2ZW50XSA9IGlucHV0LmlucHV0bWFzay5ldmVudHNbZXZlbnRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMgPSBpbnB1dC5pbnB1dG1hc2suZXZlbnRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKGV2ZW50cywgZnVuY3Rpb24oZXZlbnROYW1lLCBldkFycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChldkFyci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBldiA9IGV2QXJyLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJC5pbkFycmF5KGV2ZW50TmFtZSwgWyBcInN1Ym1pdFwiLCBcInJlc2V0XCIgXSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuZm9ybSAhPT0gbnVsbCkgJChpbnB1dC5mb3JtKS5vZmYoZXZlbnROYW1lLCBldik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKGlucHV0KS5vZmYoZXZlbnROYW1lLCBldik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGlucHV0LmlucHV0bWFzay5ldmVudHNbZXZlbnROYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBFdmVudEhhbmRsZXJzID0ge1xuICAgICAgICAgICAgICAgIGtleWRvd25FdmVudDogZnVuY3Rpb24ga2V5ZG93bkV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcywgJGlucHV0ID0gJChpbnB1dCksIGsgPSBlLmtleUNvZGUsIHBvcyA9IGNhcmV0KGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLkJBQ0tTUEFDRSB8fCBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEUgfHwgaXBob25lICYmIGsgPT09IElucHV0bWFzay5rZXlDb2RlLkJBQ0tTUEFDRV9TQUZBUkkgfHwgZS5jdHJsS2V5ICYmIGsgPT09IElucHV0bWFzay5rZXlDb2RlLlggJiYgIWlzSW5wdXRFdmVudFN1cHBvcnRlZChcImN1dFwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlUmVtb3ZlKGlucHV0LCBrLCBwb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoaW5wdXQsIGdldEJ1ZmZlcih0cnVlKSwgZ2V0TWFza1NldCgpLnAsIGUsIGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuRU5EIHx8IGsgPT09IElucHV0bWFzay5rZXlDb2RlLlBBR0VfRE9XTikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhcmV0UG9zID0gc2Vla05leHQoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgZS5zaGlmdEtleSA/IHBvcy5iZWdpbiA6IGNhcmV0UG9zLCBjYXJldFBvcywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuSE9NRSAmJiAhZS5zaGlmdEtleSB8fCBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5QQUdFX1VQKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgMCwgZS5zaGlmdEtleSA/IHBvcy5iZWdpbiA6IDAsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChvcHRzLnVuZG9PbkVzY2FwZSAmJiBrID09PSBJbnB1dG1hc2sua2V5Q29kZS5FU0NBUEUgfHwgayA9PT0gOTAgJiYgZS5jdHJsS2V5KSAmJiBlLmFsdEtleSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tWYWwoaW5wdXQsIHRydWUsIGZhbHNlLCB1bmRvVmFsdWUuc3BsaXQoXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJjbGlja1wiKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChrID09PSBJbnB1dG1hc2sua2V5Q29kZS5JTlNFUlQgJiYgIShlLnNoaWZ0S2V5IHx8IGUuY3RybEtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuaW5zZXJ0TW9kZSA9ICFvcHRzLmluc2VydE1vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoXCJpbS1pbnNlcnRcIiwgb3B0cy5pbnNlcnRNb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRzLnRhYlRocm91Z2ggPT09IHRydWUgJiYgayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuVEFCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS5zaGlmdEtleSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRUZXN0KHBvcy5iZWdpbikubWF0Y2guZm4gPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmJlZ2luID0gc2Vla05leHQocG9zLmJlZ2luKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmVuZCA9IHNlZWtQcmV2aW91cyhwb3MuYmVnaW4sIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5iZWdpbiA9IHNlZWtQcmV2aW91cyhwb3MuZW5kLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmJlZ2luID0gc2Vla05leHQocG9zLmJlZ2luLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MuZW5kID0gc2Vla05leHQocG9zLmJlZ2luLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9zLmVuZCA8IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoKSBwb3MuZW5kLS07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9zLmJlZ2luIDwgZ2V0TWFza1NldCgpLm1hc2tMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIHBvcy5iZWdpbiwgcG9zLmVuZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3B0cy5vbktleURvd24uY2FsbCh0aGlzLCBlLCBnZXRCdWZmZXIoKSwgY2FyZXQoaW5wdXQpLmJlZ2luLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWdub3JhYmxlID0gJC5pbkFycmF5KGssIG9wdHMuaWdub3JhYmxlcykgIT09IC0xO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAga2V5cHJlc3NFdmVudDogZnVuY3Rpb24ga2V5cHJlc3NFdmVudChlLCBjaGVja3ZhbCwgd3JpdGVPdXQsIHN0cmljdCwgbmR4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMsICRpbnB1dCA9ICQoaW5wdXQpLCBrID0gZS53aGljaCB8fCBlLmNoYXJDb2RlIHx8IGUua2V5Q29kZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoZWNrdmFsICE9PSB0cnVlICYmICEoZS5jdHJsS2V5ICYmIGUuYWx0S2V5KSAmJiAoZS5jdHJsS2V5IHx8IGUubWV0YUtleSB8fCBpZ25vcmFibGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuRU5URVIgJiYgdW5kb1ZhbHVlICE9PSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5kb1ZhbHVlID0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcImNoYW5nZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoayA9PT0gNDYgJiYgZS5zaGlmdEtleSA9PT0gZmFsc2UgJiYgb3B0cy5yYWRpeFBvaW50ICE9PSBcIlwiKSBrID0gb3B0cy5yYWRpeFBvaW50LmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IGNoZWNrdmFsID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogbmR4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IG5keFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gOiBjYXJldChpbnB1dCksIGZvcndhcmRQb3NpdGlvbiwgYyA9IFN0cmluZy5mcm9tQ2hhckNvZGUoayksIG9mZnNldCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuX3JhZGl4RGFuY2UgJiYgb3B0cy5udW1lcmljSW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhcmV0UG9zID0gZ2V0QnVmZmVyKCkuaW5kZXhPZihvcHRzLnJhZGl4UG9pbnQuY2hhckF0KDApKSArIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwb3MuYmVnaW4gPD0gY2FyZXRQb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrID09PSBvcHRzLnJhZGl4UG9pbnQuY2hhckNvZGVBdCgwKSkgb2Zmc2V0ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5iZWdpbiAtPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmVuZCAtPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS53cml0ZU91dEJ1ZmZlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbFJlc3VsdCA9IGlzVmFsaWQocG9zLCBjLCBzdHJpY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWxSZXN1bHQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yd2FyZFBvc2l0aW9uID0gdmFsUmVzdWx0LmNhcmV0ICE9PSB1bmRlZmluZWQgPyB2YWxSZXN1bHQuY2FyZXQgOiBzZWVrTmV4dCh2YWxSZXN1bHQucG9zLmJlZ2luID8gdmFsUmVzdWx0LnBvcy5iZWdpbiA6IHZhbFJlc3VsdC5wb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkucCA9IGZvcndhcmRQb3NpdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yd2FyZFBvc2l0aW9uID0gKG9wdHMubnVtZXJpY0lucHV0ICYmIHZhbFJlc3VsdC5jYXJldCA9PT0gdW5kZWZpbmVkID8gc2Vla1ByZXZpb3VzKGZvcndhcmRQb3NpdGlvbikgOiBmb3J3YXJkUG9zaXRpb24pICsgb2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3cml0ZU91dCAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMub25LZXlWYWxpZGF0aW9uLmNhbGwoaW5wdXQsIGssIHZhbFJlc3VsdCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLndyaXRlT3V0QnVmZmVyICYmIHZhbFJlc3VsdCAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSBnZXRCdWZmZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBidWZmZXIsIGZvcndhcmRQb3NpdGlvbiwgZSwgY2hlY2t2YWwgIT09IHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hlY2t2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbFJlc3VsdCAhPT0gZmFsc2UpIHZhbFJlc3VsdC5mb3J3YXJkUG9zaXRpb24gPSBmb3J3YXJkUG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWxSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwYXN0ZUV2ZW50OiBmdW5jdGlvbiBwYXN0ZUV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcywgZXYgPSBlLm9yaWdpbmFsRXZlbnQgfHwgZSwgJGlucHV0ID0gJChpbnB1dCksIGlucHV0VmFsdWUgPSBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KHRydWUpLCBjYXJldFBvcyA9IGNhcmV0KGlucHV0KSwgdGVtcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNSVEwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBWYWx1ZSA9IGNhcmV0UG9zLmVuZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zLmVuZCA9IGNhcmV0UG9zLmJlZ2luO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3MuYmVnaW4gPSB0ZW1wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlQmVmb3JlQ2FyZXQgPSBpbnB1dFZhbHVlLnN1YnN0cigwLCBjYXJldFBvcy5iZWdpbiksIHZhbHVlQWZ0ZXJDYXJldCA9IGlucHV0VmFsdWUuc3Vic3RyKGNhcmV0UG9zLmVuZCwgaW5wdXRWYWx1ZS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWVCZWZvcmVDYXJldCA9PT0gKGlzUlRMID8gZ2V0QnVmZmVyVGVtcGxhdGUoKS5yZXZlcnNlKCkgOiBnZXRCdWZmZXJUZW1wbGF0ZSgpKS5zbGljZSgwLCBjYXJldFBvcy5iZWdpbikuam9pbihcIlwiKSkgdmFsdWVCZWZvcmVDYXJldCA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZUFmdGVyQ2FyZXQgPT09IChpc1JUTCA/IGdldEJ1ZmZlclRlbXBsYXRlKCkucmV2ZXJzZSgpIDogZ2V0QnVmZmVyVGVtcGxhdGUoKSkuc2xpY2UoY2FyZXRQb3MuZW5kKS5qb2luKFwiXCIpKSB2YWx1ZUFmdGVyQ2FyZXQgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICBpZiAod2luZG93LmNsaXBib2FyZERhdGEgJiYgd2luZG93LmNsaXBib2FyZERhdGEuZ2V0RGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IHZhbHVlQmVmb3JlQ2FyZXQgKyB3aW5kb3cuY2xpcGJvYXJkRGF0YS5nZXREYXRhKFwiVGV4dFwiKSArIHZhbHVlQWZ0ZXJDYXJldDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChldi5jbGlwYm9hcmREYXRhICYmIGV2LmNsaXBib2FyZERhdGEuZ2V0RGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IHZhbHVlQmVmb3JlQ2FyZXQgKyBldi5jbGlwYm9hcmREYXRhLmdldERhdGEoXCJ0ZXh0L3BsYWluXCIpICsgdmFsdWVBZnRlckNhcmV0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXN0ZVZhbHVlID0gaW5wdXRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaXNGdW5jdGlvbihvcHRzLm9uQmVmb3JlUGFzdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZVZhbHVlID0gb3B0cy5vbkJlZm9yZVBhc3RlLmNhbGwoaW5wdXRtYXNrLCBpbnB1dFZhbHVlLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXN0ZVZhbHVlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXBhc3RlVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZVZhbHVlID0gaW5wdXRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjaGVja1ZhbChpbnB1dCwgZmFsc2UsIGZhbHNlLCBwYXN0ZVZhbHVlLnRvU3RyaW5nKCkuc3BsaXQoXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICB3cml0ZUJ1ZmZlcihpbnB1dCwgZ2V0QnVmZmVyKCksIHNlZWtOZXh0KGdldExhc3RWYWxpZFBvc2l0aW9uKCkpLCBlLCB1bmRvVmFsdWUgIT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgaW5wdXRGYWxsQmFja0V2ZW50OiBmdW5jdGlvbiBpbnB1dEZhbGxCYWNrRXZlbnQoZSkge1xuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiByYWRpeFBvaW50SGFuZGxlcihpbnB1dCwgaW5wdXRWYWx1ZSwgY2FyZXRQb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dFZhbHVlLmNoYXJBdChjYXJldFBvcy5iZWdpbiAtIDEpID09PSBcIi5cIiAmJiBvcHRzLnJhZGl4UG9pbnQgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlID0gaW5wdXRWYWx1ZS5zcGxpdChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlW2NhcmV0UG9zLmJlZ2luIC0gMV0gPSBvcHRzLnJhZGl4UG9pbnQuY2hhckF0KDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0VmFsdWUgPSBpbnB1dFZhbHVlLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5wdXRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBpZU1vYmlsZUhhbmRsZXIoaW5wdXQsIGlucHV0VmFsdWUsIGNhcmV0UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaWVtb2JpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXRDaGFyID0gaW5wdXRWYWx1ZS5yZXBsYWNlKGdldEJ1ZmZlcigpLmpvaW4oXCJcIiksIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dENoYXIubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpdiA9IGlucHV0VmFsdWUuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl2LnNwbGljZShjYXJldFBvcy5iZWdpbiwgMCwgaW5wdXRDaGFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGl2LmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcywgaW5wdXRWYWx1ZSA9IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdldEJ1ZmZlcigpLmpvaW4oXCJcIikgIT09IGlucHV0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYXJldFBvcyA9IGNhcmV0KGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0VmFsdWUgPSByYWRpeFBvaW50SGFuZGxlcihpbnB1dCwgaW5wdXRWYWx1ZSwgY2FyZXRQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGllTW9iaWxlSGFuZGxlcihpbnB1dCwgaW5wdXRWYWx1ZSwgY2FyZXRQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldEJ1ZmZlcigpLmpvaW4oXCJcIikgIT09IGlucHV0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSwgb2Zmc2V0ID0gIW9wdHMubnVtZXJpY0lucHV0ICYmIGlucHV0VmFsdWUubGVuZ3RoID4gYnVmZmVyLmxlbmd0aCA/IC0xIDogMCwgZnJvbnRQYXJ0ID0gaW5wdXRWYWx1ZS5zdWJzdHIoMCwgY2FyZXRQb3MuYmVnaW4pLCBiYWNrUGFydCA9IGlucHV0VmFsdWUuc3Vic3RyKGNhcmV0UG9zLmJlZ2luKSwgZnJvbnRCdWZmZXJQYXJ0ID0gYnVmZmVyLnN1YnN0cigwLCBjYXJldFBvcy5iZWdpbiArIG9mZnNldCksIGJhY2tCdWZmZXJQYXJ0ID0gYnVmZmVyLnN1YnN0cihjYXJldFBvcy5iZWdpbiArIG9mZnNldCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHNlbGVjdGlvbiA9IGNhcmV0UG9zLCBlbnRyaWVzID0gXCJcIiwgaXNFbnRyeSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcm9udFBhcnQgIT09IGZyb250QnVmZmVyUGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZnBsID0gKGlzRW50cnkgPSBmcm9udFBhcnQubGVuZ3RoID49IGZyb250QnVmZmVyUGFydC5sZW5ndGgpID8gZnJvbnRQYXJ0Lmxlbmd0aCA6IGZyb250QnVmZmVyUGFydC5sZW5ndGgsIGk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGZyb250UGFydC5jaGFyQXQoaSkgPT09IGZyb250QnVmZmVyUGFydC5jaGFyQXQoaSkgJiYgaSA8IGZwbDsgaSsrKSB7fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uLmJlZ2luID0gaSAtIG9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJpZXMgKz0gZnJvbnRQYXJ0LnNsaWNlKGksIHNlbGVjdGlvbi5lbmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYWNrUGFydCAhPT0gYmFja0J1ZmZlclBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJhY2tQYXJ0Lmxlbmd0aCA+IGJhY2tCdWZmZXJQYXJ0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW50cmllcyArPSBiYWNrUGFydC5zbGljZSgwLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYWNrUGFydC5sZW5ndGggPCBiYWNrQnVmZmVyUGFydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb24uZW5kICs9IGJhY2tCdWZmZXJQYXJ0Lmxlbmd0aCAtIGJhY2tQYXJ0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzRW50cnkgJiYgb3B0cy5yYWRpeFBvaW50ICE9PSBcIlwiICYmIGJhY2tQYXJ0ID09PSBcIlwiICYmIGZyb250UGFydC5jaGFyQXQoc2VsZWN0aW9uLmJlZ2luICsgb2Zmc2V0IC0gMSkgPT09IG9wdHMucmFkaXhQb2ludCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb24uYmVnaW4tLTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW50cmllcyA9IG9wdHMucmFkaXhQb2ludDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoaW5wdXQsIGdldEJ1ZmZlcigpLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiBzZWxlY3Rpb24uYmVnaW4gKyBvZmZzZXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZDogc2VsZWN0aW9uLmVuZCArIG9mZnNldFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbnRyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKGVudHJpZXMuc3BsaXQoXCJcIiksIGZ1bmN0aW9uKG5keCwgZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrZXlwcmVzcyA9IG5ldyAkLkV2ZW50KFwia2V5cHJlc3NcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlwcmVzcy53aGljaCA9IGVudHJ5LmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50SGFuZGxlcnMua2V5cHJlc3NFdmVudC5jYWxsKGlucHV0LCBrZXlwcmVzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZWxlY3Rpb24uYmVnaW4gPT09IHNlbGVjdGlvbi5lbmQgLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb24uYmVnaW4gPSBzZWVrUHJldmlvdXMoc2VsZWN0aW9uLmJlZ2luICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZWN0aW9uLmJlZ2luID09PSBzZWxlY3Rpb24uZW5kIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0KGlucHV0LCBzZWxlY3Rpb24uYmVnaW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgc2VsZWN0aW9uLmJlZ2luLCBzZWxlY3Rpb24uZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5ZG93biA9IG5ldyAkLkV2ZW50KFwia2V5ZG93blwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5ZG93bi5rZXlDb2RlID0gb3B0cy5udW1lcmljSW5wdXQgPyBJbnB1dG1hc2sua2V5Q29kZS5CQUNLU1BBQ0UgOiBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50SGFuZGxlcnMua2V5ZG93bkV2ZW50LmNhbGwoaW5wdXQsIGtleWRvd24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGJlZm9yZUlucHV0RXZlbnQ6IGZ1bmN0aW9uIGJlZm9yZUlucHV0RXZlbnQoZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZS5jYW5jZWxhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlLmlucHV0VHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaW5zZXJ0VGV4dFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChlLmRhdGEuc3BsaXQoXCJcIiksIGZ1bmN0aW9uKG5keCwgZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGtleXByZXNzID0gbmV3ICQuRXZlbnQoXCJrZXlwcmVzc1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cHJlc3Mud2hpY2ggPSBlbnRyeS5jaGFyQ29kZUF0KDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRIYW5kbGVycy5rZXlwcmVzc0V2ZW50LmNhbGwoaW5wdXQsIGtleXByZXNzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJkZWxldGVDb250ZW50QmFja3dhcmRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5ZG93biA9IG5ldyAkLkV2ZW50KFwia2V5ZG93blwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlkb3duLmtleUNvZGUgPSBJbnB1dG1hc2sua2V5Q29kZS5CQUNLU1BBQ0U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRIYW5kbGVycy5rZXlkb3duRXZlbnQuY2FsbChpbnB1dCwga2V5ZG93bik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZGVsZXRlQ29udGVudEZvcndhcmRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5ZG93biA9IG5ldyAkLkV2ZW50KFwia2V5ZG93blwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlkb3duLmtleUNvZGUgPSBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRIYW5kbGVycy5rZXlkb3duRXZlbnQuY2FsbChpbnB1dCwga2V5ZG93bik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0VmFsdWVFdmVudDogZnVuY3Rpb24gc2V0VmFsdWVFdmVudChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRtYXNrLnJlZnJlc2hWYWx1ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLCB2YWx1ZSA9IGUgJiYgZS5kZXRhaWwgPyBlLmRldGFpbFswXSA6IGFyZ3VtZW50c1sxXSwgdmFsdWUgPSB2YWx1ZSB8fCBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoJC5pc0Z1bmN0aW9uKG9wdHMub25CZWZvcmVNYXNrKSkgdmFsdWUgPSBvcHRzLm9uQmVmb3JlTWFzay5jYWxsKGlucHV0bWFzaywgdmFsdWUsIG9wdHMpIHx8IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCkuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrVmFsKGlucHV0LCB0cnVlLCBmYWxzZSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB1bmRvVmFsdWUgPSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgfHwgb3B0cy5jbGVhckluY29tcGxldGUpICYmIGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKSA9PT0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5qb2luKFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlU2V0KFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmb2N1c0V2ZW50OiBmdW5jdGlvbiBmb2N1c0V2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcywgbnB0VmFsdWUgPSBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnNob3dNYXNrT25Gb2N1cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5wdFZhbHVlICE9PSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIoaW5wdXQsIGdldEJ1ZmZlcigpLCBzZWVrTmV4dChnZXRMYXN0VmFsaWRQb3NpdGlvbigpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1vdXNlRW50ZXIgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQoaW5wdXQsIHNlZWtOZXh0KGdldExhc3RWYWxpZFBvc2l0aW9uKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5wb3NpdGlvbkNhcmV0T25UYWIgPT09IHRydWUgJiYgbW91c2VFbnRlciA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50SGFuZGxlcnMuY2xpY2tFdmVudC5hcHBseShpbnB1dCwgWyBlLCB0cnVlIF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHVuZG9WYWx1ZSA9IGdldEJ1ZmZlcigpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBtb3VzZWxlYXZlRXZlbnQ6IGZ1bmN0aW9uIG1vdXNlbGVhdmVFdmVudChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgICAgIG1vdXNlRW50ZXIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgJiYgZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAhPT0gaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEhhbmRsZU5hdGl2ZVBsYWNlaG9sZGVyKGlucHV0LCBvcmlnaW5hbFBsYWNlaG9sZGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY2xpY2tFdmVudDogZnVuY3Rpb24gY2xpY2tFdmVudChlLCB0YWJiZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gZG9SYWRpeEZvY3VzKGNsaWNrUG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5yYWRpeFBvaW50ICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZwcyA9IGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodnBzW2NsaWNrUG9zXSA9PT0gdW5kZWZpbmVkIHx8IHZwc1tjbGlja1Bvc10uaW5wdXQgPT09IGdldFBsYWNlaG9sZGVyKGNsaWNrUG9zKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2xpY2tQb3MgPCBzZWVrTmV4dCgtMSkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFkaXhQb3MgPSAkLmluQXJyYXkob3B0cy5yYWRpeFBvaW50LCBnZXRCdWZmZXIoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYWRpeFBvcyAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHZwIGluIHZwcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYWRpeFBvcyA8IHZwICYmIHZwc1t2cF0uaW5wdXQgIT09IGdldFBsYWNlaG9sZGVyKHZwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSBpbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3RlZENhcmV0ID0gY2FyZXQoaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0YWJiZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZENhcmV0LmVuZCA9IHNlbGVjdGVkQ2FyZXQuYmVnaW47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZENhcmV0LmJlZ2luID0gc2VsZWN0ZWRDYXJldC5lbmQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkQ2FyZXQuYmVnaW4gPT09IHNlbGVjdGVkQ2FyZXQuZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAob3B0cy5wb3NpdGlvbkNhcmV0T25DbGljaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJub25lXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzZWxlY3RcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0KGlucHV0LCAwLCBnZXRCdWZmZXIoKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaWdub3JlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgc2Vla05leHQoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwicmFkaXhGb2N1c1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvUmFkaXhGb2N1cyhzZWxlY3RlZENhcmV0LmJlZ2luKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvcyA9IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikuaW5kZXhPZihvcHRzLnJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0KGlucHV0LCBvcHRzLm51bWVyaWNJbnB1dCA/IHNlZWtOZXh0KHJhZGl4UG9zKSA6IHJhZGl4UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2xpY2tQb3NpdGlvbiA9IHNlbGVjdGVkQ2FyZXQuYmVnaW4sIGx2Y2xpY2tQb3NpdGlvbiA9IGdldExhc3RWYWxpZFBvc2l0aW9uKGNsaWNrUG9zaXRpb24sIHRydWUpLCBsYXN0UG9zaXRpb24gPSBzZWVrTmV4dChsdmNsaWNrUG9zaXRpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNsaWNrUG9zaXRpb24gPCBsYXN0UG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgIWlzTWFzayhjbGlja1Bvc2l0aW9uLCB0cnVlKSAmJiAhaXNNYXNrKGNsaWNrUG9zaXRpb24gLSAxLCB0cnVlKSA/IHNlZWtOZXh0KGNsaWNrUG9zaXRpb24pIDogY2xpY2tQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsdnAgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbHZjbGlja1Bvc2l0aW9uXSwgdHQgPSBnZXRUZXN0VGVtcGxhdGUobGFzdFBvc2l0aW9uLCBsdnAgPyBsdnAubWF0Y2gubG9jYXRvciA6IHVuZGVmaW5lZCwgbHZwKSwgcGxhY2Vob2xkZXIgPSBnZXRQbGFjZWhvbGRlcihsYXN0UG9zaXRpb24sIHR0Lm1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGxhY2Vob2xkZXIgIT09IFwiXCIgJiYgZ2V0QnVmZmVyKClbbGFzdFBvc2l0aW9uXSAhPT0gcGxhY2Vob2xkZXIgJiYgdHQubWF0Y2gub3B0aW9uYWxRdWFudGlmaWVyICE9PSB0cnVlICYmIHR0Lm1hdGNoLm5ld0Jsb2NrTWFya2VyICE9PSB0cnVlIHx8ICFpc01hc2sobGFzdFBvc2l0aW9uLCBvcHRzLmtlZXBTdGF0aWMpICYmIHR0Lm1hdGNoLmRlZiA9PT0gcGxhY2Vob2xkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1BvcyA9IHNlZWtOZXh0KGxhc3RQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjbGlja1Bvc2l0aW9uID49IG5ld1BvcyB8fCBjbGlja1Bvc2l0aW9uID09PSBsYXN0UG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RQb3NpdGlvbiA9IG5ld1BvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgbGFzdFBvc2l0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGN1dEV2ZW50OiBmdW5jdGlvbiBjdXRFdmVudChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMsICRpbnB1dCA9ICQoaW5wdXQpLCBwb3MgPSBjYXJldChpbnB1dCksIGV2ID0gZS5vcmlnaW5hbEV2ZW50IHx8IGU7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjbGlwYm9hcmREYXRhID0gd2luZG93LmNsaXBib2FyZERhdGEgfHwgZXYuY2xpcGJvYXJkRGF0YSwgY2xpcERhdGEgPSBpc1JUTCA/IGdldEJ1ZmZlcigpLnNsaWNlKHBvcy5lbmQsIHBvcy5iZWdpbikgOiBnZXRCdWZmZXIoKS5zbGljZShwb3MuYmVnaW4sIHBvcy5lbmQpO1xuICAgICAgICAgICAgICAgICAgICBjbGlwYm9hcmREYXRhLnNldERhdGEoXCJ0ZXh0XCIsIGlzUlRMID8gY2xpcERhdGEucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiBjbGlwRGF0YS5qb2luKFwiXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmV4ZWNDb21tYW5kKSBkb2N1bWVudC5leGVjQ29tbWFuZChcImNvcHlcIik7XG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZVJlbW92ZShpbnB1dCwgSW5wdXRtYXNrLmtleUNvZGUuREVMRVRFLCBwb3MpO1xuICAgICAgICAgICAgICAgICAgICB3cml0ZUJ1ZmZlcihpbnB1dCwgZ2V0QnVmZmVyKCksIGdldE1hc2tTZXQoKS5wLCBlLCB1bmRvVmFsdWUgIT09IGdldEJ1ZmZlcigpLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYmx1ckV2ZW50OiBmdW5jdGlvbiBibHVyRXZlbnQoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgJGlucHV0ID0gJCh0aGlzKSwgaW5wdXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuaW5wdXRtYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBIYW5kbGVOYXRpdmVQbGFjZWhvbGRlcihpbnB1dCwgb3JpZ2luYWxQbGFjZWhvbGRlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbnB0VmFsdWUgPSBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCksIGJ1ZmZlciA9IGdldEJ1ZmZlcigpLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobnB0VmFsdWUgIT09IFwiXCIgfHwgY29sb3JNYXNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSA9PT0gLTEgJiYgbnB0VmFsdWUgPT09IGdldEJ1ZmZlclRlbXBsYXRlKCkuam9pbihcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhck9wdGlvbmFsVGFpbChidWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0NvbXBsZXRlKGJ1ZmZlcikgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcImluY29tcGxldGVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5jbGVhckluY29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXIgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlQnVmZmVyKGlucHV0LCBidWZmZXIsIHVuZGVmaW5lZCwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodW5kb1ZhbHVlICE9PSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5kb1ZhbHVlID0gYnVmZmVyLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG1vdXNlZW50ZXJFdmVudDogZnVuY3Rpb24gbW91c2VlbnRlckV2ZW50KGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgbW91c2VFbnRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9PSBpbnB1dCAmJiBvcHRzLnNob3dNYXNrT25Ib3Zlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgSGFuZGxlTmF0aXZlUGxhY2Vob2xkZXIoaW5wdXQsIChpc1JUTCA/IGdldEJ1ZmZlcigpLnNsaWNlKCkucmV2ZXJzZSgpIDogZ2V0QnVmZmVyKCkpLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzdWJtaXRFdmVudDogZnVuY3Rpb24gc3VibWl0RXZlbnQoZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodW5kb1ZhbHVlICE9PSBnZXRCdWZmZXIoKS5qb2luKFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZWwudHJpZ2dlcihcImNoYW5nZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cyAmJiBnZXRMYXN0VmFsaWRQb3NpdGlvbigpID09PSAtMSAmJiBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0ICYmIGVsLmlucHV0bWFzay5fdmFsdWVHZXQoKSA9PT0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5qb2luKFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2suX3ZhbHVlU2V0KFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmNsZWFySW5jb21wbGV0ZSAmJiBpc0NvbXBsZXRlKGdldEJ1ZmZlcigpKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5fdmFsdWVTZXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmVtb3ZlTWFza09uU3VibWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2suX3ZhbHVlU2V0KGVsLmlucHV0bWFzay51bm1hc2tlZHZhbHVlKCksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0ZUJ1ZmZlcihlbCwgZ2V0QnVmZmVyKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlc2V0RXZlbnQ6IGZ1bmN0aW9uIHJlc2V0RXZlbnQoZSkge1xuICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2sucmVmcmVzaFZhbHVlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRlbC50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja1ZhbChpbnB1dCwgd3JpdGVPdXQsIHN0cmljdCwgbnB0dmwsIGluaXRpYXRpbmdFdmVudCkge1xuICAgICAgICAgICAgICAgIHZhciBpbnB1dG1hc2sgPSB0aGlzIHx8IGlucHV0LmlucHV0bWFzaywgaW5wdXRWYWx1ZSA9IG5wdHZsLnNsaWNlKCksIGNoYXJDb2RlcyA9IFwiXCIsIGluaXRpYWxOZHggPSAtMSwgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGVtcGxhdGVNYXRjaChuZHgsIGNoYXJDb2Rlcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hhckNvZGVOZHggPSBnZXRNYXNrVGVtcGxhdGUodHJ1ZSwgMCwgZmFsc2UpLnNsaWNlKG5keCwgc2Vla05leHQobmR4KSkuam9pbihcIlwiKS5yZXBsYWNlKC8nL2csIFwiXCIpLmluZGV4T2YoY2hhckNvZGVzKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNoYXJDb2RlTmR4ICE9PSAtMSAmJiAhaXNNYXNrKG5keCkgJiYgKGdldFRlc3QobmR4KS5tYXRjaC5uYXRpdmVEZWYgPT09IGNoYXJDb2Rlcy5jaGFyQXQoMCkgfHwgZ2V0VGVzdChuZHgpLm1hdGNoLmZuID09PSBudWxsICYmIGdldFRlc3QobmR4KS5tYXRjaC5uYXRpdmVEZWYgPT09IFwiJ1wiICsgY2hhckNvZGVzLmNoYXJBdCgwKSB8fCBnZXRUZXN0KG5keCkubWF0Y2gubmF0aXZlRGVmID09PSBcIiBcIiAmJiAoZ2V0VGVzdChuZHggKyAxKS5tYXRjaC5uYXRpdmVEZWYgPT09IGNoYXJDb2Rlcy5jaGFyQXQoMCkgfHwgZ2V0VGVzdChuZHggKyAxKS5tYXRjaC5mbiA9PT0gbnVsbCAmJiBnZXRUZXN0KG5keCArIDEpLm1hdGNoLm5hdGl2ZURlZiA9PT0gXCInXCIgKyBjaGFyQ29kZXMuY2hhckF0KDApKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc2V0TWFza1NldCgpO1xuICAgICAgICAgICAgICAgIGlmICghc3RyaWN0ICYmIG9wdHMuYXV0b1VubWFzayAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3RhdGljSW5wdXQgPSBnZXRCdWZmZXJUZW1wbGF0ZSgpLnNsaWNlKDAsIHNlZWtOZXh0KC0xKSkuam9pbihcIlwiKSwgbWF0Y2hlcyA9IGlucHV0VmFsdWUuam9pbihcIlwiKS5tYXRjaChuZXcgUmVnRXhwKFwiXlwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KHN0YXRpY0lucHV0KSwgXCJnXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoZXMgJiYgbWF0Y2hlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlLnNwbGljZSgwLCBtYXRjaGVzLmxlbmd0aCAqIHN0YXRpY0lucHV0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsTmR4ID0gc2Vla05leHQoaW5pdGlhbE5keCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsTmR4ID0gc2Vla05leHQoaW5pdGlhbE5keCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsTmR4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkucCA9IHNlZWtOZXh0KGluaXRpYWxOZHgpO1xuICAgICAgICAgICAgICAgICAgICBpbml0aWFsTmR4ID0gMDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgZ2V0TWFza1NldCgpLnAgPSBpbml0aWFsTmR4O1xuICAgICAgICAgICAgICAgIGlucHV0bWFzay5jYXJldFBvcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgYmVnaW46IGluaXRpYWxOZHhcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICQuZWFjaChpbnB1dFZhbHVlLCBmdW5jdGlvbihuZHgsIGNoYXJDb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGFyQ29kZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW25keF0gPT09IHVuZGVmaW5lZCAmJiBpbnB1dFZhbHVlW25keF0gPT09IGdldFBsYWNlaG9sZGVyKG5keCkgJiYgaXNNYXNrKG5keCwgdHJ1ZSkgJiYgaXNWYWxpZChuZHgsIGlucHV0VmFsdWVbbmR4XSwgdHJ1ZSwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHRydWUpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5wKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrZXlwcmVzcyA9IG5ldyAkLkV2ZW50KFwiX2NoZWNrdmFsXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleXByZXNzLndoaWNoID0gY2hhckNvZGUuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFyQ29kZXMgKz0gY2hhckNvZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGx2cCA9IGdldExhc3RWYWxpZFBvc2l0aW9uKHVuZGVmaW5lZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1RlbXBsYXRlTWF0Y2goaW5pdGlhbE5keCwgY2hhckNvZGVzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBFdmVudEhhbmRsZXJzLmtleXByZXNzRXZlbnQuY2FsbChpbnB1dCwga2V5cHJlc3MsIHRydWUsIGZhbHNlLCBzdHJpY3QsIGlucHV0bWFzay5jYXJldFBvcy5iZWdpbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxOZHggPSBpbnB1dG1hc2suY2FyZXRQb3MuYmVnaW4gKyAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhckNvZGVzID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEV2ZW50SGFuZGxlcnMua2V5cHJlc3NFdmVudC5jYWxsKGlucHV0LCBrZXlwcmVzcywgdHJ1ZSwgZmFsc2UsIHN0cmljdCwgbHZwICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVCdWZmZXIodW5kZWZpbmVkLCBnZXRCdWZmZXIoKSwgcmVzdWx0LmZvcndhcmRQb3NpdGlvbiwga2V5cHJlc3MsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRtYXNrLmNhcmV0UG9zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW46IHJlc3VsdC5mb3J3YXJkUG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IHJlc3VsdC5mb3J3YXJkUG9zaXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAod3JpdGVPdXQpIHdyaXRlQnVmZmVyKGlucHV0LCBnZXRCdWZmZXIoKSwgcmVzdWx0ID8gcmVzdWx0LmZvcndhcmRQb3NpdGlvbiA6IHVuZGVmaW5lZCwgaW5pdGlhdGluZ0V2ZW50IHx8IG5ldyAkLkV2ZW50KFwiY2hlY2t2YWxcIiksIGluaXRpYXRpbmdFdmVudCAmJiBpbml0aWF0aW5nRXZlbnQudHlwZSA9PT0gXCJpbnB1dFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVubWFza2VkdmFsdWUoaW5wdXQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmlucHV0bWFzayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5wdXQudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmlucHV0bWFzayAmJiBpbnB1dC5pbnB1dG1hc2sucmVmcmVzaFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudEhhbmRsZXJzLnNldFZhbHVlRXZlbnQuY2FsbChpbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHVtVmFsdWUgPSBbXSwgdnBzID0gZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHBuZHggaW4gdnBzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2cHNbcG5keF0ubWF0Y2ggJiYgdnBzW3BuZHhdLm1hdGNoLmZuICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVtVmFsdWUucHVzaCh2cHNbcG5keF0uaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciB1bm1hc2tlZFZhbHVlID0gdW1WYWx1ZS5sZW5ndGggPT09IDAgPyBcIlwiIDogKGlzUlRMID8gdW1WYWx1ZS5yZXZlcnNlKCkgOiB1bVZhbHVlKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgIGlmICgkLmlzRnVuY3Rpb24ob3B0cy5vblVuTWFzaykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlclZhbHVlID0gKGlzUlRMID8gZ2V0QnVmZmVyKCkuc2xpY2UoKS5yZXZlcnNlKCkgOiBnZXRCdWZmZXIoKSkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgdW5tYXNrZWRWYWx1ZSA9IG9wdHMub25Vbk1hc2suY2FsbChpbnB1dG1hc2ssIGJ1ZmZlclZhbHVlLCB1bm1hc2tlZFZhbHVlLCBvcHRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVubWFza2VkVmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBjYXJldChpbnB1dCwgYmVnaW4sIGVuZCwgbm90cmFuc2xhdGUpIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2xhdGVQb3NpdGlvbihwb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzUlRMICYmIHR5cGVvZiBwb3MgPT09IFwibnVtYmVyXCIgJiYgKCFvcHRzLmdyZWVkeSB8fCBvcHRzLnBsYWNlaG9sZGVyICE9PSBcIlwiKSAmJiBlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gZWwuaW5wdXRtYXNrLl92YWx1ZUdldCgpLmxlbmd0aCAtIHBvcztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcG9zO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcmFuZ2U7XG4gICAgICAgICAgICAgICAgaWYgKGJlZ2luICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaXNBcnJheShiZWdpbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IGlzUlRMID8gYmVnaW5bMF0gOiBiZWdpblsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luID0gaXNSVEwgPyBiZWdpblsxXSA6IGJlZ2luWzBdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChiZWdpbi5iZWdpbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBpc1JUTCA/IGJlZ2luLmJlZ2luIDogYmVnaW4uZW5kO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW4gPSBpc1JUTCA/IGJlZ2luLmVuZCA6IGJlZ2luLmJlZ2luO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYmVnaW4gPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luID0gbm90cmFuc2xhdGUgPyBiZWdpbiA6IHRyYW5zbGF0ZVBvc2l0aW9uKGJlZ2luKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IG5vdHJhbnNsYXRlID8gZW5kIDogdHJhbnNsYXRlUG9zaXRpb24oZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IHR5cGVvZiBlbmQgPT0gXCJudW1iZXJcIiA/IGVuZCA6IGJlZ2luO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHNjcm9sbENhbGMgPSBwYXJzZUludCgoKGlucHV0Lm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcgfHwgd2luZG93KS5nZXRDb21wdXRlZFN0eWxlID8gKGlucHV0Lm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcgfHwgd2luZG93KS5nZXRDb21wdXRlZFN0eWxlKGlucHV0LCBudWxsKSA6IGlucHV0LmN1cnJlbnRTdHlsZSkuZm9udFNpemUpICogZW5kO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2Nyb2xsTGVmdCA9IHNjcm9sbENhbGMgPiBpbnB1dC5zY3JvbGxXaWR0aCA/IHNjcm9sbENhbGMgOiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLmNhcmV0UG9zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiBiZWdpbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IGVuZFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dCA9PT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcInNlbGVjdGlvblN0YXJ0XCIgaW4gaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2VsZWN0aW9uU3RhcnQgPSBiZWdpbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2VsZWN0aW9uRW5kID0gZW5kO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAod2luZG93LmdldFNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5maXJzdENoaWxkID09PSB1bmRlZmluZWQgfHwgaW5wdXQuZmlyc3RDaGlsZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRleHROb2RlID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dC5hcHBlbmRDaGlsZCh0ZXh0Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2Uuc2V0U3RhcnQoaW5wdXQuZmlyc3RDaGlsZCwgYmVnaW4gPCBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkubGVuZ3RoID8gYmVnaW4gOiBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2Uuc2V0RW5kKGlucHV0LmZpcnN0Q2hpbGQsIGVuZCA8IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKS5sZW5ndGggPyBlbmQgOiBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UuY29sbGFwc2UodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZWwgPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbC5yZW1vdmVBbGxSYW5nZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsLmFkZFJhbmdlKHJhbmdlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlucHV0LmNyZWF0ZVRleHRSYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGlucHV0LmNyZWF0ZVRleHRSYW5nZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZS5jb2xsYXBzZSh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UubW92ZUVuZChcImNoYXJhY3RlclwiLCBlbmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZS5tb3ZlU3RhcnQoXCJjaGFyYWN0ZXJcIiwgYmVnaW4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZS5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyQ29sb3JNYXNrKGlucHV0LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiBiZWdpbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBlbmRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcInNlbGVjdGlvblN0YXJ0XCIgaW4gaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luID0gaW5wdXQuc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBpbnB1dC5zZWxlY3Rpb25FbmQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAod2luZG93LmdldFNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCkuZ2V0UmFuZ2VBdCgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYW5nZS5jb21tb25BbmNlc3RvckNvbnRhaW5lci5wYXJlbnROb2RlID09PSBpbnB1dCB8fCByYW5nZS5jb21tb25BbmNlc3RvckNvbnRhaW5lciA9PT0gaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbiA9IHJhbmdlLnN0YXJ0T2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IHJhbmdlLmVuZE9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkb2N1bWVudC5zZWxlY3Rpb24gJiYgZG9jdW1lbnQuc2VsZWN0aW9uLmNyZWF0ZVJhbmdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGRvY3VtZW50LnNlbGVjdGlvbi5jcmVhdGVSYW5nZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW4gPSAwIC0gcmFuZ2UuZHVwbGljYXRlKCkubW92ZVN0YXJ0KFwiY2hhcmFjdGVyXCIsIC1pbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IGJlZ2luICsgcmFuZ2UudGV4dC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiBub3RyYW5zbGF0ZSA/IGJlZ2luIDogdHJhbnNsYXRlUG9zaXRpb24oYmVnaW4pLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBub3RyYW5zbGF0ZSA/IGVuZCA6IHRyYW5zbGF0ZVBvc2l0aW9uKGVuZClcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBkZXRlcm1pbmVMYXN0UmVxdWlyZWRQb3NpdGlvbihyZXR1cm5EZWZpbml0aW9uKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IGdldE1hc2tUZW1wbGF0ZSh0cnVlLCBnZXRMYXN0VmFsaWRQb3NpdGlvbigpLCB0cnVlLCB0cnVlKSwgYmwgPSBidWZmZXIubGVuZ3RoLCBwb3MsIGx2cCA9IGdldExhc3RWYWxpZFBvc2l0aW9uKCksIHBvc2l0aW9ucyA9IHt9LCBsdlRlc3QgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbbHZwXSwgbmR4SW50bHpyID0gbHZUZXN0ICE9PSB1bmRlZmluZWQgPyBsdlRlc3QubG9jYXRvci5zbGljZSgpIDogdW5kZWZpbmVkLCB0ZXN0UG9zO1xuICAgICAgICAgICAgICAgIGZvciAocG9zID0gbHZwICsgMTsgcG9zIDwgYnVmZmVyLmxlbmd0aDsgcG9zKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IGdldFRlc3RUZW1wbGF0ZShwb3MsIG5keEludGx6ciwgcG9zIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIG5keEludGx6ciA9IHRlc3RQb3MubG9jYXRvci5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbcG9zXSA9ICQuZXh0ZW5kKHRydWUsIHt9LCB0ZXN0UG9zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGx2VGVzdEFsdCA9IGx2VGVzdCAmJiBsdlRlc3QuYWx0ZXJuYXRpb24gIT09IHVuZGVmaW5lZCA/IGx2VGVzdC5sb2NhdG9yW2x2VGVzdC5hbHRlcm5hdGlvbl0gOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgZm9yIChwb3MgPSBibCAtIDE7IHBvcyA+IGx2cDsgcG9zLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IHBvc2l0aW9uc1twb3NdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHRlc3RQb3MubWF0Y2gub3B0aW9uYWxpdHkgfHwgdGVzdFBvcy5tYXRjaC5vcHRpb25hbFF1YW50aWZpZXIgJiYgdGVzdFBvcy5tYXRjaC5uZXdCbG9ja01hcmtlciB8fCBsdlRlc3RBbHQgJiYgKGx2VGVzdEFsdCAhPT0gcG9zaXRpb25zW3Bvc10ubG9jYXRvcltsdlRlc3QuYWx0ZXJuYXRpb25dICYmIHRlc3RQb3MubWF0Y2guZm4gIT0gbnVsbCB8fCB0ZXN0UG9zLm1hdGNoLmZuID09PSBudWxsICYmIHRlc3RQb3MubG9jYXRvcltsdlRlc3QuYWx0ZXJuYXRpb25dICYmIGNoZWNrQWx0ZXJuYXRpb25NYXRjaCh0ZXN0UG9zLmxvY2F0b3JbbHZUZXN0LmFsdGVybmF0aW9uXS50b1N0cmluZygpLnNwbGl0KFwiLFwiKSwgbHZUZXN0QWx0LnRvU3RyaW5nKCkuc3BsaXQoXCIsXCIpKSAmJiBnZXRUZXN0cyhwb3MpWzBdLmRlZiAhPT0gXCJcIikpICYmIGJ1ZmZlcltwb3NdID09PSBnZXRQbGFjZWhvbGRlcihwb3MsIHRlc3RQb3MubWF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBibC0tO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXR1cm5EZWZpbml0aW9uID8ge1xuICAgICAgICAgICAgICAgICAgICBsOiBibCxcbiAgICAgICAgICAgICAgICAgICAgZGVmOiBwb3NpdGlvbnNbYmxdID8gcG9zaXRpb25zW2JsXS5tYXRjaCA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIH0gOiBibDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyT3B0aW9uYWxUYWlsKGJ1ZmZlcikge1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5sZW5ndGggPSAwO1xuICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IGdldE1hc2tUZW1wbGF0ZSh0cnVlLCAwLCB0cnVlLCB1bmRlZmluZWQsIHRydWUpLCBsbW50LCB2YWxpZFBvcztcbiAgICAgICAgICAgICAgICB3aGlsZSAobG1udCA9IHRlbXBsYXRlLnNoaWZ0KCksIGxtbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBidWZmZXIucHVzaChsbW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ29tcGxldGUoYnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCQuaXNGdW5jdGlvbihvcHRzLmlzQ29tcGxldGUpKSByZXR1cm4gb3B0cy5pc0NvbXBsZXRlKGJ1ZmZlciwgb3B0cyk7XG4gICAgICAgICAgICAgICAgaWYgKG9wdHMucmVwZWF0ID09PSBcIipcIikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB2YXIgY29tcGxldGUgPSBmYWxzZSwgbHJwID0gZGV0ZXJtaW5lTGFzdFJlcXVpcmVkUG9zaXRpb24odHJ1ZSksIGFtbCA9IHNlZWtQcmV2aW91cyhscnAubCk7XG4gICAgICAgICAgICAgICAgaWYgKGxycC5kZWYgPT09IHVuZGVmaW5lZCB8fCBscnAuZGVmLm5ld0Jsb2NrTWFya2VyIHx8IGxycC5kZWYub3B0aW9uYWxpdHkgfHwgbHJwLmRlZi5vcHRpb25hbFF1YW50aWZpZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8PSBhbWw7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRlc3QgPSBnZXRUZXN0VGVtcGxhdGUoaSkubWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGVzdC5mbiAhPT0gbnVsbCAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbaV0gPT09IHVuZGVmaW5lZCAmJiB0ZXN0Lm9wdGlvbmFsaXR5ICE9PSB0cnVlICYmIHRlc3Qub3B0aW9uYWxRdWFudGlmaWVyICE9PSB0cnVlIHx8IHRlc3QuZm4gPT09IG51bGwgJiYgYnVmZmVyW2ldICE9PSBnZXRQbGFjZWhvbGRlcihpLCB0ZXN0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbXBsZXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlUmVtb3ZlKGlucHV0LCBrLCBwb3MsIHN0cmljdCwgZnJvbUlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICBpZiAob3B0cy5udW1lcmljSW5wdXQgfHwgaXNSVEwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLkJBQ0tTUEFDRSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgayA9IElucHV0bWFzay5rZXlDb2RlLkRFTEVURTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChrID09PSBJbnB1dG1hc2sua2V5Q29kZS5ERUxFVEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGsgPSBJbnB1dG1hc2sua2V5Q29kZS5CQUNLU1BBQ0U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcGVuZCA9IHBvcy5lbmQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3MuZW5kID0gcG9zLmJlZ2luO1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmJlZ2luID0gcGVuZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoayA9PT0gSW5wdXRtYXNrLmtleUNvZGUuQkFDS1NQQUNFICYmIHBvcy5lbmQgLSBwb3MuYmVnaW4gPCAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvcy5iZWdpbiA9IHNlZWtQcmV2aW91cyhwb3MuYmVnaW4pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvcy5iZWdpbl0gIT09IHVuZGVmaW5lZCAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zLmJlZ2luXS5pbnB1dCA9PT0gb3B0cy5ncm91cFNlcGFyYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zLmJlZ2luLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGsgPT09IElucHV0bWFzay5rZXlDb2RlLkRFTEVURSAmJiBwb3MuYmVnaW4gPT09IHBvcy5lbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zLmVuZCA9IGlzTWFzayhwb3MuZW5kLCB0cnVlKSAmJiBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zLmVuZF0gJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvcy5lbmRdLmlucHV0ICE9PSBvcHRzLnJhZGl4UG9pbnQgPyBwb3MuZW5kICsgMSA6IHNlZWtOZXh0KHBvcy5lbmQpICsgMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3MuYmVnaW5dICE9PSB1bmRlZmluZWQgJiYgZ2V0TWFza1NldCgpLnZhbGlkUG9zaXRpb25zW3Bvcy5iZWdpbl0uaW5wdXQgPT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5lbmQrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXZhbGlkYXRlTWFzayhwb3MpO1xuICAgICAgICAgICAgICAgIGlmIChzdHJpY3QgIT09IHRydWUgJiYgb3B0cy5rZWVwU3RhdGljICE9PSBmYWxzZSB8fCBvcHRzLnJlZ2V4ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBhbHRlcm5hdGUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdQb3MgPSByZXN1bHQuY2FyZXQgIT09IHVuZGVmaW5lZCA/IHJlc3VsdC5jYXJldCA6IHJlc3VsdC5wb3MgPyBzZWVrTmV4dChyZXN1bHQucG9zLmJlZ2luID8gcmVzdWx0LnBvcy5iZWdpbiA6IHJlc3VsdC5wb3MpIDogZ2V0TGFzdFZhbGlkUG9zaXRpb24oLTEsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGsgIT09IElucHV0bWFzay5rZXlDb2RlLkRFTEVURSB8fCBwb3MuYmVnaW4gPiBuZXdQb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MuYmVnaW4gPT0gbmV3UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsdnAgPSBnZXRMYXN0VmFsaWRQb3NpdGlvbihwb3MuYmVnaW4sIHRydWUpO1xuICAgICAgICAgICAgICAgIGlmIChsdnAgPCBwb3MuYmVnaW4gfHwgcG9zLmJlZ2luID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBnZXRNYXNrU2V0KCkucCA9IHNlZWtOZXh0KGx2cCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdHJpY3QgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0TWFza1NldCgpLnAgPSBwb3MuYmVnaW47XG4gICAgICAgICAgICAgICAgICAgIGlmIChmcm9tSXNWYWxpZCAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGdldE1hc2tTZXQoKS5wIDwgbHZwICYmIGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1tnZXRNYXNrU2V0KCkucF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1hc2tTZXQoKS5wKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBpbml0aWFsaXplQ29sb3JNYXNrKGlucHV0KSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbXB1dGVkU3R5bGUgPSAoaW5wdXQub3duZXJEb2N1bWVudC5kZWZhdWx0VmlldyB8fCB3aW5kb3cpLmdldENvbXB1dGVkU3R5bGUoaW5wdXQsIG51bGwpO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGZpbmRDYXJldFBvcyhjbGllbnR4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIiksIGNhcmV0UG9zO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBzdHlsZSBpbiBjb21wdXRlZFN0eWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNOYU4oc3R5bGUpICYmIHN0eWxlLmluZGV4T2YoXCJmb250XCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuc3R5bGVbc3R5bGVdID0gY29tcHV0ZWRTdHlsZVtzdHlsZV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZS5zdHlsZS50ZXh0VHJhbnNmb3JtID0gY29tcHV0ZWRTdHlsZS50ZXh0VHJhbnNmb3JtO1xuICAgICAgICAgICAgICAgICAgICBlLnN0eWxlLmxldHRlclNwYWNpbmcgPSBjb21wdXRlZFN0eWxlLmxldHRlclNwYWNpbmc7XG4gICAgICAgICAgICAgICAgICAgIGUuc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCI7XG4gICAgICAgICAgICAgICAgICAgIGUuc3R5bGUuaGVpZ2h0ID0gXCJhdXRvXCI7XG4gICAgICAgICAgICAgICAgICAgIGUuc3R5bGUud2lkdGggPSBcImF1dG9cIjtcbiAgICAgICAgICAgICAgICAgICAgZS5zdHlsZS52aXNpYmlsaXR5ID0gXCJoaWRkZW5cIjtcbiAgICAgICAgICAgICAgICAgICAgZS5zdHlsZS53aGl0ZVNwYWNlID0gXCJub3dyYXBcIjtcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChlKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0VGV4dCA9IGlucHV0LmlucHV0bWFzay5fdmFsdWVHZXQoKSwgcHJldmlvdXNXaWR0aCA9IDAsIGl0bDtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjYXJldFBvcyA9IDAsIGl0bCA9IGlucHV0VGV4dC5sZW5ndGg7IGNhcmV0UG9zIDw9IGl0bDsgY2FyZXRQb3MrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5pbm5lckhUTUwgKz0gaW5wdXRUZXh0LmNoYXJBdChjYXJldFBvcykgfHwgXCJfXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS5vZmZzZXRXaWR0aCA+PSBjbGllbnR4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9mZnNldDEgPSBjbGllbnR4IC0gcHJldmlvdXNXaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2Zmc2V0MiA9IGUub2Zmc2V0V2lkdGggLSBjbGllbnR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuaW5uZXJIVE1MID0gaW5wdXRUZXh0LmNoYXJBdChjYXJldFBvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MSAtPSBlLm9mZnNldFdpZHRoIC8gMztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvcyA9IG9mZnNldDEgPCBvZmZzZXQyID8gY2FyZXRQb3MgLSAxIDogY2FyZXRQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1dpZHRoID0gZS5vZmZzZXRXaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGUpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FyZXRQb3M7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgICAgICAgICAgdGVtcGxhdGUuc3R5bGUud2lkdGggPSBjb21wdXRlZFN0eWxlLndpZHRoO1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlLnN0eWxlLnRleHRBbGlnbiA9IGNvbXB1dGVkU3R5bGUudGV4dEFsaWduO1xuICAgICAgICAgICAgICAgIGNvbG9yTWFzayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLmNvbG9yTWFzayA9IGNvbG9yTWFzaztcbiAgICAgICAgICAgICAgICBjb2xvck1hc2suY2xhc3NOYW1lID0gXCJpbS1jb2xvcm1hc2tcIjtcbiAgICAgICAgICAgICAgICBpbnB1dC5wYXJlbnROb2RlLmluc2VydEJlZm9yZShjb2xvck1hc2ssIGlucHV0KTtcbiAgICAgICAgICAgICAgICBpbnB1dC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGlucHV0KTtcbiAgICAgICAgICAgICAgICBjb2xvck1hc2suYXBwZW5kQ2hpbGQoaW5wdXQpO1xuICAgICAgICAgICAgICAgIGNvbG9yTWFzay5hcHBlbmRDaGlsZCh0ZW1wbGF0ZSk7XG4gICAgICAgICAgICAgICAgaW5wdXQuc3R5bGUubGVmdCA9IHRlbXBsYXRlLm9mZnNldExlZnQgKyBcInB4XCI7XG4gICAgICAgICAgICAgICAgJChjb2xvck1hc2spLm9uKFwibW91c2VsZWF2ZVwiLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBFdmVudEhhbmRsZXJzLm1vdXNlbGVhdmVFdmVudC5jYWxsKGlucHV0LCBbIGUgXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgJChjb2xvck1hc2spLm9uKFwibW91c2VlbnRlclwiLCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBFdmVudEhhbmRsZXJzLm1vdXNlZW50ZXJFdmVudC5jYWxsKGlucHV0LCBbIGUgXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgJChjb2xvck1hc2spLm9uKFwiY2xpY2tcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXJldChpbnB1dCwgZmluZENhcmV0UG9zKGUuY2xpZW50WCkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRXZlbnRIYW5kbGVycy5jbGlja0V2ZW50LmNhbGwoaW5wdXQsIFsgZSBdKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlckNvbG9yTWFzayhpbnB1dCwgY2FyZXRQb3MsIGNsZWFyKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hc2tUZW1wbGF0ZSA9IFtdLCBpc1N0YXRpYyA9IGZhbHNlLCB0ZXN0LCB0ZXN0UG9zLCBuZHhJbnRsenIsIHBvcyA9IDA7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gc2V0RW50cnkoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVudHJ5ID09PSB1bmRlZmluZWQpIGVudHJ5ID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1N0YXRpYyAmJiAodGVzdC5mbiA9PT0gbnVsbCB8fCB0ZXN0UG9zLmlucHV0ID09PSB1bmRlZmluZWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1N0YXRpYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrVGVtcGxhdGUucHVzaChcIjxzcGFuIGNsYXNzPSdpbS1zdGF0aWMnPlwiICsgZW50cnkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzU3RhdGljICYmICh0ZXN0LmZuICE9PSBudWxsICYmIHRlc3RQb3MuaW5wdXQgIT09IHVuZGVmaW5lZCB8fCB0ZXN0LmRlZiA9PT0gXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzU3RhdGljID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbXRsID0gbWFza1RlbXBsYXRlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUZW1wbGF0ZVttdGwgLSAxXSA9IG1hc2tUZW1wbGF0ZVttdGwgLSAxXSArIFwiPC9zcGFuPlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFza1RlbXBsYXRlLnB1c2goZW50cnkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgbWFza1RlbXBsYXRlLnB1c2goZW50cnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBzZXRDYXJldCgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrVGVtcGxhdGUuc3BsaWNlKGNhcmV0UG9zLmJlZ2luLCAwLCBjYXJldFBvcy5iZWdpbiA9PT0gY2FyZXRQb3MuZW5kIHx8IGNhcmV0UG9zLmVuZCA+IGdldE1hc2tTZXQoKS5tYXNrTGVuZ3RoID8gJzxtYXJrIGNsYXNzPVwiaW0tY2FyZXRcIiBzdHlsZT1cImJvcmRlci1yaWdodC13aWR0aDogMXB4O2JvcmRlci1yaWdodC1zdHlsZTogc29saWQ7XCI+JyA6ICc8bWFyayBjbGFzcz1cImltLWNhcmV0LXNlbGVjdFwiPicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFza1RlbXBsYXRlLnNwbGljZShjYXJldFBvcy5lbmQgKyAxLCAwLCBcIjwvbWFyaz5cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGNvbG9yTWFzayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSBnZXRCdWZmZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhcmV0UG9zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zID0gY2FyZXQoaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNhcmV0UG9zLmJlZ2luID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luOiBjYXJldFBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IGNhcmV0UG9zXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChjbGVhciAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGx2cCA9IGdldExhc3RWYWxpZFBvc2l0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldE1hc2tTZXQoKS52YWxpZFBvc2l0aW9uc1twb3NdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RQb3MgPSBnZXRNYXNrU2V0KCkudmFsaWRQb3NpdGlvbnNbcG9zXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9IHRlc3RQb3MubWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5keEludGx6ciA9IHRlc3RQb3MubG9jYXRvci5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRFbnRyeShidWZmZXJbcG9zXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdFBvcyA9IGdldFRlc3RUZW1wbGF0ZShwb3MsIG5keEludGx6ciwgcG9zIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSB0ZXN0UG9zLm1hdGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZHhJbnRsenIgPSB0ZXN0UG9zLmxvY2F0b3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuaml0TWFza2luZyA9PT0gZmFsc2UgfHwgcG9zIDwgbHZwIHx8IHR5cGVvZiBvcHRzLmppdE1hc2tpbmcgPT09IFwibnVtYmVyXCIgJiYgaXNGaW5pdGUob3B0cy5qaXRNYXNraW5nKSAmJiBvcHRzLmppdE1hc2tpbmcgPiBwb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldEVudHJ5KGdldFBsYWNlaG9sZGVyKHBvcywgdGVzdCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaXNTdGF0aWMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IHdoaWxlICgobWF4TGVuZ3RoID09PSB1bmRlZmluZWQgfHwgcG9zIDwgbWF4TGVuZ3RoKSAmJiAodGVzdC5mbiAhPT0gbnVsbCB8fCB0ZXN0LmRlZiAhPT0gXCJcIikgfHwgbHZwID4gcG9zIHx8IGlzU3RhdGljKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1N0YXRpYykgc2V0RW50cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldENhcmV0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHRlbXBsYXRlID0gY29sb3JNYXNrLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiZGl2XCIpWzBdO1xuICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5pbm5lckhUTUwgPSBtYXNrVGVtcGxhdGUuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuaW5wdXRtYXNrLnBvc2l0aW9uQ29sb3JNYXNrKGlucHV0LCB0ZW1wbGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gbWFzayhlbGVtKSB7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNFbGVtZW50VHlwZVN1cHBvcnRlZChpbnB1dCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFZhbHVlUHJvcGVydHkobnB0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVHZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVTZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFZhbGhvb2sodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkLnZhbEhvb2tzICYmICgkLnZhbEhvb2tzW3R5cGVdID09PSB1bmRlZmluZWQgfHwgJC52YWxIb29rc1t0eXBlXS5pbnB1dG1hc2twYXRjaCAhPT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbGhvb2tHZXQgPSAkLnZhbEhvb2tzW3R5cGVdICYmICQudmFsSG9va3NbdHlwZV0uZ2V0ID8gJC52YWxIb29rc1t0eXBlXS5nZXQgOiBmdW5jdGlvbihlbGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZWxlbS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbGhvb2tTZXQgPSAkLnZhbEhvb2tzW3R5cGVdICYmICQudmFsSG9va3NbdHlwZV0uc2V0ID8gJC52YWxIb29rc1t0eXBlXS5zZXQgOiBmdW5jdGlvbihlbGVtLCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQudmFsSG9va3NbdHlwZV0gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldChlbGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW0uaW5wdXRtYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtLmlucHV0bWFzay5vcHRzLmF1dG9Vbm1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtLmlucHV0bWFzay51bm1hc2tlZHZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gdmFsaG9va0dldChlbGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBnZXRMYXN0VmFsaWRQb3NpdGlvbih1bmRlZmluZWQsIHVuZGVmaW5lZCwgZWxlbS5pbnB1dG1hc2subWFza3NldC52YWxpZFBvc2l0aW9ucykgIT09IC0xIHx8IG9wdHMubnVsbGFibGUgIT09IHRydWUgPyByZXN1bHQgOiBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHJldHVybiB2YWxob29rR2V0KGVsZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gc2V0KGVsZW0sIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICRlbGVtID0gJChlbGVtKSwgcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbGhvb2tTZXQoZWxlbSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtLmlucHV0bWFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZWxlbS50cmlnZ2VyKFwic2V0dmFsdWVcIiwgWyB2YWx1ZSBdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dG1hc2twYXRjaDogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldHRlcigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dG1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRtYXNrLm9wdHMuYXV0b1VubWFzayA/IHRoaXMuaW5wdXRtYXNrLnVubWFza2VkdmFsdWUoKSA6IGdldExhc3RWYWxpZFBvc2l0aW9uKCkgIT09IC0xIHx8IG9wdHMubnVsbGFibGUgIT09IHRydWUgPyBkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSB0aGlzICYmIG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgPyAoaXNSVEwgPyBjbGVhck9wdGlvbmFsVGFpbChnZXRCdWZmZXIoKS5zbGljZSgpKS5yZXZlcnNlKCkgOiBjbGVhck9wdGlvbmFsVGFpbChnZXRCdWZmZXIoKS5zbGljZSgpKSkuam9pbihcIlwiKSA6IHZhbHVlR2V0LmNhbGwodGhpcykgOiBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSByZXR1cm4gdmFsdWVHZXQuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHNldHRlcih2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlU2V0LmNhbGwodGhpcywgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0bWFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnRyaWdnZXIoXCJzZXR2YWx1ZVwiLCBbIHZhbHVlIF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGluc3RhbGxOYXRpdmVWYWx1ZVNldEZhbGxiYWNrKG5wdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24obnB0LCBcIm1vdXNlZW50ZXJcIiwgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCA9ICQodGhpcyksIGlucHV0ID0gdGhpcywgdmFsdWUgPSBpbnB1dC5pbnB1dG1hc2suX3ZhbHVlR2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSAhPT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJzZXR2YWx1ZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFucHQuaW5wdXRtYXNrLl9fdmFsdWVHZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5ub1ZhbHVlUGF0Y2hpbmcgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgT2JqZWN0LmdldFByb3RvdHlwZU9mICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YgPSBfdHlwZW9mKFwidGVzdFwiLl9fcHJvdG9fXykgPT09IFwib2JqZWN0XCIgPyBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdC5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA6IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0LmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlUHJvcGVydHkgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YgPyBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE9iamVjdC5nZXRQcm90b3R5cGVPZihucHQpLCBcInZhbHVlXCIpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlUHJvcGVydHkgJiYgdmFsdWVQcm9wZXJ0eS5nZXQgJiYgdmFsdWVQcm9wZXJ0eS5zZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUdldCA9IHZhbHVlUHJvcGVydHkuZ2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlU2V0ID0gdmFsdWVQcm9wZXJ0eS5zZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG5wdCwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldDogZ2V0dGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXQ6IHNldHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG5wdC50YWdOYW1lICE9PSBcIklOUFVUXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUdldCA9IGZ1bmN0aW9uIHZhbHVlR2V0KCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50ZXh0Q29udGVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlU2V0ID0gZnVuY3Rpb24gdmFsdWVTZXQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0Q29udGVudCA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG5wdCwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldDogZ2V0dGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXQ6IHNldHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZG9jdW1lbnQuX19sb29rdXBHZXR0ZXJfXyAmJiBucHQuX19sb29rdXBHZXR0ZXJfXyhcInZhbHVlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUdldCA9IG5wdC5fX2xvb2t1cEdldHRlcl9fKFwidmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVNldCA9IG5wdC5fX2xvb2t1cFNldHRlcl9fKFwidmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBucHQuX19kZWZpbmVHZXR0ZXJfXyhcInZhbHVlXCIsIGdldHRlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBucHQuX19kZWZpbmVTZXR0ZXJfXyhcInZhbHVlXCIsIHNldHRlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnB0LmlucHV0bWFzay5fX3ZhbHVlR2V0ID0gdmFsdWVHZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5wdC5pbnB1dG1hc2suX192YWx1ZVNldCA9IHZhbHVlU2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBucHQuaW5wdXRtYXNrLl92YWx1ZUdldCA9IGZ1bmN0aW9uKG92ZXJydWxlUlRMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1JUTCAmJiBvdmVycnVsZVJUTCAhPT0gdHJ1ZSA/IHZhbHVlR2V0LmNhbGwodGhpcy5lbCkuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiB2YWx1ZUdldC5jYWxsKHRoaXMuZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbnB0LmlucHV0bWFzay5fdmFsdWVTZXQgPSBmdW5jdGlvbih2YWx1ZSwgb3ZlcnJ1bGVSVEwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVTZXQuY2FsbCh0aGlzLmVsLCB2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gXCJcIiA6IG92ZXJydWxlUlRMICE9PSB0cnVlICYmIGlzUlRMID8gdmFsdWUuc3BsaXQoXCJcIikucmV2ZXJzZSgpLmpvaW4oXCJcIikgOiB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWVHZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUdldCA9IGZ1bmN0aW9uIHZhbHVlR2V0KCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlU2V0ID0gZnVuY3Rpb24gdmFsdWVTZXQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hWYWxob29rKG5wdC50eXBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zdGFsbE5hdGl2ZVZhbHVlU2V0RmFsbGJhY2sobnB0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGVsZW1lbnRUeXBlID0gaW5wdXQuZ2V0QXR0cmlidXRlKFwidHlwZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlzU3VwcG9ydGVkID0gaW5wdXQudGFnTmFtZSA9PT0gXCJJTlBVVFwiICYmICQuaW5BcnJheShlbGVtZW50VHlwZSwgb3B0cy5zdXBwb3J0c0lucHV0VHlwZSkgIT09IC0xIHx8IGlucHV0LmlzQ29udGVudEVkaXRhYmxlIHx8IGlucHV0LnRhZ05hbWUgPT09IFwiVEVYVEFSRUFcIjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1N1cHBvcnRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LnRhZ05hbWUgPT09IFwiSU5QVVRcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoXCJ0eXBlXCIsIGVsZW1lbnRUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1N1cHBvcnRlZCA9IGVsLnR5cGUgPT09IFwidGV4dFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpc1N1cHBvcnRlZCA9IFwicGFydGlhbFwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1N1cHBvcnRlZCAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoVmFsdWVQcm9wZXJ0eShpbnB1dCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpbnB1dC5pbnB1dG1hc2sgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1N1cHBvcnRlZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vZmYoZWxlbSk7XG4gICAgICAgICAgICAgICAgdmFyIGlzU3VwcG9ydGVkID0gaXNFbGVtZW50VHlwZVN1cHBvcnRlZChlbGVtLCBvcHRzKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNTdXBwb3J0ZWQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsID0gZWxlbTtcbiAgICAgICAgICAgICAgICAgICAgJGVsID0gJChlbCk7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbmFsUGxhY2Vob2xkZXIgPSBlbC5wbGFjZWhvbGRlcjtcbiAgICAgICAgICAgICAgICAgICAgbWF4TGVuZ3RoID0gZWwgIT09IHVuZGVmaW5lZCA/IGVsLm1heExlbmd0aCA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1heExlbmd0aCA9PT0gLTEpIG1heExlbmd0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY29sb3JNYXNrID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsaXplQ29sb3JNYXNrKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobW9iaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJpbnB1dG1vZGVcIiBpbiBlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bW9kZSA9IG9wdHMuaW5wdXRtb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLnNldEF0dHJpYnV0ZShcImlucHV0bW9kZVwiLCBvcHRzLmlucHV0bW9kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5kaXNhYmxlUHJlZGljdGl2ZVRleHQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJhdXRvY29ycmVjdFwiIGluIGVsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLmF1dG9jb3JyZWN0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY29sb3JNYXNrICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsaXplQ29sb3JNYXNrKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC50eXBlID0gXCJwYXNzd29yZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNTdXBwb3J0ZWQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsLnNldEF0dHJpYnV0ZShcImltLWluc2VydFwiLCBvcHRzLmluc2VydE1vZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJzdWJtaXRcIiwgRXZlbnRIYW5kbGVycy5zdWJtaXRFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcInJlc2V0XCIsIEV2ZW50SGFuZGxlcnMucmVzZXRFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcImJsdXJcIiwgRXZlbnRIYW5kbGVycy5ibHVyRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJmb2N1c1wiLCBFdmVudEhhbmRsZXJzLmZvY3VzRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY29sb3JNYXNrICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJjbGlja1wiLCBFdmVudEhhbmRsZXJzLmNsaWNrRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwibW91c2VsZWF2ZVwiLCBFdmVudEhhbmRsZXJzLm1vdXNlbGVhdmVFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJtb3VzZWVudGVyXCIsIEV2ZW50SGFuZGxlcnMubW91c2VlbnRlckV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwicGFzdGVcIiwgRXZlbnRIYW5kbGVycy5wYXN0ZUV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiY3V0XCIsIEV2ZW50SGFuZGxlcnMuY3V0RXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJjb21wbGV0ZVwiLCBvcHRzLm9uY29tcGxldGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJpbmNvbXBsZXRlXCIsIG9wdHMub25pbmNvbXBsZXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiY2xlYXJlZFwiLCBvcHRzLm9uY2xlYXJlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW1vYmlsZSAmJiBvcHRzLmlucHV0RXZlbnRPbmx5ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJrZXlkb3duXCIsIEV2ZW50SGFuZGxlcnMua2V5ZG93bkV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudFJ1bGVyLm9uKGVsLCBcImtleXByZXNzXCIsIEV2ZW50SGFuZGxlcnMua2V5cHJlc3NFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsLnJlbW92ZUF0dHJpYnV0ZShcIm1heExlbmd0aFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwiaW5wdXRcIiwgRXZlbnRIYW5kbGVycy5pbnB1dEZhbGxCYWNrRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRSdWxlci5vbihlbCwgXCJiZWZvcmVpbnB1dFwiLCBFdmVudEhhbmRsZXJzLmJlZm9yZUlucHV0RXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub24oZWwsIFwic2V0dmFsdWVcIiwgRXZlbnRIYW5kbGVycy5zZXRWYWx1ZUV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgdW5kb1ZhbHVlID0gZ2V0QnVmZmVyVGVtcGxhdGUoKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWwuaW5wdXRtYXNrLl92YWx1ZUdldCh0cnVlKSAhPT0gXCJcIiB8fCBvcHRzLmNsZWFyTWFza09uTG9zdEZvY3VzID09PSBmYWxzZSB8fCBkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSBlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGluaXRpYWxWYWx1ZSA9ICQuaXNGdW5jdGlvbihvcHRzLm9uQmVmb3JlTWFzaykgPyBvcHRzLm9uQmVmb3JlTWFzay5jYWxsKGlucHV0bWFzaywgZWwuaW5wdXRtYXNrLl92YWx1ZUdldCh0cnVlKSwgb3B0cykgfHwgZWwuaW5wdXRtYXNrLl92YWx1ZUdldCh0cnVlKSA6IGVsLmlucHV0bWFzay5fdmFsdWVHZXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5pdGlhbFZhbHVlICE9PSBcIlwiKSBjaGVja1ZhbChlbCwgdHJ1ZSwgZmFsc2UsIGluaXRpYWxWYWx1ZS5zcGxpdChcIlwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gZ2V0QnVmZmVyKCkuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVuZG9WYWx1ZSA9IGJ1ZmZlci5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzQ29tcGxldGUoYnVmZmVyKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5jbGVhckluY29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRNYXNrU2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuY2xlYXJNYXNrT25Mb3N0Rm9jdXMgJiYgZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAhPT0gZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJPcHRpb25hbFRhaWwoYnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5jbGVhck1hc2tPbkxvc3RGb2N1cyA9PT0gZmFsc2UgfHwgb3B0cy5zaG93TWFza09uRm9jdXMgJiYgZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZWwgfHwgZWwuaW5wdXRtYXNrLl92YWx1ZUdldCh0cnVlKSAhPT0gXCJcIikgd3JpdGVCdWZmZXIoZWwsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldChlbCwgc2Vla05leHQoZ2V0TGFzdFZhbGlkUG9zaXRpb24oKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHZhbHVlQnVmZmVyO1xuICAgICAgICAgICAgaWYgKGFjdGlvbk9iaiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChhY3Rpb25PYmouYWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICBjYXNlIFwiaXNDb21wbGV0ZVwiOlxuICAgICAgICAgICAgICAgICAgICBlbCA9IGFjdGlvbk9iai5lbDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzQ29tcGxldGUoZ2V0QnVmZmVyKCkpO1xuXG4gICAgICAgICAgICAgICAgICBjYXNlIFwidW5tYXNrZWR2YWx1ZVwiOlxuICAgICAgICAgICAgICAgICAgICBpZiAoZWwgPT09IHVuZGVmaW5lZCB8fCBhY3Rpb25PYmoudmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVCdWZmZXIgPSBhY3Rpb25PYmoudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUJ1ZmZlciA9ICgkLmlzRnVuY3Rpb24ob3B0cy5vbkJlZm9yZU1hc2spID8gb3B0cy5vbkJlZm9yZU1hc2suY2FsbChpbnB1dG1hc2ssIHZhbHVlQnVmZmVyLCBvcHRzKSB8fCB2YWx1ZUJ1ZmZlciA6IHZhbHVlQnVmZmVyKS5zcGxpdChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrVmFsLmNhbGwodGhpcywgdW5kZWZpbmVkLCBmYWxzZSwgZmFsc2UsIHZhbHVlQnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkLmlzRnVuY3Rpb24ob3B0cy5vbkJlZm9yZVdyaXRlKSkgb3B0cy5vbkJlZm9yZVdyaXRlLmNhbGwoaW5wdXRtYXNrLCB1bmRlZmluZWQsIGdldEJ1ZmZlcigpLCAwLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdW5tYXNrZWR2YWx1ZShlbCk7XG5cbiAgICAgICAgICAgICAgICAgIGNhc2UgXCJtYXNrXCI6XG4gICAgICAgICAgICAgICAgICAgIG1hc2soZWwpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcImZvcm1hdFwiOlxuICAgICAgICAgICAgICAgICAgICB2YWx1ZUJ1ZmZlciA9ICgkLmlzRnVuY3Rpb24ob3B0cy5vbkJlZm9yZU1hc2spID8gb3B0cy5vbkJlZm9yZU1hc2suY2FsbChpbnB1dG1hc2ssIGFjdGlvbk9iai52YWx1ZSwgb3B0cykgfHwgYWN0aW9uT2JqLnZhbHVlIDogYWN0aW9uT2JqLnZhbHVlKS5zcGxpdChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tWYWwuY2FsbCh0aGlzLCB1bmRlZmluZWQsIHRydWUsIGZhbHNlLCB2YWx1ZUJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhY3Rpb25PYmoubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGlzUlRMID8gZ2V0QnVmZmVyKCkuc2xpY2UoKS5yZXZlcnNlKCkuam9pbihcIlwiKSA6IGdldEJ1ZmZlcigpLmpvaW4oXCJcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IG1hc2tTY29wZS5jYWxsKHRoaXMsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcImdldG1ldGFkYXRhXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBtYXNrc2V0LCBvcHRzKVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNSVEwgPyBnZXRCdWZmZXIoKS5zbGljZSgpLnJldmVyc2UoKS5qb2luKFwiXCIpIDogZ2V0QnVmZmVyKCkuam9pbihcIlwiKTtcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcImlzVmFsaWRcIjpcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFjdGlvbk9iai52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVCdWZmZXIgPSBhY3Rpb25PYmoudmFsdWUuc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGVja1ZhbC5jYWxsKHRoaXMsIHVuZGVmaW5lZCwgdHJ1ZSwgdHJ1ZSwgdmFsdWVCdWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uT2JqLnZhbHVlID0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gZ2V0QnVmZmVyKCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBybCA9IGRldGVybWluZUxhc3RSZXF1aXJlZFBvc2l0aW9uKCksIGxtaWIgPSBidWZmZXIubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICg7bG1pYiA+IHJsOyBsbWliLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc01hc2sobG1pYikpIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlci5zcGxpY2UocmwsIGxtaWIgKyAxIC0gcmwpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNDb21wbGV0ZShidWZmZXIpICYmIGFjdGlvbk9iai52YWx1ZSA9PT0gZ2V0QnVmZmVyKCkuam9pbihcIlwiKTtcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcImdldGVtcHR5bWFza1wiOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2V0QnVmZmVyVGVtcGxhdGUoKS5qb2luKFwiXCIpO1xuXG4gICAgICAgICAgICAgICAgICBjYXNlIFwicmVtb3ZlXCI6XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbCAmJiBlbC5pbnB1dG1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICQuZGF0YShlbCwgXCJfaW5wdXRtYXNrX29wdHNcIiwgbnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZWwgPSAkKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsLmlucHV0bWFzay5fdmFsdWVTZXQob3B0cy5hdXRvVW5tYXNrID8gdW5tYXNrZWR2YWx1ZShlbCkgOiBlbC5pbnB1dG1hc2suX3ZhbHVlR2V0KHRydWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50UnVsZXIub2ZmKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbC5pbnB1dG1hc2suY29sb3JNYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JNYXNrID0gZWwuaW5wdXRtYXNrLmNvbG9yTWFzaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvck1hc2sucmVtb3ZlQ2hpbGQoZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yTWFzay5wYXJlbnROb2RlLmluc2VydEJlZm9yZShlbCwgY29sb3JNYXNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvck1hc2sucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChjb2xvck1hc2spO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlUHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvciAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVByb3BlcnR5ID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihPYmplY3QuZ2V0UHJvdG90eXBlT2YoZWwpLCBcInZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZVByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbC5pbnB1dG1hc2suX192YWx1ZUdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGVsLCBcInZhbHVlXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGVsLmlucHV0bWFzay5fX3ZhbHVlR2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldDogZWwuaW5wdXRtYXNrLl9fdmFsdWVTZXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZG9jdW1lbnQuX19sb29rdXBHZXR0ZXJfXyAmJiBlbC5fX2xvb2t1cEdldHRlcl9fKFwidmFsdWVcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWwuaW5wdXRtYXNrLl9fdmFsdWVHZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuX19kZWZpbmVHZXR0ZXJfXyhcInZhbHVlXCIsIGVsLmlucHV0bWFzay5fX3ZhbHVlR2V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuX19kZWZpbmVTZXR0ZXJfXyhcInZhbHVlXCIsIGVsLmlucHV0bWFzay5fX3ZhbHVlU2V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbC5pbnB1dG1hc2sgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgY2FzZSBcImdldG1ldGFkYXRhXCI6XG4gICAgICAgICAgICAgICAgICAgIGlmICgkLmlzQXJyYXkobWFza3NldC5tZXRhZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXNrVGFyZ2V0ID0gZ2V0TWFza1RlbXBsYXRlKHRydWUsIDAsIGZhbHNlKS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKG1hc2tzZXQubWV0YWRhdGEsIGZ1bmN0aW9uKG5keCwgbXRkdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtdGR0Lm1hc2sgPT09IG1hc2tUYXJnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza1RhcmdldCA9IG10ZHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXNrVGFyZ2V0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXNrc2V0Lm1ldGFkYXRhO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gSW5wdXRtYXNrO1xuICAgIH0pO1xufSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXywgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX187XG4gICAgdmFyIF90eXBlb2YgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIiA/IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9iajtcbiAgICB9IDogZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xuICAgIH07XG4gICAgKGZ1bmN0aW9uKGZhY3RvcnkpIHtcbiAgICAgICAgaWYgKHRydWUpIHtcbiAgICAgICAgICAgICEoX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXyA9IFsgX193ZWJwYWNrX3JlcXVpcmVfXyg0KSBdLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPSBmYWN0b3J5LCBcbiAgICAgICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fID0gdHlwZW9mIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9PT0gXCJmdW5jdGlvblwiID8gX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLmFwcGx5KGV4cG9ydHMsIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18pIDogX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBcbiAgICAgICAgICAgIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fICE9PSB1bmRlZmluZWQgJiYgKG1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18pKTtcbiAgICAgICAgfSBlbHNlIHt9XG4gICAgfSkoZnVuY3Rpb24oJCkge1xuICAgICAgICByZXR1cm4gJDtcbiAgICB9KTtcbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykge1xuICAgIG1vZHVsZS5leHBvcnRzID0galF1ZXJ5O1xufSwgZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgdmFyIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fO1xuICAgIHZhciBfdHlwZW9mID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgfSA6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICB9O1xuICAgIGlmICh0cnVlKSAhKF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogbmV3IChldmFsKFwicmVxdWlyZSgnanNkb20nKS5KU0RPTVwiKSkoXCJcIikud2luZG93O1xuICAgIH0uY2FsbChleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fLCBleHBvcnRzLCBtb2R1bGUpLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyAhPT0gdW5kZWZpbmVkICYmIChtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fKSk7IGVsc2Uge31cbn0sIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIHZhciBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18sIF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fO1xuICAgIHZhciBfdHlwZW9mID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgfSA6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICB9O1xuICAgIChmdW5jdGlvbihmYWN0b3J5KSB7XG4gICAgICAgIGlmICh0cnVlKSB7XG4gICAgICAgICAgICAhKF9fV0VCUEFDS19BTURfREVGSU5FX0FSUkFZX18gPSBbIF9fd2VicGFja19yZXF1aXJlX18oMikgXSwgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID0gZmFjdG9yeSwgXG4gICAgICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyA9IHR5cGVvZiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18gPT09IFwiZnVuY3Rpb25cIiA/IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXy5hcHBseShleHBvcnRzLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fKSA6IF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXywgXG4gICAgICAgICAgICBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXyAhPT0gdW5kZWZpbmVkICYmIChtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19BTURfREVGSU5FX1JFU1VMVF9fKSk7XG4gICAgICAgIH0gZWxzZSB7fVxuICAgIH0pKGZ1bmN0aW9uKElucHV0bWFzaykge1xuICAgICAgICB2YXIgJCA9IElucHV0bWFzay5kZXBlbmRlbmN5TGliO1xuICAgICAgICB2YXIgZm9ybWF0Q29kZSA9IHtcbiAgICAgICAgICAgIGQ6IFsgXCJbMS05XXxbMTJdWzAtOV18M1swMV1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0RGF0ZSwgXCJkYXlcIiwgRGF0ZS5wcm90b3R5cGUuZ2V0RGF0ZSBdLFxuICAgICAgICAgICAgZGQ6IFsgXCIwWzEtOV18WzEyXVswLTldfDNbMDFdXCIsIERhdGUucHJvdG90eXBlLnNldERhdGUsIFwiZGF5XCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0RGF0ZS5jYWxsKHRoaXMpLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIGRkZDogWyBcIlwiIF0sXG4gICAgICAgICAgICBkZGRkOiBbIFwiXCIgXSxcbiAgICAgICAgICAgIG06IFsgXCJbMS05XXwxWzAxMl1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0TW9udGgsIFwibW9udGhcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERhdGUucHJvdG90eXBlLmdldE1vbnRoLmNhbGwodGhpcykgKyAxO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgbW06IFsgXCIwWzEtOV18MVswMTJdXCIsIERhdGUucHJvdG90eXBlLnNldE1vbnRoLCBcIm1vbnRoXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0TW9udGguY2FsbCh0aGlzKSArIDEsIDIpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgbW1tOiBbIFwiXCIgXSxcbiAgICAgICAgICAgIG1tbW06IFsgXCJcIiBdLFxuICAgICAgICAgICAgeXk6IFsgXCJbMC05XXsyfVwiLCBEYXRlLnByb3RvdHlwZS5zZXRGdWxsWWVhciwgXCJ5ZWFyXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0RnVsbFllYXIuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICB5eXl5OiBbIFwiWzAtOV17NH1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0RnVsbFllYXIsIFwieWVhclwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldEZ1bGxZZWFyLmNhbGwodGhpcyksIDQpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgaDogWyBcIlsxLTldfDFbMC0yXVwiLCBEYXRlLnByb3RvdHlwZS5zZXRIb3VycywgXCJob3Vyc1wiLCBEYXRlLnByb3RvdHlwZS5nZXRIb3VycyBdLFxuICAgICAgICAgICAgaGg6IFsgXCIwWzEtOV18MVswLTJdXCIsIERhdGUucHJvdG90eXBlLnNldEhvdXJzLCBcImhvdXJzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0SG91cnMuY2FsbCh0aGlzKSwgMik7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICBoaGg6IFsgXCJbMC05XStcIiwgRGF0ZS5wcm90b3R5cGUuc2V0SG91cnMsIFwiaG91cnNcIiwgRGF0ZS5wcm90b3R5cGUuZ2V0SG91cnMgXSxcbiAgICAgICAgICAgIEg6IFsgXCIxP1swLTldfDJbMC0zXVwiLCBEYXRlLnByb3RvdHlwZS5zZXRIb3VycywgXCJob3Vyc1wiLCBEYXRlLnByb3RvdHlwZS5nZXRIb3VycyBdLFxuICAgICAgICAgICAgSEg6IFsgXCIwWzAtOV18MVswLTldfDJbMC0zXVwiLCBEYXRlLnByb3RvdHlwZS5zZXRIb3VycywgXCJob3Vyc1wiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldEhvdXJzLmNhbGwodGhpcyksIDIpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgSEhIOiBbIFwiWzAtOV0rXCIsIERhdGUucHJvdG90eXBlLnNldEhvdXJzLCBcImhvdXJzXCIsIERhdGUucHJvdG90eXBlLmdldEhvdXJzIF0sXG4gICAgICAgICAgICBNOiBbIFwiWzEtNV0/WzAtOV1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0TWludXRlcywgXCJtaW51dGVzXCIsIERhdGUucHJvdG90eXBlLmdldE1pbnV0ZXMgXSxcbiAgICAgICAgICAgIE1NOiBbIFwiMFswLTldfDFbMC05XXwyWzAtOV18M1swLTldfDRbMC05XXw1WzAtOV1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0TWludXRlcywgXCJtaW51dGVzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYWQoRGF0ZS5wcm90b3R5cGUuZ2V0TWludXRlcy5jYWxsKHRoaXMpLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIHNzOiBbIFwiWzAtNV1bMC05XVwiLCBEYXRlLnByb3RvdHlwZS5zZXRTZWNvbmRzLCBcInNlY29uZHNcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhZChEYXRlLnByb3RvdHlwZS5nZXRTZWNvbmRzLmNhbGwodGhpcyksIDIpO1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgbDogWyBcIlswLTldezN9XCIsIERhdGUucHJvdG90eXBlLnNldE1pbGxpc2Vjb25kcywgXCJtaWxsaXNlY29uZHNcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhZChEYXRlLnByb3RvdHlwZS5nZXRNaWxsaXNlY29uZHMuY2FsbCh0aGlzKSwgMyk7XG4gICAgICAgICAgICB9IF0sXG4gICAgICAgICAgICBMOiBbIFwiWzAtOV17Mn1cIiwgRGF0ZS5wcm90b3R5cGUuc2V0TWlsbGlzZWNvbmRzLCBcIm1pbGxpc2Vjb25kc1wiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFkKERhdGUucHJvdG90eXBlLmdldE1pbGxpc2Vjb25kcy5jYWxsKHRoaXMpLCAyKTtcbiAgICAgICAgICAgIH0gXSxcbiAgICAgICAgICAgIHQ6IFsgXCJbYXBdXCIgXSxcbiAgICAgICAgICAgIHR0OiBbIFwiW2FwXW1cIiBdLFxuICAgICAgICAgICAgVDogWyBcIltBUF1cIiBdLFxuICAgICAgICAgICAgVFQ6IFsgXCJbQVBdTVwiIF0sXG4gICAgICAgICAgICBaOiBbIFwiXCIgXSxcbiAgICAgICAgICAgIG86IFsgXCJcIiBdLFxuICAgICAgICAgICAgUzogWyBcIlwiIF1cbiAgICAgICAgfSwgZm9ybWF0QWxpYXMgPSB7XG4gICAgICAgICAgICBpc29EYXRlOiBcInl5eXktbW0tZGRcIixcbiAgICAgICAgICAgIGlzb1RpbWU6IFwiSEg6TU06c3NcIixcbiAgICAgICAgICAgIGlzb0RhdGVUaW1lOiBcInl5eXktbW0tZGQnVCdISDpNTTpzc1wiLFxuICAgICAgICAgICAgaXNvVXRjRGF0ZVRpbWU6IFwiVVRDOnl5eXktbW0tZGQnVCdISDpNTTpzcydaJ1wiXG4gICAgICAgIH07XG4gICAgICAgIGZ1bmN0aW9uIGdldFRva2VuaXplcihvcHRzKSB7XG4gICAgICAgICAgICBpZiAoIW9wdHMudG9rZW5pemVyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRva2VucyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIG5keCBpbiBmb3JtYXRDb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0b2tlbnMuaW5kZXhPZihuZHhbMF0pID09PSAtMSkgdG9rZW5zLnB1c2gobmR4WzBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb3B0cy50b2tlbml6ZXIgPSBcIihcIiArIHRva2Vucy5qb2luKFwiK3xcIikgKyBcIikrP3wuXCI7XG4gICAgICAgICAgICAgICAgb3B0cy50b2tlbml6ZXIgPSBuZXcgUmVnRXhwKG9wdHMudG9rZW5pemVyLCBcImdcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3B0cy50b2tlbml6ZXI7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gaXNWYWxpZERhdGUoZGF0ZVBhcnRzLCBjdXJyZW50UmVzdWx0KSB7XG4gICAgICAgICAgICByZXR1cm4gIWlzRmluaXRlKGRhdGVQYXJ0cy5yYXdkYXkpIHx8IGRhdGVQYXJ0cy5kYXkgPT0gXCIyOVwiICYmICFpc0Zpbml0ZShkYXRlUGFydHMucmF3eWVhcikgfHwgbmV3IERhdGUoZGF0ZVBhcnRzLmRhdGUuZ2V0RnVsbFllYXIoKSwgaXNGaW5pdGUoZGF0ZVBhcnRzLnJhd21vbnRoKSA/IGRhdGVQYXJ0cy5tb250aCA6IGRhdGVQYXJ0cy5kYXRlLmdldE1vbnRoKCkgKyAxLCAwKS5nZXREYXRlKCkgPj0gZGF0ZVBhcnRzLmRheSA/IGN1cnJlbnRSZXN1bHQgOiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc0RhdGVJblJhbmdlKGRhdGVQYXJ0cywgb3B0cykge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgICAgICAgICBpZiAob3B0cy5taW4pIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZVBhcnRzW1wicmF3eWVhclwiXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmF3WWVhciA9IGRhdGVQYXJ0c1tcInJhd3llYXJcIl0ucmVwbGFjZSgvW14wLTldL2csIFwiXCIpLCBtaW5ZZWFyID0gb3B0cy5taW4ueWVhci5zdWJzdHIoMCwgcmF3WWVhci5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBtaW5ZZWFyIDw9IHJhd1llYXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChkYXRlUGFydHNbXCJ5ZWFyXCJdID09PSBkYXRlUGFydHNbXCJyYXd5ZWFyXCJdKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm1pbi5kYXRlLmdldFRpbWUoKSA9PT0gb3B0cy5taW4uZGF0ZS5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IG9wdHMubWluLmRhdGUuZ2V0VGltZSgpIDw9IGRhdGVQYXJ0cy5kYXRlLmdldFRpbWUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXN1bHQgJiYgb3B0cy5tYXggJiYgb3B0cy5tYXguZGF0ZS5nZXRUaW1lKCkgPT09IG9wdHMubWF4LmRhdGUuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gb3B0cy5tYXguZGF0ZS5nZXRUaW1lKCkgPj0gZGF0ZVBhcnRzLmRhdGUuZ2V0VGltZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBwYXJzZShmb3JtYXQsIGRhdGVPYmpWYWx1ZSwgb3B0cywgcmF3KSB7XG4gICAgICAgICAgICB2YXIgbWFzayA9IFwiXCIsIG1hdGNoO1xuICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gZ2V0VG9rZW5pemVyKG9wdHMpLmV4ZWMoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIGlmIChkYXRlT2JqVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZm9ybWF0Q29kZVttYXRjaFswXV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gXCIoXCIgKyBmb3JtYXRDb2RlW21hdGNoWzBdXVswXSArIFwiKVwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtYXRjaFswXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiW1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gXCIoXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIl1cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrICs9IFwiKT9cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG1hdGNoWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmb3JtYXRDb2RlW21hdGNoWzBdXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhdyAhPT0gdHJ1ZSAmJiBmb3JtYXRDb2RlW21hdGNoWzBdXVszXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBnZXRGbiA9IGZvcm1hdENvZGVbbWF0Y2hbMF1dWzNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gZ2V0Rm4uY2FsbChkYXRlT2JqVmFsdWUuZGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGZvcm1hdENvZGVbbWF0Y2hbMF1dWzJdKSBtYXNrICs9IGRhdGVPYmpWYWx1ZVtcInJhd1wiICsgZm9ybWF0Q29kZVttYXRjaFswXV1bMl1dOyBlbHNlIG1hc2sgKz0gbWF0Y2hbMF07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBtYXNrICs9IG1hdGNoWzBdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXNrO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHBhZCh2YWwsIGxlbikge1xuICAgICAgICAgICAgdmFsID0gU3RyaW5nKHZhbCk7XG4gICAgICAgICAgICBsZW4gPSBsZW4gfHwgMjtcbiAgICAgICAgICAgIHdoaWxlICh2YWwubGVuZ3RoIDwgbGVuKSB7XG4gICAgICAgICAgICAgICAgdmFsID0gXCIwXCIgKyB2YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGFuYWx5c2VNYXNrKG1hc2tTdHJpbmcsIGZvcm1hdCwgb3B0cykge1xuICAgICAgICAgICAgdmFyIGRhdGVPYmogPSB7XG4gICAgICAgICAgICAgICAgZGF0ZTogbmV3IERhdGUoMSwgMCwgMSlcbiAgICAgICAgICAgIH0sIHRhcmdldFByb3AsIG1hc2sgPSBtYXNrU3RyaW5nLCBtYXRjaCwgZGF0ZU9wZXJhdGlvbiwgdGFyZ2V0VmFsaWRhdG9yO1xuICAgICAgICAgICAgZnVuY3Rpb24gZXh0ZW5kUHJvcGVydHkodmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgY29ycmVjdGVkVmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC9bXjAtOV0vZywgXCIwXCIpO1xuICAgICAgICAgICAgICAgIGlmIChjb3JyZWN0ZWRWYWx1ZSAhPSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZW50ZXJlZFBhcnQgPSB2YWx1ZS5yZXBsYWNlKC9bXjAtOV0vZywgXCJcIiksIG1pbiA9IChvcHRzLm1pbiAmJiBvcHRzLm1pblt0YXJnZXRQcm9wXSB8fCB2YWx1ZSkudG9TdHJpbmcoKSwgbWF4ID0gKG9wdHMubWF4ICYmIG9wdHMubWF4W3RhcmdldFByb3BdIHx8IHZhbHVlKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBjb3JyZWN0ZWRWYWx1ZSA9IGVudGVyZWRQYXJ0ICsgKGVudGVyZWRQYXJ0IDwgbWluLnNsaWNlKDAsIGVudGVyZWRQYXJ0Lmxlbmd0aCkgPyBtaW4uc2xpY2UoZW50ZXJlZFBhcnQubGVuZ3RoKSA6IGVudGVyZWRQYXJ0ID4gbWF4LnNsaWNlKDAsIGVudGVyZWRQYXJ0Lmxlbmd0aCkgPyBtYXguc2xpY2UoZW50ZXJlZFBhcnQubGVuZ3RoKSA6IGNvcnJlY3RlZFZhbHVlLnRvU3RyaW5nKCkuc2xpY2UoZW50ZXJlZFBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBjb3JyZWN0ZWRWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHNldFZhbHVlKGRhdGVPYmosIHZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgZGF0ZU9ialt0YXJnZXRQcm9wXSA9IGV4dGVuZFByb3BlcnR5KHZhbHVlKTtcbiAgICAgICAgICAgICAgICBkYXRlT2JqW1wicmF3XCIgKyB0YXJnZXRQcm9wXSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChkYXRlT3BlcmF0aW9uICE9PSB1bmRlZmluZWQpIGRhdGVPcGVyYXRpb24uY2FsbChkYXRlT2JqLmRhdGUsIHRhcmdldFByb3AgPT0gXCJtb250aFwiID8gcGFyc2VJbnQoZGF0ZU9ialt0YXJnZXRQcm9wXSkgLSAxIDogZGF0ZU9ialt0YXJnZXRQcm9wXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1hc2sgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBnZXRUb2tlbml6ZXIob3B0cykuZXhlYyhmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IG1hc2suc2xpY2UoMCwgbWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZvcm1hdENvZGUuaGFzT3duUHJvcGVydHkobWF0Y2hbMF0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRWYWxpZGF0b3IgPSBmb3JtYXRDb2RlW21hdGNoWzBdXVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldFByb3AgPSBmb3JtYXRDb2RlW21hdGNoWzBdXVsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGVPcGVyYXRpb24gPSBmb3JtYXRDb2RlW21hdGNoWzBdXVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlKGRhdGVPYmosIHZhbHVlLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtYXNrID0gbWFzay5zbGljZSh2YWx1ZS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZU9iajtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWFzayAmJiAodHlwZW9mIG1hc2sgPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogX3R5cGVvZihtYXNrKSkgPT09IFwib2JqZWN0XCIgJiYgbWFzay5oYXNPd25Qcm9wZXJ0eShcImRhdGVcIikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWFzaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgSW5wdXRtYXNrLmV4dGVuZEFsaWFzZXMoe1xuICAgICAgICAgICAgZGF0ZXRpbWU6IHtcbiAgICAgICAgICAgICAgICBtYXNrOiBmdW5jdGlvbiBtYXNrKG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybWF0Q29kZS5TID0gb3B0cy5pMThuLm9yZGluYWxTdWZmaXguam9pbihcInxcIik7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMuaW5wdXRGb3JtYXQgPSBmb3JtYXRBbGlhc1tvcHRzLmlucHV0Rm9ybWF0XSB8fCBvcHRzLmlucHV0Rm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICBvcHRzLmRpc3BsYXlGb3JtYXQgPSBmb3JtYXRBbGlhc1tvcHRzLmRpc3BsYXlGb3JtYXRdIHx8IG9wdHMuZGlzcGxheUZvcm1hdCB8fCBvcHRzLmlucHV0Rm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICBvcHRzLm91dHB1dEZvcm1hdCA9IGZvcm1hdEFsaWFzW29wdHMub3V0cHV0Rm9ybWF0XSB8fCBvcHRzLm91dHB1dEZvcm1hdCB8fCBvcHRzLmlucHV0Rm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICBvcHRzLnBsYWNlaG9sZGVyID0gb3B0cy5wbGFjZWhvbGRlciAhPT0gXCJcIiA/IG9wdHMucGxhY2Vob2xkZXIgOiBvcHRzLmlucHV0Rm9ybWF0LnJlcGxhY2UoL1tcXFtcXF1dLywgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMucmVnZXggPSBwYXJzZShvcHRzLmlucHV0Rm9ybWF0LCB1bmRlZmluZWQsIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIlwiLFxuICAgICAgICAgICAgICAgIGlucHV0Rm9ybWF0OiBcImlzb0RhdGVUaW1lXCIsXG4gICAgICAgICAgICAgICAgZGlzcGxheUZvcm1hdDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIG91dHB1dEZvcm1hdDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIG1pbjogbnVsbCxcbiAgICAgICAgICAgICAgICBtYXg6IG51bGwsXG4gICAgICAgICAgICAgICAgaTE4bjoge1xuICAgICAgICAgICAgICAgICAgICBkYXlOYW1lczogWyBcIk1vblwiLCBcIlR1ZVwiLCBcIldlZFwiLCBcIlRodVwiLCBcIkZyaVwiLCBcIlNhdFwiLCBcIlN1blwiLCBcIk1vbmRheVwiLCBcIlR1ZXNkYXlcIiwgXCJXZWRuZXNkYXlcIiwgXCJUaHVyc2RheVwiLCBcIkZyaWRheVwiLCBcIlNhdHVyZGF5XCIsIFwiU3VuZGF5XCIgXSxcbiAgICAgICAgICAgICAgICAgICAgbW9udGhOYW1lczogWyBcIkphblwiLCBcIkZlYlwiLCBcIk1hclwiLCBcIkFwclwiLCBcIk1heVwiLCBcIkp1blwiLCBcIkp1bFwiLCBcIkF1Z1wiLCBcIlNlcFwiLCBcIk9jdFwiLCBcIk5vdlwiLCBcIkRlY1wiLCBcIkphbnVhcnlcIiwgXCJGZWJydWFyeVwiLCBcIk1hcmNoXCIsIFwiQXByaWxcIiwgXCJNYXlcIiwgXCJKdW5lXCIsIFwiSnVseVwiLCBcIkF1Z3VzdFwiLCBcIlNlcHRlbWJlclwiLCBcIk9jdG9iZXJcIiwgXCJOb3ZlbWJlclwiLCBcIkRlY2VtYmVyXCIgXSxcbiAgICAgICAgICAgICAgICAgICAgb3JkaW5hbFN1ZmZpeDogWyBcInN0XCIsIFwibmRcIiwgXCJyZFwiLCBcInRoXCIgXVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcG9zdFZhbGlkYXRpb246IGZ1bmN0aW9uIHBvc3RWYWxpZGF0aW9uKGJ1ZmZlciwgcG9zLCBjdXJyZW50UmVzdWx0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMubWluID0gYW5hbHlzZU1hc2sob3B0cy5taW4sIG9wdHMuaW5wdXRGb3JtYXQsIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBvcHRzLm1heCA9IGFuYWx5c2VNYXNrKG9wdHMubWF4LCBvcHRzLmlucHV0Rm9ybWF0LCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGN1cnJlbnRSZXN1bHQsIGRhdGVQYXJ0cyA9IGFuYWx5c2VNYXNrKGJ1ZmZlci5qb2luKFwiXCIpLCBvcHRzLmlucHV0Rm9ybWF0LCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAmJiBkYXRlUGFydHMuZGF0ZS5nZXRUaW1lKCkgPT09IGRhdGVQYXJ0cy5kYXRlLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gaXNWYWxpZERhdGUoZGF0ZVBhcnRzLCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0ICYmIGlzRGF0ZUluUmFuZ2UoZGF0ZVBhcnRzLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAocG9zICYmIHJlc3VsdCAmJiBjdXJyZW50UmVzdWx0LnBvcyAhPT0gcG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlcjogcGFyc2Uob3B0cy5pbnB1dEZvcm1hdCwgZGF0ZVBhcnRzLCBvcHRzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IGN1cnJlbnRSZXN1bHQucG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25LZXlEb3duOiBmdW5jdGlvbiBvbktleURvd24oZSwgYnVmZmVyLCBjYXJldFBvcywgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZS5jdHJsS2V5ICYmIGUua2V5Q29kZSA9PT0gSW5wdXRtYXNrLmtleUNvZGUuUklHSFQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0b2RheSA9IG5ldyBEYXRlKCksIG1hdGNoLCBkYXRlID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IGdldFRva2VuaXplcihvcHRzKS5leGVjKG9wdHMuaW5wdXRGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoWzBdLmNoYXJBdCgwKSA9PT0gXCJkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSArPSBwYWQodG9kYXkuZ2V0RGF0ZSgpLCBtYXRjaFswXS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2hbMF0uY2hhckF0KDApID09PSBcIm1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRlICs9IHBhZCh0b2RheS5nZXRNb250aCgpICsgMSwgbWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoWzBdID09PSBcInl5eXlcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRlICs9IHRvZGF5LmdldEZ1bGxZZWFyKCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoWzBdLmNoYXJBdCgwKSA9PT0gXCJ5XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSArPSBwYWQodG9kYXkuZ2V0WWVhcigpLCBtYXRjaFswXS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LmlucHV0bWFzay5fdmFsdWVTZXQoZGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKGlucHV0KS50cmlnZ2VyKFwic2V0dmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uVW5NYXNrOiBmdW5jdGlvbiBvblVuTWFzayhtYXNrZWRWYWx1ZSwgdW5tYXNrZWRWYWx1ZSwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFyc2Uob3B0cy5vdXRwdXRGb3JtYXQsIGFuYWx5c2VNYXNrKG1hc2tlZFZhbHVlLCBvcHRzLmlucHV0Rm9ybWF0LCBvcHRzKSwgb3B0cywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjYXNpbmc6IGZ1bmN0aW9uIGNhc2luZyhlbGVtLCB0ZXN0LCBwb3MsIHZhbGlkUG9zaXRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ZXN0Lm5hdGl2ZURlZi5pbmRleE9mKFwiW2FwXVwiKSA9PSAwKSByZXR1cm4gZWxlbS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGVzdC5uYXRpdmVEZWYuaW5kZXhPZihcIltBUF1cIikgPT0gMCkgcmV0dXJuIGVsZW0udG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBzaGlmdFBvc2l0aW9uczogZmFsc2VcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBJbnB1dG1hc2s7XG4gICAgfSk7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICB2YXIgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXztcbiAgICB2YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2Ygb2JqO1xuICAgIH0gOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7XG4gICAgfTtcbiAgICAoZnVuY3Rpb24oZmFjdG9yeSkge1xuICAgICAgICBpZiAodHJ1ZSkge1xuICAgICAgICAgICAgIShfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fID0gWyBfX3dlYnBhY2tfcmVxdWlyZV9fKDIpIF0sIF9fV0VCUEFDS19BTURfREVGSU5FX0ZBQ1RPUllfXyA9IGZhY3RvcnksIFxuICAgICAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSB0eXBlb2YgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID09PSBcImZ1bmN0aW9uXCIgPyBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18uYXBwbHkoZXhwb3J0cywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXykgOiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIFxuICAgICAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gIT09IHVuZGVmaW5lZCAmJiAobW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXykpO1xuICAgICAgICB9IGVsc2Uge31cbiAgICB9KShmdW5jdGlvbihJbnB1dG1hc2spIHtcbiAgICAgICAgdmFyICQgPSBJbnB1dG1hc2suZGVwZW5kZW5jeUxpYjtcbiAgICAgICAgZnVuY3Rpb24gYXV0b0VzY2FwZSh0eHQsIG9wdHMpIHtcbiAgICAgICAgICAgIHZhciBlc2NhcGVkVHh0ID0gXCJcIjtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHh0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKElucHV0bWFzay5wcm90b3R5cGUuZGVmaW5pdGlvbnNbdHh0LmNoYXJBdChpKV0gfHwgb3B0cy5kZWZpbml0aW9uc1t0eHQuY2hhckF0KGkpXSB8fCBvcHRzLm9wdGlvbmFsbWFya2VyLnN0YXJ0ID09PSB0eHQuY2hhckF0KGkpIHx8IG9wdHMub3B0aW9uYWxtYXJrZXIuZW5kID09PSB0eHQuY2hhckF0KGkpIHx8IG9wdHMucXVhbnRpZmllcm1hcmtlci5zdGFydCA9PT0gdHh0LmNoYXJBdChpKSB8fCBvcHRzLnF1YW50aWZpZXJtYXJrZXIuZW5kID09PSB0eHQuY2hhckF0KGkpIHx8IG9wdHMuZ3JvdXBtYXJrZXIuc3RhcnQgPT09IHR4dC5jaGFyQXQoaSkgfHwgb3B0cy5ncm91cG1hcmtlci5lbmQgPT09IHR4dC5jaGFyQXQoaSkgfHwgb3B0cy5hbHRlcm5hdG9ybWFya2VyID09PSB0eHQuY2hhckF0KGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVzY2FwZWRUeHQgKz0gXCJcXFxcXCIgKyB0eHQuY2hhckF0KGkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBlc2NhcGVkVHh0ICs9IHR4dC5jaGFyQXQoaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZXNjYXBlZFR4dDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBhbGlnbkRpZ2l0cyhidWZmZXIsIGRpZ2l0cywgb3B0cykge1xuICAgICAgICAgICAgaWYgKGRpZ2l0cyA+IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgcmFkaXhQb3NpdGlvbiA9ICQuaW5BcnJheShvcHRzLnJhZGl4UG9pbnQsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgaWYgKHJhZGl4UG9zaXRpb24gPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlci5wdXNoKG9wdHMucmFkaXhQb2ludCk7XG4gICAgICAgICAgICAgICAgICAgIHJhZGl4UG9zaXRpb24gPSBidWZmZXIubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gZGlnaXRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYnVmZmVyW3JhZGl4UG9zaXRpb24gKyBpXSA9IGJ1ZmZlcltyYWRpeFBvc2l0aW9uICsgaV0gfHwgXCIwXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlcjtcbiAgICAgICAgfVxuICAgICAgICBJbnB1dG1hc2suZXh0ZW5kQWxpYXNlcyh7XG4gICAgICAgICAgICBudW1lcmljOiB7XG4gICAgICAgICAgICAgICAgbWFzazogZnVuY3Rpb24gbWFzayhvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnJlcGVhdCAhPT0gMCAmJiBpc05hTihvcHRzLmludGVnZXJEaWdpdHMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmludGVnZXJEaWdpdHMgPSBvcHRzLnJlcGVhdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBvcHRzLnJlcGVhdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmdyb3VwU2VwYXJhdG9yID09PSBvcHRzLnJhZGl4UG9pbnQgJiYgb3B0cy5kaWdpdHMgJiYgb3B0cy5kaWdpdHMgIT09IFwiMFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5yYWRpeFBvaW50ID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuZ3JvdXBTZXBhcmF0b3IgPSBcIixcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0cy5yYWRpeFBvaW50ID09PSBcIixcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuZ3JvdXBTZXBhcmF0b3IgPSBcIi5cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBvcHRzLmdyb3VwU2VwYXJhdG9yID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5ncm91cFNlcGFyYXRvciA9PT0gXCIgXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuc2tpcE9wdGlvbmFsUGFydENoYXJhY3RlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBvcHRzLmF1dG9Hcm91cCA9IG9wdHMuYXV0b0dyb3VwICYmIG9wdHMuZ3JvdXBTZXBhcmF0b3IgIT09IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmF1dG9Hcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRzLmdyb3VwU2l6ZSA9PSBcInN0cmluZ1wiICYmIGlzRmluaXRlKG9wdHMuZ3JvdXBTaXplKSkgb3B0cy5ncm91cFNpemUgPSBwYXJzZUludChvcHRzLmdyb3VwU2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNGaW5pdGUob3B0cy5pbnRlZ2VyRGlnaXRzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZXBzID0gTWF0aC5mbG9vcihvcHRzLmludGVnZXJEaWdpdHMgLyBvcHRzLmdyb3VwU2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1vZCA9IG9wdHMuaW50ZWdlckRpZ2l0cyAlIG9wdHMuZ3JvdXBTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuaW50ZWdlckRpZ2l0cyA9IHBhcnNlSW50KG9wdHMuaW50ZWdlckRpZ2l0cykgKyAobW9kID09PSAwID8gc2VwcyAtIDEgOiBzZXBzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5pbnRlZ2VyRGlnaXRzIDwgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmludGVnZXJEaWdpdHMgPSBcIipcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucGxhY2Vob2xkZXIubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5wbGFjZWhvbGRlciA9IG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnBvc2l0aW9uQ2FyZXRPbkNsaWNrID09PSBcInJhZGl4Rm9jdXNcIiAmJiBvcHRzLnBsYWNlaG9sZGVyID09PSBcIlwiICYmIG9wdHMuaW50ZWdlck9wdGlvbmFsID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5wb3NpdGlvbkNhcmV0T25DbGljayA9IFwibHZwXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3B0cy5kZWZpbml0aW9uc1tcIjtcIl0gPSBvcHRzLmRlZmluaXRpb25zW1wiflwiXTtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5kZWZpbml0aW9uc1tcIjtcIl0uZGVmaW5pdGlvblN5bWJvbCA9IFwiflwiO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5udW1lcmljSW5wdXQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMucG9zaXRpb25DYXJldE9uQ2xpY2sgPSBvcHRzLnBvc2l0aW9uQ2FyZXRPbkNsaWNrID09PSBcInJhZGl4Rm9jdXNcIiA/IFwibHZwXCIgOiBvcHRzLnBvc2l0aW9uQ2FyZXRPbkNsaWNrO1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5kaWdpdHNPcHRpb25hbCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmFOKG9wdHMuZGlnaXRzKSkgb3B0cy5kaWdpdHMgPSAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5kZWNpbWFsUHJvdGVjdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXNrID0gXCJbK11cIjtcbiAgICAgICAgICAgICAgICAgICAgbWFzayArPSBhdXRvRXNjYXBlKG9wdHMucHJlZml4LCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuaW50ZWdlck9wdGlvbmFsID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrICs9IFwifnsxLFwiICsgb3B0cy5pbnRlZ2VyRGlnaXRzICsgXCJ9XCI7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBtYXNrICs9IFwifntcIiArIG9wdHMuaW50ZWdlckRpZ2l0cyArIFwifVwiO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5kaWdpdHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhZGl4RGVmID0gb3B0cy5kZWNpbWFsUHJvdGVjdCA/IFwiOlwiIDogb3B0cy5yYWRpeFBvaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRxID0gb3B0cy5kaWdpdHMudG9TdHJpbmcoKS5zcGxpdChcIixcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNGaW5pdGUoZHFbMF0pICYmIGRxWzFdICYmIGlzRmluaXRlKGRxWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gcmFkaXhEZWYgKyBcIjt7XCIgKyBvcHRzLmRpZ2l0cyArIFwifVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc05hTihvcHRzLmRpZ2l0cykgfHwgcGFyc2VJbnQob3B0cy5kaWdpdHMpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmRpZ2l0c09wdGlvbmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gXCJbXCIgKyByYWRpeERlZiArIFwiO3sxLFwiICsgb3B0cy5kaWdpdHMgKyBcIn1dXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIG1hc2sgKz0gcmFkaXhEZWYgKyBcIjt7XCIgKyBvcHRzLmRpZ2l0cyArIFwifVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gYXV0b0VzY2FwZShvcHRzLnN1ZmZpeCwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIG1hc2sgKz0gXCJbLV1cIjtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5ncmVlZHkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hc2s7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJcIixcbiAgICAgICAgICAgICAgICBncmVlZHk6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGRpZ2l0czogXCIqXCIsXG4gICAgICAgICAgICAgICAgZGlnaXRzT3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgZW5mb3JjZURpZ2l0c09uQmx1cjogZmFsc2UsXG4gICAgICAgICAgICAgICAgcmFkaXhQb2ludDogXCIuXCIsXG4gICAgICAgICAgICAgICAgcG9zaXRpb25DYXJldE9uQ2xpY2s6IFwicmFkaXhGb2N1c1wiLFxuICAgICAgICAgICAgICAgIGdyb3VwU2l6ZTogMyxcbiAgICAgICAgICAgICAgICBncm91cFNlcGFyYXRvcjogXCJcIixcbiAgICAgICAgICAgICAgICBhdXRvR3JvdXA6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGFsbG93TWludXM6IHRydWUsXG4gICAgICAgICAgICAgICAgbmVnYXRpb25TeW1ib2w6IHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbnQ6IFwiLVwiLFxuICAgICAgICAgICAgICAgICAgICBiYWNrOiBcIlwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnRlZ2VyRGlnaXRzOiBcIitcIixcbiAgICAgICAgICAgICAgICBpbnRlZ2VyT3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgcHJlZml4OiBcIlwiLFxuICAgICAgICAgICAgICAgIHN1ZmZpeDogXCJcIixcbiAgICAgICAgICAgICAgICByaWdodEFsaWduOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxQcm90ZWN0OiB0cnVlLFxuICAgICAgICAgICAgICAgIG1pbjogbnVsbCxcbiAgICAgICAgICAgICAgICBtYXg6IG51bGwsXG4gICAgICAgICAgICAgICAgc3RlcDogMSxcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGF1dG9Vbm1hc2s6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHVubWFza0FzTnVtYmVyOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpbnB1dFR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgICAgIGlucHV0bW9kZTogXCJudW1lcmljXCIsXG4gICAgICAgICAgICAgICAgcHJlVmFsaWRhdGlvbjogZnVuY3Rpb24gcHJlVmFsaWRhdGlvbihidWZmZXIsIHBvcywgYywgaXNTZWxlY3Rpb24sIG9wdHMsIG1hc2tzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGMgPT09IFwiLVwiIHx8IGMgPT09IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmFsbG93TWludXMgIT09IHRydWUpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuaXNOZWdhdGl2ZSA9IG9wdHMuaXNOZWdhdGl2ZSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6ICFvcHRzLmlzTmVnYXRpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYnVmZmVyLmpvaW4oXCJcIikgPT09IFwiXCIpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdID8gcG9zIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvcG9zdDogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNTZWxlY3Rpb24gPT09IGZhbHNlICYmIGMgPT09IG9wdHMucmFkaXhQb2ludCAmJiBvcHRzLmRpZ2l0cyAhPT0gdW5kZWZpbmVkICYmIChpc05hTihvcHRzLmRpZ2l0cykgfHwgcGFyc2VJbnQob3B0cy5kaWdpdHMpID4gMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYWRpeFBvcyA9ICQuaW5BcnJheShvcHRzLnJhZGl4UG9pbnQsIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFkaXhQb3MgIT09IC0xICYmIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcmFkaXhQb3NdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5udW1lcmljSW5wdXQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvcyA9PT0gcmFkaXhQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiByYWRpeFBvcyArIDFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcG9zdFZhbGlkYXRpb246IGZ1bmN0aW9uIHBvc3RWYWxpZGF0aW9uKGJ1ZmZlciwgcG9zLCBjdXJyZW50UmVzdWx0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGJ1aWxkUG9zdE1hc2soYnVmZmVyLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcG9zdE1hc2sgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zdE1hc2sgKz0gXCIoXCIgKyBvcHRzLmdyb3VwU2VwYXJhdG9yICsgXCIqe1wiICsgb3B0cy5ncm91cFNpemUgKyBcIn0peyp9XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5yYWRpeFBvaW50ICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhZGl4U3BsaXQgPSBidWZmZXIuam9pbihcIlwiKS5zcGxpdChvcHRzLnJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYWRpeFNwbGl0WzFdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc3RNYXNrICs9IG9wdHMucmFkaXhQb2ludCArIFwiKntcIiArIHJhZGl4U3BsaXRbMV0ubWF0Y2goL15cXGQqXFw/P1xcZCovKVswXS5sZW5ndGggKyBcIn1cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcG9zdE1hc2s7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHN1ZmZpeCA9IG9wdHMuc3VmZml4LnNwbGl0KFwiXCIpLCBwcmVmaXggPSBvcHRzLnByZWZpeC5zcGxpdChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRSZXN1bHQucG9zID09PSB1bmRlZmluZWQgJiYgY3VycmVudFJlc3VsdC5jYXJldCAhPT0gdW5kZWZpbmVkICYmIGN1cnJlbnRSZXN1bHQuZG9wb3N0ICE9PSB0cnVlKSByZXR1cm4gY3VycmVudFJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNhcmV0UG9zID0gY3VycmVudFJlc3VsdC5jYXJldCAhPT0gdW5kZWZpbmVkID8gY3VycmVudFJlc3VsdC5jYXJldCA6IGN1cnJlbnRSZXN1bHQucG9zO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWFza2VkVmFsdWUgPSBidWZmZXIuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMubnVtZXJpY0lucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvcyA9IG1hc2tlZFZhbHVlLmxlbmd0aCAtIGNhcmV0UG9zIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGFyQXRQb3MgPSBtYXNrZWRWYWx1ZVtjYXJldFBvc107XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGFyQXRQb3MgPT09IG9wdHMuZ3JvdXBTZXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zICs9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGFyQXRQb3MgPSBtYXNrZWRWYWx1ZVtjYXJldFBvc107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhcmV0UG9zID09PSBtYXNrZWRWYWx1ZS5sZW5ndGggLSBvcHRzLnN1ZmZpeC5sZW5ndGggLSAxICYmIGNoYXJBdFBvcyA9PT0gb3B0cy5yYWRpeFBvaW50KSByZXR1cm4gY3VycmVudFJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoYXJBdFBvcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckF0UG9zICE9PSBvcHRzLnJhZGl4UG9pbnQgJiYgY2hhckF0UG9zICE9PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250ICYmIGNoYXJBdFBvcyAhPT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza2VkVmFsdWVbY2FyZXRQb3NdID0gXCI/XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucHJlZml4Lmxlbmd0aCA+IDAgJiYgY2FyZXRQb3MgPj0gKG9wdHMuaXNOZWdhdGl2ZSA9PT0gZmFsc2UgPyAxIDogMCkgJiYgY2FyZXRQb3MgPCBvcHRzLnByZWZpeC5sZW5ndGggLSAxICsgKG9wdHMuaXNOZWdhdGl2ZSA9PT0gZmFsc2UgPyAxIDogMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZml4W2NhcmV0UG9zIC0gKG9wdHMuaXNOZWdhdGl2ZSA9PT0gZmFsc2UgPyAxIDogMCldID0gXCI/XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRzLnN1ZmZpeC5sZW5ndGggPiAwICYmIGNhcmV0UG9zID49IG1hc2tlZFZhbHVlLmxlbmd0aCAtIG9wdHMuc3VmZml4Lmxlbmd0aCAtIChvcHRzLmlzTmVnYXRpdmUgPT09IGZhbHNlID8gMSA6IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1ZmZpeFtjYXJldFBvcyAtIChtYXNrZWRWYWx1ZS5sZW5ndGggLSBvcHRzLnN1ZmZpeC5sZW5ndGggLSAob3B0cy5pc05lZ2F0aXZlID09PSBmYWxzZSA/IDEgOiAwKSldID0gXCI/XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHByZWZpeCA9IHByZWZpeC5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBzdWZmaXggPSBzdWZmaXguam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb2Nlc3NWYWx1ZSA9IG1hc2tlZFZhbHVlLmpvaW4oXCJcIikucmVwbGFjZShwcmVmaXgsIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShzdWZmaXgsIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLmdyb3VwU2VwYXJhdG9yKSwgXCJnXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChcIlstXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkgKyBcIl1cIiwgXCJnXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSArIFwiJFwiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc05hTihvcHRzLnBsYWNlaG9sZGVyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5wbGFjZWhvbGRlciksIFwiZ1wiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb2Nlc3NWYWx1ZS5sZW5ndGggPiAxICYmIHByb2Nlc3NWYWx1ZS5pbmRleE9mKG9wdHMucmFkaXhQb2ludCkgIT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGFyQXRQb3MgPT09IFwiMFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UoL15cXD8vZywgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZSgvXjAvZywgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb2Nlc3NWYWx1ZS5jaGFyQXQoMCkgPT09IG9wdHMucmFkaXhQb2ludCAmJiBvcHRzLnJhZGl4UG9pbnQgIT09IFwiXCIgJiYgb3B0cy5udW1lcmljSW5wdXQgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IFwiMFwiICsgcHJvY2Vzc1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9jZXNzVmFsdWUgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5zcGxpdChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoIW9wdHMuZGlnaXRzT3B0aW9uYWwgfHwgb3B0cy5lbmZvcmNlRGlnaXRzT25CbHVyICYmIGN1cnJlbnRSZXN1bHQuZXZlbnQgPT09IFwiYmx1clwiKSAmJiBpc0Zpbml0ZShvcHRzLmRpZ2l0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmFkaXhQb3NpdGlvbiA9ICQuaW5BcnJheShvcHRzLnJhZGl4UG9pbnQsIHByb2Nlc3NWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJwYiA9ICQuaW5BcnJheShvcHRzLnJhZGl4UG9pbnQsIG1hc2tlZFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFkaXhQb3NpdGlvbiA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlLnB1c2gob3B0cy5yYWRpeFBvaW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFkaXhQb3NpdGlvbiA9IHByb2Nlc3NWYWx1ZS5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8PSBvcHRzLmRpZ2l0czsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoIW9wdHMuZGlnaXRzT3B0aW9uYWwgfHwgb3B0cy5lbmZvcmNlRGlnaXRzT25CbHVyICYmIGN1cnJlbnRSZXN1bHQuZXZlbnQgPT09IFwiYmx1clwiKSAmJiAocHJvY2Vzc1ZhbHVlW3JhZGl4UG9zaXRpb24gKyBpXSA9PT0gdW5kZWZpbmVkIHx8IHByb2Nlc3NWYWx1ZVtyYWRpeFBvc2l0aW9uICsgaV0gPT09IG9wdHMucGxhY2Vob2xkZXIuY2hhckF0KDApKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlW3JhZGl4UG9zaXRpb24gKyBpXSA9IGN1cnJlbnRSZXN1bHQucGxhY2Vob2xkZXIgfHwgb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocnBiICE9PSAtMSAmJiBtYXNrZWRWYWx1ZVtycGIgKyBpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWVbcmFkaXhQb3NpdGlvbiArIGldID0gcHJvY2Vzc1ZhbHVlW3JhZGl4UG9zaXRpb24gKyBpXSB8fCBtYXNrZWRWYWx1ZVtycGIgKyBpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLmF1dG9Hcm91cCA9PT0gdHJ1ZSAmJiBvcHRzLmdyb3VwU2VwYXJhdG9yICE9PSBcIlwiICYmIChjaGFyQXRQb3MgIT09IG9wdHMucmFkaXhQb2ludCB8fCBjdXJyZW50UmVzdWx0LnBvcyAhPT0gdW5kZWZpbmVkIHx8IGN1cnJlbnRSZXN1bHQuZG9wb3N0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhZGRSYWRpeCA9IHByb2Nlc3NWYWx1ZVtwcm9jZXNzVmFsdWUubGVuZ3RoIC0gMV0gPT09IG9wdHMucmFkaXhQb2ludCAmJiBjdXJyZW50UmVzdWx0LmMgPT09IG9wdHMucmFkaXhQb2ludDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBJbnB1dG1hc2soYnVpbGRQb3N0TWFzayhwcm9jZXNzVmFsdWUsIG9wdHMpLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bWVyaWNJbnB1dDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0TWFza2luZzogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiKlwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBcIlswLTk/XVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5mb3JtYXQocHJvY2Vzc1ZhbHVlLmpvaW4oXCJcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhZGRSYWRpeCkgcHJvY2Vzc1ZhbHVlICs9IG9wdHMucmFkaXhQb2ludDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvY2Vzc1ZhbHVlLmNoYXJBdCgwKSA9PT0gb3B0cy5ncm91cFNlcGFyYXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUuc3Vic3RyKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5pc05lZ2F0aXZlICYmIGN1cnJlbnRSZXN1bHQuZXZlbnQgPT09IFwiYmx1clwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRzLmlzTmVnYXRpdmUgPSBwcm9jZXNzVmFsdWUgIT09IFwiMFwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByZWZpeCArIHByb2Nlc3NWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlICs9IHN1ZmZpeDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMuaXNOZWdhdGl2ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gb3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCArIHByb2Nlc3NWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSArPSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2s7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnNwbGl0KFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckF0UG9zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGFyQXRQb3MgIT09IG9wdHMucmFkaXhQb2ludCAmJiBjaGFyQXRQb3MgIT09IG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQgJiYgY2hhckF0UG9zICE9PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvcyA9ICQuaW5BcnJheShcIj9cIiwgcHJvY2Vzc1ZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FyZXRQb3MgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWVbY2FyZXRQb3NdID0gY2hhckF0UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBjYXJldFBvcyA9IGN1cnJlbnRSZXN1bHQuY2FyZXQgfHwgMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hhckF0UG9zID09PSBvcHRzLnJhZGl4UG9pbnQgfHwgY2hhckF0UG9zID09PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250IHx8IGNoYXJBdFBvcyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0NhcmV0UG9zID0gJC5pbkFycmF5KGNoYXJBdFBvcywgcHJvY2Vzc1ZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV3Q2FyZXRQb3MgIT09IC0xKSBjYXJldFBvcyA9IG5ld0NhcmV0UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm51bWVyaWNJbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3MgPSBwcm9jZXNzVmFsdWUubGVuZ3RoIC0gY2FyZXRQb3MgLSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgcnNsdCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiAoY2hhckF0UG9zID09PSB1bmRlZmluZWQgfHwgY3VycmVudFJlc3VsdC5wb3MgIT09IHVuZGVmaW5lZCkgJiYgY2FyZXRQb3MgIT09IHVuZGVmaW5lZCA/IGNhcmV0UG9zICsgKG9wdHMubnVtZXJpY0lucHV0ID8gLTEgOiAxKSA6IGNhcmV0UG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiBwcm9jZXNzVmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWZyZXNoRnJvbUJ1ZmZlcjogY3VycmVudFJlc3VsdC5kb3Bvc3QgfHwgYnVmZmVyLmpvaW4oXCJcIikgIT09IHByb2Nlc3NWYWx1ZS5qb2luKFwiXCIpXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByc2x0LnJlZnJlc2hGcm9tQnVmZmVyID8gcnNsdCA6IGN1cnJlbnRSZXN1bHQ7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkJlZm9yZVdyaXRlOiBmdW5jdGlvbiBvbkJlZm9yZVdyaXRlKGUsIGJ1ZmZlciwgY2FyZXRQb3MsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VNaW5NYXhPcHRpb25zKG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnBhcnNlTWluTWF4T3B0aW9ucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMubWluICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMubWluID0gb3B0cy5taW4udG9TdHJpbmcoKS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMuZ3JvdXBTZXBhcmF0b3IpLCBcImdcIiksIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5yYWRpeFBvaW50ID09PSBcIixcIikgb3B0cy5taW4gPSBvcHRzLm1pbi5yZXBsYWNlKG9wdHMucmFkaXhQb2ludCwgXCIuXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLm1pbiA9IGlzRmluaXRlKG9wdHMubWluKSA/IHBhcnNlRmxvYXQob3B0cy5taW4pIDogTmFOO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNOYU4ob3B0cy5taW4pKSBvcHRzLm1pbiA9IE51bWJlci5NSU5fVkFMVUU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm1heCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLm1heCA9IG9wdHMubWF4LnRvU3RyaW5nKCkucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLmdyb3VwU2VwYXJhdG9yKSwgXCJnXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmFkaXhQb2ludCA9PT0gXCIsXCIpIG9wdHMubWF4ID0gb3B0cy5tYXgucmVwbGFjZShvcHRzLnJhZGl4UG9pbnQsIFwiLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5tYXggPSBpc0Zpbml0ZShvcHRzLm1heCkgPyBwYXJzZUZsb2F0KG9wdHMubWF4KSA6IE5hTjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmFOKG9wdHMubWF4KSkgb3B0cy5tYXggPSBOdW1iZXIuTUFYX1ZBTFVFO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRzLnBhcnNlTWluTWF4T3B0aW9ucyA9IFwiZG9uZVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGUudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwia2V5ZG93blwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLnBvc3RWYWxpZGF0aW9uKGJ1ZmZlciwgY2FyZXRQb3MsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IGNhcmV0UG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3Bvc3Q6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBvcHRzKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYmx1clwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY2hlY2t2YWxcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdW5tYXNrZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VNaW5NYXhPcHRpb25zKG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm1pbiAhPT0gbnVsbCB8fCBvcHRzLm1heCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bm1hc2tlZCA9IG9wdHMub25Vbk1hc2soYnVmZmVyLmpvaW4oXCJcIiksIHVuZGVmaW5lZCwgJC5leHRlbmQoe30sIG9wdHMsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVubWFza0FzTnVtYmVyOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMubWluICE9PSBudWxsICYmIHVubWFza2VkIDwgb3B0cy5taW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuaXNOZWdhdGl2ZSA9IG9wdHMubWluIDwgMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLnBvc3RWYWxpZGF0aW9uKG9wdHMubWluLnRvU3RyaW5nKCkucmVwbGFjZShcIi5cIiwgb3B0cy5yYWRpeFBvaW50KS5zcGxpdChcIlwiKSwgY2FyZXRQb3MsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldDogY2FyZXRQb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9wb3N0OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0cy5tYXggIT09IG51bGwgJiYgdW5tYXNrZWQgPiBvcHRzLm1heCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0cy5pc05lZ2F0aXZlID0gb3B0cy5tYXggPCAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdHMucG9zdFZhbGlkYXRpb24ob3B0cy5tYXgudG9TdHJpbmcoKS5yZXBsYWNlKFwiLlwiLCBvcHRzLnJhZGl4UG9pbnQpLnNwbGl0KFwiXCIpLCBjYXJldFBvcywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBjYXJldFBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3Bvc3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5wb3N0VmFsaWRhdGlvbihidWZmZXIsIGNhcmV0UG9zLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBjYXJldFBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiMFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudDogXCJibHVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBvcHRzKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiX2NoZWNrdmFsXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXQ6IGNhcmV0UG9zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByZWdleDoge1xuICAgICAgICAgICAgICAgICAgICBpbnRlZ2VyUGFydDogZnVuY3Rpb24gaW50ZWdlclBhcnQob3B0cywgZW1wdHlDaGVjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVtcHR5Q2hlY2sgPyBuZXcgUmVnRXhwKFwiW1wiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpICsgXCIrXT9cIikgOiBuZXcgUmVnRXhwKFwiW1wiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpICsgXCIrXT9cXFxcZCtcIik7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGludGVnZXJOUGFydDogZnVuY3Rpb24gaW50ZWdlck5QYXJ0KG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiW1xcXFxkXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5ncm91cFNlcGFyYXRvcikgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCkpICsgXCJdK1wiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgXCJ+XCI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogZnVuY3Rpb24gdmFsaWRhdG9yKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzLCBpc1NlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkLCBsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaHJzID09PSBcImtcIiB8fCBjaHJzID09PSBcIm1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0OiBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGM6IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjaHJzID09PSBcImtcIiA/IDIgOiA1OyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkLmluc2VydC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvcyArIGksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYzogMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZC5wb3MgPSBwb3MgKyBsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNWYWxpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IHN0cmljdCA/IG5ldyBSZWdFeHAoXCJbMC05XCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5ncm91cFNlcGFyYXRvcikgKyBcIl1cIikudGVzdChjaHJzKSA6IG5ldyBSZWdFeHAoXCJbMC05XVwiKS50ZXN0KGNocnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLm51bWVyaWNJbnB1dCAhPT0gdHJ1ZSAmJiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10gIT09IHVuZGVmaW5lZCAmJiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10ubWF0Y2guZGVmID09PSBcIn5cIiAmJiAhaXNTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9jZXNzVmFsdWUgPSBtYXNrc2V0LmJ1ZmZlci5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChcIlstXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkgKyBcIl1cIiwgXCJnXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuYmFjaykgKyBcIiRcIiksIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHB2UmFkaXhTcGxpdCA9IHByb2Nlc3NWYWx1ZS5zcGxpdChvcHRzLnJhZGl4UG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHB2UmFkaXhTcGxpdC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZSYWRpeFNwbGl0WzFdID0gcHZSYWRpeFNwbGl0WzFdLnJlcGxhY2UoLzAvZywgb3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHB2UmFkaXhTcGxpdFswXSA9PT0gXCIwXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdlJhZGl4U3BsaXRbMF0gPSBwdlJhZGl4U3BsaXRbMF0ucmVwbGFjZSgvMC9nLCBvcHRzLnBsYWNlaG9sZGVyLmNoYXJBdCgwKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwdlJhZGl4U3BsaXRbMF0gKyBvcHRzLnJhZGl4UG9pbnQgKyBwdlJhZGl4U3BsaXRbMV0gfHwgXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXJUZW1wbGF0ZSA9IG1hc2tzZXQuX2J1ZmZlci5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb2Nlc3NWYWx1ZSA9PT0gb3B0cy5yYWRpeFBvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gYnVmZmVyVGVtcGxhdGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAocHJvY2Vzc1ZhbHVlLm1hdGNoKElucHV0bWFzay5lc2NhcGVSZWdleChidWZmZXJUZW1wbGF0ZSkgKyBcIiRcIikgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXJUZW1wbGF0ZSA9IGJ1ZmZlclRlbXBsYXRlLnNsaWNlKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UoYnVmZmVyVGVtcGxhdGUsIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnNwbGl0KFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb2Nlc3NWYWx1ZVtwb3NdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlOiBwb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3M6IHBvc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFzdHJpY3QgJiYgY2hycyA9PT0gb3B0cy5yYWRpeFBvaW50ICYmIG1hc2tzZXQudmFsaWRQb3NpdGlvbnNbcG9zIC0gMV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0OiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zOiBwb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYzogMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvczogcG9zICsgMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNWYWxpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBcIitcIjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoY2hycywgbWFza3NldCwgcG9zLCBzdHJpY3QsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5hbGxvd01pbnVzICYmIChjaHJzID09PSBcIi1cIiB8fCBjaHJzID09PSBvcHRzLm5lZ2F0aW9uU3ltYm9sLmZyb250KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJkaW5hbGl0eTogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIlwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIFwiLVwiOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihjaHJzLCBtYXNrc2V0LCBwb3MsIHN0cmljdCwgb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvcHRzLmFsbG93TWludXMgJiYgY2hycyA9PT0gb3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCI6XCI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRvcjogZnVuY3Rpb24gdmFsaWRhdG9yKGNocnMsIG1hc2tzZXQsIHBvcywgc3RyaWN0LCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhZGl4ID0gXCJbXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5yYWRpeFBvaW50KSArIFwiXVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1ZhbGlkID0gbmV3IFJlZ0V4cChyYWRpeCkudGVzdChjaHJzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZCAmJiBtYXNrc2V0LnZhbGlkUG9zaXRpb25zW3Bvc10gJiYgbWFza3NldC52YWxpZFBvc2l0aW9uc1twb3NdLm1hdGNoLnBsYWNlaG9sZGVyID09PSBvcHRzLnJhZGl4UG9pbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0OiBwb3MgKyAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmRpbmFsaXR5OiAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IGZ1bmN0aW9uIHBsYWNlaG9sZGVyKG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0cy5yYWRpeFBvaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvblVuTWFzazogZnVuY3Rpb24gb25Vbk1hc2sobWFza2VkVmFsdWUsIHVubWFza2VkVmFsdWUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHVubWFza2VkVmFsdWUgPT09IFwiXCIgJiYgb3B0cy5udWxsYWJsZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVubWFza2VkVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb2Nlc3NWYWx1ZSA9IG1hc2tlZFZhbHVlLnJlcGxhY2Uob3B0cy5wcmVmaXgsIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShvcHRzLnN1ZmZpeCwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMuZ3JvdXBTZXBhcmF0b3IpLCBcImdcIiksIFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCkgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NWYWx1ZSA9IHByb2Nlc3NWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAob3B0cy5wbGFjZWhvbGRlci5jaGFyQXQoMCksIFwiZ1wiKSwgXCIwXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRzLnVubWFza0FzTnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5yYWRpeFBvaW50ICE9PSBcIlwiICYmIHByb2Nlc3NWYWx1ZS5pbmRleE9mKG9wdHMucmFkaXhQb2ludCkgIT09IC0xKSBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShJbnB1dG1hc2suZXNjYXBlUmVnZXguY2FsbCh0aGlzLCBvcHRzLnJhZGl4UG9pbnQpLCBcIi5cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVmFsdWUgPSBwcm9jZXNzVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKFwiXlwiICsgSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMubmVnYXRpb25TeW1ib2wuZnJvbnQpKSwgXCItXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzc1ZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cChJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5iYWNrKSArIFwiJFwiKSwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gTnVtYmVyKHByb2Nlc3NWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NWYWx1ZTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGlzQ29tcGxldGU6IGZ1bmN0aW9uIGlzQ29tcGxldGUoYnVmZmVyLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXNrZWRWYWx1ZSA9IChvcHRzLm51bWVyaWNJbnB1dCA/IGJ1ZmZlci5zbGljZSgpLnJldmVyc2UoKSA6IGJ1ZmZlcikuam9pbihcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWFza2VkVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoXCJeXCIgKyBJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5uZWdhdGlvblN5bWJvbC5mcm9udCkpLCBcIi1cIik7XG4gICAgICAgICAgICAgICAgICAgIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmVwbGFjZShuZXcgUmVnRXhwKElucHV0bWFzay5lc2NhcGVSZWdleChvcHRzLm5lZ2F0aW9uU3ltYm9sLmJhY2spICsgXCIkXCIpLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWFza2VkVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXBsYWNlKG9wdHMucHJlZml4LCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWFza2VkVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXBsYWNlKG9wdHMuc3VmZml4LCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWFza2VkVmFsdWUgPSBtYXNrZWRWYWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KG9wdHMuZ3JvdXBTZXBhcmF0b3IpICsgXCIoWzAtOV17M30pXCIsIFwiZ1wiKSwgXCIkMVwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMucmFkaXhQb2ludCA9PT0gXCIsXCIpIG1hc2tlZFZhbHVlID0gbWFza2VkVmFsdWUucmVwbGFjZShJbnB1dG1hc2suZXNjYXBlUmVnZXgob3B0cy5yYWRpeFBvaW50KSwgXCIuXCIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNGaW5pdGUobWFza2VkVmFsdWUpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25CZWZvcmVNYXNrOiBmdW5jdGlvbiBvbkJlZm9yZU1hc2soaW5pdGlhbFZhbHVlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMuaXNOZWdhdGl2ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJhZGl4UG9pbnQgPSBvcHRzLnJhZGl4UG9pbnQgfHwgXCIsXCI7XG4gICAgICAgICAgICAgICAgICAgIGlmICgodHlwZW9mIGluaXRpYWxWYWx1ZSA9PSBcIm51bWJlclwiIHx8IG9wdHMuaW5wdXRUeXBlID09PSBcIm51bWJlclwiKSAmJiByYWRpeFBvaW50ICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUudG9TdHJpbmcoKS5yZXBsYWNlKFwiLlwiLCByYWRpeFBvaW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVQYXJ0cyA9IGluaXRpYWxWYWx1ZS5zcGxpdChyYWRpeFBvaW50KSwgaW50ZWdlclBhcnQgPSB2YWx1ZVBhcnRzWzBdLnJlcGxhY2UoL1teXFwtMC05XS9nLCBcIlwiKSwgZGVjaW1hbFBhcnQgPSB2YWx1ZVBhcnRzLmxlbmd0aCA+IDEgPyB2YWx1ZVBhcnRzWzFdLnJlcGxhY2UoL1teMC05XS9nLCBcIlwiKSA6IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGludGVnZXJQYXJ0ICsgKGRlY2ltYWxQYXJ0ICE9PSBcIlwiID8gcmFkaXhQb2ludCArIGRlY2ltYWxQYXJ0IDogZGVjaW1hbFBhcnQpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGlnaXRzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJhZGl4UG9pbnQgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IGRlY2ltYWxQYXJ0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWNpbWFsUGFydCAhPT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkaWdpdHNGYWN0b3IgPSBNYXRoLnBvdygxMCwgZGlnaXRzIHx8IDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0Zpbml0ZShvcHRzLmRpZ2l0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlnaXRzID0gcGFyc2VJbnQob3B0cy5kaWdpdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWdpdHNGYWN0b3IgPSBNYXRoLnBvdygxMCwgZGlnaXRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gaW5pdGlhbFZhbHVlLnJlcGxhY2UoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KHJhZGl4UG9pbnQpLCBcIi5cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmluaXRlKGluaXRpYWxWYWx1ZSkpIGluaXRpYWxWYWx1ZSA9IE1hdGgucm91bmQocGFyc2VGbG9hdChpbml0aWFsVmFsdWUpICogZGlnaXRzRmFjdG9yKSAvIGRpZ2l0c0ZhY3RvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWUudG9TdHJpbmcoKS5yZXBsYWNlKFwiLlwiLCByYWRpeFBvaW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0cy5kaWdpdHMgPT09IDAgJiYgaW5pdGlhbFZhbHVlLmluZGV4T2YoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KHJhZGl4UG9pbnQpKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGluaXRpYWxWYWx1ZS5zdWJzdHJpbmcoMCwgaW5pdGlhbFZhbHVlLmluZGV4T2YoSW5wdXRtYXNrLmVzY2FwZVJlZ2V4KHJhZGl4UG9pbnQpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFsaWduRGlnaXRzKGluaXRpYWxWYWx1ZS50b1N0cmluZygpLnNwbGl0KFwiXCIpLCBkaWdpdHMsIG9wdHMpLmpvaW4oXCJcIik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbktleURvd246IGZ1bmN0aW9uIG9uS2V5RG93bihlLCBidWZmZXIsIGNhcmV0UG9zLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkaW5wdXQgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZS5jdHJsS2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGUua2V5Q29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIElucHV0bWFzay5rZXlDb2RlLlVQOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwocGFyc2VGbG9hdCh0aGlzLmlucHV0bWFzay51bm1hc2tlZHZhbHVlKCkpICsgcGFyc2VJbnQob3B0cy5zdGVwKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnRyaWdnZXIoXCJzZXR2YWx1ZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIElucHV0bWFzay5rZXlDb2RlLkRPV046XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LnZhbChwYXJzZUZsb2F0KHRoaXMuaW5wdXRtYXNrLnVubWFza2VkdmFsdWUoKSkgLSBwYXJzZUludChvcHRzLnN0ZXApKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudHJpZ2dlcihcInNldHZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGN1cnJlbmN5OiB7XG4gICAgICAgICAgICAgICAgcHJlZml4OiBcIiQgXCIsXG4gICAgICAgICAgICAgICAgZ3JvdXBTZXBhcmF0b3I6IFwiLFwiLFxuICAgICAgICAgICAgICAgIGFsaWFzOiBcIm51bWVyaWNcIixcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCIwXCIsXG4gICAgICAgICAgICAgICAgYXV0b0dyb3VwOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRpZ2l0czogMixcbiAgICAgICAgICAgICAgICBkaWdpdHNPcHRpb25hbDogZmFsc2UsXG4gICAgICAgICAgICAgICAgY2xlYXJNYXNrT25Mb3N0Rm9jdXM6IGZhbHNlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVjaW1hbDoge1xuICAgICAgICAgICAgICAgIGFsaWFzOiBcIm51bWVyaWNcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGludGVnZXI6IHtcbiAgICAgICAgICAgICAgICBhbGlhczogXCJudW1lcmljXCIsXG4gICAgICAgICAgICAgICAgZGlnaXRzOiAwLFxuICAgICAgICAgICAgICAgIHJhZGl4UG9pbnQ6IFwiXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwZXJjZW50YWdlOiB7XG4gICAgICAgICAgICAgICAgYWxpYXM6IFwibnVtZXJpY1wiLFxuICAgICAgICAgICAgICAgIGRpZ2l0czogMixcbiAgICAgICAgICAgICAgICBkaWdpdHNPcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICByYWRpeFBvaW50OiBcIi5cIixcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCIwXCIsXG4gICAgICAgICAgICAgICAgYXV0b0dyb3VwOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgbWF4OiAxMDAsXG4gICAgICAgICAgICAgICAgc3VmZml4OiBcIiAlXCIsXG4gICAgICAgICAgICAgICAgYWxsb3dNaW51czogZmFsc2VcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBJbnB1dG1hc2s7XG4gICAgfSk7XG59LCBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICB2YXIgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fLCBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXztcbiAgICB2YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2Ygb2JqO1xuICAgIH0gOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7XG4gICAgfTtcbiAgICAoZnVuY3Rpb24oZmFjdG9yeSkge1xuICAgICAgICBpZiAodHJ1ZSkge1xuICAgICAgICAgICAgIShfX1dFQlBBQ0tfQU1EX0RFRklORV9BUlJBWV9fID0gWyBfX3dlYnBhY2tfcmVxdWlyZV9fKDQpLCBfX3dlYnBhY2tfcmVxdWlyZV9fKDIpIF0sIFxuICAgICAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID0gZmFjdG9yeSwgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gPSB0eXBlb2YgX19XRUJQQUNLX0FNRF9ERUZJTkVfRkFDVE9SWV9fID09PSBcImZ1bmN0aW9uXCIgPyBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18uYXBwbHkoZXhwb3J0cywgX19XRUJQQUNLX0FNRF9ERUZJTkVfQVJSQVlfXykgOiBfX1dFQlBBQ0tfQU1EX0RFRklORV9GQUNUT1JZX18sIFxuICAgICAgICAgICAgX19XRUJQQUNLX0FNRF9ERUZJTkVfUkVTVUxUX18gIT09IHVuZGVmaW5lZCAmJiAobW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfQU1EX0RFRklORV9SRVNVTFRfXykpO1xuICAgICAgICB9IGVsc2Uge31cbiAgICB9KShmdW5jdGlvbigkLCBJbnB1dG1hc2spIHtcbiAgICAgICAgaWYgKCQuZm4uaW5wdXRtYXNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICQuZm4uaW5wdXRtYXNrID0gZnVuY3Rpb24oZm4sIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbnB0bWFzaywgaW5wdXQgPSB0aGlzWzBdO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB1bmRlZmluZWQpIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGZuID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwidW5tYXNrZWR2YWx1ZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0ICYmIGlucHV0LmlucHV0bWFzayA/IGlucHV0LmlucHV0bWFzay51bm1hc2tlZHZhbHVlKCkgOiAkKGlucHV0KS52YWwoKTtcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJyZW1vdmVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRtYXNrKSB0aGlzLmlucHV0bWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImdldGVtcHR5bWFza1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0ICYmIGlucHV0LmlucHV0bWFzayA/IGlucHV0LmlucHV0bWFzay5nZXRlbXB0eW1hc2soKSA6IFwiXCI7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaGFzTWFza2VkVmFsdWVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dCAmJiBpbnB1dC5pbnB1dG1hc2sgPyBpbnB1dC5pbnB1dG1hc2suaGFzTWFza2VkVmFsdWUoKSA6IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImlzQ29tcGxldGVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dCAmJiBpbnB1dC5pbnB1dG1hc2sgPyBpbnB1dC5pbnB1dG1hc2suaXNDb21wbGV0ZSgpIDogdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJnZXRtZXRhZGF0YVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0ICYmIGlucHV0LmlucHV0bWFzayA/IGlucHV0LmlucHV0bWFzay5nZXRtZXRhZGF0YSgpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInNldHZhbHVlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBJbnB1dG1hc2suc2V0VmFsdWUoaW5wdXQsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwib3B0aW9uXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQgJiYgaW5wdXQuaW5wdXRtYXNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0LmlucHV0bWFzay5vcHRpb24ob3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dG1hc2sgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRtYXNrLm9wdGlvbihvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5hbGlhcyA9IGZuO1xuICAgICAgICAgICAgICAgICAgICAgICAgbnB0bWFzayA9IG5ldyBJbnB1dG1hc2sob3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5wdG1hc2subWFzayh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGZuKSkge1xuICAgICAgICAgICAgICAgICAgICBvcHRpb25zLmFsaWFzID0gZm47XG4gICAgICAgICAgICAgICAgICAgIG5wdG1hc2sgPSBuZXcgSW5wdXRtYXNrKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbnB0bWFzay5tYXNrKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCh0eXBlb2YgZm4gPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogX3R5cGVvZihmbikpID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbnB0bWFzayA9IG5ldyBJbnB1dG1hc2soZm4pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZm4ubWFzayA9PT0gdW5kZWZpbmVkICYmIGZuLmFsaWFzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRtYXNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRtYXNrLm9wdGlvbihmbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIG5wdG1hc2subWFzayh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBucHRtYXNrLm1hc2sodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZm4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbnB0bWFzayA9IG5ldyBJbnB1dG1hc2sob3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBucHRtYXNrLm1hc2sodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICQuZm4uaW5wdXRtYXNrO1xuICAgIH0pO1xufSBdKTsiLCIoIGZ1bmN0aW9uKCBmYWN0b3J5ICkge1xuXHRpZiAoIHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICkge1xuXG5cdFx0Ly8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxuXHRcdGRlZmluZSggWyBcImpxdWVyeVwiIF0sIGZhY3RvcnkgKTtcblx0fSBlbHNlIHtcblxuXHRcdC8vIEJyb3dzZXIgZ2xvYmFsc1xuXHRcdGZhY3RvcnkoIGpRdWVyeSApO1xuXHR9XG59ICggZnVuY3Rpb24oICQgKSB7XG5cbiQudWkgPSAkLnVpIHx8IHt9O1xuXG5yZXR1cm4gJC51aS52ZXJzaW9uID0gXCIxLjEyLjFcIjtcblxufSApICk7XG4iLCIvKiFcbiAqIGpRdWVyeSBVSSBQb3NpdGlvbiAxLjEyLjFcbiAqIGh0dHA6Ly9qcXVlcnl1aS5jb21cbiAqXG4gKiBDb3B5cmlnaHQgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLlxuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIGh0dHA6Ly9hcGkuanF1ZXJ5dWkuY29tL3Bvc2l0aW9uL1xuICovXG5cbi8vPj5sYWJlbDogUG9zaXRpb25cbi8vPj5ncm91cDogQ29yZVxuLy8+PmRlc2NyaXB0aW9uOiBQb3NpdGlvbnMgZWxlbWVudHMgcmVsYXRpdmUgdG8gb3RoZXIgZWxlbWVudHMuXG4vLz4+ZG9jczogaHR0cDovL2FwaS5qcXVlcnl1aS5jb20vcG9zaXRpb24vXG4vLz4+ZGVtb3M6IGh0dHA6Ly9qcXVlcnl1aS5jb20vcG9zaXRpb24vXG5cbiggZnVuY3Rpb24oIGZhY3RvcnkgKSB7XG5cdGlmICggdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQgKSB7XG5cblx0XHQvLyBBTUQuIFJlZ2lzdGVyIGFzIGFuIGFub255bW91cyBtb2R1bGUuXG5cdFx0ZGVmaW5lKCBbIFwianF1ZXJ5XCIsIFwiLi92ZXJzaW9uXCIgXSwgZmFjdG9yeSApO1xuXHR9IGVsc2Uge1xuXG5cdFx0Ly8gQnJvd3NlciBnbG9iYWxzXG5cdFx0ZmFjdG9yeSggalF1ZXJ5ICk7XG5cdH1cbn0oIGZ1bmN0aW9uKCAkICkge1xuKCBmdW5jdGlvbigpIHtcbnZhciBjYWNoZWRTY3JvbGxiYXJXaWR0aCxcblx0bWF4ID0gTWF0aC5tYXgsXG5cdGFicyA9IE1hdGguYWJzLFxuXHRyaG9yaXpvbnRhbCA9IC9sZWZ0fGNlbnRlcnxyaWdodC8sXG5cdHJ2ZXJ0aWNhbCA9IC90b3B8Y2VudGVyfGJvdHRvbS8sXG5cdHJvZmZzZXQgPSAvW1xcK1xcLV1cXGQrKFxcLltcXGRdKyk/JT8vLFxuXHRycG9zaXRpb24gPSAvXlxcdysvLFxuXHRycGVyY2VudCA9IC8lJC8sXG5cdF9wb3NpdGlvbiA9ICQuZm4ucG9zaXRpb247XG5cbmZ1bmN0aW9uIGdldE9mZnNldHMoIG9mZnNldHMsIHdpZHRoLCBoZWlnaHQgKSB7XG5cdHJldHVybiBbXG5cdFx0cGFyc2VGbG9hdCggb2Zmc2V0c1sgMCBdICkgKiAoIHJwZXJjZW50LnRlc3QoIG9mZnNldHNbIDAgXSApID8gd2lkdGggLyAxMDAgOiAxICksXG5cdFx0cGFyc2VGbG9hdCggb2Zmc2V0c1sgMSBdICkgKiAoIHJwZXJjZW50LnRlc3QoIG9mZnNldHNbIDEgXSApID8gaGVpZ2h0IC8gMTAwIDogMSApXG5cdF07XG59XG5cbmZ1bmN0aW9uIHBhcnNlQ3NzKCBlbGVtZW50LCBwcm9wZXJ0eSApIHtcblx0cmV0dXJuIHBhcnNlSW50KCAkLmNzcyggZWxlbWVudCwgcHJvcGVydHkgKSwgMTAgKSB8fCAwO1xufVxuXG5mdW5jdGlvbiBnZXREaW1lbnNpb25zKCBlbGVtICkge1xuXHR2YXIgcmF3ID0gZWxlbVsgMCBdO1xuXHRpZiAoIHJhdy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0d2lkdGg6IGVsZW0ud2lkdGgoKSxcblx0XHRcdGhlaWdodDogZWxlbS5oZWlnaHQoKSxcblx0XHRcdG9mZnNldDogeyB0b3A6IDAsIGxlZnQ6IDAgfVxuXHRcdH07XG5cdH1cblx0aWYgKCAkLmlzV2luZG93KCByYXcgKSApIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0d2lkdGg6IGVsZW0ud2lkdGgoKSxcblx0XHRcdGhlaWdodDogZWxlbS5oZWlnaHQoKSxcblx0XHRcdG9mZnNldDogeyB0b3A6IGVsZW0uc2Nyb2xsVG9wKCksIGxlZnQ6IGVsZW0uc2Nyb2xsTGVmdCgpIH1cblx0XHR9O1xuXHR9XG5cdGlmICggcmF3LnByZXZlbnREZWZhdWx0ICkge1xuXHRcdHJldHVybiB7XG5cdFx0XHR3aWR0aDogMCxcblx0XHRcdGhlaWdodDogMCxcblx0XHRcdG9mZnNldDogeyB0b3A6IHJhdy5wYWdlWSwgbGVmdDogcmF3LnBhZ2VYIH1cblx0XHR9O1xuXHR9XG5cdHJldHVybiB7XG5cdFx0d2lkdGg6IGVsZW0ub3V0ZXJXaWR0aCgpLFxuXHRcdGhlaWdodDogZWxlbS5vdXRlckhlaWdodCgpLFxuXHRcdG9mZnNldDogZWxlbS5vZmZzZXQoKVxuXHR9O1xufVxuXG4kLnBvc2l0aW9uID0ge1xuXHRzY3JvbGxiYXJXaWR0aDogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCBjYWNoZWRTY3JvbGxiYXJXaWR0aCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuIGNhY2hlZFNjcm9sbGJhcldpZHRoO1xuXHRcdH1cblx0XHR2YXIgdzEsIHcyLFxuXHRcdFx0ZGl2ID0gJCggXCI8ZGl2IFwiICtcblx0XHRcdFx0XCJzdHlsZT0nZGlzcGxheTpibG9jaztwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDo1MHB4O2hlaWdodDo1MHB4O292ZXJmbG93OmhpZGRlbjsnPlwiICtcblx0XHRcdFx0XCI8ZGl2IHN0eWxlPSdoZWlnaHQ6MTAwcHg7d2lkdGg6YXV0bzsnPjwvZGl2PjwvZGl2PlwiICksXG5cdFx0XHRpbm5lckRpdiA9IGRpdi5jaGlsZHJlbigpWyAwIF07XG5cblx0XHQkKCBcImJvZHlcIiApLmFwcGVuZCggZGl2ICk7XG5cdFx0dzEgPSBpbm5lckRpdi5vZmZzZXRXaWR0aDtcblx0XHRkaXYuY3NzKCBcIm92ZXJmbG93XCIsIFwic2Nyb2xsXCIgKTtcblxuXHRcdHcyID0gaW5uZXJEaXYub2Zmc2V0V2lkdGg7XG5cblx0XHRpZiAoIHcxID09PSB3MiApIHtcblx0XHRcdHcyID0gZGl2WyAwIF0uY2xpZW50V2lkdGg7XG5cdFx0fVxuXG5cdFx0ZGl2LnJlbW92ZSgpO1xuXG5cdFx0cmV0dXJuICggY2FjaGVkU2Nyb2xsYmFyV2lkdGggPSB3MSAtIHcyICk7XG5cdH0sXG5cdGdldFNjcm9sbEluZm86IGZ1bmN0aW9uKCB3aXRoaW4gKSB7XG5cdFx0dmFyIG92ZXJmbG93WCA9IHdpdGhpbi5pc1dpbmRvdyB8fCB3aXRoaW4uaXNEb2N1bWVudCA/IFwiXCIgOlxuXHRcdFx0XHR3aXRoaW4uZWxlbWVudC5jc3MoIFwib3ZlcmZsb3cteFwiICksXG5cdFx0XHRvdmVyZmxvd1kgPSB3aXRoaW4uaXNXaW5kb3cgfHwgd2l0aGluLmlzRG9jdW1lbnQgPyBcIlwiIDpcblx0XHRcdFx0d2l0aGluLmVsZW1lbnQuY3NzKCBcIm92ZXJmbG93LXlcIiApLFxuXHRcdFx0aGFzT3ZlcmZsb3dYID0gb3ZlcmZsb3dYID09PSBcInNjcm9sbFwiIHx8XG5cdFx0XHRcdCggb3ZlcmZsb3dYID09PSBcImF1dG9cIiAmJiB3aXRoaW4ud2lkdGggPCB3aXRoaW4uZWxlbWVudFsgMCBdLnNjcm9sbFdpZHRoICksXG5cdFx0XHRoYXNPdmVyZmxvd1kgPSBvdmVyZmxvd1kgPT09IFwic2Nyb2xsXCIgfHxcblx0XHRcdFx0KCBvdmVyZmxvd1kgPT09IFwiYXV0b1wiICYmIHdpdGhpbi5oZWlnaHQgPCB3aXRoaW4uZWxlbWVudFsgMCBdLnNjcm9sbEhlaWdodCApO1xuXHRcdHJldHVybiB7XG5cdFx0XHR3aWR0aDogaGFzT3ZlcmZsb3dZID8gJC5wb3NpdGlvbi5zY3JvbGxiYXJXaWR0aCgpIDogMCxcblx0XHRcdGhlaWdodDogaGFzT3ZlcmZsb3dYID8gJC5wb3NpdGlvbi5zY3JvbGxiYXJXaWR0aCgpIDogMFxuXHRcdH07XG5cdH0sXG5cdGdldFdpdGhpbkluZm86IGZ1bmN0aW9uKCBlbGVtZW50ICkge1xuXHRcdHZhciB3aXRoaW5FbGVtZW50ID0gJCggZWxlbWVudCB8fCB3aW5kb3cgKSxcblx0XHRcdGlzV2luZG93ID0gJC5pc1dpbmRvdyggd2l0aGluRWxlbWVudFsgMCBdICksXG5cdFx0XHRpc0RvY3VtZW50ID0gISF3aXRoaW5FbGVtZW50WyAwIF0gJiYgd2l0aGluRWxlbWVudFsgMCBdLm5vZGVUeXBlID09PSA5LFxuXHRcdFx0aGFzT2Zmc2V0ID0gIWlzV2luZG93ICYmICFpc0RvY3VtZW50O1xuXHRcdHJldHVybiB7XG5cdFx0XHRlbGVtZW50OiB3aXRoaW5FbGVtZW50LFxuXHRcdFx0aXNXaW5kb3c6IGlzV2luZG93LFxuXHRcdFx0aXNEb2N1bWVudDogaXNEb2N1bWVudCxcblx0XHRcdG9mZnNldDogaGFzT2Zmc2V0ID8gJCggZWxlbWVudCApLm9mZnNldCgpIDogeyBsZWZ0OiAwLCB0b3A6IDAgfSxcblx0XHRcdHNjcm9sbExlZnQ6IHdpdGhpbkVsZW1lbnQuc2Nyb2xsTGVmdCgpLFxuXHRcdFx0c2Nyb2xsVG9wOiB3aXRoaW5FbGVtZW50LnNjcm9sbFRvcCgpLFxuXHRcdFx0d2lkdGg6IHdpdGhpbkVsZW1lbnQub3V0ZXJXaWR0aCgpLFxuXHRcdFx0aGVpZ2h0OiB3aXRoaW5FbGVtZW50Lm91dGVySGVpZ2h0KClcblx0XHR9O1xuXHR9XG59O1xuXG4kLmZuLnBvc2l0aW9uID0gZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cdGlmICggIW9wdGlvbnMgfHwgIW9wdGlvbnMub2YgKSB7XG5cdFx0cmV0dXJuIF9wb3NpdGlvbi5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdH1cblxuXHQvLyBNYWtlIGEgY29weSwgd2UgZG9uJ3Qgd2FudCB0byBtb2RpZnkgYXJndW1lbnRzXG5cdG9wdGlvbnMgPSAkLmV4dGVuZCgge30sIG9wdGlvbnMgKTtcblxuXHR2YXIgYXRPZmZzZXQsIHRhcmdldFdpZHRoLCB0YXJnZXRIZWlnaHQsIHRhcmdldE9mZnNldCwgYmFzZVBvc2l0aW9uLCBkaW1lbnNpb25zLFxuXHRcdHRhcmdldCA9ICQoIG9wdGlvbnMub2YgKSxcblx0XHR3aXRoaW4gPSAkLnBvc2l0aW9uLmdldFdpdGhpbkluZm8oIG9wdGlvbnMud2l0aGluICksXG5cdFx0c2Nyb2xsSW5mbyA9ICQucG9zaXRpb24uZ2V0U2Nyb2xsSW5mbyggd2l0aGluICksXG5cdFx0Y29sbGlzaW9uID0gKCBvcHRpb25zLmNvbGxpc2lvbiB8fCBcImZsaXBcIiApLnNwbGl0KCBcIiBcIiApLFxuXHRcdG9mZnNldHMgPSB7fTtcblxuXHRkaW1lbnNpb25zID0gZ2V0RGltZW5zaW9ucyggdGFyZ2V0ICk7XG5cdGlmICggdGFyZ2V0WyAwIF0ucHJldmVudERlZmF1bHQgKSB7XG5cblx0XHQvLyBGb3JjZSBsZWZ0IHRvcCB0byBhbGxvdyBmbGlwcGluZ1xuXHRcdG9wdGlvbnMuYXQgPSBcImxlZnQgdG9wXCI7XG5cdH1cblx0dGFyZ2V0V2lkdGggPSBkaW1lbnNpb25zLndpZHRoO1xuXHR0YXJnZXRIZWlnaHQgPSBkaW1lbnNpb25zLmhlaWdodDtcblx0dGFyZ2V0T2Zmc2V0ID0gZGltZW5zaW9ucy5vZmZzZXQ7XG5cblx0Ly8gQ2xvbmUgdG8gcmV1c2Ugb3JpZ2luYWwgdGFyZ2V0T2Zmc2V0IGxhdGVyXG5cdGJhc2VQb3NpdGlvbiA9ICQuZXh0ZW5kKCB7fSwgdGFyZ2V0T2Zmc2V0ICk7XG5cblx0Ly8gRm9yY2UgbXkgYW5kIGF0IHRvIGhhdmUgdmFsaWQgaG9yaXpvbnRhbCBhbmQgdmVydGljYWwgcG9zaXRpb25zXG5cdC8vIGlmIGEgdmFsdWUgaXMgbWlzc2luZyBvciBpbnZhbGlkLCBpdCB3aWxsIGJlIGNvbnZlcnRlZCB0byBjZW50ZXJcblx0JC5lYWNoKCBbIFwibXlcIiwgXCJhdFwiIF0sIGZ1bmN0aW9uKCkge1xuXHRcdHZhciBwb3MgPSAoIG9wdGlvbnNbIHRoaXMgXSB8fCBcIlwiICkuc3BsaXQoIFwiIFwiICksXG5cdFx0XHRob3Jpem9udGFsT2Zmc2V0LFxuXHRcdFx0dmVydGljYWxPZmZzZXQ7XG5cblx0XHRpZiAoIHBvcy5sZW5ndGggPT09IDEgKSB7XG5cdFx0XHRwb3MgPSByaG9yaXpvbnRhbC50ZXN0KCBwb3NbIDAgXSApID9cblx0XHRcdFx0cG9zLmNvbmNhdCggWyBcImNlbnRlclwiIF0gKSA6XG5cdFx0XHRcdHJ2ZXJ0aWNhbC50ZXN0KCBwb3NbIDAgXSApID9cblx0XHRcdFx0XHRbIFwiY2VudGVyXCIgXS5jb25jYXQoIHBvcyApIDpcblx0XHRcdFx0XHRbIFwiY2VudGVyXCIsIFwiY2VudGVyXCIgXTtcblx0XHR9XG5cdFx0cG9zWyAwIF0gPSByaG9yaXpvbnRhbC50ZXN0KCBwb3NbIDAgXSApID8gcG9zWyAwIF0gOiBcImNlbnRlclwiO1xuXHRcdHBvc1sgMSBdID0gcnZlcnRpY2FsLnRlc3QoIHBvc1sgMSBdICkgPyBwb3NbIDEgXSA6IFwiY2VudGVyXCI7XG5cblx0XHQvLyBDYWxjdWxhdGUgb2Zmc2V0c1xuXHRcdGhvcml6b250YWxPZmZzZXQgPSByb2Zmc2V0LmV4ZWMoIHBvc1sgMCBdICk7XG5cdFx0dmVydGljYWxPZmZzZXQgPSByb2Zmc2V0LmV4ZWMoIHBvc1sgMSBdICk7XG5cdFx0b2Zmc2V0c1sgdGhpcyBdID0gW1xuXHRcdFx0aG9yaXpvbnRhbE9mZnNldCA/IGhvcml6b250YWxPZmZzZXRbIDAgXSA6IDAsXG5cdFx0XHR2ZXJ0aWNhbE9mZnNldCA/IHZlcnRpY2FsT2Zmc2V0WyAwIF0gOiAwXG5cdFx0XTtcblxuXHRcdC8vIFJlZHVjZSB0byBqdXN0IHRoZSBwb3NpdGlvbnMgd2l0aG91dCB0aGUgb2Zmc2V0c1xuXHRcdG9wdGlvbnNbIHRoaXMgXSA9IFtcblx0XHRcdHJwb3NpdGlvbi5leGVjKCBwb3NbIDAgXSApWyAwIF0sXG5cdFx0XHRycG9zaXRpb24uZXhlYyggcG9zWyAxIF0gKVsgMCBdXG5cdFx0XTtcblx0fSApO1xuXG5cdC8vIE5vcm1hbGl6ZSBjb2xsaXNpb24gb3B0aW9uXG5cdGlmICggY29sbGlzaW9uLmxlbmd0aCA9PT0gMSApIHtcblx0XHRjb2xsaXNpb25bIDEgXSA9IGNvbGxpc2lvblsgMCBdO1xuXHR9XG5cblx0aWYgKCBvcHRpb25zLmF0WyAwIF0gPT09IFwicmlnaHRcIiApIHtcblx0XHRiYXNlUG9zaXRpb24ubGVmdCArPSB0YXJnZXRXaWR0aDtcblx0fSBlbHNlIGlmICggb3B0aW9ucy5hdFsgMCBdID09PSBcImNlbnRlclwiICkge1xuXHRcdGJhc2VQb3NpdGlvbi5sZWZ0ICs9IHRhcmdldFdpZHRoIC8gMjtcblx0fVxuXG5cdGlmICggb3B0aW9ucy5hdFsgMSBdID09PSBcImJvdHRvbVwiICkge1xuXHRcdGJhc2VQb3NpdGlvbi50b3AgKz0gdGFyZ2V0SGVpZ2h0O1xuXHR9IGVsc2UgaWYgKCBvcHRpb25zLmF0WyAxIF0gPT09IFwiY2VudGVyXCIgKSB7XG5cdFx0YmFzZVBvc2l0aW9uLnRvcCArPSB0YXJnZXRIZWlnaHQgLyAyO1xuXHR9XG5cblx0YXRPZmZzZXQgPSBnZXRPZmZzZXRzKCBvZmZzZXRzLmF0LCB0YXJnZXRXaWR0aCwgdGFyZ2V0SGVpZ2h0ICk7XG5cdGJhc2VQb3NpdGlvbi5sZWZ0ICs9IGF0T2Zmc2V0WyAwIF07XG5cdGJhc2VQb3NpdGlvbi50b3AgKz0gYXRPZmZzZXRbIDEgXTtcblxuXHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHR2YXIgY29sbGlzaW9uUG9zaXRpb24sIHVzaW5nLFxuXHRcdFx0ZWxlbSA9ICQoIHRoaXMgKSxcblx0XHRcdGVsZW1XaWR0aCA9IGVsZW0ub3V0ZXJXaWR0aCgpLFxuXHRcdFx0ZWxlbUhlaWdodCA9IGVsZW0ub3V0ZXJIZWlnaHQoKSxcblx0XHRcdG1hcmdpbkxlZnQgPSBwYXJzZUNzcyggdGhpcywgXCJtYXJnaW5MZWZ0XCIgKSxcblx0XHRcdG1hcmdpblRvcCA9IHBhcnNlQ3NzKCB0aGlzLCBcIm1hcmdpblRvcFwiICksXG5cdFx0XHRjb2xsaXNpb25XaWR0aCA9IGVsZW1XaWR0aCArIG1hcmdpbkxlZnQgKyBwYXJzZUNzcyggdGhpcywgXCJtYXJnaW5SaWdodFwiICkgK1xuXHRcdFx0XHRzY3JvbGxJbmZvLndpZHRoLFxuXHRcdFx0Y29sbGlzaW9uSGVpZ2h0ID0gZWxlbUhlaWdodCArIG1hcmdpblRvcCArIHBhcnNlQ3NzKCB0aGlzLCBcIm1hcmdpbkJvdHRvbVwiICkgK1xuXHRcdFx0XHRzY3JvbGxJbmZvLmhlaWdodCxcblx0XHRcdHBvc2l0aW9uID0gJC5leHRlbmQoIHt9LCBiYXNlUG9zaXRpb24gKSxcblx0XHRcdG15T2Zmc2V0ID0gZ2V0T2Zmc2V0cyggb2Zmc2V0cy5teSwgZWxlbS5vdXRlcldpZHRoKCksIGVsZW0ub3V0ZXJIZWlnaHQoKSApO1xuXG5cdFx0aWYgKCBvcHRpb25zLm15WyAwIF0gPT09IFwicmlnaHRcIiApIHtcblx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gZWxlbVdpZHRoO1xuXHRcdH0gZWxzZSBpZiAoIG9wdGlvbnMubXlbIDAgXSA9PT0gXCJjZW50ZXJcIiApIHtcblx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gZWxlbVdpZHRoIC8gMjtcblx0XHR9XG5cblx0XHRpZiAoIG9wdGlvbnMubXlbIDEgXSA9PT0gXCJib3R0b21cIiApIHtcblx0XHRcdHBvc2l0aW9uLnRvcCAtPSBlbGVtSGVpZ2h0O1xuXHRcdH0gZWxzZSBpZiAoIG9wdGlvbnMubXlbIDEgXSA9PT0gXCJjZW50ZXJcIiApIHtcblx0XHRcdHBvc2l0aW9uLnRvcCAtPSBlbGVtSGVpZ2h0IC8gMjtcblx0XHR9XG5cblx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0WyAwIF07XG5cdFx0cG9zaXRpb24udG9wICs9IG15T2Zmc2V0WyAxIF07XG5cblx0XHRjb2xsaXNpb25Qb3NpdGlvbiA9IHtcblx0XHRcdG1hcmdpbkxlZnQ6IG1hcmdpbkxlZnQsXG5cdFx0XHRtYXJnaW5Ub3A6IG1hcmdpblRvcFxuXHRcdH07XG5cblx0XHQkLmVhY2goIFsgXCJsZWZ0XCIsIFwidG9wXCIgXSwgZnVuY3Rpb24oIGksIGRpciApIHtcblx0XHRcdGlmICggJC51aS5wb3NpdGlvblsgY29sbGlzaW9uWyBpIF0gXSApIHtcblx0XHRcdFx0JC51aS5wb3NpdGlvblsgY29sbGlzaW9uWyBpIF0gXVsgZGlyIF0oIHBvc2l0aW9uLCB7XG5cdFx0XHRcdFx0dGFyZ2V0V2lkdGg6IHRhcmdldFdpZHRoLFxuXHRcdFx0XHRcdHRhcmdldEhlaWdodDogdGFyZ2V0SGVpZ2h0LFxuXHRcdFx0XHRcdGVsZW1XaWR0aDogZWxlbVdpZHRoLFxuXHRcdFx0XHRcdGVsZW1IZWlnaHQ6IGVsZW1IZWlnaHQsXG5cdFx0XHRcdFx0Y29sbGlzaW9uUG9zaXRpb246IGNvbGxpc2lvblBvc2l0aW9uLFxuXHRcdFx0XHRcdGNvbGxpc2lvbldpZHRoOiBjb2xsaXNpb25XaWR0aCxcblx0XHRcdFx0XHRjb2xsaXNpb25IZWlnaHQ6IGNvbGxpc2lvbkhlaWdodCxcblx0XHRcdFx0XHRvZmZzZXQ6IFsgYXRPZmZzZXRbIDAgXSArIG15T2Zmc2V0WyAwIF0sIGF0T2Zmc2V0IFsgMSBdICsgbXlPZmZzZXRbIDEgXSBdLFxuXHRcdFx0XHRcdG15OiBvcHRpb25zLm15LFxuXHRcdFx0XHRcdGF0OiBvcHRpb25zLmF0LFxuXHRcdFx0XHRcdHdpdGhpbjogd2l0aGluLFxuXHRcdFx0XHRcdGVsZW06IGVsZW1cblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblxuXHRcdGlmICggb3B0aW9ucy51c2luZyApIHtcblxuXHRcdFx0Ly8gQWRkcyBmZWVkYmFjayBhcyBzZWNvbmQgYXJndW1lbnQgdG8gdXNpbmcgY2FsbGJhY2ssIGlmIHByZXNlbnRcblx0XHRcdHVzaW5nID0gZnVuY3Rpb24oIHByb3BzICkge1xuXHRcdFx0XHR2YXIgbGVmdCA9IHRhcmdldE9mZnNldC5sZWZ0IC0gcG9zaXRpb24ubGVmdCxcblx0XHRcdFx0XHRyaWdodCA9IGxlZnQgKyB0YXJnZXRXaWR0aCAtIGVsZW1XaWR0aCxcblx0XHRcdFx0XHR0b3AgPSB0YXJnZXRPZmZzZXQudG9wIC0gcG9zaXRpb24udG9wLFxuXHRcdFx0XHRcdGJvdHRvbSA9IHRvcCArIHRhcmdldEhlaWdodCAtIGVsZW1IZWlnaHQsXG5cdFx0XHRcdFx0ZmVlZGJhY2sgPSB7XG5cdFx0XHRcdFx0XHR0YXJnZXQ6IHtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudDogdGFyZ2V0LFxuXHRcdFx0XHRcdFx0XHRsZWZ0OiB0YXJnZXRPZmZzZXQubGVmdCxcblx0XHRcdFx0XHRcdFx0dG9wOiB0YXJnZXRPZmZzZXQudG9wLFxuXHRcdFx0XHRcdFx0XHR3aWR0aDogdGFyZ2V0V2lkdGgsXG5cdFx0XHRcdFx0XHRcdGhlaWdodDogdGFyZ2V0SGVpZ2h0XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0ZWxlbWVudDoge1xuXHRcdFx0XHRcdFx0XHRlbGVtZW50OiBlbGVtLFxuXHRcdFx0XHRcdFx0XHRsZWZ0OiBwb3NpdGlvbi5sZWZ0LFxuXHRcdFx0XHRcdFx0XHR0b3A6IHBvc2l0aW9uLnRvcCxcblx0XHRcdFx0XHRcdFx0d2lkdGg6IGVsZW1XaWR0aCxcblx0XHRcdFx0XHRcdFx0aGVpZ2h0OiBlbGVtSGVpZ2h0XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0aG9yaXpvbnRhbDogcmlnaHQgPCAwID8gXCJsZWZ0XCIgOiBsZWZ0ID4gMCA/IFwicmlnaHRcIiA6IFwiY2VudGVyXCIsXG5cdFx0XHRcdFx0XHR2ZXJ0aWNhbDogYm90dG9tIDwgMCA/IFwidG9wXCIgOiB0b3AgPiAwID8gXCJib3R0b21cIiA6IFwibWlkZGxlXCJcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRpZiAoIHRhcmdldFdpZHRoIDwgZWxlbVdpZHRoICYmIGFicyggbGVmdCArIHJpZ2h0ICkgPCB0YXJnZXRXaWR0aCApIHtcblx0XHRcdFx0XHRmZWVkYmFjay5ob3Jpem9udGFsID0gXCJjZW50ZXJcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIHRhcmdldEhlaWdodCA8IGVsZW1IZWlnaHQgJiYgYWJzKCB0b3AgKyBib3R0b20gKSA8IHRhcmdldEhlaWdodCApIHtcblx0XHRcdFx0XHRmZWVkYmFjay52ZXJ0aWNhbCA9IFwibWlkZGxlXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBtYXgoIGFicyggbGVmdCApLCBhYnMoIHJpZ2h0ICkgKSA+IG1heCggYWJzKCB0b3AgKSwgYWJzKCBib3R0b20gKSApICkge1xuXHRcdFx0XHRcdGZlZWRiYWNrLmltcG9ydGFudCA9IFwiaG9yaXpvbnRhbFwiO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGZlZWRiYWNrLmltcG9ydGFudCA9IFwidmVydGljYWxcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRvcHRpb25zLnVzaW5nLmNhbGwoIHRoaXMsIHByb3BzLCBmZWVkYmFjayApO1xuXHRcdFx0fTtcblx0XHR9XG5cblx0XHRlbGVtLm9mZnNldCggJC5leHRlbmQoIHBvc2l0aW9uLCB7IHVzaW5nOiB1c2luZyB9ICkgKTtcblx0fSApO1xufTtcblxuJC51aS5wb3NpdGlvbiA9IHtcblx0Zml0OiB7XG5cdFx0bGVmdDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsTGVmdCA6IHdpdGhpbi5vZmZzZXQubGVmdCxcblx0XHRcdFx0b3V0ZXJXaWR0aCA9IHdpdGhpbi53aWR0aCxcblx0XHRcdFx0Y29sbGlzaW9uUG9zTGVmdCA9IHBvc2l0aW9uLmxlZnQgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpbkxlZnQsXG5cdFx0XHRcdG92ZXJMZWZ0ID0gd2l0aGluT2Zmc2V0IC0gY29sbGlzaW9uUG9zTGVmdCxcblx0XHRcdFx0b3ZlclJpZ2h0ID0gY29sbGlzaW9uUG9zTGVmdCArIGRhdGEuY29sbGlzaW9uV2lkdGggLSBvdXRlcldpZHRoIC0gd2l0aGluT2Zmc2V0LFxuXHRcdFx0XHRuZXdPdmVyUmlnaHQ7XG5cblx0XHRcdC8vIEVsZW1lbnQgaXMgd2lkZXIgdGhhbiB3aXRoaW5cblx0XHRcdGlmICggZGF0YS5jb2xsaXNpb25XaWR0aCA+IG91dGVyV2lkdGggKSB7XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciB0aGUgbGVmdCBzaWRlIG9mIHdpdGhpblxuXHRcdFx0XHRpZiAoIG92ZXJMZWZ0ID4gMCAmJiBvdmVyUmlnaHQgPD0gMCApIHtcblx0XHRcdFx0XHRuZXdPdmVyUmlnaHQgPSBwb3NpdGlvbi5sZWZ0ICsgb3ZlckxlZnQgKyBkYXRhLmNvbGxpc2lvbldpZHRoIC0gb3V0ZXJXaWR0aCAtXG5cdFx0XHRcdFx0XHR3aXRoaW5PZmZzZXQ7XG5cdFx0XHRcdFx0cG9zaXRpb24ubGVmdCArPSBvdmVyTGVmdCAtIG5ld092ZXJSaWdodDtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIHJpZ2h0IHNpZGUgb2Ygd2l0aGluXG5cdFx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgJiYgb3ZlckxlZnQgPD0gMCApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ID0gd2l0aGluT2Zmc2V0O1xuXG5cdFx0XHRcdC8vIEVsZW1lbnQgaXMgaW5pdGlhbGx5IG92ZXIgYm90aCBsZWZ0IGFuZCByaWdodCBzaWRlcyBvZiB3aXRoaW5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpZiAoIG92ZXJMZWZ0ID4gb3ZlclJpZ2h0ICkge1xuXHRcdFx0XHRcdFx0cG9zaXRpb24ubGVmdCA9IHdpdGhpbk9mZnNldCArIG91dGVyV2lkdGggLSBkYXRhLmNvbGxpc2lvbldpZHRoO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ID0gd2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBUb28gZmFyIGxlZnQgLT4gYWxpZ24gd2l0aCBsZWZ0IGVkZ2Vcblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJMZWZ0ID4gMCApIHtcblx0XHRcdFx0cG9zaXRpb24ubGVmdCArPSBvdmVyTGVmdDtcblxuXHRcdFx0Ly8gVG9vIGZhciByaWdodCAtPiBhbGlnbiB3aXRoIHJpZ2h0IGVkZ2Vcblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLmxlZnQgLT0gb3ZlclJpZ2h0O1xuXG5cdFx0XHQvLyBBZGp1c3QgYmFzZWQgb24gcG9zaXRpb24gYW5kIG1hcmdpblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cG9zaXRpb24ubGVmdCA9IG1heCggcG9zaXRpb24ubGVmdCAtIGNvbGxpc2lvblBvc0xlZnQsIHBvc2l0aW9uLmxlZnQgKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdHRvcDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsVG9wIDogd2l0aGluLm9mZnNldC50b3AsXG5cdFx0XHRcdG91dGVySGVpZ2h0ID0gZGF0YS53aXRoaW4uaGVpZ2h0LFxuXHRcdFx0XHRjb2xsaXNpb25Qb3NUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCxcblx0XHRcdFx0b3ZlclRvcCA9IHdpdGhpbk9mZnNldCAtIGNvbGxpc2lvblBvc1RvcCxcblx0XHRcdFx0b3ZlckJvdHRvbSA9IGNvbGxpc2lvblBvc1RvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLSB3aXRoaW5PZmZzZXQsXG5cdFx0XHRcdG5ld092ZXJCb3R0b207XG5cblx0XHRcdC8vIEVsZW1lbnQgaXMgdGFsbGVyIHRoYW4gd2l0aGluXG5cdFx0XHRpZiAoIGRhdGEuY29sbGlzaW9uSGVpZ2h0ID4gb3V0ZXJIZWlnaHQgKSB7XG5cblx0XHRcdFx0Ly8gRWxlbWVudCBpcyBpbml0aWFsbHkgb3ZlciB0aGUgdG9wIG9mIHdpdGhpblxuXHRcdFx0XHRpZiAoIG92ZXJUb3AgPiAwICYmIG92ZXJCb3R0b20gPD0gMCApIHtcblx0XHRcdFx0XHRuZXdPdmVyQm90dG9tID0gcG9zaXRpb24udG9wICsgb3ZlclRvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLVxuXHRcdFx0XHRcdFx0d2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRcdHBvc2l0aW9uLnRvcCArPSBvdmVyVG9wIC0gbmV3T3ZlckJvdHRvbTtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIGJvdHRvbSBvZiB3aXRoaW5cblx0XHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgJiYgb3ZlclRvcCA8PSAwICkge1xuXHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldDtcblxuXHRcdFx0XHQvLyBFbGVtZW50IGlzIGluaXRpYWxseSBvdmVyIGJvdGggdG9wIGFuZCBib3R0b20gb2Ygd2l0aGluXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aWYgKCBvdmVyVG9wID4gb3ZlckJvdHRvbSApIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldCArIG91dGVySGVpZ2h0IC0gZGF0YS5jb2xsaXNpb25IZWlnaHQ7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uLnRvcCA9IHdpdGhpbk9mZnNldDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gVG9vIGZhciB1cCAtPiBhbGlnbiB3aXRoIHRvcFxuXHRcdFx0fSBlbHNlIGlmICggb3ZlclRvcCA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLnRvcCArPSBvdmVyVG9wO1xuXG5cdFx0XHQvLyBUb28gZmFyIGRvd24gLT4gYWxpZ24gd2l0aCBib3R0b20gZWRnZVxuXHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgKSB7XG5cdFx0XHRcdHBvc2l0aW9uLnRvcCAtPSBvdmVyQm90dG9tO1xuXG5cdFx0XHQvLyBBZGp1c3QgYmFzZWQgb24gcG9zaXRpb24gYW5kIG1hcmdpblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cG9zaXRpb24udG9wID0gbWF4KCBwb3NpdGlvbi50b3AgLSBjb2xsaXNpb25Qb3NUb3AsIHBvc2l0aW9uLnRvcCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0ZmxpcDoge1xuXHRcdGxlZnQ6IGZ1bmN0aW9uKCBwb3NpdGlvbiwgZGF0YSApIHtcblx0XHRcdHZhciB3aXRoaW4gPSBkYXRhLndpdGhpbixcblx0XHRcdFx0d2l0aGluT2Zmc2V0ID0gd2l0aGluLm9mZnNldC5sZWZ0ICsgd2l0aGluLnNjcm9sbExlZnQsXG5cdFx0XHRcdG91dGVyV2lkdGggPSB3aXRoaW4ud2lkdGgsXG5cdFx0XHRcdG9mZnNldExlZnQgPSB3aXRoaW4uaXNXaW5kb3cgPyB3aXRoaW4uc2Nyb2xsTGVmdCA6IHdpdGhpbi5vZmZzZXQubGVmdCxcblx0XHRcdFx0Y29sbGlzaW9uUG9zTGVmdCA9IHBvc2l0aW9uLmxlZnQgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpbkxlZnQsXG5cdFx0XHRcdG92ZXJMZWZ0ID0gY29sbGlzaW9uUG9zTGVmdCAtIG9mZnNldExlZnQsXG5cdFx0XHRcdG92ZXJSaWdodCA9IGNvbGxpc2lvblBvc0xlZnQgKyBkYXRhLmNvbGxpc2lvbldpZHRoIC0gb3V0ZXJXaWR0aCAtIG9mZnNldExlZnQsXG5cdFx0XHRcdG15T2Zmc2V0ID0gZGF0YS5teVsgMCBdID09PSBcImxlZnRcIiA/XG5cdFx0XHRcdFx0LWRhdGEuZWxlbVdpZHRoIDpcblx0XHRcdFx0XHRkYXRhLm15WyAwIF0gPT09IFwicmlnaHRcIiA/XG5cdFx0XHRcdFx0XHRkYXRhLmVsZW1XaWR0aCA6XG5cdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRhdE9mZnNldCA9IGRhdGEuYXRbIDAgXSA9PT0gXCJsZWZ0XCIgP1xuXHRcdFx0XHRcdGRhdGEudGFyZ2V0V2lkdGggOlxuXHRcdFx0XHRcdGRhdGEuYXRbIDAgXSA9PT0gXCJyaWdodFwiID9cblx0XHRcdFx0XHRcdC1kYXRhLnRhcmdldFdpZHRoIDpcblx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdG9mZnNldCA9IC0yICogZGF0YS5vZmZzZXRbIDAgXSxcblx0XHRcdFx0bmV3T3ZlclJpZ2h0LFxuXHRcdFx0XHRuZXdPdmVyTGVmdDtcblxuXHRcdFx0aWYgKCBvdmVyTGVmdCA8IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJSaWdodCA9IHBvc2l0aW9uLmxlZnQgKyBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0ICsgZGF0YS5jb2xsaXNpb25XaWR0aCAtXG5cdFx0XHRcdFx0b3V0ZXJXaWR0aCAtIHdpdGhpbk9mZnNldDtcblx0XHRcdFx0aWYgKCBuZXdPdmVyUmlnaHQgPCAwIHx8IG5ld092ZXJSaWdodCA8IGFicyggb3ZlckxlZnQgKSApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoIG92ZXJSaWdodCA+IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJMZWZ0ID0gcG9zaXRpb24ubGVmdCAtIGRhdGEuY29sbGlzaW9uUG9zaXRpb24ubWFyZ2luTGVmdCArIG15T2Zmc2V0ICtcblx0XHRcdFx0XHRhdE9mZnNldCArIG9mZnNldCAtIG9mZnNldExlZnQ7XG5cdFx0XHRcdGlmICggbmV3T3ZlckxlZnQgPiAwIHx8IGFicyggbmV3T3ZlckxlZnQgKSA8IG92ZXJSaWdodCApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi5sZWZ0ICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXHRcdHRvcDogZnVuY3Rpb24oIHBvc2l0aW9uLCBkYXRhICkge1xuXHRcdFx0dmFyIHdpdGhpbiA9IGRhdGEud2l0aGluLFxuXHRcdFx0XHR3aXRoaW5PZmZzZXQgPSB3aXRoaW4ub2Zmc2V0LnRvcCArIHdpdGhpbi5zY3JvbGxUb3AsXG5cdFx0XHRcdG91dGVySGVpZ2h0ID0gd2l0aGluLmhlaWdodCxcblx0XHRcdFx0b2Zmc2V0VG9wID0gd2l0aGluLmlzV2luZG93ID8gd2l0aGluLnNjcm9sbFRvcCA6IHdpdGhpbi5vZmZzZXQudG9wLFxuXHRcdFx0XHRjb2xsaXNpb25Qb3NUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCxcblx0XHRcdFx0b3ZlclRvcCA9IGNvbGxpc2lvblBvc1RvcCAtIG9mZnNldFRvcCxcblx0XHRcdFx0b3ZlckJvdHRvbSA9IGNvbGxpc2lvblBvc1RvcCArIGRhdGEuY29sbGlzaW9uSGVpZ2h0IC0gb3V0ZXJIZWlnaHQgLSBvZmZzZXRUb3AsXG5cdFx0XHRcdHRvcCA9IGRhdGEubXlbIDEgXSA9PT0gXCJ0b3BcIixcblx0XHRcdFx0bXlPZmZzZXQgPSB0b3AgP1xuXHRcdFx0XHRcdC1kYXRhLmVsZW1IZWlnaHQgOlxuXHRcdFx0XHRcdGRhdGEubXlbIDEgXSA9PT0gXCJib3R0b21cIiA/XG5cdFx0XHRcdFx0XHRkYXRhLmVsZW1IZWlnaHQgOlxuXHRcdFx0XHRcdFx0MCxcblx0XHRcdFx0YXRPZmZzZXQgPSBkYXRhLmF0WyAxIF0gPT09IFwidG9wXCIgP1xuXHRcdFx0XHRcdGRhdGEudGFyZ2V0SGVpZ2h0IDpcblx0XHRcdFx0XHRkYXRhLmF0WyAxIF0gPT09IFwiYm90dG9tXCIgP1xuXHRcdFx0XHRcdFx0LWRhdGEudGFyZ2V0SGVpZ2h0IDpcblx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdG9mZnNldCA9IC0yICogZGF0YS5vZmZzZXRbIDEgXSxcblx0XHRcdFx0bmV3T3ZlclRvcCxcblx0XHRcdFx0bmV3T3ZlckJvdHRvbTtcblx0XHRcdGlmICggb3ZlclRvcCA8IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJCb3R0b20gPSBwb3NpdGlvbi50b3AgKyBteU9mZnNldCArIGF0T2Zmc2V0ICsgb2Zmc2V0ICsgZGF0YS5jb2xsaXNpb25IZWlnaHQgLVxuXHRcdFx0XHRcdG91dGVySGVpZ2h0IC0gd2l0aGluT2Zmc2V0O1xuXHRcdFx0XHRpZiAoIG5ld092ZXJCb3R0b20gPCAwIHx8IG5ld092ZXJCb3R0b20gPCBhYnMoIG92ZXJUb3AgKSApIHtcblx0XHRcdFx0XHRwb3NpdGlvbi50b3AgKz0gbXlPZmZzZXQgKyBhdE9mZnNldCArIG9mZnNldDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICggb3ZlckJvdHRvbSA+IDAgKSB7XG5cdFx0XHRcdG5ld092ZXJUb3AgPSBwb3NpdGlvbi50b3AgLSBkYXRhLmNvbGxpc2lvblBvc2l0aW9uLm1hcmdpblRvcCArIG15T2Zmc2V0ICsgYXRPZmZzZXQgK1xuXHRcdFx0XHRcdG9mZnNldCAtIG9mZnNldFRvcDtcblx0XHRcdFx0aWYgKCBuZXdPdmVyVG9wID4gMCB8fCBhYnMoIG5ld092ZXJUb3AgKSA8IG92ZXJCb3R0b20gKSB7XG5cdFx0XHRcdFx0cG9zaXRpb24udG9wICs9IG15T2Zmc2V0ICsgYXRPZmZzZXQgKyBvZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdGZsaXBmaXQ6IHtcblx0XHRsZWZ0OiBmdW5jdGlvbigpIHtcblx0XHRcdCQudWkucG9zaXRpb24uZmxpcC5sZWZ0LmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdCQudWkucG9zaXRpb24uZml0LmxlZnQuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH0sXG5cdFx0dG9wOiBmdW5jdGlvbigpIHtcblx0XHRcdCQudWkucG9zaXRpb24uZmxpcC50b3AuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdFx0JC51aS5wb3NpdGlvbi5maXQudG9wLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHR9XG5cdH1cbn07XG5cbn0gKSgpO1xuXG5yZXR1cm4gJC51aS5wb3NpdGlvbjtcblxufSApICk7XG4iLCI7LyohIHNob3dkb3duIHYgMS45LjAgLSAxMC0xMS0yMDE4ICovXHJcbihmdW5jdGlvbigpe1xyXG4vKipcbiAqIENyZWF0ZWQgYnkgVGl2aWUgb24gMTMtMDctMjAxNS5cbiAqL1xuXG5mdW5jdGlvbiBnZXREZWZhdWx0T3B0cyAoc2ltcGxlKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgb21pdEV4dHJhV0xJbkNvZGVCbG9ja3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ09taXQgdGhlIGRlZmF1bHQgZXh0cmEgd2hpdGVsaW5lIGFkZGVkIHRvIGNvZGUgYmxvY2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbm9IZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgZ2VuZXJhdGVkIGhlYWRlciBpZCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHByZWZpeEhlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdBZGQgYSBwcmVmaXggdG8gdGhlIGdlbmVyYXRlZCBoZWFkZXIgaWRzLiBQYXNzaW5nIGEgc3RyaW5nIHdpbGwgcHJlZml4IHRoYXQgc3RyaW5nIHRvIHRoZSBoZWFkZXIgaWQuIFNldHRpbmcgdG8gdHJ1ZSB3aWxsIGFkZCBhIGdlbmVyaWMgXFwnc2VjdGlvbi1cXCcgcHJlZml4JyxcbiAgICAgIHR5cGU6ICdzdHJpbmcnXG4gICAgfSxcbiAgICByYXdQcmVmaXhIZWFkZXJJZDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnU2V0dGluZyB0aGlzIG9wdGlvbiB0byB0cnVlIHdpbGwgcHJldmVudCBzaG93ZG93biBmcm9tIG1vZGlmeWluZyB0aGUgcHJlZml4LiBUaGlzIG1pZ2h0IHJlc3VsdCBpbiBtYWxmb3JtZWQgSURzIChpZiwgZm9yIGluc3RhbmNlLCB0aGUgXCIgY2hhciBpcyB1c2VkIGluIHRoZSBwcmVmaXgpJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZ2hDb21wYXRpYmxlSGVhZGVySWQ6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ0dlbmVyYXRlIGhlYWRlciBpZHMgY29tcGF0aWJsZSB3aXRoIGdpdGh1YiBzdHlsZSAoc3BhY2VzIGFyZSByZXBsYWNlZCB3aXRoIGRhc2hlcywgYSBidW5jaCBvZiBub24gYWxwaGFudW1lcmljIGNoYXJzIGFyZSByZW1vdmVkKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHJhd0hlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdSZW1vdmUgb25seSBzcGFjZXMsIFxcJyBhbmQgXCIgZnJvbSBnZW5lcmF0ZWQgaGVhZGVyIGlkcyAoaW5jbHVkaW5nIHByZWZpeGVzKSwgcmVwbGFjaW5nIHRoZW0gd2l0aCBkYXNoZXMgKC0pLiBXQVJOSU5HOiBUaGlzIG1pZ2h0IHJlc3VsdCBpbiBtYWxmb3JtZWQgaWRzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgaGVhZGVyTGV2ZWxTdGFydDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVGhlIGhlYWRlciBibG9ja3MgbGV2ZWwgc3RhcnQnLFxuICAgICAgdHlwZTogJ2ludGVnZXInXG4gICAgfSxcbiAgICBwYXJzZUltZ0RpbWVuc2lvbnM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1R1cm4gb24vb2ZmIGltYWdlIGRpbWVuc2lvbiBwYXJzaW5nJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc2ltcGxpZmllZEF1dG9MaW5rOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiBHRk0gYXV0b2xpbmsgc3R5bGUnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBleGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdFeGNsdWRlcyB0cmFpbGluZyBwdW5jdHVhdGlvbiBmcm9tIGxpbmtzIGdlbmVyYXRlZCB3aXRoIGF1dG9MaW5raW5nJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3Jlczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnUGFyc2UgbWlkd29yZCB1bmRlcnNjb3JlcyBhcyBsaXRlcmFsIHVuZGVyc2NvcmVzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgbGl0ZXJhbE1pZFdvcmRBc3Rlcmlza3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1BhcnNlIG1pZHdvcmQgYXN0ZXJpc2tzIGFzIGxpdGVyYWwgYXN0ZXJpc2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc3RyaWtldGhyb3VnaDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaWJlOiAnVHVybiBvbi9vZmYgc3RyaWtldGhyb3VnaCBzdXBwb3J0JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgdGFibGVzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiB0YWJsZXMgc3VwcG9ydCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHRhYmxlc0hlYWRlcklkOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpYmU6ICdBZGQgYW4gaWQgdG8gdGFibGUgaGVhZGVycycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoQ29kZUJsb2Nrczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICAgICAgZGVzY3JpYmU6ICdUdXJuIG9uL29mZiBHRk0gZmVuY2VkIGNvZGUgYmxvY2tzIHN1cHBvcnQnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICB0YXNrbGlzdHM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1R1cm4gb24vb2ZmIEdGTSB0YXNrbGlzdCBzdXBwb3J0JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgc21vb3RoTGl2ZVByZXZpZXc6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmliZTogJ1ByZXZlbnRzIHdlaXJkIGVmZmVjdHMgaW4gbGl2ZSBwcmV2aWV3cyBkdWUgdG8gaW5jb21wbGV0ZSBpbnB1dCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHNtYXJ0SW5kZW50YXRpb25GaXg6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1RyaWVzIHRvIHNtYXJ0bHkgZml4IGluZGVudGF0aW9uIGluIGVzNiBzdHJpbmdzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdEaXNhYmxlcyB0aGUgcmVxdWlyZW1lbnQgb2YgaW5kZW50aW5nIG5lc3RlZCBzdWJsaXN0cyBieSA0IHNwYWNlcycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHNpbXBsZUxpbmVCcmVha3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1BhcnNlcyBzaW1wbGUgbGluZSBicmVha3MgYXMgPGJyPiAoR0ZNIFN0eWxlKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHJlcXVpcmVTcGFjZUJlZm9yZUhlYWRpbmdUZXh0OiB7XG4gICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdNYWtlcyBhZGRpbmcgYSBzcGFjZSBiZXR3ZWVuIGAjYCBhbmQgdGhlIGhlYWRlciB0ZXh0IG1hbmRhdG9yeSAoR0ZNIFN0eWxlKScsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoTWVudGlvbnM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VuYWJsZXMgZ2l0aHViIEBtZW50aW9ucycsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIGdoTWVudGlvbnNMaW5rOiB7XG4gICAgICBkZWZhdWx0VmFsdWU6ICdodHRwczovL2dpdGh1Yi5jb20ve3V9JyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnQ2hhbmdlcyB0aGUgbGluayBnZW5lcmF0ZWQgYnkgQG1lbnRpb25zLiBPbmx5IGFwcGxpZXMgaWYgZ2hNZW50aW9ucyBvcHRpb24gaXMgZW5hYmxlZC4nLFxuICAgICAgdHlwZTogJ3N0cmluZydcbiAgICB9LFxuICAgIGVuY29kZUVtYWlsczoge1xuICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICAgICAgZGVzY3JpcHRpb246ICdFbmNvZGUgZS1tYWlsIGFkZHJlc3NlcyB0aHJvdWdoIHRoZSB1c2Ugb2YgQ2hhcmFjdGVyIEVudGl0aWVzLCB0cmFuc2Zvcm1pbmcgQVNDSUkgZS1tYWlsIGFkZHJlc3NlcyBpbnRvIGl0cyBlcXVpdmFsZW50IGRlY2ltYWwgZW50aXRpZXMnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBvcGVuTGlua3NJbk5ld1dpbmRvdzoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnT3BlbiBhbGwgbGlua3MgaW4gbmV3IHdpbmRvd3MnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBiYWNrc2xhc2hFc2NhcGVzSFRNTFRhZ3M6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1N1cHBvcnQgZm9yIEhUTUwgVGFnIGVzY2FwaW5nLiBleDogXFw8ZGl2PmZvb1xcPC9kaXY+JyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH0sXG4gICAgZW1vamk6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ0VuYWJsZSBlbW9qaSBzdXBwb3J0LiBFeDogYHRoaXMgaXMgYSA6c21pbGU6IGVtb2ppYCcsXG4gICAgICB0eXBlOiAnYm9vbGVhbidcbiAgICB9LFxuICAgIHVuZGVybGluZToge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW5hYmxlIHN1cHBvcnQgZm9yIHVuZGVybGluZS4gU3ludGF4IGlzIGRvdWJsZSBvciB0cmlwbGUgdW5kZXJzY29yZXM6IGBfX3VuZGVybGluZSB3b3JkX19gLiBXaXRoIHRoaXMgb3B0aW9uIGVuYWJsZWQsIHVuZGVyc2NvcmVzIG5vIGxvbmdlciBwYXJzZXMgaW50byBgPGVtPmAgYW5kIGA8c3Ryb25nPmAnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBjb21wbGV0ZUhUTUxEb2N1bWVudDoge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnT3V0cHV0cyBhIGNvbXBsZXRlIGh0bWwgZG9jdW1lbnQsIGluY2x1ZGluZyBgPGh0bWw+YCwgYDxoZWFkPmAgYW5kIGA8Ym9keT5gIHRhZ3MnLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBtZXRhZGF0YToge1xuICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnRW5hYmxlIHN1cHBvcnQgZm9yIGRvY3VtZW50IG1ldGFkYXRhIChkZWZpbmVkIGF0IHRoZSB0b3Agb2YgdGhlIGRvY3VtZW50IGJldHdlZW4gYMKrwqvCq2AgYW5kIGDCu8K7wrtgIG9yIGJldHdlZW4gYC0tLWAgYW5kIGAtLS1gKS4nLFxuICAgICAgdHlwZTogJ2Jvb2xlYW4nXG4gICAgfSxcbiAgICBzcGxpdEFkamFjZW50QmxvY2txdW90ZXM6IHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICBkZXNjcmlwdGlvbjogJ1NwbGl0IGFkamFjZW50IGJsb2NrcXVvdGUgYmxvY2tzJyxcbiAgICAgIHR5cGU6ICdib29sZWFuJ1xuICAgIH1cbiAgfTtcbiAgaWYgKHNpbXBsZSA9PT0gZmFsc2UpIHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShkZWZhdWx0T3B0aW9ucykpO1xuICB9XG4gIHZhciByZXQgPSB7fTtcbiAgZm9yICh2YXIgb3B0IGluIGRlZmF1bHRPcHRpb25zKSB7XG4gICAgaWYgKGRlZmF1bHRPcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpIHtcbiAgICAgIHJldFtvcHRdID0gZGVmYXVsdE9wdGlvbnNbb3B0XS5kZWZhdWx0VmFsdWU7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIGFsbE9wdGlvbnNPbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIG9wdGlvbnMgPSBnZXREZWZhdWx0T3B0cyh0cnVlKSxcbiAgICAgIHJldCA9IHt9O1xuICBmb3IgKHZhciBvcHQgaW4gb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KG9wdCkpIHtcbiAgICAgIHJldFtvcHRdID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxyXG4vKipcbiAqIENyZWF0ZWQgYnkgVGl2aWUgb24gMDYtMDEtMjAxNS5cbiAqL1xuXG4vLyBQcml2YXRlIHByb3BlcnRpZXNcbnZhciBzaG93ZG93biA9IHt9LFxuICAgIHBhcnNlcnMgPSB7fSxcbiAgICBleHRlbnNpb25zID0ge30sXG4gICAgZ2xvYmFsT3B0aW9ucyA9IGdldERlZmF1bHRPcHRzKHRydWUpLFxuICAgIHNldEZsYXZvciA9ICd2YW5pbGxhJyxcbiAgICBmbGF2b3IgPSB7XG4gICAgICBnaXRodWI6IHtcbiAgICAgICAgb21pdEV4dHJhV0xJbkNvZGVCbG9ja3M6ICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBzaW1wbGlmaWVkQXV0b0xpbms6ICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGV4Y2x1ZGVUcmFpbGluZ1B1bmN0dWF0aW9uRnJvbVVSTHM6ICAgdHJ1ZSxcbiAgICAgICAgbGl0ZXJhbE1pZFdvcmRVbmRlcnNjb3JlczogICAgICAgICAgICB0cnVlLFxuICAgICAgICBzdHJpa2V0aHJvdWdoOiAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhYmxlczogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgdGFibGVzSGVhZGVySWQ6ICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBnaENvZGVCbG9ja3M6ICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhc2tsaXN0czogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzOiB0cnVlLFxuICAgICAgICBzaW1wbGVMaW5lQnJlYWtzOiAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHJlcXVpcmVTcGFjZUJlZm9yZUhlYWRpbmdUZXh0OiAgICAgICAgdHJ1ZSxcbiAgICAgICAgZ2hDb21wYXRpYmxlSGVhZGVySWQ6ICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBnaE1lbnRpb25zOiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGJhY2tzbGFzaEVzY2FwZXNIVE1MVGFnczogICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZW1vamk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBzcGxpdEFkamFjZW50QmxvY2txdW90ZXM6ICAgICAgICAgICAgIHRydWVcbiAgICAgIH0sXG4gICAgICBvcmlnaW5hbDoge1xuICAgICAgICBub0hlYWRlcklkOiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIGdoQ29kZUJsb2NrczogICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2VcbiAgICAgIH0sXG4gICAgICBnaG9zdDoge1xuICAgICAgICBvbWl0RXh0cmFXTEluQ29kZUJsb2NrczogICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHBhcnNlSW1nRGltZW5zaW9uczogICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc2ltcGxpZmllZEF1dG9MaW5rOiAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICBleGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzOiAgIHRydWUsXG4gICAgICAgIGxpdGVyYWxNaWRXb3JkVW5kZXJzY29yZXM6ICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc3RyaWtldGhyb3VnaDogICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YWJsZXM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHRhYmxlc0hlYWRlcklkOiAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgZ2hDb2RlQmxvY2tzOiAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICB0YXNrbGlzdHM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgIHNtb290aExpdmVQcmV2aWV3OiAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgc2ltcGxlTGluZUJyZWFrczogICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICByZXF1aXJlU3BhY2VCZWZvcmVIZWFkaW5nVGV4dDogICAgICAgIHRydWUsXG4gICAgICAgIGdoTWVudGlvbnM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgIGVuY29kZUVtYWlsczogICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgfSxcbiAgICAgIHZhbmlsbGE6IGdldERlZmF1bHRPcHRzKHRydWUpLFxuICAgICAgYWxsT246IGFsbE9wdGlvbnNPbigpXG4gICAgfTtcblxuLyoqXG4gKiBoZWxwZXIgbmFtZXNwYWNlXG4gKiBAdHlwZSB7e319XG4gKi9cbnNob3dkb3duLmhlbHBlciA9IHt9O1xuXG4vKipcbiAqIFRPRE8gTEVHQUNZIFNVUFBPUlQgQ09ERVxuICogQHR5cGUge3t9fVxuICovXG5zaG93ZG93bi5leHRlbnNpb25zID0ge307XG5cbi8qKlxuICogU2V0IGEgZ2xvYmFsIG9wdGlvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHJldHVybnMge3Nob3dkb3dufVxuICovXG5zaG93ZG93bi5zZXRPcHRpb24gPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAndXNlIHN0cmljdCc7XG4gIGdsb2JhbE9wdGlvbnNba2V5XSA9IHZhbHVlO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogR2V0IGEgZ2xvYmFsIG9wdGlvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICogQHJldHVybnMgeyp9XG4gKi9cbnNob3dkb3duLmdldE9wdGlvbiA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gZ2xvYmFsT3B0aW9uc1trZXldO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGdsb2JhbCBvcHRpb25zXG4gKiBAc3RhdGljXG4gKiBAcmV0dXJucyB7e319XG4gKi9cbnNob3dkb3duLmdldE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIGdsb2JhbE9wdGlvbnM7XG59O1xuXG4vKipcbiAqIFJlc2V0IGdsb2JhbCBvcHRpb25zIHRvIHRoZSBkZWZhdWx0IHZhbHVlc1xuICogQHN0YXRpY1xuICovXG5zaG93ZG93bi5yZXNldE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgZ2xvYmFsT3B0aW9ucyA9IGdldERlZmF1bHRPcHRzKHRydWUpO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGZsYXZvciBzaG93ZG93biBzaG91bGQgdXNlIGFzIGRlZmF1bHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKi9cbnNob3dkb3duLnNldEZsYXZvciA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgaWYgKCFmbGF2b3IuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICB0aHJvdyBFcnJvcihuYW1lICsgJyBmbGF2b3Igd2FzIG5vdCBmb3VuZCcpO1xuICB9XG4gIHNob3dkb3duLnJlc2V0T3B0aW9ucygpO1xuICB2YXIgcHJlc2V0ID0gZmxhdm9yW25hbWVdO1xuICBzZXRGbGF2b3IgPSBuYW1lO1xuICBmb3IgKHZhciBvcHRpb24gaW4gcHJlc2V0KSB7XG4gICAgaWYgKHByZXNldC5oYXNPd25Qcm9wZXJ0eShvcHRpb24pKSB7XG4gICAgICBnbG9iYWxPcHRpb25zW29wdGlvbl0gPSBwcmVzZXRbb3B0aW9uXTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogR2V0IHRoZSBjdXJyZW50bHkgc2V0IGZsYXZvclxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uZ2V0Rmxhdm9yID0gZnVuY3Rpb24gKCkge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBzZXRGbGF2b3I7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgb3B0aW9ucyBvZiBhIHNwZWNpZmllZCBmbGF2b3IuIFJldHVybnMgdW5kZWZpbmVkIGlmIHRoZSBmbGF2b3Igd2FzIG5vdCBmb3VuZFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgZmxhdm9yXG4gKiBAcmV0dXJucyB7e318dW5kZWZpbmVkfVxuICovXG5zaG93ZG93bi5nZXRGbGF2b3JPcHRpb25zID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBpZiAoZmxhdm9yLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgcmV0dXJuIGZsYXZvcltuYW1lXTtcbiAgfVxufTtcblxuLyoqXG4gKiBHZXQgdGhlIGRlZmF1bHQgb3B0aW9uc1xuICogQHN0YXRpY1xuICogQHBhcmFtIHtib29sZWFufSBbc2ltcGxlPXRydWVdXG4gKiBAcmV0dXJucyB7e319XG4gKi9cbnNob3dkb3duLmdldERlZmF1bHRPcHRpb25zID0gZnVuY3Rpb24gKHNpbXBsZSkge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBnZXREZWZhdWx0T3B0cyhzaW1wbGUpO1xufTtcblxuLyoqXG4gKiBHZXQgb3Igc2V0IGEgc3ViUGFyc2VyXG4gKlxuICogc3ViUGFyc2VyKG5hbWUpICAgICAgIC0gR2V0IGEgcmVnaXN0ZXJlZCBzdWJQYXJzZXJcbiAqIHN1YlBhcnNlcihuYW1lLCBmdW5jKSAtIFJlZ2lzdGVyIGEgc3ViUGFyc2VyXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gW2Z1bmNdXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyID0gZnVuY3Rpb24gKG5hbWUsIGZ1bmMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKG5hbWUpKSB7XG4gICAgaWYgKHR5cGVvZiBmdW5jICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcGFyc2Vyc1tuYW1lXSA9IGZ1bmM7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChwYXJzZXJzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZXJzW25hbWVdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ1N1YlBhcnNlciBuYW1lZCAnICsgbmFtZSArICcgbm90IHJlZ2lzdGVyZWQhJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEdldHMgb3IgcmVnaXN0ZXJzIGFuIGV4dGVuc2lvblxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7b2JqZWN0fGZ1bmN0aW9uPX0gZXh0XG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuc2hvd2Rvd24uZXh0ZW5zaW9uID0gZnVuY3Rpb24gKG5hbWUsIGV4dCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcobmFtZSkpIHtcbiAgICB0aHJvdyBFcnJvcignRXh0ZW5zaW9uIFxcJ25hbWVcXCcgbXVzdCBiZSBhIHN0cmluZycpO1xuICB9XG5cbiAgbmFtZSA9IHNob3dkb3duLmhlbHBlci5zdGRFeHROYW1lKG5hbWUpO1xuXG4gIC8vIEdldHRlclxuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dCkpIHtcbiAgICBpZiAoIWV4dGVuc2lvbnMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdFeHRlbnNpb24gbmFtZWQgJyArIG5hbWUgKyAnIGlzIG5vdCByZWdpc3RlcmVkIScpO1xuICAgIH1cbiAgICByZXR1cm4gZXh0ZW5zaW9uc1tuYW1lXTtcblxuICAgIC8vIFNldHRlclxuICB9IGVsc2Uge1xuICAgIC8vIEV4cGFuZCBleHRlbnNpb24gaWYgaXQncyB3cmFwcGVkIGluIGEgZnVuY3Rpb25cbiAgICBpZiAodHlwZW9mIGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZXh0ID0gZXh0KCk7XG4gICAgfVxuXG4gICAgLy8gRW5zdXJlIGV4dGVuc2lvbiBpcyBhbiBhcnJheVxuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0KSkge1xuICAgICAgZXh0ID0gW2V4dF07XG4gICAgfVxuXG4gICAgdmFyIHZhbGlkRXh0ZW5zaW9uID0gdmFsaWRhdGUoZXh0LCBuYW1lKTtcblxuICAgIGlmICh2YWxpZEV4dGVuc2lvbi52YWxpZCkge1xuICAgICAgZXh0ZW5zaW9uc1tuYW1lXSA9IGV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IodmFsaWRFeHRlbnNpb24uZXJyb3IpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBHZXRzIGFsbCBleHRlbnNpb25zIHJlZ2lzdGVyZWRcbiAqIEByZXR1cm5zIHt7fX1cbiAqL1xuc2hvd2Rvd24uZ2V0QWxsRXh0ZW5zaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gZXh0ZW5zaW9ucztcbn07XG5cbi8qKlxuICogUmVtb3ZlIGFuIGV4dGVuc2lvblxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqL1xuc2hvd2Rvd24ucmVtb3ZlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICBkZWxldGUgZXh0ZW5zaW9uc1tuYW1lXTtcbn07XG5cbi8qKlxuICogUmVtb3ZlcyBhbGwgZXh0ZW5zaW9uc1xuICovXG5zaG93ZG93bi5yZXNldEV4dGVuc2lvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgZXh0ZW5zaW9ucyA9IHt9O1xufTtcblxuLyoqXG4gKiBWYWxpZGF0ZSBleHRlbnNpb25cbiAqIEBwYXJhbSB7YXJyYXl9IGV4dGVuc2lvblxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEByZXR1cm5zIHt7dmFsaWQ6IGJvb2xlYW4sIGVycm9yOiBzdHJpbmd9fVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZSAoZXh0ZW5zaW9uLCBuYW1lKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgZXJyTXNnID0gKG5hbWUpID8gJ0Vycm9yIGluICcgKyBuYW1lICsgJyBleHRlbnNpb24tPicgOiAnRXJyb3IgaW4gdW5uYW1lZCBleHRlbnNpb24nLFxuICAgICAgcmV0ID0ge1xuICAgICAgICB2YWxpZDogdHJ1ZSxcbiAgICAgICAgZXJyb3I6ICcnXG4gICAgICB9O1xuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0ZW5zaW9uKSkge1xuICAgIGV4dGVuc2lvbiA9IFtleHRlbnNpb25dO1xuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBleHRlbnNpb24ubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYmFzZU1zZyA9IGVyck1zZyArICcgc3ViLWV4dGVuc2lvbiAnICsgaSArICc6ICcsXG4gICAgICAgIGV4dCA9IGV4dGVuc2lvbltpXTtcbiAgICBpZiAodHlwZW9mIGV4dCAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdtdXN0IGJlIGFuIG9iamVjdCwgYnV0ICcgKyB0eXBlb2YgZXh0ICsgJyBnaXZlbic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKGV4dC50eXBlKSkge1xuICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ3Byb3BlcnR5IFwidHlwZVwiIG11c3QgYmUgYSBzdHJpbmcsIGJ1dCAnICsgdHlwZW9mIGV4dC50eXBlICsgJyBnaXZlbic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIHZhciB0eXBlID0gZXh0LnR5cGUgPSBleHQudHlwZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gbm9ybWFsaXplIGV4dGVuc2lvbiB0eXBlXG4gICAgaWYgKHR5cGUgPT09ICdsYW5ndWFnZScpIHtcbiAgICAgIHR5cGUgPSBleHQudHlwZSA9ICdsYW5nJztcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gJ2h0bWwnKSB7XG4gICAgICB0eXBlID0gZXh0LnR5cGUgPSAnb3V0cHV0JztcbiAgICB9XG5cbiAgICBpZiAodHlwZSAhPT0gJ2xhbmcnICYmIHR5cGUgIT09ICdvdXRwdXQnICYmIHR5cGUgIT09ICdsaXN0ZW5lcicpIHtcbiAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICd0eXBlICcgKyB0eXBlICsgJyBpcyBub3QgcmVjb2duaXplZC4gVmFsaWQgdmFsdWVzOiBcImxhbmcvbGFuZ3VhZ2VcIiwgXCJvdXRwdXQvaHRtbFwiIG9yIFwibGlzdGVuZXJcIic7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnbGlzdGVuZXInKSB7XG4gICAgICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dC5saXN0ZW5lcnMpKSB7XG4gICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJy4gRXh0ZW5zaW9ucyBvZiB0eXBlIFwibGlzdGVuZXJcIiBtdXN0IGhhdmUgYSBwcm9wZXJ0eSBjYWxsZWQgXCJsaXN0ZW5lcnNcIic7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZXh0LmZpbHRlcikgJiYgc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGV4dC5yZWdleCkpIHtcbiAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyB0eXBlICsgJyBleHRlbnNpb25zIG11c3QgZGVmaW5lIGVpdGhlciBhIFwicmVnZXhcIiBwcm9wZXJ0eSBvciBhIFwiZmlsdGVyXCIgbWV0aG9kJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZXh0Lmxpc3RlbmVycykge1xuICAgICAgaWYgKHR5cGVvZiBleHQubGlzdGVuZXJzICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdcImxpc3RlbmVyc1wiIHByb3BlcnR5IG11c3QgYmUgYW4gb2JqZWN0IGJ1dCAnICsgdHlwZW9mIGV4dC5saXN0ZW5lcnMgKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGxuIGluIGV4dC5saXN0ZW5lcnMpIHtcbiAgICAgICAgaWYgKGV4dC5saXN0ZW5lcnMuaGFzT3duUHJvcGVydHkobG4pKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBleHQubGlzdGVuZXJzW2xuXSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ1wibGlzdGVuZXJzXCIgcHJvcGVydHkgbXVzdCBiZSBhbiBoYXNoIG9mIFtldmVudCBuYW1lXTogW2NhbGxiYWNrXS4gbGlzdGVuZXJzLicgKyBsbiArXG4gICAgICAgICAgICAgICcgbXVzdCBiZSBhIGZ1bmN0aW9uIGJ1dCAnICsgdHlwZW9mIGV4dC5saXN0ZW5lcnNbbG5dICsgJyBnaXZlbic7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChleHQuZmlsdGVyKSB7XG4gICAgICBpZiAodHlwZW9mIGV4dC5maWx0ZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHJldC5lcnJvciA9IGJhc2VNc2cgKyAnXCJmaWx0ZXJcIiBtdXN0IGJlIGEgZnVuY3Rpb24sIGJ1dCAnICsgdHlwZW9mIGV4dC5maWx0ZXIgKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGV4dC5yZWdleCkge1xuICAgICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1N0cmluZyhleHQucmVnZXgpKSB7XG4gICAgICAgIGV4dC5yZWdleCA9IG5ldyBSZWdFeHAoZXh0LnJlZ2V4LCAnZycpO1xuICAgICAgfVxuICAgICAgaWYgKCEoZXh0LnJlZ2V4IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICByZXQudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgcmV0LmVycm9yID0gYmFzZU1zZyArICdcInJlZ2V4XCIgcHJvcGVydHkgbXVzdCBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgYSBSZWdFeHAgb2JqZWN0LCBidXQgJyArIHR5cGVvZiBleHQucmVnZXggKyAnIGdpdmVuJztcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH1cbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoZXh0LnJlcGxhY2UpKSB7XG4gICAgICAgIHJldC52YWxpZCA9IGZhbHNlO1xuICAgICAgICByZXQuZXJyb3IgPSBiYXNlTXNnICsgJ1wicmVnZXhcIiBleHRlbnNpb25zIG11c3QgaW1wbGVtZW50IGEgcmVwbGFjZSBzdHJpbmcgb3IgZnVuY3Rpb24nO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGV4dGVuc2lvblxuICogQHBhcmFtIHtvYmplY3R9IGV4dFxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnNob3dkb3duLnZhbGlkYXRlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKGV4dCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHZhbGlkYXRlRXh0ZW5zaW9uID0gdmFsaWRhdGUoZXh0LCBudWxsKTtcbiAgaWYgKCF2YWxpZGF0ZUV4dGVuc2lvbi52YWxpZCkge1xuICAgIGNvbnNvbGUud2Fybih2YWxpZGF0ZUV4dGVuc2lvbi5lcnJvcik7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufTtcblxyXG4vKipcbiAqIHNob3dkb3duanMgaGVscGVyIGZ1bmN0aW9uc1xuICovXG5cbmlmICghc2hvd2Rvd24uaGFzT3duUHJvcGVydHkoJ2hlbHBlcicpKSB7XG4gIHNob3dkb3duLmhlbHBlciA9IHt9O1xufVxuXG4vKipcbiAqIENoZWNrIGlmIHZhciBpcyBzdHJpbmdcbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7c3RyaW5nfSBhXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nID0gZnVuY3Rpb24gKGEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gKHR5cGVvZiBhID09PSAnc3RyaW5nJyB8fCBhIGluc3RhbmNlb2YgU3RyaW5nKTtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgdmFyIGlzIGEgZnVuY3Rpb25cbiAqIEBzdGF0aWNcbiAqIEBwYXJhbSB7Kn0gYVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnNob3dkb3duLmhlbHBlci5pc0Z1bmN0aW9uID0gZnVuY3Rpb24gKGEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB2YXIgZ2V0VHlwZSA9IHt9O1xuICByZXR1cm4gYSAmJiBnZXRUeXBlLnRvU3RyaW5nLmNhbGwoYSkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59O1xuXG4vKipcbiAqIGlzQXJyYXkgaGVscGVyIGZ1bmN0aW9uXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0geyp9IGFcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5zaG93ZG93bi5oZWxwZXIuaXNBcnJheSA9IGZ1bmN0aW9uIChhKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYSk7XG59O1xuXG4vKipcbiAqIENoZWNrIGlmIHZhbHVlIGlzIHVuZGVmaW5lZFxuICogQHN0YXRpY1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYCwgZWxzZSBgZmFsc2VgLlxuICovXG5zaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn07XG5cbi8qKlxuICogRm9yRWFjaCBoZWxwZXIgZnVuY3Rpb25cbiAqIEl0ZXJhdGVzIG92ZXIgQXJyYXlzIGFuZCBPYmplY3RzIChvd24gcHJvcGVydGllcyBvbmx5KVxuICogQHN0YXRpY1xuICogQHBhcmFtIHsqfSBvYmpcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIEFjY2VwdHMgMyBwYXJhbXM6IDEuIHZhbHVlLCAyLiBrZXksIDMuIHRoZSBvcmlnaW5hbCBhcnJheS9vYmplY3RcbiAqL1xuc2hvd2Rvd24uaGVscGVyLmZvckVhY2ggPSBmdW5jdGlvbiAob2JqLCBjYWxsYmFjaykge1xuICAndXNlIHN0cmljdCc7XG4gIC8vIGNoZWNrIGlmIG9iaiBpcyBkZWZpbmVkXG4gIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQob2JqKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignb2JqIHBhcmFtIGlzIHJlcXVpcmVkJyk7XG4gIH1cblxuICBpZiAoc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGNhbGxiYWNrKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2FsbGJhY2sgcGFyYW0gaXMgcmVxdWlyZWQnKTtcbiAgfVxuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjYWxsYmFjayBwYXJhbSBtdXN0IGJlIGEgZnVuY3Rpb24vY2xvc3VyZScpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvYmouZm9yRWFjaCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIG9iai5mb3JFYWNoKGNhbGxiYWNrKTtcbiAgfSBlbHNlIGlmIChzaG93ZG93bi5oZWxwZXIuaXNBcnJheShvYmopKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmoubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNhbGxiYWNrKG9ialtpXSwgaSwgb2JqKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZW9mIChvYmopID09PSAnb2JqZWN0Jykge1xuICAgIGZvciAodmFyIHByb3AgaW4gb2JqKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgIGNhbGxiYWNrKG9ialtwcm9wXSwgcHJvcCwgb2JqKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdvYmogZG9lcyBub3Qgc2VlbSB0byBiZSBhbiBhcnJheSBvciBhbiBpdGVyYWJsZSBvYmplY3QnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTdGFuZGFyZGlkaXplIGV4dGVuc2lvbiBuYW1lXG4gKiBAc3RhdGljXG4gKiBAcGFyYW0ge3N0cmluZ30gcyBleHRlbnNpb24gbmFtZVxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLnN0ZEV4dE5hbWUgPSBmdW5jdGlvbiAocykge1xuICAndXNlIHN0cmljdCc7XG4gIHJldHVybiBzLnJlcGxhY2UoL1tfPyorXFwvXFxcXC5eLV0vZywgJycpLnJlcGxhY2UoL1xccy9nLCAnJykudG9Mb3dlckNhc2UoKTtcbn07XG5cbmZ1bmN0aW9uIGVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayAod2hvbGVNYXRjaCwgbTEpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB2YXIgY2hhckNvZGVUb0VzY2FwZSA9IG0xLmNoYXJDb2RlQXQoMCk7XG4gIHJldHVybiAnwqhFJyArIGNoYXJDb2RlVG9Fc2NhcGUgKyAnRSc7XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgdXNlZCB0byBlc2NhcGUgY2hhcmFjdGVycyB3aGVuIHBhc3NpbmcgdGhyb3VnaCBTdHJpbmcucmVwbGFjZVxuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IHdob2xlTWF0Y2hcbiAqIEBwYXJhbSB7c3RyaW5nfSBtMVxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayA9IGVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjaztcblxuLyoqXG4gKiBFc2NhcGUgY2hhcmFjdGVycyBpbiBhIHN0cmluZ1xuICogQHN0YXRpY1xuICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjaGFyc1RvRXNjYXBlXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGFmdGVyQmFja3NsYXNoXG4gKiBAcmV0dXJucyB7WE1MfHN0cmluZ3x2b2lkfCp9XG4gKi9cbnNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzID0gZnVuY3Rpb24gKHRleHQsIGNoYXJzVG9Fc2NhcGUsIGFmdGVyQmFja3NsYXNoKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgLy8gRmlyc3Qgd2UgaGF2ZSB0byBlc2NhcGUgdGhlIGVzY2FwZSBjaGFyYWN0ZXJzIHNvIHRoYXRcbiAgLy8gd2UgY2FuIGJ1aWxkIGEgY2hhcmFjdGVyIGNsYXNzIG91dCBvZiB0aGVtXG4gIHZhciByZWdleFN0cmluZyA9ICcoWycgKyBjaGFyc1RvRXNjYXBlLnJlcGxhY2UoLyhbXFxbXFxdXFxcXF0pL2csICdcXFxcJDEnKSArICddKSc7XG5cbiAgaWYgKGFmdGVyQmFja3NsYXNoKSB7XG4gICAgcmVnZXhTdHJpbmcgPSAnXFxcXFxcXFwnICsgcmVnZXhTdHJpbmc7XG4gIH1cblxuICB2YXIgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4U3RyaW5nLCAnZycpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlZ2V4LCBlc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gIHJldHVybiB0ZXh0O1xufTtcblxuLyoqXG4gKiBVbmVzY2FwZSBIVE1MIGVudGl0aWVzXG4gKiBAcGFyYW0gdHh0XG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5zaG93ZG93bi5oZWxwZXIudW5lc2NhcGVIVE1MRW50aXRpZXMgPSBmdW5jdGlvbiAodHh0KSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICByZXR1cm4gdHh0XG4gICAgLnJlcGxhY2UoLyZxdW90Oy9nLCAnXCInKVxuICAgIC5yZXBsYWNlKC8mbHQ7L2csICc8JylcbiAgICAucmVwbGFjZSgvJmd0Oy9nLCAnPicpXG4gICAgLnJlcGxhY2UoLyZhbXA7L2csICcmJyk7XG59O1xuXG52YXIgcmd4RmluZE1hdGNoUG9zID0gZnVuY3Rpb24gKHN0ciwgbGVmdCwgcmlnaHQsIGZsYWdzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdmFyIGYgPSBmbGFncyB8fCAnJyxcbiAgICAgIGcgPSBmLmluZGV4T2YoJ2cnKSA+IC0xLFxuICAgICAgeCA9IG5ldyBSZWdFeHAobGVmdCArICd8JyArIHJpZ2h0LCAnZycgKyBmLnJlcGxhY2UoL2cvZywgJycpKSxcbiAgICAgIGwgPSBuZXcgUmVnRXhwKGxlZnQsIGYucmVwbGFjZSgvZy9nLCAnJykpLFxuICAgICAgcG9zID0gW10sXG4gICAgICB0LCBzLCBtLCBzdGFydCwgZW5kO1xuXG4gIGRvIHtcbiAgICB0ID0gMDtcbiAgICB3aGlsZSAoKG0gPSB4LmV4ZWMoc3RyKSkpIHtcbiAgICAgIGlmIChsLnRlc3QobVswXSkpIHtcbiAgICAgICAgaWYgKCEodCsrKSkge1xuICAgICAgICAgIHMgPSB4Lmxhc3RJbmRleDtcbiAgICAgICAgICBzdGFydCA9IHMgLSBtWzBdLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0KSB7XG4gICAgICAgIGlmICghLS10KSB7XG4gICAgICAgICAgZW5kID0gbS5pbmRleCArIG1bMF0ubGVuZ3RoO1xuICAgICAgICAgIHZhciBvYmogPSB7XG4gICAgICAgICAgICBsZWZ0OiB7c3RhcnQ6IHN0YXJ0LCBlbmQ6IHN9LFxuICAgICAgICAgICAgbWF0Y2g6IHtzdGFydDogcywgZW5kOiBtLmluZGV4fSxcbiAgICAgICAgICAgIHJpZ2h0OiB7c3RhcnQ6IG0uaW5kZXgsIGVuZDogZW5kfSxcbiAgICAgICAgICAgIHdob2xlTWF0Y2g6IHtzdGFydDogc3RhcnQsIGVuZDogZW5kfVxuICAgICAgICAgIH07XG4gICAgICAgICAgcG9zLnB1c2gob2JqKTtcbiAgICAgICAgICBpZiAoIWcpIHtcbiAgICAgICAgICAgIHJldHVybiBwb3M7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IHdoaWxlICh0ICYmICh4Lmxhc3RJbmRleCA9IHMpKTtcblxuICByZXR1cm4gcG9zO1xufTtcblxuLyoqXG4gKiBtYXRjaFJlY3Vyc2l2ZVJlZ0V4cFxuICpcbiAqIChjKSAyMDA3IFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICogTUlUIExpY2Vuc2VcbiAqXG4gKiBBY2NlcHRzIGEgc3RyaW5nIHRvIHNlYXJjaCwgYSBsZWZ0IGFuZCByaWdodCBmb3JtYXQgZGVsaW1pdGVyXG4gKiBhcyByZWdleCBwYXR0ZXJucywgYW5kIG9wdGlvbmFsIHJlZ2V4IGZsYWdzLiBSZXR1cm5zIGFuIGFycmF5XG4gKiBvZiBtYXRjaGVzLCBhbGxvd2luZyBuZXN0ZWQgaW5zdGFuY2VzIG9mIGxlZnQvcmlnaHQgZGVsaW1pdGVycy5cbiAqIFVzZSB0aGUgXCJnXCIgZmxhZyB0byByZXR1cm4gYWxsIG1hdGNoZXMsIG90aGVyd2lzZSBvbmx5IHRoZVxuICogZmlyc3QgaXMgcmV0dXJuZWQuIEJlIGNhcmVmdWwgdG8gZW5zdXJlIHRoYXQgdGhlIGxlZnQgYW5kXG4gKiByaWdodCBmb3JtYXQgZGVsaW1pdGVycyBwcm9kdWNlIG11dHVhbGx5IGV4Y2x1c2l2ZSBtYXRjaGVzLlxuICogQmFja3JlZmVyZW5jZXMgYXJlIG5vdCBzdXBwb3J0ZWQgd2l0aGluIHRoZSByaWdodCBkZWxpbWl0ZXJcbiAqIGR1ZSB0byBob3cgaXQgaXMgaW50ZXJuYWxseSBjb21iaW5lZCB3aXRoIHRoZSBsZWZ0IGRlbGltaXRlci5cbiAqIFdoZW4gbWF0Y2hpbmcgc3RyaW5ncyB3aG9zZSBmb3JtYXQgZGVsaW1pdGVycyBhcmUgdW5iYWxhbmNlZFxuICogdG8gdGhlIGxlZnQgb3IgcmlnaHQsIHRoZSBvdXRwdXQgaXMgaW50ZW50aW9uYWxseSBhcyBhXG4gKiBjb252ZW50aW9uYWwgcmVnZXggbGlicmFyeSB3aXRoIHJlY3Vyc2lvbiBzdXBwb3J0IHdvdWxkXG4gKiBwcm9kdWNlLCBlLmcuIFwiPDx4PlwiIGFuZCBcIjx4Pj5cIiBib3RoIHByb2R1Y2UgW1wieFwiXSB3aGVuIHVzaW5nXG4gKiBcIjxcIiBhbmQgXCI+XCIgYXMgdGhlIGRlbGltaXRlcnMgKGJvdGggc3RyaW5ncyBjb250YWluIGEgc2luZ2xlLFxuICogYmFsYW5jZWQgaW5zdGFuY2Ugb2YgXCI8eD5cIikuXG4gKlxuICogZXhhbXBsZXM6XG4gKiBtYXRjaFJlY3Vyc2l2ZVJlZ0V4cChcInRlc3RcIiwgXCJcXFxcKFwiLCBcIlxcXFwpXCIpXG4gKiByZXR1cm5zOiBbXVxuICogbWF0Y2hSZWN1cnNpdmVSZWdFeHAoXCI8dDw8ZT4+PHM+PnQ8PlwiLCBcIjxcIiwgXCI+XCIsIFwiZ1wiKVxuICogcmV0dXJuczogW1widDw8ZT4+PHM+XCIsIFwiXCJdXG4gKiBtYXRjaFJlY3Vyc2l2ZVJlZ0V4cChcIjxkaXYgaWQ9XFxcInhcXFwiPnRlc3Q8L2Rpdj5cIiwgXCI8ZGl2XFxcXGJbXj5dKj5cIiwgXCI8L2Rpdj5cIiwgXCJnaVwiKVxuICogcmV0dXJuczogW1widGVzdFwiXVxuICovXG5zaG93ZG93bi5oZWxwZXIubWF0Y2hSZWN1cnNpdmVSZWdFeHAgPSBmdW5jdGlvbiAoc3RyLCBsZWZ0LCByaWdodCwgZmxhZ3MpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciBtYXRjaFBvcyA9IHJneEZpbmRNYXRjaFBvcyAoc3RyLCBsZWZ0LCByaWdodCwgZmxhZ3MpLFxuICAgICAgcmVzdWx0cyA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbWF0Y2hQb3MubGVuZ3RoOyArK2kpIHtcbiAgICByZXN1bHRzLnB1c2goW1xuICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLndob2xlTWF0Y2guc3RhcnQsIG1hdGNoUG9zW2ldLndob2xlTWF0Y2guZW5kKSxcbiAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS5tYXRjaC5zdGFydCwgbWF0Y2hQb3NbaV0ubWF0Y2guZW5kKSxcbiAgICAgIHN0ci5zbGljZShtYXRjaFBvc1tpXS5sZWZ0LnN0YXJ0LCBtYXRjaFBvc1tpXS5sZWZ0LmVuZCksXG4gICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ucmlnaHQuc3RhcnQsIG1hdGNoUG9zW2ldLnJpZ2h0LmVuZClcbiAgICBdKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0cztcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAqIEBwYXJhbSB7c3RyaW5nfGZ1bmN0aW9ufSByZXBsYWNlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IGxlZnRcbiAqIEBwYXJhbSB7c3RyaW5nfSByaWdodFxuICogQHBhcmFtIHtzdHJpbmd9IGZsYWdzXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5zaG93ZG93bi5oZWxwZXIucmVwbGFjZVJlY3Vyc2l2ZVJlZ0V4cCA9IGZ1bmN0aW9uIChzdHIsIHJlcGxhY2VtZW50LCBsZWZ0LCByaWdodCwgZmxhZ3MpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzRnVuY3Rpb24ocmVwbGFjZW1lbnQpKSB7XG4gICAgdmFyIHJlcFN0ciA9IHJlcGxhY2VtZW50O1xuICAgIHJlcGxhY2VtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHJlcFN0cjtcbiAgICB9O1xuICB9XG5cbiAgdmFyIG1hdGNoUG9zID0gcmd4RmluZE1hdGNoUG9zKHN0ciwgbGVmdCwgcmlnaHQsIGZsYWdzKSxcbiAgICAgIGZpbmFsU3RyID0gc3RyLFxuICAgICAgbG5nID0gbWF0Y2hQb3MubGVuZ3RoO1xuXG4gIGlmIChsbmcgPiAwKSB7XG4gICAgdmFyIGJpdHMgPSBbXTtcbiAgICBpZiAobWF0Y2hQb3NbMF0ud2hvbGVNYXRjaC5zdGFydCAhPT0gMCkge1xuICAgICAgYml0cy5wdXNoKHN0ci5zbGljZSgwLCBtYXRjaFBvc1swXS53aG9sZU1hdGNoLnN0YXJ0KSk7XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG5nOyArK2kpIHtcbiAgICAgIGJpdHMucHVzaChcbiAgICAgICAgcmVwbGFjZW1lbnQoXG4gICAgICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLndob2xlTWF0Y2guc3RhcnQsIG1hdGNoUG9zW2ldLndob2xlTWF0Y2guZW5kKSxcbiAgICAgICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ubWF0Y2guc3RhcnQsIG1hdGNoUG9zW2ldLm1hdGNoLmVuZCksXG4gICAgICAgICAgc3RyLnNsaWNlKG1hdGNoUG9zW2ldLmxlZnQuc3RhcnQsIG1hdGNoUG9zW2ldLmxlZnQuZW5kKSxcbiAgICAgICAgICBzdHIuc2xpY2UobWF0Y2hQb3NbaV0ucmlnaHQuc3RhcnQsIG1hdGNoUG9zW2ldLnJpZ2h0LmVuZClcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICAgIGlmIChpIDwgbG5nIC0gMSkge1xuICAgICAgICBiaXRzLnB1c2goc3RyLnNsaWNlKG1hdGNoUG9zW2ldLndob2xlTWF0Y2guZW5kLCBtYXRjaFBvc1tpICsgMV0ud2hvbGVNYXRjaC5zdGFydCkpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAobWF0Y2hQb3NbbG5nIC0gMV0ud2hvbGVNYXRjaC5lbmQgPCBzdHIubGVuZ3RoKSB7XG4gICAgICBiaXRzLnB1c2goc3RyLnNsaWNlKG1hdGNoUG9zW2xuZyAtIDFdLndob2xlTWF0Y2guZW5kKSk7XG4gICAgfVxuICAgIGZpbmFsU3RyID0gYml0cy5qb2luKCcnKTtcbiAgfVxuICByZXR1cm4gZmluYWxTdHI7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IHdpdGhpbiB0aGUgcGFzc2VkIFN0cmluZyBvYmplY3Qgb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlIHNwZWNpZmllZCByZWdleCxcbiAqIHN0YXJ0aW5nIHRoZSBzZWFyY2ggYXQgZnJvbUluZGV4LiBSZXR1cm5zIC0xIGlmIHRoZSB2YWx1ZSBpcyBub3QgZm91bmQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0ciBzdHJpbmcgdG8gc2VhcmNoXG4gKiBAcGFyYW0ge1JlZ0V4cH0gcmVnZXggUmVndWxhciBleHByZXNzaW9uIHRvIHNlYXJjaFxuICogQHBhcmFtIHtpbnR9IFtmcm9tSW5kZXggPSAwXSBJbmRleCB0byBzdGFydCB0aGUgc2VhcmNoXG4gKiBAcmV0dXJucyB7TnVtYmVyfVxuICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFcnJvclxuICovXG5zaG93ZG93bi5oZWxwZXIucmVnZXhJbmRleE9mID0gZnVuY3Rpb24gKHN0ciwgcmVnZXgsIGZyb21JbmRleCkge1xuICAndXNlIHN0cmljdCc7XG4gIGlmICghc2hvd2Rvd24uaGVscGVyLmlzU3RyaW5nKHN0cikpIHtcbiAgICB0aHJvdyAnSW52YWxpZEFyZ3VtZW50RXJyb3I6IGZpcnN0IHBhcmFtZXRlciBvZiBzaG93ZG93bi5oZWxwZXIucmVnZXhJbmRleE9mIGZ1bmN0aW9uIG11c3QgYmUgYSBzdHJpbmcnO1xuICB9XG4gIGlmIChyZWdleCBpbnN0YW5jZW9mIFJlZ0V4cCA9PT0gZmFsc2UpIHtcbiAgICB0aHJvdyAnSW52YWxpZEFyZ3VtZW50RXJyb3I6IHNlY29uZCBwYXJhbWV0ZXIgb2Ygc2hvd2Rvd24uaGVscGVyLnJlZ2V4SW5kZXhPZiBmdW5jdGlvbiBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIFJlZ0V4cCc7XG4gIH1cbiAgdmFyIGluZGV4T2YgPSBzdHIuc3Vic3RyaW5nKGZyb21JbmRleCB8fCAwKS5zZWFyY2gocmVnZXgpO1xuICByZXR1cm4gKGluZGV4T2YgPj0gMCkgPyAoaW5kZXhPZiArIChmcm9tSW5kZXggfHwgMCkpIDogaW5kZXhPZjtcbn07XG5cbi8qKlxuICogU3BsaXRzIHRoZSBwYXNzZWQgc3RyaW5nIG9iamVjdCBhdCB0aGUgZGVmaW5lZCBpbmRleCwgYW5kIHJldHVybnMgYW4gYXJyYXkgY29tcG9zZWQgb2YgdGhlIHR3byBzdWJzdHJpbmdzXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIHN0cmluZyB0byBzcGxpdFxuICogQHBhcmFtIHtpbnR9IGluZGV4IGluZGV4IHRvIHNwbGl0IHN0cmluZyBhdFxuICogQHJldHVybnMge1tzdHJpbmcsc3RyaW5nXX1cbiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXJyb3JcbiAqL1xuc2hvd2Rvd24uaGVscGVyLnNwbGl0QXRJbmRleCA9IGZ1bmN0aW9uIChzdHIsIGluZGV4KSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcoc3RyKSkge1xuICAgIHRocm93ICdJbnZhbGlkQXJndW1lbnRFcnJvcjogZmlyc3QgcGFyYW1ldGVyIG9mIHNob3dkb3duLmhlbHBlci5yZWdleEluZGV4T2YgZnVuY3Rpb24gbXVzdCBiZSBhIHN0cmluZyc7XG4gIH1cbiAgcmV0dXJuIFtzdHIuc3Vic3RyaW5nKDAsIGluZGV4KSwgc3RyLnN1YnN0cmluZyhpbmRleCldO1xufTtcblxuLyoqXG4gKiBPYmZ1c2NhdGUgYW4gZS1tYWlsIGFkZHJlc3MgdGhyb3VnaCB0aGUgdXNlIG9mIENoYXJhY3RlciBFbnRpdGllcyxcbiAqIHRyYW5zZm9ybWluZyBBU0NJSSBjaGFyYWN0ZXJzIGludG8gdGhlaXIgZXF1aXZhbGVudCBkZWNpbWFsIG9yIGhleCBlbnRpdGllcy5cbiAqXG4gKiBTaW5jZSBpdCBoYXMgYSByYW5kb20gY29tcG9uZW50LCBzdWJzZXF1ZW50IGNhbGxzIHRvIHRoaXMgZnVuY3Rpb24gcHJvZHVjZSBkaWZmZXJlbnQgcmVzdWx0c1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtYWlsXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5zaG93ZG93bi5oZWxwZXIuZW5jb2RlRW1haWxBZGRyZXNzID0gZnVuY3Rpb24gKG1haWwpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB2YXIgZW5jb2RlID0gW1xuICAgIGZ1bmN0aW9uIChjaCkge1xuICAgICAgcmV0dXJuICcmIycgKyBjaC5jaGFyQ29kZUF0KDApICsgJzsnO1xuICAgIH0sXG4gICAgZnVuY3Rpb24gKGNoKSB7XG4gICAgICByZXR1cm4gJyYjeCcgKyBjaC5jaGFyQ29kZUF0KDApLnRvU3RyaW5nKDE2KSArICc7JztcbiAgICB9LFxuICAgIGZ1bmN0aW9uIChjaCkge1xuICAgICAgcmV0dXJuIGNoO1xuICAgIH1cbiAgXTtcblxuICBtYWlsID0gbWFpbC5yZXBsYWNlKC8uL2csIGZ1bmN0aW9uIChjaCkge1xuICAgIGlmIChjaCA9PT0gJ0AnKSB7XG4gICAgICAvLyB0aGlzICptdXN0KiBiZSBlbmNvZGVkLiBJIGluc2lzdC5cbiAgICAgIGNoID0gZW5jb2RlW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDIpXShjaCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciByID0gTWF0aC5yYW5kb20oKTtcbiAgICAgIC8vIHJvdWdobHkgMTAlIHJhdywgNDUlIGhleCwgNDUlIGRlY1xuICAgICAgY2ggPSAoXG4gICAgICAgIHIgPiAwLjkgPyBlbmNvZGVbMl0oY2gpIDogciA+IDAuNDUgPyBlbmNvZGVbMV0oY2gpIDogZW5jb2RlWzBdKGNoKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGNoO1xuICB9KTtcblxuICByZXR1cm4gbWFpbDtcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBzdHJcbiAqIEBwYXJhbSB0YXJnZXRMZW5ndGhcbiAqIEBwYXJhbSBwYWRTdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbnNob3dkb3duLmhlbHBlci5wYWRFbmQgPSBmdW5jdGlvbiBwYWRFbmQgKHN0ciwgdGFyZ2V0TGVuZ3RoLCBwYWRTdHJpbmcpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICAvKmpzaGludCBiaXR3aXNlOiBmYWxzZSovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzcGFjZS1pbmZpeC1vcHNcbiAgdGFyZ2V0TGVuZ3RoID0gdGFyZ2V0TGVuZ3RoPj4wOyAvL2Zsb29yIGlmIG51bWJlciBvciBjb252ZXJ0IG5vbi1udW1iZXIgdG8gMDtcbiAgLypqc2hpbnQgYml0d2lzZTogdHJ1ZSovXG4gIHBhZFN0cmluZyA9IFN0cmluZyhwYWRTdHJpbmcgfHwgJyAnKTtcbiAgaWYgKHN0ci5sZW5ndGggPiB0YXJnZXRMZW5ndGgpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cik7XG4gIH0gZWxzZSB7XG4gICAgdGFyZ2V0TGVuZ3RoID0gdGFyZ2V0TGVuZ3RoIC0gc3RyLmxlbmd0aDtcbiAgICBpZiAodGFyZ2V0TGVuZ3RoID4gcGFkU3RyaW5nLmxlbmd0aCkge1xuICAgICAgcGFkU3RyaW5nICs9IHBhZFN0cmluZy5yZXBlYXQodGFyZ2V0TGVuZ3RoIC8gcGFkU3RyaW5nLmxlbmd0aCk7IC8vYXBwZW5kIHRvIG9yaWdpbmFsIHRvIGVuc3VyZSB3ZSBhcmUgbG9uZ2VyIHRoYW4gbmVlZGVkXG4gICAgfVxuICAgIHJldHVybiBTdHJpbmcoc3RyKSArIHBhZFN0cmluZy5zbGljZSgwLHRhcmdldExlbmd0aCk7XG4gIH1cbn07XG5cbi8qKlxuICogUE9MWUZJTExTXG4gKi9cbi8vIHVzZSB0aGlzIGluc3RlYWQgb2YgYnVpbHRpbiBpcyB1bmRlZmluZWQgZm9yIElFOCBjb21wYXRpYmlsaXR5XG5pZiAodHlwZW9mKGNvbnNvbGUpID09PSAndW5kZWZpbmVkJykge1xuICBjb25zb2xlID0ge1xuICAgIHdhcm46IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgIGFsZXJ0KG1zZyk7XG4gICAgfSxcbiAgICBsb2c6IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICd1c2Ugc3RyaWN0JztcbiAgICAgIGFsZXJ0KG1zZyk7XG4gICAgfSxcbiAgICBlcnJvcjogZnVuY3Rpb24gKG1zZykge1xuICAgICAgJ3VzZSBzdHJpY3QnO1xuICAgICAgdGhyb3cgbXNnO1xuICAgIH1cbiAgfTtcbn1cblxuLyoqXG4gKiBDb21tb24gcmVnZXhlcy5cbiAqIFdlIGRlY2xhcmUgc29tZSBjb21tb24gcmVnZXhlcyB0byBpbXByb3ZlIHBlcmZvcm1hbmNlXG4gKi9cbnNob3dkb3duLmhlbHBlci5yZWdleGVzID0ge1xuICBhc3Rlcmlza0Rhc2hBbmRDb2xvbjogLyhbKl86fl0pL2dcbn07XG5cbi8qKlxuICogRU1PSklTIExJU1RcbiAqL1xuc2hvd2Rvd24uaGVscGVyLmVtb2ppcyA9IHtcbiAgJysxJzonXFx1ZDgzZFxcdWRjNGQnLFxuICAnLTEnOidcXHVkODNkXFx1ZGM0ZScsXG4gICcxMDAnOidcXHVkODNkXFx1ZGNhZicsXG4gICcxMjM0JzonXFx1ZDgzZFxcdWRkMjInLFxuICAnMXN0X3BsYWNlX21lZGFsJzonXFx1ZDgzZVxcdWRkNDcnLFxuICAnMm5kX3BsYWNlX21lZGFsJzonXFx1ZDgzZVxcdWRkNDgnLFxuICAnM3JkX3BsYWNlX21lZGFsJzonXFx1ZDgzZVxcdWRkNDknLFxuICAnOGJhbGwnOidcXHVkODNjXFx1ZGZiMScsXG4gICdhJzonXFx1ZDgzY1xcdWRkNzBcXHVmZTBmJyxcbiAgJ2FiJzonXFx1ZDgzY1xcdWRkOGUnLFxuICAnYWJjJzonXFx1ZDgzZFxcdWRkMjQnLFxuICAnYWJjZCc6J1xcdWQ4M2RcXHVkZDIxJyxcbiAgJ2FjY2VwdCc6J1xcdWQ4M2NcXHVkZTUxJyxcbiAgJ2FlcmlhbF90cmFtd2F5JzonXFx1ZDgzZFxcdWRlYTEnLFxuICAnYWlycGxhbmUnOidcXHUyNzA4XFx1ZmUwZicsXG4gICdhbGFybV9jbG9jayc6J1xcdTIzZjAnLFxuICAnYWxlbWJpYyc6J1xcdTI2OTdcXHVmZTBmJyxcbiAgJ2FsaWVuJzonXFx1ZDgzZFxcdWRjN2QnLFxuICAnYW1idWxhbmNlJzonXFx1ZDgzZFxcdWRlOTEnLFxuICAnYW1waG9yYSc6J1xcdWQ4M2NcXHVkZmZhJyxcbiAgJ2FuY2hvcic6J1xcdTI2OTNcXHVmZTBmJyxcbiAgJ2FuZ2VsJzonXFx1ZDgzZFxcdWRjN2MnLFxuICAnYW5nZXInOidcXHVkODNkXFx1ZGNhMicsXG4gICdhbmdyeSc6J1xcdWQ4M2RcXHVkZTIwJyxcbiAgJ2FuZ3Vpc2hlZCc6J1xcdWQ4M2RcXHVkZTI3JyxcbiAgJ2FudCc6J1xcdWQ4M2RcXHVkYzFjJyxcbiAgJ2FwcGxlJzonXFx1ZDgzY1xcdWRmNGUnLFxuICAnYXF1YXJpdXMnOidcXHUyNjUyXFx1ZmUwZicsXG4gICdhcmllcyc6J1xcdTI2NDhcXHVmZTBmJyxcbiAgJ2Fycm93X2JhY2t3YXJkJzonXFx1MjVjMFxcdWZlMGYnLFxuICAnYXJyb3dfZG91YmxlX2Rvd24nOidcXHUyM2VjJyxcbiAgJ2Fycm93X2RvdWJsZV91cCc6J1xcdTIzZWInLFxuICAnYXJyb3dfZG93bic6J1xcdTJiMDdcXHVmZTBmJyxcbiAgJ2Fycm93X2Rvd25fc21hbGwnOidcXHVkODNkXFx1ZGQzZCcsXG4gICdhcnJvd19mb3J3YXJkJzonXFx1MjViNlxcdWZlMGYnLFxuICAnYXJyb3dfaGVhZGluZ19kb3duJzonXFx1MjkzNVxcdWZlMGYnLFxuICAnYXJyb3dfaGVhZGluZ191cCc6J1xcdTI5MzRcXHVmZTBmJyxcbiAgJ2Fycm93X2xlZnQnOidcXHUyYjA1XFx1ZmUwZicsXG4gICdhcnJvd19sb3dlcl9sZWZ0JzonXFx1MjE5OVxcdWZlMGYnLFxuICAnYXJyb3dfbG93ZXJfcmlnaHQnOidcXHUyMTk4XFx1ZmUwZicsXG4gICdhcnJvd19yaWdodCc6J1xcdTI3YTFcXHVmZTBmJyxcbiAgJ2Fycm93X3JpZ2h0X2hvb2snOidcXHUyMWFhXFx1ZmUwZicsXG4gICdhcnJvd191cCc6J1xcdTJiMDZcXHVmZTBmJyxcbiAgJ2Fycm93X3VwX2Rvd24nOidcXHUyMTk1XFx1ZmUwZicsXG4gICdhcnJvd191cF9zbWFsbCc6J1xcdWQ4M2RcXHVkZDNjJyxcbiAgJ2Fycm93X3VwcGVyX2xlZnQnOidcXHUyMTk2XFx1ZmUwZicsXG4gICdhcnJvd191cHBlcl9yaWdodCc6J1xcdTIxOTdcXHVmZTBmJyxcbiAgJ2Fycm93c19jbG9ja3dpc2UnOidcXHVkODNkXFx1ZGQwMycsXG4gICdhcnJvd3NfY291bnRlcmNsb2Nrd2lzZSc6J1xcdWQ4M2RcXHVkZDA0JyxcbiAgJ2FydCc6J1xcdWQ4M2NcXHVkZmE4JyxcbiAgJ2FydGljdWxhdGVkX2xvcnJ5JzonXFx1ZDgzZFxcdWRlOWInLFxuICAnYXJ0aWZpY2lhbF9zYXRlbGxpdGUnOidcXHVkODNkXFx1ZGVmMCcsXG4gICdhc3RvbmlzaGVkJzonXFx1ZDgzZFxcdWRlMzInLFxuICAnYXRobGV0aWNfc2hvZSc6J1xcdWQ4M2RcXHVkYzVmJyxcbiAgJ2F0bSc6J1xcdWQ4M2NcXHVkZmU3JyxcbiAgJ2F0b21fc3ltYm9sJzonXFx1MjY5YlxcdWZlMGYnLFxuICAnYXZvY2Fkbyc6J1xcdWQ4M2VcXHVkZDUxJyxcbiAgJ2InOidcXHVkODNjXFx1ZGQ3MVxcdWZlMGYnLFxuICAnYmFieSc6J1xcdWQ4M2RcXHVkYzc2JyxcbiAgJ2JhYnlfYm90dGxlJzonXFx1ZDgzY1xcdWRmN2MnLFxuICAnYmFieV9jaGljayc6J1xcdWQ4M2RcXHVkYzI0JyxcbiAgJ2JhYnlfc3ltYm9sJzonXFx1ZDgzZFxcdWRlYmMnLFxuICAnYmFjayc6J1xcdWQ4M2RcXHVkZDE5JyxcbiAgJ2JhY29uJzonXFx1ZDgzZVxcdWRkNTMnLFxuICAnYmFkbWludG9uJzonXFx1ZDgzY1xcdWRmZjgnLFxuICAnYmFnZ2FnZV9jbGFpbSc6J1xcdWQ4M2RcXHVkZWM0JyxcbiAgJ2JhZ3VldHRlX2JyZWFkJzonXFx1ZDgzZVxcdWRkNTYnLFxuICAnYmFsYW5jZV9zY2FsZSc6J1xcdTI2OTZcXHVmZTBmJyxcbiAgJ2JhbGxvb24nOidcXHVkODNjXFx1ZGY4OCcsXG4gICdiYWxsb3RfYm94JzonXFx1ZDgzZFxcdWRkZjMnLFxuICAnYmFsbG90X2JveF93aXRoX2NoZWNrJzonXFx1MjYxMVxcdWZlMGYnLFxuICAnYmFtYm9vJzonXFx1ZDgzY1xcdWRmOGQnLFxuICAnYmFuYW5hJzonXFx1ZDgzY1xcdWRmNGMnLFxuICAnYmFuZ2JhbmcnOidcXHUyMDNjXFx1ZmUwZicsXG4gICdiYW5rJzonXFx1ZDgzY1xcdWRmZTYnLFxuICAnYmFyX2NoYXJ0JzonXFx1ZDgzZFxcdWRjY2EnLFxuICAnYmFyYmVyJzonXFx1ZDgzZFxcdWRjODgnLFxuICAnYmFzZWJhbGwnOidcXHUyNmJlXFx1ZmUwZicsXG4gICdiYXNrZXRiYWxsJzonXFx1ZDgzY1xcdWRmYzAnLFxuICAnYmFza2V0YmFsbF9tYW4nOidcXHUyNmY5XFx1ZmUwZicsXG4gICdiYXNrZXRiYWxsX3dvbWFuJzonXFx1MjZmOVxcdWZlMGYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2JhdCc6J1xcdWQ4M2VcXHVkZDg3JyxcbiAgJ2JhdGgnOidcXHVkODNkXFx1ZGVjMCcsXG4gICdiYXRodHViJzonXFx1ZDgzZFxcdWRlYzEnLFxuICAnYmF0dGVyeSc6J1xcdWQ4M2RcXHVkZDBiJyxcbiAgJ2JlYWNoX3VtYnJlbGxhJzonXFx1ZDgzY1xcdWRmZDYnLFxuICAnYmVhcic6J1xcdWQ4M2RcXHVkYzNiJyxcbiAgJ2JlZCc6J1xcdWQ4M2RcXHVkZWNmJyxcbiAgJ2JlZSc6J1xcdWQ4M2RcXHVkYzFkJyxcbiAgJ2JlZXInOidcXHVkODNjXFx1ZGY3YScsXG4gICdiZWVycyc6J1xcdWQ4M2NcXHVkZjdiJyxcbiAgJ2JlZXRsZSc6J1xcdWQ4M2RcXHVkYzFlJyxcbiAgJ2JlZ2lubmVyJzonXFx1ZDgzZFxcdWRkMzAnLFxuICAnYmVsbCc6J1xcdWQ4M2RcXHVkZDE0JyxcbiAgJ2JlbGxob3BfYmVsbCc6J1xcdWQ4M2RcXHVkZWNlJyxcbiAgJ2JlbnRvJzonXFx1ZDgzY1xcdWRmNzEnLFxuICAnYmlraW5nX21hbic6J1xcdWQ4M2RcXHVkZWI0JyxcbiAgJ2Jpa2UnOidcXHVkODNkXFx1ZGViMicsXG4gICdiaWtpbmdfd29tYW4nOidcXHVkODNkXFx1ZGViNCZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnYmlraW5pJzonXFx1ZDgzZFxcdWRjNTknLFxuICAnYmlvaGF6YXJkJzonXFx1MjYyM1xcdWZlMGYnLFxuICAnYmlyZCc6J1xcdWQ4M2RcXHVkYzI2JyxcbiAgJ2JpcnRoZGF5JzonXFx1ZDgzY1xcdWRmODInLFxuICAnYmxhY2tfY2lyY2xlJzonXFx1MjZhYlxcdWZlMGYnLFxuICAnYmxhY2tfZmxhZyc6J1xcdWQ4M2NcXHVkZmY0JyxcbiAgJ2JsYWNrX2hlYXJ0JzonXFx1ZDgzZFxcdWRkYTQnLFxuICAnYmxhY2tfam9rZXInOidcXHVkODNjXFx1ZGNjZicsXG4gICdibGFja19sYXJnZV9zcXVhcmUnOidcXHUyYjFiXFx1ZmUwZicsXG4gICdibGFja19tZWRpdW1fc21hbGxfc3F1YXJlJzonXFx1MjVmZVxcdWZlMGYnLFxuICAnYmxhY2tfbWVkaXVtX3NxdWFyZSc6J1xcdTI1ZmNcXHVmZTBmJyxcbiAgJ2JsYWNrX25pYic6J1xcdTI3MTJcXHVmZTBmJyxcbiAgJ2JsYWNrX3NtYWxsX3NxdWFyZSc6J1xcdTI1YWFcXHVmZTBmJyxcbiAgJ2JsYWNrX3NxdWFyZV9idXR0b24nOidcXHVkODNkXFx1ZGQzMicsXG4gICdibG9uZGVfbWFuJzonXFx1ZDgzZFxcdWRjNzEnLFxuICAnYmxvbmRlX3dvbWFuJzonXFx1ZDgzZFxcdWRjNzEmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2Jsb3Nzb20nOidcXHVkODNjXFx1ZGYzYycsXG4gICdibG93ZmlzaCc6J1xcdWQ4M2RcXHVkYzIxJyxcbiAgJ2JsdWVfYm9vayc6J1xcdWQ4M2RcXHVkY2Q4JyxcbiAgJ2JsdWVfY2FyJzonXFx1ZDgzZFxcdWRlOTknLFxuICAnYmx1ZV9oZWFydCc6J1xcdWQ4M2RcXHVkYzk5JyxcbiAgJ2JsdXNoJzonXFx1ZDgzZFxcdWRlMGEnLFxuICAnYm9hcic6J1xcdWQ4M2RcXHVkYzE3JyxcbiAgJ2JvYXQnOidcXHUyNmY1XFx1ZmUwZicsXG4gICdib21iJzonXFx1ZDgzZFxcdWRjYTMnLFxuICAnYm9vayc6J1xcdWQ4M2RcXHVkY2Q2JyxcbiAgJ2Jvb2ttYXJrJzonXFx1ZDgzZFxcdWRkMTYnLFxuICAnYm9va21hcmtfdGFicyc6J1xcdWQ4M2RcXHVkY2QxJyxcbiAgJ2Jvb2tzJzonXFx1ZDgzZFxcdWRjZGEnLFxuICAnYm9vbSc6J1xcdWQ4M2RcXHVkY2E1JyxcbiAgJ2Jvb3QnOidcXHVkODNkXFx1ZGM2MicsXG4gICdib3VxdWV0JzonXFx1ZDgzZFxcdWRjOTAnLFxuICAnYm93aW5nX21hbic6J1xcdWQ4M2RcXHVkZTQ3JyxcbiAgJ2Jvd19hbmRfYXJyb3cnOidcXHVkODNjXFx1ZGZmOScsXG4gICdib3dpbmdfd29tYW4nOidcXHVkODNkXFx1ZGU0NyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnYm93bGluZyc6J1xcdWQ4M2NcXHVkZmIzJyxcbiAgJ2JveGluZ19nbG92ZSc6J1xcdWQ4M2VcXHVkZDRhJyxcbiAgJ2JveSc6J1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2JyZWFkJzonXFx1ZDgzY1xcdWRmNWUnLFxuICAnYnJpZGVfd2l0aF92ZWlsJzonXFx1ZDgzZFxcdWRjNzAnLFxuICAnYnJpZGdlX2F0X25pZ2h0JzonXFx1ZDgzY1xcdWRmMDknLFxuICAnYnJpZWZjYXNlJzonXFx1ZDgzZFxcdWRjYmMnLFxuICAnYnJva2VuX2hlYXJ0JzonXFx1ZDgzZFxcdWRjOTQnLFxuICAnYnVnJzonXFx1ZDgzZFxcdWRjMWInLFxuICAnYnVpbGRpbmdfY29uc3RydWN0aW9uJzonXFx1ZDgzY1xcdWRmZDcnLFxuICAnYnVsYic6J1xcdWQ4M2RcXHVkY2ExJyxcbiAgJ2J1bGxldHRyYWluX2Zyb250JzonXFx1ZDgzZFxcdWRlODUnLFxuICAnYnVsbGV0dHJhaW5fc2lkZSc6J1xcdWQ4M2RcXHVkZTg0JyxcbiAgJ2J1cnJpdG8nOidcXHVkODNjXFx1ZGYyZicsXG4gICdidXMnOidcXHVkODNkXFx1ZGU4YycsXG4gICdidXNpbmVzc19zdWl0X2xldml0YXRpbmcnOidcXHVkODNkXFx1ZGQ3NCcsXG4gICdidXNzdG9wJzonXFx1ZDgzZFxcdWRlOGYnLFxuICAnYnVzdF9pbl9zaWxob3VldHRlJzonXFx1ZDgzZFxcdWRjNjQnLFxuICAnYnVzdHNfaW5fc2lsaG91ZXR0ZSc6J1xcdWQ4M2RcXHVkYzY1JyxcbiAgJ2J1dHRlcmZseSc6J1xcdWQ4M2VcXHVkZDhiJyxcbiAgJ2NhY3R1cyc6J1xcdWQ4M2NcXHVkZjM1JyxcbiAgJ2Nha2UnOidcXHVkODNjXFx1ZGY3MCcsXG4gICdjYWxlbmRhcic6J1xcdWQ4M2RcXHVkY2M2JyxcbiAgJ2NhbGxfbWVfaGFuZCc6J1xcdWQ4M2VcXHVkZDE5JyxcbiAgJ2NhbGxpbmcnOidcXHVkODNkXFx1ZGNmMicsXG4gICdjYW1lbCc6J1xcdWQ4M2RcXHVkYzJiJyxcbiAgJ2NhbWVyYSc6J1xcdWQ4M2RcXHVkY2Y3JyxcbiAgJ2NhbWVyYV9mbGFzaCc6J1xcdWQ4M2RcXHVkY2Y4JyxcbiAgJ2NhbXBpbmcnOidcXHVkODNjXFx1ZGZkNScsXG4gICdjYW5jZXInOidcXHUyNjRiXFx1ZmUwZicsXG4gICdjYW5kbGUnOidcXHVkODNkXFx1ZGQ2ZicsXG4gICdjYW5keSc6J1xcdWQ4M2NcXHVkZjZjJyxcbiAgJ2Nhbm9lJzonXFx1ZDgzZFxcdWRlZjYnLFxuICAnY2FwaXRhbF9hYmNkJzonXFx1ZDgzZFxcdWRkMjAnLFxuICAnY2Fwcmljb3JuJzonXFx1MjY1MVxcdWZlMGYnLFxuICAnY2FyJzonXFx1ZDgzZFxcdWRlOTcnLFxuICAnY2FyZF9maWxlX2JveCc6J1xcdWQ4M2RcXHVkZGMzJyxcbiAgJ2NhcmRfaW5kZXgnOidcXHVkODNkXFx1ZGNjNycsXG4gICdjYXJkX2luZGV4X2RpdmlkZXJzJzonXFx1ZDgzZFxcdWRkYzInLFxuICAnY2Fyb3VzZWxfaG9yc2UnOidcXHVkODNjXFx1ZGZhMCcsXG4gICdjYXJyb3QnOidcXHVkODNlXFx1ZGQ1NScsXG4gICdjYXQnOidcXHVkODNkXFx1ZGMzMScsXG4gICdjYXQyJzonXFx1ZDgzZFxcdWRjMDgnLFxuICAnY2QnOidcXHVkODNkXFx1ZGNiZicsXG4gICdjaGFpbnMnOidcXHUyNmQzJyxcbiAgJ2NoYW1wYWduZSc6J1xcdWQ4M2NcXHVkZjdlJyxcbiAgJ2NoYXJ0JzonXFx1ZDgzZFxcdWRjYjknLFxuICAnY2hhcnRfd2l0aF9kb3dud2FyZHNfdHJlbmQnOidcXHVkODNkXFx1ZGNjOScsXG4gICdjaGFydF93aXRoX3Vwd2FyZHNfdHJlbmQnOidcXHVkODNkXFx1ZGNjOCcsXG4gICdjaGVja2VyZWRfZmxhZyc6J1xcdWQ4M2NcXHVkZmMxJyxcbiAgJ2NoZWVzZSc6J1xcdWQ4M2VcXHVkZGMwJyxcbiAgJ2NoZXJyaWVzJzonXFx1ZDgzY1xcdWRmNTInLFxuICAnY2hlcnJ5X2Jsb3Nzb20nOidcXHVkODNjXFx1ZGYzOCcsXG4gICdjaGVzdG51dCc6J1xcdWQ4M2NcXHVkZjMwJyxcbiAgJ2NoaWNrZW4nOidcXHVkODNkXFx1ZGMxNCcsXG4gICdjaGlsZHJlbl9jcm9zc2luZyc6J1xcdWQ4M2RcXHVkZWI4JyxcbiAgJ2NoaXBtdW5rJzonXFx1ZDgzZFxcdWRjM2YnLFxuICAnY2hvY29sYXRlX2Jhcic6J1xcdWQ4M2NcXHVkZjZiJyxcbiAgJ2NocmlzdG1hc190cmVlJzonXFx1ZDgzY1xcdWRmODQnLFxuICAnY2h1cmNoJzonXFx1MjZlYVxcdWZlMGYnLFxuICAnY2luZW1hJzonXFx1ZDgzY1xcdWRmYTYnLFxuICAnY2lyY3VzX3RlbnQnOidcXHVkODNjXFx1ZGZhYScsXG4gICdjaXR5X3N1bnJpc2UnOidcXHVkODNjXFx1ZGYwNycsXG4gICdjaXR5X3N1bnNldCc6J1xcdWQ4M2NcXHVkZjA2JyxcbiAgJ2NpdHlzY2FwZSc6J1xcdWQ4M2NcXHVkZmQ5JyxcbiAgJ2NsJzonXFx1ZDgzY1xcdWRkOTEnLFxuICAnY2xhbXAnOidcXHVkODNkXFx1ZGRkYycsXG4gICdjbGFwJzonXFx1ZDgzZFxcdWRjNGYnLFxuICAnY2xhcHBlcic6J1xcdWQ4M2NcXHVkZmFjJyxcbiAgJ2NsYXNzaWNhbF9idWlsZGluZyc6J1xcdWQ4M2NcXHVkZmRiJyxcbiAgJ2NsaW5raW5nX2dsYXNzZXMnOidcXHVkODNlXFx1ZGQ0MicsXG4gICdjbGlwYm9hcmQnOidcXHVkODNkXFx1ZGNjYicsXG4gICdjbG9jazEnOidcXHVkODNkXFx1ZGQ1MCcsXG4gICdjbG9jazEwJzonXFx1ZDgzZFxcdWRkNTknLFxuICAnY2xvY2sxMDMwJzonXFx1ZDgzZFxcdWRkNjUnLFxuICAnY2xvY2sxMSc6J1xcdWQ4M2RcXHVkZDVhJyxcbiAgJ2Nsb2NrMTEzMCc6J1xcdWQ4M2RcXHVkZDY2JyxcbiAgJ2Nsb2NrMTInOidcXHVkODNkXFx1ZGQ1YicsXG4gICdjbG9jazEyMzAnOidcXHVkODNkXFx1ZGQ2NycsXG4gICdjbG9jazEzMCc6J1xcdWQ4M2RcXHVkZDVjJyxcbiAgJ2Nsb2NrMic6J1xcdWQ4M2RcXHVkZDUxJyxcbiAgJ2Nsb2NrMjMwJzonXFx1ZDgzZFxcdWRkNWQnLFxuICAnY2xvY2szJzonXFx1ZDgzZFxcdWRkNTInLFxuICAnY2xvY2szMzAnOidcXHVkODNkXFx1ZGQ1ZScsXG4gICdjbG9jazQnOidcXHVkODNkXFx1ZGQ1MycsXG4gICdjbG9jazQzMCc6J1xcdWQ4M2RcXHVkZDVmJyxcbiAgJ2Nsb2NrNSc6J1xcdWQ4M2RcXHVkZDU0JyxcbiAgJ2Nsb2NrNTMwJzonXFx1ZDgzZFxcdWRkNjAnLFxuICAnY2xvY2s2JzonXFx1ZDgzZFxcdWRkNTUnLFxuICAnY2xvY2s2MzAnOidcXHVkODNkXFx1ZGQ2MScsXG4gICdjbG9jazcnOidcXHVkODNkXFx1ZGQ1NicsXG4gICdjbG9jazczMCc6J1xcdWQ4M2RcXHVkZDYyJyxcbiAgJ2Nsb2NrOCc6J1xcdWQ4M2RcXHVkZDU3JyxcbiAgJ2Nsb2NrODMwJzonXFx1ZDgzZFxcdWRkNjMnLFxuICAnY2xvY2s5JzonXFx1ZDgzZFxcdWRkNTgnLFxuICAnY2xvY2s5MzAnOidcXHVkODNkXFx1ZGQ2NCcsXG4gICdjbG9zZWRfYm9vayc6J1xcdWQ4M2RcXHVkY2Q1JyxcbiAgJ2Nsb3NlZF9sb2NrX3dpdGhfa2V5JzonXFx1ZDgzZFxcdWRkMTAnLFxuICAnY2xvc2VkX3VtYnJlbGxhJzonXFx1ZDgzY1xcdWRmMDInLFxuICAnY2xvdWQnOidcXHUyNjAxXFx1ZmUwZicsXG4gICdjbG91ZF93aXRoX2xpZ2h0bmluZyc6J1xcdWQ4M2NcXHVkZjI5JyxcbiAgJ2Nsb3VkX3dpdGhfbGlnaHRuaW5nX2FuZF9yYWluJzonXFx1MjZjOCcsXG4gICdjbG91ZF93aXRoX3JhaW4nOidcXHVkODNjXFx1ZGYyNycsXG4gICdjbG91ZF93aXRoX3Nub3cnOidcXHVkODNjXFx1ZGYyOCcsXG4gICdjbG93bl9mYWNlJzonXFx1ZDgzZVxcdWRkMjEnLFxuICAnY2x1YnMnOidcXHUyNjYzXFx1ZmUwZicsXG4gICdjb2NrdGFpbCc6J1xcdWQ4M2NcXHVkZjc4JyxcbiAgJ2NvZmZlZSc6J1xcdTI2MTVcXHVmZTBmJyxcbiAgJ2NvZmZpbic6J1xcdTI2YjBcXHVmZTBmJyxcbiAgJ2NvbGRfc3dlYXQnOidcXHVkODNkXFx1ZGUzMCcsXG4gICdjb21ldCc6J1xcdTI2MDRcXHVmZTBmJyxcbiAgJ2NvbXB1dGVyJzonXFx1ZDgzZFxcdWRjYmInLFxuICAnY29tcHV0ZXJfbW91c2UnOidcXHVkODNkXFx1ZGRiMScsXG4gICdjb25mZXR0aV9iYWxsJzonXFx1ZDgzY1xcdWRmOGEnLFxuICAnY29uZm91bmRlZCc6J1xcdWQ4M2RcXHVkZTE2JyxcbiAgJ2NvbmZ1c2VkJzonXFx1ZDgzZFxcdWRlMTUnLFxuICAnY29uZ3JhdHVsYXRpb25zJzonXFx1MzI5N1xcdWZlMGYnLFxuICAnY29uc3RydWN0aW9uJzonXFx1ZDgzZFxcdWRlYTcnLFxuICAnY29uc3RydWN0aW9uX3dvcmtlcl9tYW4nOidcXHVkODNkXFx1ZGM3NycsXG4gICdjb25zdHJ1Y3Rpb25fd29ya2VyX3dvbWFuJzonXFx1ZDgzZFxcdWRjNzcmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2NvbnRyb2xfa25vYnMnOidcXHVkODNjXFx1ZGY5YicsXG4gICdjb252ZW5pZW5jZV9zdG9yZSc6J1xcdWQ4M2NcXHVkZmVhJyxcbiAgJ2Nvb2tpZSc6J1xcdWQ4M2NcXHVkZjZhJyxcbiAgJ2Nvb2wnOidcXHVkODNjXFx1ZGQ5MicsXG4gICdwb2xpY2VtYW4nOidcXHVkODNkXFx1ZGM2ZScsXG4gICdjb3B5cmlnaHQnOidcXHUwMGE5XFx1ZmUwZicsXG4gICdjb3JuJzonXFx1ZDgzY1xcdWRmM2QnLFxuICAnY291Y2hfYW5kX2xhbXAnOidcXHVkODNkXFx1ZGVjYicsXG4gICdjb3VwbGUnOidcXHVkODNkXFx1ZGM2YicsXG4gICdjb3VwbGVfd2l0aF9oZWFydF93b21hbl9tYW4nOidcXHVkODNkXFx1ZGM5MScsXG4gICdjb3VwbGVfd2l0aF9oZWFydF9tYW5fbWFuJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdTI3NjRcXHVmZTBmJnp3ajtcXHVkODNkXFx1ZGM2OCcsXG4gICdjb3VwbGVfd2l0aF9oZWFydF93b21hbl93b21hbic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHUyNzY0XFx1ZmUwZiZ6d2o7XFx1ZDgzZFxcdWRjNjknLFxuICAnY291cGxla2lzc19tYW5fbWFuJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdTI3NjRcXHVmZTBmJnp3ajtcXHVkODNkXFx1ZGM4YiZ6d2o7XFx1ZDgzZFxcdWRjNjgnLFxuICAnY291cGxla2lzc19tYW5fd29tYW4nOidcXHVkODNkXFx1ZGM4ZicsXG4gICdjb3VwbGVraXNzX3dvbWFuX3dvbWFuJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdTI3NjRcXHVmZTBmJnp3ajtcXHVkODNkXFx1ZGM4YiZ6d2o7XFx1ZDgzZFxcdWRjNjknLFxuICAnY293JzonXFx1ZDgzZFxcdWRjMmUnLFxuICAnY293Mic6J1xcdWQ4M2RcXHVkYzA0JyxcbiAgJ2Nvd2JveV9oYXRfZmFjZSc6J1xcdWQ4M2VcXHVkZDIwJyxcbiAgJ2NyYWInOidcXHVkODNlXFx1ZGQ4MCcsXG4gICdjcmF5b24nOidcXHVkODNkXFx1ZGQ4ZCcsXG4gICdjcmVkaXRfY2FyZCc6J1xcdWQ4M2RcXHVkY2IzJyxcbiAgJ2NyZXNjZW50X21vb24nOidcXHVkODNjXFx1ZGYxOScsXG4gICdjcmlja2V0JzonXFx1ZDgzY1xcdWRmY2YnLFxuICAnY3JvY29kaWxlJzonXFx1ZDgzZFxcdWRjMGEnLFxuICAnY3JvaXNzYW50JzonXFx1ZDgzZVxcdWRkNTAnLFxuICAnY3Jvc3NlZF9maW5nZXJzJzonXFx1ZDgzZVxcdWRkMWUnLFxuICAnY3Jvc3NlZF9mbGFncyc6J1xcdWQ4M2NcXHVkZjhjJyxcbiAgJ2Nyb3NzZWRfc3dvcmRzJzonXFx1MjY5NFxcdWZlMGYnLFxuICAnY3Jvd24nOidcXHVkODNkXFx1ZGM1MScsXG4gICdjcnknOidcXHVkODNkXFx1ZGUyMicsXG4gICdjcnlpbmdfY2F0X2ZhY2UnOidcXHVkODNkXFx1ZGUzZicsXG4gICdjcnlzdGFsX2JhbGwnOidcXHVkODNkXFx1ZGQyZScsXG4gICdjdWN1bWJlcic6J1xcdWQ4M2VcXHVkZDUyJyxcbiAgJ2N1cGlkJzonXFx1ZDgzZFxcdWRjOTgnLFxuICAnY3VybHlfbG9vcCc6J1xcdTI3YjAnLFxuICAnY3VycmVuY3lfZXhjaGFuZ2UnOidcXHVkODNkXFx1ZGNiMScsXG4gICdjdXJyeSc6J1xcdWQ4M2NcXHVkZjViJyxcbiAgJ2N1c3RhcmQnOidcXHVkODNjXFx1ZGY2ZScsXG4gICdjdXN0b21zJzonXFx1ZDgzZFxcdWRlYzMnLFxuICAnY3ljbG9uZSc6J1xcdWQ4M2NcXHVkZjAwJyxcbiAgJ2RhZ2dlcic6J1xcdWQ4M2RcXHVkZGUxJyxcbiAgJ2RhbmNlcic6J1xcdWQ4M2RcXHVkYzgzJyxcbiAgJ2RhbmNpbmdfd29tZW4nOidcXHVkODNkXFx1ZGM2ZicsXG4gICdkYW5jaW5nX21lbic6J1xcdWQ4M2RcXHVkYzZmJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdkYW5nbyc6J1xcdWQ4M2NcXHVkZjYxJyxcbiAgJ2Rhcmtfc3VuZ2xhc3Nlcyc6J1xcdWQ4M2RcXHVkZDc2JyxcbiAgJ2RhcnQnOidcXHVkODNjXFx1ZGZhZicsXG4gICdkYXNoJzonXFx1ZDgzZFxcdWRjYTgnLFxuICAnZGF0ZSc6J1xcdWQ4M2RcXHVkY2M1JyxcbiAgJ2RlY2lkdW91c190cmVlJzonXFx1ZDgzY1xcdWRmMzMnLFxuICAnZGVlcic6J1xcdWQ4M2VcXHVkZDhjJyxcbiAgJ2RlcGFydG1lbnRfc3RvcmUnOidcXHVkODNjXFx1ZGZlYycsXG4gICdkZXJlbGljdF9ob3VzZSc6J1xcdWQ4M2NcXHVkZmRhJyxcbiAgJ2Rlc2VydCc6J1xcdWQ4M2NcXHVkZmRjJyxcbiAgJ2Rlc2VydF9pc2xhbmQnOidcXHVkODNjXFx1ZGZkZCcsXG4gICdkZXNrdG9wX2NvbXB1dGVyJzonXFx1ZDgzZFxcdWRkYTUnLFxuICAnbWFsZV9kZXRlY3RpdmUnOidcXHVkODNkXFx1ZGQ3NVxcdWZlMGYnLFxuICAnZGlhbW9uZF9zaGFwZV93aXRoX2FfZG90X2luc2lkZSc6J1xcdWQ4M2RcXHVkY2EwJyxcbiAgJ2RpYW1vbmRzJzonXFx1MjY2NlxcdWZlMGYnLFxuICAnZGlzYXBwb2ludGVkJzonXFx1ZDgzZFxcdWRlMWUnLFxuICAnZGlzYXBwb2ludGVkX3JlbGlldmVkJzonXFx1ZDgzZFxcdWRlMjUnLFxuICAnZGl6enknOidcXHVkODNkXFx1ZGNhYicsXG4gICdkaXp6eV9mYWNlJzonXFx1ZDgzZFxcdWRlMzUnLFxuICAnZG9fbm90X2xpdHRlcic6J1xcdWQ4M2RcXHVkZWFmJyxcbiAgJ2RvZyc6J1xcdWQ4M2RcXHVkYzM2JyxcbiAgJ2RvZzInOidcXHVkODNkXFx1ZGMxNScsXG4gICdkb2xsYXInOidcXHVkODNkXFx1ZGNiNScsXG4gICdkb2xscyc6J1xcdWQ4M2NcXHVkZjhlJyxcbiAgJ2RvbHBoaW4nOidcXHVkODNkXFx1ZGMyYycsXG4gICdkb29yJzonXFx1ZDgzZFxcdWRlYWEnLFxuICAnZG91Z2hudXQnOidcXHVkODNjXFx1ZGY2OScsXG4gICdkb3ZlJzonXFx1ZDgzZFxcdWRkNGEnLFxuICAnZHJhZ29uJzonXFx1ZDgzZFxcdWRjMDknLFxuICAnZHJhZ29uX2ZhY2UnOidcXHVkODNkXFx1ZGMzMicsXG4gICdkcmVzcyc6J1xcdWQ4M2RcXHVkYzU3JyxcbiAgJ2Ryb21lZGFyeV9jYW1lbCc6J1xcdWQ4M2RcXHVkYzJhJyxcbiAgJ2Ryb29saW5nX2ZhY2UnOidcXHVkODNlXFx1ZGQyNCcsXG4gICdkcm9wbGV0JzonXFx1ZDgzZFxcdWRjYTcnLFxuICAnZHJ1bSc6J1xcdWQ4M2VcXHVkZDQxJyxcbiAgJ2R1Y2snOidcXHVkODNlXFx1ZGQ4NicsXG4gICdkdmQnOidcXHVkODNkXFx1ZGNjMCcsXG4gICdlLW1haWwnOidcXHVkODNkXFx1ZGNlNycsXG4gICdlYWdsZSc6J1xcdWQ4M2VcXHVkZDg1JyxcbiAgJ2Vhcic6J1xcdWQ4M2RcXHVkYzQyJyxcbiAgJ2Vhcl9vZl9yaWNlJzonXFx1ZDgzY1xcdWRmM2UnLFxuICAnZWFydGhfYWZyaWNhJzonXFx1ZDgzY1xcdWRmMGQnLFxuICAnZWFydGhfYW1lcmljYXMnOidcXHVkODNjXFx1ZGYwZScsXG4gICdlYXJ0aF9hc2lhJzonXFx1ZDgzY1xcdWRmMGYnLFxuICAnZWdnJzonXFx1ZDgzZVxcdWRkNWEnLFxuICAnZWdncGxhbnQnOidcXHVkODNjXFx1ZGY0NicsXG4gICdlaWdodF9wb2ludGVkX2JsYWNrX3N0YXInOidcXHUyNzM0XFx1ZmUwZicsXG4gICdlaWdodF9zcG9rZWRfYXN0ZXJpc2snOidcXHUyNzMzXFx1ZmUwZicsXG4gICdlbGVjdHJpY19wbHVnJzonXFx1ZDgzZFxcdWRkMGMnLFxuICAnZWxlcGhhbnQnOidcXHVkODNkXFx1ZGMxOCcsXG4gICdlbWFpbCc6J1xcdTI3MDlcXHVmZTBmJyxcbiAgJ2VuZCc6J1xcdWQ4M2RcXHVkZDFhJyxcbiAgJ2VudmVsb3BlX3dpdGhfYXJyb3cnOidcXHVkODNkXFx1ZGNlOScsXG4gICdldXJvJzonXFx1ZDgzZFxcdWRjYjYnLFxuICAnZXVyb3BlYW5fY2FzdGxlJzonXFx1ZDgzY1xcdWRmZjAnLFxuICAnZXVyb3BlYW5fcG9zdF9vZmZpY2UnOidcXHVkODNjXFx1ZGZlNCcsXG4gICdldmVyZ3JlZW5fdHJlZSc6J1xcdWQ4M2NcXHVkZjMyJyxcbiAgJ2V4Y2xhbWF0aW9uJzonXFx1Mjc1N1xcdWZlMGYnLFxuICAnZXhwcmVzc2lvbmxlc3MnOidcXHVkODNkXFx1ZGUxMScsXG4gICdleWUnOidcXHVkODNkXFx1ZGM0MScsXG4gICdleWVfc3BlZWNoX2J1YmJsZSc6J1xcdWQ4M2RcXHVkYzQxJnp3ajtcXHVkODNkXFx1ZGRlOCcsXG4gICdleWVnbGFzc2VzJzonXFx1ZDgzZFxcdWRjNTMnLFxuICAnZXllcyc6J1xcdWQ4M2RcXHVkYzQwJyxcbiAgJ2ZhY2Vfd2l0aF9oZWFkX2JhbmRhZ2UnOidcXHVkODNlXFx1ZGQxNScsXG4gICdmYWNlX3dpdGhfdGhlcm1vbWV0ZXInOidcXHVkODNlXFx1ZGQxMicsXG4gICdmaXN0X29uY29taW5nJzonXFx1ZDgzZFxcdWRjNGEnLFxuICAnZmFjdG9yeSc6J1xcdWQ4M2NcXHVkZmVkJyxcbiAgJ2ZhbGxlbl9sZWFmJzonXFx1ZDgzY1xcdWRmNDInLFxuICAnZmFtaWx5X21hbl93b21hbl9ib3knOidcXHVkODNkXFx1ZGM2YScsXG4gICdmYW1pbHlfbWFuX2JveSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjYmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV9tYW5fZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfbWFuX2dpcmxfYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X21hbl9tYW5fYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX21hbl9ib3lfYm95JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2NiZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X21hbl9tYW5fZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X21hbl9tYW5fZ2lybF9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX21hbl9naXJsX2dpcmwnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NycsXG4gICdmYW1pbHlfbWFuX3dvbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY2Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX3dvbWFuX2dpcmwnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV9tYW5fd29tYW5fZ2lybF9ib3knOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfbWFuX3dvbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV93b21hbl9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjYmendqO1xcdWQ4M2RcXHVkYzY2JyxcbiAgJ2ZhbWlseV93b21hbl9naXJsJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2ZhbWlseV93b21hbl9naXJsX2JveSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2JveSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2JveV9ib3knOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY2Jnp3ajtcXHVkODNkXFx1ZGM2NicsXG4gICdmYW1pbHlfd29tYW5fd29tYW5fZ2lybCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2dpcmxfYm95JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2NyZ6d2o7XFx1ZDgzZFxcdWRjNjYnLFxuICAnZmFtaWx5X3dvbWFuX3dvbWFuX2dpcmxfZ2lybCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjNjcmendqO1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2Zhc3RfZm9yd2FyZCc6J1xcdTIzZTknLFxuICAnZmF4JzonXFx1ZDgzZFxcdWRjZTAnLFxuICAnZmVhcmZ1bCc6J1xcdWQ4M2RcXHVkZTI4JyxcbiAgJ2ZlZXQnOidcXHVkODNkXFx1ZGMzZScsXG4gICdmZW1hbGVfZGV0ZWN0aXZlJzonXFx1ZDgzZFxcdWRkNzVcXHVmZTBmJnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdmZXJyaXNfd2hlZWwnOidcXHVkODNjXFx1ZGZhMScsXG4gICdmZXJyeSc6J1xcdTI2ZjQnLFxuICAnZmllbGRfaG9ja2V5JzonXFx1ZDgzY1xcdWRmZDEnLFxuICAnZmlsZV9jYWJpbmV0JzonXFx1ZDgzZFxcdWRkYzQnLFxuICAnZmlsZV9mb2xkZXInOidcXHVkODNkXFx1ZGNjMScsXG4gICdmaWxtX3Byb2plY3Rvcic6J1xcdWQ4M2RcXHVkY2ZkJyxcbiAgJ2ZpbG1fc3RyaXAnOidcXHVkODNjXFx1ZGY5ZScsXG4gICdmaXJlJzonXFx1ZDgzZFxcdWRkMjUnLFxuICAnZmlyZV9lbmdpbmUnOidcXHVkODNkXFx1ZGU5MicsXG4gICdmaXJld29ya3MnOidcXHVkODNjXFx1ZGY4NicsXG4gICdmaXJzdF9xdWFydGVyX21vb24nOidcXHVkODNjXFx1ZGYxMycsXG4gICdmaXJzdF9xdWFydGVyX21vb25fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWInLFxuICAnZmlzaCc6J1xcdWQ4M2RcXHVkYzFmJyxcbiAgJ2Zpc2hfY2FrZSc6J1xcdWQ4M2NcXHVkZjY1JyxcbiAgJ2Zpc2hpbmdfcG9sZV9hbmRfZmlzaCc6J1xcdWQ4M2NcXHVkZmEzJyxcbiAgJ2Zpc3RfcmFpc2VkJzonXFx1MjcwYScsXG4gICdmaXN0X2xlZnQnOidcXHVkODNlXFx1ZGQxYicsXG4gICdmaXN0X3JpZ2h0JzonXFx1ZDgzZVxcdWRkMWMnLFxuICAnZmxhZ3MnOidcXHVkODNjXFx1ZGY4ZicsXG4gICdmbGFzaGxpZ2h0JzonXFx1ZDgzZFxcdWRkMjYnLFxuICAnZmxldXJfZGVfbGlzJzonXFx1MjY5Y1xcdWZlMGYnLFxuICAnZmxpZ2h0X2Fycml2YWwnOidcXHVkODNkXFx1ZGVlYycsXG4gICdmbGlnaHRfZGVwYXJ0dXJlJzonXFx1ZDgzZFxcdWRlZWInLFxuICAnZmxvcHB5X2Rpc2snOidcXHVkODNkXFx1ZGNiZScsXG4gICdmbG93ZXJfcGxheWluZ19jYXJkcyc6J1xcdWQ4M2NcXHVkZmI0JyxcbiAgJ2ZsdXNoZWQnOidcXHVkODNkXFx1ZGUzMycsXG4gICdmb2cnOidcXHVkODNjXFx1ZGYyYicsXG4gICdmb2dneSc6J1xcdWQ4M2NcXHVkZjAxJyxcbiAgJ2Zvb3RiYWxsJzonXFx1ZDgzY1xcdWRmYzgnLFxuICAnZm9vdHByaW50cyc6J1xcdWQ4M2RcXHVkYzYzJyxcbiAgJ2ZvcmtfYW5kX2tuaWZlJzonXFx1ZDgzY1xcdWRmNzQnLFxuICAnZm91bnRhaW4nOidcXHUyNmYyXFx1ZmUwZicsXG4gICdmb3VudGFpbl9wZW4nOidcXHVkODNkXFx1ZGQ4YicsXG4gICdmb3VyX2xlYWZfY2xvdmVyJzonXFx1ZDgzY1xcdWRmNDAnLFxuICAnZm94X2ZhY2UnOidcXHVkODNlXFx1ZGQ4YScsXG4gICdmcmFtZWRfcGljdHVyZSc6J1xcdWQ4M2RcXHVkZGJjJyxcbiAgJ2ZyZWUnOidcXHVkODNjXFx1ZGQ5MycsXG4gICdmcmllZF9lZ2cnOidcXHVkODNjXFx1ZGY3MycsXG4gICdmcmllZF9zaHJpbXAnOidcXHVkODNjXFx1ZGY2NCcsXG4gICdmcmllcyc6J1xcdWQ4M2NcXHVkZjVmJyxcbiAgJ2Zyb2cnOidcXHVkODNkXFx1ZGMzOCcsXG4gICdmcm93bmluZyc6J1xcdWQ4M2RcXHVkZTI2JyxcbiAgJ2Zyb3duaW5nX2ZhY2UnOidcXHUyNjM5XFx1ZmUwZicsXG4gICdmcm93bmluZ19tYW4nOidcXHVkODNkXFx1ZGU0ZCZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnZnJvd25pbmdfd29tYW4nOidcXHVkODNkXFx1ZGU0ZCcsXG4gICdtaWRkbGVfZmluZ2VyJzonXFx1ZDgzZFxcdWRkOTUnLFxuICAnZnVlbHB1bXAnOidcXHUyNmZkXFx1ZmUwZicsXG4gICdmdWxsX21vb24nOidcXHVkODNjXFx1ZGYxNScsXG4gICdmdWxsX21vb25fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWQnLFxuICAnZnVuZXJhbF91cm4nOidcXHUyNmIxXFx1ZmUwZicsXG4gICdnYW1lX2RpZSc6J1xcdWQ4M2NcXHVkZmIyJyxcbiAgJ2dlYXInOidcXHUyNjk5XFx1ZmUwZicsXG4gICdnZW0nOidcXHVkODNkXFx1ZGM4ZScsXG4gICdnZW1pbmknOidcXHUyNjRhXFx1ZmUwZicsXG4gICdnaG9zdCc6J1xcdWQ4M2RcXHVkYzdiJyxcbiAgJ2dpZnQnOidcXHVkODNjXFx1ZGY4MScsXG4gICdnaWZ0X2hlYXJ0JzonXFx1ZDgzZFxcdWRjOWQnLFxuICAnZ2lybCc6J1xcdWQ4M2RcXHVkYzY3JyxcbiAgJ2dsb2JlX3dpdGhfbWVyaWRpYW5zJzonXFx1ZDgzY1xcdWRmMTAnLFxuICAnZ29hbF9uZXQnOidcXHVkODNlXFx1ZGQ0NScsXG4gICdnb2F0JzonXFx1ZDgzZFxcdWRjMTAnLFxuICAnZ29sZic6J1xcdTI2ZjNcXHVmZTBmJyxcbiAgJ2dvbGZpbmdfbWFuJzonXFx1ZDgzY1xcdWRmY2NcXHVmZTBmJyxcbiAgJ2dvbGZpbmdfd29tYW4nOidcXHVkODNjXFx1ZGZjY1xcdWZlMGYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ2dvcmlsbGEnOidcXHVkODNlXFx1ZGQ4ZCcsXG4gICdncmFwZXMnOidcXHVkODNjXFx1ZGY0NycsXG4gICdncmVlbl9hcHBsZSc6J1xcdWQ4M2NcXHVkZjRmJyxcbiAgJ2dyZWVuX2Jvb2snOidcXHVkODNkXFx1ZGNkNycsXG4gICdncmVlbl9oZWFydCc6J1xcdWQ4M2RcXHVkYzlhJyxcbiAgJ2dyZWVuX3NhbGFkJzonXFx1ZDgzZVxcdWRkNTcnLFxuICAnZ3JleV9leGNsYW1hdGlvbic6J1xcdTI3NTUnLFxuICAnZ3JleV9xdWVzdGlvbic6J1xcdTI3NTQnLFxuICAnZ3JpbWFjaW5nJzonXFx1ZDgzZFxcdWRlMmMnLFxuICAnZ3Jpbic6J1xcdWQ4M2RcXHVkZTAxJyxcbiAgJ2dyaW5uaW5nJzonXFx1ZDgzZFxcdWRlMDAnLFxuICAnZ3VhcmRzbWFuJzonXFx1ZDgzZFxcdWRjODInLFxuICAnZ3VhcmRzd29tYW4nOidcXHVkODNkXFx1ZGM4MiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnZ3VpdGFyJzonXFx1ZDgzY1xcdWRmYjgnLFxuICAnZ3VuJzonXFx1ZDgzZFxcdWRkMmInLFxuICAnaGFpcmN1dF93b21hbic6J1xcdWQ4M2RcXHVkYzg3JyxcbiAgJ2hhaXJjdXRfbWFuJzonXFx1ZDgzZFxcdWRjODcmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ2hhbWJ1cmdlcic6J1xcdWQ4M2NcXHVkZjU0JyxcbiAgJ2hhbW1lcic6J1xcdWQ4M2RcXHVkZDI4JyxcbiAgJ2hhbW1lcl9hbmRfcGljayc6J1xcdTI2OTInLFxuICAnaGFtbWVyX2FuZF93cmVuY2gnOidcXHVkODNkXFx1ZGVlMCcsXG4gICdoYW1zdGVyJzonXFx1ZDgzZFxcdWRjMzknLFxuICAnaGFuZCc6J1xcdTI3MGInLFxuICAnaGFuZGJhZyc6J1xcdWQ4M2RcXHVkYzVjJyxcbiAgJ2hhbmRzaGFrZSc6J1xcdWQ4M2VcXHVkZDFkJyxcbiAgJ2hhbmtleSc6J1xcdWQ4M2RcXHVkY2E5JyxcbiAgJ2hhdGNoZWRfY2hpY2snOidcXHVkODNkXFx1ZGMyNScsXG4gICdoYXRjaGluZ19jaGljayc6J1xcdWQ4M2RcXHVkYzIzJyxcbiAgJ2hlYWRwaG9uZXMnOidcXHVkODNjXFx1ZGZhNycsXG4gICdoZWFyX25vX2V2aWwnOidcXHVkODNkXFx1ZGU0OScsXG4gICdoZWFydCc6J1xcdTI3NjRcXHVmZTBmJyxcbiAgJ2hlYXJ0X2RlY29yYXRpb24nOidcXHVkODNkXFx1ZGM5ZicsXG4gICdoZWFydF9leWVzJzonXFx1ZDgzZFxcdWRlMGQnLFxuICAnaGVhcnRfZXllc19jYXQnOidcXHVkODNkXFx1ZGUzYicsXG4gICdoZWFydGJlYXQnOidcXHVkODNkXFx1ZGM5MycsXG4gICdoZWFydHB1bHNlJzonXFx1ZDgzZFxcdWRjOTcnLFxuICAnaGVhcnRzJzonXFx1MjY2NVxcdWZlMGYnLFxuICAnaGVhdnlfY2hlY2tfbWFyayc6J1xcdTI3MTRcXHVmZTBmJyxcbiAgJ2hlYXZ5X2RpdmlzaW9uX3NpZ24nOidcXHUyNzk3JyxcbiAgJ2hlYXZ5X2RvbGxhcl9zaWduJzonXFx1ZDgzZFxcdWRjYjInLFxuICAnaGVhdnlfaGVhcnRfZXhjbGFtYXRpb24nOidcXHUyNzYzXFx1ZmUwZicsXG4gICdoZWF2eV9taW51c19zaWduJzonXFx1Mjc5NicsXG4gICdoZWF2eV9tdWx0aXBsaWNhdGlvbl94JzonXFx1MjcxNlxcdWZlMGYnLFxuICAnaGVhdnlfcGx1c19zaWduJzonXFx1Mjc5NScsXG4gICdoZWxpY29wdGVyJzonXFx1ZDgzZFxcdWRlODEnLFxuICAnaGVyYic6J1xcdWQ4M2NcXHVkZjNmJyxcbiAgJ2hpYmlzY3VzJzonXFx1ZDgzY1xcdWRmM2EnLFxuICAnaGlnaF9icmlnaHRuZXNzJzonXFx1ZDgzZFxcdWRkMDYnLFxuICAnaGlnaF9oZWVsJzonXFx1ZDgzZFxcdWRjNjAnLFxuICAnaG9jaG8nOidcXHVkODNkXFx1ZGQyYScsXG4gICdob2xlJzonXFx1ZDgzZFxcdWRkNzMnLFxuICAnaG9uZXlfcG90JzonXFx1ZDgzY1xcdWRmNmYnLFxuICAnaG9yc2UnOidcXHVkODNkXFx1ZGMzNCcsXG4gICdob3JzZV9yYWNpbmcnOidcXHVkODNjXFx1ZGZjNycsXG4gICdob3NwaXRhbCc6J1xcdWQ4M2NcXHVkZmU1JyxcbiAgJ2hvdF9wZXBwZXInOidcXHVkODNjXFx1ZGYzNicsXG4gICdob3Rkb2cnOidcXHVkODNjXFx1ZGYyZCcsXG4gICdob3RlbCc6J1xcdWQ4M2NcXHVkZmU4JyxcbiAgJ2hvdHNwcmluZ3MnOidcXHUyNjY4XFx1ZmUwZicsXG4gICdob3VyZ2xhc3MnOidcXHUyMzFiXFx1ZmUwZicsXG4gICdob3VyZ2xhc3NfZmxvd2luZ19zYW5kJzonXFx1MjNmMycsXG4gICdob3VzZSc6J1xcdWQ4M2NcXHVkZmUwJyxcbiAgJ2hvdXNlX3dpdGhfZ2FyZGVuJzonXFx1ZDgzY1xcdWRmZTEnLFxuICAnaG91c2VzJzonXFx1ZDgzY1xcdWRmZDgnLFxuICAnaHVncyc6J1xcdWQ4M2VcXHVkZDE3JyxcbiAgJ2h1c2hlZCc6J1xcdWQ4M2RcXHVkZTJmJyxcbiAgJ2ljZV9jcmVhbSc6J1xcdWQ4M2NcXHVkZjY4JyxcbiAgJ2ljZV9ob2NrZXknOidcXHVkODNjXFx1ZGZkMicsXG4gICdpY2Vfc2thdGUnOidcXHUyNmY4JyxcbiAgJ2ljZWNyZWFtJzonXFx1ZDgzY1xcdWRmNjYnLFxuICAnaWQnOidcXHVkODNjXFx1ZGQ5NCcsXG4gICdpZGVvZ3JhcGhfYWR2YW50YWdlJzonXFx1ZDgzY1xcdWRlNTAnLFxuICAnaW1wJzonXFx1ZDgzZFxcdWRjN2YnLFxuICAnaW5ib3hfdHJheSc6J1xcdWQ4M2RcXHVkY2U1JyxcbiAgJ2luY29taW5nX2VudmVsb3BlJzonXFx1ZDgzZFxcdWRjZTgnLFxuICAndGlwcGluZ19oYW5kX3dvbWFuJzonXFx1ZDgzZFxcdWRjODEnLFxuICAnaW5mb3JtYXRpb25fc291cmNlJzonXFx1MjEzOVxcdWZlMGYnLFxuICAnaW5ub2NlbnQnOidcXHVkODNkXFx1ZGUwNycsXG4gICdpbnRlcnJvYmFuZyc6J1xcdTIwNDlcXHVmZTBmJyxcbiAgJ2lwaG9uZSc6J1xcdWQ4M2RcXHVkY2YxJyxcbiAgJ2l6YWtheWFfbGFudGVybic6J1xcdWQ4M2NcXHVkZmVlJyxcbiAgJ2phY2tfb19sYW50ZXJuJzonXFx1ZDgzY1xcdWRmODMnLFxuICAnamFwYW4nOidcXHVkODNkXFx1ZGRmZScsXG4gICdqYXBhbmVzZV9jYXN0bGUnOidcXHVkODNjXFx1ZGZlZicsXG4gICdqYXBhbmVzZV9nb2JsaW4nOidcXHVkODNkXFx1ZGM3YScsXG4gICdqYXBhbmVzZV9vZ3JlJzonXFx1ZDgzZFxcdWRjNzknLFxuICAnamVhbnMnOidcXHVkODNkXFx1ZGM1NicsXG4gICdqb3knOidcXHVkODNkXFx1ZGUwMicsXG4gICdqb3lfY2F0JzonXFx1ZDgzZFxcdWRlMzknLFxuICAnam95c3RpY2snOidcXHVkODNkXFx1ZGQ3OScsXG4gICdrYWFiYSc6J1xcdWQ4M2RcXHVkZDRiJyxcbiAgJ2tleSc6J1xcdWQ4M2RcXHVkZDExJyxcbiAgJ2tleWJvYXJkJzonXFx1MjMyOFxcdWZlMGYnLFxuICAna2V5Y2FwX3Rlbic6J1xcdWQ4M2RcXHVkZDFmJyxcbiAgJ2tpY2tfc2Nvb3Rlcic6J1xcdWQ4M2RcXHVkZWY0JyxcbiAgJ2tpbW9ubyc6J1xcdWQ4M2RcXHVkYzU4JyxcbiAgJ2tpc3MnOidcXHVkODNkXFx1ZGM4YicsXG4gICdraXNzaW5nJzonXFx1ZDgzZFxcdWRlMTcnLFxuICAna2lzc2luZ19jYXQnOidcXHVkODNkXFx1ZGUzZCcsXG4gICdraXNzaW5nX2Nsb3NlZF9leWVzJzonXFx1ZDgzZFxcdWRlMWEnLFxuICAna2lzc2luZ19oZWFydCc6J1xcdWQ4M2RcXHVkZTE4JyxcbiAgJ2tpc3Npbmdfc21pbGluZ19leWVzJzonXFx1ZDgzZFxcdWRlMTknLFxuICAna2l3aV9mcnVpdCc6J1xcdWQ4M2VcXHVkZDVkJyxcbiAgJ2tvYWxhJzonXFx1ZDgzZFxcdWRjMjgnLFxuICAna29rbyc6J1xcdWQ4M2NcXHVkZTAxJyxcbiAgJ2xhYmVsJzonXFx1ZDgzY1xcdWRmZjcnLFxuICAnbGFyZ2VfYmx1ZV9jaXJjbGUnOidcXHVkODNkXFx1ZGQzNScsXG4gICdsYXJnZV9ibHVlX2RpYW1vbmQnOidcXHVkODNkXFx1ZGQzNycsXG4gICdsYXJnZV9vcmFuZ2VfZGlhbW9uZCc6J1xcdWQ4M2RcXHVkZDM2JyxcbiAgJ2xhc3RfcXVhcnRlcl9tb29uJzonXFx1ZDgzY1xcdWRmMTcnLFxuICAnbGFzdF9xdWFydGVyX21vb25fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWMnLFxuICAnbGF0aW5fY3Jvc3MnOidcXHUyNzFkXFx1ZmUwZicsXG4gICdsYXVnaGluZyc6J1xcdWQ4M2RcXHVkZTA2JyxcbiAgJ2xlYXZlcyc6J1xcdWQ4M2NcXHVkZjQzJyxcbiAgJ2xlZGdlcic6J1xcdWQ4M2RcXHVkY2QyJyxcbiAgJ2xlZnRfbHVnZ2FnZSc6J1xcdWQ4M2RcXHVkZWM1JyxcbiAgJ2xlZnRfcmlnaHRfYXJyb3cnOidcXHUyMTk0XFx1ZmUwZicsXG4gICdsZWZ0d2FyZHNfYXJyb3dfd2l0aF9ob29rJzonXFx1MjFhOVxcdWZlMGYnLFxuICAnbGVtb24nOidcXHVkODNjXFx1ZGY0YicsXG4gICdsZW8nOidcXHUyNjRjXFx1ZmUwZicsXG4gICdsZW9wYXJkJzonXFx1ZDgzZFxcdWRjMDYnLFxuICAnbGV2ZWxfc2xpZGVyJzonXFx1ZDgzY1xcdWRmOWEnLFxuICAnbGlicmEnOidcXHUyNjRlXFx1ZmUwZicsXG4gICdsaWdodF9yYWlsJzonXFx1ZDgzZFxcdWRlODgnLFxuICAnbGluayc6J1xcdWQ4M2RcXHVkZDE3JyxcbiAgJ2xpb24nOidcXHVkODNlXFx1ZGQ4MScsXG4gICdsaXBzJzonXFx1ZDgzZFxcdWRjNDQnLFxuICAnbGlwc3RpY2snOidcXHVkODNkXFx1ZGM4NCcsXG4gICdsaXphcmQnOidcXHVkODNlXFx1ZGQ4ZScsXG4gICdsb2NrJzonXFx1ZDgzZFxcdWRkMTInLFxuICAnbG9ja193aXRoX2lua19wZW4nOidcXHVkODNkXFx1ZGQwZicsXG4gICdsb2xsaXBvcCc6J1xcdWQ4M2NcXHVkZjZkJyxcbiAgJ2xvb3AnOidcXHUyN2JmJyxcbiAgJ2xvdWRfc291bmQnOidcXHVkODNkXFx1ZGQwYScsXG4gICdsb3Vkc3BlYWtlcic6J1xcdWQ4M2RcXHVkY2UyJyxcbiAgJ2xvdmVfaG90ZWwnOidcXHVkODNjXFx1ZGZlOScsXG4gICdsb3ZlX2xldHRlcic6J1xcdWQ4M2RcXHVkYzhjJyxcbiAgJ2xvd19icmlnaHRuZXNzJzonXFx1ZDgzZFxcdWRkMDUnLFxuICAnbHlpbmdfZmFjZSc6J1xcdWQ4M2VcXHVkZDI1JyxcbiAgJ20nOidcXHUyNGMyXFx1ZmUwZicsXG4gICdtYWcnOidcXHVkODNkXFx1ZGQwZCcsXG4gICdtYWdfcmlnaHQnOidcXHVkODNkXFx1ZGQwZScsXG4gICdtYWhqb25nJzonXFx1ZDgzY1xcdWRjMDRcXHVmZTBmJyxcbiAgJ21haWxib3gnOidcXHVkODNkXFx1ZGNlYicsXG4gICdtYWlsYm94X2Nsb3NlZCc6J1xcdWQ4M2RcXHVkY2VhJyxcbiAgJ21haWxib3hfd2l0aF9tYWlsJzonXFx1ZDgzZFxcdWRjZWMnLFxuICAnbWFpbGJveF93aXRoX25vX21haWwnOidcXHVkODNkXFx1ZGNlZCcsXG4gICdtYW4nOidcXHVkODNkXFx1ZGM2OCcsXG4gICdtYW5fYXJ0aXN0JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZmE4JyxcbiAgJ21hbl9hc3Ryb25hdXQnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRlODAnLFxuICAnbWFuX2NhcnR3aGVlbGluZyc6J1xcdWQ4M2VcXHVkZDM4Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fY29vayc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGY3MycsXG4gICdtYW5fZGFuY2luZyc6J1xcdWQ4M2RcXHVkZDdhJyxcbiAgJ21hbl9mYWNlcGFsbWluZyc6J1xcdWQ4M2VcXHVkZDI2Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fZmFjdG9yeV93b3JrZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzY1xcdWRmZWQnLFxuICAnbWFuX2Zhcm1lcic6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHVkODNjXFx1ZGYzZScsXG4gICdtYW5fZmlyZWZpZ2h0ZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRlOTInLFxuICAnbWFuX2hlYWx0aF93b3JrZXInOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1MjY5NVxcdWZlMGYnLFxuICAnbWFuX2luX3R1eGVkbyc6J1xcdWQ4M2VcXHVkZDM1JyxcbiAgJ21hbl9qdWRnZSc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHUyNjk2XFx1ZmUwZicsXG4gICdtYW5fanVnZ2xpbmcnOidcXHVkODNlXFx1ZGQzOSZ6d2o7XFx1MjY0MlxcdWZlMGYnLFxuICAnbWFuX21lY2hhbmljJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkZDI3JyxcbiAgJ21hbl9vZmZpY2Vfd29ya2VyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2RcXHVkY2JjJyxcbiAgJ21hbl9waWxvdCc6J1xcdWQ4M2RcXHVkYzY4Jnp3ajtcXHUyNzA4XFx1ZmUwZicsXG4gICdtYW5fcGxheWluZ19oYW5kYmFsbCc6J1xcdWQ4M2VcXHVkZDNlJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fcGxheWluZ193YXRlcl9wb2xvJzonXFx1ZDgzZVxcdWRkM2QmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21hbl9zY2llbnRpc3QnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRkMmMnLFxuICAnbWFuX3NocnVnZ2luZyc6J1xcdWQ4M2VcXHVkZDM3Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtYW5fc2luZ2VyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZmE0JyxcbiAgJ21hbl9zdHVkZW50JzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZjkzJyxcbiAgJ21hbl90ZWFjaGVyJzonXFx1ZDgzZFxcdWRjNjgmendqO1xcdWQ4M2NcXHVkZmViJyxcbiAgJ21hbl90ZWNobm9sb2dpc3QnOidcXHVkODNkXFx1ZGM2OCZ6d2o7XFx1ZDgzZFxcdWRjYmInLFxuICAnbWFuX3dpdGhfZ3VhX3BpX21hbyc6J1xcdWQ4M2RcXHVkYzcyJyxcbiAgJ21hbl93aXRoX3R1cmJhbic6J1xcdWQ4M2RcXHVkYzczJyxcbiAgJ3RhbmdlcmluZSc6J1xcdWQ4M2NcXHVkZjRhJyxcbiAgJ21hbnNfc2hvZSc6J1xcdWQ4M2RcXHVkYzVlJyxcbiAgJ21hbnRlbHBpZWNlX2Nsb2NrJzonXFx1ZDgzZFxcdWRkNzAnLFxuICAnbWFwbGVfbGVhZic6J1xcdWQ4M2NcXHVkZjQxJyxcbiAgJ21hcnRpYWxfYXJ0c191bmlmb3JtJzonXFx1ZDgzZVxcdWRkNGInLFxuICAnbWFzayc6J1xcdWQ4M2RcXHVkZTM3JyxcbiAgJ21hc3NhZ2Vfd29tYW4nOidcXHVkODNkXFx1ZGM4NicsXG4gICdtYXNzYWdlX21hbic6J1xcdWQ4M2RcXHVkYzg2Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdtZWF0X29uX2JvbmUnOidcXHVkODNjXFx1ZGY1NicsXG4gICdtZWRhbF9taWxpdGFyeSc6J1xcdWQ4M2NcXHVkZjk2JyxcbiAgJ21lZGFsX3Nwb3J0cyc6J1xcdWQ4M2NcXHVkZmM1JyxcbiAgJ21lZ2EnOidcXHVkODNkXFx1ZGNlMycsXG4gICdtZWxvbic6J1xcdWQ4M2NcXHVkZjQ4JyxcbiAgJ21lbW8nOidcXHVkODNkXFx1ZGNkZCcsXG4gICdtZW5fd3Jlc3RsaW5nJzonXFx1ZDgzZVxcdWRkM2MmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ21lbm9yYWgnOidcXHVkODNkXFx1ZGQ0ZScsXG4gICdtZW5zJzonXFx1ZDgzZFxcdWRlYjknLFxuICAnbWV0YWwnOidcXHVkODNlXFx1ZGQxOCcsXG4gICdtZXRybyc6J1xcdWQ4M2RcXHVkZTg3JyxcbiAgJ21pY3JvcGhvbmUnOidcXHVkODNjXFx1ZGZhNCcsXG4gICdtaWNyb3Njb3BlJzonXFx1ZDgzZFxcdWRkMmMnLFxuICAnbWlsa19nbGFzcyc6J1xcdWQ4M2VcXHVkZDViJyxcbiAgJ21pbGt5X3dheSc6J1xcdWQ4M2NcXHVkZjBjJyxcbiAgJ21pbmlidXMnOidcXHVkODNkXFx1ZGU5MCcsXG4gICdtaW5pZGlzYyc6J1xcdWQ4M2RcXHVkY2JkJyxcbiAgJ21vYmlsZV9waG9uZV9vZmYnOidcXHVkODNkXFx1ZGNmNCcsXG4gICdtb25leV9tb3V0aF9mYWNlJzonXFx1ZDgzZVxcdWRkMTEnLFxuICAnbW9uZXlfd2l0aF93aW5ncyc6J1xcdWQ4M2RcXHVkY2I4JyxcbiAgJ21vbmV5YmFnJzonXFx1ZDgzZFxcdWRjYjAnLFxuICAnbW9ua2V5JzonXFx1ZDgzZFxcdWRjMTInLFxuICAnbW9ua2V5X2ZhY2UnOidcXHVkODNkXFx1ZGMzNScsXG4gICdtb25vcmFpbCc6J1xcdWQ4M2RcXHVkZTlkJyxcbiAgJ21vb24nOidcXHVkODNjXFx1ZGYxNCcsXG4gICdtb3J0YXJfYm9hcmQnOidcXHVkODNjXFx1ZGY5MycsXG4gICdtb3NxdWUnOidcXHVkODNkXFx1ZGQ0YycsXG4gICdtb3Rvcl9ib2F0JzonXFx1ZDgzZFxcdWRlZTUnLFxuICAnbW90b3Jfc2Nvb3Rlcic6J1xcdWQ4M2RcXHVkZWY1JyxcbiAgJ21vdG9yY3ljbGUnOidcXHVkODNjXFx1ZGZjZCcsXG4gICdtb3RvcndheSc6J1xcdWQ4M2RcXHVkZWUzJyxcbiAgJ21vdW50X2Z1amknOidcXHVkODNkXFx1ZGRmYicsXG4gICdtb3VudGFpbic6J1xcdTI2ZjAnLFxuICAnbW91bnRhaW5fYmlraW5nX21hbic6J1xcdWQ4M2RcXHVkZWI1JyxcbiAgJ21vdW50YWluX2Jpa2luZ193b21hbic6J1xcdWQ4M2RcXHVkZWI1Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICdtb3VudGFpbl9jYWJsZXdheSc6J1xcdWQ4M2RcXHVkZWEwJyxcbiAgJ21vdW50YWluX3JhaWx3YXknOidcXHVkODNkXFx1ZGU5ZScsXG4gICdtb3VudGFpbl9zbm93JzonXFx1ZDgzY1xcdWRmZDQnLFxuICAnbW91c2UnOidcXHVkODNkXFx1ZGMyZCcsXG4gICdtb3VzZTInOidcXHVkODNkXFx1ZGMwMScsXG4gICdtb3ZpZV9jYW1lcmEnOidcXHVkODNjXFx1ZGZhNScsXG4gICdtb3lhaSc6J1xcdWQ4M2RcXHVkZGZmJyxcbiAgJ21yc19jbGF1cyc6J1xcdWQ4M2VcXHVkZDM2JyxcbiAgJ211c2NsZSc6J1xcdWQ4M2RcXHVkY2FhJyxcbiAgJ211c2hyb29tJzonXFx1ZDgzY1xcdWRmNDQnLFxuICAnbXVzaWNhbF9rZXlib2FyZCc6J1xcdWQ4M2NcXHVkZmI5JyxcbiAgJ211c2ljYWxfbm90ZSc6J1xcdWQ4M2NcXHVkZmI1JyxcbiAgJ211c2ljYWxfc2NvcmUnOidcXHVkODNjXFx1ZGZiYycsXG4gICdtdXRlJzonXFx1ZDgzZFxcdWRkMDcnLFxuICAnbmFpbF9jYXJlJzonXFx1ZDgzZFxcdWRjODUnLFxuICAnbmFtZV9iYWRnZSc6J1xcdWQ4M2RcXHVkY2RiJyxcbiAgJ25hdGlvbmFsX3BhcmsnOidcXHVkODNjXFx1ZGZkZScsXG4gICduYXVzZWF0ZWRfZmFjZSc6J1xcdWQ4M2VcXHVkZDIyJyxcbiAgJ25lY2t0aWUnOidcXHVkODNkXFx1ZGM1NCcsXG4gICduZWdhdGl2ZV9zcXVhcmVkX2Nyb3NzX21hcmsnOidcXHUyNzRlJyxcbiAgJ25lcmRfZmFjZSc6J1xcdWQ4M2VcXHVkZDEzJyxcbiAgJ25ldXRyYWxfZmFjZSc6J1xcdWQ4M2RcXHVkZTEwJyxcbiAgJ25ldyc6J1xcdWQ4M2NcXHVkZDk1JyxcbiAgJ25ld19tb29uJzonXFx1ZDgzY1xcdWRmMTEnLFxuICAnbmV3X21vb25fd2l0aF9mYWNlJzonXFx1ZDgzY1xcdWRmMWEnLFxuICAnbmV3c3BhcGVyJzonXFx1ZDgzZFxcdWRjZjAnLFxuICAnbmV3c3BhcGVyX3JvbGwnOidcXHVkODNkXFx1ZGRkZScsXG4gICduZXh0X3RyYWNrX2J1dHRvbic6J1xcdTIzZWQnLFxuICAnbmcnOidcXHVkODNjXFx1ZGQ5NicsXG4gICdub19nb29kX21hbic6J1xcdWQ4M2RcXHVkZTQ1Jnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdub19nb29kX3dvbWFuJzonXFx1ZDgzZFxcdWRlNDUnLFxuICAnbmlnaHRfd2l0aF9zdGFycyc6J1xcdWQ4M2NcXHVkZjAzJyxcbiAgJ25vX2JlbGwnOidcXHVkODNkXFx1ZGQxNScsXG4gICdub19iaWN5Y2xlcyc6J1xcdWQ4M2RcXHVkZWIzJyxcbiAgJ25vX2VudHJ5JzonXFx1MjZkNFxcdWZlMGYnLFxuICAnbm9fZW50cnlfc2lnbic6J1xcdWQ4M2RcXHVkZWFiJyxcbiAgJ25vX21vYmlsZV9waG9uZXMnOidcXHVkODNkXFx1ZGNmNScsXG4gICdub19tb3V0aCc6J1xcdWQ4M2RcXHVkZTM2JyxcbiAgJ25vX3BlZGVzdHJpYW5zJzonXFx1ZDgzZFxcdWRlYjcnLFxuICAnbm9fc21va2luZyc6J1xcdWQ4M2RcXHVkZWFkJyxcbiAgJ25vbi1wb3RhYmxlX3dhdGVyJzonXFx1ZDgzZFxcdWRlYjEnLFxuICAnbm9zZSc6J1xcdWQ4M2RcXHVkYzQzJyxcbiAgJ25vdGVib29rJzonXFx1ZDgzZFxcdWRjZDMnLFxuICAnbm90ZWJvb2tfd2l0aF9kZWNvcmF0aXZlX2NvdmVyJzonXFx1ZDgzZFxcdWRjZDQnLFxuICAnbm90ZXMnOidcXHVkODNjXFx1ZGZiNicsXG4gICdudXRfYW5kX2JvbHQnOidcXHVkODNkXFx1ZGQyOScsXG4gICdvJzonXFx1MmI1NVxcdWZlMGYnLFxuICAnbzInOidcXHVkODNjXFx1ZGQ3ZVxcdWZlMGYnLFxuICAnb2NlYW4nOidcXHVkODNjXFx1ZGYwYScsXG4gICdvY3RvcHVzJzonXFx1ZDgzZFxcdWRjMTknLFxuICAnb2Rlbic6J1xcdWQ4M2NcXHVkZjYyJyxcbiAgJ29mZmljZSc6J1xcdWQ4M2NcXHVkZmUyJyxcbiAgJ29pbF9kcnVtJzonXFx1ZDgzZFxcdWRlZTInLFxuICAnb2snOidcXHVkODNjXFx1ZGQ5NycsXG4gICdva19oYW5kJzonXFx1ZDgzZFxcdWRjNGMnLFxuICAnb2tfbWFuJzonXFx1ZDgzZFxcdWRlNDYmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ29rX3dvbWFuJzonXFx1ZDgzZFxcdWRlNDYnLFxuICAnb2xkX2tleSc6J1xcdWQ4M2RcXHVkZGRkJyxcbiAgJ29sZGVyX21hbic6J1xcdWQ4M2RcXHVkYzc0JyxcbiAgJ29sZGVyX3dvbWFuJzonXFx1ZDgzZFxcdWRjNzUnLFxuICAnb20nOidcXHVkODNkXFx1ZGQ0OScsXG4gICdvbic6J1xcdWQ4M2RcXHVkZDFiJyxcbiAgJ29uY29taW5nX2F1dG9tb2JpbGUnOidcXHVkODNkXFx1ZGU5OCcsXG4gICdvbmNvbWluZ19idXMnOidcXHVkODNkXFx1ZGU4ZCcsXG4gICdvbmNvbWluZ19wb2xpY2VfY2FyJzonXFx1ZDgzZFxcdWRlOTQnLFxuICAnb25jb21pbmdfdGF4aSc6J1xcdWQ4M2RcXHVkZTk2JyxcbiAgJ29wZW5fZmlsZV9mb2xkZXInOidcXHVkODNkXFx1ZGNjMicsXG4gICdvcGVuX2hhbmRzJzonXFx1ZDgzZFxcdWRjNTAnLFxuICAnb3Blbl9tb3V0aCc6J1xcdWQ4M2RcXHVkZTJlJyxcbiAgJ29wZW5fdW1icmVsbGEnOidcXHUyNjAyXFx1ZmUwZicsXG4gICdvcGhpdWNodXMnOidcXHUyNmNlJyxcbiAgJ29yYW5nZV9ib29rJzonXFx1ZDgzZFxcdWRjZDknLFxuICAnb3J0aG9kb3hfY3Jvc3MnOidcXHUyNjI2XFx1ZmUwZicsXG4gICdvdXRib3hfdHJheSc6J1xcdWQ4M2RcXHVkY2U0JyxcbiAgJ293bCc6J1xcdWQ4M2VcXHVkZDg5JyxcbiAgJ294JzonXFx1ZDgzZFxcdWRjMDInLFxuICAncGFja2FnZSc6J1xcdWQ4M2RcXHVkY2U2JyxcbiAgJ3BhZ2VfZmFjaW5nX3VwJzonXFx1ZDgzZFxcdWRjYzQnLFxuICAncGFnZV93aXRoX2N1cmwnOidcXHVkODNkXFx1ZGNjMycsXG4gICdwYWdlcic6J1xcdWQ4M2RcXHVkY2RmJyxcbiAgJ3BhaW50YnJ1c2gnOidcXHVkODNkXFx1ZGQ4YycsXG4gICdwYWxtX3RyZWUnOidcXHVkODNjXFx1ZGYzNCcsXG4gICdwYW5jYWtlcyc6J1xcdWQ4M2VcXHVkZDVlJyxcbiAgJ3BhbmRhX2ZhY2UnOidcXHVkODNkXFx1ZGMzYycsXG4gICdwYXBlcmNsaXAnOidcXHVkODNkXFx1ZGNjZScsXG4gICdwYXBlcmNsaXBzJzonXFx1ZDgzZFxcdWRkODcnLFxuICAncGFyYXNvbF9vbl9ncm91bmQnOidcXHUyNmYxJyxcbiAgJ3BhcmtpbmcnOidcXHVkODNjXFx1ZGQ3ZlxcdWZlMGYnLFxuICAncGFydF9hbHRlcm5hdGlvbl9tYXJrJzonXFx1MzAzZFxcdWZlMGYnLFxuICAncGFydGx5X3N1bm55JzonXFx1MjZjNVxcdWZlMGYnLFxuICAncGFzc2VuZ2VyX3NoaXAnOidcXHVkODNkXFx1ZGVmMycsXG4gICdwYXNzcG9ydF9jb250cm9sJzonXFx1ZDgzZFxcdWRlYzInLFxuICAncGF1c2VfYnV0dG9uJzonXFx1MjNmOCcsXG4gICdwZWFjZV9zeW1ib2wnOidcXHUyNjJlXFx1ZmUwZicsXG4gICdwZWFjaCc6J1xcdWQ4M2NcXHVkZjUxJyxcbiAgJ3BlYW51dHMnOidcXHVkODNlXFx1ZGQ1YycsXG4gICdwZWFyJzonXFx1ZDgzY1xcdWRmNTAnLFxuICAncGVuJzonXFx1ZDgzZFxcdWRkOGEnLFxuICAncGVuY2lsMic6J1xcdTI3MGZcXHVmZTBmJyxcbiAgJ3Blbmd1aW4nOidcXHVkODNkXFx1ZGMyNycsXG4gICdwZW5zaXZlJzonXFx1ZDgzZFxcdWRlMTQnLFxuICAncGVyZm9ybWluZ19hcnRzJzonXFx1ZDgzY1xcdWRmYWQnLFxuICAncGVyc2V2ZXJlJzonXFx1ZDgzZFxcdWRlMjMnLFxuICAncGVyc29uX2ZlbmNpbmcnOidcXHVkODNlXFx1ZGQzYScsXG4gICdwb3V0aW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlNGUnLFxuICAncGhvbmUnOidcXHUyNjBlXFx1ZmUwZicsXG4gICdwaWNrJzonXFx1MjZjZicsXG4gICdwaWcnOidcXHVkODNkXFx1ZGMzNycsXG4gICdwaWcyJzonXFx1ZDgzZFxcdWRjMTYnLFxuICAncGlnX25vc2UnOidcXHVkODNkXFx1ZGMzZCcsXG4gICdwaWxsJzonXFx1ZDgzZFxcdWRjOGEnLFxuICAncGluZWFwcGxlJzonXFx1ZDgzY1xcdWRmNGQnLFxuICAncGluZ19wb25nJzonXFx1ZDgzY1xcdWRmZDMnLFxuICAncGlzY2VzJzonXFx1MjY1M1xcdWZlMGYnLFxuICAncGl6emEnOidcXHVkODNjXFx1ZGY1NScsXG4gICdwbGFjZV9vZl93b3JzaGlwJzonXFx1ZDgzZFxcdWRlZDAnLFxuICAncGxhdGVfd2l0aF9jdXRsZXJ5JzonXFx1ZDgzY1xcdWRmN2QnLFxuICAncGxheV9vcl9wYXVzZV9idXR0b24nOidcXHUyM2VmJyxcbiAgJ3BvaW50X2Rvd24nOidcXHVkODNkXFx1ZGM0NycsXG4gICdwb2ludF9sZWZ0JzonXFx1ZDgzZFxcdWRjNDgnLFxuICAncG9pbnRfcmlnaHQnOidcXHVkODNkXFx1ZGM0OScsXG4gICdwb2ludF91cCc6J1xcdTI2MWRcXHVmZTBmJyxcbiAgJ3BvaW50X3VwXzInOidcXHVkODNkXFx1ZGM0NicsXG4gICdwb2xpY2VfY2FyJzonXFx1ZDgzZFxcdWRlOTMnLFxuICAncG9saWNld29tYW4nOidcXHVkODNkXFx1ZGM2ZSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAncG9vZGxlJzonXFx1ZDgzZFxcdWRjMjknLFxuICAncG9wY29ybic6J1xcdWQ4M2NcXHVkZjdmJyxcbiAgJ3Bvc3Rfb2ZmaWNlJzonXFx1ZDgzY1xcdWRmZTMnLFxuICAncG9zdGFsX2hvcm4nOidcXHVkODNkXFx1ZGNlZicsXG4gICdwb3N0Ym94JzonXFx1ZDgzZFxcdWRjZWUnLFxuICAncG90YWJsZV93YXRlcic6J1xcdWQ4M2RcXHVkZWIwJyxcbiAgJ3BvdGF0byc6J1xcdWQ4M2VcXHVkZDU0JyxcbiAgJ3BvdWNoJzonXFx1ZDgzZFxcdWRjNWQnLFxuICAncG91bHRyeV9sZWcnOidcXHVkODNjXFx1ZGY1NycsXG4gICdwb3VuZCc6J1xcdWQ4M2RcXHVkY2I3JyxcbiAgJ3JhZ2UnOidcXHVkODNkXFx1ZGUyMScsXG4gICdwb3V0aW5nX2NhdCc6J1xcdWQ4M2RcXHVkZTNlJyxcbiAgJ3BvdXRpbmdfbWFuJzonXFx1ZDgzZFxcdWRlNGUmendqO1xcdTI2NDJcXHVmZTBmJyxcbiAgJ3ByYXknOidcXHVkODNkXFx1ZGU0ZicsXG4gICdwcmF5ZXJfYmVhZHMnOidcXHVkODNkXFx1ZGNmZicsXG4gICdwcmVnbmFudF93b21hbic6J1xcdWQ4M2VcXHVkZDMwJyxcbiAgJ3ByZXZpb3VzX3RyYWNrX2J1dHRvbic6J1xcdTIzZWUnLFxuICAncHJpbmNlJzonXFx1ZDgzZVxcdWRkMzQnLFxuICAncHJpbmNlc3MnOidcXHVkODNkXFx1ZGM3OCcsXG4gICdwcmludGVyJzonXFx1ZDgzZFxcdWRkYTgnLFxuICAncHVycGxlX2hlYXJ0JzonXFx1ZDgzZFxcdWRjOWMnLFxuICAncHVyc2UnOidcXHVkODNkXFx1ZGM1YicsXG4gICdwdXNocGluJzonXFx1ZDgzZFxcdWRjY2MnLFxuICAncHV0X2xpdHRlcl9pbl9pdHNfcGxhY2UnOidcXHVkODNkXFx1ZGVhZScsXG4gICdxdWVzdGlvbic6J1xcdTI3NTMnLFxuICAncmFiYml0JzonXFx1ZDgzZFxcdWRjMzAnLFxuICAncmFiYml0Mic6J1xcdWQ4M2RcXHVkYzA3JyxcbiAgJ3JhY2Vob3JzZSc6J1xcdWQ4M2RcXHVkYzBlJyxcbiAgJ3JhY2luZ19jYXInOidcXHVkODNjXFx1ZGZjZScsXG4gICdyYWRpbyc6J1xcdWQ4M2RcXHVkY2ZiJyxcbiAgJ3JhZGlvX2J1dHRvbic6J1xcdWQ4M2RcXHVkZDE4JyxcbiAgJ3JhZGlvYWN0aXZlJzonXFx1MjYyMlxcdWZlMGYnLFxuICAncmFpbHdheV9jYXInOidcXHVkODNkXFx1ZGU4MycsXG4gICdyYWlsd2F5X3RyYWNrJzonXFx1ZDgzZFxcdWRlZTQnLFxuICAncmFpbmJvdyc6J1xcdWQ4M2NcXHVkZjA4JyxcbiAgJ3JhaW5ib3dfZmxhZyc6J1xcdWQ4M2NcXHVkZmYzXFx1ZmUwZiZ6d2o7XFx1ZDgzY1xcdWRmMDgnLFxuICAncmFpc2VkX2JhY2tfb2ZfaGFuZCc6J1xcdWQ4M2VcXHVkZDFhJyxcbiAgJ3JhaXNlZF9oYW5kX3dpdGhfZmluZ2Vyc19zcGxheWVkJzonXFx1ZDgzZFxcdWRkOTAnLFxuICAncmFpc2VkX2hhbmRzJzonXFx1ZDgzZFxcdWRlNGMnLFxuICAncmFpc2luZ19oYW5kX3dvbWFuJzonXFx1ZDgzZFxcdWRlNGInLFxuICAncmFpc2luZ19oYW5kX21hbic6J1xcdWQ4M2RcXHVkZTRiJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICdyYW0nOidcXHVkODNkXFx1ZGMwZicsXG4gICdyYW1lbic6J1xcdWQ4M2NcXHVkZjVjJyxcbiAgJ3JhdCc6J1xcdWQ4M2RcXHVkYzAwJyxcbiAgJ3JlY29yZF9idXR0b24nOidcXHUyM2ZhJyxcbiAgJ3JlY3ljbGUnOidcXHUyNjdiXFx1ZmUwZicsXG4gICdyZWRfY2lyY2xlJzonXFx1ZDgzZFxcdWRkMzQnLFxuICAncmVnaXN0ZXJlZCc6J1xcdTAwYWVcXHVmZTBmJyxcbiAgJ3JlbGF4ZWQnOidcXHUyNjNhXFx1ZmUwZicsXG4gICdyZWxpZXZlZCc6J1xcdWQ4M2RcXHVkZTBjJyxcbiAgJ3JlbWluZGVyX3JpYmJvbic6J1xcdWQ4M2NcXHVkZjk3JyxcbiAgJ3JlcGVhdCc6J1xcdWQ4M2RcXHVkZDAxJyxcbiAgJ3JlcGVhdF9vbmUnOidcXHVkODNkXFx1ZGQwMicsXG4gICdyZXNjdWVfd29ya2VyX2hlbG1ldCc6J1xcdTI2ZDEnLFxuICAncmVzdHJvb20nOidcXHVkODNkXFx1ZGViYicsXG4gICdyZXZvbHZpbmdfaGVhcnRzJzonXFx1ZDgzZFxcdWRjOWUnLFxuICAncmV3aW5kJzonXFx1MjNlYScsXG4gICdyaGlub2Nlcm9zJzonXFx1ZDgzZVxcdWRkOGYnLFxuICAncmliYm9uJzonXFx1ZDgzY1xcdWRmODAnLFxuICAncmljZSc6J1xcdWQ4M2NcXHVkZjVhJyxcbiAgJ3JpY2VfYmFsbCc6J1xcdWQ4M2NcXHVkZjU5JyxcbiAgJ3JpY2VfY3JhY2tlcic6J1xcdWQ4M2NcXHVkZjU4JyxcbiAgJ3JpY2Vfc2NlbmUnOidcXHVkODNjXFx1ZGY5MScsXG4gICdyaWdodF9hbmdlcl9idWJibGUnOidcXHVkODNkXFx1ZGRlZicsXG4gICdyaW5nJzonXFx1ZDgzZFxcdWRjOGQnLFxuICAncm9ib3QnOidcXHVkODNlXFx1ZGQxNicsXG4gICdyb2NrZXQnOidcXHVkODNkXFx1ZGU4MCcsXG4gICdyb2ZsJzonXFx1ZDgzZVxcdWRkMjMnLFxuICAncm9sbF9leWVzJzonXFx1ZDgzZFxcdWRlNDQnLFxuICAncm9sbGVyX2NvYXN0ZXInOidcXHVkODNjXFx1ZGZhMicsXG4gICdyb29zdGVyJzonXFx1ZDgzZFxcdWRjMTMnLFxuICAncm9zZSc6J1xcdWQ4M2NcXHVkZjM5JyxcbiAgJ3Jvc2V0dGUnOidcXHVkODNjXFx1ZGZmNScsXG4gICdyb3RhdGluZ19saWdodCc6J1xcdWQ4M2RcXHVkZWE4JyxcbiAgJ3JvdW5kX3B1c2hwaW4nOidcXHVkODNkXFx1ZGNjZCcsXG4gICdyb3dpbmdfbWFuJzonXFx1ZDgzZFxcdWRlYTMnLFxuICAncm93aW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlYTMmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3J1Z2J5X2Zvb3RiYWxsJzonXFx1ZDgzY1xcdWRmYzknLFxuICAncnVubmluZ19tYW4nOidcXHVkODNjXFx1ZGZjMycsXG4gICdydW5uaW5nX3NoaXJ0X3dpdGhfc2FzaCc6J1xcdWQ4M2NcXHVkZmJkJyxcbiAgJ3J1bm5pbmdfd29tYW4nOidcXHVkODNjXFx1ZGZjMyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnc2EnOidcXHVkODNjXFx1ZGUwMlxcdWZlMGYnLFxuICAnc2FnaXR0YXJpdXMnOidcXHUyNjUwXFx1ZmUwZicsXG4gICdzYWtlJzonXFx1ZDgzY1xcdWRmNzYnLFxuICAnc2FuZGFsJzonXFx1ZDgzZFxcdWRjNjEnLFxuICAnc2FudGEnOidcXHVkODNjXFx1ZGY4NScsXG4gICdzYXRlbGxpdGUnOidcXHVkODNkXFx1ZGNlMScsXG4gICdzYXhvcGhvbmUnOidcXHVkODNjXFx1ZGZiNycsXG4gICdzY2hvb2wnOidcXHVkODNjXFx1ZGZlYicsXG4gICdzY2hvb2xfc2F0Y2hlbCc6J1xcdWQ4M2NcXHVkZjkyJyxcbiAgJ3NjaXNzb3JzJzonXFx1MjcwMlxcdWZlMGYnLFxuICAnc2NvcnBpb24nOidcXHVkODNlXFx1ZGQ4MicsXG4gICdzY29ycGl1cyc6J1xcdTI2NGZcXHVmZTBmJyxcbiAgJ3NjcmVhbSc6J1xcdWQ4M2RcXHVkZTMxJyxcbiAgJ3NjcmVhbV9jYXQnOidcXHVkODNkXFx1ZGU0MCcsXG4gICdzY3JvbGwnOidcXHVkODNkXFx1ZGNkYycsXG4gICdzZWF0JzonXFx1ZDgzZFxcdWRjYmEnLFxuICAnc2VjcmV0JzonXFx1MzI5OVxcdWZlMGYnLFxuICAnc2VlX25vX2V2aWwnOidcXHVkODNkXFx1ZGU0OCcsXG4gICdzZWVkbGluZyc6J1xcdWQ4M2NcXHVkZjMxJyxcbiAgJ3NlbGZpZSc6J1xcdWQ4M2VcXHVkZDMzJyxcbiAgJ3NoYWxsb3dfcGFuX29mX2Zvb2QnOidcXHVkODNlXFx1ZGQ1OCcsXG4gICdzaGFtcm9jayc6J1xcdTI2MThcXHVmZTBmJyxcbiAgJ3NoYXJrJzonXFx1ZDgzZVxcdWRkODgnLFxuICAnc2hhdmVkX2ljZSc6J1xcdWQ4M2NcXHVkZjY3JyxcbiAgJ3NoZWVwJzonXFx1ZDgzZFxcdWRjMTEnLFxuICAnc2hlbGwnOidcXHVkODNkXFx1ZGMxYScsXG4gICdzaGllbGQnOidcXHVkODNkXFx1ZGVlMScsXG4gICdzaGludG9fc2hyaW5lJzonXFx1MjZlOScsXG4gICdzaGlwJzonXFx1ZDgzZFxcdWRlYTInLFxuICAnc2hpcnQnOidcXHVkODNkXFx1ZGM1NScsXG4gICdzaG9wcGluZyc6J1xcdWQ4M2RcXHVkZWNkJyxcbiAgJ3Nob3BwaW5nX2NhcnQnOidcXHVkODNkXFx1ZGVkMicsXG4gICdzaG93ZXInOidcXHVkODNkXFx1ZGViZicsXG4gICdzaHJpbXAnOidcXHVkODNlXFx1ZGQ5MCcsXG4gICdzaWduYWxfc3RyZW5ndGgnOidcXHVkODNkXFx1ZGNmNicsXG4gICdzaXhfcG9pbnRlZF9zdGFyJzonXFx1ZDgzZFxcdWRkMmYnLFxuICAnc2tpJzonXFx1ZDgzY1xcdWRmYmYnLFxuICAnc2tpZXInOidcXHUyNmY3JyxcbiAgJ3NrdWxsJzonXFx1ZDgzZFxcdWRjODAnLFxuICAnc2t1bGxfYW5kX2Nyb3NzYm9uZXMnOidcXHUyNjIwXFx1ZmUwZicsXG4gICdzbGVlcGluZyc6J1xcdWQ4M2RcXHVkZTM0JyxcbiAgJ3NsZWVwaW5nX2JlZCc6J1xcdWQ4M2RcXHVkZWNjJyxcbiAgJ3NsZWVweSc6J1xcdWQ4M2RcXHVkZTJhJyxcbiAgJ3NsaWdodGx5X2Zyb3duaW5nX2ZhY2UnOidcXHVkODNkXFx1ZGU0MScsXG4gICdzbGlnaHRseV9zbWlsaW5nX2ZhY2UnOidcXHVkODNkXFx1ZGU0MicsXG4gICdzbG90X21hY2hpbmUnOidcXHVkODNjXFx1ZGZiMCcsXG4gICdzbWFsbF9haXJwbGFuZSc6J1xcdWQ4M2RcXHVkZWU5JyxcbiAgJ3NtYWxsX2JsdWVfZGlhbW9uZCc6J1xcdWQ4M2RcXHVkZDM5JyxcbiAgJ3NtYWxsX29yYW5nZV9kaWFtb25kJzonXFx1ZDgzZFxcdWRkMzgnLFxuICAnc21hbGxfcmVkX3RyaWFuZ2xlJzonXFx1ZDgzZFxcdWRkM2EnLFxuICAnc21hbGxfcmVkX3RyaWFuZ2xlX2Rvd24nOidcXHVkODNkXFx1ZGQzYicsXG4gICdzbWlsZSc6J1xcdWQ4M2RcXHVkZTA0JyxcbiAgJ3NtaWxlX2NhdCc6J1xcdWQ4M2RcXHVkZTM4JyxcbiAgJ3NtaWxleSc6J1xcdWQ4M2RcXHVkZTAzJyxcbiAgJ3NtaWxleV9jYXQnOidcXHVkODNkXFx1ZGUzYScsXG4gICdzbWlsaW5nX2ltcCc6J1xcdWQ4M2RcXHVkZTA4JyxcbiAgJ3NtaXJrJzonXFx1ZDgzZFxcdWRlMGYnLFxuICAnc21pcmtfY2F0JzonXFx1ZDgzZFxcdWRlM2MnLFxuICAnc21va2luZyc6J1xcdWQ4M2RcXHVkZWFjJyxcbiAgJ3NuYWlsJzonXFx1ZDgzZFxcdWRjMGMnLFxuICAnc25ha2UnOidcXHVkODNkXFx1ZGMwZCcsXG4gICdzbmVlemluZ19mYWNlJzonXFx1ZDgzZVxcdWRkMjcnLFxuICAnc25vd2JvYXJkZXInOidcXHVkODNjXFx1ZGZjMicsXG4gICdzbm93Zmxha2UnOidcXHUyNzQ0XFx1ZmUwZicsXG4gICdzbm93bWFuJzonXFx1MjZjNFxcdWZlMGYnLFxuICAnc25vd21hbl93aXRoX3Nub3cnOidcXHUyNjAzXFx1ZmUwZicsXG4gICdzb2InOidcXHVkODNkXFx1ZGUyZCcsXG4gICdzb2NjZXInOidcXHUyNmJkXFx1ZmUwZicsXG4gICdzb29uJzonXFx1ZDgzZFxcdWRkMWMnLFxuICAnc29zJzonXFx1ZDgzY1xcdWRkOTgnLFxuICAnc291bmQnOidcXHVkODNkXFx1ZGQwOScsXG4gICdzcGFjZV9pbnZhZGVyJzonXFx1ZDgzZFxcdWRjN2UnLFxuICAnc3BhZGVzJzonXFx1MjY2MFxcdWZlMGYnLFxuICAnc3BhZ2hldHRpJzonXFx1ZDgzY1xcdWRmNWQnLFxuICAnc3BhcmtsZSc6J1xcdTI3NDdcXHVmZTBmJyxcbiAgJ3NwYXJrbGVyJzonXFx1ZDgzY1xcdWRmODcnLFxuICAnc3BhcmtsZXMnOidcXHUyNzI4JyxcbiAgJ3NwYXJrbGluZ19oZWFydCc6J1xcdWQ4M2RcXHVkYzk2JyxcbiAgJ3NwZWFrX25vX2V2aWwnOidcXHVkODNkXFx1ZGU0YScsXG4gICdzcGVha2VyJzonXFx1ZDgzZFxcdWRkMDgnLFxuICAnc3BlYWtpbmdfaGVhZCc6J1xcdWQ4M2RcXHVkZGUzJyxcbiAgJ3NwZWVjaF9iYWxsb29uJzonXFx1ZDgzZFxcdWRjYWMnLFxuICAnc3BlZWRib2F0JzonXFx1ZDgzZFxcdWRlYTQnLFxuICAnc3BpZGVyJzonXFx1ZDgzZFxcdWRkNzcnLFxuICAnc3BpZGVyX3dlYic6J1xcdWQ4M2RcXHVkZDc4JyxcbiAgJ3NwaXJhbF9jYWxlbmRhcic6J1xcdWQ4M2RcXHVkZGQzJyxcbiAgJ3NwaXJhbF9ub3RlcGFkJzonXFx1ZDgzZFxcdWRkZDInLFxuICAnc3Bvb24nOidcXHVkODNlXFx1ZGQ0NCcsXG4gICdzcXVpZCc6J1xcdWQ4M2VcXHVkZDkxJyxcbiAgJ3N0YWRpdW0nOidcXHVkODNjXFx1ZGZkZicsXG4gICdzdGFyJzonXFx1MmI1MFxcdWZlMGYnLFxuICAnc3RhcjInOidcXHVkODNjXFx1ZGYxZicsXG4gICdzdGFyX2FuZF9jcmVzY2VudCc6J1xcdTI2MmFcXHVmZTBmJyxcbiAgJ3N0YXJfb2ZfZGF2aWQnOidcXHUyNzIxXFx1ZmUwZicsXG4gICdzdGFycyc6J1xcdWQ4M2NcXHVkZjIwJyxcbiAgJ3N0YXRpb24nOidcXHVkODNkXFx1ZGU4OScsXG4gICdzdGF0dWVfb2ZfbGliZXJ0eSc6J1xcdWQ4M2RcXHVkZGZkJyxcbiAgJ3N0ZWFtX2xvY29tb3RpdmUnOidcXHVkODNkXFx1ZGU4MicsXG4gICdzdGV3JzonXFx1ZDgzY1xcdWRmNzInLFxuICAnc3RvcF9idXR0b24nOidcXHUyM2Y5JyxcbiAgJ3N0b3Bfc2lnbic6J1xcdWQ4M2RcXHVkZWQxJyxcbiAgJ3N0b3B3YXRjaCc6J1xcdTIzZjEnLFxuICAnc3RyYWlnaHRfcnVsZXInOidcXHVkODNkXFx1ZGNjZicsXG4gICdzdHJhd2JlcnJ5JzonXFx1ZDgzY1xcdWRmNTMnLFxuICAnc3R1Y2tfb3V0X3Rvbmd1ZSc6J1xcdWQ4M2RcXHVkZTFiJyxcbiAgJ3N0dWNrX291dF90b25ndWVfY2xvc2VkX2V5ZXMnOidcXHVkODNkXFx1ZGUxZCcsXG4gICdzdHVja19vdXRfdG9uZ3VlX3dpbmtpbmdfZXllJzonXFx1ZDgzZFxcdWRlMWMnLFxuICAnc3R1ZGlvX21pY3JvcGhvbmUnOidcXHVkODNjXFx1ZGY5OScsXG4gICdzdHVmZmVkX2ZsYXRicmVhZCc6J1xcdWQ4M2VcXHVkZDU5JyxcbiAgJ3N1bl9iZWhpbmRfbGFyZ2VfY2xvdWQnOidcXHVkODNjXFx1ZGYyNScsXG4gICdzdW5fYmVoaW5kX3JhaW5fY2xvdWQnOidcXHVkODNjXFx1ZGYyNicsXG4gICdzdW5fYmVoaW5kX3NtYWxsX2Nsb3VkJzonXFx1ZDgzY1xcdWRmMjQnLFxuICAnc3VuX3dpdGhfZmFjZSc6J1xcdWQ4M2NcXHVkZjFlJyxcbiAgJ3N1bmZsb3dlcic6J1xcdWQ4M2NcXHVkZjNiJyxcbiAgJ3N1bmdsYXNzZXMnOidcXHVkODNkXFx1ZGUwZScsXG4gICdzdW5ueSc6J1xcdTI2MDBcXHVmZTBmJyxcbiAgJ3N1bnJpc2UnOidcXHVkODNjXFx1ZGYwNScsXG4gICdzdW5yaXNlX292ZXJfbW91bnRhaW5zJzonXFx1ZDgzY1xcdWRmMDQnLFxuICAnc3VyZmluZ19tYW4nOidcXHVkODNjXFx1ZGZjNCcsXG4gICdzdXJmaW5nX3dvbWFuJzonXFx1ZDgzY1xcdWRmYzQmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3N1c2hpJzonXFx1ZDgzY1xcdWRmNjMnLFxuICAnc3VzcGVuc2lvbl9yYWlsd2F5JzonXFx1ZDgzZFxcdWRlOWYnLFxuICAnc3dlYXQnOidcXHVkODNkXFx1ZGUxMycsXG4gICdzd2VhdF9kcm9wcyc6J1xcdWQ4M2RcXHVkY2E2JyxcbiAgJ3N3ZWF0X3NtaWxlJzonXFx1ZDgzZFxcdWRlMDUnLFxuICAnc3dlZXRfcG90YXRvJzonXFx1ZDgzY1xcdWRmNjAnLFxuICAnc3dpbW1pbmdfbWFuJzonXFx1ZDgzY1xcdWRmY2EnLFxuICAnc3dpbW1pbmdfd29tYW4nOidcXHVkODNjXFx1ZGZjYSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnc3ltYm9scyc6J1xcdWQ4M2RcXHVkZDIzJyxcbiAgJ3N5bmFnb2d1ZSc6J1xcdWQ4M2RcXHVkZDRkJyxcbiAgJ3N5cmluZ2UnOidcXHVkODNkXFx1ZGM4OScsXG4gICd0YWNvJzonXFx1ZDgzY1xcdWRmMmUnLFxuICAndGFkYSc6J1xcdWQ4M2NcXHVkZjg5JyxcbiAgJ3RhbmFiYXRhX3RyZWUnOidcXHVkODNjXFx1ZGY4YicsXG4gICd0YXVydXMnOidcXHUyNjQ5XFx1ZmUwZicsXG4gICd0YXhpJzonXFx1ZDgzZFxcdWRlOTUnLFxuICAndGVhJzonXFx1ZDgzY1xcdWRmNzUnLFxuICAndGVsZXBob25lX3JlY2VpdmVyJzonXFx1ZDgzZFxcdWRjZGUnLFxuICAndGVsZXNjb3BlJzonXFx1ZDgzZFxcdWRkMmQnLFxuICAndGVubmlzJzonXFx1ZDgzY1xcdWRmYmUnLFxuICAndGVudCc6J1xcdTI2ZmFcXHVmZTBmJyxcbiAgJ3RoZXJtb21ldGVyJzonXFx1ZDgzY1xcdWRmMjEnLFxuICAndGhpbmtpbmcnOidcXHVkODNlXFx1ZGQxNCcsXG4gICd0aG91Z2h0X2JhbGxvb24nOidcXHVkODNkXFx1ZGNhZCcsXG4gICd0aWNrZXQnOidcXHVkODNjXFx1ZGZhYicsXG4gICd0aWNrZXRzJzonXFx1ZDgzY1xcdWRmOWYnLFxuICAndGlnZXInOidcXHVkODNkXFx1ZGMyZicsXG4gICd0aWdlcjInOidcXHVkODNkXFx1ZGMwNScsXG4gICd0aW1lcl9jbG9jayc6J1xcdTIzZjInLFxuICAndGlwcGluZ19oYW5kX21hbic6J1xcdWQ4M2RcXHVkYzgxJnp3ajtcXHUyNjQyXFx1ZmUwZicsXG4gICd0aXJlZF9mYWNlJzonXFx1ZDgzZFxcdWRlMmInLFxuICAndG0nOidcXHUyMTIyXFx1ZmUwZicsXG4gICd0b2lsZXQnOidcXHVkODNkXFx1ZGViZCcsXG4gICd0b2t5b190b3dlcic6J1xcdWQ4M2RcXHVkZGZjJyxcbiAgJ3RvbWF0byc6J1xcdWQ4M2NcXHVkZjQ1JyxcbiAgJ3Rvbmd1ZSc6J1xcdWQ4M2RcXHVkYzQ1JyxcbiAgJ3RvcCc6J1xcdWQ4M2RcXHVkZDFkJyxcbiAgJ3RvcGhhdCc6J1xcdWQ4M2NcXHVkZmE5JyxcbiAgJ3Rvcm5hZG8nOidcXHVkODNjXFx1ZGYyYScsXG4gICd0cmFja2JhbGwnOidcXHVkODNkXFx1ZGRiMicsXG4gICd0cmFjdG9yJzonXFx1ZDgzZFxcdWRlOWMnLFxuICAndHJhZmZpY19saWdodCc6J1xcdWQ4M2RcXHVkZWE1JyxcbiAgJ3RyYWluJzonXFx1ZDgzZFxcdWRlOGInLFxuICAndHJhaW4yJzonXFx1ZDgzZFxcdWRlODYnLFxuICAndHJhbSc6J1xcdWQ4M2RcXHVkZThhJyxcbiAgJ3RyaWFuZ3VsYXJfZmxhZ19vbl9wb3N0JzonXFx1ZDgzZFxcdWRlYTknLFxuICAndHJpYW5ndWxhcl9ydWxlcic6J1xcdWQ4M2RcXHVkY2QwJyxcbiAgJ3RyaWRlbnQnOidcXHVkODNkXFx1ZGQzMScsXG4gICd0cml1bXBoJzonXFx1ZDgzZFxcdWRlMjQnLFxuICAndHJvbGxleWJ1cyc6J1xcdWQ4M2RcXHVkZThlJyxcbiAgJ3Ryb3BoeSc6J1xcdWQ4M2NcXHVkZmM2JyxcbiAgJ3Ryb3BpY2FsX2RyaW5rJzonXFx1ZDgzY1xcdWRmNzknLFxuICAndHJvcGljYWxfZmlzaCc6J1xcdWQ4M2RcXHVkYzIwJyxcbiAgJ3RydWNrJzonXFx1ZDgzZFxcdWRlOWEnLFxuICAndHJ1bXBldCc6J1xcdWQ4M2NcXHVkZmJhJyxcbiAgJ3R1bGlwJzonXFx1ZDgzY1xcdWRmMzcnLFxuICAndHVtYmxlcl9nbGFzcyc6J1xcdWQ4M2VcXHVkZDQzJyxcbiAgJ3R1cmtleSc6J1xcdWQ4M2VcXHVkZDgzJyxcbiAgJ3R1cnRsZSc6J1xcdWQ4M2RcXHVkYzIyJyxcbiAgJ3R2JzonXFx1ZDgzZFxcdWRjZmEnLFxuICAndHdpc3RlZF9yaWdodHdhcmRzX2Fycm93cyc6J1xcdWQ4M2RcXHVkZDAwJyxcbiAgJ3R3b19oZWFydHMnOidcXHVkODNkXFx1ZGM5NScsXG4gICd0d29fbWVuX2hvbGRpbmdfaGFuZHMnOidcXHVkODNkXFx1ZGM2YycsXG4gICd0d29fd29tZW5faG9sZGluZ19oYW5kcyc6J1xcdWQ4M2RcXHVkYzZkJyxcbiAgJ3U1MjcyJzonXFx1ZDgzY1xcdWRlMzknLFxuICAndTU0MDgnOidcXHVkODNjXFx1ZGUzNCcsXG4gICd1NTViNic6J1xcdWQ4M2NcXHVkZTNhJyxcbiAgJ3U2MzA3JzonXFx1ZDgzY1xcdWRlMmZcXHVmZTBmJyxcbiAgJ3U2NzA4JzonXFx1ZDgzY1xcdWRlMzdcXHVmZTBmJyxcbiAgJ3U2NzA5JzonXFx1ZDgzY1xcdWRlMzYnLFxuICAndTZlODAnOidcXHVkODNjXFx1ZGUzNScsXG4gICd1NzEyMSc6J1xcdWQ4M2NcXHVkZTFhXFx1ZmUwZicsXG4gICd1NzUzMyc6J1xcdWQ4M2NcXHVkZTM4JyxcbiAgJ3U3OTgxJzonXFx1ZDgzY1xcdWRlMzInLFxuICAndTdhN2EnOidcXHVkODNjXFx1ZGUzMycsXG4gICd1bWJyZWxsYSc6J1xcdTI2MTRcXHVmZTBmJyxcbiAgJ3VuYW11c2VkJzonXFx1ZDgzZFxcdWRlMTInLFxuICAndW5kZXJhZ2UnOidcXHVkODNkXFx1ZGQxZScsXG4gICd1bmljb3JuJzonXFx1ZDgzZVxcdWRkODQnLFxuICAndW5sb2NrJzonXFx1ZDgzZFxcdWRkMTMnLFxuICAndXAnOidcXHVkODNjXFx1ZGQ5OScsXG4gICd1cHNpZGVfZG93bl9mYWNlJzonXFx1ZDgzZFxcdWRlNDMnLFxuICAndic6J1xcdTI3MGNcXHVmZTBmJyxcbiAgJ3ZlcnRpY2FsX3RyYWZmaWNfbGlnaHQnOidcXHVkODNkXFx1ZGVhNicsXG4gICd2aHMnOidcXHVkODNkXFx1ZGNmYycsXG4gICd2aWJyYXRpb25fbW9kZSc6J1xcdWQ4M2RcXHVkY2YzJyxcbiAgJ3ZpZGVvX2NhbWVyYSc6J1xcdWQ4M2RcXHVkY2Y5JyxcbiAgJ3ZpZGVvX2dhbWUnOidcXHVkODNjXFx1ZGZhZScsXG4gICd2aW9saW4nOidcXHVkODNjXFx1ZGZiYicsXG4gICd2aXJnbyc6J1xcdTI2NGRcXHVmZTBmJyxcbiAgJ3ZvbGNhbm8nOidcXHVkODNjXFx1ZGYwYicsXG4gICd2b2xsZXliYWxsJzonXFx1ZDgzY1xcdWRmZDAnLFxuICAndnMnOidcXHVkODNjXFx1ZGQ5YScsXG4gICd2dWxjYW5fc2FsdXRlJzonXFx1ZDgzZFxcdWRkOTYnLFxuICAnd2Fsa2luZ19tYW4nOidcXHVkODNkXFx1ZGViNicsXG4gICd3YWxraW5nX3dvbWFuJzonXFx1ZDgzZFxcdWRlYjYmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dhbmluZ19jcmVzY2VudF9tb29uJzonXFx1ZDgzY1xcdWRmMTgnLFxuICAnd2FuaW5nX2dpYmJvdXNfbW9vbic6J1xcdWQ4M2NcXHVkZjE2JyxcbiAgJ3dhcm5pbmcnOidcXHUyNmEwXFx1ZmUwZicsXG4gICd3YXN0ZWJhc2tldCc6J1xcdWQ4M2RcXHVkZGQxJyxcbiAgJ3dhdGNoJzonXFx1MjMxYVxcdWZlMGYnLFxuICAnd2F0ZXJfYnVmZmFsbyc6J1xcdWQ4M2RcXHVkYzAzJyxcbiAgJ3dhdGVybWVsb24nOidcXHVkODNjXFx1ZGY0OScsXG4gICd3YXZlJzonXFx1ZDgzZFxcdWRjNGInLFxuICAnd2F2eV9kYXNoJzonXFx1MzAzMFxcdWZlMGYnLFxuICAnd2F4aW5nX2NyZXNjZW50X21vb24nOidcXHVkODNjXFx1ZGYxMicsXG4gICd3Yyc6J1xcdWQ4M2RcXHVkZWJlJyxcbiAgJ3dlYXJ5JzonXFx1ZDgzZFxcdWRlMjknLFxuICAnd2VkZGluZyc6J1xcdWQ4M2RcXHVkYzkyJyxcbiAgJ3dlaWdodF9saWZ0aW5nX21hbic6J1xcdWQ4M2NcXHVkZmNiXFx1ZmUwZicsXG4gICd3ZWlnaHRfbGlmdGluZ193b21hbic6J1xcdWQ4M2NcXHVkZmNiXFx1ZmUwZiZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd2hhbGUnOidcXHVkODNkXFx1ZGMzMycsXG4gICd3aGFsZTInOidcXHVkODNkXFx1ZGMwYicsXG4gICd3aGVlbF9vZl9kaGFybWEnOidcXHUyNjM4XFx1ZmUwZicsXG4gICd3aGVlbGNoYWlyJzonXFx1MjY3ZlxcdWZlMGYnLFxuICAnd2hpdGVfY2hlY2tfbWFyayc6J1xcdTI3MDUnLFxuICAnd2hpdGVfY2lyY2xlJzonXFx1MjZhYVxcdWZlMGYnLFxuICAnd2hpdGVfZmxhZyc6J1xcdWQ4M2NcXHVkZmYzXFx1ZmUwZicsXG4gICd3aGl0ZV9mbG93ZXInOidcXHVkODNkXFx1ZGNhZScsXG4gICd3aGl0ZV9sYXJnZV9zcXVhcmUnOidcXHUyYjFjXFx1ZmUwZicsXG4gICd3aGl0ZV9tZWRpdW1fc21hbGxfc3F1YXJlJzonXFx1MjVmZFxcdWZlMGYnLFxuICAnd2hpdGVfbWVkaXVtX3NxdWFyZSc6J1xcdTI1ZmJcXHVmZTBmJyxcbiAgJ3doaXRlX3NtYWxsX3NxdWFyZSc6J1xcdTI1YWJcXHVmZTBmJyxcbiAgJ3doaXRlX3NxdWFyZV9idXR0b24nOidcXHVkODNkXFx1ZGQzMycsXG4gICd3aWx0ZWRfZmxvd2VyJzonXFx1ZDgzZVxcdWRkNDAnLFxuICAnd2luZF9jaGltZSc6J1xcdWQ4M2NcXHVkZjkwJyxcbiAgJ3dpbmRfZmFjZSc6J1xcdWQ4M2NcXHVkZjJjJyxcbiAgJ3dpbmVfZ2xhc3MnOidcXHVkODNjXFx1ZGY3NycsXG4gICd3aW5rJzonXFx1ZDgzZFxcdWRlMDknLFxuICAnd29sZic6J1xcdWQ4M2RcXHVkYzNhJyxcbiAgJ3dvbWFuJzonXFx1ZDgzZFxcdWRjNjknLFxuICAnd29tYW5fYXJ0aXN0JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZmE4JyxcbiAgJ3dvbWFuX2FzdHJvbmF1dCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGU4MCcsXG4gICd3b21hbl9jYXJ0d2hlZWxpbmcnOidcXHVkODNlXFx1ZGQzOCZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fY29vayc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGY3MycsXG4gICd3b21hbl9mYWNlcGFsbWluZyc6J1xcdWQ4M2VcXHVkZDI2Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbl9mYWN0b3J5X3dvcmtlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGZlZCcsXG4gICd3b21hbl9mYXJtZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmM2UnLFxuICAnd29tYW5fZmlyZWZpZ2h0ZXInOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRlOTInLFxuICAnd29tYW5faGVhbHRoX3dvcmtlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHUyNjk1XFx1ZmUwZicsXG4gICd3b21hbl9qdWRnZSc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHUyNjk2XFx1ZmUwZicsXG4gICd3b21hbl9qdWdnbGluZyc6J1xcdWQ4M2VcXHVkZDM5Jnp3ajtcXHUyNjQwXFx1ZmUwZicsXG4gICd3b21hbl9tZWNoYW5pYyc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGQyNycsXG4gICd3b21hbl9vZmZpY2Vfd29ya2VyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2RcXHVkY2JjJyxcbiAgJ3dvbWFuX3BpbG90JzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdTI3MDhcXHVmZTBmJyxcbiAgJ3dvbWFuX3BsYXlpbmdfaGFuZGJhbGwnOidcXHVkODNlXFx1ZGQzZSZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fcGxheWluZ193YXRlcl9wb2xvJzonXFx1ZDgzZVxcdWRkM2QmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWFuX3NjaWVudGlzdCc6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNkXFx1ZGQyYycsXG4gICd3b21hbl9zaHJ1Z2dpbmcnOidcXHVkODNlXFx1ZGQzNyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5fc2luZ2VyJzonXFx1ZDgzZFxcdWRjNjkmendqO1xcdWQ4M2NcXHVkZmE0JyxcbiAgJ3dvbWFuX3N0dWRlbnQnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzY1xcdWRmOTMnLFxuICAnd29tYW5fdGVhY2hlcic6J1xcdWQ4M2RcXHVkYzY5Jnp3ajtcXHVkODNjXFx1ZGZlYicsXG4gICd3b21hbl90ZWNobm9sb2dpc3QnOidcXHVkODNkXFx1ZGM2OSZ6d2o7XFx1ZDgzZFxcdWRjYmInLFxuICAnd29tYW5fd2l0aF90dXJiYW4nOidcXHVkODNkXFx1ZGM3MyZ6d2o7XFx1MjY0MFxcdWZlMGYnLFxuICAnd29tYW5zX2Nsb3RoZXMnOidcXHVkODNkXFx1ZGM1YScsXG4gICd3b21hbnNfaGF0JzonXFx1ZDgzZFxcdWRjNTInLFxuICAnd29tZW5fd3Jlc3RsaW5nJzonXFx1ZDgzZVxcdWRkM2MmendqO1xcdTI2NDBcXHVmZTBmJyxcbiAgJ3dvbWVucyc6J1xcdWQ4M2RcXHVkZWJhJyxcbiAgJ3dvcmxkX21hcCc6J1xcdWQ4M2RcXHVkZGZhJyxcbiAgJ3dvcnJpZWQnOidcXHVkODNkXFx1ZGUxZicsXG4gICd3cmVuY2gnOidcXHVkODNkXFx1ZGQyNycsXG4gICd3cml0aW5nX2hhbmQnOidcXHUyNzBkXFx1ZmUwZicsXG4gICd4JzonXFx1Mjc0YycsXG4gICd5ZWxsb3dfaGVhcnQnOidcXHVkODNkXFx1ZGM5YicsXG4gICd5ZW4nOidcXHVkODNkXFx1ZGNiNCcsXG4gICd5aW5feWFuZyc6J1xcdTI2MmZcXHVmZTBmJyxcbiAgJ3l1bSc6J1xcdWQ4M2RcXHVkZTBiJyxcbiAgJ3phcCc6J1xcdTI2YTFcXHVmZTBmJyxcbiAgJ3ppcHBlcl9tb3V0aF9mYWNlJzonXFx1ZDgzZVxcdWRkMTAnLFxuICAnenp6JzonXFx1ZDgzZFxcdWRjYTQnLFxuXG4gIC8qIHNwZWNpYWwgZW1vamlzIDpQICovXG4gICdvY3RvY2F0JzogICc8aW1nIGFsdD1cIjpvY3RvY2F0OlwiIGhlaWdodD1cIjIwXCIgd2lkdGg9XCIyMFwiIGFsaWduPVwiYWJzbWlkZGxlXCIgc3JjPVwiaHR0cHM6Ly9hc3NldHMtY2RuLmdpdGh1Yi5jb20vaW1hZ2VzL2ljb25zL2Vtb2ppL29jdG9jYXQucG5nXCI+JyxcbiAgJ3Nob3dkb3duJzogJzxzcGFuIHN0eWxlPVwiZm9udC1mYW1pbHk6IFxcJ0Fub255bW91cyBQcm9cXCcsIG1vbm9zcGFjZTsgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7IHRleHQtZGVjb3JhdGlvbi1zdHlsZTogZGFzaGVkOyB0ZXh0LWRlY29yYXRpb24tY29sb3I6ICMzZThiOGE7dGV4dC11bmRlcmxpbmUtcG9zaXRpb246IHVuZGVyO1wiPlM8L3NwYW4+J1xufTtcblxyXG4vKipcbiAqIENyZWF0ZWQgYnkgRXN0ZXZhbyBvbiAzMS0wNS0yMDE1LlxuICovXG5cbi8qKlxuICogU2hvd2Rvd24gQ29udmVydGVyIGNsYXNzXG4gKiBAY2xhc3NcbiAqIEBwYXJhbSB7b2JqZWN0fSBbY29udmVydGVyT3B0aW9uc11cbiAqIEByZXR1cm5zIHtDb252ZXJ0ZXJ9XG4gKi9cbnNob3dkb3duLkNvbnZlcnRlciA9IGZ1bmN0aW9uIChjb252ZXJ0ZXJPcHRpb25zKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXJcbiAgICAgIC8qKlxuICAgICAgICogT3B0aW9ucyB1c2VkIGJ5IHRoaXMgY29udmVydGVyXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICogQHR5cGUge3t9fVxuICAgICAgICovXG4gICAgICBvcHRpb25zID0ge30sXG5cbiAgICAgIC8qKlxuICAgICAgICogTGFuZ3VhZ2UgZXh0ZW5zaW9ucyB1c2VkIGJ5IHRoaXMgY29udmVydGVyXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICogQHR5cGUge0FycmF5fVxuICAgICAgICovXG4gICAgICBsYW5nRXh0ZW5zaW9ucyA9IFtdLFxuXG4gICAgICAvKipcbiAgICAgICAqIE91dHB1dCBtb2RpZmllcnMgZXh0ZW5zaW9ucyB1c2VkIGJ5IHRoaXMgY29udmVydGVyXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICogQHR5cGUge0FycmF5fVxuICAgICAgICovXG4gICAgICBvdXRwdXRNb2RpZmllcnMgPSBbXSxcblxuICAgICAgLyoqXG4gICAgICAgKiBFdmVudCBsaXN0ZW5lcnNcbiAgICAgICAqIEBwcml2YXRlXG4gICAgICAgKiBAdHlwZSB7e319XG4gICAgICAgKi9cbiAgICAgIGxpc3RlbmVycyA9IHt9LFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBmbGF2b3Igc2V0IGluIHRoaXMgY29udmVydGVyXG4gICAgICAgKi9cbiAgICAgIHNldENvbnZGbGF2b3IgPSBzZXRGbGF2b3IsXG5cbiAgICAvKipcbiAgICAgKiBNZXRhZGF0YSBvZiB0aGUgZG9jdW1lbnRcbiAgICAgKiBAdHlwZSB7e3BhcnNlZDoge30sIHJhdzogc3RyaW5nLCBmb3JtYXQ6IHN0cmluZ319XG4gICAgICovXG4gICAgICBtZXRhZGF0YSA9IHtcbiAgICAgICAgcGFyc2VkOiB7fSxcbiAgICAgICAgcmF3OiAnJyxcbiAgICAgICAgZm9ybWF0OiAnJ1xuICAgICAgfTtcblxuICBfY29uc3RydWN0b3IoKTtcblxuICAvKipcbiAgICogQ29udmVydGVyIGNvbnN0cnVjdG9yXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBmdW5jdGlvbiBfY29uc3RydWN0b3IgKCkge1xuICAgIGNvbnZlcnRlck9wdGlvbnMgPSBjb252ZXJ0ZXJPcHRpb25zIHx8IHt9O1xuXG4gICAgZm9yICh2YXIgZ09wdCBpbiBnbG9iYWxPcHRpb25zKSB7XG4gICAgICBpZiAoZ2xvYmFsT3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShnT3B0KSkge1xuICAgICAgICBvcHRpb25zW2dPcHRdID0gZ2xvYmFsT3B0aW9uc1tnT3B0XTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBNZXJnZSBvcHRpb25zXG4gICAgaWYgKHR5cGVvZiBjb252ZXJ0ZXJPcHRpb25zID09PSAnb2JqZWN0Jykge1xuICAgICAgZm9yICh2YXIgb3B0IGluIGNvbnZlcnRlck9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGNvbnZlcnRlck9wdGlvbnMuaGFzT3duUHJvcGVydHkob3B0KSkge1xuICAgICAgICAgIG9wdGlvbnNbb3B0XSA9IGNvbnZlcnRlck9wdGlvbnNbb3B0XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBFcnJvcignQ29udmVydGVyIGV4cGVjdHMgdGhlIHBhc3NlZCBwYXJhbWV0ZXIgdG8gYmUgYW4gb2JqZWN0LCBidXQgJyArIHR5cGVvZiBjb252ZXJ0ZXJPcHRpb25zICtcbiAgICAgICcgd2FzIHBhc3NlZCBpbnN0ZWFkLicpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmV4dGVuc2lvbnMpIHtcbiAgICAgIHNob3dkb3duLmhlbHBlci5mb3JFYWNoKG9wdGlvbnMuZXh0ZW5zaW9ucywgX3BhcnNlRXh0ZW5zaW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGFyc2UgZXh0ZW5zaW9uXG4gICAqIEBwYXJhbSB7Kn0gZXh0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZT0nJ11cbiAgICogQHByaXZhdGVcbiAgICovXG4gIGZ1bmN0aW9uIF9wYXJzZUV4dGVuc2lvbiAoZXh0LCBuYW1lKSB7XG5cbiAgICBuYW1lID0gbmFtZSB8fCBudWxsO1xuICAgIC8vIElmIGl0J3MgYSBzdHJpbmcsIHRoZSBleHRlbnNpb24gd2FzIHByZXZpb3VzbHkgbG9hZGVkXG4gICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1N0cmluZyhleHQpKSB7XG4gICAgICBleHQgPSBzaG93ZG93bi5oZWxwZXIuc3RkRXh0TmFtZShleHQpO1xuICAgICAgbmFtZSA9IGV4dDtcblxuICAgICAgLy8gTEVHQUNZX1NVUFBPUlQgQ09ERVxuICAgICAgaWYgKHNob3dkb3duLmV4dGVuc2lvbnNbZXh0XSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0RFUFJFQ0FUSU9OIFdBUk5JTkc6ICcgKyBleHQgKyAnIGlzIGFuIG9sZCBleHRlbnNpb24gdGhhdCB1c2VzIGEgZGVwcmVjYXRlZCBsb2FkaW5nIG1ldGhvZC4nICtcbiAgICAgICAgICAnUGxlYXNlIGluZm9ybSB0aGUgZGV2ZWxvcGVyIHRoYXQgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgdXBkYXRlZCEnKTtcbiAgICAgICAgbGVnYWN5RXh0ZW5zaW9uTG9hZGluZyhzaG93ZG93bi5leHRlbnNpb25zW2V4dF0sIGV4dCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIC8vIEVORCBMRUdBQ1kgU1VQUE9SVCBDT0RFXG5cbiAgICAgIH0gZWxzZSBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChleHRlbnNpb25zW2V4dF0pKSB7XG4gICAgICAgIGV4dCA9IGV4dGVuc2lvbnNbZXh0XTtcblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ0V4dGVuc2lvbiBcIicgKyBleHQgKyAnXCIgY291bGQgbm90IGJlIGxvYWRlZC4gSXQgd2FzIGVpdGhlciBub3QgZm91bmQgb3IgaXMgbm90IGEgdmFsaWQgZXh0ZW5zaW9uLicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlb2YgZXh0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBleHQgPSBleHQoKTtcbiAgICB9XG5cbiAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0FycmF5KGV4dCkpIHtcbiAgICAgIGV4dCA9IFtleHRdO1xuICAgIH1cblxuICAgIHZhciB2YWxpZEV4dCA9IHZhbGlkYXRlKGV4dCwgbmFtZSk7XG4gICAgaWYgKCF2YWxpZEV4dC52YWxpZCkge1xuICAgICAgdGhyb3cgRXJyb3IodmFsaWRFeHQuZXJyb3IpO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXh0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBzd2l0Y2ggKGV4dFtpXS50eXBlKSB7XG5cbiAgICAgICAgY2FzZSAnbGFuZyc6XG4gICAgICAgICAgbGFuZ0V4dGVuc2lvbnMucHVzaChleHRbaV0pO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ291dHB1dCc6XG4gICAgICAgICAgb3V0cHV0TW9kaWZpZXJzLnB1c2goZXh0W2ldKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmIChleHRbaV0uaGFzT3duUHJvcGVydHkoJ2xpc3RlbmVycycpKSB7XG4gICAgICAgIGZvciAodmFyIGxuIGluIGV4dFtpXS5saXN0ZW5lcnMpIHtcbiAgICAgICAgICBpZiAoZXh0W2ldLmxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShsbikpIHtcbiAgICAgICAgICAgIGxpc3RlbihsbiwgZXh0W2ldLmxpc3RlbmVyc1tsbl0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICB9XG5cbiAgLyoqXG4gICAqIExFR0FDWV9TVVBQT1JUXG4gICAqIEBwYXJhbSB7Kn0gZXh0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqL1xuICBmdW5jdGlvbiBsZWdhY3lFeHRlbnNpb25Mb2FkaW5nIChleHQsIG5hbWUpIHtcbiAgICBpZiAodHlwZW9mIGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgZXh0ID0gZXh0KG5ldyBzaG93ZG93bi5Db252ZXJ0ZXIoKSk7XG4gICAgfVxuICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzQXJyYXkoZXh0KSkge1xuICAgICAgZXh0ID0gW2V4dF07XG4gICAgfVxuICAgIHZhciB2YWxpZCA9IHZhbGlkYXRlKGV4dCwgbmFtZSk7XG5cbiAgICBpZiAoIXZhbGlkLnZhbGlkKSB7XG4gICAgICB0aHJvdyBFcnJvcih2YWxpZC5lcnJvcik7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBleHQubGVuZ3RoOyArK2kpIHtcbiAgICAgIHN3aXRjaCAoZXh0W2ldLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnbGFuZyc6XG4gICAgICAgICAgbGFuZ0V4dGVuc2lvbnMucHVzaChleHRbaV0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdvdXRwdXQnOlxuICAgICAgICAgIG91dHB1dE1vZGlmaWVycy5wdXNoKGV4dFtpXSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6Ly8gc2hvdWxkIG5ldmVyIHJlYWNoIGhlcmVcbiAgICAgICAgICB0aHJvdyBFcnJvcignRXh0ZW5zaW9uIGxvYWRlciBlcnJvcjogVHlwZSB1bnJlY29nbml6ZWQhISEnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTGlzdGVuIHRvIGFuIGV2ZW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBmdW5jdGlvbiBsaXN0ZW4gKG5hbWUsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcobmFtZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdJbnZhbGlkIGFyZ3VtZW50IGluIGNvbnZlcnRlci5saXN0ZW4oKSBtZXRob2Q6IG5hbWUgbXVzdCBiZSBhIHN0cmluZywgYnV0ICcgKyB0eXBlb2YgbmFtZSArICcgZ2l2ZW4nKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyBFcnJvcignSW52YWxpZCBhcmd1bWVudCBpbiBjb252ZXJ0ZXIubGlzdGVuKCkgbWV0aG9kOiBjYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24sIGJ1dCAnICsgdHlwZW9mIGNhbGxiYWNrICsgJyBnaXZlbicpO1xuICAgIH1cblxuICAgIGlmICghbGlzdGVuZXJzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICBsaXN0ZW5lcnNbbmFtZV0gPSBbXTtcbiAgICB9XG4gICAgbGlzdGVuZXJzW25hbWVdLnB1c2goY2FsbGJhY2spO1xuICB9XG5cbiAgZnVuY3Rpb24gclRyaW1JbnB1dFRleHQgKHRleHQpIHtcbiAgICB2YXIgcnNwID0gdGV4dC5tYXRjaCgvXlxccyovKVswXS5sZW5ndGgsXG4gICAgICAgIHJneCA9IG5ldyBSZWdFeHAoJ15cXFxcc3swLCcgKyByc3AgKyAnfScsICdnbScpO1xuICAgIHJldHVybiB0ZXh0LnJlcGxhY2Uocmd4LCAnJyk7XG4gIH1cblxuICAvKipcbiAgICogRGlzcGF0Y2ggYW4gZXZlbnRcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV2dE5hbWUgRXZlbnQgbmFtZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCBUZXh0XG4gICAqIEBwYXJhbSB7e319IG9wdGlvbnMgQ29udmVydGVyIE9wdGlvbnNcbiAgICogQHBhcmFtIHt7fX0gZ2xvYmFsc1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgdGhpcy5fZGlzcGF0Y2ggPSBmdW5jdGlvbiBkaXNwYXRjaCAoZXZ0TmFtZSwgdGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoZXZ0TmFtZSkpIHtcbiAgICAgIGZvciAodmFyIGVpID0gMDsgZWkgPCBsaXN0ZW5lcnNbZXZ0TmFtZV0ubGVuZ3RoOyArK2VpKSB7XG4gICAgICAgIHZhciBuVGV4dCA9IGxpc3RlbmVyc1tldnROYW1lXVtlaV0oZXZ0TmFtZSwgdGV4dCwgdGhpcywgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIGlmIChuVGV4dCAmJiB0eXBlb2YgblRleHQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGV4dCA9IG5UZXh0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0ZXh0O1xuICB9O1xuXG4gIC8qKlxuICAgKiBMaXN0ZW4gdG8gYW4gZXZlbnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICogQHJldHVybnMge3Nob3dkb3duLkNvbnZlcnRlcn1cbiAgICovXG4gIHRoaXMubGlzdGVuID0gZnVuY3Rpb24gKG5hbWUsIGNhbGxiYWNrKSB7XG4gICAgbGlzdGVuKG5hbWUsIGNhbGxiYWNrKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICAvKipcbiAgICogQ29udmVydHMgYSBtYXJrZG93biBzdHJpbmcgaW50byBIVE1MXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgdGhpcy5tYWtlSHRtbCA9IGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgLy9jaGVjayBpZiB0ZXh0IGlzIG5vdCBmYWxzeVxuICAgIGlmICghdGV4dCkge1xuICAgICAgcmV0dXJuIHRleHQ7XG4gICAgfVxuXG4gICAgdmFyIGdsb2JhbHMgPSB7XG4gICAgICBnSHRtbEJsb2NrczogICAgIFtdLFxuICAgICAgZ0h0bWxNZEJsb2NrczogICBbXSxcbiAgICAgIGdIdG1sU3BhbnM6ICAgICAgW10sXG4gICAgICBnVXJsczogICAgICAgICAgIHt9LFxuICAgICAgZ1RpdGxlczogICAgICAgICB7fSxcbiAgICAgIGdEaW1lbnNpb25zOiAgICAge30sXG4gICAgICBnTGlzdExldmVsOiAgICAgIDAsXG4gICAgICBoYXNoTGlua0NvdW50czogIHt9LFxuICAgICAgbGFuZ0V4dGVuc2lvbnM6ICBsYW5nRXh0ZW5zaW9ucyxcbiAgICAgIG91dHB1dE1vZGlmaWVyczogb3V0cHV0TW9kaWZpZXJzLFxuICAgICAgY29udmVydGVyOiAgICAgICB0aGlzLFxuICAgICAgZ2hDb2RlQmxvY2tzOiAgICBbXSxcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIHBhcnNlZDoge30sXG4gICAgICAgIHJhdzogJycsXG4gICAgICAgIGZvcm1hdDogJydcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLy8gVGhpcyBsZXRzIHVzIHVzZSDCqCB0cmVtYSBhcyBhbiBlc2NhcGUgY2hhciB0byBhdm9pZCBtZDUgaGFzaGVzXG4gICAgLy8gVGhlIGNob2ljZSBvZiBjaGFyYWN0ZXIgaXMgYXJiaXRyYXJ5OyBhbnl0aGluZyB0aGF0IGlzbid0XG4gICAgLy8gbWFnaWMgaW4gTWFya2Rvd24gd2lsbCB3b3JrLlxuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoL2csICfCqFQnKTtcblxuICAgIC8vIFJlcGxhY2UgJCB3aXRoIMKoRFxuICAgIC8vIFJlZ0V4cCBpbnRlcnByZXRzICQgYXMgYSBzcGVjaWFsIGNoYXJhY3RlclxuICAgIC8vIHdoZW4gaXQncyBpbiBhIHJlcGxhY2VtZW50IHN0cmluZ1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcJC9nLCAnwqhEJyk7XG5cbiAgICAvLyBTdGFuZGFyZGl6ZSBsaW5lIGVuZGluZ3NcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpOyAvLyBET1MgdG8gVW5peFxuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcci9nLCAnXFxuJyk7IC8vIE1hYyB0byBVbml4XG5cbiAgICAvLyBTdGFyZGFyZGl6ZSBsaW5lIHNwYWNlc1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcdTAwQTAvZywgJyZuYnNwOycpO1xuXG4gICAgaWYgKG9wdGlvbnMuc21hcnRJbmRlbnRhdGlvbkZpeCkge1xuICAgICAgdGV4dCA9IHJUcmltSW5wdXRUZXh0KHRleHQpO1xuICAgIH1cblxuICAgIC8vIE1ha2Ugc3VyZSB0ZXh0IGJlZ2lucyBhbmQgZW5kcyB3aXRoIGEgY291cGxlIG9mIG5ld2xpbmVzOlxuICAgIHRleHQgPSAnXFxuXFxuJyArIHRleHQgKyAnXFxuXFxuJztcblxuICAgIC8vIGRldGFiXG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZGV0YWInKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAgIC8qKlxuICAgICAqIFN0cmlwIGFueSBsaW5lcyBjb25zaXN0aW5nIG9ubHkgb2Ygc3BhY2VzIGFuZCB0YWJzLlxuICAgICAqIFRoaXMgbWFrZXMgc3Vic2VxdWVudCByZWdleHMgZWFzaWVyIHRvIHdyaXRlLCBiZWNhdXNlIHdlIGNhblxuICAgICAqIG1hdGNoIGNvbnNlY3V0aXZlIGJsYW5rIGxpbmVzIHdpdGggL1xcbisvIGluc3RlYWQgb2Ygc29tZXRoaW5nXG4gICAgICogY29udG9ydGVkIGxpa2UgL1sgXFx0XSpcXG4rL1xuICAgICAqL1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL15bIFxcdF0rJC9tZywgJycpO1xuXG4gICAgLy9ydW4gbGFuZ3VhZ2VFeHRlbnNpb25zXG4gICAgc2hvd2Rvd24uaGVscGVyLmZvckVhY2gobGFuZ0V4dGVuc2lvbnMsIGZ1bmN0aW9uIChleHQpIHtcbiAgICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3J1bkV4dGVuc2lvbicpKGV4dCwgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgfSk7XG5cbiAgICAvLyBydW4gdGhlIHN1YiBwYXJzZXJzXG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWV0YWRhdGEnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoUHJlQ29kZVRhZ3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdnaXRodWJDb2RlQmxvY2tzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxCbG9ja3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQ29kZVRhZ3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzdHJpcExpbmtEZWZpbml0aW9ucycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2Jsb2NrR2FtdXQnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmhhc2hIVE1MU3BhbnMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmVzY2FwZVNwZWNpYWxDaGFycycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gICAgLy8gYXR0YWNrbGFiOiBSZXN0b3JlIGRvbGxhciBzaWduc1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoRC9nLCAnJCQnKTtcblxuICAgIC8vIGF0dGFja2xhYjogUmVzdG9yZSB0cmVtYXNcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqFQvZywgJ8KoJyk7XG5cbiAgICAvLyByZW5kZXIgYSBjb21wbGV0ZSBodG1sIGRvY3VtZW50IGluc3RlYWQgb2YgYSBwYXJ0aWFsIGlmIHRoZSBvcHRpb24gaXMgZW5hYmxlZFxuICAgIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2NvbXBsZXRlSFRNTERvY3VtZW50JykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgICAvLyBSdW4gb3V0cHV0IG1vZGlmaWVyc1xuICAgIHNob3dkb3duLmhlbHBlci5mb3JFYWNoKG91dHB1dE1vZGlmaWVycywgZnVuY3Rpb24gKGV4dCkge1xuICAgICAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcigncnVuRXh0ZW5zaW9uJykoZXh0LCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB9KTtcblxuICAgIC8vIHVwZGF0ZSBtZXRhZGF0YVxuICAgIG1ldGFkYXRhID0gZ2xvYmFscy5tZXRhZGF0YTtcbiAgICByZXR1cm4gdGV4dDtcbiAgfTtcblxuICAvKipcbiAgICogQ29udmVydHMgYW4gSFRNTCBzdHJpbmcgaW50byBhIG1hcmtkb3duIHN0cmluZ1xuICAgKiBAcGFyYW0gc3JjXG4gICAqIEBwYXJhbSBbSFRNTFBhcnNlcl0gQSBXSEFUV0cgRE9NIGFuZCBIVE1MIHBhcnNlciwgc3VjaCBhcyBKU0RPTS4gSWYgbm9uZSBpcyBzdXBwbGllZCwgd2luZG93LmRvY3VtZW50IHdpbGwgYmUgdXNlZC5cbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHRoaXMubWFrZU1hcmtkb3duID0gdGhpcy5tYWtlTWQgPSBmdW5jdGlvbiAoc3JjLCBIVE1MUGFyc2VyKSB7XG5cbiAgICAvLyByZXBsYWNlIFxcclxcbiB3aXRoIFxcblxuICAgIHNyYyA9IHNyYy5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpO1xuICAgIHNyYyA9IHNyYy5yZXBsYWNlKC9cXHIvZywgJ1xcbicpOyAvLyBvbGQgbWFjc1xuXG4gICAgLy8gZHVlIHRvIGFuIGVkZ2UgY2FzZSwgd2UgbmVlZCB0byBmaW5kIHRoaXM6ID4gPFxuICAgIC8vIHRvIHByZXZlbnQgcmVtb3Zpbmcgb2Ygbm9uIHNpbGVudCB3aGl0ZSBzcGFjZXNcbiAgICAvLyBleDogPGVtPnRoaXMgaXM8L2VtPiA8c3Ryb25nPnNwYXJ0YTwvc3Ryb25nPlxuICAgIHNyYyA9IHNyYy5yZXBsYWNlKC8+WyBcXHRdKzwvLCAnPsKoTkJTUDs8Jyk7XG5cbiAgICBpZiAoIUhUTUxQYXJzZXIpIHtcbiAgICAgIGlmICh3aW5kb3cgJiYgd2luZG93LmRvY3VtZW50KSB7XG4gICAgICAgIEhUTUxQYXJzZXIgPSB3aW5kb3cuZG9jdW1lbnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0hUTUxQYXJzZXIgaXMgdW5kZWZpbmVkLiBJZiBpbiBhIHdlYndvcmtlciBvciBub2RlanMgZW52aXJvbm1lbnQsIHlvdSBuZWVkIHRvIHByb3ZpZGUgYSBXSEFUV0cgRE9NIGFuZCBIVE1MIHN1Y2ggYXMgSlNET00nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZG9jID0gSFRNTFBhcnNlci5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBkb2MuaW5uZXJIVE1MID0gc3JjO1xuXG4gICAgdmFyIGdsb2JhbHMgPSB7XG4gICAgICBwcmVMaXN0OiBzdWJzdGl0dXRlUHJlQ29kZVRhZ3MoZG9jKVxuICAgIH07XG5cbiAgICAvLyByZW1vdmUgYWxsIG5ld2xpbmVzIGFuZCBjb2xsYXBzZSBzcGFjZXNcbiAgICBjbGVhbihkb2MpO1xuXG4gICAgLy8gc29tZSBzdHVmZiwgbGlrZSBhY2NpZGVudGFsIHJlZmVyZW5jZSBsaW5rcyBtdXN0IG5vdyBiZSBlc2NhcGVkXG4gICAgLy8gVE9ET1xuICAgIC8vIGRvYy5pbm5lckhUTUwgPSBkb2MuaW5uZXJIVE1MLnJlcGxhY2UoL1xcW1tcXFNcXHQgXV0vKTtcblxuICAgIHZhciBub2RlcyA9IGRvYy5jaGlsZE5vZGVzLFxuICAgICAgICBtZERvYyA9ICcnO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgbWREb2MgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKG5vZGVzW2ldLCBnbG9iYWxzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbGVhbiAobm9kZSkge1xuICAgICAgZm9yICh2YXIgbiA9IDA7IG4gPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyArK24pIHtcbiAgICAgICAgdmFyIGNoaWxkID0gbm9kZS5jaGlsZE5vZGVzW25dO1xuICAgICAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICBpZiAoIS9cXFMvLnRlc3QoY2hpbGQubm9kZVZhbHVlKSkge1xuICAgICAgICAgICAgbm9kZS5yZW1vdmVDaGlsZChjaGlsZCk7XG4gICAgICAgICAgICAtLW47XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoaWxkLm5vZGVWYWx1ZSA9IGNoaWxkLm5vZGVWYWx1ZS5zcGxpdCgnXFxuJykuam9pbignICcpO1xuICAgICAgICAgICAgY2hpbGQubm9kZVZhbHVlID0gY2hpbGQubm9kZVZhbHVlLnJlcGxhY2UoLyhcXHMpKy9nLCAnJDEnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoY2hpbGQubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgICBjbGVhbihjaGlsZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmaW5kIGFsbCBwcmUgdGFncyBhbmQgcmVwbGFjZSBjb250ZW50cyB3aXRoIHBsYWNlaG9sZGVyXG4gICAgLy8gd2UgbmVlZCB0aGlzIHNvIHRoYXQgd2UgY2FuIHJlbW92ZSBhbGwgaW5kZW50YXRpb24gZnJvbSBodG1sXG4gICAgLy8gdG8gZWFzZSB1cCBwYXJzaW5nXG4gICAgZnVuY3Rpb24gc3Vic3RpdHV0ZVByZUNvZGVUYWdzIChkb2MpIHtcblxuICAgICAgdmFyIHByZXMgPSBkb2MucXVlcnlTZWxlY3RvckFsbCgncHJlJyksXG4gICAgICAgICAgcHJlc1BIID0gW107XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlcy5sZW5ndGg7ICsraSkge1xuXG4gICAgICAgIGlmIChwcmVzW2ldLmNoaWxkRWxlbWVudENvdW50ID09PSAxICYmIHByZXNbaV0uZmlyc3RDaGlsZC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdjb2RlJykge1xuICAgICAgICAgIHZhciBjb250ZW50ID0gcHJlc1tpXS5maXJzdENoaWxkLmlubmVySFRNTC50cmltKCksXG4gICAgICAgICAgICAgIGxhbmd1YWdlID0gcHJlc1tpXS5maXJzdENoaWxkLmdldEF0dHJpYnV0ZSgnZGF0YS1sYW5ndWFnZScpIHx8ICcnO1xuXG4gICAgICAgICAgLy8gaWYgZGF0YS1sYW5ndWFnZSBhdHRyaWJ1dGUgaXMgbm90IGRlZmluZWQsIHRoZW4gd2UgbG9vayBmb3IgY2xhc3MgbGFuZ3VhZ2UtKlxuICAgICAgICAgIGlmIChsYW5ndWFnZSA9PT0gJycpIHtcbiAgICAgICAgICAgIHZhciBjbGFzc2VzID0gcHJlc1tpXS5maXJzdENoaWxkLmNsYXNzTmFtZS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgZm9yICh2YXIgYyA9IDA7IGMgPCBjbGFzc2VzLmxlbmd0aDsgKytjKSB7XG4gICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gY2xhc3Nlc1tjXS5tYXRjaCgvXmxhbmd1YWdlLSguKykkLyk7XG4gICAgICAgICAgICAgIGlmIChtYXRjaGVzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbGFuZ3VhZ2UgPSBtYXRjaGVzWzFdO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gdW5lc2NhcGUgaHRtbCBlbnRpdGllcyBpbiBjb250ZW50XG4gICAgICAgICAgY29udGVudCA9IHNob3dkb3duLmhlbHBlci51bmVzY2FwZUhUTUxFbnRpdGllcyhjb250ZW50KTtcblxuICAgICAgICAgIHByZXNQSC5wdXNoKGNvbnRlbnQpO1xuICAgICAgICAgIHByZXNbaV0ub3V0ZXJIVE1MID0gJzxwcmVjb2RlIGxhbmd1YWdlPVwiJyArIGxhbmd1YWdlICsgJ1wiIHByZWNvZGVudW09XCInICsgaS50b1N0cmluZygpICsgJ1wiPjwvcHJlY29kZT4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHByZXNQSC5wdXNoKHByZXNbaV0uaW5uZXJIVE1MKTtcbiAgICAgICAgICBwcmVzW2ldLmlubmVySFRNTCA9ICcnO1xuICAgICAgICAgIHByZXNbaV0uc2V0QXR0cmlidXRlKCdwcmVudW0nLCBpLnRvU3RyaW5nKCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJlc1BIO1xuICAgIH1cblxuICAgIHJldHVybiBtZERvYztcbiAgfTtcblxuICAvKipcbiAgICogU2V0IGFuIG9wdGlvbiBvZiB0aGlzIENvbnZlcnRlciBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5XG4gICAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAgICovXG4gIHRoaXMuc2V0T3B0aW9uID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICBvcHRpb25zW2tleV0gPSB2YWx1ZTtcbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBvcHRpb24gb2YgdGhpcyBDb252ZXJ0ZXIgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHRoaXMuZ2V0T3B0aW9uID0gZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiBvcHRpb25zW2tleV07XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgb3B0aW9ucyBvZiB0aGlzIENvbnZlcnRlciBpbnN0YW5jZVxuICAgKiBAcmV0dXJucyB7e319XG4gICAqL1xuICB0aGlzLmdldE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFkZCBleHRlbnNpb24gdG8gVEhJUyBjb252ZXJ0ZXJcbiAgICogQHBhcmFtIHt7fX0gZXh0ZW5zaW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZT1udWxsXVxuICAgKi9cbiAgdGhpcy5hZGRFeHRlbnNpb24gPSBmdW5jdGlvbiAoZXh0ZW5zaW9uLCBuYW1lKSB7XG4gICAgbmFtZSA9IG5hbWUgfHwgbnVsbDtcbiAgICBfcGFyc2VFeHRlbnNpb24oZXh0ZW5zaW9uLCBuYW1lKTtcbiAgfTtcblxuICAvKipcbiAgICogVXNlIGEgZ2xvYmFsIHJlZ2lzdGVyZWQgZXh0ZW5zaW9uIHdpdGggVEhJUyBjb252ZXJ0ZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV4dGVuc2lvbk5hbWUgTmFtZSBvZiB0aGUgcHJldmlvdXNseSByZWdpc3RlcmVkIGV4dGVuc2lvblxuICAgKi9cbiAgdGhpcy51c2VFeHRlbnNpb24gPSBmdW5jdGlvbiAoZXh0ZW5zaW9uTmFtZSkge1xuICAgIF9wYXJzZUV4dGVuc2lvbihleHRlbnNpb25OYW1lKTtcbiAgfTtcblxuICAvKipcbiAgICogU2V0IHRoZSBmbGF2b3IgVEhJUyBjb252ZXJ0ZXIgc2hvdWxkIHVzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgKi9cbiAgdGhpcy5zZXRGbGF2b3IgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIGlmICghZmxhdm9yLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICB0aHJvdyBFcnJvcihuYW1lICsgJyBmbGF2b3Igd2FzIG5vdCBmb3VuZCcpO1xuICAgIH1cbiAgICB2YXIgcHJlc2V0ID0gZmxhdm9yW25hbWVdO1xuICAgIHNldENvbnZGbGF2b3IgPSBuYW1lO1xuICAgIGZvciAodmFyIG9wdGlvbiBpbiBwcmVzZXQpIHtcbiAgICAgIGlmIChwcmVzZXQuaGFzT3duUHJvcGVydHkob3B0aW9uKSkge1xuICAgICAgICBvcHRpb25zW29wdGlvbl0gPSBwcmVzZXRbb3B0aW9uXTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudGx5IHNldCBmbGF2b3Igb2YgdGhpcyBjb252ZXJ0ZXJcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHRoaXMuZ2V0Rmxhdm9yID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBzZXRDb252Rmxhdm9yO1xuICB9O1xuXG4gIC8qKlxuICAgKiBSZW1vdmUgYW4gZXh0ZW5zaW9uIGZyb20gVEhJUyBjb252ZXJ0ZXIuXG4gICAqIE5vdGU6IFRoaXMgaXMgYSBjb3N0bHkgb3BlcmF0aW9uLiBJdCdzIGJldHRlciB0byBpbml0aWFsaXplIGEgbmV3IGNvbnZlcnRlclxuICAgKiBhbmQgc3BlY2lmeSB0aGUgZXh0ZW5zaW9ucyB5b3Ugd2lzaCB0byB1c2VcbiAgICogQHBhcmFtIHtBcnJheX0gZXh0ZW5zaW9uXG4gICAqL1xuICB0aGlzLnJlbW92ZUV4dGVuc2lvbiA9IGZ1bmN0aW9uIChleHRlbnNpb24pIHtcbiAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc0FycmF5KGV4dGVuc2lvbikpIHtcbiAgICAgIGV4dGVuc2lvbiA9IFtleHRlbnNpb25dO1xuICAgIH1cbiAgICBmb3IgKHZhciBhID0gMDsgYSA8IGV4dGVuc2lvbi5sZW5ndGg7ICsrYSkge1xuICAgICAgdmFyIGV4dCA9IGV4dGVuc2lvblthXTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFuZ0V4dGVuc2lvbnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWYgKGxhbmdFeHRlbnNpb25zW2ldID09PSBleHQpIHtcbiAgICAgICAgICBsYW5nRXh0ZW5zaW9uc1tpXS5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCBvdXRwdXRNb2RpZmllcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWYgKG91dHB1dE1vZGlmaWVyc1tpaV0gPT09IGV4dCkge1xuICAgICAgICAgIG91dHB1dE1vZGlmaWVyc1tpaV0uc3BsaWNlKGksIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBHZXQgYWxsIGV4dGVuc2lvbiBvZiBUSElTIGNvbnZlcnRlclxuICAgKiBAcmV0dXJucyB7e2xhbmd1YWdlOiBBcnJheSwgb3V0cHV0OiBBcnJheX19XG4gICAqL1xuICB0aGlzLmdldEFsbEV4dGVuc2lvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhbmd1YWdlOiBsYW5nRXh0ZW5zaW9ucyxcbiAgICAgIG91dHB1dDogb3V0cHV0TW9kaWZpZXJzXG4gICAgfTtcbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBtZXRhZGF0YSBvZiB0aGUgcHJldmlvdXNseSBwYXJzZWQgZG9jdW1lbnRcbiAgICogQHBhcmFtIHJhd1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfHt9fVxuICAgKi9cbiAgdGhpcy5nZXRNZXRhZGF0YSA9IGZ1bmN0aW9uIChyYXcpIHtcbiAgICBpZiAocmF3KSB7XG4gICAgICByZXR1cm4gbWV0YWRhdGEucmF3O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbWV0YWRhdGEucGFyc2VkO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBtZXRhZGF0YSBmb3JtYXQgb2YgdGhlIHByZXZpb3VzbHkgcGFyc2VkIGRvY3VtZW50XG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICB0aGlzLmdldE1ldGFkYXRhRm9ybWF0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBtZXRhZGF0YS5mb3JtYXQ7XG4gIH07XG5cbiAgLyoqXG4gICAqIFByaXZhdGU6IHNldCBhIHNpbmdsZSBrZXksIHZhbHVlIG1ldGFkYXRhIHBhaXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICovXG4gIHRoaXMuX3NldE1ldGFkYXRhUGFpciA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgbWV0YWRhdGEucGFyc2VkW2tleV0gPSB2YWx1ZTtcbiAgfTtcblxuICAvKipcbiAgICogUHJpdmF0ZTogc2V0IG1ldGFkYXRhIGZvcm1hdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gZm9ybWF0XG4gICAqL1xuICB0aGlzLl9zZXRNZXRhZGF0YUZvcm1hdCA9IGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICBtZXRhZGF0YS5mb3JtYXQgPSBmb3JtYXQ7XG4gIH07XG5cbiAgLyoqXG4gICAqIFByaXZhdGU6IHNldCBtZXRhZGF0YSByYXcgdGV4dFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcmF3XG4gICAqL1xuICB0aGlzLl9zZXRNZXRhZGF0YVJhdyA9IGZ1bmN0aW9uIChyYXcpIHtcbiAgICBtZXRhZGF0YS5yYXcgPSByYXc7XG4gIH07XG59O1xuXHJcbi8qKlxuICogVHVybiBNYXJrZG93biBsaW5rIHNob3J0Y3V0cyBpbnRvIFhIVE1MIDxhPiB0YWdzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2FuY2hvcnMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYW5jaG9ycy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIgd3JpdGVBbmNob3JUYWcgPSBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbGlua1RleHQsIGxpbmtJZCwgdXJsLCBtNSwgbTYsIHRpdGxlKSB7XG4gICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZCh0aXRsZSkpIHtcbiAgICAgIHRpdGxlID0gJyc7XG4gICAgfVxuICAgIGxpbmtJZCA9IGxpbmtJZC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gU3BlY2lhbCBjYXNlIGZvciBleHBsaWNpdCBlbXB0eSB1cmxcbiAgICBpZiAod2hvbGVNYXRjaC5zZWFyY2goL1xcKDw/XFxzKj4/ID8oWydcIl0uKlsnXCJdKT9cXCkkL20pID4gLTEpIHtcbiAgICAgIHVybCA9ICcnO1xuICAgIH0gZWxzZSBpZiAoIXVybCkge1xuICAgICAgaWYgKCFsaW5rSWQpIHtcbiAgICAgICAgLy8gbG93ZXItY2FzZSBhbmQgdHVybiBlbWJlZGRlZCBuZXdsaW5lcyBpbnRvIHNwYWNlc1xuICAgICAgICBsaW5rSWQgPSBsaW5rVGV4dC50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoLyA/XFxuL2csICcgJyk7XG4gICAgICB9XG4gICAgICB1cmwgPSAnIycgKyBsaW5rSWQ7XG5cbiAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGdsb2JhbHMuZ1VybHNbbGlua0lkXSkpIHtcbiAgICAgICAgdXJsID0gZ2xvYmFscy5nVXJsc1tsaW5rSWRdO1xuICAgICAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChnbG9iYWxzLmdUaXRsZXNbbGlua0lkXSkpIHtcbiAgICAgICAgICB0aXRsZSA9IGdsb2JhbHMuZ1RpdGxlc1tsaW5rSWRdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gd2hvbGVNYXRjaDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvL3VybCA9IHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzKHVybCwgJypfJywgZmFsc2UpOyAvLyByZXBsYWNlZCBsaW5lIHRvIGltcHJvdmUgcGVyZm9ybWFuY2VcbiAgICB1cmwgPSB1cmwucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG5cbiAgICB2YXIgcmVzdWx0ID0gJzxhIGhyZWY9XCInICsgdXJsICsgJ1wiJztcblxuICAgIGlmICh0aXRsZSAhPT0gJycgJiYgdGl0bGUgIT09IG51bGwpIHtcbiAgICAgIHRpdGxlID0gdGl0bGUucmVwbGFjZSgvXCIvZywgJyZxdW90OycpO1xuICAgICAgLy90aXRsZSA9IHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzKHRpdGxlLCAnKl8nLCBmYWxzZSk7IC8vIHJlcGxhY2VkIGxpbmUgdG8gaW1wcm92ZSBwZXJmb3JtYW5jZVxuICAgICAgdGl0bGUgPSB0aXRsZS5yZXBsYWNlKHNob3dkb3duLmhlbHBlci5yZWdleGVzLmFzdGVyaXNrRGFzaEFuZENvbG9uLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcbiAgICAgIHJlc3VsdCArPSAnIHRpdGxlPVwiJyArIHRpdGxlICsgJ1wiJztcbiAgICB9XG5cbiAgICAvLyBvcHRpb25MaW5rc0luTmV3V2luZG93IG9ubHkgYXBwbGllc1xuICAgIC8vIHRvIGV4dGVybmFsIGxpbmtzLiBIYXNoIGxpbmtzICgjKSBvcGVuIGluIHNhbWUgcGFnZVxuICAgIGlmIChvcHRpb25zLm9wZW5MaW5rc0luTmV3V2luZG93ICYmICEvXiMvLnRlc3QodXJsKSkge1xuICAgICAgLy8gZXNjYXBlZCBfXG4gICAgICByZXN1bHQgKz0gJyB0YXJnZXQ9XCLCqEU5NUVibGFua1wiJztcbiAgICB9XG5cbiAgICByZXN1bHQgKz0gJz4nICsgbGlua1RleHQgKyAnPC9hPic7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIEZpcnN0LCBoYW5kbGUgcmVmZXJlbmNlLXN0eWxlIGxpbmtzOiBbbGluayB0ZXh0XSBbaWRdXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcWygoPzpcXFtbXlxcXV0qXXxbXlxcW1xcXV0pKildID8oPzpcXG4gKik/XFxbKC4qPyldKCkoKSgpKCkvZywgd3JpdGVBbmNob3JUYWcpO1xuXG4gIC8vIE5leHQsIGlubGluZS1zdHlsZSBsaW5rczogW2xpbmsgdGV4dF0odXJsIFwib3B0aW9uYWwgdGl0bGVcIilcbiAgLy8gY2FzZXMgd2l0aCBjcmF6eSB1cmxzIGxpa2UgLi9pbWFnZS9jYXQxKS5wbmdcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxbKCg/OlxcW1teXFxdXSpdfFteXFxbXFxdXSkqKV0oKVsgXFx0XSpcXChbIFxcdF0/PChbXj5dKik+KD86WyBcXHRdKigoW1wiJ10pKFteXCJdKj8pXFw1KSk/WyBcXHRdP1xcKS9nLFxuICAgIHdyaXRlQW5jaG9yVGFnKTtcblxuICAvLyBub3JtYWwgY2FzZXNcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxbKCg/OlxcW1teXFxdXSpdfFteXFxbXFxdXSkqKV0oKVsgXFx0XSpcXChbIFxcdF0/PD8oW1xcU10rPyg/OlxcKFtcXFNdKj9cXClbXFxTXSo/KT8pPj8oPzpbIFxcdF0qKChbXCInXSkoW15cIl0qPylcXDUpKT9bIFxcdF0/XFwpL2csXG4gICAgICAgICAgICAgICAgICAgICAgd3JpdGVBbmNob3JUYWcpO1xuXG4gIC8vIGhhbmRsZSByZWZlcmVuY2Utc3R5bGUgc2hvcnRjdXRzOiBbbGluayB0ZXh0XVxuICAvLyBUaGVzZSBtdXN0IGNvbWUgbGFzdCBpbiBjYXNlIHlvdSd2ZSBhbHNvIGdvdCBbbGluayB0ZXN0XVsxXVxuICAvLyBvciBbbGluayB0ZXN0XSgvZm9vKVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXFsoW15cXFtcXF1dKyldKCkoKSgpKCkoKS9nLCB3cml0ZUFuY2hvclRhZyk7XG5cbiAgLy8gTGFzdGx5IGhhbmRsZSBHaXRodWJNZW50aW9ucyBpZiBvcHRpb24gaXMgZW5hYmxlZFxuICBpZiAob3B0aW9ucy5naE1lbnRpb25zKSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvKF58XFxzKShcXFxcKT8oQChbYS16XFxkXSsoPzpbYS16XFxkLi1dKz9bYS16XFxkXSspKikpL2dtaSwgZnVuY3Rpb24gKHdtLCBzdCwgZXNjYXBlLCBtZW50aW9ucywgdXNlcm5hbWUpIHtcbiAgICAgIGlmIChlc2NhcGUgPT09ICdcXFxcJykge1xuICAgICAgICByZXR1cm4gc3QgKyBtZW50aW9ucztcbiAgICAgIH1cblxuICAgICAgLy9jaGVjayBpZiBvcHRpb25zLmdoTWVudGlvbnNMaW5rIGlzIGEgc3RyaW5nXG4gICAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1N0cmluZyhvcHRpb25zLmdoTWVudGlvbnNMaW5rKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2doTWVudGlvbnNMaW5rIG9wdGlvbiBtdXN0IGJlIGEgc3RyaW5nJyk7XG4gICAgICB9XG4gICAgICB2YXIgbG5rID0gb3B0aW9ucy5naE1lbnRpb25zTGluay5yZXBsYWNlKC9cXHt1fS9nLCB1c2VybmFtZSksXG4gICAgICAgICAgdGFyZ2V0ID0gJyc7XG4gICAgICBpZiAob3B0aW9ucy5vcGVuTGlua3NJbk5ld1dpbmRvdykge1xuICAgICAgICB0YXJnZXQgPSAnIHRhcmdldD1cIsKoRTk1RWJsYW5rXCInO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0ICsgJzxhIGhyZWY9XCInICsgbG5rICsgJ1wiJyArIHRhcmdldCArICc+JyArIG1lbnRpb25zICsgJzwvYT4nO1xuICAgIH0pO1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYW5jaG9ycy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8vIHVybCBhbGxvd2VkIGNoYXJzIFthLXpcXGRfLn46Lz8jW11AISQmJygpKissOz0tXVxuXG52YXIgc2ltcGxlVVJMUmVnZXggID0gLyhbKn5fXSt8XFxiKSgoKGh0dHBzP3xmdHB8ZGljdCk6XFwvXFwvfHd3d1xcLilbXidcIj5cXHNdKz9cXC5bXidcIj5cXHNdKz8pKCkoXFwxKT8oPz1cXHN8JCkoPyFbXCI8Pl0pL2dpLFxuICAgIHNpbXBsZVVSTFJlZ2V4MiA9IC8oWyp+X10rfFxcYikoKChodHRwcz98ZnRwfGRpY3QpOlxcL1xcL3x3d3dcXC4pW14nXCI+XFxzXStcXC5bXidcIj5cXHNdKz8pKFsuIT8sKClcXFtcXF1dKT8oXFwxKT8oPz1cXHN8JCkoPyFbXCI8Pl0pL2dpLFxuICAgIGRlbGltVXJsUmVnZXggICA9IC8oKTwoKChodHRwcz98ZnRwfGRpY3QpOlxcL1xcL3x3d3dcXC4pW14nXCI+XFxzXSspKCk+KCkvZ2ksXG4gICAgc2ltcGxlTWFpbFJlZ2V4ID0gLyhefFxccykoPzptYWlsdG86KT8oW0EtWmEtejAtOSEjJCUmJyorLS89P15fYHt8fX4uXStAWy1hLXowLTldKyhcXC5bLWEtejAtOV0rKSpcXC5bYS16XSspKD89JHxcXHMpL2dtaSxcbiAgICBkZWxpbU1haWxSZWdleCAgPSAvPCgpKD86bWFpbHRvOik/KFstLlxcd10rQFstYS16MC05XSsoXFwuWy1hLXowLTldKykqXFwuW2Etel0rKT4vZ2ksXG5cbiAgICByZXBsYWNlTGluayA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAndXNlIHN0cmljdCc7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gKHdtLCBsZWFkaW5nTWFnaWNDaGFycywgbGluaywgbTIsIG0zLCB0cmFpbGluZ1B1bmN0dWF0aW9uLCB0cmFpbGluZ01hZ2ljQ2hhcnMpIHtcbiAgICAgICAgbGluayA9IGxpbmsucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgICAgIHZhciBsbmtUeHQgPSBsaW5rLFxuICAgICAgICAgICAgYXBwZW5kID0gJycsXG4gICAgICAgICAgICB0YXJnZXQgPSAnJyxcbiAgICAgICAgICAgIGxtYyAgICA9IGxlYWRpbmdNYWdpY0NoYXJzIHx8ICcnLFxuICAgICAgICAgICAgdG1jICAgID0gdHJhaWxpbmdNYWdpY0NoYXJzIHx8ICcnO1xuICAgICAgICBpZiAoL153d3dcXC4vaS50ZXN0KGxpbmspKSB7XG4gICAgICAgICAgbGluayA9IGxpbmsucmVwbGFjZSgvXnd3d1xcLi9pLCAnaHR0cDovL3d3dy4nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5leGNsdWRlVHJhaWxpbmdQdW5jdHVhdGlvbkZyb21VUkxzICYmIHRyYWlsaW5nUHVuY3R1YXRpb24pIHtcbiAgICAgICAgICBhcHBlbmQgPSB0cmFpbGluZ1B1bmN0dWF0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLm9wZW5MaW5rc0luTmV3V2luZG93KSB7XG4gICAgICAgICAgdGFyZ2V0ID0gJyB0YXJnZXQ9XCLCqEU5NUVibGFua1wiJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbG1jICsgJzxhIGhyZWY9XCInICsgbGluayArICdcIicgKyB0YXJnZXQgKyAnPicgKyBsbmtUeHQgKyAnPC9hPicgKyBhcHBlbmQgKyB0bWM7XG4gICAgICB9O1xuICAgIH0sXG5cbiAgICByZXBsYWNlTWFpbCA9IGZ1bmN0aW9uIChvcHRpb25zLCBnbG9iYWxzKSB7XG4gICAgICAndXNlIHN0cmljdCc7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gKHdob2xlTWF0Y2gsIGIsIG1haWwpIHtcbiAgICAgICAgdmFyIGhyZWYgPSAnbWFpbHRvOic7XG4gICAgICAgIGIgPSBiIHx8ICcnO1xuICAgICAgICBtYWlsID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmVzY2FwZVNwZWNpYWxDaGFycycpKG1haWwsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICBpZiAob3B0aW9ucy5lbmNvZGVFbWFpbHMpIHtcbiAgICAgICAgICBocmVmID0gc2hvd2Rvd24uaGVscGVyLmVuY29kZUVtYWlsQWRkcmVzcyhocmVmICsgbWFpbCk7XG4gICAgICAgICAgbWFpbCA9IHNob3dkb3duLmhlbHBlci5lbmNvZGVFbWFpbEFkZHJlc3MobWFpbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaHJlZiA9IGhyZWYgKyBtYWlsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiICsgJzxhIGhyZWY9XCInICsgaHJlZiArICdcIj4nICsgbWFpbCArICc8L2E+JztcbiAgICAgIH07XG4gICAgfTtcblxuc2hvd2Rvd24uc3ViUGFyc2VyKCdhdXRvTGlua3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYXV0b0xpbmtzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoZGVsaW1VcmxSZWdleCwgcmVwbGFjZUxpbmsob3B0aW9ucykpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGRlbGltTWFpbFJlZ2V4LCByZXBsYWNlTWFpbChvcHRpb25zLCBnbG9iYWxzKSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYXV0b0xpbmtzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxuc2hvd2Rvd24uc3ViUGFyc2VyKCdzaW1wbGlmaWVkQXV0b0xpbmtzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmICghb3B0aW9ucy5zaW1wbGlmaWVkQXV0b0xpbmspIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3NpbXBsaWZpZWRBdXRvTGlua3MuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgaWYgKG9wdGlvbnMuZXhjbHVkZVRyYWlsaW5nUHVuY3R1YXRpb25Gcm9tVVJMcykge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2ltcGxlVVJMUmVnZXgyLCByZXBsYWNlTGluayhvcHRpb25zKSk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZShzaW1wbGVVUkxSZWdleCwgcmVwbGFjZUxpbmsob3B0aW9ucykpO1xuICB9XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2ltcGxlTWFpbFJlZ2V4LCByZXBsYWNlTWFpbChvcHRpb25zLCBnbG9iYWxzKSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc2ltcGxpZmllZEF1dG9MaW5rcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBUaGVzZSBhcmUgYWxsIHRoZSB0cmFuc2Zvcm1hdGlvbnMgdGhhdCBmb3JtIGJsb2NrLWxldmVsXG4gKiB0YWdzIGxpa2UgcGFyYWdyYXBocywgaGVhZGVycywgYW5kIGxpc3QgaXRlbXMuXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignYmxvY2tHYW11dCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdibG9ja0dhbXV0LmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIHdlIHBhcnNlIGJsb2NrcXVvdGVzIGZpcnN0IHNvIHRoYXQgd2UgY2FuIGhhdmUgaGVhZGluZ3MgYW5kIGhyc1xuICAvLyBpbnNpZGUgYmxvY2txdW90ZXNcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignYmxvY2tRdW90ZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaGVhZGVycycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIERvIEhvcml6b250YWwgUnVsZXM6XG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hvcml6b250YWxSdWxlJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbGlzdHMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignY29kZUJsb2NrcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd0YWJsZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBXZSBhbHJlYWR5IHJhbiBfSGFzaEhUTUxCbG9ja3MoKSBiZWZvcmUsIGluIE1hcmtkb3duKCksIGJ1dCB0aGF0XG4gIC8vIHdhcyB0byBlc2NhcGUgcmF3IEhUTUwgaW4gdGhlIG9yaWdpbmFsIE1hcmtkb3duIHNvdXJjZS4gVGhpcyB0aW1lLFxuICAvLyB3ZSdyZSBlc2NhcGluZyB0aGUgbWFya3VwIHdlJ3ZlIGp1c3QgY3JlYXRlZCwgc28gdGhhdCB3ZSBkb24ndCB3cmFwXG4gIC8vIDxwPiB0YWdzIGFyb3VuZCBibG9jay1sZXZlbCB0YWdzLlxuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoSFRNTEJsb2NrcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdwYXJhZ3JhcGhzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnYmxvY2tHYW11dC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdibG9ja1F1b3RlcycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdibG9ja1F1b3Rlcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBhZGQgYSBjb3VwbGUgZXh0cmEgbGluZXMgYWZ0ZXIgdGhlIHRleHQgYW5kIGVuZHRleHQgbWFya1xuICB0ZXh0ID0gdGV4dCArICdcXG5cXG4nO1xuXG4gIHZhciByZ3ggPSAvKF4gezAsM30+WyBcXHRdPy4rXFxuKC4rXFxuKSpcXG4qKSsvZ207XG5cbiAgaWYgKG9wdGlvbnMuc3BsaXRBZGphY2VudEJsb2NrcXVvdGVzKSB7XG4gICAgcmd4ID0gL14gezAsM30+W1xcc1xcU10qPyg/OlxcblxcbikvZ207XG4gIH1cblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJneCwgZnVuY3Rpb24gKGJxKSB7XG4gICAgLy8gYXR0YWNrbGFiOiBoYWNrIGFyb3VuZCBLb25xdWVyb3IgMy41LjQgYnVnOlxuICAgIC8vIFwiLS0tLS0tLS0tLWJ1Z1wiLnJlcGxhY2UoL14tL2csXCJcIikgPT0gXCJidWdcIlxuICAgIGJxID0gYnEucmVwbGFjZSgvXlsgXFx0XSo+WyBcXHRdPy9nbSwgJycpOyAvLyB0cmltIG9uZSBsZXZlbCBvZiBxdW90aW5nXG5cbiAgICAvLyBhdHRhY2tsYWI6IGNsZWFuIHVwIGhhY2tcbiAgICBicSA9IGJxLnJlcGxhY2UoL8KoMC9nLCAnJyk7XG5cbiAgICBicSA9IGJxLnJlcGxhY2UoL15bIFxcdF0rJC9nbSwgJycpOyAvLyB0cmltIHdoaXRlc3BhY2Utb25seSBsaW5lc1xuICAgIGJxID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdnaXRodWJDb2RlQmxvY2tzJykoYnEsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGJxID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdibG9ja0dhbXV0JykoYnEsIG9wdGlvbnMsIGdsb2JhbHMpOyAvLyByZWN1cnNlXG5cbiAgICBicSA9IGJxLnJlcGxhY2UoLyhefFxcbikvZywgJyQxICAnKTtcbiAgICAvLyBUaGVzZSBsZWFkaW5nIHNwYWNlcyBzY3JldyB3aXRoIDxwcmU+IGNvbnRlbnQsIHNvIHdlIG5lZWQgdG8gZml4IHRoYXQ6XG4gICAgYnEgPSBicS5yZXBsYWNlKC8oXFxzKjxwcmU+W15cXHJdKz88XFwvcHJlPikvZ20sIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSkge1xuICAgICAgdmFyIHByZSA9IG0xO1xuICAgICAgLy8gYXR0YWNrbGFiOiBoYWNrIGFyb3VuZCBLb25xdWVyb3IgMy41LjQgYnVnOlxuICAgICAgcHJlID0gcHJlLnJlcGxhY2UoL14gIC9tZywgJ8KoMCcpO1xuICAgICAgcHJlID0gcHJlLnJlcGxhY2UoL8KoMC9nLCAnJyk7XG4gICAgICByZXR1cm4gcHJlO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoJzxibG9ja3F1b3RlPlxcbicgKyBicSArICdcXG48L2Jsb2NrcXVvdGU+Jywgb3B0aW9ucywgZ2xvYmFscyk7XG4gIH0pO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2Jsb2NrUXVvdGVzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBQcm9jZXNzIE1hcmtkb3duIGA8cHJlPjxjb2RlPmAgYmxvY2tzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2NvZGVCbG9ja3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnY29kZUJsb2Nrcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBzZW50aW5lbCB3b3JrYXJvdW5kcyBmb3IgbGFjayBvZiBcXEEgYW5kIFxcWiwgc2FmYXJpXFxraHRtbCBidWdcbiAgdGV4dCArPSAnwqgwJztcblxuICB2YXIgcGF0dGVybiA9IC8oPzpcXG5cXG58XikoKD86KD86WyBdezR9fFxcdCkuKlxcbispKykoXFxuKlsgXXswLDN9W14gXFx0XFxuXXwoPz3CqDApKS9nO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHBhdHRlcm4sIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSwgbTIpIHtcbiAgICB2YXIgY29kZWJsb2NrID0gbTEsXG4gICAgICAgIG5leHRDaGFyID0gbTIsXG4gICAgICAgIGVuZCA9ICdcXG4nO1xuXG4gICAgY29kZWJsb2NrID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdvdXRkZW50JykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICBjb2RlYmxvY2sgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2VuY29kZUNvZGUnKShjb2RlYmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGNvZGVibG9jayA9IHNob3dkb3duLnN1YlBhcnNlcignZGV0YWInKShjb2RlYmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIGNvZGVibG9jayA9IGNvZGVibG9jay5yZXBsYWNlKC9eXFxuKy9nLCAnJyk7IC8vIHRyaW0gbGVhZGluZyBuZXdsaW5lc1xuICAgIGNvZGVibG9jayA9IGNvZGVibG9jay5yZXBsYWNlKC9cXG4rJC9nLCAnJyk7IC8vIHRyaW0gdHJhaWxpbmcgbmV3bGluZXNcblxuICAgIGlmIChvcHRpb25zLm9taXRFeHRyYVdMSW5Db2RlQmxvY2tzKSB7XG4gICAgICBlbmQgPSAnJztcbiAgICB9XG5cbiAgICBjb2RlYmxvY2sgPSAnPHByZT48Y29kZT4nICsgY29kZWJsb2NrICsgZW5kICsgJzwvY29kZT48L3ByZT4nO1xuXG4gICAgcmV0dXJuIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoY29kZWJsb2NrLCBvcHRpb25zLCBnbG9iYWxzKSArIG5leHRDaGFyO1xuICB9KTtcblxuICAvLyBzdHJpcCBzZW50aW5lbFxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqDAvLCAnJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnY29kZUJsb2Nrcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICpcbiAqICAgKiAgQmFja3RpY2sgcXVvdGVzIGFyZSB1c2VkIGZvciA8Y29kZT48L2NvZGU+IHNwYW5zLlxuICpcbiAqICAgKiAgWW91IGNhbiB1c2UgbXVsdGlwbGUgYmFja3RpY2tzIGFzIHRoZSBkZWxpbWl0ZXJzIGlmIHlvdSB3YW50IHRvXG4gKiAgICAgaW5jbHVkZSBsaXRlcmFsIGJhY2t0aWNrcyBpbiB0aGUgY29kZSBzcGFuLiBTbywgdGhpcyBpbnB1dDpcbiAqXG4gKiAgICAgICAgIEp1c3QgdHlwZSBgYGZvbyBgYmFyYCBiYXpgYCBhdCB0aGUgcHJvbXB0LlxuICpcbiAqICAgICAgIFdpbGwgdHJhbnNsYXRlIHRvOlxuICpcbiAqICAgICAgICAgPHA+SnVzdCB0eXBlIDxjb2RlPmZvbyBgYmFyYCBiYXo8L2NvZGU+IGF0IHRoZSBwcm9tcHQuPC9wPlxuICpcbiAqICAgIFRoZXJlJ3Mgbm8gYXJiaXRyYXJ5IGxpbWl0IHRvIHRoZSBudW1iZXIgb2YgYmFja3RpY2tzIHlvdVxuICogICAgY2FuIHVzZSBhcyBkZWxpbXRlcnMuIElmIHlvdSBuZWVkIHRocmVlIGNvbnNlY3V0aXZlIGJhY2t0aWNrc1xuICogICAgaW4geW91ciBjb2RlLCB1c2UgZm91ciBmb3IgZGVsaW1pdGVycywgZXRjLlxuICpcbiAqICAqICBZb3UgY2FuIHVzZSBzcGFjZXMgdG8gZ2V0IGxpdGVyYWwgYmFja3RpY2tzIGF0IHRoZSBlZGdlczpcbiAqXG4gKiAgICAgICAgIC4uLiB0eXBlIGBgIGBiYXJgIGBgIC4uLlxuICpcbiAqICAgICAgIFR1cm5zIHRvOlxuICpcbiAqICAgICAgICAgLi4uIHR5cGUgPGNvZGU+YGJhcmA8L2NvZGU+IC4uLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2NvZGVTcGFucycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdjb2RlU3BhbnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgaWYgKHR5cGVvZih0ZXh0KSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB0ZXh0ID0gJyc7XG4gIH1cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKF58W15cXFxcXSkoYCspKFteXFxyXSo/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/KT4vZywgZnVuY3Rpb24gKHdtLCBpbnNpZGUpIHtcbiAgICAgIHJldHVybiAnJmx0OycgKyBpbnNpZGUgKyAnJmd0Oyc7XG4gICAgfSk7XG4gIH1cblxuICAvLyBoYXNoIEhUTUwgQmxvY2tzXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tUYWdzLmxlbmd0aDsgKytpKSB7XG5cbiAgICB2YXIgb3BUYWdQb3MsXG4gICAgICAgIHJneDEgICAgID0gbmV3IFJlZ0V4cCgnXiB7MCwzfSg8JyArIGJsb2NrVGFnc1tpXSArICdcXFxcYltePl0qPiknLCAnaW0nKSxcbiAgICAgICAgcGF0TGVmdCAgPSAnPCcgKyBibG9ja1RhZ3NbaV0gKyAnXFxcXGJbXj5dKj4nLFxuICAgICAgICBwYXRSaWdodCA9ICc8LycgKyBibG9ja1RhZ3NbaV0gKyAnPic7XG4gICAgLy8gMS4gTG9vayBmb3IgdGhlIGZpcnN0IHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBvcGVuaW5nIEhUTUwgdGFnIGluIHRoZSB0ZXh0XG4gICAgd2hpbGUgKChvcFRhZ1BvcyA9IHNob3dkb3duLmhlbHBlci5yZWdleEluZGV4T2YodGV4dCwgcmd4MSkpICE9PSAtMSkge1xuXG4gICAgICAvLyBpZiB0aGUgSFRNTCB0YWcgaXMgXFwgZXNjYXBlZCwgd2UgbmVlZCB0byBlc2NhcGUgaXQgYW5kIGJyZWFrXG5cblxuICAgICAgLy8yLiBTcGxpdCB0aGUgdGV4dCBpbiB0aGF0IHBvc2l0aW9uXG4gICAgICB2YXIgc3ViVGV4dHMgPSBzaG93ZG93bi5oZWxwZXIuc3BsaXRBdEluZGV4KHRleHQsIG9wVGFnUG9zKSxcbiAgICAgIC8vMy4gTWF0Y2ggcmVjdXJzaXZlbHlcbiAgICAgICAgICBuZXdTdWJUZXh0MSA9IHNob3dkb3duLmhlbHBlci5yZXBsYWNlUmVjdXJzaXZlUmVnRXhwKHN1YlRleHRzWzFdLCByZXBGdW5jLCBwYXRMZWZ0LCBwYXRSaWdodCwgJ2ltJyk7XG5cbiAgICAgIC8vIHByZXZlbnQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgaWYgKG5ld1N1YlRleHQxID09PSBzdWJUZXh0c1sxXSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHRleHQgPSBzdWJUZXh0c1swXS5jb25jYXQobmV3U3ViVGV4dDEpO1xuICAgIH1cbiAgfVxuICAvLyBIUiBTUEVDSUFMIENBU0VcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKFxcbiB7MCwzfSg8KGhyKVxcYihbXjw+XSkqP1xcLz8+KVsgXFx0XSooPz1cXG57Mix9KSkvZyxcbiAgICBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hFbGVtZW50JykodGV4dCwgb3B0aW9ucywgZ2xvYmFscykpO1xuXG4gIC8vIFNwZWNpYWwgY2FzZSBmb3Igc3RhbmRhbG9uZSBIVE1MIGNvbW1lbnRzXG4gIHRleHQgPSBzaG93ZG93bi5oZWxwZXIucmVwbGFjZVJlY3Vyc2l2ZVJlZ0V4cCh0ZXh0LCBmdW5jdGlvbiAodHh0KSB7XG4gICAgcmV0dXJuICdcXG5cXG7CqEsnICsgKGdsb2JhbHMuZ0h0bWxCbG9ja3MucHVzaCh0eHQpIC0gMSkgKyAnS1xcblxcbic7XG4gIH0sICdeIHswLDN9PCEtLScsICctLT4nLCAnZ20nKTtcblxuICAvLyBQSFAgYW5kIEFTUC1zdHlsZSBwcm9jZXNzb3IgaW5zdHJ1Y3Rpb25zICg8Py4uLj8+IGFuZCA8JS4uLiU+KVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oPzpcXG5cXG4pKCB7MCwzfSg/OjwoWz8lXSlbXlxccl0qP1xcMj4pWyBcXHRdKig/PVxcbnsyLH0pKS9nLFxuICAgIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEVsZW1lbnQnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaEhUTUxCbG9ja3MuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIEhhc2ggc3BhbiBlbGVtZW50cyB0aGF0IHNob3VsZCBub3QgYmUgcGFyc2VkIGFzIG1hcmtkb3duXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxTcGFucycsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaEhUTUxTcGFucy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICBmdW5jdGlvbiBoYXNoSFRNTFNwYW4gKGh0bWwpIHtcbiAgICByZXR1cm4gJ8KoQycgKyAoZ2xvYmFscy5nSHRtbFNwYW5zLnB1c2goaHRtbCkgLSAxKSArICdDJztcbiAgfVxuXG4gIC8vIEhhc2ggU2VsZiBDbG9zaW5nIHRhZ3NcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvPFtePl0rP1xcLz4vZ2ksIGZ1bmN0aW9uICh3bSkge1xuICAgIHJldHVybiBoYXNoSFRNTFNwYW4od20pO1xuICB9KTtcblxuICAvLyBIYXNoIHRhZ3Mgd2l0aG91dCBwcm9wZXJ0aWVzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLzwoW14+XSs/KT5bXFxzXFxTXSo/PFxcL1xcMT4vZywgZnVuY3Rpb24gKHdtKSB7XG4gICAgcmV0dXJuIGhhc2hIVE1MU3Bhbih3bSk7XG4gIH0pO1xuXG4gIC8vIEhhc2ggdGFncyB3aXRoIHByb3BlcnRpZXNcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvPChbXj5dKz8pXFxzW14+XSs/PltcXHNcXFNdKj88XFwvXFwxPi9nLCBmdW5jdGlvbiAod20pIHtcbiAgICByZXR1cm4gaGFzaEhUTUxTcGFuKHdtKTtcbiAgfSk7XG5cbiAgLy8gSGFzaCBzZWxmIGNsb3NpbmcgdGFncyB3aXRob3V0IC8+XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoLzxbXj5dKz8+L2dpLCBmdW5jdGlvbiAod20pIHtcbiAgICByZXR1cm4gaGFzaEhUTUxTcGFuKHdtKTtcbiAgfSk7XG5cbiAgLypzaG93ZG93bi5oZWxwZXIubWF0Y2hSZWN1cnNpdmVSZWdFeHAodGV4dCwgJzxjb2RlXFxcXGJbXj5dKj4nLCAnPC9jb2RlPicsICdnaScpOyovXG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaEhUTUxTcGFucy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXG4vKipcbiAqIFVuaGFzaCBIVE1MIHNwYW5zXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcigndW5oYXNoSFRNTFNwYW5zJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmhhc2hIVE1MU3BhbnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBnbG9iYWxzLmdIdG1sU3BhbnMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcmVwVGV4dCA9IGdsb2JhbHMuZ0h0bWxTcGFuc1tpXSxcbiAgICAgICAgLy8gbGltaXRlciB0byBwcmV2ZW50IGluZmluaXRlIGxvb3AgKGFzc3VtZSAxMCBhcyBsaW1pdCBmb3IgcmVjdXJzZSlcbiAgICAgICAgbGltaXQgPSAwO1xuXG4gICAgd2hpbGUgKC/CqEMoXFxkKylDLy50ZXN0KHJlcFRleHQpKSB7XG4gICAgICB2YXIgbnVtID0gUmVnRXhwLiQxO1xuICAgICAgcmVwVGV4dCA9IHJlcFRleHQucmVwbGFjZSgnwqhDJyArIG51bSArICdDJywgZ2xvYmFscy5nSHRtbFNwYW5zW251bV0pO1xuICAgICAgaWYgKGxpbWl0ID09PSAxMCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdtYXhpbXVtIG5lc3Rpbmcgb2YgMTAgc3BhbnMgcmVhY2hlZCEhIScpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgICsrbGltaXQ7XG4gICAgfVxuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoJ8KoQycgKyBpICsgJ0MnLCByZXBUZXh0KTtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3VuaGFzaEhUTUxTcGFucy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogSGFzaCBhbmQgZXNjYXBlIDxwcmU+PGNvZGU+IGVsZW1lbnRzIHRoYXQgc2hvdWxkIG5vdCBiZSBwYXJzZWQgYXMgbWFya2Rvd25cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoUHJlQ29kZVRhZ3MnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hhc2hQcmVDb2RlVGFncy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB2YXIgcmVwRnVuYyA9IGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtYXRjaCwgbGVmdCwgcmlnaHQpIHtcbiAgICAvLyBlbmNvZGUgaHRtbCBlbnRpdGllc1xuICAgIHZhciBjb2RlYmxvY2sgPSBsZWZ0ICsgc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVDb2RlJykobWF0Y2gsIG9wdGlvbnMsIGdsb2JhbHMpICsgcmlnaHQ7XG4gICAgcmV0dXJuICdcXG5cXG7CqEcnICsgKGdsb2JhbHMuZ2hDb2RlQmxvY2tzLnB1c2goe3RleHQ6IHdob2xlTWF0Y2gsIGNvZGVibG9jazogY29kZWJsb2NrfSkgLSAxKSArICdHXFxuXFxuJztcbiAgfTtcblxuICAvLyBIYXNoIDxwcmU+PGNvZGU+XG4gIHRleHQgPSBzaG93ZG93bi5oZWxwZXIucmVwbGFjZVJlY3Vyc2l2ZVJlZ0V4cCh0ZXh0LCByZXBGdW5jLCAnXiB7MCwzfTxwcmVcXFxcYltePl0qPlxcXFxzKjxjb2RlXFxcXGJbXj5dKj4nLCAnXiB7MCwzfTwvY29kZT5cXFxccyo8L3ByZT4nLCAnZ2ltJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaGFzaFByZUNvZGVUYWdzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdoZWFkZXJzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hlYWRlcnMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdmFyIGhlYWRlckxldmVsU3RhcnQgPSAoaXNOYU4ocGFyc2VJbnQob3B0aW9ucy5oZWFkZXJMZXZlbFN0YXJ0KSkpID8gMSA6IHBhcnNlSW50KG9wdGlvbnMuaGVhZGVyTGV2ZWxTdGFydCksXG5cbiAgLy8gU2V0IHRleHQtc3R5bGUgaGVhZGVyczpcbiAgLy9cdEhlYWRlciAxXG4gIC8vXHQ9PT09PT09PVxuICAvL1xuICAvL1x0SGVhZGVyIDJcbiAgLy9cdC0tLS0tLS0tXG4gIC8vXG4gICAgICBzZXRleHRSZWdleEgxID0gKG9wdGlvbnMuc21vb3RoTGl2ZVByZXZpZXcpID8gL14oLispWyBcXHRdKlxcbj17Mix9WyBcXHRdKlxcbisvZ20gOiAvXiguKylbIFxcdF0qXFxuPStbIFxcdF0qXFxuKy9nbSxcbiAgICAgIHNldGV4dFJlZ2V4SDIgPSAob3B0aW9ucy5zbW9vdGhMaXZlUHJldmlldykgPyAvXiguKylbIFxcdF0qXFxuLXsyLH1bIFxcdF0qXFxuKy9nbSA6IC9eKC4rKVsgXFx0XSpcXG4tK1sgXFx0XSpcXG4rL2dtO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2V0ZXh0UmVnZXhIMSwgZnVuY3Rpb24gKHdob2xlTWF0Y2gsIG0xKSB7XG5cbiAgICB2YXIgc3BhbkdhbXV0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShtMSwgb3B0aW9ucywgZ2xvYmFscyksXG4gICAgICAgIGhJRCA9IChvcHRpb25zLm5vSGVhZGVySWQpID8gJycgOiAnIGlkPVwiJyArIGhlYWRlcklkKG0xKSArICdcIicsXG4gICAgICAgIGhMZXZlbCA9IGhlYWRlckxldmVsU3RhcnQsXG4gICAgICAgIGhhc2hCbG9jayA9ICc8aCcgKyBoTGV2ZWwgKyBoSUQgKyAnPicgKyBzcGFuR2FtdXQgKyAnPC9oJyArIGhMZXZlbCArICc+JztcbiAgICByZXR1cm4gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQmxvY2snKShoYXNoQmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB9KTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHNldGV4dFJlZ2V4SDIsIGZ1bmN0aW9uIChtYXRjaEZvdW5kLCBtMSkge1xuICAgIHZhciBzcGFuR2FtdXQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcpKG0xLCBvcHRpb25zLCBnbG9iYWxzKSxcbiAgICAgICAgaElEID0gKG9wdGlvbnMubm9IZWFkZXJJZCkgPyAnJyA6ICcgaWQ9XCInICsgaGVhZGVySWQobTEpICsgJ1wiJyxcbiAgICAgICAgaExldmVsID0gaGVhZGVyTGV2ZWxTdGFydCArIDEsXG4gICAgICAgIGhhc2hCbG9jayA9ICc8aCcgKyBoTGV2ZWwgKyBoSUQgKyAnPicgKyBzcGFuR2FtdXQgKyAnPC9oJyArIGhMZXZlbCArICc+JztcbiAgICByZXR1cm4gc2hvd2Rvd24uc3ViUGFyc2VyKCdoYXNoQmxvY2snKShoYXNoQmxvY2ssIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB9KTtcblxuICAvLyBhdHgtc3R5bGUgaGVhZGVyczpcbiAgLy8gICMgSGVhZGVyIDFcbiAgLy8gICMjIEhlYWRlciAyXG4gIC8vICAjIyBIZWFkZXIgMiB3aXRoIGNsb3NpbmcgaGFzaGVzICMjXG4gIC8vICAuLi5cbiAgLy8gICMjIyMjIyBIZWFkZXIgNlxuICAvL1xuICB2YXIgYXR4U3R5bGUgPSAob3B0aW9ucy5yZXF1aXJlU3BhY2VCZWZvcmVIZWFkaW5nVGV4dCkgPyAvXigjezEsNn0pWyBcXHRdKyguKz8pWyBcXHRdKiMqXFxuKy9nbSA6IC9eKCN7MSw2fSlbIFxcdF0qKC4rPylbIFxcdF0qIypcXG4rL2dtO1xuXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoYXR4U3R5bGUsIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSwgbTIpIHtcbiAgICB2YXIgaFRleHQgPSBtMjtcbiAgICBpZiAob3B0aW9ucy5jdXN0b21pemVkSGVhZGVySWQpIHtcbiAgICAgIGhUZXh0ID0gbTIucmVwbGFjZSgvXFxzP1xceyhbXntdKz8pfVxccyokLywgJycpO1xuICAgIH1cblxuICAgIHZhciBzcGFuID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShoVGV4dCwgb3B0aW9ucywgZ2xvYmFscyksXG4gICAgICAgIGhJRCA9IChvcHRpb25zLm5vSGVhZGVySWQpID8gJycgOiAnIGlkPVwiJyArIGhlYWRlcklkKG0yKSArICdcIicsXG4gICAgICAgIGhMZXZlbCA9IGhlYWRlckxldmVsU3RhcnQgLSAxICsgbTEubGVuZ3RoLFxuICAgICAgICBoZWFkZXIgPSAnPGgnICsgaExldmVsICsgaElEICsgJz4nICsgc3BhbiArICc8L2gnICsgaExldmVsICsgJz4nO1xuXG4gICAgcmV0dXJuIHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoaGVhZGVyLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgfSk7XG5cbiAgZnVuY3Rpb24gaGVhZGVySWQgKG0pIHtcbiAgICB2YXIgdGl0bGUsXG4gICAgICAgIHByZWZpeDtcblxuICAgIC8vIEl0IGlzIHNlcGFyYXRlIGZyb20gb3RoZXIgb3B0aW9ucyB0byBhbGxvdyBjb21iaW5pbmcgcHJlZml4IGFuZCBjdXN0b21pemVkXG4gICAgaWYgKG9wdGlvbnMuY3VzdG9taXplZEhlYWRlcklkKSB7XG4gICAgICB2YXIgbWF0Y2ggPSBtLm1hdGNoKC9cXHsoW157XSs/KX1cXHMqJC8pO1xuICAgICAgaWYgKG1hdGNoICYmIG1hdGNoWzFdKSB7XG4gICAgICAgIG0gPSBtYXRjaFsxXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aXRsZSA9IG07XG5cbiAgICAvLyBQcmVmaXggaWQgdG8gcHJldmVudCBjYXVzaW5nIGluYWR2ZXJ0ZW50IHByZS1leGlzdGluZyBzdHlsZSBtYXRjaGVzLlxuICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5wcmVmaXhIZWFkZXJJZCkpIHtcbiAgICAgIHByZWZpeCA9IG9wdGlvbnMucHJlZml4SGVhZGVySWQ7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnByZWZpeEhlYWRlcklkID09PSB0cnVlKSB7XG4gICAgICBwcmVmaXggPSAnc2VjdGlvbi0nO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcmVmaXggPSAnJztcbiAgICB9XG5cbiAgICBpZiAoIW9wdGlvbnMucmF3UHJlZml4SGVhZGVySWQpIHtcbiAgICAgIHRpdGxlID0gcHJlZml4ICsgdGl0bGU7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuZ2hDb21wYXRpYmxlSGVhZGVySWQpIHtcbiAgICAgIHRpdGxlID0gdGl0bGVcbiAgICAgICAgLnJlcGxhY2UoLyAvZywgJy0nKVxuICAgICAgICAvLyByZXBsYWNlIHByZXZpb3VzbHkgZXNjYXBlZCBjaGFycyAoJiwgwqggYW5kICQpXG4gICAgICAgIC5yZXBsYWNlKC8mYW1wOy9nLCAnJylcbiAgICAgICAgLnJlcGxhY2UoL8KoVC9nLCAnJylcbiAgICAgICAgLnJlcGxhY2UoL8KoRC9nLCAnJylcbiAgICAgICAgLy8gcmVwbGFjZSByZXN0IG9mIHRoZSBjaGFycyAoJn4kIGFyZSByZXBlYXRlZCBhcyB0aGV5IG1pZ2h0IGhhdmUgYmVlbiBlc2NhcGVkKVxuICAgICAgICAvLyBib3Jyb3dlZCBmcm9tIGdpdGh1YidzIHJlZGNhcnBldCAoc29tZSB0aGV5IHNob3VsZCBwcm9kdWNlIHNpbWlsYXIgcmVzdWx0cylcbiAgICAgICAgLnJlcGxhY2UoL1smKyQsXFwvOjs9P0BcIiN7fXxewqh+XFxbXFxdYFxcXFwqKSglLiEnPD5dL2csICcnKVxuICAgICAgICAudG9Mb3dlckNhc2UoKTtcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMucmF3SGVhZGVySWQpIHtcbiAgICAgIHRpdGxlID0gdGl0bGVcbiAgICAgICAgLnJlcGxhY2UoLyAvZywgJy0nKVxuICAgICAgICAvLyByZXBsYWNlIHByZXZpb3VzbHkgZXNjYXBlZCBjaGFycyAoJiwgwqggYW5kICQpXG4gICAgICAgIC5yZXBsYWNlKC8mYW1wOy9nLCAnJicpXG4gICAgICAgIC5yZXBsYWNlKC/CqFQvZywgJ8KoJylcbiAgICAgICAgLnJlcGxhY2UoL8KoRC9nLCAnJCcpXG4gICAgICAgIC8vIHJlcGxhY2UgXCIgYW5kICdcbiAgICAgICAgLnJlcGxhY2UoL1tcIiddL2csICctJylcbiAgICAgICAgLnRvTG93ZXJDYXNlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRpdGxlID0gdGl0bGVcbiAgICAgICAgLnJlcGxhY2UoL1teXFx3XS9nLCAnJylcbiAgICAgICAgLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMucmF3UHJlZml4SGVhZGVySWQpIHtcbiAgICAgIHRpdGxlID0gcHJlZml4ICsgdGl0bGU7XG4gICAgfVxuXG4gICAgaWYgKGdsb2JhbHMuaGFzaExpbmtDb3VudHNbdGl0bGVdKSB7XG4gICAgICB0aXRsZSA9IHRpdGxlICsgJy0nICsgKGdsb2JhbHMuaGFzaExpbmtDb3VudHNbdGl0bGVdKyspO1xuICAgIH0gZWxzZSB7XG4gICAgICBnbG9iYWxzLmhhc2hMaW5rQ291bnRzW3RpdGxlXSA9IDE7XG4gICAgfVxuICAgIHJldHVybiB0aXRsZTtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2hlYWRlcnMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFR1cm4gTWFya2Rvd24gbGluayBzaG9ydGN1dHMgaW50byBYSFRNTCA8YT4gdGFncy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdob3Jpem9udGFsUnVsZScsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaG9yaXpvbnRhbFJ1bGUuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgdmFyIGtleSA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaEJsb2NrJykoJzxociAvPicsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eIHswLDJ9KCA/LSl7Myx9WyBcXHRdKiQvZ20sIGtleSk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL14gezAsMn0oID9cXCopezMsfVsgXFx0XSokL2dtLCBrZXkpO1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eIHswLDJ9KCA/Xyl7Myx9WyBcXHRdKiQvZ20sIGtleSk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaG9yaXpvbnRhbFJ1bGUuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFR1cm4gTWFya2Rvd24gaW1hZ2Ugc2hvcnRjdXRzIGludG8gPGltZz4gdGFncy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdpbWFnZXMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaW1hZ2VzLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHZhciBpbmxpbmVSZWdFeHAgICAgICA9IC8hXFxbKFteXFxdXSo/KV1bIFxcdF0qKClcXChbIFxcdF0/PD8oW1xcU10rPyg/OlxcKFtcXFNdKj9cXClbXFxTXSo/KT8pPj8oPzogPShbKlxcZF0rW0EtWmEteiVdezAsNH0peChbKlxcZF0rW0EtWmEteiVdezAsNH0pKT9bIFxcdF0qKD86KFtcIiddKShbXlwiXSo/KVxcNik/WyBcXHRdP1xcKS9nLFxuICAgICAgY3JhenlSZWdFeHAgICAgICAgPSAvIVxcWyhbXlxcXV0qPyldWyBcXHRdKigpXFwoWyBcXHRdPzwoW14+XSopPig/OiA9KFsqXFxkXStbQS1aYS16JV17MCw0fSl4KFsqXFxkXStbQS1aYS16JV17MCw0fSkpP1sgXFx0XSooPzooPzooW1wiJ10pKFteXCJdKj8pXFw2KSk/WyBcXHRdP1xcKS9nLFxuICAgICAgYmFzZTY0UmVnRXhwICAgICAgPSAvIVxcWyhbXlxcXV0qPyldWyBcXHRdKigpXFwoWyBcXHRdPzw/KGRhdGE6Lis/XFwvLis/O2Jhc2U2NCxbQS1aYS16MC05Ky89XFxuXSs/KT4/KD86ID0oWypcXGRdK1tBLVphLXolXXswLDR9KXgoWypcXGRdK1tBLVphLXolXXswLDR9KSk/WyBcXHRdKig/OihbXCInXSkoW15cIl0qPylcXDYpP1sgXFx0XT9cXCkvZyxcbiAgICAgIHJlZmVyZW5jZVJlZ0V4cCAgID0gLyFcXFsoW15cXF1dKj8pXSA/KD86XFxuICopP1xcWyhbXFxzXFxTXSo/KV0oKSgpKCkoKSgpL2csXG4gICAgICByZWZTaG9ydGN1dFJlZ0V4cCA9IC8hXFxbKFteXFxbXFxdXSspXSgpKCkoKSgpKCkvZztcblxuICBmdW5jdGlvbiB3cml0ZUltYWdlVGFnQmFzZTY0ICh3aG9sZU1hdGNoLCBhbHRUZXh0LCBsaW5rSWQsIHVybCwgd2lkdGgsIGhlaWdodCwgbTUsIHRpdGxlKSB7XG4gICAgdXJsID0gdXJsLnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgcmV0dXJuIHdyaXRlSW1hZ2VUYWcgKHdob2xlTWF0Y2gsIGFsdFRleHQsIGxpbmtJZCwgdXJsLCB3aWR0aCwgaGVpZ2h0LCBtNSwgdGl0bGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gd3JpdGVJbWFnZVRhZyAod2hvbGVNYXRjaCwgYWx0VGV4dCwgbGlua0lkLCB1cmwsIHdpZHRoLCBoZWlnaHQsIG01LCB0aXRsZSkge1xuXG4gICAgdmFyIGdVcmxzICAgPSBnbG9iYWxzLmdVcmxzLFxuICAgICAgICBnVGl0bGVzID0gZ2xvYmFscy5nVGl0bGVzLFxuICAgICAgICBnRGltcyAgID0gZ2xvYmFscy5nRGltZW5zaW9ucztcblxuICAgIGxpbmtJZCA9IGxpbmtJZC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgaWYgKCF0aXRsZSkge1xuICAgICAgdGl0bGUgPSAnJztcbiAgICB9XG4gICAgLy8gU3BlY2lhbCBjYXNlIGZvciBleHBsaWNpdCBlbXB0eSB1cmxcbiAgICBpZiAod2hvbGVNYXRjaC5zZWFyY2goL1xcKDw/XFxzKj4/ID8oWydcIl0uKlsnXCJdKT9cXCkkL20pID4gLTEpIHtcbiAgICAgIHVybCA9ICcnO1xuXG4gICAgfSBlbHNlIGlmICh1cmwgPT09ICcnIHx8IHVybCA9PT0gbnVsbCkge1xuICAgICAgaWYgKGxpbmtJZCA9PT0gJycgfHwgbGlua0lkID09PSBudWxsKSB7XG4gICAgICAgIC8vIGxvd2VyLWNhc2UgYW5kIHR1cm4gZW1iZWRkZWQgbmV3bGluZXMgaW50byBzcGFjZXNcbiAgICAgICAgbGlua0lkID0gYWx0VGV4dC50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoLyA/XFxuL2csICcgJyk7XG4gICAgICB9XG4gICAgICB1cmwgPSAnIycgKyBsaW5rSWQ7XG5cbiAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGdVcmxzW2xpbmtJZF0pKSB7XG4gICAgICAgIHVybCA9IGdVcmxzW2xpbmtJZF07XG4gICAgICAgIGlmICghc2hvd2Rvd24uaGVscGVyLmlzVW5kZWZpbmVkKGdUaXRsZXNbbGlua0lkXSkpIHtcbiAgICAgICAgICB0aXRsZSA9IGdUaXRsZXNbbGlua0lkXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChnRGltc1tsaW5rSWRdKSkge1xuICAgICAgICAgIHdpZHRoID0gZ0RpbXNbbGlua0lkXS53aWR0aDtcbiAgICAgICAgICBoZWlnaHQgPSBnRGltc1tsaW5rSWRdLmhlaWdodDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHdob2xlTWF0Y2g7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYWx0VGV4dCA9IGFsdFRleHRcbiAgICAgIC5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JylcbiAgICAvL2FsdFRleHQgPSBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyhhbHRUZXh0LCAnKl8nLCBmYWxzZSk7XG4gICAgICAucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgLy91cmwgPSBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVycyh1cmwsICcqXycsIGZhbHNlKTtcbiAgICB1cmwgPSB1cmwucmVwbGFjZShzaG93ZG93bi5oZWxwZXIucmVnZXhlcy5hc3Rlcmlza0Rhc2hBbmRDb2xvbiwgc2hvd2Rvd24uaGVscGVyLmVzY2FwZUNoYXJhY3RlcnNDYWxsYmFjayk7XG4gICAgdmFyIHJlc3VsdCA9ICc8aW1nIHNyYz1cIicgKyB1cmwgKyAnXCIgYWx0PVwiJyArIGFsdFRleHQgKyAnXCInO1xuXG4gICAgaWYgKHRpdGxlICYmIHNob3dkb3duLmhlbHBlci5pc1N0cmluZyh0aXRsZSkpIHtcbiAgICAgIHRpdGxlID0gdGl0bGVcbiAgICAgICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKVxuICAgICAgLy90aXRsZSA9IHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzKHRpdGxlLCAnKl8nLCBmYWxzZSk7XG4gICAgICAgIC5yZXBsYWNlKHNob3dkb3duLmhlbHBlci5yZWdleGVzLmFzdGVyaXNrRGFzaEFuZENvbG9uLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcbiAgICAgIHJlc3VsdCArPSAnIHRpdGxlPVwiJyArIHRpdGxlICsgJ1wiJztcbiAgICB9XG5cbiAgICBpZiAod2lkdGggJiYgaGVpZ2h0KSB7XG4gICAgICB3aWR0aCAgPSAod2lkdGggPT09ICcqJykgPyAnYXV0bycgOiB3aWR0aDtcbiAgICAgIGhlaWdodCA9IChoZWlnaHQgPT09ICcqJykgPyAnYXV0bycgOiBoZWlnaHQ7XG5cbiAgICAgIHJlc3VsdCArPSAnIHdpZHRoPVwiJyArIHdpZHRoICsgJ1wiJztcbiAgICAgIHJlc3VsdCArPSAnIGhlaWdodD1cIicgKyBoZWlnaHQgKyAnXCInO1xuICAgIH1cblxuICAgIHJlc3VsdCArPSAnIC8+JztcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLyBGaXJzdCwgaGFuZGxlIHJlZmVyZW5jZS1zdHlsZSBsYWJlbGVkIGltYWdlczogIVthbHQgdGV4dF1baWRdXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UocmVmZXJlbmNlUmVnRXhwLCB3cml0ZUltYWdlVGFnKTtcblxuICAvLyBOZXh0LCBoYW5kbGUgaW5saW5lIGltYWdlczogICFbYWx0IHRleHRdKHVybCA9PHdpZHRoPng8aGVpZ2h0PiBcIm9wdGlvbmFsIHRpdGxlXCIpXG5cbiAgLy8gYmFzZTY0IGVuY29kZWQgaW1hZ2VzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoYmFzZTY0UmVnRXhwLCB3cml0ZUltYWdlVGFnQmFzZTY0KTtcblxuICAvLyBjYXNlcyB3aXRoIGNyYXp5IHVybHMgbGlrZSAuL2ltYWdlL2NhdDEpLnBuZ1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGNyYXp5UmVnRXhwLCB3cml0ZUltYWdlVGFnKTtcblxuICAvLyBub3JtYWwgY2FzZXNcbiAgdGV4dCA9IHRleHQucmVwbGFjZShpbmxpbmVSZWdFeHAsIHdyaXRlSW1hZ2VUYWcpO1xuXG4gIC8vIGhhbmRsZSByZWZlcmVuY2Utc3R5bGUgc2hvcnRjdXRzOiAhW2ltZyB0ZXh0XVxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlZlNob3J0Y3V0UmVnRXhwLCB3cml0ZUltYWdlVGFnKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdpbWFnZXMuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2l0YWxpY3NBbmRCb2xkJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ2l0YWxpY3NBbmRCb2xkLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIGl0J3MgZmFzdGVyIHRvIGhhdmUgMyBzZXBhcmF0ZSByZWdleGVzIGZvciBlYWNoIGNhc2UgdGhhbiBoYXZlIGp1c3Qgb25lXG4gIC8vIGJlY2F1c2Ugb2YgYmFja3RyYWNpbmcsIGluIHNvbWUgY2FzZXMsIGl0IGNvdWxkIGxlYWQgdG8gYW4gZXhwb25lbnRpYWwgZWZmZWN0XG4gIC8vIGNhbGxlZCBcImNhdGFzdHJvcGhpYyBiYWNrdHJhY2VcIi4gT21pbm91cyFcblxuICBmdW5jdGlvbiBwYXJzZUluc2lkZSAodHh0LCBsZWZ0LCByaWdodCkge1xuICAgIC8qXG4gICAgaWYgKG9wdGlvbnMuc2ltcGxpZmllZEF1dG9MaW5rKSB7XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NpbXBsaWZpZWRBdXRvTGlua3MnKSh0eHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIH1cbiAgICAqL1xuICAgIHJldHVybiBsZWZ0ICsgdHh0ICsgcmlnaHQ7XG4gIH1cblxuICAvLyBQYXJzZSB1bmRlcnNjb3Jlc1xuICBpZiAob3B0aW9ucy5saXRlcmFsTWlkV29yZFVuZGVyc2NvcmVzKSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxiX19fKFxcU1tcXHNcXFNdKj8pX19fXFxiL2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnNpZGUgKHR4dCwgJzxzdHJvbmc+PGVtPicsICc8L2VtPjwvc3Ryb25nPicpO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcYl9fKFxcU1tcXHNcXFNdKj8pX19cXGIvZywgZnVuY3Rpb24gKHdtLCB0eHQpIHtcbiAgICAgIHJldHVybiBwYXJzZUluc2lkZSAodHh0LCAnPHN0cm9uZz4nLCAnPC9zdHJvbmc+Jyk7XG4gICAgfSk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxiXyhcXFNbXFxzXFxTXSo/KV9cXGIvZywgZnVuY3Rpb24gKHdtLCB0eHQpIHtcbiAgICAgIHJldHVybiBwYXJzZUluc2lkZSAodHh0LCAnPGVtPicsICc8L2VtPicpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL19fXyhcXFNbXFxzXFxTXSo/KV9fXy9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gcGFyc2VJbnNpZGUgKG0sICc8c3Ryb25nPjxlbT4nLCAnPC9lbT48L3N0cm9uZz4nKSA6IHdtO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL19fKFxcU1tcXHNcXFNdKj8pX18vZywgZnVuY3Rpb24gKHdtLCBtKSB7XG4gICAgICByZXR1cm4gKC9cXFMkLy50ZXN0KG0pKSA/IHBhcnNlSW5zaWRlIChtLCAnPHN0cm9uZz4nLCAnPC9zdHJvbmc+JykgOiB3bTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9fKFteXFxzX11bXFxzXFxTXSo/KV8vZywgZnVuY3Rpb24gKHdtLCBtKSB7XG4gICAgICAvLyAhL15fW15fXS8udGVzdChtKSAtIHRlc3QgaWYgaXQgZG9lc24ndCBzdGFydCB3aXRoIF9fIChzaW5jZSBpdCBzZWVtcyByZWR1bmRhbnQsIHdlIHJlbW92ZWQgaXQpXG4gICAgICByZXR1cm4gKC9cXFMkLy50ZXN0KG0pKSA/IHBhcnNlSW5zaWRlIChtLCAnPGVtPicsICc8L2VtPicpIDogd207XG4gICAgfSk7XG4gIH1cblxuICAvLyBOb3cgcGFyc2UgYXN0ZXJpc2tzXG4gIGlmIChvcHRpb25zLmxpdGVyYWxNaWRXb3JkQXN0ZXJpc2tzKSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvKFteKl18XilcXEJcXCpcXCpcXCooXFxTW1xcc1xcU10qPylcXCpcXCpcXCpcXEIoPyFcXCopL2csIGZ1bmN0aW9uICh3bSwgbGVhZCwgdHh0KSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnNpZGUgKHR4dCwgbGVhZCArICc8c3Ryb25nPjxlbT4nLCAnPC9lbT48L3N0cm9uZz4nKTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC8oW14qXXxeKVxcQlxcKlxcKihcXFNbXFxzXFxTXSo/KVxcKlxcKlxcQig/IVxcKikvZywgZnVuY3Rpb24gKHdtLCBsZWFkLCB0eHQpIHtcbiAgICAgIHJldHVybiBwYXJzZUluc2lkZSAodHh0LCBsZWFkICsgJzxzdHJvbmc+JywgJzwvc3Ryb25nPicpO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhbXipdfF4pXFxCXFwqKFxcU1tcXHNcXFNdKj8pXFwqXFxCKD8hXFwqKS9nLCBmdW5jdGlvbiAod20sIGxlYWQsIHR4dCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW5zaWRlICh0eHQsIGxlYWQgKyAnPGVtPicsICc8L2VtPicpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcKlxcKlxcKihcXFNbXFxzXFxTXSo/KVxcKlxcKlxcKi9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gcGFyc2VJbnNpZGUgKG0sICc8c3Ryb25nPjxlbT4nLCAnPC9lbT48L3N0cm9uZz4nKSA6IHdtO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcKlxcKihcXFNbXFxzXFxTXSo/KVxcKlxcKi9nLCBmdW5jdGlvbiAod20sIG0pIHtcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gcGFyc2VJbnNpZGUgKG0sICc8c3Ryb25nPicsICc8L3N0cm9uZz4nKSA6IHdtO1xuICAgIH0pO1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcKihbXlxccypdW1xcc1xcU10qPylcXCovZywgZnVuY3Rpb24gKHdtLCBtKSB7XG4gICAgICAvLyAhL15cXCpbXipdLy50ZXN0KG0pIC0gdGVzdCBpZiBpdCBkb2Vzbid0IHN0YXJ0IHdpdGggKiogKHNpbmNlIGl0IHNlZW1zIHJlZHVuZGFudCwgd2UgcmVtb3ZlZCBpdClcbiAgICAgIHJldHVybiAoL1xcUyQvLnRlc3QobSkpID8gcGFyc2VJbnNpZGUgKG0sICc8ZW0+JywgJzwvZW0+JykgOiB3bTtcbiAgICB9KTtcbiAgfVxuXG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnaXRhbGljc0FuZEJvbGQuYWZ0ZXInLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIEZvcm0gSFRNTCBvcmRlcmVkIChudW1iZXJlZCkgYW5kIHVub3JkZXJlZCAoYnVsbGV0ZWQpIGxpc3RzLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ2xpc3RzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qKlxuICAgKiBQcm9jZXNzIHRoZSBjb250ZW50cyBvZiBhIHNpbmdsZSBvcmRlcmVkIG9yIHVub3JkZXJlZCBsaXN0LCBzcGxpdHRpbmcgaXRcbiAgICogaW50byBpbmRpdmlkdWFsIGxpc3QgaXRlbXMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsaXN0U3RyXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gdHJpbVRyYWlsaW5nXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICBmdW5jdGlvbiBwcm9jZXNzTGlzdEl0ZW1zIChsaXN0U3RyLCB0cmltVHJhaWxpbmcpIHtcbiAgICAvLyBUaGUgJGdfbGlzdF9sZXZlbCBnbG9iYWwga2VlcHMgdHJhY2sgb2Ygd2hlbiB3ZSdyZSBpbnNpZGUgYSBsaXN0LlxuICAgIC8vIEVhY2ggdGltZSB3ZSBlbnRlciBhIGxpc3QsIHdlIGluY3JlbWVudCBpdDsgd2hlbiB3ZSBsZWF2ZSBhIGxpc3QsXG4gICAgLy8gd2UgZGVjcmVtZW50LiBJZiBpdCdzIHplcm8sIHdlJ3JlIG5vdCBpbiBhIGxpc3QgYW55bW9yZS5cbiAgICAvL1xuICAgIC8vIFdlIGRvIHRoaXMgYmVjYXVzZSB3aGVuIHdlJ3JlIG5vdCBpbnNpZGUgYSBsaXN0LCB3ZSB3YW50IHRvIHRyZWF0XG4gICAgLy8gc29tZXRoaW5nIGxpa2UgdGhpczpcbiAgICAvL1xuICAgIC8vICAgIEkgcmVjb21tZW5kIHVwZ3JhZGluZyB0byB2ZXJzaW9uXG4gICAgLy8gICAgOC4gT29wcywgbm93IHRoaXMgbGluZSBpcyB0cmVhdGVkXG4gICAgLy8gICAgYXMgYSBzdWItbGlzdC5cbiAgICAvL1xuICAgIC8vIEFzIGEgc2luZ2xlIHBhcmFncmFwaCwgZGVzcGl0ZSB0aGUgZmFjdCB0aGF0IHRoZSBzZWNvbmQgbGluZSBzdGFydHNcbiAgICAvLyB3aXRoIGEgZGlnaXQtcGVyaW9kLXNwYWNlIHNlcXVlbmNlLlxuICAgIC8vXG4gICAgLy8gV2hlcmVhcyB3aGVuIHdlJ3JlIGluc2lkZSBhIGxpc3QgKG9yIHN1Yi1saXN0KSwgdGhhdCBsaW5lIHdpbGwgYmVcbiAgICAvLyB0cmVhdGVkIGFzIHRoZSBzdGFydCBvZiBhIHN1Yi1saXN0LiBXaGF0IGEga2x1ZGdlLCBodWg/IFRoaXMgaXNcbiAgICAvLyBhbiBhc3BlY3Qgb2YgTWFya2Rvd24ncyBzeW50YXggdGhhdCdzIGhhcmQgdG8gcGFyc2UgcGVyZmVjdGx5XG4gICAgLy8gd2l0aG91dCByZXNvcnRpbmcgdG8gbWluZC1yZWFkaW5nLiBQZXJoYXBzIHRoZSBzb2x1dGlvbiBpcyB0b1xuICAgIC8vIGNoYW5nZSB0aGUgc3ludGF4IHJ1bGVzIHN1Y2ggdGhhdCBzdWItbGlzdHMgbXVzdCBzdGFydCB3aXRoIGFcbiAgICAvLyBzdGFydGluZyBjYXJkaW5hbCBudW1iZXI7IGUuZy4gXCIxLlwiIG9yIFwiYS5cIi5cbiAgICBnbG9iYWxzLmdMaXN0TGV2ZWwrKztcblxuICAgIC8vIHRyaW0gdHJhaWxpbmcgYmxhbmsgbGluZXM6XG4gICAgbGlzdFN0ciA9IGxpc3RTdHIucmVwbGFjZSgvXFxuezIsfSQvLCAnXFxuJyk7XG5cbiAgICAvLyBhdHRhY2tsYWI6IGFkZCBzZW50aW5lbCB0byBlbXVsYXRlIFxcelxuICAgIGxpc3RTdHIgKz0gJ8KoMCc7XG5cbiAgICB2YXIgcmd4ID0gLyhcXG4pPyheIHswLDN9KShbKistXXxcXGQrWy5dKVsgXFx0XSsoKFxcWyh4fFh8ICk/XSk/WyBcXHRdKlteXFxyXSs/KFxcbnsxLDJ9KSkoPz1cXG4qKMKoMHwgezAsM30oWyorLV18XFxkK1suXSlbIFxcdF0rKSkvZ20sXG4gICAgICAgIGlzUGFyYWdyYXBoZWQgPSAoL1xcblsgXFx0XSpcXG4oPyHCqDApLy50ZXN0KGxpc3RTdHIpKTtcblxuICAgIC8vIFNpbmNlIHZlcnNpb24gMS41LCBuZXN0aW5nIHN1Ymxpc3RzIHJlcXVpcmVzIDQgc3BhY2VzIChvciAxIHRhYikgaW5kZW50YXRpb24sXG4gICAgLy8gd2hpY2ggaXMgYSBzeW50YXggYnJlYWtpbmcgY2hhbmdlXG4gICAgLy8gYWN0aXZhdGluZyB0aGlzIG9wdGlvbiByZXZlcnRzIHRvIG9sZCBiZWhhdmlvclxuICAgIGlmIChvcHRpb25zLmRpc2FibGVGb3JjZWQ0U3BhY2VzSW5kZW50ZWRTdWJsaXN0cykge1xuICAgICAgcmd4ID0gLyhcXG4pPyheIHswLDN9KShbKistXXxcXGQrWy5dKVsgXFx0XSsoKFxcWyh4fFh8ICk/XSk/WyBcXHRdKlteXFxyXSs/KFxcbnsxLDJ9KSkoPz1cXG4qKMKoMHxcXDIoWyorLV18XFxkK1suXSlbIFxcdF0rKSkvZ207XG4gICAgfVxuXG4gICAgbGlzdFN0ciA9IGxpc3RTdHIucmVwbGFjZShyZ3gsIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSwgbTIsIG0zLCBtNCwgdGFza2J0biwgY2hlY2tlZCkge1xuICAgICAgY2hlY2tlZCA9IChjaGVja2VkICYmIGNoZWNrZWQudHJpbSgpICE9PSAnJyk7XG5cbiAgICAgIHZhciBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdvdXRkZW50JykobTQsIG9wdGlvbnMsIGdsb2JhbHMpLFxuICAgICAgICAgIGJ1bGxldFN0eWxlID0gJyc7XG5cbiAgICAgIC8vIFN1cHBvcnQgZm9yIGdpdGh1YiB0YXNrbGlzdHNcbiAgICAgIGlmICh0YXNrYnRuICYmIG9wdGlvbnMudGFza2xpc3RzKSB7XG4gICAgICAgIGJ1bGxldFN0eWxlID0gJyBjbGFzcz1cInRhc2stbGlzdC1pdGVtXCIgc3R5bGU9XCJsaXN0LXN0eWxlLXR5cGU6IG5vbmU7XCInO1xuICAgICAgICBpdGVtID0gaXRlbS5yZXBsYWNlKC9eWyBcXHRdKlxcWyh4fFh8ICk/XS9tLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIG90cCA9ICc8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgZGlzYWJsZWQgc3R5bGU9XCJtYXJnaW46IDBweCAwLjM1ZW0gMC4yNWVtIC0xLjZlbTsgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcIic7XG4gICAgICAgICAgaWYgKGNoZWNrZWQpIHtcbiAgICAgICAgICAgIG90cCArPSAnIGNoZWNrZWQnO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvdHAgKz0gJz4nO1xuICAgICAgICAgIHJldHVybiBvdHA7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyBJU1NVRSAjMzEyXG4gICAgICAvLyBUaGlzIGlucHV0OiAtIC0gLSBhXG4gICAgICAvLyBjYXVzZXMgdHJvdWJsZSB0byB0aGUgcGFyc2VyLCBzaW5jZSBpdCBpbnRlcnByZXRzIGl0IGFzOlxuICAgICAgLy8gPHVsPjxsaT48bGk+PGxpPmE8L2xpPjwvbGk+PC9saT48L3VsPlxuICAgICAgLy8gaW5zdGVhZCBvZjpcbiAgICAgIC8vIDx1bD48bGk+LSAtIGE8L2xpPjwvdWw+XG4gICAgICAvLyBTbywgdG8gcHJldmVudCBpdCwgd2Ugd2lsbCBwdXQgYSBtYXJrZXIgKMKoQSlpbiB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5lXG4gICAgICAvLyBLaW5kIG9mIGhhY2tpc2gvbW9ua2V5IHBhdGNoaW5nLCBidXQgc2VlbXMgbW9yZSBlZmZlY3RpdmUgdGhhbiBvdmVyY29tcGxpY2F0aW5nIHRoZSBsaXN0IHBhcnNlclxuICAgICAgaXRlbSA9IGl0ZW0ucmVwbGFjZSgvXihbLSorXXxcXGRcXC4pWyBcXHRdK1tcXFNcXG4gXSovZywgZnVuY3Rpb24gKHdtMikge1xuICAgICAgICByZXR1cm4gJ8KoQScgKyB3bTI7XG4gICAgICB9KTtcblxuICAgICAgLy8gbTEgLSBMZWFkaW5nIGxpbmUgb3JcbiAgICAgIC8vIEhhcyBhIGRvdWJsZSByZXR1cm4gKG11bHRpIHBhcmFncmFwaCkgb3JcbiAgICAgIC8vIEhhcyBzdWJsaXN0XG4gICAgICBpZiAobTEgfHwgKGl0ZW0uc2VhcmNoKC9cXG57Mix9LykgPiAtMSkpIHtcbiAgICAgICAgaXRlbSA9IHNob3dkb3duLnN1YlBhcnNlcignZ2l0aHViQ29kZUJsb2NrcycpKGl0ZW0sIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdibG9ja0dhbXV0JykoaXRlbSwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBSZWN1cnNpb24gZm9yIHN1Yi1saXN0czpcbiAgICAgICAgaXRlbSA9IHNob3dkb3duLnN1YlBhcnNlcignbGlzdHMnKShpdGVtLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgICAgaXRlbSA9IGl0ZW0ucmVwbGFjZSgvXFxuJC8sICcnKTsgLy8gY2hvbXAoaXRlbSlcbiAgICAgICAgaXRlbSA9IHNob3dkb3duLnN1YlBhcnNlcignaGFzaEhUTUxCbG9ja3MnKShpdGVtLCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAgICAgICAvLyBDb2xhcHNlIGRvdWJsZSBsaW5lYnJlYWtzXG4gICAgICAgIGl0ZW0gPSBpdGVtLnJlcGxhY2UoL1xcblxcbisvZywgJ1xcblxcbicpO1xuICAgICAgICBpZiAoaXNQYXJhZ3JhcGhlZCkge1xuICAgICAgICAgIGl0ZW0gPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3BhcmFncmFwaHMnKShpdGVtLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpdGVtID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShpdGVtLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBub3cgd2UgbmVlZCB0byByZW1vdmUgdGhlIG1hcmtlciAowqhBKVxuICAgICAgaXRlbSA9IGl0ZW0ucmVwbGFjZSgnwqhBJywgJycpO1xuICAgICAgLy8gd2UgY2FuIGZpbmFsbHkgd3JhcCB0aGUgbGluZSBpbiBsaXN0IGl0ZW0gdGFnc1xuICAgICAgaXRlbSA9ICAnPGxpJyArIGJ1bGxldFN0eWxlICsgJz4nICsgaXRlbSArICc8L2xpPlxcbic7XG5cbiAgICAgIHJldHVybiBpdGVtO1xuICAgIH0pO1xuXG4gICAgLy8gYXR0YWNrbGFiOiBzdHJpcCBzZW50aW5lbFxuICAgIGxpc3RTdHIgPSBsaXN0U3RyLnJlcGxhY2UoL8KoMC9nLCAnJyk7XG5cbiAgICBnbG9iYWxzLmdMaXN0TGV2ZWwtLTtcblxuICAgIGlmICh0cmltVHJhaWxpbmcpIHtcbiAgICAgIGxpc3RTdHIgPSBsaXN0U3RyLnJlcGxhY2UoL1xccyskLywgJycpO1xuICAgIH1cblxuICAgIHJldHVybiBsaXN0U3RyO1xuICB9XG5cbiAgZnVuY3Rpb24gc3R5bGVTdGFydE51bWJlciAobGlzdCwgbGlzdFR5cGUpIHtcbiAgICAvLyBjaGVjayBpZiBvbCBhbmQgc3RhcnRzIGJ5IGEgbnVtYmVyIGRpZmZlcmVudCB0aGFuIDFcbiAgICBpZiAobGlzdFR5cGUgPT09ICdvbCcpIHtcbiAgICAgIHZhciByZXMgPSBsaXN0Lm1hdGNoKC9eICooXFxkKylcXC4vKTtcbiAgICAgIGlmIChyZXMgJiYgcmVzWzFdICE9PSAnMScpIHtcbiAgICAgICAgcmV0dXJuICcgc3RhcnQ9XCInICsgcmVzWzFdICsgJ1wiJztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGFuZCBwYXJzZSBjb25zZWN1dGl2ZSBsaXN0cyAoYmV0dGVyIGZpeCBmb3IgaXNzdWUgIzE0MilcbiAgICogQHBhcmFtIHtzdHJpbmd9IGxpc3RcbiAgICogQHBhcmFtIHtzdHJpbmd9IGxpc3RUeXBlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gdHJpbVRyYWlsaW5nXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICBmdW5jdGlvbiBwYXJzZUNvbnNlY3V0aXZlTGlzdHMgKGxpc3QsIGxpc3RUeXBlLCB0cmltVHJhaWxpbmcpIHtcbiAgICAvLyBjaGVjayBpZiB3ZSBjYXVnaHQgMiBvciBtb3JlIGNvbnNlY3V0aXZlIGxpc3RzIGJ5IG1pc3Rha2VcbiAgICAvLyB3ZSB1c2UgdGhlIGNvdW50ZXJSZ3gsIG1lYW5pbmcgaWYgbGlzdFR5cGUgaXMgVUwgd2UgbG9vayBmb3IgT0wgYW5kIHZpY2UgdmVyc2FcbiAgICB2YXIgb2xSZ3ggPSAob3B0aW9ucy5kaXNhYmxlRm9yY2VkNFNwYWNlc0luZGVudGVkU3VibGlzdHMpID8gL14gP1xcZCtcXC5bIFxcdF0vZ20gOiAvXiB7MCwzfVxcZCtcXC5bIFxcdF0vZ20sXG4gICAgICAgIHVsUmd4ID0gKG9wdGlvbnMuZGlzYWJsZUZvcmNlZDRTcGFjZXNJbmRlbnRlZFN1Ymxpc3RzKSA/IC9eID9bKistXVsgXFx0XS9nbSA6IC9eIHswLDN9WyorLV1bIFxcdF0vZ20sXG4gICAgICAgIGNvdW50ZXJSeGcgPSAobGlzdFR5cGUgPT09ICd1bCcpID8gb2xSZ3ggOiB1bFJneCxcbiAgICAgICAgcmVzdWx0ID0gJyc7XG5cbiAgICBpZiAobGlzdC5zZWFyY2goY291bnRlclJ4ZykgIT09IC0xKSB7XG4gICAgICAoZnVuY3Rpb24gcGFyc2VDTCAodHh0KSB7XG4gICAgICAgIHZhciBwb3MgPSB0eHQuc2VhcmNoKGNvdW50ZXJSeGcpLFxuICAgICAgICAgICAgc3R5bGUgPSBzdHlsZVN0YXJ0TnVtYmVyKGxpc3QsIGxpc3RUeXBlKTtcbiAgICAgICAgaWYgKHBvcyAhPT0gLTEpIHtcbiAgICAgICAgICAvLyBzbGljZVxuICAgICAgICAgIHJlc3VsdCArPSAnXFxuXFxuPCcgKyBsaXN0VHlwZSArIHN0eWxlICsgJz5cXG4nICsgcHJvY2Vzc0xpc3RJdGVtcyh0eHQuc2xpY2UoMCwgcG9zKSwgISF0cmltVHJhaWxpbmcpICsgJzwvJyArIGxpc3RUeXBlICsgJz5cXG4nO1xuXG4gICAgICAgICAgLy8gaW52ZXJ0IGNvdW50ZXJUeXBlIGFuZCBsaXN0VHlwZVxuICAgICAgICAgIGxpc3RUeXBlID0gKGxpc3RUeXBlID09PSAndWwnKSA/ICdvbCcgOiAndWwnO1xuICAgICAgICAgIGNvdW50ZXJSeGcgPSAobGlzdFR5cGUgPT09ICd1bCcpID8gb2xSZ3ggOiB1bFJneDtcblxuICAgICAgICAgIC8vcmVjdXJzZVxuICAgICAgICAgIHBhcnNlQ0wodHh0LnNsaWNlKHBvcykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc3VsdCArPSAnXFxuXFxuPCcgKyBsaXN0VHlwZSArIHN0eWxlICsgJz5cXG4nICsgcHJvY2Vzc0xpc3RJdGVtcyh0eHQsICEhdHJpbVRyYWlsaW5nKSArICc8LycgKyBsaXN0VHlwZSArICc+XFxuJztcbiAgICAgICAgfVxuICAgICAgfSkobGlzdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBzdHlsZSA9IHN0eWxlU3RhcnROdW1iZXIobGlzdCwgbGlzdFR5cGUpO1xuICAgICAgcmVzdWx0ID0gJ1xcblxcbjwnICsgbGlzdFR5cGUgKyBzdHlsZSArICc+XFxuJyArIHByb2Nlc3NMaXN0SXRlbXMobGlzdCwgISF0cmltVHJhaWxpbmcpICsgJzwvJyArIGxpc3RUeXBlICsgJz5cXG4nO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKiogU3RhcnQgb2YgbGlzdCBwYXJzaW5nICoqL1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdsaXN0cy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgLy8gYWRkIHNlbnRpbmVsIHRvIGhhY2sgYXJvdW5kIGtodG1sL3NhZmFyaSBidWc6XG4gIC8vIGh0dHA6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTExMjMxXG4gIHRleHQgKz0gJ8KoMCc7XG5cbiAgaWYgKGdsb2JhbHMuZ0xpc3RMZXZlbCkge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL14oKCB7MCwzfShbKistXXxcXGQrWy5dKVsgXFx0XSspW15cXHJdKz8owqgwfFxcbnsyLH0oPz1cXFMpKD8hWyBcXHRdKig/OlsqKy1dfFxcZCtbLl0pWyBcXHRdKykpKS9nbSxcbiAgICAgIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBsaXN0LCBtMikge1xuICAgICAgICB2YXIgbGlzdFR5cGUgPSAobTIuc2VhcmNoKC9bKistXS9nKSA+IC0xKSA/ICd1bCcgOiAnb2wnO1xuICAgICAgICByZXR1cm4gcGFyc2VDb25zZWN1dGl2ZUxpc3RzKGxpc3QsIGxpc3RUeXBlLCB0cnVlKTtcbiAgICAgIH1cbiAgICApO1xuICB9IGVsc2Uge1xuICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoLyhcXG5cXG58Xlxcbj8pKCggezAsM30oWyorLV18XFxkK1suXSlbIFxcdF0rKVteXFxyXSs/KMKoMHxcXG57Mix9KD89XFxTKSg/IVsgXFx0XSooPzpbKistXXxcXGQrWy5dKVsgXFx0XSspKSkvZ20sXG4gICAgICBmdW5jdGlvbiAod2hvbGVNYXRjaCwgbTEsIGxpc3QsIG0zKSB7XG4gICAgICAgIHZhciBsaXN0VHlwZSA9IChtMy5zZWFyY2goL1sqKy1dL2cpID4gLTEpID8gJ3VsJyA6ICdvbCc7XG4gICAgICAgIHJldHVybiBwYXJzZUNvbnNlY3V0aXZlTGlzdHMobGlzdCwgbGlzdFR5cGUsIGZhbHNlKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgLy8gc3RyaXAgc2VudGluZWxcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqgwLywgJycpO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdsaXN0cy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogUGFyc2UgbWV0YWRhdGEgYXQgdGhlIHRvcCBvZiB0aGUgZG9jdW1lbnRcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdtZXRhZGF0YScsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBpZiAoIW9wdGlvbnMubWV0YWRhdGEpIHtcbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ21ldGFkYXRhLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIGZ1bmN0aW9uIHBhcnNlTWV0YWRhdGFDb250ZW50cyAoY29udGVudCkge1xuICAgIC8vIHJhdyBpcyByYXcgc28gaXQncyBub3QgY2hhbmdlZCBpbiBhbnkgd2F5XG4gICAgZ2xvYmFscy5tZXRhZGF0YS5yYXcgPSBjb250ZW50O1xuXG4gICAgLy8gZXNjYXBlIGNoYXJzIGZvcmJpZGRlbiBpbiBodG1sIGF0dHJpYnV0ZXNcbiAgICAvLyBkb3VibGUgcXVvdGVzXG4gICAgY29udGVudCA9IGNvbnRlbnRcbiAgICAgIC8vIGFtcGVyc2FuZCBmaXJzdFxuICAgICAgLnJlcGxhY2UoLyYvZywgJyZhbXA7JylcbiAgICAgIC8vIGRvdWJsZSBxdW90ZXNcbiAgICAgIC5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7Jyk7XG5cbiAgICBjb250ZW50ID0gY29udGVudC5yZXBsYWNlKC9cXG4gezR9L2csICcgJyk7XG4gICAgY29udGVudC5yZXBsYWNlKC9eKFtcXFMgXSspOiArKFtcXHNcXFNdKz8pJC9nbSwgZnVuY3Rpb24gKHdtLCBrZXksIHZhbHVlKSB7XG4gICAgICBnbG9iYWxzLm1ldGFkYXRhLnBhcnNlZFtrZXldID0gdmFsdWU7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfSk7XG4gIH1cblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eXFxzKsKrwqvCqysoXFxTKj8pXFxuKFtcXHNcXFNdKz8pXFxuwrvCu8K7K1xcbi8sIGZ1bmN0aW9uICh3aG9sZW1hdGNoLCBmb3JtYXQsIGNvbnRlbnQpIHtcbiAgICBwYXJzZU1ldGFkYXRhQ29udGVudHMoY29udGVudCk7XG4gICAgcmV0dXJuICfCqE0nO1xuICB9KTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eXFxzKi0tLSsoXFxTKj8pXFxuKFtcXHNcXFNdKz8pXFxuLS0tK1xcbi8sIGZ1bmN0aW9uICh3aG9sZW1hdGNoLCBmb3JtYXQsIGNvbnRlbnQpIHtcbiAgICBpZiAoZm9ybWF0KSB7XG4gICAgICBnbG9iYWxzLm1ldGFkYXRhLmZvcm1hdCA9IGZvcm1hdDtcbiAgICB9XG4gICAgcGFyc2VNZXRhZGF0YUNvbnRlbnRzKGNvbnRlbnQpO1xuICAgIHJldHVybiAnwqhNJztcbiAgfSk7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqhNL2csICcnKTtcblxuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdtZXRhZGF0YS5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogUmVtb3ZlIG9uZSBsZXZlbCBvZiBsaW5lLWxlYWRpbmcgdGFicyBvciBzcGFjZXNcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdvdXRkZW50JywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCdvdXRkZW50LmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIGF0dGFja2xhYjogaGFjayBhcm91bmQgS29ucXVlcm9yIDMuNS40IGJ1ZzpcbiAgLy8gXCItLS0tLS0tLS0tYnVnXCIucmVwbGFjZSgvXi0vZyxcIlwiKSA9PSBcImJ1Z1wiXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL14oXFx0fFsgXXsxLDR9KS9nbSwgJ8KoMCcpOyAvLyBhdHRhY2tsYWI6IGdfdGFiX3dpZHRoXG5cbiAgLy8gYXR0YWNrbGFiOiBjbGVhbiB1cCBoYWNrXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL8KoMC9nLCAnJyk7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnb3V0ZGVudC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICpcbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdwYXJhZ3JhcGhzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3BhcmFncmFwaHMuYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIC8vIFN0cmlwIGxlYWRpbmcgYW5kIHRyYWlsaW5nIGxpbmVzOlxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eXFxuKy9nLCAnJyk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcbiskL2csICcnKTtcblxuICB2YXIgZ3JhZnMgPSB0ZXh0LnNwbGl0KC9cXG57Mix9L2cpLFxuICAgICAgZ3JhZnNPdXQgPSBbXSxcbiAgICAgIGVuZCA9IGdyYWZzLmxlbmd0aDsgLy8gV3JhcCA8cD4gdGFnc1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZW5kOyBpKyspIHtcbiAgICB2YXIgc3RyID0gZ3JhZnNbaV07XG4gICAgLy8gaWYgdGhpcyBpcyBhbiBIVE1MIG1hcmtlciwgY29weSBpdFxuICAgIGlmIChzdHIuc2VhcmNoKC/CqChLfEcpKFxcZCspXFwxL2cpID49IDApIHtcbiAgICAgIGdyYWZzT3V0LnB1c2goc3RyKTtcblxuICAgIC8vIHRlc3QgZm9yIHByZXNlbmNlIG9mIGNoYXJhY3RlcnMgdG8gcHJldmVudCBlbXB0eSBsaW5lcyBiZWluZyBwYXJzZWRcbiAgICAvLyBhcyBwYXJhZ3JhcGhzIChyZXN1bHRpbmcgaW4gdW5kZXNpcmVkIGV4dHJhIGVtcHR5IHBhcmFncmFwaHMpXG4gICAgfSBlbHNlIGlmIChzdHIuc2VhcmNoKC9cXFMvKSA+PSAwKSB7XG4gICAgICBzdHIgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NwYW5HYW11dCcpKHN0ciwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICBzdHIgPSBzdHIucmVwbGFjZSgvXihbIFxcdF0qKS9nLCAnPHA+Jyk7XG4gICAgICBzdHIgKz0gJzwvcD4nO1xuICAgICAgZ3JhZnNPdXQucHVzaChzdHIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBVbmhhc2hpZnkgSFRNTCBibG9ja3MgKi9cbiAgZW5kID0gZ3JhZnNPdXQubGVuZ3RoO1xuICBmb3IgKGkgPSAwOyBpIDwgZW5kOyBpKyspIHtcbiAgICB2YXIgYmxvY2tUZXh0ID0gJycsXG4gICAgICAgIGdyYWZzT3V0SXQgPSBncmFmc091dFtpXSxcbiAgICAgICAgY29kZUZsYWcgPSBmYWxzZTtcbiAgICAvLyBpZiB0aGlzIGlzIGEgbWFya2VyIGZvciBhbiBodG1sIGJsb2NrLi4uXG4gICAgLy8gdXNlIFJlZ0V4cC50ZXN0IGluc3RlYWQgb2Ygc3RyaW5nLnNlYXJjaCBiZWNhdXNlIG9mIFFNTCBidWdcbiAgICB3aGlsZSAoL8KoKEt8RykoXFxkKylcXDEvLnRlc3QoZ3JhZnNPdXRJdCkpIHtcbiAgICAgIHZhciBkZWxpbSA9IFJlZ0V4cC4kMSxcbiAgICAgICAgICBudW0gICA9IFJlZ0V4cC4kMjtcblxuICAgICAgaWYgKGRlbGltID09PSAnSycpIHtcbiAgICAgICAgYmxvY2tUZXh0ID0gZ2xvYmFscy5nSHRtbEJsb2Nrc1tudW1dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gd2UgbmVlZCB0byBjaGVjayBpZiBnaEJsb2NrIGlzIGEgZmFsc2UgcG9zaXRpdmVcbiAgICAgICAgaWYgKGNvZGVGbGFnKSB7XG4gICAgICAgICAgLy8gdXNlIGVuY29kZWQgdmVyc2lvbiBvZiBhbGwgdGV4dFxuICAgICAgICAgIGJsb2NrVGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQ29kZScpKGdsb2JhbHMuZ2hDb2RlQmxvY2tzW251bV0udGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYmxvY2tUZXh0ID0gZ2xvYmFscy5naENvZGVCbG9ja3NbbnVtXS5jb2RlYmxvY2s7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJsb2NrVGV4dCA9IGJsb2NrVGV4dC5yZXBsYWNlKC9cXCQvZywgJyQkJCQnKTsgLy8gRXNjYXBlIGFueSBkb2xsYXIgc2lnbnNcblxuICAgICAgZ3JhZnNPdXRJdCA9IGdyYWZzT3V0SXQucmVwbGFjZSgvKFxcblxcbik/wqgoS3xHKVxcZCtcXDIoXFxuXFxuKT8vLCBibG9ja1RleHQpO1xuICAgICAgLy8gQ2hlY2sgaWYgZ3JhZnNPdXRJdCBpcyBhIHByZS0+Y29kZVxuICAgICAgaWYgKC9ePHByZVxcYltePl0qPlxccyo8Y29kZVxcYltePl0qPi8udGVzdChncmFmc091dEl0KSkge1xuICAgICAgICBjb2RlRmxhZyA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIGdyYWZzT3V0W2ldID0gZ3JhZnNPdXRJdDtcbiAgfVxuICB0ZXh0ID0gZ3JhZnNPdXQuam9pbignXFxuJyk7XG4gIC8vIFN0cmlwIGxlYWRpbmcgYW5kIHRyYWlsaW5nIGxpbmVzOlxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eXFxuKy9nLCAnJyk7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcbiskL2csICcnKTtcbiAgcmV0dXJuIGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgncGFyYWdyYXBocy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xufSk7XG5cclxuLyoqXG4gKiBSdW4gZXh0ZW5zaW9uXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcigncnVuRXh0ZW5zaW9uJywgZnVuY3Rpb24gKGV4dCwgdGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKGV4dC5maWx0ZXIpIHtcbiAgICB0ZXh0ID0gZXh0LmZpbHRlcih0ZXh0LCBnbG9iYWxzLmNvbnZlcnRlciwgb3B0aW9ucyk7XG5cbiAgfSBlbHNlIGlmIChleHQucmVnZXgpIHtcbiAgICAvLyBUT0RPIHJlbW92ZSB0aGlzIHdoZW4gb2xkIGV4dGVuc2lvbiBsb2FkaW5nIG1lY2hhbmlzbSBpcyBkZXByZWNhdGVkXG4gICAgdmFyIHJlID0gZXh0LnJlZ2V4O1xuICAgIGlmICghKHJlIGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgcmUgPSBuZXcgUmVnRXhwKHJlLCAnZycpO1xuICAgIH1cbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHJlLCBleHQucmVwbGFjZSk7XG4gIH1cblxuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbi8qKlxuICogVGhlc2UgYXJlIGFsbCB0aGUgdHJhbnNmb3JtYXRpb25zIHRoYXQgb2NjdXIgKndpdGhpbiogYmxvY2stbGV2ZWxcbiAqIHRhZ3MgbGlrZSBwYXJhZ3JhcGhzLCBoZWFkZXJzLCBhbmQgbGlzdCBpdGVtcy5cbiAqL1xuc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc3BhbkdhbXV0LmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdjb2RlU3BhbnMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignZXNjYXBlU3BlY2lhbENoYXJzV2l0aGluVGFnQXR0cmlidXRlcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVCYWNrc2xhc2hFc2NhcGVzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gUHJvY2VzcyBhbmNob3IgYW5kIGltYWdlIHRhZ3MuIEltYWdlcyBtdXN0IGNvbWUgZmlyc3QsXG4gIC8vIGJlY2F1c2UgIVtmb29dW2ZdIGxvb2tzIGxpa2UgYW4gYW5jaG9yLlxuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdpbWFnZXMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignYW5jaG9ycycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIE1ha2UgbGlua3Mgb3V0IG9mIHRoaW5ncyBsaWtlIGA8aHR0cDovL2V4YW1wbGUuY29tLz5gXG4gIC8vIE11c3QgY29tZSBhZnRlciBhbmNob3JzLCBiZWNhdXNlIHlvdSBjYW4gdXNlIDwgYW5kID5cbiAgLy8gZGVsaW1pdGVycyBpbiBpbmxpbmUgbGlua3MgbGlrZSBbdGhpc10oPHVybD4pLlxuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdhdXRvTGlua3MnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignc2ltcGxpZmllZEF1dG9MaW5rcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbW9qaScpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmRlcmxpbmUnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignaXRhbGljc0FuZEJvbGQnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgdGV4dCA9IHNob3dkb3duLnN1YlBhcnNlcignc3RyaWtldGhyb3VnaCcpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbGxpcHNpcycpKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIC8vIHdlIG5lZWQgdG8gaGFzaCBIVE1MIHRhZ3MgaW5zaWRlIHNwYW5zXG4gIHRleHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ2hhc2hIVE1MU3BhbnMnKSh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBub3cgd2UgZW5jb2RlIGFtcHMgYW5kIGFuZ2xlc1xuICB0ZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdlbmNvZGVBbXBzQW5kQW5nbGVzJykodGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG5cbiAgLy8gRG8gaGFyZCBicmVha3NcbiAgaWYgKG9wdGlvbnMuc2ltcGxlTGluZUJyZWFrcykge1xuICAgIC8vIEdGTSBzdHlsZSBoYXJkIGJyZWFrc1xuICAgIC8vIG9ubHkgYWRkIGxpbmUgYnJlYWtzIGlmIHRoZSB0ZXh0IGRvZXMgbm90IGNvbnRhaW4gYSBibG9jayAoc3BlY2lhbCBjYXNlIGZvciBsaXN0cylcbiAgICBpZiAoIS9cXG5cXG7CqEsvLnRlc3QodGV4dCkpIHtcbiAgICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcbisvZywgJzxiciAvPlxcbicpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBWYW5pbGxhIGhhcmQgYnJlYWtzXG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvICArXFxuL2csICc8YnIgLz5cXG4nKTtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3NwYW5HYW11dC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICByZXR1cm4gdGV4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignc3RyaWtldGhyb3VnaCcsIGZ1bmN0aW9uICh0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBmdW5jdGlvbiBwYXJzZUluc2lkZSAodHh0KSB7XG4gICAgaWYgKG9wdGlvbnMuc2ltcGxpZmllZEF1dG9MaW5rKSB7XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ3NpbXBsaWZpZWRBdXRvTGlua3MnKSh0eHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICAgIH1cbiAgICByZXR1cm4gJzxkZWw+JyArIHR4dCArICc8L2RlbD4nO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMuc3RyaWtldGhyb3VnaCkge1xuICAgIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3N0cmlrZXRocm91Z2guYmVmb3JlJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvKD86fil7Mn0oW1xcc1xcU10rPykoPzp+KXsyfS9nLCBmdW5jdGlvbiAod20sIHR4dCkgeyByZXR1cm4gcGFyc2VJbnNpZGUodHh0KTsgfSk7XG4gICAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgnc3RyaWtldGhyb3VnaC5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuICB9XG5cbiAgcmV0dXJuIHRleHQ7XG59KTtcblxyXG4vKipcbiAqIFN0cmlwcyBsaW5rIGRlZmluaXRpb25zIGZyb20gdGV4dCwgc3RvcmVzIHRoZSBVUkxzIGFuZCB0aXRsZXMgaW5cbiAqIGhhc2ggcmVmZXJlbmNlcy5cbiAqIExpbmsgZGVmcyBhcmUgaW4gdGhlIGZvcm06IF5baWRdOiB1cmwgXCJvcHRpb25hbCB0aXRsZVwiXG4gKi9cbnNob3dkb3duLnN1YlBhcnNlcignc3RyaXBMaW5rRGVmaW5pdGlvbnMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHJlZ2V4ICAgICAgID0gL14gezAsM31cXFsoLispXTpbIFxcdF0qXFxuP1sgXFx0XSo8PyhbXj5cXHNdKyk+Pyg/OiA9KFsqXFxkXStbQS1aYS16JV17MCw0fSl4KFsqXFxkXStbQS1aYS16JV17MCw0fSkpP1sgXFx0XSpcXG4/WyBcXHRdKig/OihcXG4qKVtcInwnKF0oLis/KVtcInwnKV1bIFxcdF0qKT8oPzpcXG4rfCg/PcKoMCkpL2dtLFxuICAgICAgYmFzZTY0UmVnZXggPSAvXiB7MCwzfVxcWyguKyldOlsgXFx0XSpcXG4/WyBcXHRdKjw/KGRhdGE6Lis/XFwvLis/O2Jhc2U2NCxbQS1aYS16MC05Ky89XFxuXSs/KT4/KD86ID0oWypcXGRdK1tBLVphLXolXXswLDR9KXgoWypcXGRdK1tBLVphLXolXXswLDR9KSk/WyBcXHRdKlxcbj9bIFxcdF0qKD86KFxcbiopW1wifCcoXSguKz8pW1wifCcpXVsgXFx0XSopPyg/OlxcblxcbnwoPz3CqDApfCg/PVxcblxcWykpL2dtO1xuXG4gIC8vIGF0dGFja2xhYjogc2VudGluZWwgd29ya2Fyb3VuZHMgZm9yIGxhY2sgb2YgXFxBIGFuZCBcXFosIHNhZmFyaVxca2h0bWwgYnVnXG4gIHRleHQgKz0gJ8KoMCc7XG5cbiAgdmFyIHJlcGxhY2VGdW5jID0gZnVuY3Rpb24gKHdob2xlTWF0Y2gsIGxpbmtJZCwgdXJsLCB3aWR0aCwgaGVpZ2h0LCBibGFua0xpbmVzLCB0aXRsZSkge1xuICAgIGxpbmtJZCA9IGxpbmtJZC50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICh1cmwubWF0Y2goL15kYXRhOi4rP1xcLy4rPztiYXNlNjQsLykpIHtcbiAgICAgIC8vIHJlbW92ZSBuZXdsaW5lc1xuICAgICAgZ2xvYmFscy5nVXJsc1tsaW5rSWRdID0gdXJsLnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGdsb2JhbHMuZ1VybHNbbGlua0lkXSA9IHNob3dkb3duLnN1YlBhcnNlcignZW5jb2RlQW1wc0FuZEFuZ2xlcycpKHVybCwgb3B0aW9ucywgZ2xvYmFscyk7ICAvLyBMaW5rIElEcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZVxuICAgIH1cblxuICAgIGlmIChibGFua0xpbmVzKSB7XG4gICAgICAvLyBPb3BzLCBmb3VuZCBibGFuayBsaW5lcywgc28gaXQncyBub3QgYSB0aXRsZS5cbiAgICAgIC8vIFB1dCBiYWNrIHRoZSBwYXJlbnRoZXRpY2FsIHN0YXRlbWVudCB3ZSBzdG9sZS5cbiAgICAgIHJldHVybiBibGFua0xpbmVzICsgdGl0bGU7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRpdGxlKSB7XG4gICAgICAgIGdsb2JhbHMuZ1RpdGxlc1tsaW5rSWRdID0gdGl0bGUucmVwbGFjZSgvXCJ8Jy9nLCAnJnF1b3Q7Jyk7XG4gICAgICB9XG4gICAgICBpZiAob3B0aW9ucy5wYXJzZUltZ0RpbWVuc2lvbnMgJiYgd2lkdGggJiYgaGVpZ2h0KSB7XG4gICAgICAgIGdsb2JhbHMuZ0RpbWVuc2lvbnNbbGlua0lkXSA9IHtcbiAgICAgICAgICB3aWR0aDogIHdpZHRoLFxuICAgICAgICAgIGhlaWdodDogaGVpZ2h0XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENvbXBsZXRlbHkgcmVtb3ZlIHRoZSBkZWZpbml0aW9uIGZyb20gdGhlIHRleHRcbiAgICByZXR1cm4gJyc7XG4gIH07XG5cbiAgLy8gZmlyc3Qgd2UgdHJ5IHRvIGZpbmQgYmFzZTY0IGxpbmsgcmVmZXJlbmNlc1xuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKGJhc2U2NFJlZ2V4LCByZXBsYWNlRnVuYyk7XG5cbiAgdGV4dCA9IHRleHQucmVwbGFjZShyZWdleCwgcmVwbGFjZUZ1bmMpO1xuXG4gIC8vIGF0dGFja2xhYjogc3RyaXAgc2VudGluZWxcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvwqgwLywgJycpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCd0YWJsZXMnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFvcHRpb25zLnRhYmxlcykge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgdmFyIHRhYmxlUmd4ICAgICAgID0gL14gezAsM31cXHw/LitcXHwuK1xcbiB7MCwzfVxcfD9bIFxcdF0qOj9bIFxcdF0qKD86Wy09XSl7Mix9WyBcXHRdKjo/WyBcXHRdKlxcfFsgXFx0XSo6P1sgXFx0XSooPzpbLT1dKXsyLH1bXFxzXFxTXSs/KD86XFxuXFxufMKoMCkvZ20sXG4gICAgLy9zaW5nZUNvbFRibFJneCA9IC9eIHswLDN9XFx8LitcXHxcXG4gezAsM31cXHxbIFxcdF0qOj9bIFxcdF0qKD86Wy09XSl7Mix9WyBcXHRdKjo/WyBcXHRdKlxcfFsgXFx0XSpcXG4oPzogezAsM31cXHwuK1xcfFxcbikrKD86XFxuXFxufMKoMCkvZ207XG4gICAgICBzaW5nZUNvbFRibFJneCA9IC9eIHswLDN9XFx8LitcXHxbIFxcdF0qXFxuIHswLDN9XFx8WyBcXHRdKjo/WyBcXHRdKig/OlstPV0pezIsfVsgXFx0XSo6P1sgXFx0XSpcXHxbIFxcdF0qXFxuKCB7MCwzfVxcfC4rXFx8WyBcXHRdKlxcbikqKD86XFxufMKoMCkvZ207XG5cbiAgZnVuY3Rpb24gcGFyc2VTdHlsZXMgKHNMaW5lKSB7XG4gICAgaWYgKC9eOlsgXFx0XSotLSokLy50ZXN0KHNMaW5lKSkge1xuICAgICAgcmV0dXJuICcgc3R5bGU9XCJ0ZXh0LWFsaWduOmxlZnQ7XCInO1xuICAgIH0gZWxzZSBpZiAoL14tLSpbIFxcdF0qOlsgXFx0XSokLy50ZXN0KHNMaW5lKSkge1xuICAgICAgcmV0dXJuICcgc3R5bGU9XCJ0ZXh0LWFsaWduOnJpZ2h0O1wiJztcbiAgICB9IGVsc2UgaWYgKC9eOlsgXFx0XSotLSpbIFxcdF0qOiQvLnRlc3Qoc0xpbmUpKSB7XG4gICAgICByZXR1cm4gJyBzdHlsZT1cInRleHQtYWxpZ246Y2VudGVyO1wiJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlSGVhZGVycyAoaGVhZGVyLCBzdHlsZSkge1xuICAgIHZhciBpZCA9ICcnO1xuICAgIGhlYWRlciA9IGhlYWRlci50cmltKCk7XG4gICAgLy8gc3VwcG9ydCBib3RoIHRhYmxlc0hlYWRlcklkIGFuZCB0YWJsZUhlYWRlcklkIGR1ZSB0byBlcnJvciBpbiBkb2N1bWVudGF0aW9uIHNvIHdlIGRvbid0IGJyZWFrIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG4gICAgaWYgKG9wdGlvbnMudGFibGVzSGVhZGVySWQgfHwgb3B0aW9ucy50YWJsZUhlYWRlcklkKSB7XG4gICAgICBpZCA9ICcgaWQ9XCInICsgaGVhZGVyLnJlcGxhY2UoLyAvZywgJ18nKS50b0xvd2VyQ2FzZSgpICsgJ1wiJztcbiAgICB9XG4gICAgaGVhZGVyID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShoZWFkZXIsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gICAgcmV0dXJuICc8dGgnICsgaWQgKyBzdHlsZSArICc+JyArIGhlYWRlciArICc8L3RoPlxcbic7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUNlbGxzIChjZWxsLCBzdHlsZSkge1xuICAgIHZhciBzdWJUZXh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdzcGFuR2FtdXQnKShjZWxsLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICByZXR1cm4gJzx0ZCcgKyBzdHlsZSArICc+JyArIHN1YlRleHQgKyAnPC90ZD5cXG4nO1xuICB9XG5cbiAgZnVuY3Rpb24gYnVpbGRUYWJsZSAoaGVhZGVycywgY2VsbHMpIHtcbiAgICB2YXIgdGIgPSAnPHRhYmxlPlxcbjx0aGVhZD5cXG48dHI+XFxuJyxcbiAgICAgICAgdGJsTGduID0gaGVhZGVycy5sZW5ndGg7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRibExnbjsgKytpKSB7XG4gICAgICB0YiArPSBoZWFkZXJzW2ldO1xuICAgIH1cbiAgICB0YiArPSAnPC90cj5cXG48L3RoZWFkPlxcbjx0Ym9keT5cXG4nO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgICB0YiArPSAnPHRyPlxcbic7XG4gICAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgdGJsTGduOyArK2lpKSB7XG4gICAgICAgIHRiICs9IGNlbGxzW2ldW2lpXTtcbiAgICAgIH1cbiAgICAgIHRiICs9ICc8L3RyPlxcbic7XG4gICAgfVxuICAgIHRiICs9ICc8L3Rib2R5PlxcbjwvdGFibGU+XFxuJztcbiAgICByZXR1cm4gdGI7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZVRhYmxlIChyYXdUYWJsZSkge1xuICAgIHZhciBpLCB0YWJsZUxpbmVzID0gcmF3VGFibGUuc3BsaXQoJ1xcbicpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IHRhYmxlTGluZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIC8vIHN0cmlwIHdyb25nIGZpcnN0IGFuZCBsYXN0IGNvbHVtbiBpZiB3cmFwcGVkIHRhYmxlcyBhcmUgdXNlZFxuICAgICAgaWYgKC9eIHswLDN9XFx8Ly50ZXN0KHRhYmxlTGluZXNbaV0pKSB7XG4gICAgICAgIHRhYmxlTGluZXNbaV0gPSB0YWJsZUxpbmVzW2ldLnJlcGxhY2UoL14gezAsM31cXHwvLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoL1xcfFsgXFx0XSokLy50ZXN0KHRhYmxlTGluZXNbaV0pKSB7XG4gICAgICAgIHRhYmxlTGluZXNbaV0gPSB0YWJsZUxpbmVzW2ldLnJlcGxhY2UoL1xcfFsgXFx0XSokLywgJycpO1xuICAgICAgfVxuICAgICAgLy8gcGFyc2UgY29kZSBzcGFucyBmaXJzdCwgYnV0IHdlIG9ubHkgc3VwcG9ydCBvbmUgbGluZSBjb2RlIHNwYW5zXG4gICAgICB0YWJsZUxpbmVzW2ldID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdjb2RlU3BhbnMnKSh0YWJsZUxpbmVzW2ldLCBvcHRpb25zLCBnbG9iYWxzKTtcbiAgICB9XG5cbiAgICB2YXIgcmF3SGVhZGVycyA9IHRhYmxlTGluZXNbMF0uc3BsaXQoJ3wnKS5tYXAoZnVuY3Rpb24gKHMpIHsgcmV0dXJuIHMudHJpbSgpO30pLFxuICAgICAgICByYXdTdHlsZXMgPSB0YWJsZUxpbmVzWzFdLnNwbGl0KCd8JykubWFwKGZ1bmN0aW9uIChzKSB7IHJldHVybiBzLnRyaW0oKTt9KSxcbiAgICAgICAgcmF3Q2VsbHMgPSBbXSxcbiAgICAgICAgaGVhZGVycyA9IFtdLFxuICAgICAgICBzdHlsZXMgPSBbXSxcbiAgICAgICAgY2VsbHMgPSBbXTtcblxuICAgIHRhYmxlTGluZXMuc2hpZnQoKTtcbiAgICB0YWJsZUxpbmVzLnNoaWZ0KCk7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgdGFibGVMaW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKHRhYmxlTGluZXNbaV0udHJpbSgpID09PSAnJykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHJhd0NlbGxzLnB1c2goXG4gICAgICAgIHRhYmxlTGluZXNbaV1cbiAgICAgICAgICAuc3BsaXQoJ3wnKVxuICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgIHJldHVybiBzLnRyaW0oKTtcbiAgICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAocmF3SGVhZGVycy5sZW5ndGggPCByYXdTdHlsZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gcmF3VGFibGU7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMDsgaSA8IHJhd1N0eWxlcy5sZW5ndGg7ICsraSkge1xuICAgICAgc3R5bGVzLnB1c2gocGFyc2VTdHlsZXMocmF3U3R5bGVzW2ldKSk7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMDsgaSA8IHJhd0hlYWRlcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmIChzaG93ZG93bi5oZWxwZXIuaXNVbmRlZmluZWQoc3R5bGVzW2ldKSkge1xuICAgICAgICBzdHlsZXNbaV0gPSAnJztcbiAgICAgIH1cbiAgICAgIGhlYWRlcnMucHVzaChwYXJzZUhlYWRlcnMocmF3SGVhZGVyc1tpXSwgc3R5bGVzW2ldKSk7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMDsgaSA8IHJhd0NlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgcm93ID0gW107XG4gICAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgaGVhZGVycy5sZW5ndGg7ICsraWkpIHtcbiAgICAgICAgaWYgKHNob3dkb3duLmhlbHBlci5pc1VuZGVmaW5lZChyYXdDZWxsc1tpXVtpaV0pKSB7XG5cbiAgICAgICAgfVxuICAgICAgICByb3cucHVzaChwYXJzZUNlbGxzKHJhd0NlbGxzW2ldW2lpXSwgc3R5bGVzW2lpXSkpO1xuICAgICAgfVxuICAgICAgY2VsbHMucHVzaChyb3cpO1xuICAgIH1cblxuICAgIHJldHVybiBidWlsZFRhYmxlKGhlYWRlcnMsIGNlbGxzKTtcbiAgfVxuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3RhYmxlcy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICAvLyBmaW5kIGVzY2FwZWQgcGlwZSBjaGFyYWN0ZXJzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcXFwoXFx8KS9nLCBzaG93ZG93bi5oZWxwZXIuZXNjYXBlQ2hhcmFjdGVyc0NhbGxiYWNrKTtcblxuICAvLyBwYXJzZSBtdWx0aSBjb2x1bW4gdGFibGVzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UodGFibGVSZ3gsIHBhcnNlVGFibGUpO1xuXG4gIC8vIHBhcnNlIG9uZSBjb2x1bW4gdGFibGVzXG4gIHRleHQgPSB0ZXh0LnJlcGxhY2Uoc2luZ2VDb2xUYmxSZ3gsIHBhcnNlVGFibGUpO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3RhYmxlcy5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCd1bmRlcmxpbmUnLCBmdW5jdGlvbiAodGV4dCwgb3B0aW9ucywgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKCFvcHRpb25zLnVuZGVybGluZSkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgdGV4dCA9IGdsb2JhbHMuY29udmVydGVyLl9kaXNwYXRjaCgndW5kZXJsaW5lLmJlZm9yZScsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIGlmIChvcHRpb25zLmxpdGVyYWxNaWRXb3JkVW5kZXJzY29yZXMpIHtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXGJfX18oXFxTW1xcc1xcU10qPylfX19cXGIvZywgZnVuY3Rpb24gKHdtLCB0eHQpIHtcbiAgICAgIHJldHVybiAnPHU+JyArIHR4dCArICc8L3U+JztcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXGJfXyhcXFNbXFxzXFxTXSo/KV9fXFxiL2csIGZ1bmN0aW9uICh3bSwgdHh0KSB7XG4gICAgICByZXR1cm4gJzx1PicgKyB0eHQgKyAnPC91Pic7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvX19fKFxcU1tcXHNcXFNdKj8pX19fL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyAnPHU+JyArIG0gKyAnPC91PicgOiB3bTtcbiAgICB9KTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9fXyhcXFNbXFxzXFxTXSo/KV9fL2csIGZ1bmN0aW9uICh3bSwgbSkge1xuICAgICAgcmV0dXJuICgvXFxTJC8udGVzdChtKSkgPyAnPHU+JyArIG0gKyAnPC91PicgOiB3bTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGVzY2FwZSByZW1haW5pbmcgdW5kZXJzY29yZXMgdG8gcHJldmVudCB0aGVtIGJlaW5nIHBhcnNlZCBieSBpdGFsaWMgYW5kIGJvbGRcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvKF8pL2csIHNob3dkb3duLmhlbHBlci5lc2NhcGVDaGFyYWN0ZXJzQ2FsbGJhY2spO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3VuZGVybGluZS5hZnRlcicsIHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpO1xuXG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuLyoqXG4gKiBTd2FwIGJhY2sgaW4gYWxsIHRoZSBzcGVjaWFsIGNoYXJhY3RlcnMgd2UndmUgaGlkZGVuLlxuICovXG5zaG93ZG93bi5zdWJQYXJzZXIoJ3VuZXNjYXBlU3BlY2lhbENoYXJzJywgZnVuY3Rpb24gKHRleHQsIG9wdGlvbnMsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICB0ZXh0ID0gZ2xvYmFscy5jb252ZXJ0ZXIuX2Rpc3BhdGNoKCd1bmVzY2FwZVNwZWNpYWxDaGFycy5iZWZvcmUnLCB0ZXh0LCBvcHRpb25zLCBnbG9iYWxzKTtcblxuICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC/CqEUoXFxkKylFL2csIGZ1bmN0aW9uICh3aG9sZU1hdGNoLCBtMSkge1xuICAgIHZhciBjaGFyQ29kZVRvUmVwbGFjZSA9IHBhcnNlSW50KG0xKTtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZVRvUmVwbGFjZSk7XG4gIH0pO1xuXG4gIHRleHQgPSBnbG9iYWxzLmNvbnZlcnRlci5fZGlzcGF0Y2goJ3VuZXNjYXBlU3BlY2lhbENoYXJzLmFmdGVyJywgdGV4dCwgb3B0aW9ucywgZ2xvYmFscyk7XG4gIHJldHVybiB0ZXh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uYmxvY2txdW90ZScsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBpbm5lclR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG5cbiAgICAgIGlmIChpbm5lclR4dCA9PT0gJycpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICB0eHQgKz0gaW5uZXJUeHQ7XG4gICAgfVxuICB9XG4gIC8vIGNsZWFudXBcbiAgdHh0ID0gdHh0LnRyaW0oKTtcbiAgdHh0ID0gJz4gJyArIHR4dC5zcGxpdCgnXFxuJykuam9pbignXFxuPiAnKTtcbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmNvZGVCbG9jaycsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgbGFuZyA9IG5vZGUuZ2V0QXR0cmlidXRlKCdsYW5ndWFnZScpLFxuICAgICAgbnVtICA9IG5vZGUuZ2V0QXR0cmlidXRlKCdwcmVjb2RlbnVtJyk7XG4gIHJldHVybiAnYGBgJyArIGxhbmcgKyAnXFxuJyArIGdsb2JhbHMucHJlTGlzdFtudW1dICsgJ1xcbmBgYCc7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5jb2RlU3BhbicsIGZ1bmN0aW9uIChub2RlKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICByZXR1cm4gJ2AnICsgbm9kZS5pbm5lckhUTUwgKyAnYCc7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5lbXBoYXNpcycsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHR4dCArPSAnKic7XG4gICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZE5vZGVzLFxuICAgICAgICBjaGlsZHJlbkxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ3RoOyArK2kpIHtcbiAgICAgIHR4dCArPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMpO1xuICAgIH1cbiAgICB0eHQgKz0gJyonO1xuICB9XG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5oZWFkZXInLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscywgaGVhZGVyTGV2ZWwpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciBoZWFkZXJNYXJrID0gbmV3IEFycmF5KGhlYWRlckxldmVsICsgMSkuam9pbignIycpLFxuICAgICAgdHh0ID0gJyc7XG5cbiAgaWYgKG5vZGUuaGFzQ2hpbGROb2RlcygpKSB7XG4gICAgdHh0ID0gaGVhZGVyTWFyayArICcgJztcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICAgIGNoaWxkcmVuTGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmhyJywgZnVuY3Rpb24gKCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgcmV0dXJuICctLS0nO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaW1hZ2UnLCBmdW5jdGlvbiAobm9kZSkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAobm9kZS5oYXNBdHRyaWJ1dGUoJ3NyYycpKSB7XG4gICAgdHh0ICs9ICchWycgKyBub2RlLmdldEF0dHJpYnV0ZSgnYWx0JykgKyAnXSgnO1xuICAgIHR4dCArPSAnPCcgKyBub2RlLmdldEF0dHJpYnV0ZSgnc3JjJykgKyAnPic7XG4gICAgaWYgKG5vZGUuaGFzQXR0cmlidXRlKCd3aWR0aCcpICYmIG5vZGUuaGFzQXR0cmlidXRlKCdoZWlnaHQnKSkge1xuICAgICAgdHh0ICs9ICcgPScgKyBub2RlLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSArICd4JyArIG5vZGUuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKTtcbiAgICB9XG5cbiAgICBpZiAobm9kZS5oYXNBdHRyaWJ1dGUoJ3RpdGxlJykpIHtcbiAgICAgIHR4dCArPSAnIFwiJyArIG5vZGUuZ2V0QXR0cmlidXRlKCd0aXRsZScpICsgJ1wiJztcbiAgICB9XG4gICAgdHh0ICs9ICcpJztcbiAgfVxuICByZXR1cm4gdHh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlua3MnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAobm9kZS5oYXNDaGlsZE5vZGVzKCkgJiYgbm9kZS5oYXNBdHRyaWJ1dGUoJ2hyZWYnKSkge1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgdHh0ID0gJ1snO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5ndGg7ICsraSkge1xuICAgICAgdHh0ICs9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG4gICAgfVxuICAgIHR4dCArPSAnXSgnO1xuICAgIHR4dCArPSAnPCcgKyBub2RlLmdldEF0dHJpYnV0ZSgnaHJlZicpICsgJz4nO1xuICAgIGlmIChub2RlLmhhc0F0dHJpYnV0ZSgndGl0bGUnKSkge1xuICAgICAgdHh0ICs9ICcgXCInICsgbm9kZS5nZXRBdHRyaWJ1dGUoJ3RpdGxlJykgKyAnXCInO1xuICAgIH1cbiAgICB0eHQgKz0gJyknO1xuICB9XG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5saXN0JywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMsIHR5cGUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJztcbiAgaWYgKCFub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuICB2YXIgbGlzdEl0ZW1zICAgICAgID0gbm9kZS5jaGlsZE5vZGVzLFxuICAgICAgbGlzdEl0ZW1zTGVuZ2h0ID0gbGlzdEl0ZW1zLmxlbmd0aCxcbiAgICAgIGxpc3ROdW0gPSBub2RlLmdldEF0dHJpYnV0ZSgnc3RhcnQnKSB8fCAxO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGlzdEl0ZW1zTGVuZ2h0OyArK2kpIHtcbiAgICBpZiAodHlwZW9mIGxpc3RJdGVtc1tpXS50YWdOYW1lID09PSAndW5kZWZpbmVkJyB8fCBsaXN0SXRlbXNbaV0udGFnTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnbGknKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBkZWZpbmUgdGhlIGJ1bGxldCB0byB1c2UgaW4gbGlzdFxuICAgIHZhciBidWxsZXQgPSAnJztcbiAgICBpZiAodHlwZSA9PT0gJ29sJykge1xuICAgICAgYnVsbGV0ID0gbGlzdE51bS50b1N0cmluZygpICsgJy4gJztcbiAgICB9IGVsc2Uge1xuICAgICAgYnVsbGV0ID0gJy0gJztcbiAgICB9XG5cbiAgICAvLyBwYXJzZSBsaXN0IGl0ZW1cbiAgICB0eHQgKz0gYnVsbGV0ICsgc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlzdEl0ZW0nKShsaXN0SXRlbXNbaV0sIGdsb2JhbHMpO1xuICAgICsrbGlzdE51bTtcbiAgfVxuXG4gIC8vIGFkZCBjb21tZW50IGF0IHRoZSBlbmQgdG8gcHJldmVudCBjb25zZWN1dGl2ZSBsaXN0cyB0byBiZSBwYXJzZWQgYXMgb25lXG4gIHR4dCArPSAnXFxuPCEtLSAtLT5cXG4nO1xuICByZXR1cm4gdHh0LnRyaW0oKTtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmxpc3RJdGVtJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciBsaXN0SXRlbVR4dCA9ICcnO1xuXG4gIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgIGNoaWxkcmVuTGVuZ2h0ID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5naHQ7ICsraSkge1xuICAgIGxpc3RJdGVtVHh0ICs9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnKShjaGlsZHJlbltpXSwgZ2xvYmFscyk7XG4gIH1cbiAgLy8gaWYgaXQncyBvbmx5IG9uZSBsaW5lciwgd2UgbmVlZCB0byBhZGQgYSBuZXdsaW5lIGF0IHRoZSBlbmRcbiAgaWYgKCEvXFxuJC8udGVzdChsaXN0SXRlbVR4dCkpIHtcbiAgICBsaXN0SXRlbVR4dCArPSAnXFxuJztcbiAgfSBlbHNlIHtcbiAgICAvLyBpdCdzIG11bHRpcGFyYWdyYXBoLCBzbyB3ZSBuZWVkIHRvIGluZGVudFxuICAgIGxpc3RJdGVtVHh0ID0gbGlzdEl0ZW1UeHRcbiAgICAgIC5zcGxpdCgnXFxuJylcbiAgICAgIC5qb2luKCdcXG4gICAgJylcbiAgICAgIC5yZXBsYWNlKC9eIHs0fSQvZ20sICcnKVxuICAgICAgLnJlcGxhY2UoL1xcblxcbisvZywgJ1xcblxcbicpO1xuICB9XG5cbiAgcmV0dXJuIGxpc3RJdGVtVHh0O1xufSk7XG5cclxuXG5cbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLm5vZGUnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscywgc3BhbnNPbmx5KSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICBzcGFuc09ubHkgPSBzcGFuc09ubHkgfHwgZmFsc2U7XG5cbiAgdmFyIHR4dCA9ICcnO1xuXG4gIC8vIGVkZ2UgY2FzZSBvZiB0ZXh0IHdpdGhvdXQgd3JhcHBlciBwYXJhZ3JhcGhcbiAgaWYgKG5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICByZXR1cm4gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24udHh0Jykobm9kZSwgZ2xvYmFscyk7XG4gIH1cblxuICAvLyBIVE1MIGNvbW1lbnRcbiAgaWYgKG5vZGUubm9kZVR5cGUgPT09IDgpIHtcbiAgICByZXR1cm4gJzwhLS0nICsgbm9kZS5kYXRhICsgJy0tPlxcblxcbic7XG4gIH1cblxuICAvLyBwcm9jZXNzIG9ubHkgbm9kZSBlbGVtZW50c1xuICBpZiAobm9kZS5ub2RlVHlwZSAhPT0gMSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIHZhciB0YWdOYW1lID0gbm9kZS50YWdOYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgc3dpdGNoICh0YWdOYW1lKSB7XG5cbiAgICAvL1xuICAgIC8vIEJMT0NLU1xuICAgIC8vXG4gICAgY2FzZSAnaDEnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgMSkgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDInOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgMikgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDMnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgMykgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDQnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgNCkgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDUnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgNSkgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaDYnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaGVhZGVyJykobm9kZSwgZ2xvYmFscywgNikgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdwJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnBhcmFncmFwaCcpKG5vZGUsIGdsb2JhbHMpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnYmxvY2txdW90ZSc6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ibG9ja3F1b3RlJykobm9kZSwgZ2xvYmFscykgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdocic6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ocicpKG5vZGUsIGdsb2JhbHMpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnb2wnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlzdCcpKG5vZGUsIGdsb2JhbHMsICdvbCcpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAndWwnOlxuICAgICAgaWYgKCFzcGFuc09ubHkpIHsgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubGlzdCcpKG5vZGUsIGdsb2JhbHMsICd1bCcpICsgJ1xcblxcbic7IH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAncHJlY29kZSc6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5jb2RlQmxvY2snKShub2RlLCBnbG9iYWxzKSArICdcXG5cXG4nOyB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3ByZSc6XG4gICAgICBpZiAoIXNwYW5zT25seSkgeyB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5wcmUnKShub2RlLCBnbG9iYWxzKSArICdcXG5cXG4nOyB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3RhYmxlJzpcbiAgICAgIGlmICghc3BhbnNPbmx5KSB7IHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnRhYmxlJykobm9kZSwgZ2xvYmFscykgKyAnXFxuXFxuJzsgfVxuICAgICAgYnJlYWs7XG5cbiAgICAvL1xuICAgIC8vIFNQQU5TXG4gICAgLy9cbiAgICBjYXNlICdjb2RlJzpcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmNvZGVTcGFuJykobm9kZSwgZ2xvYmFscyk7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2VtJzpcbiAgICBjYXNlICdpJzpcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLmVtcGhhc2lzJykobm9kZSwgZ2xvYmFscyk7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ3N0cm9uZyc6XG4gICAgY2FzZSAnYic6XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5zdHJvbmcnKShub2RlLCBnbG9iYWxzKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnZGVsJzpcbiAgICAgIHR4dCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnN0cmlrZXRocm91Z2gnKShub2RlLCBnbG9iYWxzKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnYSc6XG4gICAgICB0eHQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5saW5rcycpKG5vZGUsIGdsb2JhbHMpO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdpbWcnOlxuICAgICAgdHh0ID0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uaW1hZ2UnKShub2RlLCBnbG9iYWxzKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHR4dCA9IG5vZGUub3V0ZXJIVE1MICsgJ1xcblxcbic7XG4gIH1cblxuICAvLyBjb21tb24gbm9ybWFsaXphdGlvblxuICAvLyBUT0RPIGV2ZW50dWFsbHlcblxuICByZXR1cm4gdHh0O1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ucGFyYWdyYXBoJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJztcbiAgaWYgKG5vZGUuaGFzQ2hpbGROb2RlcygpKSB7XG4gICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZE5vZGVzLFxuICAgICAgICBjaGlsZHJlbkxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuTGVuZ3RoOyArK2kpIHtcbiAgICAgIHR4dCArPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHNvbWUgdGV4dCBub3JtYWxpemF0aW9uXG4gIHR4dCA9IHR4dC50cmltKCk7XG5cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnByZScsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgbnVtICA9IG5vZGUuZ2V0QXR0cmlidXRlKCdwcmVudW0nKTtcbiAgcmV0dXJuICc8cHJlPicgKyBnbG9iYWxzLnByZUxpc3RbbnVtXSArICc8L3ByZT4nO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24uc3RyaWtldGhyb3VnaCcsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHR4dCArPSAnfn4nO1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzKTtcbiAgICB9XG4gICAgdHh0ICs9ICd+fic7XG4gIH1cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnN0cm9uZycsIGZ1bmN0aW9uIChub2RlLCBnbG9iYWxzKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdHh0ID0gJyc7XG4gIGlmIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgIHR4dCArPSAnKionO1xuICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbkxlbmd0aDsgKytpKSB7XG4gICAgICB0eHQgKz0gc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24ubm9kZScpKGNoaWxkcmVuW2ldLCBnbG9iYWxzKTtcbiAgICB9XG4gICAgdHh0ICs9ICcqKic7XG4gIH1cbiAgcmV0dXJuIHR4dDtcbn0pO1xuXHJcbnNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnRhYmxlJywgZnVuY3Rpb24gKG5vZGUsIGdsb2JhbHMpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSAnJyxcbiAgICAgIHRhYmxlQXJyYXkgPSBbW10sIFtdXSxcbiAgICAgIGhlYWRpbmdzICAgPSBub2RlLnF1ZXJ5U2VsZWN0b3JBbGwoJ3RoZWFkPnRyPnRoJyksXG4gICAgICByb3dzICAgICAgID0gbm9kZS5xdWVyeVNlbGVjdG9yQWxsKCd0Ym9keT50cicpLFxuICAgICAgaSwgaWk7XG4gIGZvciAoaSA9IDA7IGkgPCBoZWFkaW5ncy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBoZWFkQ29udGVudCA9IHNob3dkb3duLnN1YlBhcnNlcignbWFrZU1hcmtkb3duLnRhYmxlQ2VsbCcpKGhlYWRpbmdzW2ldLCBnbG9iYWxzKSxcbiAgICAgICAgYWxsaWduID0gJy0tLSc7XG5cbiAgICBpZiAoaGVhZGluZ3NbaV0uaGFzQXR0cmlidXRlKCdzdHlsZScpKSB7XG4gICAgICB2YXIgc3R5bGUgPSBoZWFkaW5nc1tpXS5nZXRBdHRyaWJ1dGUoJ3N0eWxlJykudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgICAgc3dpdGNoIChzdHlsZSkge1xuICAgICAgICBjYXNlICd0ZXh0LWFsaWduOmxlZnQ7JzpcbiAgICAgICAgICBhbGxpZ24gPSAnOi0tLSc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3RleHQtYWxpZ246cmlnaHQ7JzpcbiAgICAgICAgICBhbGxpZ24gPSAnLS0tOic7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3RleHQtYWxpZ246Y2VudGVyOyc6XG4gICAgICAgICAgYWxsaWduID0gJzotLS06JztcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgdGFibGVBcnJheVswXVtpXSA9IGhlYWRDb250ZW50LnRyaW0oKTtcbiAgICB0YWJsZUFycmF5WzFdW2ldID0gYWxsaWduO1xuICB9XG5cbiAgZm9yIChpID0gMDsgaSA8IHJvd3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgciA9IHRhYmxlQXJyYXkucHVzaChbXSkgLSAxLFxuICAgICAgICBjb2xzID0gcm93c1tpXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgndGQnKTtcblxuICAgIGZvciAoaWkgPSAwOyBpaSA8IGhlYWRpbmdzLmxlbmd0aDsgKytpaSkge1xuICAgICAgdmFyIGNlbGxDb250ZW50ID0gJyAnO1xuICAgICAgaWYgKHR5cGVvZiBjb2xzW2lpXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY2VsbENvbnRlbnQgPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi50YWJsZUNlbGwnKShjb2xzW2lpXSwgZ2xvYmFscyk7XG4gICAgICB9XG4gICAgICB0YWJsZUFycmF5W3JdLnB1c2goY2VsbENvbnRlbnQpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBjZWxsU3BhY2VzQ291bnQgPSAzO1xuICBmb3IgKGkgPSAwOyBpIDwgdGFibGVBcnJheS5sZW5ndGg7ICsraSkge1xuICAgIGZvciAoaWkgPSAwOyBpaSA8IHRhYmxlQXJyYXlbaV0ubGVuZ3RoOyArK2lpKSB7XG4gICAgICB2YXIgc3RyTGVuID0gdGFibGVBcnJheVtpXVtpaV0ubGVuZ3RoO1xuICAgICAgaWYgKHN0ckxlbiA+IGNlbGxTcGFjZXNDb3VudCkge1xuICAgICAgICBjZWxsU3BhY2VzQ291bnQgPSBzdHJMZW47XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9yIChpID0gMDsgaSA8IHRhYmxlQXJyYXkubGVuZ3RoOyArK2kpIHtcbiAgICBmb3IgKGlpID0gMDsgaWkgPCB0YWJsZUFycmF5W2ldLmxlbmd0aDsgKytpaSkge1xuICAgICAgaWYgKGkgPT09IDEpIHtcbiAgICAgICAgaWYgKHRhYmxlQXJyYXlbaV1baWldLnNsaWNlKC0xKSA9PT0gJzonKSB7XG4gICAgICAgICAgdGFibGVBcnJheVtpXVtpaV0gPSBzaG93ZG93bi5oZWxwZXIucGFkRW5kKHRhYmxlQXJyYXlbaV1baWldLnNsaWNlKC0xKSwgY2VsbFNwYWNlc0NvdW50IC0gMSwgJy0nKSArICc6JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0YWJsZUFycmF5W2ldW2lpXSA9IHNob3dkb3duLmhlbHBlci5wYWRFbmQodGFibGVBcnJheVtpXVtpaV0sIGNlbGxTcGFjZXNDb3VudCwgJy0nKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGFibGVBcnJheVtpXVtpaV0gPSBzaG93ZG93bi5oZWxwZXIucGFkRW5kKHRhYmxlQXJyYXlbaV1baWldLCBjZWxsU3BhY2VzQ291bnQpO1xuICAgICAgfVxuICAgIH1cbiAgICB0eHQgKz0gJ3wgJyArIHRhYmxlQXJyYXlbaV0uam9pbignIHwgJykgKyAnIHxcXG4nO1xuICB9XG5cbiAgcmV0dXJuIHR4dC50cmltKCk7XG59KTtcblxyXG5zaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi50YWJsZUNlbGwnLCBmdW5jdGlvbiAobm9kZSwgZ2xvYmFscykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHR4dCA9ICcnO1xuICBpZiAoIW5vZGUuaGFzQ2hpbGROb2RlcygpKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG4gIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgIGNoaWxkcmVuTGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW5MZW5ndGg7ICsraSkge1xuICAgIHR4dCArPSBzaG93ZG93bi5zdWJQYXJzZXIoJ21ha2VNYXJrZG93bi5ub2RlJykoY2hpbGRyZW5baV0sIGdsb2JhbHMsIHRydWUpO1xuICB9XG4gIHJldHVybiB0eHQudHJpbSgpO1xufSk7XG5cclxuc2hvd2Rvd24uc3ViUGFyc2VyKCdtYWtlTWFya2Rvd24udHh0JywgZnVuY3Rpb24gKG5vZGUpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB0eHQgPSBub2RlLm5vZGVWYWx1ZTtcblxuICAvLyBtdWx0aXBsZSBzcGFjZXMgYXJlIGNvbGxhcHNlZFxuICB0eHQgPSB0eHQucmVwbGFjZSgvICsvZywgJyAnKTtcblxuICAvLyByZXBsYWNlIHRoZSBjdXN0b20gwqhOQlNQOyB3aXRoIGEgc3BhY2VcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL8KoTkJTUDsvZywgJyAnKTtcblxuICAvLyBcIiwgPCwgPiBhbmQgJiBzaG91bGQgcmVwbGFjZSBlc2NhcGVkIGh0bWwgZW50aXRpZXNcbiAgdHh0ID0gc2hvd2Rvd24uaGVscGVyLnVuZXNjYXBlSFRNTEVudGl0aWVzKHR4dCk7XG5cbiAgLy8gZXNjYXBlIG1hcmtkb3duIG1hZ2ljIGNoYXJhY3RlcnNcbiAgLy8gZW1waGFzaXMsIHN0cm9uZyBhbmQgc3RyaWtldGhyb3VnaCAtIGNhbiBhcHBlYXIgZXZlcnl3aGVyZVxuICAvLyB3ZSBhbHNvIGVzY2FwZSBwaXBlICh8KSBiZWNhdXNlIG9mIHRhYmxlc1xuICAvLyBhbmQgZXNjYXBlIGAgYmVjYXVzZSBvZiBjb2RlIGJsb2NrcyBhbmQgc3BhbnNcbiAgdHh0ID0gdHh0LnJlcGxhY2UoLyhbKl9+fGBdKS9nLCAnXFxcXCQxJyk7XG5cbiAgLy8gZXNjYXBlID4gYmVjYXVzZSBvZiBibG9ja3F1b3Rlc1xuICB0eHQgPSB0eHQucmVwbGFjZSgvXihcXHMqKT4vZywgJ1xcXFwkMT4nKTtcblxuICAvLyBoYXNoIGNoYXJhY3Rlciwgb25seSB0cm91Ymxlc29tZSBhdCB0aGUgYmVnaW5uaW5nIG9mIGEgbGluZSBiZWNhdXNlIG9mIGhlYWRlcnNcbiAgdHh0ID0gdHh0LnJlcGxhY2UoL14jL2dtLCAnXFxcXCMnKTtcblxuICAvLyBob3Jpem9udGFsIHJ1bGVzXG4gIHR4dCA9IHR4dC5yZXBsYWNlKC9eKFxccyopKFstPV17Myx9KShcXHMqKSQvLCAnJDFcXFxcJDIkMycpO1xuXG4gIC8vIGRvdCwgYmVjYXVzZSBvZiBvcmRlcmVkIGxpc3RzLCBvbmx5IHRyb3VibGVzb21lIGF0IHRoZSBiZWdpbm5pbmcgb2YgYSBsaW5lIHdoZW4gcHJlY2VkZWQgYnkgYW4gaW50ZWdlclxuICB0eHQgPSB0eHQucmVwbGFjZSgvXiggezAsM31cXGQrKVxcLi9nbSwgJyQxXFxcXC4nKTtcblxuICAvLyArLCAqIGFuZCAtLCBhdCB0aGUgYmVnaW5uaW5nIG9mIGEgbGluZSBiZWNvbWVzIGEgbGlzdCwgc28gd2UgbmVlZCB0byBlc2NhcGUgdGhlbSBhbHNvIChhc3RlcmlzayB3YXMgYWxyZWFkeSBlc2NhcGVkKVxuICB0eHQgPSB0eHQucmVwbGFjZSgvXiggezAsM30pKFsrLV0pL2dtLCAnJDFcXFxcJDInKTtcblxuICAvLyBpbWFnZXMgYW5kIGxpbmtzLCBdIGZvbGxvd2VkIGJ5ICggaXMgcHJvYmxlbWF0aWMsIHNvIHdlIGVzY2FwZSBpdFxuICB0eHQgPSB0eHQucmVwbGFjZSgvXShbXFxzXSopXFwoL2csICdcXFxcXSQxXFxcXCgnKTtcblxuICAvLyByZWZlcmVuY2UgVVJJcyBtdXN0IGFsc28gYmUgZXNjYXBlZFxuICB0eHQgPSB0eHQucmVwbGFjZSgvXiB7MCwzfVxcWyhbXFxTIFxcdF0qPyldOi9nbSwgJ1xcXFxbJDFdOicpO1xuXG4gIHJldHVybiB0eHQ7XG59KTtcblxyXG52YXIgcm9vdCA9IHRoaXM7XG5cbi8vIEFNRCBMb2FkZXJcbmlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAndXNlIHN0cmljdCc7XG4gICAgcmV0dXJuIHNob3dkb3duO1xuICB9KTtcblxuLy8gQ29tbW9uSlMvbm9kZUpTIExvYWRlclxufSBlbHNlIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICBtb2R1bGUuZXhwb3J0cyA9IHNob3dkb3duO1xuXG4vLyBSZWd1bGFyIEJyb3dzZXIgbG9hZGVyXG59IGVsc2Uge1xuICByb290LnNob3dkb3duID0gc2hvd2Rvd247XG59XG59KS5jYWxsKHRoaXMpO1xyXG5cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNob3dkb3duLmpzLm1hcFxyXG4iLCIvLyBSZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZVxuLy8gQ29weXJpZ2h0IChjKSAyMDA5LTIwMTAgRG9taW5pYyBCYWdnb3R0XG4vLyBDb3B5cmlnaHQgKGMpIDIwMDktMjAxMCBBc2ggQmVybGluXG4vLyBDb3B5cmlnaHQgKGMpIDIwMTEgQ2hyaXN0b3BoIERvcm4gPGNocmlzdG9waEBjaHJpc3RvcGhkb3JuLmNvbT4gKGh0dHA6Ly93d3cuY2hyaXN0b3BoZG9ybi5jb20pXG5cbi8qanNoaW50IGJyb3dzZXI6dHJ1ZSwgZGV2ZWw6dHJ1ZSAqL1xuXG4oZnVuY3Rpb24oIGV4cG9zZSApIHtcblxuLyoqXG4gKiAgY2xhc3MgTWFya2Rvd25cbiAqXG4gKiAgTWFya2Rvd24gcHJvY2Vzc2luZyBpbiBKYXZhc2NyaXB0IGRvbmUgcmlnaHQuIFdlIGhhdmUgdmVyeSBwYXJ0aWN1bGFyIHZpZXdzXG4gKiAgb24gd2hhdCBjb25zdGl0dXRlcyAncmlnaHQnIHdoaWNoIGluY2x1ZGU6XG4gKlxuICogIC0gcHJvZHVjZXMgd2VsbC1mb3JtZWQgSFRNTCAodGhpcyBtZWFucyB0aGF0IGVtIGFuZCBzdHJvbmcgbmVzdGluZyBpc1xuICogICAgaW1wb3J0YW50KVxuICpcbiAqICAtIGhhcyBhbiBpbnRlcm1lZGlhdGUgcmVwcmVzZW50YXRpb24gdG8gYWxsb3cgcHJvY2Vzc2luZyBvZiBwYXJzZWQgZGF0YSAoV2VcbiAqICAgIGluIGZhY3QgaGF2ZSB0d28sIGJvdGggYXMgW0pzb25NTF06IGEgbWFya2Rvd24gdHJlZSBhbmQgYW4gSFRNTCB0cmVlKS5cbiAqXG4gKiAgLSBpcyBlYXNpbHkgZXh0ZW5zaWJsZSB0byBhZGQgbmV3IGRpYWxlY3RzIHdpdGhvdXQgaGF2aW5nIHRvIHJld3JpdGUgdGhlXG4gKiAgICBlbnRpcmUgcGFyc2luZyBtZWNoYW5pY3NcbiAqXG4gKiAgLSBoYXMgYSBnb29kIHRlc3Qgc3VpdGVcbiAqXG4gKiAgVGhpcyBpbXBsZW1lbnRhdGlvbiBmdWxmaWxscyBhbGwgb2YgdGhlc2UgKGV4Y2VwdCB0aGF0IHRoZSB0ZXN0IHN1aXRlIGNvdWxkXG4gKiAgZG8gd2l0aCBleHBhbmRpbmcgdG8gYXV0b21hdGljYWxseSBydW4gYWxsIHRoZSBmaXh0dXJlcyBmcm9tIG90aGVyIE1hcmtkb3duXG4gKiAgaW1wbGVtZW50YXRpb25zLilcbiAqXG4gKiAgIyMjIyMgSW50ZXJtZWRpYXRlIFJlcHJlc2VudGF0aW9uXG4gKlxuICogICpUT0RPKiBUYWxrIGFib3V0IHRoaXMgOikgSXRzIEpzb25NTCwgYnV0IGRvY3VtZW50IHRoZSBub2RlIG5hbWVzIHdlIHVzZS5cbiAqXG4gKiAgW0pzb25NTF06IGh0dHA6Ly9qc29ubWwub3JnLyBcIkpTT04gTWFya3VwIExhbmd1YWdlXCJcbiAqKi9cbnZhciBNYXJrZG93biA9IGV4cG9zZS5NYXJrZG93biA9IGZ1bmN0aW9uKGRpYWxlY3QpIHtcbiAgc3dpdGNoICh0eXBlb2YgZGlhbGVjdCkge1xuICAgIGNhc2UgXCJ1bmRlZmluZWRcIjpcbiAgICAgIHRoaXMuZGlhbGVjdCA9IE1hcmtkb3duLmRpYWxlY3RzLkdydWJlcjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgIHRoaXMuZGlhbGVjdCA9IGRpYWxlY3Q7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgaWYgKCBkaWFsZWN0IGluIE1hcmtkb3duLmRpYWxlY3RzICkge1xuICAgICAgICB0aGlzLmRpYWxlY3QgPSBNYXJrZG93bi5kaWFsZWN0c1tkaWFsZWN0XTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIE1hcmtkb3duIGRpYWxlY3QgJ1wiICsgU3RyaW5nKGRpYWxlY3QpICsgXCInXCIpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gIH1cbiAgdGhpcy5lbV9zdGF0ZSA9IFtdO1xuICB0aGlzLnN0cm9uZ19zdGF0ZSA9IFtdO1xuICB0aGlzLmRlYnVnX2luZGVudCA9IFwiXCI7XG59O1xuXG4vKipcbiAqICBwYXJzZSggbWFya2Rvd24sIFtkaWFsZWN0XSApIC0+IEpzb25NTFxuICogIC0gbWFya2Rvd24gKFN0cmluZyk6IG1hcmtkb3duIHN0cmluZyB0byBwYXJzZVxuICogIC0gZGlhbGVjdCAoU3RyaW5nIHwgRGlhbGVjdCk6IHRoZSBkaWFsZWN0IHRvIHVzZSwgZGVmYXVsdHMgdG8gZ3J1YmVyXG4gKlxuICogIFBhcnNlIGBtYXJrZG93bmAgYW5kIHJldHVybiBhIG1hcmtkb3duIGRvY3VtZW50IGFzIGEgTWFya2Rvd24uSnNvbk1MIHRyZWUuXG4gKiovXG5leHBvc2UucGFyc2UgPSBmdW5jdGlvbiggc291cmNlLCBkaWFsZWN0ICkge1xuICAvLyBkaWFsZWN0IHdpbGwgZGVmYXVsdCBpZiB1bmRlZmluZWRcbiAgdmFyIG1kID0gbmV3IE1hcmtkb3duKCBkaWFsZWN0ICk7XG4gIHJldHVybiBtZC50b1RyZWUoIHNvdXJjZSApO1xufTtcblxuLyoqXG4gKiAgdG9IVE1MKCBtYXJrZG93biwgW2RpYWxlY3RdICApIC0+IFN0cmluZ1xuICogIHRvSFRNTCggbWRfdHJlZSApIC0+IFN0cmluZ1xuICogIC0gbWFya2Rvd24gKFN0cmluZyk6IG1hcmtkb3duIHN0cmluZyB0byBwYXJzZVxuICogIC0gbWRfdHJlZSAoTWFya2Rvd24uSnNvbk1MKTogcGFyc2VkIG1hcmtkb3duIHRyZWVcbiAqXG4gKiAgVGFrZSBtYXJrZG93biAoZWl0aGVyIGFzIGEgc3RyaW5nIG9yIGFzIGEgSnNvbk1MIHRyZWUpIGFuZCBydW4gaXQgdGhyb3VnaFxuICogIFtbdG9IVE1MVHJlZV1dIHRoZW4gdHVybiBpdCBpbnRvIGEgd2VsbC1mb3JtYXRlZCBIVE1MIGZyYWdtZW50LlxuICoqL1xuZXhwb3NlLnRvSFRNTCA9IGZ1bmN0aW9uIHRvSFRNTCggc291cmNlICwgZGlhbGVjdCAsIG9wdGlvbnMgKSB7XG4gIHZhciBpbnB1dCA9IGV4cG9zZS50b0hUTUxUcmVlKCBzb3VyY2UgLCBkaWFsZWN0ICwgb3B0aW9ucyApO1xuXG4gIHJldHVybiBleHBvc2UucmVuZGVySnNvbk1MKCBpbnB1dCApO1xufTtcblxuLyoqXG4gKiAgdG9IVE1MVHJlZSggbWFya2Rvd24sIFtkaWFsZWN0XSApIC0+IEpzb25NTFxuICogIHRvSFRNTFRyZWUoIG1kX3RyZWUgKSAtPiBKc29uTUxcbiAqICAtIG1hcmtkb3duIChTdHJpbmcpOiBtYXJrZG93biBzdHJpbmcgdG8gcGFyc2VcbiAqICAtIGRpYWxlY3QgKFN0cmluZyB8IERpYWxlY3QpOiB0aGUgZGlhbGVjdCB0byB1c2UsIGRlZmF1bHRzIHRvIGdydWJlclxuICogIC0gbWRfdHJlZSAoTWFya2Rvd24uSnNvbk1MKTogcGFyc2VkIG1hcmtkb3duIHRyZWVcbiAqXG4gKiAgVHVybiBtYXJrZG93biBpbnRvIEhUTUwsIHJlcHJlc2VudGVkIGFzIGEgSnNvbk1MIHRyZWUuIElmIGEgc3RyaW5nIGlzIGdpdmVuXG4gKiAgdG8gdGhpcyBmdW5jdGlvbiwgaXQgaXMgZmlyc3QgcGFyc2VkIGludG8gYSBtYXJrZG93biB0cmVlIGJ5IGNhbGxpbmdcbiAqICBbW3BhcnNlXV0uXG4gKiovXG5leHBvc2UudG9IVE1MVHJlZSA9IGZ1bmN0aW9uIHRvSFRNTFRyZWUoIGlucHV0LCBkaWFsZWN0ICwgb3B0aW9ucyApIHtcbiAgLy8gY29udmVydCBzdHJpbmcgaW5wdXQgdG8gYW4gTUQgdHJlZVxuICBpZiAoIHR5cGVvZiBpbnB1dCA9PT1cInN0cmluZ1wiICkgaW5wdXQgPSB0aGlzLnBhcnNlKCBpbnB1dCwgZGlhbGVjdCApO1xuXG4gIC8vIE5vdyBjb252ZXJ0IHRoZSBNRCB0cmVlIHRvIGFuIEhUTUwgdHJlZVxuXG4gIC8vIHJlbW92ZSByZWZlcmVuY2VzIGZyb20gdGhlIHRyZWVcbiAgdmFyIGF0dHJzID0gZXh0cmFjdF9hdHRyKCBpbnB1dCApLFxuICAgICAgcmVmcyA9IHt9O1xuXG4gIGlmICggYXR0cnMgJiYgYXR0cnMucmVmZXJlbmNlcyApIHtcbiAgICByZWZzID0gYXR0cnMucmVmZXJlbmNlcztcbiAgfVxuXG4gIHZhciBodG1sID0gY29udmVydF90cmVlX3RvX2h0bWwoIGlucHV0LCByZWZzICwgb3B0aW9ucyApO1xuICBtZXJnZV90ZXh0X25vZGVzKCBodG1sICk7XG4gIHJldHVybiBodG1sO1xufTtcblxuLy8gRm9yIFNwaWRlcm1vbmtleSBiYXNlZCBlbmdpbmVzXG5mdW5jdGlvbiBta19ibG9ja190b1NvdXJjZSgpIHtcbiAgcmV0dXJuIFwiTWFya2Rvd24ubWtfYmxvY2soIFwiICtcbiAgICAgICAgICB1bmV2YWwodGhpcy50b1N0cmluZygpKSArXG4gICAgICAgICAgXCIsIFwiICtcbiAgICAgICAgICB1bmV2YWwodGhpcy50cmFpbGluZykgK1xuICAgICAgICAgIFwiLCBcIiArXG4gICAgICAgICAgdW5ldmFsKHRoaXMubGluZU51bWJlcikgK1xuICAgICAgICAgIFwiIClcIjtcbn1cblxuLy8gbm9kZVxuZnVuY3Rpb24gbWtfYmxvY2tfaW5zcGVjdCgpIHtcbiAgdmFyIHV0aWwgPSByZXF1aXJlKFwidXRpbFwiKTtcbiAgcmV0dXJuIFwiTWFya2Rvd24ubWtfYmxvY2soIFwiICtcbiAgICAgICAgICB1dGlsLmluc3BlY3QodGhpcy50b1N0cmluZygpKSArXG4gICAgICAgICAgXCIsIFwiICtcbiAgICAgICAgICB1dGlsLmluc3BlY3QodGhpcy50cmFpbGluZykgK1xuICAgICAgICAgIFwiLCBcIiArXG4gICAgICAgICAgdXRpbC5pbnNwZWN0KHRoaXMubGluZU51bWJlcikgK1xuICAgICAgICAgIFwiIClcIjtcblxufVxuXG52YXIgbWtfYmxvY2sgPSBNYXJrZG93bi5ta19ibG9jayA9IGZ1bmN0aW9uKGJsb2NrLCB0cmFpbCwgbGluZSkge1xuICAvLyBCZSBoZWxwZnVsIGZvciBkZWZhdWx0IGNhc2UgaW4gdGVzdHMuXG4gIGlmICggYXJndW1lbnRzLmxlbmd0aCA9PSAxICkgdHJhaWwgPSBcIlxcblxcblwiO1xuXG4gIHZhciBzID0gbmV3IFN0cmluZyhibG9jayk7XG4gIHMudHJhaWxpbmcgPSB0cmFpbDtcbiAgLy8gVG8gbWFrZSBpdCBjbGVhciBpdHMgbm90IGp1c3QgYSBzdHJpbmdcbiAgcy5pbnNwZWN0ID0gbWtfYmxvY2tfaW5zcGVjdDtcbiAgcy50b1NvdXJjZSA9IG1rX2Jsb2NrX3RvU291cmNlO1xuXG4gIGlmICggbGluZSAhPSB1bmRlZmluZWQgKVxuICAgIHMubGluZU51bWJlciA9IGxpbmU7XG5cbiAgcmV0dXJuIHM7XG59O1xuXG5mdW5jdGlvbiBjb3VudF9saW5lcyggc3RyICkge1xuICB2YXIgbiA9IDAsIGkgPSAtMTtcbiAgd2hpbGUgKCAoIGkgPSBzdHIuaW5kZXhPZihcIlxcblwiLCBpICsgMSkgKSAhPT0gLTEgKSBuKys7XG4gIHJldHVybiBuO1xufVxuXG4vLyBJbnRlcm5hbCAtIHNwbGl0IHNvdXJjZSBpbnRvIHJvdWdoIGJsb2Nrc1xuTWFya2Rvd24ucHJvdG90eXBlLnNwbGl0X2Jsb2NrcyA9IGZ1bmN0aW9uIHNwbGl0QmxvY2tzKCBpbnB1dCwgc3RhcnRMaW5lICkge1xuICBpbnB1dCA9IGlucHV0LnJlcGxhY2UoLyhcXHJcXG58XFxufFxccikvZywgXCJcXG5cIik7XG4gIC8vIFtcXHNcXFNdIG1hdGNoZXMgX2FueXRoaW5nXyAobmV3bGluZSBvciBzcGFjZSlcbiAgLy8gW15dIGlzIGVxdWl2YWxlbnQgYnV0IGRvZXNuJ3Qgd29yayBpbiBJRXMuXG4gIHZhciByZSA9IC8oW1xcc1xcU10rPykoJHxcXG4jfFxcbig/OlxccypcXG58JCkrKS9nLFxuICAgICAgYmxvY2tzID0gW10sXG4gICAgICBtO1xuXG4gIHZhciBsaW5lX25vID0gMTtcblxuICBpZiAoICggbSA9IC9eKFxccypcXG4pLy5leGVjKGlucHV0KSApICE9IG51bGwgKSB7XG4gICAgLy8gc2tpcCAoYnV0IGNvdW50KSBsZWFkaW5nIGJsYW5rIGxpbmVzXG4gICAgbGluZV9ubyArPSBjb3VudF9saW5lcyggbVswXSApO1xuICAgIHJlLmxhc3RJbmRleCA9IG1bMF0ubGVuZ3RoO1xuICB9XG5cbiAgd2hpbGUgKCAoIG0gPSByZS5leGVjKGlucHV0KSApICE9PSBudWxsICkge1xuICAgIGlmIChtWzJdID09IFwiXFxuI1wiKSB7XG4gICAgICBtWzJdID0gXCJcXG5cIjtcbiAgICAgIHJlLmxhc3RJbmRleC0tO1xuICAgIH1cbiAgICBibG9ja3MucHVzaCggbWtfYmxvY2soIG1bMV0sIG1bMl0sIGxpbmVfbm8gKSApO1xuICAgIGxpbmVfbm8gKz0gY291bnRfbGluZXMoIG1bMF0gKTtcbiAgfVxuXG4gIHJldHVybiBibG9ja3M7XG59O1xuXG4vKipcbiAqICBNYXJrZG93biNwcm9jZXNzQmxvY2soIGJsb2NrLCBuZXh0ICkgLT4gdW5kZWZpbmVkIHwgWyBKc29uTUwsIC4uLiBdXG4gKiAgLSBibG9jayAoU3RyaW5nKTogdGhlIGJsb2NrIHRvIHByb2Nlc3NcbiAqICAtIG5leHQgKEFycmF5KTogdGhlIGZvbGxvd2luZyBibG9ja3NcbiAqXG4gKiBQcm9jZXNzIGBibG9ja2AgYW5kIHJldHVybiBhbiBhcnJheSBvZiBKc29uTUwgbm9kZXMgcmVwcmVzZW50aW5nIGBibG9ja2AuXG4gKlxuICogSXQgZG9lcyB0aGlzIGJ5IGFza2luZyBlYWNoIGJsb2NrIGxldmVsIGZ1bmN0aW9uIGluIHRoZSBkaWFsZWN0IHRvIHByb2Nlc3NcbiAqIHRoZSBibG9jayB1bnRpbCBvbmUgY2FuLiBTdWNjZXNmdWwgaGFuZGxpbmcgaXMgaW5kaWNhdGVkIGJ5IHJldHVybmluZyBhblxuICogYXJyYXkgKHdpdGggemVybyBvciBtb3JlIEpzb25NTCBub2RlcyksIGZhaWx1cmUgYnkgYSBmYWxzZSB2YWx1ZS5cbiAqXG4gKiBCbG9ja3MgaGFuZGxlcnMgYXJlIHJlc3BvbnNpYmxlIGZvciBjYWxsaW5nIFtbTWFya2Rvd24jcHJvY2Vzc0lubGluZV1dXG4gKiB0aGVtc2VsdmVzIGFzIGFwcHJvcHJpYXRlLlxuICpcbiAqIElmIHRoZSBibG9ja3Mgd2VyZSBzcGxpdCBpbmNvcnJlY3RseSBvciBhZGphY2VudCBibG9ja3MgbmVlZCBjb2xsYXBzaW5nIHlvdVxuICogY2FuIGFkanVzdCBgbmV4dGAgaW4gcGxhY2UgdXNpbmcgc2hpZnQvc3BsaWNlIGV0Yy5cbiAqXG4gKiBJZiBhbnkgb2YgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBpcyBub3QgcmlnaHQgZm9yIHRoZSBkaWFsZWN0LCB5b3UgY2FuXG4gKiBkZWZpbmUgYSBgX19jYWxsX19gIG1ldGhvZCBvbiB0aGUgZGlhbGVjdCB0aGF0IHdpbGwgZ2V0IGludm9rZWQgdG8gaGFuZGxlXG4gKiB0aGUgYmxvY2sgcHJvY2Vzc2luZy5cbiAqL1xuTWFya2Rvd24ucHJvdG90eXBlLnByb2Nlc3NCbG9jayA9IGZ1bmN0aW9uIHByb2Nlc3NCbG9jayggYmxvY2ssIG5leHQgKSB7XG4gIHZhciBjYnMgPSB0aGlzLmRpYWxlY3QuYmxvY2ssXG4gICAgICBvcmQgPSBjYnMuX19vcmRlcl9fO1xuXG4gIGlmICggXCJfX2NhbGxfX1wiIGluIGNicyApIHtcbiAgICByZXR1cm4gY2JzLl9fY2FsbF9fLmNhbGwodGhpcywgYmxvY2ssIG5leHQpO1xuICB9XG5cbiAgZm9yICggdmFyIGkgPSAwOyBpIDwgb3JkLmxlbmd0aDsgaSsrICkge1xuICAgIC8vRDp0aGlzLmRlYnVnKCBcIlRlc3RpbmdcIiwgb3JkW2ldICk7XG4gICAgdmFyIHJlcyA9IGNic1sgb3JkW2ldIF0uY2FsbCggdGhpcywgYmxvY2ssIG5leHQgKTtcbiAgICBpZiAoIHJlcyApIHtcbiAgICAgIC8vRDp0aGlzLmRlYnVnKFwiICBtYXRjaGVkXCIpO1xuICAgICAgaWYgKCAhaXNBcnJheShyZXMpIHx8ICggcmVzLmxlbmd0aCA+IDAgJiYgISggaXNBcnJheShyZXNbMF0pICkgKSApXG4gICAgICAgIHRoaXMuZGVidWcob3JkW2ldLCBcImRpZG4ndCByZXR1cm4gYSBwcm9wZXIgYXJyYXlcIik7XG4gICAgICAvL0Q6dGhpcy5kZWJ1ZyggXCJcIiApO1xuICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gIH1cblxuICAvLyBVaG9oISBubyBtYXRjaCEgU2hvdWxkIHdlIHRocm93IGFuIGVycm9yP1xuICByZXR1cm4gW107XG59O1xuXG5NYXJrZG93bi5wcm90b3R5cGUucHJvY2Vzc0lubGluZSA9IGZ1bmN0aW9uIHByb2Nlc3NJbmxpbmUoIGJsb2NrICkge1xuICByZXR1cm4gdGhpcy5kaWFsZWN0LmlubGluZS5fX2NhbGxfXy5jYWxsKCB0aGlzLCBTdHJpbmcoIGJsb2NrICkgKTtcbn07XG5cbi8qKlxuICogIE1hcmtkb3duI3RvVHJlZSggc291cmNlICkgLT4gSnNvbk1MXG4gKiAgLSBzb3VyY2UgKFN0cmluZyk6IG1hcmtkb3duIHNvdXJjZSB0byBwYXJzZVxuICpcbiAqICBQYXJzZSBgc291cmNlYCBpbnRvIGEgSnNvbk1MIHRyZWUgcmVwcmVzZW50aW5nIHRoZSBtYXJrZG93biBkb2N1bWVudC5cbiAqKi9cbi8vIGN1c3RvbV90cmVlIG1lYW5zIHNldCB0aGlzLnRyZWUgdG8gYGN1c3RvbV90cmVlYCBhbmQgcmVzdG9yZSBvbGQgdmFsdWUgb24gcmV0dXJuXG5NYXJrZG93bi5wcm90b3R5cGUudG9UcmVlID0gZnVuY3Rpb24gdG9UcmVlKCBzb3VyY2UsIGN1c3RvbV9yb290ICkge1xuICB2YXIgYmxvY2tzID0gc291cmNlIGluc3RhbmNlb2YgQXJyYXkgPyBzb3VyY2UgOiB0aGlzLnNwbGl0X2Jsb2Nrcyggc291cmNlICk7XG5cbiAgLy8gTWFrZSB0cmVlIGEgbWVtYmVyIHZhcmlhYmxlIHNvIGl0cyBlYXNpZXIgdG8gbWVzcyB3aXRoIGluIGV4dGVuc2lvbnNcbiAgdmFyIG9sZF90cmVlID0gdGhpcy50cmVlO1xuICB0cnkge1xuICAgIHRoaXMudHJlZSA9IGN1c3RvbV9yb290IHx8IHRoaXMudHJlZSB8fCBbIFwibWFya2Rvd25cIiBdO1xuXG4gICAgYmxvY2tzOlxuICAgIHdoaWxlICggYmxvY2tzLmxlbmd0aCApIHtcbiAgICAgIHZhciBiID0gdGhpcy5wcm9jZXNzQmxvY2soIGJsb2Nrcy5zaGlmdCgpLCBibG9ja3MgKTtcblxuICAgICAgLy8gUmVmZXJlbmNlIGJsb2NrcyBhbmQgdGhlIGxpa2Ugd29uJ3QgcmV0dXJuIGFueSBjb250ZW50XG4gICAgICBpZiAoICFiLmxlbmd0aCApIGNvbnRpbnVlIGJsb2NrcztcblxuICAgICAgdGhpcy50cmVlLnB1c2guYXBwbHkoIHRoaXMudHJlZSwgYiApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50cmVlO1xuICB9XG4gIGZpbmFsbHkge1xuICAgIGlmICggY3VzdG9tX3Jvb3QgKSB7XG4gICAgICB0aGlzLnRyZWUgPSBvbGRfdHJlZTtcbiAgICB9XG4gIH1cbn07XG5cbi8vIE5vb3AgYnkgZGVmYXVsdFxuTWFya2Rvd24ucHJvdG90eXBlLmRlYnVnID0gZnVuY3Rpb24gKCkge1xuICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKCBhcmd1bWVudHMpO1xuICBhcmdzLnVuc2hpZnQodGhpcy5kZWJ1Z19pbmRlbnQpO1xuICBpZiAoIHR5cGVvZiBwcmludCAhPT0gXCJ1bmRlZmluZWRcIiApXG4gICAgICBwcmludC5hcHBseSggcHJpbnQsIGFyZ3MgKTtcbiAgaWYgKCB0eXBlb2YgY29uc29sZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgY29uc29sZS5sb2cgIT09IFwidW5kZWZpbmVkXCIgKVxuICAgICAgY29uc29sZS5sb2cuYXBwbHkoIG51bGwsIGFyZ3MgKTtcbn1cblxuTWFya2Rvd24ucHJvdG90eXBlLmxvb3BfcmVfb3Zlcl9ibG9jayA9IGZ1bmN0aW9uKCByZSwgYmxvY2ssIGNiICkge1xuICAvLyBEb250IHVzZSAvZyByZWdleHBzIHdpdGggdGhpc1xuICB2YXIgbSxcbiAgICAgIGIgPSBibG9jay52YWx1ZU9mKCk7XG5cbiAgd2hpbGUgKCBiLmxlbmd0aCAmJiAobSA9IHJlLmV4ZWMoYikgKSAhPSBudWxsICkge1xuICAgIGIgPSBiLnN1YnN0ciggbVswXS5sZW5ndGggKTtcbiAgICBjYi5jYWxsKHRoaXMsIG0pO1xuICB9XG4gIHJldHVybiBiO1xufTtcblxuLyoqXG4gKiBNYXJrZG93bi5kaWFsZWN0c1xuICpcbiAqIE5hbWVzcGFjZSBvZiBidWlsdC1pbiBkaWFsZWN0cy5cbiAqKi9cbk1hcmtkb3duLmRpYWxlY3RzID0ge307XG5cbi8qKlxuICogTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyXG4gKlxuICogVGhlIGRlZmF1bHQgZGlhbGVjdCB0aGF0IGZvbGxvd3MgdGhlIHJ1bGVzIHNldCBvdXQgYnkgSm9obiBHcnViZXInc1xuICogbWFya2Rvd24ucGwgYXMgY2xvc2VseSBhcyBwb3NzaWJsZS4gV2VsbCBhY3R1YWxseSB3ZSBmb2xsb3cgdGhlIGJlaGF2aW91ciBvZlxuICogdGhhdCBzY3JpcHQgd2hpY2ggaW4gc29tZSBwbGFjZXMgaXMgbm90IGV4YWN0bHkgd2hhdCB0aGUgc3ludGF4IHdlYiBwYWdlXG4gKiBzYXlzLlxuICoqL1xuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyID0ge1xuICBibG9jazoge1xuICAgIGF0eEhlYWRlcjogZnVuY3Rpb24gYXR4SGVhZGVyKCBibG9jaywgbmV4dCApIHtcbiAgICAgIHZhciBtID0gYmxvY2subWF0Y2goIC9eKCN7MSw2fSlcXHMqKC4qPylcXHMqIypcXHMqKD86XFxufCQpLyApO1xuXG4gICAgICBpZiAoICFtICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgdmFyIGhlYWRlciA9IFsgXCJoZWFkZXJcIiwgeyBsZXZlbDogbVsgMSBdLmxlbmd0aCB9IF07XG4gICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShoZWFkZXIsIHRoaXMucHJvY2Vzc0lubGluZShtWyAyIF0pKTtcblxuICAgICAgaWYgKCBtWzBdLmxlbmd0aCA8IGJsb2NrLmxlbmd0aCApXG4gICAgICAgIG5leHQudW5zaGlmdCggbWtfYmxvY2soIGJsb2NrLnN1YnN0ciggbVswXS5sZW5ndGggKSwgYmxvY2sudHJhaWxpbmcsIGJsb2NrLmxpbmVOdW1iZXIgKyAyICkgKTtcblxuICAgICAgcmV0dXJuIFsgaGVhZGVyIF07XG4gICAgfSxcblxuICAgIHNldGV4dEhlYWRlcjogZnVuY3Rpb24gc2V0ZXh0SGVhZGVyKCBibG9jaywgbmV4dCApIHtcbiAgICAgIHZhciBtID0gYmxvY2subWF0Y2goIC9eKC4qKVxcbihbLT1dKVxcMlxcMisoPzpcXG58JCkvICk7XG5cbiAgICAgIGlmICggIW0gKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICB2YXIgbGV2ZWwgPSAoIG1bIDIgXSA9PT0gXCI9XCIgKSA/IDEgOiAyO1xuICAgICAgdmFyIGhlYWRlciA9IFsgXCJoZWFkZXJcIiwgeyBsZXZlbCA6IGxldmVsIH0sIG1bIDEgXSBdO1xuXG4gICAgICBpZiAoIG1bMF0ubGVuZ3RoIDwgYmxvY2subGVuZ3RoIClcbiAgICAgICAgbmV4dC51bnNoaWZ0KCBta19ibG9jayggYmxvY2suc3Vic3RyKCBtWzBdLmxlbmd0aCApLCBibG9jay50cmFpbGluZywgYmxvY2subGluZU51bWJlciArIDIgKSApO1xuXG4gICAgICByZXR1cm4gWyBoZWFkZXIgXTtcbiAgICB9LFxuXG4gICAgY29kZTogZnVuY3Rpb24gY29kZSggYmxvY2ssIG5leHQgKSB7XG4gICAgICAvLyB8ICAgIEZvb1xuICAgICAgLy8gfGJhclxuICAgICAgLy8gc2hvdWxkIGJlIGEgY29kZSBibG9jayBmb2xsb3dlZCBieSBhIHBhcmFncmFwaC4gRnVuXG4gICAgICAvL1xuICAgICAgLy8gVGhlcmUgbWlnaHQgYWxzbyBiZSBhZGphY2VudCBjb2RlIGJsb2NrIHRvIG1lcmdlLlxuXG4gICAgICB2YXIgcmV0ID0gW10sXG4gICAgICAgICAgcmUgPSAvXig/OiB7MCwzfVxcdHwgezR9KSguKilcXG4/LyxcbiAgICAgICAgICBsaW5lcztcblxuICAgICAgLy8gNCBzcGFjZXMgKyBjb250ZW50XG4gICAgICBpZiAoICFibG9jay5tYXRjaCggcmUgKSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIGJsb2NrX3NlYXJjaDpcbiAgICAgIGRvIHtcbiAgICAgICAgLy8gTm93IHB1bGwgb3V0IHRoZSByZXN0IG9mIHRoZSBsaW5lc1xuICAgICAgICB2YXIgYiA9IHRoaXMubG9vcF9yZV9vdmVyX2Jsb2NrKFxuICAgICAgICAgICAgICAgICAgcmUsIGJsb2NrLnZhbHVlT2YoKSwgZnVuY3Rpb24oIG0gKSB7IHJldC5wdXNoKCBtWzFdICk7IH0gKTtcblxuICAgICAgICBpZiAoIGIubGVuZ3RoICkge1xuICAgICAgICAgIC8vIENhc2UgYWxsdWRlZCB0byBpbiBmaXJzdCBjb21tZW50LiBwdXNoIGl0IGJhY2sgb24gYXMgYSBuZXcgYmxvY2tcbiAgICAgICAgICBuZXh0LnVuc2hpZnQoIG1rX2Jsb2NrKGIsIGJsb2NrLnRyYWlsaW5nKSApO1xuICAgICAgICAgIGJyZWFrIGJsb2NrX3NlYXJjaDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICggbmV4dC5sZW5ndGggKSB7XG4gICAgICAgICAgLy8gQ2hlY2sgdGhlIG5leHQgYmxvY2sgLSBpdCBtaWdodCBiZSBjb2RlIHRvb1xuICAgICAgICAgIGlmICggIW5leHRbMF0ubWF0Y2goIHJlICkgKSBicmVhayBibG9ja19zZWFyY2g7XG5cbiAgICAgICAgICAvLyBQdWxsIGhvdyBob3cgbWFueSBibGFua3MgbGluZXMgZm9sbG93IC0gbWludXMgdHdvIHRvIGFjY291bnQgZm9yIC5qb2luXG4gICAgICAgICAgcmV0LnB1c2ggKCBibG9jay50cmFpbGluZy5yZXBsYWNlKC9bXlxcbl0vZywgXCJcIikuc3Vic3RyaW5nKDIpICk7XG5cbiAgICAgICAgICBibG9jayA9IG5leHQuc2hpZnQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBicmVhayBibG9ja19zZWFyY2g7XG4gICAgICAgIH1cbiAgICAgIH0gd2hpbGUgKCB0cnVlICk7XG5cbiAgICAgIHJldHVybiBbIFsgXCJjb2RlX2Jsb2NrXCIsIHJldC5qb2luKFwiXFxuXCIpIF0gXTtcbiAgICB9LFxuXG4gICAgaG9yaXpSdWxlOiBmdW5jdGlvbiBob3JpelJ1bGUoIGJsb2NrLCBuZXh0ICkge1xuICAgICAgLy8gdGhpcyBuZWVkcyB0byBmaW5kIGFueSBociBpbiB0aGUgYmxvY2sgdG8gaGFuZGxlIGFidXR0aW5nIGJsb2Nrc1xuICAgICAgdmFyIG0gPSBibG9jay5tYXRjaCggL14oPzooW1xcc1xcU10qPylcXG4pP1sgXFx0XSooWy1fKl0pKD86WyBcXHRdKlxcMil7Mix9WyBcXHRdKig/OlxcbihbXFxzXFxTXSopKT8kLyApO1xuXG4gICAgICBpZiAoICFtICkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICB2YXIganNvbm1sID0gWyBbIFwiaHJcIiBdIF07XG5cbiAgICAgIC8vIGlmIHRoZXJlJ3MgYSBsZWFkaW5nIGFidXR0aW5nIGJsb2NrLCBwcm9jZXNzIGl0XG4gICAgICBpZiAoIG1bIDEgXSApIHtcbiAgICAgICAganNvbm1sLnVuc2hpZnQuYXBwbHkoIGpzb25tbCwgdGhpcy5wcm9jZXNzQmxvY2soIG1bIDEgXSwgW10gKSApO1xuICAgICAgfVxuXG4gICAgICAvLyBpZiB0aGVyZSdzIGEgdHJhaWxpbmcgYWJ1dHRpbmcgYmxvY2ssIHN0aWNrIGl0IGludG8gbmV4dFxuICAgICAgaWYgKCBtWyAzIF0gKSB7XG4gICAgICAgIG5leHQudW5zaGlmdCggbWtfYmxvY2soIG1bIDMgXSApICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBqc29ubWw7XG4gICAgfSxcblxuICAgIC8vIFRoZXJlIGFyZSB0d28gdHlwZXMgb2YgbGlzdHMuIFRpZ2h0IGFuZCBsb29zZS4gVGlnaHQgbGlzdHMgaGF2ZSBubyB3aGl0ZXNwYWNlXG4gICAgLy8gYmV0d2VlbiB0aGUgaXRlbXMgKGFuZCByZXN1bHQgaW4gdGV4dCBqdXN0IGluIHRoZSA8bGk+KSBhbmQgbG9vc2UgbGlzdHMsXG4gICAgLy8gd2hpY2ggaGF2ZSBhbiBlbXB0eSBsaW5lIGJldHdlZW4gbGlzdCBpdGVtcywgcmVzdWx0aW5nIGluIChvbmUgb3IgbW9yZSlcbiAgICAvLyBwYXJhZ3JhcGhzIGluc2lkZSB0aGUgPGxpPi5cbiAgICAvL1xuICAgIC8vIFRoZXJlIGFyZSBhbGwgc29ydHMgd2VpcmQgZWRnZSBjYXNlcyBhYm91dCB0aGUgb3JpZ2luYWwgbWFya2Rvd24ucGwnc1xuICAgIC8vIGhhbmRsaW5nIG9mIGxpc3RzOlxuICAgIC8vXG4gICAgLy8gKiBOZXN0ZWQgbGlzdHMgYXJlIHN1cHBvc2VkIHRvIGJlIGluZGVudGVkIGJ5IGZvdXIgY2hhcnMgcGVyIGxldmVsLiBCdXRcbiAgICAvLyAgIGlmIHRoZXkgYXJlbid0LCB5b3UgY2FuIGdldCBhIG5lc3RlZCBsaXN0IGJ5IGluZGVudGluZyBieSBsZXNzIHRoYW5cbiAgICAvLyAgIGZvdXIgc28gbG9uZyBhcyB0aGUgaW5kZW50IGRvZXNuJ3QgbWF0Y2ggYW4gaW5kZW50IG9mIGFuIGV4aXN0aW5nIGxpc3RcbiAgICAvLyAgIGl0ZW0gaW4gdGhlICduZXN0IHN0YWNrJy5cbiAgICAvL1xuICAgIC8vICogVGhlIHR5cGUgb2YgdGhlIGxpc3QgKGJ1bGxldCBvciBudW1iZXIpIGlzIGNvbnRyb2xsZWQganVzdCBieSB0aGVcbiAgICAvLyAgICBmaXJzdCBpdGVtIGF0IHRoZSBpbmRlbnQuIFN1YnNlcXVlbnQgY2hhbmdlcyBhcmUgaWdub3JlZCB1bmxlc3MgdGhleVxuICAgIC8vICAgIGFyZSBmb3IgbmVzdGVkIGxpc3RzXG4gICAgLy9cbiAgICBsaXN0czogKGZ1bmN0aW9uKCApIHtcbiAgICAgIC8vIFVzZSBhIGNsb3N1cmUgdG8gaGlkZSBhIGZldyB2YXJpYWJsZXMuXG4gICAgICB2YXIgYW55X2xpc3QgPSBcIlsqKy1dfFxcXFxkK1xcXFwuXCIsXG4gICAgICAgICAgYnVsbGV0X2xpc3QgPSAvWyorLV0vLFxuICAgICAgICAgIG51bWJlcl9saXN0ID0gL1xcZCtcXC4vLFxuICAgICAgICAgIC8vIENhcHR1cmUgbGVhZGluZyBpbmRlbnQgYXMgaXQgbWF0dGVycyBmb3IgZGV0ZXJtaW5pbmcgbmVzdGVkIGxpc3RzLlxuICAgICAgICAgIGlzX2xpc3RfcmUgPSBuZXcgUmVnRXhwKCBcIl4oIHswLDN9KShcIiArIGFueV9saXN0ICsgXCIpWyBcXHRdK1wiICksXG4gICAgICAgICAgaW5kZW50X3JlID0gXCIoPzogezAsM31cXFxcdHwgezR9KVwiO1xuXG4gICAgICAvLyBUT0RPOiBDYWNoZSB0aGlzIHJlZ2V4cCBmb3IgY2VydGFpbiBkZXB0aHMuXG4gICAgICAvLyBDcmVhdGUgYSByZWdleHAgc3VpdGFibGUgZm9yIG1hdGNoaW5nIGFuIGxpIGZvciBhIGdpdmVuIHN0YWNrIGRlcHRoXG4gICAgICBmdW5jdGlvbiByZWdleF9mb3JfZGVwdGgoIGRlcHRoICkge1xuXG4gICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFxuICAgICAgICAgIC8vIG1bMV0gPSBpbmRlbnQsIG1bMl0gPSBsaXN0X3R5cGVcbiAgICAgICAgICBcIig/Ol4oXCIgKyBpbmRlbnRfcmUgKyBcInswLFwiICsgZGVwdGggKyBcIn0gezAsM30pKFwiICsgYW55X2xpc3QgKyBcIilcXFxccyspfFwiICtcbiAgICAgICAgICAvLyBtWzNdID0gY29udFxuICAgICAgICAgIFwiKF5cIiArIGluZGVudF9yZSArIFwiezAsXCIgKyAoZGVwdGgtMSkgKyBcIn1bIF17MCw0fSlcIlxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gZXhwYW5kX3RhYiggaW5wdXQgKSB7XG4gICAgICAgIHJldHVybiBpbnB1dC5yZXBsYWNlKCAvIHswLDN9XFx0L2csIFwiICAgIFwiICk7XG4gICAgICB9XG5cbiAgICAgIC8vIEFkZCBpbmxpbmUgY29udGVudCBgaW5saW5lYCB0byBgbGlgLiBpbmxpbmUgY29tZXMgZnJvbSBwcm9jZXNzSW5saW5lXG4gICAgICAvLyBzbyBpcyBhbiBhcnJheSBvZiBjb250ZW50XG4gICAgICBmdW5jdGlvbiBhZGQobGksIGxvb3NlLCBpbmxpbmUsIG5sKSB7XG4gICAgICAgIGlmICggbG9vc2UgKSB7XG4gICAgICAgICAgbGkucHVzaCggWyBcInBhcmFcIiBdLmNvbmNhdChpbmxpbmUpICk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIEhtbW0sIHNob3VsZCB0aGlzIGJlIGFueSBibG9jayBsZXZlbCBlbGVtZW50IG9yIGp1c3QgcGFyYXM/XG4gICAgICAgIHZhciBhZGRfdG8gPSBsaVtsaS5sZW5ndGggLTFdIGluc3RhbmNlb2YgQXJyYXkgJiYgbGlbbGkubGVuZ3RoIC0gMV1bMF0gPT0gXCJwYXJhXCJcbiAgICAgICAgICAgICAgICAgICA/IGxpW2xpLmxlbmd0aCAtMV1cbiAgICAgICAgICAgICAgICAgICA6IGxpO1xuXG4gICAgICAgIC8vIElmIHRoZXJlIGlzIGFscmVhZHkgc29tZSBjb250ZW50IGluIHRoaXMgbGlzdCwgYWRkIHRoZSBuZXcgbGluZSBpblxuICAgICAgICBpZiAoIG5sICYmIGxpLmxlbmd0aCA+IDEgKSBpbmxpbmUudW5zaGlmdChubCk7XG5cbiAgICAgICAgZm9yICggdmFyIGkgPSAwOyBpIDwgaW5saW5lLmxlbmd0aDsgaSsrICkge1xuICAgICAgICAgIHZhciB3aGF0ID0gaW5saW5lW2ldLFxuICAgICAgICAgICAgICBpc19zdHIgPSB0eXBlb2Ygd2hhdCA9PSBcInN0cmluZ1wiO1xuICAgICAgICAgIGlmICggaXNfc3RyICYmIGFkZF90by5sZW5ndGggPiAxICYmIHR5cGVvZiBhZGRfdG9bYWRkX3RvLmxlbmd0aC0xXSA9PSBcInN0cmluZ1wiICkge1xuICAgICAgICAgICAgYWRkX3RvWyBhZGRfdG8ubGVuZ3RoLTEgXSArPSB3aGF0O1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGFkZF90by5wdXNoKCB3aGF0ICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIGNvbnRhaW5lZCBtZWFucyBoYXZlIGFuIGluZGVudCBncmVhdGVyIHRoYW4gdGhlIGN1cnJlbnQgb25lLiBPblxuICAgICAgLy8gKmV2ZXJ5KiBsaW5lIGluIHRoZSBibG9ja1xuICAgICAgZnVuY3Rpb24gZ2V0X2NvbnRhaW5lZF9ibG9ja3MoIGRlcHRoLCBibG9ja3MgKSB7XG5cbiAgICAgICAgdmFyIHJlID0gbmV3IFJlZ0V4cCggXCJeKFwiICsgaW5kZW50X3JlICsgXCJ7XCIgKyBkZXB0aCArIFwifS4qP1xcXFxuPykqJFwiICksXG4gICAgICAgICAgICByZXBsYWNlID0gbmV3IFJlZ0V4cChcIl5cIiArIGluZGVudF9yZSArIFwie1wiICsgZGVwdGggKyBcIn1cIiwgXCJnbVwiKSxcbiAgICAgICAgICAgIHJldCA9IFtdO1xuXG4gICAgICAgIHdoaWxlICggYmxvY2tzLmxlbmd0aCA+IDAgKSB7XG4gICAgICAgICAgaWYgKCByZS5leGVjKCBibG9ja3NbMF0gKSApIHtcbiAgICAgICAgICAgIHZhciBiID0gYmxvY2tzLnNoaWZ0KCksXG4gICAgICAgICAgICAgICAgLy8gTm93IHJlbW92ZSB0aGF0IGluZGVudFxuICAgICAgICAgICAgICAgIHggPSBiLnJlcGxhY2UoIHJlcGxhY2UsIFwiXCIpO1xuXG4gICAgICAgICAgICByZXQucHVzaCggbWtfYmxvY2soIHgsIGIudHJhaWxpbmcsIGIubGluZU51bWJlciApICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgICB9XG5cbiAgICAgIC8vIHBhc3NlZCB0byBzdGFjay5mb3JFYWNoIHRvIHR1cm4gbGlzdCBpdGVtcyB1cCB0aGUgc3RhY2sgaW50byBwYXJhc1xuICAgICAgZnVuY3Rpb24gcGFyYWdyYXBoaWZ5KHMsIGksIHN0YWNrKSB7XG4gICAgICAgIHZhciBsaXN0ID0gcy5saXN0O1xuICAgICAgICB2YXIgbGFzdF9saSA9IGxpc3RbbGlzdC5sZW5ndGgtMV07XG5cbiAgICAgICAgaWYgKCBsYXN0X2xpWzFdIGluc3RhbmNlb2YgQXJyYXkgJiYgbGFzdF9saVsxXVswXSA9PSBcInBhcmFcIiApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCBpICsgMSA9PSBzdGFjay5sZW5ndGggKSB7XG4gICAgICAgICAgLy8gTGFzdCBzdGFjayBmcmFtZVxuICAgICAgICAgIC8vIEtlZXAgdGhlIHNhbWUgYXJyYXksIGJ1dCByZXBsYWNlIHRoZSBjb250ZW50c1xuICAgICAgICAgIGxhc3RfbGkucHVzaCggW1wicGFyYVwiXS5jb25jYXQoIGxhc3RfbGkuc3BsaWNlKDEsIGxhc3RfbGkubGVuZ3RoIC0gMSkgKSApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHZhciBzdWJsaXN0ID0gbGFzdF9saS5wb3AoKTtcbiAgICAgICAgICBsYXN0X2xpLnB1c2goIFtcInBhcmFcIl0uY29uY2F0KCBsYXN0X2xpLnNwbGljZSgxLCBsYXN0X2xpLmxlbmd0aCAtIDEpICksIHN1Ymxpc3QgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBUaGUgbWF0Y2hlciBmdW5jdGlvblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCBibG9jaywgbmV4dCApIHtcbiAgICAgICAgdmFyIG0gPSBibG9jay5tYXRjaCggaXNfbGlzdF9yZSApO1xuICAgICAgICBpZiAoICFtICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgICBmdW5jdGlvbiBtYWtlX2xpc3QoIG0gKSB7XG4gICAgICAgICAgdmFyIGxpc3QgPSBidWxsZXRfbGlzdC5leGVjKCBtWzJdIClcbiAgICAgICAgICAgICAgICAgICA/IFtcImJ1bGxldGxpc3RcIl1cbiAgICAgICAgICAgICAgICAgICA6IFtcIm51bWJlcmxpc3RcIl07XG5cbiAgICAgICAgICBzdGFjay5wdXNoKCB7IGxpc3Q6IGxpc3QsIGluZGVudDogbVsxXSB9ICk7XG4gICAgICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgICAgIH1cblxuXG4gICAgICAgIHZhciBzdGFjayA9IFtdLCAvLyBTdGFjayBvZiBsaXN0cyBmb3IgbmVzdGluZy5cbiAgICAgICAgICAgIGxpc3QgPSBtYWtlX2xpc3QoIG0gKSxcbiAgICAgICAgICAgIGxhc3RfbGksXG4gICAgICAgICAgICBsb29zZSA9IGZhbHNlLFxuICAgICAgICAgICAgcmV0ID0gWyBzdGFja1swXS5saXN0IF0sXG4gICAgICAgICAgICBpO1xuXG4gICAgICAgIC8vIExvb3AgdG8gc2VhcmNoIG92ZXIgYmxvY2sgbG9va2luZyBmb3IgaW5uZXIgYmxvY2sgZWxlbWVudHMgYW5kIGxvb3NlIGxpc3RzXG4gICAgICAgIGxvb3NlX3NlYXJjaDpcbiAgICAgICAgd2hpbGUgKCB0cnVlICkge1xuICAgICAgICAgIC8vIFNwbGl0IGludG8gbGluZXMgcHJlc2VydmluZyBuZXcgbGluZXMgYXQgZW5kIG9mIGxpbmVcbiAgICAgICAgICB2YXIgbGluZXMgPSBibG9jay5zcGxpdCggLyg/PVxcbikvICk7XG5cbiAgICAgICAgICAvLyBXZSBoYXZlIHRvIGdyYWIgYWxsIGxpbmVzIGZvciBhIGxpIGFuZCBjYWxsIHByb2Nlc3NJbmxpbmUgb24gdGhlbVxuICAgICAgICAgIC8vIG9uY2UgYXMgdGhlcmUgYXJlIHNvbWUgaW5saW5lIHRoaW5ncyB0aGF0IGNhbiBzcGFuIGxpbmVzLlxuICAgICAgICAgIHZhciBsaV9hY2N1bXVsYXRlID0gXCJcIjtcblxuICAgICAgICAgIC8vIExvb3Agb3ZlciB0aGUgbGluZXMgaW4gdGhpcyBibG9jayBsb29raW5nIGZvciB0aWdodCBsaXN0cy5cbiAgICAgICAgICB0aWdodF9zZWFyY2g6XG4gICAgICAgICAgZm9yICggdmFyIGxpbmVfbm8gPSAwOyBsaW5lX25vIDwgbGluZXMubGVuZ3RoOyBsaW5lX25vKysgKSB7XG4gICAgICAgICAgICB2YXIgbmwgPSBcIlwiLFxuICAgICAgICAgICAgICAgIGwgPSBsaW5lc1tsaW5lX25vXS5yZXBsYWNlKC9eXFxuLywgZnVuY3Rpb24obikgeyBubCA9IG47IHJldHVybiBcIlwiOyB9KTtcblxuICAgICAgICAgICAgLy8gVE9ETzogcmVhbGx5IHNob3VsZCBjYWNoZSB0aGlzXG4gICAgICAgICAgICB2YXIgbGluZV9yZSA9IHJlZ2V4X2Zvcl9kZXB0aCggc3RhY2subGVuZ3RoICk7XG5cbiAgICAgICAgICAgIG0gPSBsLm1hdGNoKCBsaW5lX3JlICk7XG4gICAgICAgICAgICAvL3ByaW50KCBcImxpbmU6XCIsIHVuZXZhbChsKSwgXCJcXG5saW5lIG1hdGNoOlwiLCB1bmV2YWwobSkgKTtcblxuICAgICAgICAgICAgLy8gV2UgaGF2ZSBhIGxpc3QgaXRlbVxuICAgICAgICAgICAgaWYgKCBtWzFdICE9PSB1bmRlZmluZWQgKSB7XG4gICAgICAgICAgICAgIC8vIFByb2Nlc3MgdGhlIHByZXZpb3VzIGxpc3QgaXRlbSwgaWYgYW55XG4gICAgICAgICAgICAgIGlmICggbGlfYWNjdW11bGF0ZS5sZW5ndGggKSB7XG4gICAgICAgICAgICAgICAgYWRkKCBsYXN0X2xpLCBsb29zZSwgdGhpcy5wcm9jZXNzSW5saW5lKCBsaV9hY2N1bXVsYXRlICksIG5sICk7XG4gICAgICAgICAgICAgICAgLy8gTG9vc2UgbW9kZSB3aWxsIGhhdmUgYmVlbiBkZWFsdCB3aXRoLiBSZXNldCBpdFxuICAgICAgICAgICAgICAgIGxvb3NlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgbGlfYWNjdW11bGF0ZSA9IFwiXCI7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBtWzFdID0gZXhwYW5kX3RhYiggbVsxXSApO1xuICAgICAgICAgICAgICB2YXIgd2FudGVkX2RlcHRoID0gTWF0aC5mbG9vcihtWzFdLmxlbmd0aC80KSsxO1xuICAgICAgICAgICAgICAvL3ByaW50KCBcIndhbnQ6XCIsIHdhbnRlZF9kZXB0aCwgXCJzdGFjazpcIiwgc3RhY2subGVuZ3RoKTtcbiAgICAgICAgICAgICAgaWYgKCB3YW50ZWRfZGVwdGggPiBzdGFjay5sZW5ndGggKSB7XG4gICAgICAgICAgICAgICAgLy8gRGVlcCBlbm91Z2ggZm9yIGEgbmVzdGVkIGxpc3Qgb3V0cmlnaHRcbiAgICAgICAgICAgICAgICAvL3ByaW50ICggXCJuZXcgbmVzdGVkIGxpc3RcIiApO1xuICAgICAgICAgICAgICAgIGxpc3QgPSBtYWtlX2xpc3QoIG0gKTtcbiAgICAgICAgICAgICAgICBsYXN0X2xpLnB1c2goIGxpc3QgKTtcbiAgICAgICAgICAgICAgICBsYXN0X2xpID0gbGlzdFsxXSA9IFsgXCJsaXN0aXRlbVwiIF07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gV2UgYXJlbid0IGRlZXAgZW5vdWdoIHRvIGJlIHN0cmljdGx5IGEgbmV3IGxldmVsLiBUaGlzIGlzXG4gICAgICAgICAgICAgICAgLy8gd2hlcmUgTWQucGwgZ29lcyBudXRzLiBJZiB0aGUgaW5kZW50IG1hdGNoZXMgYSBsZXZlbCBpbiB0aGVcbiAgICAgICAgICAgICAgICAvLyBzdGFjaywgcHV0IGl0IHRoZXJlLCBlbHNlIHB1dCBpdCBvbmUgZGVlcGVyIHRoZW4gdGhlXG4gICAgICAgICAgICAgICAgLy8gd2FudGVkX2RlcHRoIGRlc2VydmVzLlxuICAgICAgICAgICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZvciAoIGkgPSAwOyBpIDwgc3RhY2subGVuZ3RoOyBpKysgKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoIHN0YWNrWyBpIF0uaW5kZW50ICE9IG1bMV0gKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgIGxpc3QgPSBzdGFja1sgaSBdLmxpc3Q7XG4gICAgICAgICAgICAgICAgICBzdGFjay5zcGxpY2UoIGkrMSwgc3RhY2subGVuZ3RoIC0gKGkrMSkgKTtcbiAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghZm91bmQpIHtcbiAgICAgICAgICAgICAgICAgIC8vcHJpbnQoXCJub3QgZm91bmQuIGw6XCIsIHVuZXZhbChsKSk7XG4gICAgICAgICAgICAgICAgICB3YW50ZWRfZGVwdGgrKztcbiAgICAgICAgICAgICAgICAgIGlmICggd2FudGVkX2RlcHRoIDw9IHN0YWNrLmxlbmd0aCApIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhY2suc3BsaWNlKHdhbnRlZF9kZXB0aCwgc3RhY2subGVuZ3RoIC0gd2FudGVkX2RlcHRoKTtcbiAgICAgICAgICAgICAgICAgICAgLy9wcmludChcIkRlc2lyZWQgZGVwdGggbm93XCIsIHdhbnRlZF9kZXB0aCwgXCJzdGFjazpcIiwgc3RhY2subGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgbGlzdCA9IHN0YWNrW3dhbnRlZF9kZXB0aC0xXS5saXN0O1xuICAgICAgICAgICAgICAgICAgICAvL3ByaW50KFwibGlzdDpcIiwgdW5ldmFsKGxpc3QpICk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy9wcmludCAoXCJtYWRlIG5ldyBzdGFjayBmb3IgbWVzc3kgaW5kZW50XCIpO1xuICAgICAgICAgICAgICAgICAgICBsaXN0ID0gbWFrZV9saXN0KG0pO1xuICAgICAgICAgICAgICAgICAgICBsYXN0X2xpLnB1c2gobGlzdCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy9wcmludCggdW5ldmFsKGxpc3QpLCBcImxhc3RcIiwgbGlzdCA9PT0gc3RhY2tbc3RhY2subGVuZ3RoLTFdLmxpc3QgKTtcbiAgICAgICAgICAgICAgICBsYXN0X2xpID0gWyBcImxpc3RpdGVtXCIgXTtcbiAgICAgICAgICAgICAgICBsaXN0LnB1c2gobGFzdF9saSk7XG4gICAgICAgICAgICAgIH0gLy8gZW5kIGRlcHRoIG9mIHNoZW5lZ2FpbnNcbiAgICAgICAgICAgICAgbmwgPSBcIlwiO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBZGQgY29udGVudFxuICAgICAgICAgICAgaWYgKCBsLmxlbmd0aCA+IG1bMF0ubGVuZ3RoICkge1xuICAgICAgICAgICAgICBsaV9hY2N1bXVsYXRlICs9IG5sICsgbC5zdWJzdHIoIG1bMF0ubGVuZ3RoICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyB0aWdodF9zZWFyY2hcblxuICAgICAgICAgIGlmICggbGlfYWNjdW11bGF0ZS5sZW5ndGggKSB7XG4gICAgICAgICAgICBhZGQoIGxhc3RfbGksIGxvb3NlLCB0aGlzLnByb2Nlc3NJbmxpbmUoIGxpX2FjY3VtdWxhdGUgKSwgbmwgKTtcbiAgICAgICAgICAgIC8vIExvb3NlIG1vZGUgd2lsbCBoYXZlIGJlZW4gZGVhbHQgd2l0aC4gUmVzZXQgaXRcbiAgICAgICAgICAgIGxvb3NlID0gZmFsc2U7XG4gICAgICAgICAgICBsaV9hY2N1bXVsYXRlID0gXCJcIjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBMb29rIGF0IHRoZSBuZXh0IGJsb2NrIC0gd2UgbWlnaHQgaGF2ZSBhIGxvb3NlIGxpc3QuIE9yIGFuIGV4dHJhXG4gICAgICAgICAgLy8gcGFyYWdyYXBoIGZvciB0aGUgY3VycmVudCBsaVxuICAgICAgICAgIHZhciBjb250YWluZWQgPSBnZXRfY29udGFpbmVkX2Jsb2Nrcyggc3RhY2subGVuZ3RoLCBuZXh0ICk7XG5cbiAgICAgICAgICAvLyBEZWFsIHdpdGggY29kZSBibG9ja3Mgb3IgcHJvcGVybHkgbmVzdGVkIGxpc3RzXG4gICAgICAgICAgaWYgKCBjb250YWluZWQubGVuZ3RoID4gMCApIHtcbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBhbGwgbGlzdGl0ZW1zIHVwIHRoZSBzdGFjayBhcmUgcGFyYWdyYXBoc1xuICAgICAgICAgICAgZm9yRWFjaCggc3RhY2ssIHBhcmFncmFwaGlmeSwgdGhpcyk7XG5cbiAgICAgICAgICAgIGxhc3RfbGkucHVzaC5hcHBseSggbGFzdF9saSwgdGhpcy50b1RyZWUoIGNvbnRhaW5lZCwgW10gKSApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBuZXh0X2Jsb2NrID0gbmV4dFswXSAmJiBuZXh0WzBdLnZhbHVlT2YoKSB8fCBcIlwiO1xuXG4gICAgICAgICAgaWYgKCBuZXh0X2Jsb2NrLm1hdGNoKGlzX2xpc3RfcmUpIHx8IG5leHRfYmxvY2subWF0Y2goIC9eIC8gKSApIHtcbiAgICAgICAgICAgIGJsb2NrID0gbmV4dC5zaGlmdCgpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgYW4gSFIgZm9sbG93aW5nIGEgbGlzdDogZmVhdHVyZXMvbGlzdHMvaHJfYWJ1dHRpbmdcbiAgICAgICAgICAgIHZhciBociA9IHRoaXMuZGlhbGVjdC5ibG9jay5ob3JpelJ1bGUoIGJsb2NrLCBuZXh0ICk7XG5cbiAgICAgICAgICAgIGlmICggaHIgKSB7XG4gICAgICAgICAgICAgIHJldC5wdXNoLmFwcGx5KHJldCwgaHIpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIGFsbCBsaXN0aXRlbXMgdXAgdGhlIHN0YWNrIGFyZSBwYXJhZ3JhcGhzXG4gICAgICAgICAgICBmb3JFYWNoKCBzdGFjaywgcGFyYWdyYXBoaWZ5LCB0aGlzKTtcblxuICAgICAgICAgICAgbG9vc2UgPSB0cnVlO1xuICAgICAgICAgICAgY29udGludWUgbG9vc2Vfc2VhcmNoO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfSAvLyBsb29zZV9zZWFyY2hcblxuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfTtcbiAgICB9KSgpLFxuXG4gICAgYmxvY2txdW90ZTogZnVuY3Rpb24gYmxvY2txdW90ZSggYmxvY2ssIG5leHQgKSB7XG4gICAgICBpZiAoICFibG9jay5tYXRjaCggL14+L20gKSApXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIHZhciBqc29ubWwgPSBbXTtcblxuICAgICAgLy8gc2VwYXJhdGUgb3V0IHRoZSBsZWFkaW5nIGFidXR0aW5nIGJsb2NrLCBpZiBhbnkuIEkuZS4gaW4gdGhpcyBjYXNlOlxuICAgICAgLy9cbiAgICAgIC8vICBhXG4gICAgICAvLyAgPiBiXG4gICAgICAvL1xuICAgICAgaWYgKCBibG9ja1sgMCBdICE9IFwiPlwiICkge1xuICAgICAgICB2YXIgbGluZXMgPSBibG9jay5zcGxpdCggL1xcbi8gKSxcbiAgICAgICAgICAgIHByZXYgPSBbXSxcbiAgICAgICAgICAgIGxpbmVfbm8gPSBibG9jay5saW5lTnVtYmVyO1xuXG4gICAgICAgIC8vIGtlZXAgc2hpZnRpbmcgbGluZXMgdW50aWwgeW91IGZpbmQgYSBjcm90Y2hldFxuICAgICAgICB3aGlsZSAoIGxpbmVzLmxlbmd0aCAmJiBsaW5lc1sgMCBdWyAwIF0gIT0gXCI+XCIgKSB7XG4gICAgICAgICAgICBwcmV2LnB1c2goIGxpbmVzLnNoaWZ0KCkgKTtcbiAgICAgICAgICAgIGxpbmVfbm8rKztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhYnV0dGluZyA9IG1rX2Jsb2NrKCBwcmV2LmpvaW4oIFwiXFxuXCIgKSwgXCJcXG5cIiwgYmxvY2subGluZU51bWJlciApO1xuICAgICAgICBqc29ubWwucHVzaC5hcHBseSgganNvbm1sLCB0aGlzLnByb2Nlc3NCbG9jayggYWJ1dHRpbmcsIFtdICkgKTtcbiAgICAgICAgLy8gcmVhc3NlbWJsZSBuZXcgYmxvY2sgb2YganVzdCBibG9jayBxdW90ZXMhXG4gICAgICAgIGJsb2NrID0gbWtfYmxvY2soIGxpbmVzLmpvaW4oIFwiXFxuXCIgKSwgYmxvY2sudHJhaWxpbmcsIGxpbmVfbm8gKTtcbiAgICAgIH1cblxuXG4gICAgICAvLyBpZiB0aGUgbmV4dCBibG9jayBpcyBhbHNvIGEgYmxvY2txdW90ZSBtZXJnZSBpdCBpblxuICAgICAgd2hpbGUgKCBuZXh0Lmxlbmd0aCAmJiBuZXh0WyAwIF1bIDAgXSA9PSBcIj5cIiApIHtcbiAgICAgICAgdmFyIGIgPSBuZXh0LnNoaWZ0KCk7XG4gICAgICAgIGJsb2NrID0gbWtfYmxvY2soIGJsb2NrICsgYmxvY2sudHJhaWxpbmcgKyBiLCBiLnRyYWlsaW5nLCBibG9jay5saW5lTnVtYmVyICk7XG4gICAgICB9XG5cbiAgICAgIC8vIFN0cmlwIG9mZiB0aGUgbGVhZGluZyBcIj4gXCIgYW5kIHJlLXByb2Nlc3MgYXMgYSBibG9jay5cbiAgICAgIHZhciBpbnB1dCA9IGJsb2NrLnJlcGxhY2UoIC9ePiA/L2dtLCBcIlwiICksXG4gICAgICAgICAgb2xkX3RyZWUgPSB0aGlzLnRyZWUsXG4gICAgICAgICAgcHJvY2Vzc2VkQmxvY2sgPSB0aGlzLnRvVHJlZSggaW5wdXQsIFsgXCJibG9ja3F1b3RlXCIgXSApLFxuICAgICAgICAgIGF0dHIgPSBleHRyYWN0X2F0dHIoIHByb2Nlc3NlZEJsb2NrICk7XG5cbiAgICAgIC8vIElmIGFueSBsaW5rIHJlZmVyZW5jZXMgd2VyZSBmb3VuZCBnZXQgcmlkIG9mIHRoZW1cbiAgICAgIGlmICggYXR0ciAmJiBhdHRyLnJlZmVyZW5jZXMgKSB7XG4gICAgICAgIGRlbGV0ZSBhdHRyLnJlZmVyZW5jZXM7XG4gICAgICAgIC8vIEFuZCB0aGVuIHJlbW92ZSB0aGUgYXR0cmlidXRlIG9iamVjdCBpZiBpdCdzIGVtcHR5XG4gICAgICAgIGlmICggaXNFbXB0eSggYXR0ciApICkge1xuICAgICAgICAgIHByb2Nlc3NlZEJsb2NrLnNwbGljZSggMSwgMSApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGpzb25tbC5wdXNoKCBwcm9jZXNzZWRCbG9jayApO1xuICAgICAgcmV0dXJuIGpzb25tbDtcbiAgICB9LFxuXG4gICAgcmVmZXJlbmNlRGVmbjogZnVuY3Rpb24gcmVmZXJlbmNlRGVmbiggYmxvY2ssIG5leHQpIHtcbiAgICAgIHZhciByZSA9IC9eXFxzKlxcWyguKj8pXFxdOlxccyooXFxTKykoPzpcXHMrKD86KFsnXCJdKSguKj8pXFwzfFxcKCguKj8pXFwpKSk/XFxuPy87XG4gICAgICAvLyBpbnRlcmVzdGluZyBtYXRjaGVzIGFyZSBbICwgcmVmX2lkLCB1cmwsICwgdGl0bGUsIHRpdGxlIF1cblxuICAgICAgaWYgKCAhYmxvY2subWF0Y2gocmUpIClcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgLy8gbWFrZSBhbiBhdHRyaWJ1dGUgbm9kZSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICBpZiAoICFleHRyYWN0X2F0dHIoIHRoaXMudHJlZSApICkge1xuICAgICAgICB0aGlzLnRyZWUuc3BsaWNlKCAxLCAwLCB7fSApO1xuICAgICAgfVxuXG4gICAgICB2YXIgYXR0cnMgPSBleHRyYWN0X2F0dHIoIHRoaXMudHJlZSApO1xuXG4gICAgICAvLyBtYWtlIGEgcmVmZXJlbmNlcyBoYXNoIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgIGlmICggYXR0cnMucmVmZXJlbmNlcyA9PT0gdW5kZWZpbmVkICkge1xuICAgICAgICBhdHRycy5yZWZlcmVuY2VzID0ge307XG4gICAgICB9XG5cbiAgICAgIHZhciBiID0gdGhpcy5sb29wX3JlX292ZXJfYmxvY2socmUsIGJsb2NrLCBmdW5jdGlvbiggbSApIHtcblxuICAgICAgICBpZiAoIG1bMl0gJiYgbVsyXVswXSA9PSBcIjxcIiAmJiBtWzJdW21bMl0ubGVuZ3RoLTFdID09IFwiPlwiIClcbiAgICAgICAgICBtWzJdID0gbVsyXS5zdWJzdHJpbmcoIDEsIG1bMl0ubGVuZ3RoIC0gMSApO1xuXG4gICAgICAgIHZhciByZWYgPSBhdHRycy5yZWZlcmVuY2VzWyBtWzFdLnRvTG93ZXJDYXNlKCkgXSA9IHtcbiAgICAgICAgICBocmVmOiBtWzJdXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKCBtWzRdICE9PSB1bmRlZmluZWQgKVxuICAgICAgICAgIHJlZi50aXRsZSA9IG1bNF07XG4gICAgICAgIGVsc2UgaWYgKCBtWzVdICE9PSB1bmRlZmluZWQgKVxuICAgICAgICAgIHJlZi50aXRsZSA9IG1bNV07XG5cbiAgICAgIH0gKTtcblxuICAgICAgaWYgKCBiLmxlbmd0aCApXG4gICAgICAgIG5leHQudW5zaGlmdCggbWtfYmxvY2soIGIsIGJsb2NrLnRyYWlsaW5nICkgKTtcblxuICAgICAgcmV0dXJuIFtdO1xuICAgIH0sXG5cbiAgICBwYXJhOiBmdW5jdGlvbiBwYXJhKCBibG9jaywgbmV4dCApIHtcbiAgICAgIC8vIGV2ZXJ5dGhpbmcncyBhIHBhcmEhXG4gICAgICByZXR1cm4gWyBbXCJwYXJhXCJdLmNvbmNhdCggdGhpcy5wcm9jZXNzSW5saW5lKCBibG9jayApICkgXTtcbiAgICB9XG4gIH1cbn07XG5cbk1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5pbmxpbmUgPSB7XG5cbiAgICBfX29uZUVsZW1lbnRfXzogZnVuY3Rpb24gb25lRWxlbWVudCggdGV4dCwgcGF0dGVybnNfb3JfcmUsIHByZXZpb3VzX25vZGVzICkge1xuICAgICAgdmFyIG0sXG4gICAgICAgICAgcmVzLFxuICAgICAgICAgIGxhc3RJbmRleCA9IDA7XG5cbiAgICAgIHBhdHRlcm5zX29yX3JlID0gcGF0dGVybnNfb3JfcmUgfHwgdGhpcy5kaWFsZWN0LmlubGluZS5fX3BhdHRlcm5zX187XG4gICAgICB2YXIgcmUgPSBuZXcgUmVnRXhwKCBcIihbXFxcXHNcXFxcU10qPykoXCIgKyAocGF0dGVybnNfb3JfcmUuc291cmNlIHx8IHBhdHRlcm5zX29yX3JlKSArIFwiKVwiICk7XG5cbiAgICAgIG0gPSByZS5leGVjKCB0ZXh0ICk7XG4gICAgICBpZiAoIW0pIHtcbiAgICAgICAgLy8gSnVzdCBib3JpbmcgdGV4dFxuICAgICAgICByZXR1cm4gWyB0ZXh0Lmxlbmd0aCwgdGV4dCBdO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAoIG1bMV0gKSB7XG4gICAgICAgIC8vIFNvbWUgdW4taW50ZXJlc3RpbmcgdGV4dCBtYXRjaGVkLiBSZXR1cm4gdGhhdCBmaXJzdFxuICAgICAgICByZXR1cm4gWyBtWzFdLmxlbmd0aCwgbVsxXSBdO1xuICAgICAgfVxuXG4gICAgICB2YXIgcmVzO1xuICAgICAgaWYgKCBtWzJdIGluIHRoaXMuZGlhbGVjdC5pbmxpbmUgKSB7XG4gICAgICAgIHJlcyA9IHRoaXMuZGlhbGVjdC5pbmxpbmVbIG1bMl0gXS5jYWxsKFxuICAgICAgICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgICAgICAgIHRleHQuc3Vic3RyKCBtLmluZGV4ICksIG0sIHByZXZpb3VzX25vZGVzIHx8IFtdICk7XG4gICAgICB9XG4gICAgICAvLyBEZWZhdWx0IGZvciBub3cgdG8gbWFrZSBkZXYgZWFzaWVyLiBqdXN0IHNsdXJwIHNwZWNpYWwgYW5kIG91dHB1dCBpdC5cbiAgICAgIHJlcyA9IHJlcyB8fCBbIG1bMl0ubGVuZ3RoLCBtWzJdIF07XG4gICAgICByZXR1cm4gcmVzO1xuICAgIH0sXG5cbiAgICBfX2NhbGxfXzogZnVuY3Rpb24gaW5saW5lKCB0ZXh0LCBwYXR0ZXJucyApIHtcblxuICAgICAgdmFyIG91dCA9IFtdLFxuICAgICAgICAgIHJlcztcblxuICAgICAgZnVuY3Rpb24gYWRkKHgpIHtcbiAgICAgICAgLy9EOnNlbGYuZGVidWcoXCIgIGFkZGluZyBvdXRwdXRcIiwgdW5ldmFsKHgpKTtcbiAgICAgICAgaWYgKCB0eXBlb2YgeCA9PSBcInN0cmluZ1wiICYmIHR5cGVvZiBvdXRbb3V0Lmxlbmd0aC0xXSA9PSBcInN0cmluZ1wiIClcbiAgICAgICAgICBvdXRbIG91dC5sZW5ndGgtMSBdICs9IHg7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBvdXQucHVzaCh4KTtcbiAgICAgIH1cblxuICAgICAgd2hpbGUgKCB0ZXh0Lmxlbmd0aCA+IDAgKSB7XG4gICAgICAgIHJlcyA9IHRoaXMuZGlhbGVjdC5pbmxpbmUuX19vbmVFbGVtZW50X18uY2FsbCh0aGlzLCB0ZXh0LCBwYXR0ZXJucywgb3V0ICk7XG4gICAgICAgIHRleHQgPSB0ZXh0LnN1YnN0ciggcmVzLnNoaWZ0KCkgKTtcbiAgICAgICAgZm9yRWFjaChyZXMsIGFkZCApXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvdXQ7XG4gICAgfSxcblxuICAgIC8vIFRoZXNlIGNoYXJhY3RlcnMgYXJlIGludGVyc3RpbmcgZWxzZXdoZXJlLCBzbyBoYXZlIHJ1bGVzIGZvciB0aGVtIHNvIHRoYXRcbiAgICAvLyBjaHVua3Mgb2YgcGxhaW4gdGV4dCBibG9ja3MgZG9uJ3QgaW5jbHVkZSB0aGVtXG4gICAgXCJdXCI6IGZ1bmN0aW9uICgpIHt9LFxuICAgIFwifVwiOiBmdW5jdGlvbiAoKSB7fSxcblxuICAgIF9fZXNjYXBlX18gOiAvXlxcXFxbXFxcXGBcXCpfe31cXFtcXF0oKSNcXCsuIVxcLV0vLFxuXG4gICAgXCJcXFxcXCI6IGZ1bmN0aW9uIGVzY2FwZWQoIHRleHQgKSB7XG4gICAgICAvLyBbIGxlbmd0aCBvZiBpbnB1dCBwcm9jZXNzZWQsIG5vZGUvY2hpbGRyZW4gdG8gYWRkLi4uIF1cbiAgICAgIC8vIE9ubHkgZXNhY2FwZTogXFwgYCAqIF8geyB9IFsgXSAoICkgIyAqICsgLSAuICFcbiAgICAgIGlmICggdGhpcy5kaWFsZWN0LmlubGluZS5fX2VzY2FwZV9fLmV4ZWMoIHRleHQgKSApXG4gICAgICAgIHJldHVybiBbIDIsIHRleHQuY2hhckF0KCAxICkgXTtcbiAgICAgIGVsc2VcbiAgICAgICAgLy8gTm90IGFuIGVzYWNwZVxuICAgICAgICByZXR1cm4gWyAxLCBcIlxcXFxcIiBdO1xuICAgIH0sXG5cbiAgICBcIiFbXCI6IGZ1bmN0aW9uIGltYWdlKCB0ZXh0ICkge1xuXG4gICAgICAvLyBVbmxpa2UgaW1hZ2VzLCBhbHQgdGV4dCBpcyBwbGFpbiB0ZXh0IG9ubHkuIG5vIG90aGVyIGVsZW1lbnRzIGFyZVxuICAgICAgLy8gYWxsb3dlZCBpbiB0aGVyZVxuXG4gICAgICAvLyAhW0FsdCB0ZXh0XSgvcGF0aC90by9pbWcuanBnIFwiT3B0aW9uYWwgdGl0bGVcIilcbiAgICAgIC8vICAgICAgMSAgICAgICAgICAyICAgICAgICAgICAgMyAgICAgICA0ICAgICAgICAgPC0tLSBjYXB0dXJlc1xuICAgICAgdmFyIG0gPSB0ZXh0Lm1hdGNoKCAvXiFcXFsoLio/KVxcXVsgXFx0XSpcXChbIFxcdF0qKFteXCIpXSo/KSg/OlsgXFx0XSsoW1wiJ10pKC4qPylcXDMpP1sgXFx0XSpcXCkvICk7XG5cbiAgICAgIGlmICggbSApIHtcbiAgICAgICAgaWYgKCBtWzJdICYmIG1bMl1bMF0gPT0gXCI8XCIgJiYgbVsyXVttWzJdLmxlbmd0aC0xXSA9PSBcIj5cIiApXG4gICAgICAgICAgbVsyXSA9IG1bMl0uc3Vic3RyaW5nKCAxLCBtWzJdLmxlbmd0aCAtIDEgKTtcblxuICAgICAgICBtWzJdID0gdGhpcy5kaWFsZWN0LmlubGluZS5fX2NhbGxfXy5jYWxsKCB0aGlzLCBtWzJdLCAvXFxcXC8gKVswXTtcblxuICAgICAgICB2YXIgYXR0cnMgPSB7IGFsdDogbVsxXSwgaHJlZjogbVsyXSB8fCBcIlwiIH07XG4gICAgICAgIGlmICggbVs0XSAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIGF0dHJzLnRpdGxlID0gbVs0XTtcblxuICAgICAgICByZXR1cm4gWyBtWzBdLmxlbmd0aCwgWyBcImltZ1wiLCBhdHRycyBdIF07XG4gICAgICB9XG5cbiAgICAgIC8vICFbQWx0IHRleHRdW2lkXVxuICAgICAgbSA9IHRleHQubWF0Y2goIC9eIVxcWyguKj8pXFxdWyBcXHRdKlxcWyguKj8pXFxdLyApO1xuXG4gICAgICBpZiAoIG0gKSB7XG4gICAgICAgIC8vIFdlIGNhbid0IGNoZWNrIGlmIHRoZSByZWZlcmVuY2UgaXMga25vd24gaGVyZSBhcyBpdCBsaWtlbHkgd29udCBiZVxuICAgICAgICAvLyBmb3VuZCB0aWxsIGFmdGVyLiBDaGVjayBpdCBpbiBtZCB0cmVlLT5obXRsIHRyZWUgY29udmVyc2lvblxuICAgICAgICByZXR1cm4gWyBtWzBdLmxlbmd0aCwgWyBcImltZ19yZWZcIiwgeyBhbHQ6IG1bMV0sIHJlZjogbVsyXS50b0xvd2VyQ2FzZSgpLCBvcmlnaW5hbDogbVswXSB9IF0gXTtcbiAgICAgIH1cblxuICAgICAgLy8gSnVzdCBjb25zdW1lIHRoZSAnIVsnXG4gICAgICByZXR1cm4gWyAyLCBcIiFbXCIgXTtcbiAgICB9LFxuXG4gICAgXCJbXCI6IGZ1bmN0aW9uIGxpbmsoIHRleHQgKSB7XG5cbiAgICAgIHZhciBvcmlnID0gU3RyaW5nKHRleHQpO1xuICAgICAgLy8gSW5saW5lIGNvbnRlbnQgaXMgcG9zc2libGUgaW5zaWRlIGBsaW5rIHRleHRgXG4gICAgICB2YXIgcmVzID0gTWFya2Rvd24uRGlhbGVjdEhlbHBlcnMuaW5saW5lX3VudGlsX2NoYXIuY2FsbCggdGhpcywgdGV4dC5zdWJzdHIoMSksIFwiXVwiICk7XG5cbiAgICAgIC8vIE5vIGNsb3NpbmcgJ10nIGZvdW5kLiBKdXN0IGNvbnN1bWUgdGhlIFtcbiAgICAgIGlmICggIXJlcyApIHJldHVybiBbIDEsIFwiW1wiIF07XG5cbiAgICAgIHZhciBjb25zdW1lZCA9IDEgKyByZXNbIDAgXSxcbiAgICAgICAgICBjaGlsZHJlbiA9IHJlc1sgMSBdLFxuICAgICAgICAgIGxpbmssXG4gICAgICAgICAgYXR0cnM7XG5cbiAgICAgIC8vIEF0IHRoaXMgcG9pbnQgdGhlIGZpcnN0IFsuLi5dIGhhcyBiZWVuIHBhcnNlZC4gU2VlIHdoYXQgZm9sbG93cyB0byBmaW5kXG4gICAgICAvLyBvdXQgd2hpY2gga2luZCBvZiBsaW5rIHdlIGFyZSAocmVmZXJlbmNlIG9yIGRpcmVjdCB1cmwpXG4gICAgICB0ZXh0ID0gdGV4dC5zdWJzdHIoIGNvbnN1bWVkICk7XG5cbiAgICAgIC8vIFtsaW5rIHRleHRdKC9wYXRoL3RvL2ltZy5qcGcgXCJPcHRpb25hbCB0aXRsZVwiKVxuICAgICAgLy8gICAgICAgICAgICAgICAgIDEgICAgICAgICAgICAyICAgICAgIDMgICAgICAgICA8LS0tIGNhcHR1cmVzXG4gICAgICAvLyBUaGlzIHdpbGwgY2FwdHVyZSB1cCB0byB0aGUgbGFzdCBwYXJlbiBpbiB0aGUgYmxvY2suIFdlIHRoZW4gcHVsbFxuICAgICAgLy8gYmFjayBiYXNlZCBvbiBpZiB0aGVyZSBhIG1hdGNoaW5nIG9uZXMgaW4gdGhlIHVybFxuICAgICAgLy8gICAgKFtoZXJlXSgvdXJsLyh0ZXN0KSlcbiAgICAgIC8vIFRoZSBwYXJlbnMgaGF2ZSB0byBiZSBiYWxhbmNlZFxuICAgICAgdmFyIG0gPSB0ZXh0Lm1hdGNoKCAvXlxccypcXChbIFxcdF0qKFteXCInXSopKD86WyBcXHRdKyhbXCInXSkoLio/KVxcMik/WyBcXHRdKlxcKS8gKTtcbiAgICAgIGlmICggbSApIHtcbiAgICAgICAgdmFyIHVybCA9IG1bMV07XG4gICAgICAgIGNvbnN1bWVkICs9IG1bMF0ubGVuZ3RoO1xuXG4gICAgICAgIGlmICggdXJsICYmIHVybFswXSA9PSBcIjxcIiAmJiB1cmxbdXJsLmxlbmd0aC0xXSA9PSBcIj5cIiApXG4gICAgICAgICAgdXJsID0gdXJsLnN1YnN0cmluZyggMSwgdXJsLmxlbmd0aCAtIDEgKTtcblxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBhIHRpdGxlIHdlIGRvbid0IGhhdmUgdG8gd29ycnkgYWJvdXQgcGFyZW5zIGluIHRoZSB1cmxcbiAgICAgICAgaWYgKCAhbVszXSApIHtcbiAgICAgICAgICB2YXIgb3Blbl9wYXJlbnMgPSAxOyAvLyBPbmUgb3BlbiB0aGF0IGlzbid0IGluIHRoZSBjYXB0dXJlXG4gICAgICAgICAgZm9yICggdmFyIGxlbiA9IDA7IGxlbiA8IHVybC5sZW5ndGg7IGxlbisrICkge1xuICAgICAgICAgICAgc3dpdGNoICggdXJsW2xlbl0gKSB7XG4gICAgICAgICAgICBjYXNlIFwiKFwiOlxuICAgICAgICAgICAgICBvcGVuX3BhcmVucysrO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCIpXCI6XG4gICAgICAgICAgICAgIGlmICggLS1vcGVuX3BhcmVucyA9PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3VtZWQgLT0gdXJsLmxlbmd0aCAtIGxlbjtcbiAgICAgICAgICAgICAgICB1cmwgPSB1cmwuc3Vic3RyaW5nKDAsIGxlbik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvY2VzcyBlc2NhcGVzIG9ubHlcbiAgICAgICAgdXJsID0gdGhpcy5kaWFsZWN0LmlubGluZS5fX2NhbGxfXy5jYWxsKCB0aGlzLCB1cmwsIC9cXFxcLyApWzBdO1xuXG4gICAgICAgIGF0dHJzID0geyBocmVmOiB1cmwgfHwgXCJcIiB9O1xuICAgICAgICBpZiAoIG1bM10gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICBhdHRycy50aXRsZSA9IG1bM107XG5cbiAgICAgICAgbGluayA9IFsgXCJsaW5rXCIsIGF0dHJzIF0uY29uY2F0KCBjaGlsZHJlbiApO1xuICAgICAgICByZXR1cm4gWyBjb25zdW1lZCwgbGluayBdO1xuICAgICAgfVxuXG4gICAgICAvLyBbQWx0IHRleHRdW2lkXVxuICAgICAgLy8gW0FsdCB0ZXh0XSBbaWRdXG4gICAgICBtID0gdGV4dC5tYXRjaCggL15cXHMqXFxbKC4qPylcXF0vICk7XG5cbiAgICAgIGlmICggbSApIHtcblxuICAgICAgICBjb25zdW1lZCArPSBtWyAwIF0ubGVuZ3RoO1xuXG4gICAgICAgIC8vIFtsaW5rc11bXSB1c2VzIGxpbmtzIGFzIGl0cyByZWZlcmVuY2VcbiAgICAgICAgYXR0cnMgPSB7IHJlZjogKCBtWyAxIF0gfHwgU3RyaW5nKGNoaWxkcmVuKSApLnRvTG93ZXJDYXNlKCksICBvcmlnaW5hbDogb3JpZy5zdWJzdHIoIDAsIGNvbnN1bWVkICkgfTtcblxuICAgICAgICBsaW5rID0gWyBcImxpbmtfcmVmXCIsIGF0dHJzIF0uY29uY2F0KCBjaGlsZHJlbiApO1xuXG4gICAgICAgIC8vIFdlIGNhbid0IGNoZWNrIGlmIHRoZSByZWZlcmVuY2UgaXMga25vd24gaGVyZSBhcyBpdCBsaWtlbHkgd29udCBiZVxuICAgICAgICAvLyBmb3VuZCB0aWxsIGFmdGVyLiBDaGVjayBpdCBpbiBtZCB0cmVlLT5obXRsIHRyZWUgY29udmVyc2lvbi5cbiAgICAgICAgLy8gU3RvcmUgdGhlIG9yaWdpbmFsIHNvIHRoYXQgY29udmVyc2lvbiBjYW4gcmV2ZXJ0IGlmIHRoZSByZWYgaXNuJ3QgZm91bmQuXG4gICAgICAgIHJldHVybiBbIGNvbnN1bWVkLCBsaW5rIF07XG4gICAgICB9XG5cbiAgICAgIC8vIFtpZF1cbiAgICAgIC8vIE9ubHkgaWYgaWQgaXMgcGxhaW4gKG5vIGZvcm1hdHRpbmcuKVxuICAgICAgaWYgKCBjaGlsZHJlbi5sZW5ndGggPT0gMSAmJiB0eXBlb2YgY2hpbGRyZW5bMF0gPT0gXCJzdHJpbmdcIiApIHtcblxuICAgICAgICBhdHRycyA9IHsgcmVmOiBjaGlsZHJlblswXS50b0xvd2VyQ2FzZSgpLCAgb3JpZ2luYWw6IG9yaWcuc3Vic3RyKCAwLCBjb25zdW1lZCApIH07XG4gICAgICAgIGxpbmsgPSBbIFwibGlua19yZWZcIiwgYXR0cnMsIGNoaWxkcmVuWzBdIF07XG4gICAgICAgIHJldHVybiBbIGNvbnN1bWVkLCBsaW5rIF07XG4gICAgICB9XG5cbiAgICAgIC8vIEp1c3QgY29uc3VtZSB0aGUgXCJbXCJcbiAgICAgIHJldHVybiBbIDEsIFwiW1wiIF07XG4gICAgfSxcblxuXG4gICAgXCI8XCI6IGZ1bmN0aW9uIGF1dG9MaW5rKCB0ZXh0ICkge1xuICAgICAgdmFyIG07XG5cbiAgICAgIGlmICggKCBtID0gdGV4dC5tYXRjaCggL148KD86KChodHRwcz98ZnRwfG1haWx0byk6W14+XSspfCguKj9ALio/XFwuW2EtekEtWl0rKSk+LyApICkgIT0gbnVsbCApIHtcbiAgICAgICAgaWYgKCBtWzNdICkge1xuICAgICAgICAgIHJldHVybiBbIG1bMF0ubGVuZ3RoLCBbIFwibGlua1wiLCB7IGhyZWY6IFwibWFpbHRvOlwiICsgbVszXSB9LCBtWzNdIF0gXTtcblxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCBtWzJdID09IFwibWFpbHRvXCIgKSB7XG4gICAgICAgICAgcmV0dXJuIFsgbVswXS5sZW5ndGgsIFsgXCJsaW5rXCIsIHsgaHJlZjogbVsxXSB9LCBtWzFdLnN1YnN0cihcIm1haWx0bzpcIi5sZW5ndGggKSBdIF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZVxuICAgICAgICAgIHJldHVybiBbIG1bMF0ubGVuZ3RoLCBbIFwibGlua1wiLCB7IGhyZWY6IG1bMV0gfSwgbVsxXSBdIF07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBbIDEsIFwiPFwiIF07XG4gICAgfSxcblxuICAgIFwiYFwiOiBmdW5jdGlvbiBpbmxpbmVDb2RlKCB0ZXh0ICkge1xuICAgICAgLy8gSW5saW5lIGNvZGUgYmxvY2suIGFzIG1hbnkgYmFja3RpY2tzIGFzIHlvdSBsaWtlIHRvIHN0YXJ0IGl0XG4gICAgICAvLyBBbHdheXMgc2tpcCBvdmVyIHRoZSBvcGVuaW5nIHRpY2tzLlxuICAgICAgdmFyIG0gPSB0ZXh0Lm1hdGNoKCAvKGArKSgoW1xcc1xcU10qPylcXDEpLyApO1xuXG4gICAgICBpZiAoIG0gJiYgbVsyXSApXG4gICAgICAgIHJldHVybiBbIG1bMV0ubGVuZ3RoICsgbVsyXS5sZW5ndGgsIFsgXCJpbmxpbmVjb2RlXCIsIG1bM10gXSBdO1xuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIFRPRE86IE5vIG1hdGNoaW5nIGVuZCBjb2RlIGZvdW5kIC0gd2FybiFcbiAgICAgICAgcmV0dXJuIFsgMSwgXCJgXCIgXTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgXCIgIFxcblwiOiBmdW5jdGlvbiBsaW5lQnJlYWsoIHRleHQgKSB7XG4gICAgICByZXR1cm4gWyAzLCBbIFwibGluZWJyZWFrXCIgXSBdO1xuICAgIH1cblxufTtcblxuLy8gTWV0YSBIZWxwZXIvZ2VuZXJhdG9yIG1ldGhvZCBmb3IgZW0gYW5kIHN0cm9uZyBoYW5kbGluZ1xuZnVuY3Rpb24gc3Ryb25nX2VtKCB0YWcsIG1kICkge1xuXG4gIHZhciBzdGF0ZV9zbG90ID0gdGFnICsgXCJfc3RhdGVcIixcbiAgICAgIG90aGVyX3Nsb3QgPSB0YWcgPT0gXCJzdHJvbmdcIiA/IFwiZW1fc3RhdGVcIiA6IFwic3Ryb25nX3N0YXRlXCI7XG5cbiAgZnVuY3Rpb24gQ2xvc2VUYWcobGVuKSB7XG4gICAgdGhpcy5sZW5fYWZ0ZXIgPSBsZW47XG4gICAgdGhpcy5uYW1lID0gXCJjbG9zZV9cIiArIG1kO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICggdGV4dCwgb3JpZ19tYXRjaCApIHtcblxuICAgIGlmICggdGhpc1tzdGF0ZV9zbG90XVswXSA9PSBtZCApIHtcbiAgICAgIC8vIE1vc3QgcmVjZW50IGVtIGlzIG9mIHRoaXMgdHlwZVxuICAgICAgLy9EOnRoaXMuZGVidWcoXCJjbG9zaW5nXCIsIG1kKTtcbiAgICAgIHRoaXNbc3RhdGVfc2xvdF0uc2hpZnQoKTtcblxuICAgICAgLy8gXCJDb25zdW1lXCIgZXZlcnl0aGluZyB0byBnbyBiYWNrIHRvIHRoZSByZWNydXNpb24gaW4gdGhlIGVsc2UtYmxvY2sgYmVsb3dcbiAgICAgIHJldHVyblsgdGV4dC5sZW5ndGgsIG5ldyBDbG9zZVRhZyh0ZXh0Lmxlbmd0aC1tZC5sZW5ndGgpIF07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgLy8gU3RvcmUgYSBjbG9uZSBvZiB0aGUgZW0vc3Ryb25nIHN0YXRlc1xuICAgICAgdmFyIG90aGVyID0gdGhpc1tvdGhlcl9zbG90XS5zbGljZSgpLFxuICAgICAgICAgIHN0YXRlID0gdGhpc1tzdGF0ZV9zbG90XS5zbGljZSgpO1xuXG4gICAgICB0aGlzW3N0YXRlX3Nsb3RdLnVuc2hpZnQobWQpO1xuXG4gICAgICAvL0Q6dGhpcy5kZWJ1Z19pbmRlbnQgKz0gXCIgIFwiO1xuXG4gICAgICAvLyBSZWN1cnNlXG4gICAgICB2YXIgcmVzID0gdGhpcy5wcm9jZXNzSW5saW5lKCB0ZXh0LnN1YnN0ciggbWQubGVuZ3RoICkgKTtcbiAgICAgIC8vRDp0aGlzLmRlYnVnX2luZGVudCA9IHRoaXMuZGVidWdfaW5kZW50LnN1YnN0cigyKTtcblxuICAgICAgdmFyIGxhc3QgPSByZXNbcmVzLmxlbmd0aCAtIDFdO1xuXG4gICAgICAvL0Q6dGhpcy5kZWJ1ZyhcInByb2Nlc3NJbmxpbmUgZnJvbVwiLCB0YWcgKyBcIjogXCIsIHVuZXZhbCggcmVzICkgKTtcblxuICAgICAgdmFyIGNoZWNrID0gdGhpc1tzdGF0ZV9zbG90XS5zaGlmdCgpO1xuICAgICAgaWYgKCBsYXN0IGluc3RhbmNlb2YgQ2xvc2VUYWcgKSB7XG4gICAgICAgIHJlcy5wb3AoKTtcbiAgICAgICAgLy8gV2UgbWF0Y2hlZCEgSHV6emFoLlxuICAgICAgICB2YXIgY29uc3VtZWQgPSB0ZXh0Lmxlbmd0aCAtIGxhc3QubGVuX2FmdGVyO1xuICAgICAgICByZXR1cm4gWyBjb25zdW1lZCwgWyB0YWcgXS5jb25jYXQocmVzKSBdO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIFJlc3RvcmUgdGhlIHN0YXRlIG9mIHRoZSBvdGhlciBraW5kLiBXZSBtaWdodCBoYXZlIG1pc3Rha2VubHkgY2xvc2VkIGl0LlxuICAgICAgICB0aGlzW290aGVyX3Nsb3RdID0gb3RoZXI7XG4gICAgICAgIHRoaXNbc3RhdGVfc2xvdF0gPSBzdGF0ZTtcblxuICAgICAgICAvLyBXZSBjYW4ndCByZXVzZSB0aGUgcHJvY2Vzc2VkIHJlc3VsdCBhcyBpdCBjb3VsZCBoYXZlIHdyb25nIHBhcnNpbmcgY29udGV4dHMgaW4gaXQuXG4gICAgICAgIHJldHVybiBbIG1kLmxlbmd0aCwgbWQgXTtcbiAgICAgIH1cbiAgICB9XG4gIH07IC8vIEVuZCByZXR1cm5lZCBmdW5jdGlvblxufVxuXG5NYXJrZG93bi5kaWFsZWN0cy5HcnViZXIuaW5saW5lW1wiKipcIl0gPSBzdHJvbmdfZW0oXCJzdHJvbmdcIiwgXCIqKlwiKTtcbk1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5pbmxpbmVbXCJfX1wiXSA9IHN0cm9uZ19lbShcInN0cm9uZ1wiLCBcIl9fXCIpO1xuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZVtcIipcIl0gID0gc3Ryb25nX2VtKFwiZW1cIiwgXCIqXCIpO1xuTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZVtcIl9cIl0gID0gc3Ryb25nX2VtKFwiZW1cIiwgXCJfXCIpO1xuXG5cbi8vIEJ1aWxkIGRlZmF1bHQgb3JkZXIgZnJvbSBpbnNlcnRpb24gb3JkZXIuXG5NYXJrZG93bi5idWlsZEJsb2NrT3JkZXIgPSBmdW5jdGlvbihkKSB7XG4gIHZhciBvcmQgPSBbXTtcbiAgZm9yICggdmFyIGkgaW4gZCApIHtcbiAgICBpZiAoIGkgPT0gXCJfX29yZGVyX19cIiB8fCBpID09IFwiX19jYWxsX19cIiApIGNvbnRpbnVlO1xuICAgIG9yZC5wdXNoKCBpICk7XG4gIH1cbiAgZC5fX29yZGVyX18gPSBvcmQ7XG59O1xuXG4vLyBCdWlsZCBwYXR0ZXJucyBmb3IgaW5saW5lIG1hdGNoZXJcbk1hcmtkb3duLmJ1aWxkSW5saW5lUGF0dGVybnMgPSBmdW5jdGlvbihkKSB7XG4gIHZhciBwYXR0ZXJucyA9IFtdO1xuXG4gIGZvciAoIHZhciBpIGluIGQgKSB7XG4gICAgLy8gX19mb29fXyBpcyByZXNlcnZlZCBhbmQgbm90IGEgcGF0dGVyblxuICAgIGlmICggaS5tYXRjaCggL15fXy4qX18kLykgKSBjb250aW51ZTtcbiAgICB2YXIgbCA9IGkucmVwbGFjZSggLyhbXFxcXC4qKz98KClcXFtcXF17fV0pL2csIFwiXFxcXCQxXCIgKVxuICAgICAgICAgICAgIC5yZXBsYWNlKCAvXFxuLywgXCJcXFxcblwiICk7XG4gICAgcGF0dGVybnMucHVzaCggaS5sZW5ndGggPT0gMSA/IGwgOiBcIig/OlwiICsgbCArIFwiKVwiICk7XG4gIH1cblxuICBwYXR0ZXJucyA9IHBhdHRlcm5zLmpvaW4oXCJ8XCIpO1xuICBkLl9fcGF0dGVybnNfXyA9IHBhdHRlcm5zO1xuICAvL3ByaW50KFwicGF0dGVybnM6XCIsIHVuZXZhbCggcGF0dGVybnMgKSApO1xuXG4gIHZhciBmbiA9IGQuX19jYWxsX187XG4gIGQuX19jYWxsX18gPSBmdW5jdGlvbih0ZXh0LCBwYXR0ZXJuKSB7XG4gICAgaWYgKCBwYXR0ZXJuICE9IHVuZGVmaW5lZCApIHtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoaXMsIHRleHQsIHBhdHRlcm4pO1xuICAgIH1cbiAgICBlbHNlXG4gICAge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhpcywgdGV4dCwgcGF0dGVybnMpO1xuICAgIH1cbiAgfTtcbn07XG5cbk1hcmtkb3duLkRpYWxlY3RIZWxwZXJzID0ge307XG5NYXJrZG93bi5EaWFsZWN0SGVscGVycy5pbmxpbmVfdW50aWxfY2hhciA9IGZ1bmN0aW9uKCB0ZXh0LCB3YW50ICkge1xuICB2YXIgY29uc3VtZWQgPSAwLFxuICAgICAgbm9kZXMgPSBbXTtcblxuICB3aGlsZSAoIHRydWUgKSB7XG4gICAgaWYgKCB0ZXh0LmNoYXJBdCggY29uc3VtZWQgKSA9PSB3YW50ICkge1xuICAgICAgLy8gRm91bmQgdGhlIGNoYXJhY3RlciB3ZSB3ZXJlIGxvb2tpbmcgZm9yXG4gICAgICBjb25zdW1lZCsrO1xuICAgICAgcmV0dXJuIFsgY29uc3VtZWQsIG5vZGVzIF07XG4gICAgfVxuXG4gICAgaWYgKCBjb25zdW1lZCA+PSB0ZXh0Lmxlbmd0aCApIHtcbiAgICAgIC8vIE5vIGNsb3NpbmcgY2hhciBmb3VuZC4gQWJvcnQuXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgcmVzID0gdGhpcy5kaWFsZWN0LmlubGluZS5fX29uZUVsZW1lbnRfXy5jYWxsKHRoaXMsIHRleHQuc3Vic3RyKCBjb25zdW1lZCApICk7XG4gICAgY29uc3VtZWQgKz0gcmVzWyAwIF07XG4gICAgLy8gQWRkIGFueSByZXR1cm5lZCBub2Rlcy5cbiAgICBub2Rlcy5wdXNoLmFwcGx5KCBub2RlcywgcmVzLnNsaWNlKCAxICkgKTtcbiAgfVxufVxuXG4vLyBIZWxwZXIgZnVuY3Rpb24gdG8gbWFrZSBzdWItY2xhc3NpbmcgYSBkaWFsZWN0IGVhc2llclxuTWFya2Rvd24uc3ViY2xhc3NEaWFsZWN0ID0gZnVuY3Rpb24oIGQgKSB7XG4gIGZ1bmN0aW9uIEJsb2NrKCkge31cbiAgQmxvY2sucHJvdG90eXBlID0gZC5ibG9jaztcbiAgZnVuY3Rpb24gSW5saW5lKCkge31cbiAgSW5saW5lLnByb3RvdHlwZSA9IGQuaW5saW5lO1xuXG4gIHJldHVybiB7IGJsb2NrOiBuZXcgQmxvY2soKSwgaW5saW5lOiBuZXcgSW5saW5lKCkgfTtcbn07XG5cbk1hcmtkb3duLmJ1aWxkQmxvY2tPcmRlciAoIE1hcmtkb3duLmRpYWxlY3RzLkdydWJlci5ibG9jayApO1xuTWFya2Rvd24uYnVpbGRJbmxpbmVQYXR0ZXJucyggTWFya2Rvd24uZGlhbGVjdHMuR3J1YmVyLmlubGluZSApO1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UgPSBNYXJrZG93bi5zdWJjbGFzc0RpYWxlY3QoIE1hcmtkb3duLmRpYWxlY3RzLkdydWJlciApO1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UucHJvY2Vzc01ldGFIYXNoID0gZnVuY3Rpb24gcHJvY2Vzc01ldGFIYXNoKCBtZXRhX3N0cmluZyApIHtcbiAgdmFyIG1ldGEgPSBzcGxpdF9tZXRhX2hhc2goIG1ldGFfc3RyaW5nICksXG4gICAgICBhdHRyID0ge307XG5cbiAgZm9yICggdmFyIGkgPSAwOyBpIDwgbWV0YS5sZW5ndGg7ICsraSApIHtcbiAgICAvLyBpZDogI2Zvb1xuICAgIGlmICggL14jLy50ZXN0KCBtZXRhWyBpIF0gKSApIHtcbiAgICAgIGF0dHIuaWQgPSBtZXRhWyBpIF0uc3Vic3RyaW5nKCAxICk7XG4gICAgfVxuICAgIC8vIGNsYXNzOiAuZm9vXG4gICAgZWxzZSBpZiAoIC9eXFwuLy50ZXN0KCBtZXRhWyBpIF0gKSApIHtcbiAgICAgIC8vIGlmIGNsYXNzIGFscmVhZHkgZXhpc3RzLCBhcHBlbmQgdGhlIG5ldyBvbmVcbiAgICAgIGlmICggYXR0cltcImNsYXNzXCJdICkge1xuICAgICAgICBhdHRyW1wiY2xhc3NcIl0gPSBhdHRyW1wiY2xhc3NcIl0gKyBtZXRhWyBpIF0ucmVwbGFjZSggLy4vLCBcIiBcIiApO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGF0dHJbXCJjbGFzc1wiXSA9IG1ldGFbIGkgXS5zdWJzdHJpbmcoIDEgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gYXR0cmlidXRlOiBmb289YmFyXG4gICAgZWxzZSBpZiAoIC9cXD0vLnRlc3QoIG1ldGFbIGkgXSApICkge1xuICAgICAgdmFyIHMgPSBtZXRhWyBpIF0uc3BsaXQoIC9cXD0vICk7XG4gICAgICBhdHRyWyBzWyAwIF0gXSA9IHNbIDEgXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYXR0cjtcbn1cblxuZnVuY3Rpb24gc3BsaXRfbWV0YV9oYXNoKCBtZXRhX3N0cmluZyApIHtcbiAgdmFyIG1ldGEgPSBtZXRhX3N0cmluZy5zcGxpdCggXCJcIiApLFxuICAgICAgcGFydHMgPSBbIFwiXCIgXSxcbiAgICAgIGluX3F1b3RlcyA9IGZhbHNlO1xuXG4gIHdoaWxlICggbWV0YS5sZW5ndGggKSB7XG4gICAgdmFyIGxldHRlciA9IG1ldGEuc2hpZnQoKTtcbiAgICBzd2l0Y2ggKCBsZXR0ZXIgKSB7XG4gICAgICBjYXNlIFwiIFwiIDpcbiAgICAgICAgLy8gaWYgd2UncmUgaW4gYSBxdW90ZWQgc2VjdGlvbiwga2VlcCBpdFxuICAgICAgICBpZiAoIGluX3F1b3RlcyApIHtcbiAgICAgICAgICBwYXJ0c1sgcGFydHMubGVuZ3RoIC0gMSBdICs9IGxldHRlcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2UgbWFrZSBhIG5ldyBwYXJ0XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHBhcnRzLnB1c2goIFwiXCIgKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCInXCIgOlxuICAgICAgY2FzZSAnXCInIDpcbiAgICAgICAgLy8gcmV2ZXJzZSB0aGUgcXVvdGVzIGFuZCBtb3ZlIHN0cmFpZ2h0IG9uXG4gICAgICAgIGluX3F1b3RlcyA9ICFpbl9xdW90ZXM7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcIlxcXFxcIiA6XG4gICAgICAgIC8vIHNoaWZ0IG9mZiB0aGUgbmV4dCBsZXR0ZXIgdG8gYmUgdXNlZCBzdHJhaWdodCBhd2F5LlxuICAgICAgICAvLyBpdCB3YXMgZXNjYXBlZCBzbyB3ZSdsbCBrZWVwIGl0IHdoYXRldmVyIGl0IGlzXG4gICAgICAgIGxldHRlciA9IG1ldGEuc2hpZnQoKTtcbiAgICAgIGRlZmF1bHQgOlxuICAgICAgICBwYXJ0c1sgcGFydHMubGVuZ3RoIC0gMSBdICs9IGxldHRlcjtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHBhcnRzO1xufVxuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2suZG9jdW1lbnRfbWV0YSA9IGZ1bmN0aW9uIGRvY3VtZW50X21ldGEoIGJsb2NrLCBuZXh0ICkge1xuICAvLyB3ZSdyZSBvbmx5IGludGVyZXN0ZWQgaW4gdGhlIGZpcnN0IGJsb2NrXG4gIGlmICggYmxvY2subGluZU51bWJlciA+IDEgKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIC8vIGRvY3VtZW50X21ldGEgYmxvY2tzIGNvbnNpc3Qgb2Ygb25lIG9yIG1vcmUgbGluZXMgb2YgYEtleTogVmFsdWVcXG5gXG4gIGlmICggISBibG9jay5tYXRjaCggL14oPzpcXHcrOi4qXFxuKSpcXHcrOi4qJC8gKSApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgLy8gbWFrZSBhbiBhdHRyaWJ1dGUgbm9kZSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gIGlmICggIWV4dHJhY3RfYXR0ciggdGhpcy50cmVlICkgKSB7XG4gICAgdGhpcy50cmVlLnNwbGljZSggMSwgMCwge30gKTtcbiAgfVxuXG4gIHZhciBwYWlycyA9IGJsb2NrLnNwbGl0KCAvXFxuLyApO1xuICBmb3IgKCBwIGluIHBhaXJzICkge1xuICAgIHZhciBtID0gcGFpcnNbIHAgXS5tYXRjaCggLyhcXHcrKTpcXHMqKC4qKSQvICksXG4gICAgICAgIGtleSA9IG1bIDEgXS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICB2YWx1ZSA9IG1bIDIgXTtcblxuICAgIHRoaXMudHJlZVsgMSBdWyBrZXkgXSA9IHZhbHVlO1xuICB9XG5cbiAgLy8gZG9jdW1lbnRfbWV0YSBwcm9kdWNlcyBubyBjb250ZW50IVxuICByZXR1cm4gW107XG59O1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2suYmxvY2tfbWV0YSA9IGZ1bmN0aW9uIGJsb2NrX21ldGEoIGJsb2NrLCBuZXh0ICkge1xuICAvLyBjaGVjayBpZiB0aGUgbGFzdCBsaW5lIG9mIHRoZSBibG9jayBpcyBhbiBtZXRhIGhhc2hcbiAgdmFyIG0gPSBibG9jay5tYXRjaCggLyhefFxcbikgezAsM31cXHs6XFxzKigoPzpcXFxcXFx9fFteXFx9XSkqKVxccypcXH0kLyApO1xuICBpZiAoICFtICkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAvLyBwcm9jZXNzIHRoZSBtZXRhIGhhc2hcbiAgdmFyIGF0dHIgPSB0aGlzLmRpYWxlY3QucHJvY2Vzc01ldGFIYXNoKCBtWyAyIF0gKTtcblxuICB2YXIgaGFzaDtcblxuICAvLyBpZiB3ZSBtYXRjaGVkIF4gdGhlbiB3ZSBuZWVkIHRvIGFwcGx5IG1ldGEgdG8gdGhlIHByZXZpb3VzIGJsb2NrXG4gIGlmICggbVsgMSBdID09PSBcIlwiICkge1xuICAgIHZhciBub2RlID0gdGhpcy50cmVlWyB0aGlzLnRyZWUubGVuZ3RoIC0gMSBdO1xuICAgIGhhc2ggPSBleHRyYWN0X2F0dHIoIG5vZGUgKTtcblxuICAgIC8vIGlmIHRoZSBub2RlIGlzIGEgc3RyaW5nIChyYXRoZXIgdGhhbiBKc29uTUwpLCBiYWlsXG4gICAgaWYgKCB0eXBlb2Ygbm9kZSA9PT0gXCJzdHJpbmdcIiApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAvLyBjcmVhdGUgdGhlIGF0dHJpYnV0ZSBoYXNoIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICBpZiAoICFoYXNoICkge1xuICAgICAgaGFzaCA9IHt9O1xuICAgICAgbm9kZS5zcGxpY2UoIDEsIDAsIGhhc2ggKTtcbiAgICB9XG5cbiAgICAvLyBhZGQgdGhlIGF0dHJpYnV0ZXMgaW5cbiAgICBmb3IgKCBhIGluIGF0dHIgKSB7XG4gICAgICBoYXNoWyBhIF0gPSBhdHRyWyBhIF07XG4gICAgfVxuXG4gICAgLy8gcmV0dXJuIG5vdGhpbmcgc28gdGhlIG1ldGEgaGFzaCBpcyByZW1vdmVkXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLy8gcHVsbCB0aGUgbWV0YSBoYXNoIG9mZiB0aGUgYmxvY2sgYW5kIHByb2Nlc3Mgd2hhdCdzIGxlZnRcbiAgdmFyIGIgPSBibG9jay5yZXBsYWNlKCAvXFxuLiokLywgXCJcIiApLFxuICAgICAgcmVzdWx0ID0gdGhpcy5wcm9jZXNzQmxvY2soIGIsIFtdICk7XG5cbiAgLy8gZ2V0IG9yIG1ha2UgdGhlIGF0dHJpYnV0ZXMgaGFzaFxuICBoYXNoID0gZXh0cmFjdF9hdHRyKCByZXN1bHRbIDAgXSApO1xuICBpZiAoICFoYXNoICkge1xuICAgIGhhc2ggPSB7fTtcbiAgICByZXN1bHRbIDAgXS5zcGxpY2UoIDEsIDAsIGhhc2ggKTtcbiAgfVxuXG4gIC8vIGF0dGFjaCB0aGUgYXR0cmlidXRlcyB0byB0aGUgYmxvY2tcbiAgZm9yICggYSBpbiBhdHRyICkge1xuICAgIGhhc2hbIGEgXSA9IGF0dHJbIGEgXTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2suZGVmaW5pdGlvbl9saXN0ID0gZnVuY3Rpb24gZGVmaW5pdGlvbl9saXN0KCBibG9jaywgbmV4dCApIHtcbiAgLy8gb25lIG9yIG1vcmUgdGVybXMgZm9sbG93ZWQgYnkgb25lIG9yIG1vcmUgZGVmaW5pdGlvbnMsIGluIGEgc2luZ2xlIGJsb2NrXG4gIHZhciB0aWdodCA9IC9eKCg/OlteXFxzOl0uKlxcbikrKTpcXHMrKFtcXHNcXFNdKykkLyxcbiAgICAgIGxpc3QgPSBbIFwiZGxcIiBdLFxuICAgICAgaSwgbTtcblxuICAvLyBzZWUgaWYgd2UncmUgZGVhbGluZyB3aXRoIGEgdGlnaHQgb3IgbG9vc2UgYmxvY2tcbiAgaWYgKCAoIG0gPSBibG9jay5tYXRjaCggdGlnaHQgKSApICkge1xuICAgIC8vIHB1bGwgc3Vic2VxdWVudCB0aWdodCBETCBibG9ja3Mgb3V0IG9mIGBuZXh0YFxuICAgIHZhciBibG9ja3MgPSBbIGJsb2NrIF07XG4gICAgd2hpbGUgKCBuZXh0Lmxlbmd0aCAmJiB0aWdodC5leGVjKCBuZXh0WyAwIF0gKSApIHtcbiAgICAgIGJsb2Nrcy5wdXNoKCBuZXh0LnNoaWZ0KCkgKTtcbiAgICB9XG5cbiAgICBmb3IgKCB2YXIgYiA9IDA7IGIgPCBibG9ja3MubGVuZ3RoOyArK2IgKSB7XG4gICAgICB2YXIgbSA9IGJsb2Nrc1sgYiBdLm1hdGNoKCB0aWdodCApLFxuICAgICAgICAgIHRlcm1zID0gbVsgMSBdLnJlcGxhY2UoIC9cXG4kLywgXCJcIiApLnNwbGl0KCAvXFxuLyApLFxuICAgICAgICAgIGRlZm5zID0gbVsgMiBdLnNwbGl0KCAvXFxuOlxccysvICk7XG5cbiAgICAgIC8vIHByaW50KCB1bmV2YWwoIG0gKSApO1xuXG4gICAgICBmb3IgKCBpID0gMDsgaSA8IHRlcm1zLmxlbmd0aDsgKytpICkge1xuICAgICAgICBsaXN0LnB1c2goIFsgXCJkdFwiLCB0ZXJtc1sgaSBdIF0gKTtcbiAgICAgIH1cblxuICAgICAgZm9yICggaSA9IDA7IGkgPCBkZWZucy5sZW5ndGg7ICsraSApIHtcbiAgICAgICAgLy8gcnVuIGlubGluZSBwcm9jZXNzaW5nIG92ZXIgdGhlIGRlZmluaXRpb25cbiAgICAgICAgbGlzdC5wdXNoKCBbIFwiZGRcIiBdLmNvbmNhdCggdGhpcy5wcm9jZXNzSW5saW5lKCBkZWZuc1sgaSBdLnJlcGxhY2UoIC8oXFxuKVxccysvLCBcIiQxXCIgKSApICkgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZWxzZSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiBbIGxpc3QgXTtcbn07XG5cbi8vIHNwbGl0cyBvbiB1bmVzY2FwZWQgaW5zdGFuY2VzIG9mIEBjaC4gSWYgQGNoIGlzIG5vdCBhIGNoYXJhY3RlciB0aGUgcmVzdWx0XG4vLyBjYW4gYmUgdW5wcmVkaWN0YWJsZVxuXG5NYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2sudGFibGUgPSBmdW5jdGlvbiB0YWJsZSAoYmxvY2ssIG5leHQpIHtcblxuICAgIHZhciBfc3BsaXRfb25fdW5lc2NhcGVkID0gZnVuY3Rpb24ocywgY2gpIHtcbiAgICAgICAgY2ggPSBjaCB8fCAnXFxcXHMnO1xuICAgICAgICBpZiAoY2gubWF0Y2goL15bXFxcXHxcXFtcXF17fT8qLiteJF0kLykpIHsgY2ggPSAnXFxcXCcgKyBjaDsgfVxuICAgICAgICB2YXIgcmVzID0gWyBdLFxuICAgICAgICAgICAgciA9IG5ldyBSZWdFeHAoJ14oKD86XFxcXFxcXFwufFteXFxcXFxcXFwnICsgY2ggKyAnXSkqKScgKyBjaCArICcoLiopJyksXG4gICAgICAgICAgICBtO1xuICAgICAgICB3aGlsZShtID0gcy5tYXRjaChyKSkge1xuICAgICAgICAgICAgcmVzLnB1c2gobVsxXSk7XG4gICAgICAgICAgICBzID0gbVsyXTtcbiAgICAgICAgfVxuICAgICAgICByZXMucHVzaChzKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICB2YXIgbGVhZGluZ19waXBlID0gL14gezAsM31cXHwoLispXFxuIHswLDN9XFx8XFxzKihbXFwtOl0rW1xcLXwgOl0qKVxcbigoPzpcXHMqXFx8LiooPzpcXG58JCkpKikoPz1cXG58JCkvLFxuICAgICAgICAvLyBmaW5kIGF0IGxlYXN0IGFuIHVuZXNjYXBlZCBwaXBlIGluIGVhY2ggbGluZVxuICAgICAgICBub19sZWFkaW5nX3BpcGUgPSAvXiB7MCwzfShcXFMoPzpcXFxcLnxbXlxcXFx8XSkqXFx8LiopXFxuIHswLDN9KFtcXC06XStcXHMqXFx8W1xcLXwgOl0qKVxcbigoPzooPzpcXFxcLnxbXlxcXFx8XSkqXFx8LiooPzpcXG58JCkpKikoPz1cXG58JCkvLFxuICAgICAgICBpLCBtO1xuICAgIGlmIChtID0gYmxvY2subWF0Y2gobGVhZGluZ19waXBlKSkge1xuICAgICAgICAvLyByZW1vdmUgbGVhZGluZyBwaXBlcyBpbiBjb250ZW50c1xuICAgICAgICAvLyAoaGVhZGVyIGFuZCBob3Jpem9udGFsIHJ1bGUgYWxyZWFkeSBoYXZlIHRoZSBsZWFkaW5nIHBpcGUgbGVmdCBvdXQpXG4gICAgICAgIG1bM10gPSBtWzNdLnJlcGxhY2UoL15cXHMqXFx8L2dtLCAnJyk7XG4gICAgfSBlbHNlIGlmICghICggbSA9IGJsb2NrLm1hdGNoKG5vX2xlYWRpbmdfcGlwZSkpKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgdmFyIHRhYmxlID0gWyBcInRhYmxlXCIsIFsgXCJ0aGVhZFwiLCBbIFwidHJcIiBdIF0sIFsgXCJ0Ym9keVwiIF0gXTtcblxuICAgIC8vIHJlbW92ZSB0cmFpbGluZyBwaXBlcywgdGhlbiBzcGxpdCBvbiBwaXBlc1xuICAgIC8vIChubyBlc2NhcGVkIHBpcGVzIGFyZSBhbGxvd2VkIGluIGhvcml6b250YWwgcnVsZSlcbiAgICBtWzJdID0gbVsyXS5yZXBsYWNlKC9cXHxcXHMqJC8sICcnKS5zcGxpdCgnfCcpO1xuXG4gICAgLy8gcHJvY2VzcyBhbGlnbm1lbnRcbiAgICB2YXIgaHRtbF9hdHRycyA9IFsgXTtcbiAgICBmb3JFYWNoIChtWzJdLCBmdW5jdGlvbiAocykge1xuICAgICAgICBpZiAocy5tYXRjaCgvXlxccyotKzpcXHMqJC8pKSAgICAgICBodG1sX2F0dHJzLnB1c2goe2FsaWduOiBcInJpZ2h0XCJ9KTtcbiAgICAgICAgZWxzZSBpZiAocy5tYXRjaCgvXlxccyo6LStcXHMqJC8pKSAgaHRtbF9hdHRycy5wdXNoKHthbGlnbjogXCJsZWZ0XCJ9KTtcbiAgICAgICAgZWxzZSBpZiAocy5tYXRjaCgvXlxccyo6LSs6XFxzKiQvKSkgaHRtbF9hdHRycy5wdXNoKHthbGlnbjogXCJjZW50ZXJcIn0pO1xuICAgICAgICBlbHNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbF9hdHRycy5wdXNoKHt9KTtcbiAgICB9KTtcblxuICAgIC8vIG5vdyBmb3IgdGhlIGhlYWRlciwgYXZvaWQgZXNjYXBlZCBwaXBlc1xuICAgIG1bMV0gPSBfc3BsaXRfb25fdW5lc2NhcGVkKG1bMV0ucmVwbGFjZSgvXFx8XFxzKiQvLCAnJyksICd8Jyk7XG4gICAgZm9yIChpID0gMDsgaSA8IG1bMV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGFibGVbMV1bMV0ucHVzaChbJ3RoJywgaHRtbF9hdHRyc1tpXSB8fCB7fV0uY29uY2F0KFxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzSW5saW5lKG1bMV1baV0udHJpbSgpKSkpO1xuICAgIH1cblxuICAgIC8vIG5vdyBmb3IgYm9keSBjb250ZW50c1xuICAgIGZvckVhY2ggKG1bM10ucmVwbGFjZSgvXFx8XFxzKiQvbWcsICcnKS5zcGxpdCgnXFxuJyksIGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIGh0bWxfcm93ID0gWyd0ciddO1xuICAgICAgICByb3cgPSBfc3BsaXRfb25fdW5lc2NhcGVkKHJvdywgJ3wnKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJvdy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaHRtbF9yb3cucHVzaChbJ3RkJywgaHRtbF9hdHRyc1tpXSB8fCB7fV0uY29uY2F0KHRoaXMucHJvY2Vzc0lubGluZShyb3dbaV0udHJpbSgpKSkpO1xuICAgICAgICB9XG4gICAgICAgIHRhYmxlWzJdLnB1c2goaHRtbF9yb3cpO1xuICAgIH0sIHRoaXMpO1xuXG4gICAgcmV0dXJuIFt0YWJsZV07XG59XG5cbk1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5pbmxpbmVbIFwiezpcIiBdID0gZnVuY3Rpb24gaW5saW5lX21ldGEoIHRleHQsIG1hdGNoZXMsIG91dCApIHtcbiAgaWYgKCAhb3V0Lmxlbmd0aCApIHtcbiAgICByZXR1cm4gWyAyLCBcIns6XCIgXTtcbiAgfVxuXG4gIC8vIGdldCB0aGUgcHJlY2VlZGluZyBlbGVtZW50XG4gIHZhciBiZWZvcmUgPSBvdXRbIG91dC5sZW5ndGggLSAxIF07XG5cbiAgaWYgKCB0eXBlb2YgYmVmb3JlID09PSBcInN0cmluZ1wiICkge1xuICAgIHJldHVybiBbIDIsIFwiezpcIiBdO1xuICB9XG5cbiAgLy8gbWF0Y2ggYSBtZXRhIGhhc2hcbiAgdmFyIG0gPSB0ZXh0Lm1hdGNoKCAvXlxcezpcXHMqKCg/OlxcXFxcXH18W15cXH1dKSopXFxzKlxcfS8gKTtcblxuICAvLyBubyBtYXRjaCwgZmFsc2UgYWxhcm1cbiAgaWYgKCAhbSApIHtcbiAgICByZXR1cm4gWyAyLCBcIns6XCIgXTtcbiAgfVxuXG4gIC8vIGF0dGFjaCB0aGUgYXR0cmlidXRlcyB0byB0aGUgcHJlY2VlZGluZyBlbGVtZW50XG4gIHZhciBtZXRhID0gdGhpcy5kaWFsZWN0LnByb2Nlc3NNZXRhSGFzaCggbVsgMSBdICksXG4gICAgICBhdHRyID0gZXh0cmFjdF9hdHRyKCBiZWZvcmUgKTtcblxuICBpZiAoICFhdHRyICkge1xuICAgIGF0dHIgPSB7fTtcbiAgICBiZWZvcmUuc3BsaWNlKCAxLCAwLCBhdHRyICk7XG4gIH1cblxuICBmb3IgKCB2YXIgayBpbiBtZXRhICkge1xuICAgIGF0dHJbIGsgXSA9IG1ldGFbIGsgXTtcbiAgfVxuXG4gIC8vIGN1dCBvdXQgdGhlIHN0cmluZyBhbmQgcmVwbGFjZSBpdCB3aXRoIG5vdGhpbmdcbiAgcmV0dXJuIFsgbVsgMCBdLmxlbmd0aCwgXCJcIiBdO1xufTtcblxuTWFya2Rvd24uZGlhbGVjdHMuTWFydWt1LmlubGluZS5fX2VzY2FwZV9fID0gL15cXFxcW1xcXFxgXFwqX3t9XFxbXFxdKCkjXFwrLiFcXC18Ol0vO1xuXG5NYXJrZG93bi5idWlsZEJsb2NrT3JkZXIgKCBNYXJrZG93bi5kaWFsZWN0cy5NYXJ1a3UuYmxvY2sgKTtcbk1hcmtkb3duLmJ1aWxkSW5saW5lUGF0dGVybnMoIE1hcmtkb3duLmRpYWxlY3RzLk1hcnVrdS5pbmxpbmUgKTtcblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uKG9iaikge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT0gXCJbb2JqZWN0IEFycmF5XVwiO1xufTtcblxudmFyIGZvckVhY2g7XG4vLyBEb24ndCBtZXNzIHdpdGggQXJyYXkucHJvdG90eXBlLiBJdHMgbm90IGZyaWVuZGx5XG5pZiAoIEFycmF5LnByb3RvdHlwZS5mb3JFYWNoICkge1xuICBmb3JFYWNoID0gZnVuY3Rpb24oIGFyciwgY2IsIHRoaXNwICkge1xuICAgIHJldHVybiBhcnIuZm9yRWFjaCggY2IsIHRoaXNwICk7XG4gIH07XG59XG5lbHNlIHtcbiAgZm9yRWFjaCA9IGZ1bmN0aW9uKGFyciwgY2IsIHRoaXNwKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNiLmNhbGwodGhpc3AgfHwgYXJyLCBhcnJbaV0sIGksIGFycik7XG4gICAgfVxuICB9XG59XG5cbnZhciBpc0VtcHR5ID0gZnVuY3Rpb24oIG9iaiApIHtcbiAgZm9yICggdmFyIGtleSBpbiBvYmogKSB7XG4gICAgaWYgKCBoYXNPd25Qcm9wZXJ0eS5jYWxsKCBvYmosIGtleSApICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0X2F0dHIoIGpzb25tbCApIHtcbiAgcmV0dXJuIGlzQXJyYXkoanNvbm1sKVxuICAgICAgJiYganNvbm1sLmxlbmd0aCA+IDFcbiAgICAgICYmIHR5cGVvZiBqc29ubWxbIDEgXSA9PT0gXCJvYmplY3RcIlxuICAgICAgJiYgISggaXNBcnJheShqc29ubWxbIDEgXSkgKVxuICAgICAgPyBqc29ubWxbIDEgXVxuICAgICAgOiB1bmRlZmluZWQ7XG59XG5cblxuXG4vKipcbiAqICByZW5kZXJKc29uTUwoIGpzb25tbFssIG9wdGlvbnNdICkgLT4gU3RyaW5nXG4gKiAgLSBqc29ubWwgKEFycmF5KTogSnNvbk1MIGFycmF5IHRvIHJlbmRlciB0byBYTUxcbiAqICAtIG9wdGlvbnMgKE9iamVjdCk6IG9wdGlvbnNcbiAqXG4gKiAgQ29udmVydHMgdGhlIGdpdmVuIEpzb25NTCBpbnRvIHdlbGwtZm9ybWVkIFhNTC5cbiAqXG4gKiAgVGhlIG9wdGlvbnMgY3VycmVudGx5IHVuZGVyc3Rvb2QgYXJlOlxuICpcbiAqICAtIHJvb3QgKEJvb2xlYW4pOiB3ZXRoZXIgb3Igbm90IHRoZSByb290IG5vZGUgc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZVxuICogICAgb3V0cHV0LCBvciBqdXN0IGl0cyBjaGlsZHJlbi4gVGhlIGRlZmF1bHQgYGZhbHNlYCBpcyB0byBub3QgaW5jbHVkZSB0aGVcbiAqICAgIHJvb3QgaXRzZWxmLlxuICovXG5leHBvc2UucmVuZGVySnNvbk1MID0gZnVuY3Rpb24oIGpzb25tbCwgb3B0aW9ucyApIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIC8vIGluY2x1ZGUgdGhlIHJvb3QgZWxlbWVudCBpbiB0aGUgcmVuZGVyZWQgb3V0cHV0P1xuICBvcHRpb25zLnJvb3QgPSBvcHRpb25zLnJvb3QgfHwgZmFsc2U7XG5cbiAgdmFyIGNvbnRlbnQgPSBbXTtcblxuICBpZiAoIG9wdGlvbnMucm9vdCApIHtcbiAgICBjb250ZW50LnB1c2goIHJlbmRlcl90cmVlKCBqc29ubWwgKSApO1xuICB9XG4gIGVsc2Uge1xuICAgIGpzb25tbC5zaGlmdCgpOyAvLyBnZXQgcmlkIG9mIHRoZSB0YWdcbiAgICBpZiAoIGpzb25tbC5sZW5ndGggJiYgdHlwZW9mIGpzb25tbFsgMCBdID09PSBcIm9iamVjdFwiICYmICEoIGpzb25tbFsgMCBdIGluc3RhbmNlb2YgQXJyYXkgKSApIHtcbiAgICAgIGpzb25tbC5zaGlmdCgpOyAvLyBnZXQgcmlkIG9mIHRoZSBhdHRyaWJ1dGVzXG4gICAgfVxuXG4gICAgd2hpbGUgKCBqc29ubWwubGVuZ3RoICkge1xuICAgICAgY29udGVudC5wdXNoKCByZW5kZXJfdHJlZSgganNvbm1sLnNoaWZ0KCkgKSApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjb250ZW50LmpvaW4oIFwiXFxuXFxuXCIgKTtcbn07XG5cbmZ1bmN0aW9uIGVzY2FwZUhUTUwoIHRleHQgKSB7XG4gIHJldHVybiB0ZXh0LnJlcGxhY2UoIC8mL2csIFwiJmFtcDtcIiApXG4gICAgICAgICAgICAgLnJlcGxhY2UoIC88L2csIFwiJmx0O1wiIClcbiAgICAgICAgICAgICAucmVwbGFjZSggLz4vZywgXCImZ3Q7XCIgKVxuICAgICAgICAgICAgIC5yZXBsYWNlKCAvXCIvZywgXCImcXVvdDtcIiApXG4gICAgICAgICAgICAgLnJlcGxhY2UoIC8nL2csIFwiJiMzOTtcIiApO1xufVxuXG5mdW5jdGlvbiByZW5kZXJfdHJlZSgganNvbm1sICkge1xuICAvLyBiYXNpYyBjYXNlXG4gIGlmICggdHlwZW9mIGpzb25tbCA9PT0gXCJzdHJpbmdcIiApIHtcbiAgICByZXR1cm4gZXNjYXBlSFRNTCgganNvbm1sICk7XG4gIH1cblxuICB2YXIgdGFnID0ganNvbm1sLnNoaWZ0KCksXG4gICAgICBhdHRyaWJ1dGVzID0ge30sXG4gICAgICBjb250ZW50ID0gW107XG5cbiAgaWYgKCBqc29ubWwubGVuZ3RoICYmIHR5cGVvZiBqc29ubWxbIDAgXSA9PT0gXCJvYmplY3RcIiAmJiAhKCBqc29ubWxbIDAgXSBpbnN0YW5jZW9mIEFycmF5ICkgKSB7XG4gICAgYXR0cmlidXRlcyA9IGpzb25tbC5zaGlmdCgpO1xuICB9XG5cbiAgd2hpbGUgKCBqc29ubWwubGVuZ3RoICkge1xuICAgIGNvbnRlbnQucHVzaCggcmVuZGVyX3RyZWUoIGpzb25tbC5zaGlmdCgpICkgKTtcbiAgfVxuXG4gIHZhciB0YWdfYXR0cnMgPSBcIlwiO1xuICBmb3IgKCB2YXIgYSBpbiBhdHRyaWJ1dGVzICkge1xuICAgIHRhZ19hdHRycyArPSBcIiBcIiArIGEgKyAnPVwiJyArIGVzY2FwZUhUTUwoIGF0dHJpYnV0ZXNbIGEgXSApICsgJ1wiJztcbiAgfVxuXG4gIC8vIGJlIGNhcmVmdWwgYWJvdXQgYWRkaW5nIHdoaXRlc3BhY2UgaGVyZSBmb3IgaW5saW5lIGVsZW1lbnRzXG4gIGlmICggdGFnID09IFwiaW1nXCIgfHwgdGFnID09IFwiYnJcIiB8fCB0YWcgPT0gXCJoclwiICkge1xuICAgIHJldHVybiBcIjxcIisgdGFnICsgdGFnX2F0dHJzICsgXCIvPlwiO1xuICB9XG4gIGVsc2Uge1xuICAgIHJldHVybiBcIjxcIisgdGFnICsgdGFnX2F0dHJzICsgXCI+XCIgKyBjb250ZW50LmpvaW4oIFwiXCIgKSArIFwiPC9cIiArIHRhZyArIFwiPlwiO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRfdHJlZV90b19odG1sKCB0cmVlLCByZWZlcmVuY2VzLCBvcHRpb25zICkge1xuICB2YXIgaTtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgLy8gc2hhbGxvdyBjbG9uZVxuICB2YXIganNvbm1sID0gdHJlZS5zbGljZSggMCApO1xuXG4gIGlmICggdHlwZW9mIG9wdGlvbnMucHJlcHJvY2Vzc1RyZWVOb2RlID09PSBcImZ1bmN0aW9uXCIgKSB7XG4gICAgICBqc29ubWwgPSBvcHRpb25zLnByZXByb2Nlc3NUcmVlTm9kZShqc29ubWwsIHJlZmVyZW5jZXMpO1xuICB9XG5cbiAgLy8gQ2xvbmUgYXR0cmlidXRlcyBpZiB0aGV5IGV4aXN0XG4gIHZhciBhdHRycyA9IGV4dHJhY3RfYXR0cigganNvbm1sICk7XG4gIGlmICggYXR0cnMgKSB7XG4gICAganNvbm1sWyAxIF0gPSB7fTtcbiAgICBmb3IgKCBpIGluIGF0dHJzICkge1xuICAgICAganNvbm1sWyAxIF1bIGkgXSA9IGF0dHJzWyBpIF07XG4gICAgfVxuICAgIGF0dHJzID0ganNvbm1sWyAxIF07XG4gIH1cblxuICAvLyBiYXNpYyBjYXNlXG4gIGlmICggdHlwZW9mIGpzb25tbCA9PT0gXCJzdHJpbmdcIiApIHtcbiAgICByZXR1cm4ganNvbm1sO1xuICB9XG5cbiAgLy8gY29udmVydCB0aGlzIG5vZGVcbiAgc3dpdGNoICgganNvbm1sWyAwIF0gKSB7XG4gICAgY2FzZSBcImhlYWRlclwiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImhcIiArIGpzb25tbFsgMSBdLmxldmVsO1xuICAgICAgZGVsZXRlIGpzb25tbFsgMSBdLmxldmVsO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImJ1bGxldGxpc3RcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJ1bFwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcIm51bWJlcmxpc3RcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJvbFwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImxpc3RpdGVtXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwibGlcIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJwYXJhXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwicFwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcIm1hcmtkb3duXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiaHRtbFwiO1xuICAgICAgaWYgKCBhdHRycyApIGRlbGV0ZSBhdHRycy5yZWZlcmVuY2VzO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImNvZGVfYmxvY2tcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJwcmVcIjtcbiAgICAgIGkgPSBhdHRycyA/IDIgOiAxO1xuICAgICAgdmFyIGNvZGUgPSBbIFwiY29kZVwiIF07XG4gICAgICBjb2RlLnB1c2guYXBwbHkoIGNvZGUsIGpzb25tbC5zcGxpY2UoIGksIGpzb25tbC5sZW5ndGggLSBpICkgKTtcbiAgICAgIGpzb25tbFsgaSBdID0gY29kZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJpbmxpbmVjb2RlXCI6XG4gICAgICBqc29ubWxbIDAgXSA9IFwiY29kZVwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImltZ1wiOlxuICAgICAganNvbm1sWyAxIF0uc3JjID0ganNvbm1sWyAxIF0uaHJlZjtcbiAgICAgIGRlbGV0ZSBqc29ubWxbIDEgXS5ocmVmO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImxpbmVicmVha1wiOlxuICAgICAganNvbm1sWyAwIF0gPSBcImJyXCI7XG4gICAgYnJlYWs7XG4gICAgY2FzZSBcImxpbmtcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJhXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwibGlua19yZWZcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJhXCI7XG5cbiAgICAgIC8vIGdyYWIgdGhpcyByZWYgYW5kIGNsZWFuIHVwIHRoZSBhdHRyaWJ1dGUgbm9kZVxuICAgICAgdmFyIHJlZiA9IHJlZmVyZW5jZXNbIGF0dHJzLnJlZiBdO1xuXG4gICAgICAvLyBpZiB0aGUgcmVmZXJlbmNlIGV4aXN0cywgbWFrZSB0aGUgbGlua1xuICAgICAgaWYgKCByZWYgKSB7XG4gICAgICAgIGRlbGV0ZSBhdHRycy5yZWY7XG5cbiAgICAgICAgLy8gYWRkIGluIHRoZSBocmVmIGFuZCB0aXRsZSwgaWYgcHJlc2VudFxuICAgICAgICBhdHRycy5ocmVmID0gcmVmLmhyZWY7XG4gICAgICAgIGlmICggcmVmLnRpdGxlICkge1xuICAgICAgICAgIGF0dHJzLnRpdGxlID0gcmVmLnRpdGxlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZ2V0IHJpZCBvZiB0aGUgdW5uZWVkZWQgb3JpZ2luYWwgdGV4dFxuICAgICAgICBkZWxldGUgYXR0cnMub3JpZ2luYWw7XG4gICAgICB9XG4gICAgICAvLyB0aGUgcmVmZXJlbmNlIGRvZXNuJ3QgZXhpc3QsIHNvIHJldmVydCB0byBwbGFpbiB0ZXh0XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGF0dHJzLm9yaWdpbmFsO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImltZ19yZWZcIjpcbiAgICAgIGpzb25tbFsgMCBdID0gXCJpbWdcIjtcblxuICAgICAgLy8gZ3JhYiB0aGlzIHJlZiBhbmQgY2xlYW4gdXAgdGhlIGF0dHJpYnV0ZSBub2RlXG4gICAgICB2YXIgcmVmID0gcmVmZXJlbmNlc1sgYXR0cnMucmVmIF07XG5cbiAgICAgIC8vIGlmIHRoZSByZWZlcmVuY2UgZXhpc3RzLCBtYWtlIHRoZSBsaW5rXG4gICAgICBpZiAoIHJlZiApIHtcbiAgICAgICAgZGVsZXRlIGF0dHJzLnJlZjtcblxuICAgICAgICAvLyBhZGQgaW4gdGhlIGhyZWYgYW5kIHRpdGxlLCBpZiBwcmVzZW50XG4gICAgICAgIGF0dHJzLnNyYyA9IHJlZi5ocmVmO1xuICAgICAgICBpZiAoIHJlZi50aXRsZSApIHtcbiAgICAgICAgICBhdHRycy50aXRsZSA9IHJlZi50aXRsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGdldCByaWQgb2YgdGhlIHVubmVlZGVkIG9yaWdpbmFsIHRleHRcbiAgICAgICAgZGVsZXRlIGF0dHJzLm9yaWdpbmFsO1xuICAgICAgfVxuICAgICAgLy8gdGhlIHJlZmVyZW5jZSBkb2Vzbid0IGV4aXN0LCBzbyByZXZlcnQgdG8gcGxhaW4gdGV4dFxuICAgICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBhdHRycy5vcmlnaW5hbDtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgLy8gY29udmVydCBhbGwgdGhlIGNoaWxkcmVuXG4gIGkgPSAxO1xuXG4gIC8vIGRlYWwgd2l0aCB0aGUgYXR0cmlidXRlIG5vZGUsIGlmIGl0IGV4aXN0c1xuICBpZiAoIGF0dHJzICkge1xuICAgIC8vIGlmIHRoZXJlIGFyZSBrZXlzLCBza2lwIG92ZXIgaXRcbiAgICBmb3IgKCB2YXIga2V5IGluIGpzb25tbFsgMSBdICkge1xuICAgICAgICBpID0gMjtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIC8vIGlmIHRoZXJlIGFyZW4ndCwgcmVtb3ZlIGl0XG4gICAgaWYgKCBpID09PSAxICkge1xuICAgICAganNvbm1sLnNwbGljZSggaSwgMSApO1xuICAgIH1cbiAgfVxuXG4gIGZvciAoIDsgaSA8IGpzb25tbC5sZW5ndGg7ICsraSApIHtcbiAgICBqc29ubWxbIGkgXSA9IGNvbnZlcnRfdHJlZV90b19odG1sKCBqc29ubWxbIGkgXSwgcmVmZXJlbmNlcywgb3B0aW9ucyApO1xuICB9XG5cbiAgcmV0dXJuIGpzb25tbDtcbn1cblxuXG4vLyBtZXJnZXMgYWRqYWNlbnQgdGV4dCBub2RlcyBpbnRvIGEgc2luZ2xlIG5vZGVcbmZ1bmN0aW9uIG1lcmdlX3RleHRfbm9kZXMoIGpzb25tbCApIHtcbiAgLy8gc2tpcCB0aGUgdGFnIG5hbWUgYW5kIGF0dHJpYnV0ZSBoYXNoXG4gIHZhciBpID0gZXh0cmFjdF9hdHRyKCBqc29ubWwgKSA/IDIgOiAxO1xuXG4gIHdoaWxlICggaSA8IGpzb25tbC5sZW5ndGggKSB7XG4gICAgLy8gaWYgaXQncyBhIHN0cmluZyBjaGVjayB0aGUgbmV4dCBpdGVtIHRvb1xuICAgIGlmICggdHlwZW9mIGpzb25tbFsgaSBdID09PSBcInN0cmluZ1wiICkge1xuICAgICAgaWYgKCBpICsgMSA8IGpzb25tbC5sZW5ndGggJiYgdHlwZW9mIGpzb25tbFsgaSArIDEgXSA9PT0gXCJzdHJpbmdcIiApIHtcbiAgICAgICAgLy8gbWVyZ2UgdGhlIHNlY29uZCBzdHJpbmcgaW50byB0aGUgZmlyc3QgYW5kIHJlbW92ZSBpdFxuICAgICAgICBqc29ubWxbIGkgXSArPSBqc29ubWwuc3BsaWNlKCBpICsgMSwgMSApWyAwIF07XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgKytpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBpZiBpdCdzIG5vdCBhIHN0cmluZyByZWN1cnNlXG4gICAgZWxzZSB7XG4gICAgICBtZXJnZV90ZXh0X25vZGVzKCBqc29ubWxbIGkgXSApO1xuICAgICAgKytpO1xuICAgIH1cbiAgfVxufVxuXG59ICkoIChmdW5jdGlvbigpIHtcbiAgaWYgKCB0eXBlb2YgZXhwb3J0cyA9PT0gXCJ1bmRlZmluZWRcIiApIHtcbiAgICB3aW5kb3cubWFya2Rvd24gPSB7fTtcbiAgICByZXR1cm4gd2luZG93Lm1hcmtkb3duO1xuICB9XG4gIGVsc2Uge1xuICAgIHJldHVybiBleHBvcnRzO1xuICB9XG59ICkoKSApO1xuIiwiKGZ1bmN0aW9uKGYpe2lmKHR5cGVvZiBleHBvcnRzPT09XCJvYmplY3RcIiYmdHlwZW9mIG1vZHVsZSE9PVwidW5kZWZpbmVkXCIpe21vZHVsZS5leHBvcnRzPWYoKX1lbHNlIGlmKHR5cGVvZiBkZWZpbmU9PT1cImZ1bmN0aW9uXCImJmRlZmluZS5hbWQpe2RlZmluZShbXSxmKX1lbHNle3ZhciBnO2lmKHR5cGVvZiB3aW5kb3chPT1cInVuZGVmaW5lZFwiKXtnPXdpbmRvd31lbHNlIGlmKHR5cGVvZiBnbG9iYWwhPT1cInVuZGVmaW5lZFwiKXtnPWdsb2JhbH1lbHNlIGlmKHR5cGVvZiBzZWxmIT09XCJ1bmRlZmluZWRcIil7Zz1zZWxmfWVsc2V7Zz10aGlzfWcudG9NYXJrZG93biA9IGYoKX19KShmdW5jdGlvbigpe3ZhciBkZWZpbmUsbW9kdWxlLGV4cG9ydHM7cmV0dXJuIChmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pKHsxOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiB0by1tYXJrZG93biAtIGFuIEhUTUwgdG8gTWFya2Rvd24gY29udmVydGVyXG4gKlxuICogQ29weXJpZ2h0IDIwMTErLCBEb20gQ2hyaXN0aWVcbiAqIExpY2VuY2VkIHVuZGVyIHRoZSBNSVQgbGljZW5jZVxuICpcbiAqL1xuXG4ndXNlIHN0cmljdCdcblxudmFyIHRvTWFya2Rvd25cbnZhciBjb252ZXJ0ZXJzXG52YXIgbWRDb252ZXJ0ZXJzID0gcmVxdWlyZSgnLi9saWIvbWQtY29udmVydGVycycpXG52YXIgZ2ZtQ29udmVydGVycyA9IHJlcXVpcmUoJy4vbGliL2dmbS1jb252ZXJ0ZXJzJylcbnZhciBIdG1sUGFyc2VyID0gcmVxdWlyZSgnLi9saWIvaHRtbC1wYXJzZXInKVxudmFyIGNvbGxhcHNlID0gcmVxdWlyZSgnY29sbGFwc2Utd2hpdGVzcGFjZScpXG5cbi8qXG4gKiBVdGlsaXRpZXNcbiAqL1xuXG52YXIgYmxvY2tzID0gWydhZGRyZXNzJywgJ2FydGljbGUnLCAnYXNpZGUnLCAnYXVkaW8nLCAnYmxvY2txdW90ZScsICdib2R5JyxcbiAgJ2NhbnZhcycsICdjZW50ZXInLCAnZGQnLCAnZGlyJywgJ2RpdicsICdkbCcsICdkdCcsICdmaWVsZHNldCcsICdmaWdjYXB0aW9uJyxcbiAgJ2ZpZ3VyZScsICdmb290ZXInLCAnZm9ybScsICdmcmFtZXNldCcsICdoMScsICdoMicsICdoMycsICdoNCcsICdoNScsICdoNicsXG4gICdoZWFkZXInLCAnaGdyb3VwJywgJ2hyJywgJ2h0bWwnLCAnaXNpbmRleCcsICdsaScsICdtYWluJywgJ21lbnUnLCAnbmF2JyxcbiAgJ25vZnJhbWVzJywgJ25vc2NyaXB0JywgJ29sJywgJ291dHB1dCcsICdwJywgJ3ByZScsICdzZWN0aW9uJywgJ3RhYmxlJyxcbiAgJ3Rib2R5JywgJ3RkJywgJ3Rmb290JywgJ3RoJywgJ3RoZWFkJywgJ3RyJywgJ3VsJ1xuXVxuXG5mdW5jdGlvbiBpc0Jsb2NrIChub2RlKSB7XG4gIHJldHVybiBibG9ja3MuaW5kZXhPZihub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkpICE9PSAtMVxufVxuXG52YXIgdm9pZHMgPSBbXG4gICdhcmVhJywgJ2Jhc2UnLCAnYnInLCAnY29sJywgJ2NvbW1hbmQnLCAnZW1iZWQnLCAnaHInLCAnaW1nJywgJ2lucHV0JyxcbiAgJ2tleWdlbicsICdsaW5rJywgJ21ldGEnLCAncGFyYW0nLCAnc291cmNlJywgJ3RyYWNrJywgJ3dicidcbl1cblxuZnVuY3Rpb24gaXNWb2lkIChub2RlKSB7XG4gIHJldHVybiB2b2lkcy5pbmRleE9mKG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSkgIT09IC0xXG59XG5cbmZ1bmN0aW9uIGh0bWxUb0RvbSAoc3RyaW5nKSB7XG4gIHZhciB0cmVlID0gbmV3IEh0bWxQYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcoc3RyaW5nLCAndGV4dC9odG1sJylcbiAgY29sbGFwc2UodHJlZS5kb2N1bWVudEVsZW1lbnQsIGlzQmxvY2spXG4gIHJldHVybiB0cmVlXG59XG5cbi8qXG4gKiBGbGF0dGVucyBET00gdHJlZSBpbnRvIHNpbmdsZSBhcnJheVxuICovXG5cbmZ1bmN0aW9uIGJmc09yZGVyIChub2RlKSB7XG4gIHZhciBpbnF1ZXVlID0gW25vZGVdXG4gIHZhciBvdXRxdWV1ZSA9IFtdXG4gIHZhciBlbGVtXG4gIHZhciBjaGlsZHJlblxuICB2YXIgaVxuXG4gIHdoaWxlIChpbnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICBlbGVtID0gaW5xdWV1ZS5zaGlmdCgpXG4gICAgb3V0cXVldWUucHVzaChlbGVtKVxuICAgIGNoaWxkcmVuID0gZWxlbS5jaGlsZE5vZGVzXG4gICAgZm9yIChpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoY2hpbGRyZW5baV0ubm9kZVR5cGUgPT09IDEpIGlucXVldWUucHVzaChjaGlsZHJlbltpXSlcbiAgICB9XG4gIH1cbiAgb3V0cXVldWUuc2hpZnQoKVxuICByZXR1cm4gb3V0cXVldWVcbn1cblxuLypcbiAqIENvbnRydWN0cyBhIE1hcmtkb3duIHN0cmluZyBvZiByZXBsYWNlbWVudCB0ZXh0IGZvciBhIGdpdmVuIG5vZGVcbiAqL1xuXG5mdW5jdGlvbiBnZXRDb250ZW50IChub2RlKSB7XG4gIHZhciB0ZXh0ID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAobm9kZS5jaGlsZE5vZGVzW2ldLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICB0ZXh0ICs9IG5vZGUuY2hpbGROb2Rlc1tpXS5fcmVwbGFjZW1lbnRcbiAgICB9IGVsc2UgaWYgKG5vZGUuY2hpbGROb2Rlc1tpXS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgdGV4dCArPSBub2RlLmNoaWxkTm9kZXNbaV0uZGF0YVxuICAgIH0gZWxzZSBjb250aW51ZVxuICB9XG4gIHJldHVybiB0ZXh0XG59XG5cbi8qXG4gKiBSZXR1cm5zIHRoZSBIVE1MIHN0cmluZyBvZiBhbiBlbGVtZW50IHdpdGggaXRzIGNvbnRlbnRzIGNvbnZlcnRlZFxuICovXG5cbmZ1bmN0aW9uIG91dGVyIChub2RlLCBjb250ZW50KSB7XG4gIHJldHVybiBub2RlLmNsb25lTm9kZShmYWxzZSkub3V0ZXJIVE1MLnJlcGxhY2UoJz48JywgJz4nICsgY29udGVudCArICc8Jylcbn1cblxuZnVuY3Rpb24gY2FuQ29udmVydCAobm9kZSwgZmlsdGVyKSB7XG4gIGlmICh0eXBlb2YgZmlsdGVyID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmaWx0ZXIgPT09IG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKVxuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KGZpbHRlcikpIHtcbiAgICByZXR1cm4gZmlsdGVyLmluZGV4T2Yobm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSAhPT0gLTFcbiAgfSBlbHNlIGlmICh0eXBlb2YgZmlsdGVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGZpbHRlci5jYWxsKHRvTWFya2Rvd24sIG5vZGUpXG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYGZpbHRlcmAgbmVlZHMgdG8gYmUgYSBzdHJpbmcsIGFycmF5LCBvciBmdW5jdGlvbicpXG4gIH1cbn1cblxuZnVuY3Rpb24gaXNGbGFua2VkQnlXaGl0ZXNwYWNlIChzaWRlLCBub2RlKSB7XG4gIHZhciBzaWJsaW5nXG4gIHZhciByZWdFeHBcbiAgdmFyIGlzRmxhbmtlZFxuXG4gIGlmIChzaWRlID09PSAnbGVmdCcpIHtcbiAgICBzaWJsaW5nID0gbm9kZS5wcmV2aW91c1NpYmxpbmdcbiAgICByZWdFeHAgPSAvICQvXG4gIH0gZWxzZSB7XG4gICAgc2libGluZyA9IG5vZGUubmV4dFNpYmxpbmdcbiAgICByZWdFeHAgPSAvXiAvXG4gIH1cblxuICBpZiAoc2libGluZykge1xuICAgIGlmIChzaWJsaW5nLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICBpc0ZsYW5rZWQgPSByZWdFeHAudGVzdChzaWJsaW5nLm5vZGVWYWx1ZSlcbiAgICB9IGVsc2UgaWYgKHNpYmxpbmcubm9kZVR5cGUgPT09IDEgJiYgIWlzQmxvY2soc2libGluZykpIHtcbiAgICAgIGlzRmxhbmtlZCA9IHJlZ0V4cC50ZXN0KHNpYmxpbmcudGV4dENvbnRlbnQpXG4gICAgfVxuICB9XG4gIHJldHVybiBpc0ZsYW5rZWRcbn1cblxuZnVuY3Rpb24gZmxhbmtpbmdXaGl0ZXNwYWNlIChub2RlLCBjb250ZW50KSB7XG4gIHZhciBsZWFkaW5nID0gJydcbiAgdmFyIHRyYWlsaW5nID0gJydcblxuICBpZiAoIWlzQmxvY2sobm9kZSkpIHtcbiAgICB2YXIgaGFzTGVhZGluZyA9IC9eWyBcXHJcXG5cXHRdLy50ZXN0KGNvbnRlbnQpXG4gICAgdmFyIGhhc1RyYWlsaW5nID0gL1sgXFxyXFxuXFx0XSQvLnRlc3QoY29udGVudClcblxuICAgIGlmIChoYXNMZWFkaW5nICYmICFpc0ZsYW5rZWRCeVdoaXRlc3BhY2UoJ2xlZnQnLCBub2RlKSkge1xuICAgICAgbGVhZGluZyA9ICcgJ1xuICAgIH1cbiAgICBpZiAoaGFzVHJhaWxpbmcgJiYgIWlzRmxhbmtlZEJ5V2hpdGVzcGFjZSgncmlnaHQnLCBub2RlKSkge1xuICAgICAgdHJhaWxpbmcgPSAnICdcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBsZWFkaW5nOiBsZWFkaW5nLCB0cmFpbGluZzogdHJhaWxpbmcgfVxufVxuXG4vKlxuICogRmluZHMgYSBNYXJrZG93biBjb252ZXJ0ZXIsIGdldHMgdGhlIHJlcGxhY2VtZW50LCBhbmQgc2V0cyBpdCBvblxuICogYF9yZXBsYWNlbWVudGBcbiAqL1xuXG5mdW5jdGlvbiBwcm9jZXNzIChub2RlKSB7XG4gIHZhciByZXBsYWNlbWVudFxuICB2YXIgY29udGVudCA9IGdldENvbnRlbnQobm9kZSlcblxuICAvLyBSZW1vdmUgYmxhbmsgbm9kZXNcbiAgaWYgKCFpc1ZvaWQobm9kZSkgJiYgIS9BfFRIfFRELy50ZXN0KG5vZGUubm9kZU5hbWUpICYmIC9eXFxzKiQvaS50ZXN0KGNvbnRlbnQpKSB7XG4gICAgbm9kZS5fcmVwbGFjZW1lbnQgPSAnJ1xuICAgIHJldHVyblxuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb252ZXJ0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGNvbnZlcnRlciA9IGNvbnZlcnRlcnNbaV1cblxuICAgIGlmIChjYW5Db252ZXJ0KG5vZGUsIGNvbnZlcnRlci5maWx0ZXIpKSB7XG4gICAgICBpZiAodHlwZW9mIGNvbnZlcnRlci5yZXBsYWNlbWVudCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICdgcmVwbGFjZW1lbnRgIG5lZWRzIHRvIGJlIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgc3RyaW5nJ1xuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIHZhciB3aGl0ZXNwYWNlID0gZmxhbmtpbmdXaGl0ZXNwYWNlKG5vZGUsIGNvbnRlbnQpXG5cbiAgICAgIGlmICh3aGl0ZXNwYWNlLmxlYWRpbmcgfHwgd2hpdGVzcGFjZS50cmFpbGluZykge1xuICAgICAgICBjb250ZW50ID0gY29udGVudC50cmltKClcbiAgICAgIH1cbiAgICAgIHJlcGxhY2VtZW50ID0gd2hpdGVzcGFjZS5sZWFkaW5nICtcbiAgICAgICAgY29udmVydGVyLnJlcGxhY2VtZW50LmNhbGwodG9NYXJrZG93biwgY29udGVudCwgbm9kZSkgK1xuICAgICAgICB3aGl0ZXNwYWNlLnRyYWlsaW5nXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIG5vZGUuX3JlcGxhY2VtZW50ID0gcmVwbGFjZW1lbnRcbn1cblxudG9NYXJrZG93biA9IGZ1bmN0aW9uIChpbnB1dCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIGlmICh0eXBlb2YgaW5wdXQgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihpbnB1dCArICcgaXMgbm90IGEgc3RyaW5nJylcbiAgfVxuXG4gIGlmIChpbnB1dCA9PT0gJycpIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIC8vIEVzY2FwZSBwb3RlbnRpYWwgb2wgdHJpZ2dlcnNcbiAgaW5wdXQgPSBpbnB1dC5yZXBsYWNlKC8oXFxkKylcXC4gL2csICckMVxcXFwuICcpXG5cbiAgdmFyIGNsb25lID0gaHRtbFRvRG9tKGlucHV0KS5ib2R5XG4gIHZhciBub2RlcyA9IGJmc09yZGVyKGNsb25lKVxuICB2YXIgb3V0cHV0XG5cbiAgY29udmVydGVycyA9IG1kQ29udmVydGVycy5zbGljZSgwKVxuICBpZiAob3B0aW9ucy5nZm0pIHtcbiAgICBjb252ZXJ0ZXJzID0gZ2ZtQ29udmVydGVycy5jb25jYXQoY29udmVydGVycylcbiAgfVxuXG4gIGlmIChvcHRpb25zLmNvbnZlcnRlcnMpIHtcbiAgICBjb252ZXJ0ZXJzID0gb3B0aW9ucy5jb252ZXJ0ZXJzLmNvbmNhdChjb252ZXJ0ZXJzKVxuICB9XG5cbiAgLy8gUHJvY2VzcyB0aHJvdWdoIG5vZGVzIGluIHJldmVyc2UgKHNvIGRlZXBlc3QgY2hpbGQgZWxlbWVudHMgYXJlIGZpcnN0KS5cbiAgZm9yICh2YXIgaSA9IG5vZGVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgcHJvY2Vzcyhub2Rlc1tpXSlcbiAgfVxuICBvdXRwdXQgPSBnZXRDb250ZW50KGNsb25lKVxuXG4gIHJldHVybiBvdXRwdXQucmVwbGFjZSgvXltcXHRcXHJcXG5dK3xbXFx0XFxyXFxuXFxzXSskL2csICcnKVxuICAgIC5yZXBsYWNlKC9cXG5cXHMrXFxuL2csICdcXG5cXG4nKVxuICAgIC5yZXBsYWNlKC9cXG57Myx9L2csICdcXG5cXG4nKVxufVxuXG50b01hcmtkb3duLmlzQmxvY2sgPSBpc0Jsb2NrXG50b01hcmtkb3duLmlzVm9pZCA9IGlzVm9pZFxudG9NYXJrZG93bi5vdXRlciA9IG91dGVyXG5cbm1vZHVsZS5leHBvcnRzID0gdG9NYXJrZG93blxuXG59LHtcIi4vbGliL2dmbS1jb252ZXJ0ZXJzXCI6MixcIi4vbGliL2h0bWwtcGFyc2VyXCI6MyxcIi4vbGliL21kLWNvbnZlcnRlcnNcIjo0LFwiY29sbGFwc2Utd2hpdGVzcGFjZVwiOjd9XSwyOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5mdW5jdGlvbiBjZWxsIChjb250ZW50LCBub2RlKSB7XG4gIHZhciBpbmRleCA9IEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwobm9kZS5wYXJlbnROb2RlLmNoaWxkTm9kZXMsIG5vZGUpXG4gIHZhciBwcmVmaXggPSAnICdcbiAgaWYgKGluZGV4ID09PSAwKSBwcmVmaXggPSAnfCAnXG4gIHJldHVybiBwcmVmaXggKyBjb250ZW50ICsgJyB8J1xufVxuXG52YXIgaGlnaGxpZ2h0UmVnRXggPSAvaGlnaGxpZ2h0IGhpZ2hsaWdodC0oXFxTKykvXG5cbm1vZHVsZS5leHBvcnRzID0gW1xuICB7XG4gICAgZmlsdGVyOiAnYnInLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ1xcbidcbiAgICB9XG4gIH0sXG4gIHtcbiAgICBmaWx0ZXI6IFsnZGVsJywgJ3MnLCAnc3RyaWtlJ10sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJ35+JyArIGNvbnRlbnQgKyAnfn4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS50eXBlID09PSAnY2hlY2tib3gnICYmIG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSA9PT0gJ0xJJ1xuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gKG5vZGUuY2hlY2tlZCA/ICdbeF0nIDogJ1sgXScpICsgJyAnXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsndGgnLCAndGQnXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHJldHVybiBjZWxsKGNvbnRlbnQsIG5vZGUpXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICd0cicsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICB2YXIgYm9yZGVyQ2VsbHMgPSAnJ1xuICAgICAgdmFyIGFsaWduTWFwID0geyBsZWZ0OiAnOi0tJywgcmlnaHQ6ICctLTonLCBjZW50ZXI6ICc6LTonIH1cblxuICAgICAgaWYgKG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSA9PT0gJ1RIRUFEJykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBhbGlnbiA9IG5vZGUuY2hpbGROb2Rlc1tpXS5hdHRyaWJ1dGVzLmFsaWduXG4gICAgICAgICAgdmFyIGJvcmRlciA9ICctLS0nXG5cbiAgICAgICAgICBpZiAoYWxpZ24pIGJvcmRlciA9IGFsaWduTWFwW2FsaWduLnZhbHVlXSB8fCBib3JkZXJcblxuICAgICAgICAgIGJvcmRlckNlbGxzICs9IGNlbGwoYm9yZGVyLCBub2RlLmNoaWxkTm9kZXNbaV0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAnXFxuJyArIGNvbnRlbnQgKyAoYm9yZGVyQ2VsbHMgPyAnXFxuJyArIGJvcmRlckNlbGxzIDogJycpXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICd0YWJsZScsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgICByZXR1cm4gJ1xcblxcbicgKyBjb250ZW50ICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogWyd0aGVhZCcsICd0Ym9keScsICd0Zm9vdCddLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuIGNvbnRlbnRcbiAgICB9XG4gIH0sXG5cbiAgLy8gRmVuY2VkIGNvZGUgYmxvY2tzXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ1BSRScgJiZcbiAgICAgIG5vZGUuZmlyc3RDaGlsZCAmJlxuICAgICAgbm9kZS5maXJzdENoaWxkLm5vZGVOYW1lID09PSAnQ09ERSdcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgcmV0dXJuICdcXG5cXG5gYGBcXG4nICsgbm9kZS5maXJzdENoaWxkLnRleHRDb250ZW50ICsgJ1xcbmBgYFxcblxcbidcbiAgICB9XG4gIH0sXG5cbiAgLy8gU3ludGF4LWhpZ2hsaWdodGVkIGNvZGUgYmxvY2tzXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ1BSRScgJiZcbiAgICAgIG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSA9PT0gJ0RJVicgJiZcbiAgICAgIGhpZ2hsaWdodFJlZ0V4LnRlc3Qobm9kZS5wYXJlbnROb2RlLmNsYXNzTmFtZSlcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgdmFyIGxhbmd1YWdlID0gbm9kZS5wYXJlbnROb2RlLmNsYXNzTmFtZS5tYXRjaChoaWdobGlnaHRSZWdFeClbMV1cbiAgICAgIHJldHVybiAnXFxuXFxuYGBgJyArIGxhbmd1YWdlICsgJ1xcbicgKyBub2RlLnRleHRDb250ZW50ICsgJ1xcbmBgYFxcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnRElWJyAmJlxuICAgICAgaGlnaGxpZ2h0UmVnRXgudGVzdChub2RlLmNsYXNzTmFtZSlcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICdcXG5cXG4nICsgY29udGVudCArICdcXG5cXG4nXG4gICAgfVxuICB9XG5dXG5cbn0se31dLDM6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFNldCB1cCB3aW5kb3cgZm9yIE5vZGUuanNcbiAqL1xuXG52YXIgX3dpbmRvdyA9ICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMpXG5cbi8qXG4gKiBQYXJzaW5nIEhUTUwgc3RyaW5nc1xuICovXG5cbmZ1bmN0aW9uIGNhblBhcnNlSHRtbE5hdGl2ZWx5ICgpIHtcbiAgdmFyIFBhcnNlciA9IF93aW5kb3cuRE9NUGFyc2VyXG4gIHZhciBjYW5QYXJzZSA9IGZhbHNlXG5cbiAgLy8gQWRhcHRlZCBmcm9tIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tLzExMjkwMzFcbiAgLy8gRmlyZWZveC9PcGVyYS9JRSB0aHJvdyBlcnJvcnMgb24gdW5zdXBwb3J0ZWQgdHlwZXNcbiAgdHJ5IHtcbiAgICAvLyBXZWJLaXQgcmV0dXJucyBudWxsIG9uIHVuc3VwcG9ydGVkIHR5cGVzXG4gICAgaWYgKG5ldyBQYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcoJycsICd0ZXh0L2h0bWwnKSkge1xuICAgICAgY2FuUGFyc2UgPSB0cnVlXG4gICAgfVxuICB9IGNhdGNoIChlKSB7fVxuXG4gIHJldHVybiBjYW5QYXJzZVxufVxuXG5mdW5jdGlvbiBjcmVhdGVIdG1sUGFyc2VyICgpIHtcbiAgdmFyIFBhcnNlciA9IGZ1bmN0aW9uICgpIHt9XG5cbiAgLy8gRm9yIE5vZGUuanMgZW52aXJvbm1lbnRzXG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdmFyIGpzZG9tID0gcmVxdWlyZSgnanNkb20nKVxuICAgIFBhcnNlci5wcm90b3R5cGUucGFyc2VGcm9tU3RyaW5nID0gZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgcmV0dXJuIGpzZG9tLmpzZG9tKHN0cmluZywge1xuICAgICAgICBmZWF0dXJlczoge1xuICAgICAgICAgIEZldGNoRXh0ZXJuYWxSZXNvdXJjZXM6IFtdLFxuICAgICAgICAgIFByb2Nlc3NFeHRlcm5hbFJlc291cmNlczogZmFsc2VcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFzaG91bGRVc2VBY3RpdmVYKCkpIHtcbiAgICAgIFBhcnNlci5wcm90b3R5cGUucGFyc2VGcm9tU3RyaW5nID0gZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICB2YXIgZG9jID0gZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCcnKVxuICAgICAgICBkb2Mub3BlbigpXG4gICAgICAgIGRvYy53cml0ZShzdHJpbmcpXG4gICAgICAgIGRvYy5jbG9zZSgpXG4gICAgICAgIHJldHVybiBkb2NcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgUGFyc2VyLnByb3RvdHlwZS5wYXJzZUZyb21TdHJpbmcgPSBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHZhciBkb2MgPSBuZXcgd2luZG93LkFjdGl2ZVhPYmplY3QoJ2h0bWxmaWxlJylcbiAgICAgICAgZG9jLmRlc2lnbk1vZGUgPSAnb24nIC8vIGRpc2FibGUgb24tcGFnZSBzY3JpcHRzXG4gICAgICAgIGRvYy5vcGVuKClcbiAgICAgICAgZG9jLndyaXRlKHN0cmluZylcbiAgICAgICAgZG9jLmNsb3NlKClcbiAgICAgICAgcmV0dXJuIGRvY1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gUGFyc2VyXG59XG5cbmZ1bmN0aW9uIHNob3VsZFVzZUFjdGl2ZVggKCkge1xuICB2YXIgdXNlQWN0aXZlWCA9IGZhbHNlXG5cbiAgdHJ5IHtcbiAgICBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoJycpLm9wZW4oKVxuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKHdpbmRvdy5BY3RpdmVYT2JqZWN0KSB1c2VBY3RpdmVYID0gdHJ1ZVxuICB9XG5cbiAgcmV0dXJuIHVzZUFjdGl2ZVhcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjYW5QYXJzZUh0bWxOYXRpdmVseSgpID8gX3dpbmRvdy5ET01QYXJzZXIgOiBjcmVhdGVIdG1sUGFyc2VyKClcblxufSx7XCJqc2RvbVwiOjZ9XSw0OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IFtcbiAge1xuICAgIGZpbHRlcjogJ3AnLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgcmV0dXJuICdcXG5cXG4nICsgY29udGVudCArICdcXG5cXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6ICdicicsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnICBcXG4nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsnaDEnLCAnaDInLCAnaDMnLCAnaDQnLCAnaDUnLCAnaDYnXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHZhciBoTGV2ZWwgPSBub2RlLm5vZGVOYW1lLmNoYXJBdCgxKVxuICAgICAgdmFyIGhQcmVmaXggPSAnJ1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoTGV2ZWw7IGkrKykge1xuICAgICAgICBoUHJlZml4ICs9ICcjJ1xuICAgICAgfVxuICAgICAgcmV0dXJuICdcXG5cXG4nICsgaFByZWZpeCArICcgJyArIGNvbnRlbnQgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAnaHInLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ1xcblxcbiogKiAqXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBbJ2VtJywgJ2knXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnXycgKyBjb250ZW50ICsgJ18nXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsnc3Ryb25nJywgJ2InXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnKionICsgY29udGVudCArICcqKidcbiAgICB9XG4gIH0sXG5cbiAgLy8gSW5saW5lIGNvZGVcbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHZhciBoYXNTaWJsaW5ncyA9IG5vZGUucHJldmlvdXNTaWJsaW5nIHx8IG5vZGUubmV4dFNpYmxpbmdcbiAgICAgIHZhciBpc0NvZGVCbG9jayA9IG5vZGUucGFyZW50Tm9kZS5ub2RlTmFtZSA9PT0gJ1BSRScgJiYgIWhhc1NpYmxpbmdzXG5cbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnQ09ERScgJiYgIWlzQ29kZUJsb2NrXG4gICAgfSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgIHJldHVybiAnYCcgKyBjb250ZW50ICsgJ2AnXG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICByZXR1cm4gbm9kZS5ub2RlTmFtZSA9PT0gJ0EnICYmIG5vZGUuZ2V0QXR0cmlidXRlKCdocmVmJylcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgdmFyIHRpdGxlUGFydCA9IG5vZGUudGl0bGUgPyAnIFwiJyArIG5vZGUudGl0bGUgKyAnXCInIDogJydcbiAgICAgIHJldHVybiAnWycgKyBjb250ZW50ICsgJ10oJyArIG5vZGUuZ2V0QXR0cmlidXRlKCdocmVmJykgKyB0aXRsZVBhcnQgKyAnKSdcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ2ltZycsXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICB2YXIgYWx0ID0gbm9kZS5hbHQgfHwgJydcbiAgICAgIHZhciBzcmMgPSBub2RlLmdldEF0dHJpYnV0ZSgnc3JjJykgfHwgJydcbiAgICAgIHZhciB0aXRsZSA9IG5vZGUudGl0bGUgfHwgJydcbiAgICAgIHZhciB0aXRsZVBhcnQgPSB0aXRsZSA/ICcgXCInICsgdGl0bGUgKyAnXCInIDogJydcbiAgICAgIHJldHVybiBzcmMgPyAnIVsnICsgYWx0ICsgJ10nICsgJygnICsgc3JjICsgdGl0bGVQYXJ0ICsgJyknIDogJydcbiAgICB9XG4gIH0sXG5cbiAgLy8gQ29kZSBibG9ja3NcbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIHJldHVybiBub2RlLm5vZGVOYW1lID09PSAnUFJFJyAmJiBub2RlLmZpcnN0Q2hpbGQubm9kZU5hbWUgPT09ICdDT0RFJ1xuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gJ1xcblxcbiAgICAnICsgbm9kZS5maXJzdENoaWxkLnRleHRDb250ZW50LnJlcGxhY2UoL1xcbi9nLCAnXFxuICAgICcpICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAge1xuICAgIGZpbHRlcjogJ2Jsb2NrcXVvdGUnLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgY29udGVudCA9IGNvbnRlbnQudHJpbSgpXG4gICAgICBjb250ZW50ID0gY29udGVudC5yZXBsYWNlKC9cXG57Myx9L2csICdcXG5cXG4nKVxuICAgICAgY29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvXi9nbSwgJz4gJylcbiAgICAgIHJldHVybiAnXFxuXFxuJyArIGNvbnRlbnQgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiAnbGknLFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgY29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvXlxccysvLCAnJykucmVwbGFjZSgvXFxuL2dtLCAnXFxuICAgICcpXG4gICAgICB2YXIgcHJlZml4ID0gJyogICAnXG4gICAgICB2YXIgcGFyZW50ID0gbm9kZS5wYXJlbnROb2RlXG4gICAgICB2YXIgaW5kZXggPSBBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKHBhcmVudC5jaGlsZHJlbiwgbm9kZSkgKyAxXG5cbiAgICAgIHByZWZpeCA9IC9vbC9pLnRlc3QocGFyZW50Lm5vZGVOYW1lKSA/IGluZGV4ICsgJy4gICcgOiAnKiAgICdcbiAgICAgIHJldHVybiBwcmVmaXggKyBjb250ZW50XG4gICAgfVxuICB9LFxuXG4gIHtcbiAgICBmaWx0ZXI6IFsndWwnLCAnb2wnXSxcbiAgICByZXBsYWNlbWVudDogZnVuY3Rpb24gKGNvbnRlbnQsIG5vZGUpIHtcbiAgICAgIHZhciBzdHJpbmdzID0gW11cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHN0cmluZ3MucHVzaChub2RlLmNoaWxkTm9kZXNbaV0uX3JlcGxhY2VtZW50KVxuICAgICAgfVxuXG4gICAgICBpZiAoL2xpL2kudGVzdChub2RlLnBhcmVudE5vZGUubm9kZU5hbWUpKSB7XG4gICAgICAgIHJldHVybiAnXFxuJyArIHN0cmluZ3Muam9pbignXFxuJylcbiAgICAgIH1cbiAgICAgIHJldHVybiAnXFxuXFxuJyArIHN0cmluZ3Muam9pbignXFxuJykgKyAnXFxuXFxuJ1xuICAgIH1cbiAgfSxcblxuICB7XG4gICAgZmlsdGVyOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgcmV0dXJuIHRoaXMuaXNCbG9jayhub2RlKVxuICAgIH0sXG4gICAgcmVwbGFjZW1lbnQ6IGZ1bmN0aW9uIChjb250ZW50LCBub2RlKSB7XG4gICAgICByZXR1cm4gJ1xcblxcbicgKyB0aGlzLm91dGVyKG5vZGUsIGNvbnRlbnQpICsgJ1xcblxcbidcbiAgICB9XG4gIH0sXG5cbiAgLy8gQW55dGhpbmcgZWxzZSFcbiAge1xuICAgIGZpbHRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9LFxuICAgIHJlcGxhY2VtZW50OiBmdW5jdGlvbiAoY29udGVudCwgbm9kZSkge1xuICAgICAgcmV0dXJuIHRoaXMub3V0ZXIobm9kZSwgY29udGVudClcbiAgICB9XG4gIH1cbl1cblxufSx7fV0sNTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiAqIFRoaXMgZmlsZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBmcm9tIGBidWlsZC5qc2AuXG4gKiBEbyBub3QgbWFudWFsbHkgZWRpdC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IFtcbiAgXCJhZGRyZXNzXCIsXG4gIFwiYXJ0aWNsZVwiLFxuICBcImFzaWRlXCIsXG4gIFwiYXVkaW9cIixcbiAgXCJibG9ja3F1b3RlXCIsXG4gIFwiY2FudmFzXCIsXG4gIFwiZGRcIixcbiAgXCJkaXZcIixcbiAgXCJkbFwiLFxuICBcImZpZWxkc2V0XCIsXG4gIFwiZmlnY2FwdGlvblwiLFxuICBcImZpZ3VyZVwiLFxuICBcImZvb3RlclwiLFxuICBcImZvcm1cIixcbiAgXCJoMVwiLFxuICBcImgyXCIsXG4gIFwiaDNcIixcbiAgXCJoNFwiLFxuICBcImg1XCIsXG4gIFwiaDZcIixcbiAgXCJoZWFkZXJcIixcbiAgXCJoZ3JvdXBcIixcbiAgXCJoclwiLFxuICBcIm1haW5cIixcbiAgXCJuYXZcIixcbiAgXCJub3NjcmlwdFwiLFxuICBcIm9sXCIsXG4gIFwib3V0cHV0XCIsXG4gIFwicFwiLFxuICBcInByZVwiLFxuICBcInNlY3Rpb25cIixcbiAgXCJ0YWJsZVwiLFxuICBcInRmb290XCIsXG4gIFwidWxcIixcbiAgXCJ2aWRlb1wiXG5dO1xuXG59LHt9XSw2OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcblxufSx7fV0sNzpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCc7XG5cbnZhciB2b2lkRWxlbWVudHMgPSByZXF1aXJlKCd2b2lkLWVsZW1lbnRzJyk7XG5PYmplY3Qua2V5cyh2b2lkRWxlbWVudHMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgdm9pZEVsZW1lbnRzW25hbWUudG9VcHBlckNhc2UoKV0gPSAxO1xufSk7XG5cbnZhciBibG9ja0VsZW1lbnRzID0ge307XG5yZXF1aXJlKCdibG9jay1lbGVtZW50cycpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgYmxvY2tFbGVtZW50c1tuYW1lLnRvVXBwZXJDYXNlKCldID0gMTtcbn0pO1xuXG4vKipcbiAqIGlzQmxvY2tFbGVtKG5vZGUpIGRldGVybWluZXMgaWYgdGhlIGdpdmVuIG5vZGUgaXMgYSBibG9jayBlbGVtZW50LlxuICpcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNCbG9ja0VsZW0obm9kZSkge1xuICByZXR1cm4gISEobm9kZSAmJiBibG9ja0VsZW1lbnRzW25vZGUubm9kZU5hbWVdKTtcbn1cblxuLyoqXG4gKiBpc1ZvaWQobm9kZSkgZGV0ZXJtaW5lcyBpZiB0aGUgZ2l2ZW4gbm9kZSBpcyBhIHZvaWQgZWxlbWVudC5cbiAqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGVcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzVm9pZChub2RlKSB7XG4gIHJldHVybiAhIShub2RlICYmIHZvaWRFbGVtZW50c1tub2RlLm5vZGVOYW1lXSk7XG59XG5cbi8qKlxuICogd2hpdGVzcGFjZShlbGVtIFssIGlzQmxvY2tdKSByZW1vdmVzIGV4dHJhbmVvdXMgd2hpdGVzcGFjZSBmcm9tIGFuXG4gKiB0aGUgZ2l2ZW4gZWxlbWVudC4gVGhlIGZ1bmN0aW9uIGlzQmxvY2sgbWF5IG9wdGlvbmFsbHkgYmUgcGFzc2VkIGluXG4gKiB0byBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgYW4gZWxlbWVudCBpcyBhIGJsb2NrIGVsZW1lbnQ7IGlmIG5vbmVcbiAqIGlzIHByb3ZpZGVkLCBkZWZhdWx0cyB0byB1c2luZyB0aGUgbGlzdCBvZiBibG9jayBlbGVtZW50cyBwcm92aWRlZFxuICogYnkgdGhlIGBibG9jay1lbGVtZW50c2AgbW9kdWxlLlxuICpcbiAqIEBwYXJhbSB7Tm9kZX0gZWxlbVxuICogQHBhcmFtIHtGdW5jdGlvbn0gYmxvY2tUZXN0XG4gKi9cbmZ1bmN0aW9uIGNvbGxhcHNlV2hpdGVzcGFjZShlbGVtLCBpc0Jsb2NrKSB7XG4gIGlmICghZWxlbS5maXJzdENoaWxkIHx8IGVsZW0ubm9kZU5hbWUgPT09ICdQUkUnKSByZXR1cm47XG5cbiAgaWYgKHR5cGVvZiBpc0Jsb2NrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgaXNCbG9jayA9IGlzQmxvY2tFbGVtO1xuICB9XG5cbiAgdmFyIHByZXZUZXh0ID0gbnVsbDtcbiAgdmFyIHByZXZWb2lkID0gZmFsc2U7XG5cbiAgdmFyIHByZXYgPSBudWxsO1xuICB2YXIgbm9kZSA9IG5leHQocHJldiwgZWxlbSk7XG5cbiAgd2hpbGUgKG5vZGUgIT09IGVsZW0pIHtcbiAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgLy8gTm9kZS5URVhUX05PREVcbiAgICAgIHZhciB0ZXh0ID0gbm9kZS5kYXRhLnJlcGxhY2UoL1sgXFxyXFxuXFx0XSsvZywgJyAnKTtcblxuICAgICAgaWYgKCghcHJldlRleHQgfHwgLyAkLy50ZXN0KHByZXZUZXh0LmRhdGEpKSAmJiAhcHJldlZvaWQgJiYgdGV4dFswXSA9PT0gJyAnKSB7XG4gICAgICAgIHRleHQgPSB0ZXh0LnN1YnN0cigxKTtcbiAgICAgIH1cblxuICAgICAgLy8gYHRleHRgIG1pZ2h0IGJlIGVtcHR5IGF0IHRoaXMgcG9pbnQuXG4gICAgICBpZiAoIXRleHQpIHtcbiAgICAgICAgbm9kZSA9IHJlbW92ZShub2RlKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIG5vZGUuZGF0YSA9IHRleHQ7XG4gICAgICBwcmV2VGV4dCA9IG5vZGU7XG4gICAgfSBlbHNlIGlmIChub2RlLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICAvLyBOb2RlLkVMRU1FTlRfTk9ERVxuICAgICAgaWYgKGlzQmxvY2sobm9kZSkgfHwgbm9kZS5ub2RlTmFtZSA9PT0gJ0JSJykge1xuICAgICAgICBpZiAocHJldlRleHQpIHtcbiAgICAgICAgICBwcmV2VGV4dC5kYXRhID0gcHJldlRleHQuZGF0YS5yZXBsYWNlKC8gJC8sICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByZXZUZXh0ID0gbnVsbDtcbiAgICAgICAgcHJldlZvaWQgPSBmYWxzZTtcbiAgICAgIH0gZWxzZSBpZiAoaXNWb2lkKG5vZGUpKSB7XG4gICAgICAgIC8vIEF2b2lkIHRyaW1taW5nIHNwYWNlIGFyb3VuZCBub24tYmxvY2ssIG5vbi1CUiB2b2lkIGVsZW1lbnRzLlxuICAgICAgICBwcmV2VGV4dCA9IG51bGw7XG4gICAgICAgIHByZXZWb2lkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbm9kZSA9IHJlbW92ZShub2RlKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBuZXh0Tm9kZSA9IG5leHQocHJldiwgbm9kZSk7XG4gICAgcHJldiA9IG5vZGU7XG4gICAgbm9kZSA9IG5leHROb2RlO1xuICB9XG5cbiAgaWYgKHByZXZUZXh0KSB7XG4gICAgcHJldlRleHQuZGF0YSA9IHByZXZUZXh0LmRhdGEucmVwbGFjZSgvICQvLCAnJyk7XG4gICAgaWYgKCFwcmV2VGV4dC5kYXRhKSB7XG4gICAgICByZW1vdmUocHJldlRleHQpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIHJlbW92ZShub2RlKSByZW1vdmVzIHRoZSBnaXZlbiBub2RlIGZyb20gdGhlIERPTSBhbmQgcmV0dXJucyB0aGVcbiAqIG5leHQgbm9kZSBpbiB0aGUgc2VxdWVuY2UuXG4gKlxuICogQHBhcmFtIHtOb2RlfSBub2RlXG4gKiBAcmV0dXJuIHtOb2RlfSBub2RlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZShub2RlKSB7XG4gIHZhciBuZXh0ID0gbm9kZS5uZXh0U2libGluZyB8fCBub2RlLnBhcmVudE5vZGU7XG5cbiAgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuXG4gIHJldHVybiBuZXh0O1xufVxuXG4vKipcbiAqIG5leHQocHJldiwgY3VycmVudCkgcmV0dXJucyB0aGUgbmV4dCBub2RlIGluIHRoZSBzZXF1ZW5jZSwgZ2l2ZW4gdGhlXG4gKiBjdXJyZW50IGFuZCBwcmV2aW91cyBub2Rlcy5cbiAqXG4gKiBAcGFyYW0ge05vZGV9IHByZXZcbiAqIEBwYXJhbSB7Tm9kZX0gY3VycmVudFxuICogQHJldHVybiB7Tm9kZX1cbiAqL1xuZnVuY3Rpb24gbmV4dChwcmV2LCBjdXJyZW50KSB7XG4gIGlmIChwcmV2ICYmIHByZXYucGFyZW50Tm9kZSA9PT0gY3VycmVudCB8fCBjdXJyZW50Lm5vZGVOYW1lID09PSAnUFJFJykge1xuICAgIHJldHVybiBjdXJyZW50Lm5leHRTaWJsaW5nIHx8IGN1cnJlbnQucGFyZW50Tm9kZTtcbiAgfVxuXG4gIHJldHVybiBjdXJyZW50LmZpcnN0Q2hpbGQgfHwgY3VycmVudC5uZXh0U2libGluZyB8fCBjdXJyZW50LnBhcmVudE5vZGU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY29sbGFwc2VXaGl0ZXNwYWNlO1xuXG59LHtcImJsb2NrLWVsZW1lbnRzXCI6NSxcInZvaWQtZWxlbWVudHNcIjo4fV0sODpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiAqIFRoaXMgZmlsZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBmcm9tIGBwcmUtcHVibGlzaC5qc2AuXG4gKiBEbyBub3QgbWFudWFsbHkgZWRpdC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgXCJhcmVhXCI6IHRydWUsXG4gIFwiYmFzZVwiOiB0cnVlLFxuICBcImJyXCI6IHRydWUsXG4gIFwiY29sXCI6IHRydWUsXG4gIFwiZW1iZWRcIjogdHJ1ZSxcbiAgXCJoclwiOiB0cnVlLFxuICBcImltZ1wiOiB0cnVlLFxuICBcImlucHV0XCI6IHRydWUsXG4gIFwia2V5Z2VuXCI6IHRydWUsXG4gIFwibGlua1wiOiB0cnVlLFxuICBcIm1lbnVpdGVtXCI6IHRydWUsXG4gIFwibWV0YVwiOiB0cnVlLFxuICBcInBhcmFtXCI6IHRydWUsXG4gIFwic291cmNlXCI6IHRydWUsXG4gIFwidHJhY2tcIjogdHJ1ZSxcbiAgXCJ3YnJcIjogdHJ1ZVxufTtcblxufSx7fV19LHt9LFsxXSkoMSlcbn0pOyIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogYm9vdHN0cmFwLW1hcmtkb3duLmpzIHYyLjEwLjBcbiAqIGh0dHA6Ly9naXRodWIuY29tL3Rvb3BheS9ib290c3RyYXAtbWFya2Rvd25cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29weXJpZ2h0IDIwMTMtMjAxNiBUYXVmYW4gQWRpdHlhXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cbihmdW5jdGlvbihmYWN0b3J5KXtcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgLy9SZXF1aXJlSlNcbiAgICAgICAgZGVmaW5lKFtcImpxdWVyeVwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgLy9CYWNrYm9uZS5qc1xuICAgICAgICBmYWN0b3J5KHJlcXVpcmUoJ2pxdWVyeScpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvL0pxdWVyeSBwbHVnaW5cbiAgICAgICAgZmFjdG9yeShqUXVlcnkpO1xuICAgIH1cbn0oZnVuY3Rpb24oJCl7XG4gIFwidXNlIHN0cmljdFwiOyAvLyBqc2hpbnQgO187XG5cbiAgLyogTUFSS0RPV04gQ0xBU1MgREVGSU5JVElPTlxuICAgKiA9PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG4gIHZhciBNYXJrZG93biA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgLy8gQFRPRE8gOiByZW1vdmUgdGhpcyBCQyBvbiBuZXh0IG1ham9yIHJlbGVhc2VcbiAgICAvLyBAc2VlIDogaHR0cHM6Ly9naXRodWIuY29tL3Rvb3BheS9ib290c3RyYXAtbWFya2Rvd24vaXNzdWVzLzEwOVxuICAgIHZhciBvcHRzID0gWydhdXRvZm9jdXMnLCAnc2F2YWJsZScsICdoaWRlYWJsZScsICd3aWR0aCcsIFxuICAgICAgJ2hlaWdodCcsICdyZXNpemUnLCAnaWNvbmxpYnJhcnknLCAnbGFuZ3VhZ2UnLCBcbiAgICAgICdmb290ZXInLCAnZnVsbHNjcmVlbicsICdoaWRkZW5CdXR0b25zJywgJ2Rpc2FibGVkQnV0dG9ucyddO1xuICAgICQuZWFjaChvcHRzLGZ1bmN0aW9uKF8sIG9wdCl7XG4gICAgICBpZiAodHlwZW9mICQoZWxlbWVudCkuZGF0YShvcHQpICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBvcHRpb25zID0gdHlwZW9mIG9wdGlvbnMgPT0gJ29iamVjdCcgPyBvcHRpb25zIDoge31cbiAgICAgICAgb3B0aW9uc1tvcHRdID0gJChlbGVtZW50KS5kYXRhKG9wdClcbiAgICAgIH1cbiAgICB9KTtcbiAgICAvLyBFbmQgQkNcblxuICAgIC8vIENsYXNzIFByb3BlcnRpZXNcbiAgICB0aGlzLiRucyAgICAgICAgICAgPSAnYm9vdHN0cmFwLW1hcmtkb3duJztcbiAgICB0aGlzLiRlbGVtZW50ICAgICAgPSAkKGVsZW1lbnQpO1xuICAgIHRoaXMuJGVkaXRhYmxlICAgICA9IHtlbDpudWxsLCB0eXBlOm51bGwsYXR0cktleXM6W10sIGF0dHJWYWx1ZXM6W10sIGNvbnRlbnQ6bnVsbH07XG4gICAgdGhpcy4kb3B0aW9ucyAgICAgID0gJC5leHRlbmQodHJ1ZSwge30sICQuZm4ubWFya2Rvd24uZGVmYXVsdHMsIG9wdGlvbnMsIHRoaXMuJGVsZW1lbnQuZGF0YSgnb3B0aW9ucycpKTtcbiAgICB0aGlzLiRvbGRDb250ZW50ICAgPSBudWxsO1xuICAgIHRoaXMuJGlzUHJldmlldyAgICA9IGZhbHNlO1xuICAgIHRoaXMuJGlzRnVsbHNjcmVlbiA9IGZhbHNlO1xuICAgIHRoaXMuJGVkaXRvciAgICAgICA9IG51bGw7XG4gICAgdGhpcy4kdGV4dGFyZWEgICAgID0gbnVsbDtcbiAgICB0aGlzLiRoYW5kbGVyICAgICAgPSBbXTtcbiAgICB0aGlzLiRjYWxsYmFjayAgICAgPSBbXTtcbiAgICB0aGlzLiRuZXh0VGFiICAgICAgPSBbXTtcblxuICAgIHRoaXMuc2hvd0VkaXRvcigpO1xuICB9O1xuXG4gIE1hcmtkb3duLnByb3RvdHlwZSA9IHtcblxuICAgIGNvbnN0cnVjdG9yOiBNYXJrZG93blxuXG4gICwgX19hbHRlckJ1dHRvbnM6IGZ1bmN0aW9uKG5hbWUsYWx0ZXIpIHtcbiAgICAgIHZhciBoYW5kbGVyID0gdGhpcy4kaGFuZGxlciwgaXNBbGwgPSAobmFtZSA9PSAnYWxsJyksdGhhdCA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChoYW5kbGVyLGZ1bmN0aW9uKGssdikge1xuICAgICAgICB2YXIgaGFsdCA9IHRydWU7XG4gICAgICAgIGlmIChpc0FsbCkge1xuICAgICAgICAgIGhhbHQgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBoYWx0ID0gdi5pbmRleE9mKG5hbWUpIDwgMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChoYWx0ID09PSBmYWxzZSkge1xuICAgICAgICAgIGFsdGVyKHRoYXQuJGVkaXRvci5maW5kKCdidXR0b25bZGF0YS1oYW5kbGVyPVwiJyt2KydcIl0nKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAsIF9fYnVpbGRCdXR0b25zOiBmdW5jdGlvbihidXR0b25zQXJyYXksIGNvbnRhaW5lcikge1xuICAgICAgdmFyIGksXG4gICAgICAgICAgbnMgPSB0aGlzLiRucyxcbiAgICAgICAgICBoYW5kbGVyID0gdGhpcy4kaGFuZGxlcixcbiAgICAgICAgICBjYWxsYmFjayA9IHRoaXMuJGNhbGxiYWNrO1xuXG4gICAgICBmb3IgKGk9MDtpPGJ1dHRvbnNBcnJheS5sZW5ndGg7aSsrKSB7XG4gICAgICAgIC8vIEJ1aWxkIGVhY2ggZ3JvdXAgY29udGFpbmVyXG4gICAgICAgIHZhciB5LCBidG5Hcm91cHMgPSBidXR0b25zQXJyYXlbaV07XG4gICAgICAgIGZvciAoeT0wO3k8YnRuR3JvdXBzLmxlbmd0aDt5KyspIHtcbiAgICAgICAgICAvLyBCdWlsZCBlYWNoIGJ1dHRvbiBncm91cFxuICAgICAgICAgIHZhciB6LFxuICAgICAgICAgICAgICBidXR0b25zID0gYnRuR3JvdXBzW3ldLmRhdGEsXG4gICAgICAgICAgICAgIGJ0bkdyb3VwQ29udGFpbmVyID0gJCgnPGRpdi8+Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ2J0bi1ncm91cCdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgIGZvciAoej0wO3o8YnV0dG9ucy5sZW5ndGg7eisrKSB7XG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gYnV0dG9uc1t6XSxcbiAgICAgICAgICAgICAgICBidXR0b25Db250YWluZXIsIGJ1dHRvbkljb25Db250YWluZXIsXG4gICAgICAgICAgICAgICAgYnV0dG9uSGFuZGxlciA9IG5zKyctJytidXR0b24ubmFtZSxcbiAgICAgICAgICAgICAgICBidXR0b25JY29uID0gdGhpcy5fX2dldEljb24oYnV0dG9uLmljb24pLFxuICAgICAgICAgICAgICAgIGJ0blRleHQgPSBidXR0b24uYnRuVGV4dCA/IGJ1dHRvbi5idG5UZXh0IDogJycsXG4gICAgICAgICAgICAgICAgYnRuQ2xhc3MgPSBidXR0b24uYnRuQ2xhc3MgPyBidXR0b24uYnRuQ2xhc3MgOiAnYnRuJyxcbiAgICAgICAgICAgICAgICB0YWJJbmRleCA9IGJ1dHRvbi50YWJJbmRleCA/IGJ1dHRvbi50YWJJbmRleCA6ICctMScsXG4gICAgICAgICAgICAgICAgaG90a2V5ID0gdHlwZW9mIGJ1dHRvbi5ob3RrZXkgIT09ICd1bmRlZmluZWQnID8gYnV0dG9uLmhvdGtleSA6ICcnLFxuICAgICAgICAgICAgICAgIGhvdGtleUNhcHRpb24gPSB0eXBlb2YgalF1ZXJ5LmhvdGtleXMgIT09ICd1bmRlZmluZWQnICYmIGhvdGtleSAhPT0gJycgPyAnICgnK2hvdGtleSsnKScgOiAnJztcblxuICAgICAgICAgICAgLy8gQ29uc3RydWN0IHRoZSBidXR0b24gb2JqZWN0XG4gICAgICAgICAgICBidXR0b25Db250YWluZXIgPSAkKCc8YnV0dG9uPjwvYnV0dG9uPicpO1xuICAgICAgICAgICAgYnV0dG9uQ29udGFpbmVyLnRleHQoJyAnICsgdGhpcy5fX2xvY2FsaXplKGJ0blRleHQpKS5hZGRDbGFzcygnYnRuLWRlZmF1bHQgYnRuLXNtJykuYWRkQ2xhc3MoYnRuQ2xhc3MpO1xuICAgICAgICAgICAgaWYoYnRuQ2xhc3MubWF0Y2goL2J0blxcLShwcmltYXJ5fHN1Y2Nlc3N8aW5mb3x3YXJuaW5nfGRhbmdlcnxsaW5rKS8pKXtcbiAgICAgICAgICAgICAgICBidXR0b25Db250YWluZXIucmVtb3ZlQ2xhc3MoJ2J0bi1kZWZhdWx0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidXR0b25Db250YWluZXIuYXR0cih7XG4gICAgICAgICAgICAgICAgJ3R5cGUnOiAnYnV0dG9uJyxcbiAgICAgICAgICAgICAgICAndGl0bGUnOiB0aGlzLl9fbG9jYWxpemUoYnV0dG9uLnRpdGxlKSArIGhvdGtleUNhcHRpb24sXG4gICAgICAgICAgICAgICAgJ3RhYmluZGV4JzogdGFiSW5kZXgsXG4gICAgICAgICAgICAgICAgJ2RhdGEtcHJvdmlkZXInOiBucyxcbiAgICAgICAgICAgICAgICAnZGF0YS1oYW5kbGVyJzogYnV0dG9uSGFuZGxlcixcbiAgICAgICAgICAgICAgICAnZGF0YS1ob3RrZXknOiBob3RrZXlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKGJ1dHRvbi50b2dnbGUgPT09IHRydWUpe1xuICAgICAgICAgICAgICBidXR0b25Db250YWluZXIuYXR0cignZGF0YS10b2dnbGUnLCAnYnV0dG9uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidXR0b25JY29uQ29udGFpbmVyID0gJCgnPHNwYW4vPicpO1xuICAgICAgICAgICAgYnV0dG9uSWNvbkNvbnRhaW5lci5hZGRDbGFzcyhidXR0b25JY29uKTtcbiAgICAgICAgICAgIGJ1dHRvbkljb25Db250YWluZXIucHJlcGVuZFRvKGJ1dHRvbkNvbnRhaW5lcik7XG5cbiAgICAgICAgICAgIC8vIEF0dGFjaCB0aGUgYnV0dG9uIG9iamVjdFxuICAgICAgICAgICAgYnRuR3JvdXBDb250YWluZXIuYXBwZW5kKGJ1dHRvbkNvbnRhaW5lcik7XG5cbiAgICAgICAgICAgIC8vIFJlZ2lzdGVyIGhhbmRsZXIgYW5kIGNhbGxiYWNrXG4gICAgICAgICAgICBoYW5kbGVyLnB1c2goYnV0dG9uSGFuZGxlcik7XG4gICAgICAgICAgICBjYWxsYmFjay5wdXNoKGJ1dHRvbi5jYWxsYmFjayk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQXR0YWNoIHRoZSBidXR0b24gZ3JvdXAgaW50byBjb250YWluZXIgZG9tXG4gICAgICAgICAgY29udGFpbmVyLmFwcGVuZChidG5Hcm91cENvbnRhaW5lcik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbnRhaW5lcjtcbiAgICB9XG4gICwgX19zZXRMaXN0ZW5lcjogZnVuY3Rpb24oKSB7XG4gICAgICAvLyBTZXQgc2l6ZSBhbmQgcmVzaXphYmxlIFByb3BlcnRpZXNcbiAgICAgIHZhciBoYXNSb3dzID0gdHlwZW9mIHRoaXMuJHRleHRhcmVhLmF0dHIoJ3Jvd3MnKSAhPT0gJ3VuZGVmaW5lZCcsXG4gICAgICAgICAgbWF4Um93cyA9IHRoaXMuJHRleHRhcmVhLnZhbCgpLnNwbGl0KFwiXFxuXCIpLmxlbmd0aCA+IDUgPyB0aGlzLiR0ZXh0YXJlYS52YWwoKS5zcGxpdChcIlxcblwiKS5sZW5ndGggOiAnNScsXG4gICAgICAgICAgcm93c1ZhbCA9IGhhc1Jvd3MgPyB0aGlzLiR0ZXh0YXJlYS5hdHRyKCdyb3dzJykgOiBtYXhSb3dzO1xuXG4gICAgICB0aGlzLiR0ZXh0YXJlYS5hdHRyKCdyb3dzJyxyb3dzVmFsKTtcbiAgICAgIGlmICh0aGlzLiRvcHRpb25zLnJlc2l6ZSkge1xuICAgICAgICB0aGlzLiR0ZXh0YXJlYS5jc3MoJ3Jlc2l6ZScsdGhpcy4kb3B0aW9ucy5yZXNpemUpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLiR0ZXh0YXJlYS5vbih7XG4gICAgICAgICAgJ2ZvY3VzJyA6ICQucHJveHkodGhpcy5mb2N1cywgdGhpcyksXG4gICAgICAgICAgJ2tleXVwJyA6ICQucHJveHkodGhpcy5rZXl1cCwgdGhpcyksXG4gICAgICAgICAgJ2NoYW5nZScgOiAkLnByb3h5KHRoaXMuY2hhbmdlLCB0aGlzKSxcbiAgICAgICAgICAnc2VsZWN0JyA6ICQucHJveHkodGhpcy5zZWxlY3QsIHRoaXMpXG4gICAgICB9KTtcblxuICAgICAgaWYgKHRoaXMuZXZlbnRTdXBwb3J0ZWQoJ2tleWRvd24nKSkge1xuICAgICAgICB0aGlzLiR0ZXh0YXJlYS5vbigna2V5ZG93bicsICQucHJveHkodGhpcy5rZXlkb3duLCB0aGlzKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmV2ZW50U3VwcG9ydGVkKCdrZXlwcmVzcycpKSB7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhLm9uKCdrZXlwcmVzcycsICQucHJveHkodGhpcy5rZXlwcmVzcywgdGhpcykpXG4gICAgICB9XG5cbiAgICAgIC8vIFJlLWF0dGFjaCBtYXJrZG93biBkYXRhXG4gICAgICB0aGlzLiR0ZXh0YXJlYS5kYXRhKCdtYXJrZG93bicsdGhpcyk7XG4gICAgfVxuXG4gICwgX19oYW5kbGU6IGZ1bmN0aW9uKGUpIHtcbiAgICAgIHZhciB0YXJnZXQgPSAkKGUuY3VycmVudFRhcmdldCksXG4gICAgICAgICAgaGFuZGxlciA9IHRoaXMuJGhhbmRsZXIsXG4gICAgICAgICAgY2FsbGJhY2sgPSB0aGlzLiRjYWxsYmFjayxcbiAgICAgICAgICBoYW5kbGVyTmFtZSA9IHRhcmdldC5hdHRyKCdkYXRhLWhhbmRsZXInKSxcbiAgICAgICAgICBjYWxsYmFja0luZGV4ID0gaGFuZGxlci5pbmRleE9mKGhhbmRsZXJOYW1lKSxcbiAgICAgICAgICBjYWxsYmFja0hhbmRsZXIgPSBjYWxsYmFja1tjYWxsYmFja0luZGV4XTtcblxuICAgICAgLy8gVHJpZ2dlciB0aGUgZm9jdXNpblxuICAgICAgJChlLmN1cnJlbnRUYXJnZXQpLmZvY3VzKCk7XG5cbiAgICAgIGNhbGxiYWNrSGFuZGxlcih0aGlzKTtcblxuICAgICAgLy8gVHJpZ2dlciBvbkNoYW5nZSBmb3IgZWFjaCBidXR0b24gaGFuZGxlXG4gICAgICB0aGlzLmNoYW5nZSh0aGlzKTtcblxuICAgICAgLy8gVW5sZXNzIGl0IHdhcyB0aGUgc2F2ZSBoYW5kbGVyLFxuICAgICAgLy8gZm9jdXNpbiB0aGUgdGV4dGFyZWFcbiAgICAgIGlmIChoYW5kbGVyTmFtZS5pbmRleE9mKCdjbWRTYXZlJykgPCAwKSB7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhLmZvY3VzKCk7XG4gICAgICB9XG5cbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgLCBfX2xvY2FsaXplOiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgIHZhciBtZXNzYWdlcyA9ICQuZm4ubWFya2Rvd24ubWVzc2FnZXMsXG4gICAgICAgICAgbGFuZ3VhZ2UgPSB0aGlzLiRvcHRpb25zLmxhbmd1YWdlO1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgbWVzc2FnZXMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIHR5cGVvZiBtZXNzYWdlc1tsYW5ndWFnZV0gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIHR5cGVvZiBtZXNzYWdlc1tsYW5ndWFnZV1bc3RyaW5nXSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbWVzc2FnZXNbbGFuZ3VhZ2VdW3N0cmluZ107XG4gICAgICB9XG4gICAgICByZXR1cm4gc3RyaW5nO1xuICAgIH1cblxuICAsIF9fZ2V0SWNvbjogZnVuY3Rpb24oc3JjKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBzcmMgPT0gJ29iamVjdCcgPyBzcmNbdGhpcy4kb3B0aW9ucy5pY29ubGlicmFyeV0gOiBzcmM7XG4gIH1cblxuICAsIHNldEZ1bGxzY3JlZW46IGZ1bmN0aW9uKG1vZGUpIHtcbiAgICB2YXIgJGVkaXRvciA9IHRoaXMuJGVkaXRvcixcbiAgICAgICAgJHRleHRhcmVhID0gdGhpcy4kdGV4dGFyZWE7XG5cbiAgICBpZiAobW9kZSA9PT0gdHJ1ZSkge1xuICAgICAgJGVkaXRvci5hZGRDbGFzcygnbWQtZnVsbHNjcmVlbi1tb2RlJyk7XG4gICAgICAkKCdib2R5JykuYWRkQ2xhc3MoJ21kLW5vb3ZlcmZsb3cnKTtcbiAgICAgIHRoaXMuJG9wdGlvbnMub25GdWxsc2NyZWVuKHRoaXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAkZWRpdG9yLnJlbW92ZUNsYXNzKCdtZC1mdWxsc2NyZWVuLW1vZGUnKTtcbiAgICAgICQoJ2JvZHknKS5yZW1vdmVDbGFzcygnbWQtbm9vdmVyZmxvdycpO1xuXG4gICAgICBpZiAodGhpcy4kaXNQcmV2aWV3ID09IHRydWUpIHRoaXMuaGlkZVByZXZpZXcoKS5zaG93UHJldmlldygpXG4gICAgfVxuXG4gICAgdGhpcy4kaXNGdWxsc2NyZWVuID0gbW9kZTtcbiAgICAkdGV4dGFyZWEuZm9jdXMoKTtcbiAgfVxuXG4gICwgc2hvd0VkaXRvcjogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgaW5zdGFuY2UgPSB0aGlzLFxuICAgICAgICAgIHRleHRhcmVhLFxuICAgICAgICAgIG5zID0gdGhpcy4kbnMsXG4gICAgICAgICAgY29udGFpbmVyID0gdGhpcy4kZWxlbWVudCxcbiAgICAgICAgICBvcmlnaW5hbEhlaWd0aCA9IGNvbnRhaW5lci5jc3MoJ2hlaWdodCcpLFxuICAgICAgICAgIG9yaWdpbmFsV2lkdGggPSBjb250YWluZXIuY3NzKCd3aWR0aCcpLFxuICAgICAgICAgIGVkaXRhYmxlID0gdGhpcy4kZWRpdGFibGUsXG4gICAgICAgICAgaGFuZGxlciA9IHRoaXMuJGhhbmRsZXIsXG4gICAgICAgICAgY2FsbGJhY2sgPSB0aGlzLiRjYWxsYmFjayxcbiAgICAgICAgICBvcHRpb25zID0gdGhpcy4kb3B0aW9ucyxcbiAgICAgICAgICBlZGl0b3IgPSAkKCAnPGRpdi8+Jywge1xuICAgICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtZC1lZGl0b3InLFxuICAgICAgICAgICAgICAgICAgICAgIGNsaWNrOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgLy8gUHJlcGFyZSB0aGUgZWRpdG9yXG4gICAgICBpZiAodGhpcy4kZWRpdG9yID09PSBudWxsKSB7XG4gICAgICAgIC8vIENyZWF0ZSB0aGUgcGFuZWxcbiAgICAgICAgdmFyIGVkaXRvckhlYWRlciA9ICQoJzxkaXYvPicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWQtaGVhZGVyIGJ0bi10b29sYmFyJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIC8vIE1lcmdlIHRoZSBtYWluICYgYWRkaXRpb25hbCBidXR0b24gZ3JvdXBzIHRvZ2V0aGVyXG4gICAgICAgIHZhciBhbGxCdG5Hcm91cHMgPSBbXTtcbiAgICAgICAgaWYgKG9wdGlvbnMuYnV0dG9ucy5sZW5ndGggPiAwKSBhbGxCdG5Hcm91cHMgPSBhbGxCdG5Hcm91cHMuY29uY2F0KG9wdGlvbnMuYnV0dG9uc1swXSk7XG4gICAgICAgIGlmIChvcHRpb25zLmFkZGl0aW9uYWxCdXR0b25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAvLyBpdGVyYXRlIHRoZSBhZGRpdGlvbmFsIGJ1dHRvbiBncm91cHNcbiAgICAgICAgICAkLmVhY2gob3B0aW9ucy5hZGRpdGlvbmFsQnV0dG9uc1swXSwgZnVuY3Rpb24oaWR4LCBidXR0b25Hcm91cCl7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIHNlZSBpZiB0aGUgZ3JvdXAgbmFtZSBvZiB0aGUgYWRkaW9uYWwgZ3JvdXAgbWF0Y2hlcyBhbiBleGlzdGluZyBncm91cFxuICAgICAgICAgICAgdmFyIG1hdGNoaW5nR3JvdXBzID0gJC5ncmVwKGFsbEJ0bkdyb3VwcywgZnVuY3Rpb24oYWxsQnV0dG9uR3JvdXAsIGFsbElkeCl7XG4gICAgICAgICAgICAgIHJldHVybiBhbGxCdXR0b25Hcm91cC5uYW1lID09PSBidXR0b25Hcm91cC5uYW1lO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIGlmIGl0IG1hdGNoZXMgYWRkIHRoZSBhZGRpb25hbCBidXR0b25zIHRvIHRoYXQgZ3JvdXAsIGlmIG5vdCBqdXN0IGFkZCBpdCB0byB0aGUgYWxsIGJ1dHRvbnMgZ3JvdXBcbiAgICAgICAgICAgIGlmKG1hdGNoaW5nR3JvdXBzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgbWF0Y2hpbmdHcm91cHNbMF0uZGF0YSA9IG1hdGNoaW5nR3JvdXBzWzBdLmRhdGEuY29uY2F0KGJ1dHRvbkdyb3VwLmRhdGEpO1xuICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICBhbGxCdG5Hcm91cHMucHVzaChvcHRpb25zLmFkZGl0aW9uYWxCdXR0b25zWzBdW2lkeF0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gXG5cbiAgICAgICAgLy8gUmVkdWNlIGFuZC9vciByZW9yZGVyIHRoZSBidXR0b24gZ3JvdXBzXG4gICAgICAgIGlmIChvcHRpb25zLnJlb3JkZXJCdXR0b25Hcm91cHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGFsbEJ0bkdyb3VwcyA9IGFsbEJ0bkdyb3Vwc1xuICAgICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKGJ0bkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5pbmRleE9mKGJ0bkdyb3VwLm5hbWUpID4gLTE7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5yZW9yZGVyQnV0dG9uR3JvdXBzLmluZGV4T2YoYS5uYW1lKSA8IG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5pbmRleE9mKGIubmFtZSkpIHJldHVybiAtMTtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5yZW9yZGVyQnV0dG9uR3JvdXBzLmluZGV4T2YoYS5uYW1lKSA+IG9wdGlvbnMucmVvcmRlckJ1dHRvbkdyb3Vwcy5pbmRleE9mKGIubmFtZSkpIHJldHVybiAxO1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJ1aWxkIHRoZSBidXR0b25zXG4gICAgICAgIGlmIChhbGxCdG5Hcm91cHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGVkaXRvckhlYWRlciA9IHRoaXMuX19idWlsZEJ1dHRvbnMoW2FsbEJ0bkdyb3Vwc10sIGVkaXRvckhlYWRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5mdWxsc2NyZWVuLmVuYWJsZSkge1xuICAgICAgICAgIGVkaXRvckhlYWRlci5hcHBlbmQoJzxkaXYgY2xhc3M9XCJtZC1jb250cm9sc1wiPjxhIGNsYXNzPVwibWQtY29udHJvbCBtZC1jb250cm9sLWZ1bGxzY3JlZW5cIiBocmVmPVwiI1wiPjxzcGFuIGNsYXNzPVwiJyt0aGlzLl9fZ2V0SWNvbihvcHRpb25zLmZ1bGxzY3JlZW4uaWNvbnMuZnVsbHNjcmVlbk9uKSsnXCI+PC9zcGFuPjwvYT48L2Rpdj4nKS5vbignY2xpY2snLCAnLm1kLWNvbnRyb2wtZnVsbHNjcmVlbicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICBpbnN0YW5jZS5zZXRGdWxsc2NyZWVuKHRydWUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgZWRpdG9yLmFwcGVuZChlZGl0b3JIZWFkZXIpO1xuXG4gICAgICAgIC8vIFdyYXAgdGhlIHRleHRhcmVhXG4gICAgICAgIGlmIChjb250YWluZXIuaXMoJ3RleHRhcmVhJykpIHtcbiAgICAgICAgICBjb250YWluZXIuYmVmb3JlKGVkaXRvcik7XG4gICAgICAgICAgdGV4dGFyZWEgPSBjb250YWluZXI7XG4gICAgICAgICAgdGV4dGFyZWEuYWRkQ2xhc3MoJ21kLWlucHV0Jyk7XG4gICAgICAgICAgZWRpdG9yLmFwcGVuZCh0ZXh0YXJlYSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHJhd0NvbnRlbnQgPSAodHlwZW9mIHRvTWFya2Rvd24gPT0gJ2Z1bmN0aW9uJykgPyB0b01hcmtkb3duKGNvbnRhaW5lci5odG1sKCkpIDogY29udGFpbmVyLmh0bWwoKSxcbiAgICAgICAgICAgICAgY3VycmVudENvbnRlbnQgPSAkLnRyaW0ocmF3Q29udGVudCk7XG5cbiAgICAgICAgICAvLyBUaGlzIGlzIHNvbWUgYXJiaXRyYXJ5IGNvbnRlbnQgdGhhdCBjb3VsZCBiZSBlZGl0ZWRcbiAgICAgICAgICB0ZXh0YXJlYSA9ICQoJzx0ZXh0YXJlYS8+Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWQtaW5wdXQnLFxuICAgICAgICAgICAgICAgICAgICAgICAndmFsJyA6IGN1cnJlbnRDb250ZW50XG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICBlZGl0b3IuYXBwZW5kKHRleHRhcmVhKTtcblxuICAgICAgICAgIC8vIFNhdmUgdGhlIGVkaXRhYmxlXG4gICAgICAgICAgZWRpdGFibGUuZWwgPSBjb250YWluZXI7XG4gICAgICAgICAgZWRpdGFibGUudHlwZSA9IGNvbnRhaW5lci5wcm9wKCd0YWdOYW1lJykudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICBlZGl0YWJsZS5jb250ZW50ID0gY29udGFpbmVyLmh0bWwoKTtcblxuICAgICAgICAgICQoY29udGFpbmVyWzBdLmF0dHJpYnV0ZXMpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIGVkaXRhYmxlLmF0dHJLZXlzLnB1c2godGhpcy5ub2RlTmFtZSk7XG4gICAgICAgICAgICBlZGl0YWJsZS5hdHRyVmFsdWVzLnB1c2godGhpcy5ub2RlVmFsdWUpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gU2V0IGVkaXRvciB0byBibG9ja2VkIHRoZSBvcmlnaW5hbCBjb250YWluZXJcbiAgICAgICAgICBjb250YWluZXIucmVwbGFjZVdpdGgoZWRpdG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBlZGl0b3JGb290ZXIgPSAkKCc8ZGl2Lz4nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWQtZm9vdGVyJ1xuICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgY3JlYXRlRm9vdGVyID0gZmFsc2UsXG4gICAgICAgICAgICBmb290ZXIgPSAnJztcbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBmb290ZXIgaWYgc2F2YWJsZVxuICAgICAgICBpZiAob3B0aW9ucy5zYXZhYmxlKSB7XG4gICAgICAgICAgY3JlYXRlRm9vdGVyID0gdHJ1ZTtcbiAgICAgICAgICB2YXIgc2F2ZUhhbmRsZXIgPSAnY21kU2F2ZSc7XG5cbiAgICAgICAgICAvLyBSZWdpc3RlciBoYW5kbGVyIGFuZCBjYWxsYmFja1xuICAgICAgICAgIGhhbmRsZXIucHVzaChzYXZlSGFuZGxlcik7XG4gICAgICAgICAgY2FsbGJhY2sucHVzaChvcHRpb25zLm9uU2F2ZSk7XG5cbiAgICAgICAgICBlZGl0b3JGb290ZXIuYXBwZW5kKCc8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzXCIgZGF0YS1wcm92aWRlcj1cIidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgbnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgJ1wiIGRhdGEtaGFuZGxlcj1cIidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgc2F2ZUhhbmRsZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgJ1wiPjxpIGNsYXNzPVwiaWNvbiBpY29uLXdoaXRlIGljb24tb2tcIj48L2k+ICdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgdGhpcy5fX2xvY2FsaXplKCdTYXZlJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgJzwvYnV0dG9uPicpO1xuXG5cbiAgICAgICAgfVxuXG4gICAgICAgIGZvb3RlciA9IHR5cGVvZiBvcHRpb25zLmZvb3RlciA9PT0gJ2Z1bmN0aW9uJyA/IG9wdGlvbnMuZm9vdGVyKHRoaXMpIDogb3B0aW9ucy5mb290ZXI7XG5cbiAgICAgICAgaWYgKCQudHJpbShmb290ZXIpICE9PSAnJykge1xuICAgICAgICAgIGNyZWF0ZUZvb3RlciA9IHRydWU7XG4gICAgICAgICAgZWRpdG9yRm9vdGVyLmFwcGVuZChmb290ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNyZWF0ZUZvb3RlcikgZWRpdG9yLmFwcGVuZChlZGl0b3JGb290ZXIpO1xuXG4gICAgICAgIC8vIFNldCB3aWR0aFxuICAgICAgICBpZiAob3B0aW9ucy53aWR0aCAmJiBvcHRpb25zLndpZHRoICE9PSAnaW5oZXJpdCcpIHtcbiAgICAgICAgICBpZiAoalF1ZXJ5LmlzTnVtZXJpYyhvcHRpb25zLndpZHRoKSkge1xuICAgICAgICAgICAgZWRpdG9yLmNzcygnZGlzcGxheScsICd0YWJsZScpO1xuICAgICAgICAgICAgdGV4dGFyZWEuY3NzKCd3aWR0aCcsIG9wdGlvbnMud2lkdGggKyAncHgnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWRpdG9yLmFkZENsYXNzKG9wdGlvbnMud2lkdGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCBoZWlnaHRcbiAgICAgICAgaWYgKG9wdGlvbnMuaGVpZ2h0ICYmIG9wdGlvbnMuaGVpZ2h0ICE9PSAnaW5oZXJpdCcpIHtcbiAgICAgICAgICBpZiAoalF1ZXJ5LmlzTnVtZXJpYyhvcHRpb25zLmhlaWdodCkpIHtcbiAgICAgICAgICAgIHZhciBoZWlnaHQgPSBvcHRpb25zLmhlaWdodDtcbiAgICAgICAgICAgIGlmIChlZGl0b3JIZWFkZXIpIGhlaWdodCA9IE1hdGgubWF4KDAsIGhlaWdodCAtIGVkaXRvckhlYWRlci5vdXRlckhlaWdodCgpKTtcbiAgICAgICAgICAgIGlmIChlZGl0b3JGb290ZXIpIGhlaWdodCA9IE1hdGgubWF4KDAsIGhlaWdodCAtIGVkaXRvckZvb3Rlci5vdXRlckhlaWdodCgpKTtcbiAgICAgICAgICAgIHRleHRhcmVhLmNzcygnaGVpZ2h0JywgaGVpZ2h0ICsgJ3B4Jyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVkaXRvci5hZGRDbGFzcyhvcHRpb25zLmhlaWdodCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVmZXJlbmNlXG4gICAgICAgIHRoaXMuJGVkaXRvciAgICAgPSBlZGl0b3I7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhICAgPSB0ZXh0YXJlYTtcbiAgICAgICAgdGhpcy4kZWRpdGFibGUgICA9IGVkaXRhYmxlO1xuICAgICAgICB0aGlzLiRvbGRDb250ZW50ID0gdGhpcy5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgdGhpcy5fX3NldExpc3RlbmVyKCk7XG5cbiAgICAgICAgLy8gU2V0IGVkaXRvciBhdHRyaWJ1dGVzLCBkYXRhIHNob3J0LWhhbmQgQVBJIGFuZCBsaXN0ZW5lclxuICAgICAgICB0aGlzLiRlZGl0b3IuYXR0cignaWQnLChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkpO1xuICAgICAgICB0aGlzLiRlZGl0b3Iub24oJ2NsaWNrJywgJ1tkYXRhLXByb3ZpZGVyPVwiYm9vdHN0cmFwLW1hcmtkb3duXCJdJywgJC5wcm94eSh0aGlzLl9faGFuZGxlLCB0aGlzKSk7XG5cbiAgICAgICAgaWYgKHRoaXMuJGVsZW1lbnQuaXMoJzpkaXNhYmxlZCcpIHx8IHRoaXMuJGVsZW1lbnQuaXMoJ1tyZWFkb25seV0nKSkge1xuICAgICAgICAgIHRoaXMuJGVkaXRvci5hZGRDbGFzcygnbWQtZWRpdG9yLWRpc2FibGVkJyk7XG4gICAgICAgICAgdGhpcy5kaXNhYmxlQnV0dG9ucygnYWxsJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5ldmVudFN1cHBvcnRlZCgna2V5ZG93bicpICYmIHR5cGVvZiBqUXVlcnkuaG90a2V5cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBlZGl0b3JIZWFkZXIuZmluZCgnW2RhdGEtcHJvdmlkZXI9XCJib290c3RyYXAtbWFya2Rvd25cIl0nKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyICRidXR0b24gPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgIGhvdGtleSA9ICRidXR0b24uYXR0cignZGF0YS1ob3RrZXknKTtcbiAgICAgICAgICAgIGlmIChob3RrZXkudG9Mb3dlckNhc2UoKSAhPT0gJycpIHtcbiAgICAgICAgICAgICAgdGV4dGFyZWEuYmluZCgna2V5ZG93bicsIGhvdGtleSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgJGJ1dHRvbi50cmlnZ2VyKCdjbGljaycpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5pbml0aWFsc3RhdGUgPT09ICdwcmV2aWV3Jykge1xuICAgICAgICAgIHRoaXMuc2hvd1ByZXZpZXcoKTtcbiAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmluaXRpYWxzdGF0ZSA9PT0gJ2Z1bGxzY3JlZW4nICYmIG9wdGlvbnMuZnVsbHNjcmVlbi5lbmFibGUpIHtcbiAgICAgICAgICB0aGlzLnNldEZ1bGxzY3JlZW4odHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy4kZWRpdG9yLnNob3coKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuYXV0b2ZvY3VzKSB7XG4gICAgICAgIHRoaXMuJHRleHRhcmVhLmZvY3VzKCk7XG4gICAgICAgIHRoaXMuJGVkaXRvci5hZGRDbGFzcygnYWN0aXZlJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLmZ1bGxzY3JlZW4uZW5hYmxlICYmIG9wdGlvbnMuZnVsbHNjcmVlbiAhPT0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy4kZWRpdG9yLmFwcGVuZCgnPGRpdiBjbGFzcz1cIm1kLWZ1bGxzY3JlZW4tY29udHJvbHNcIj4nXG4gICAgICAgICAgICAgICAgICAgICAgICArICc8YSBocmVmPVwiI1wiIGNsYXNzPVwiZXhpdC1mdWxsc2NyZWVuXCIgdGl0bGU9XCJFeGl0IGZ1bGxzY3JlZW5cIj48c3BhbiBjbGFzcz1cIicgKyB0aGlzLl9fZ2V0SWNvbihvcHRpb25zLmZ1bGxzY3JlZW4uaWNvbnMuZnVsbHNjcmVlbk9mZikgKyAnXCI+J1xuICAgICAgICAgICAgICAgICAgICAgICAgKyAnPC9zcGFuPjwvYT4nXG4gICAgICAgICAgICAgICAgICAgICAgICArICc8L2Rpdj4nKTtcbiAgICAgICAgdGhpcy4kZWRpdG9yLm9uKCdjbGljaycsICcuZXhpdC1mdWxsc2NyZWVuJywgZnVuY3Rpb24oZSkge1xuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICBpbnN0YW5jZS5zZXRGdWxsc2NyZWVuKGZhbHNlKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIGhpZGUgaGlkZGVuIGJ1dHRvbnMgZnJvbSBvcHRpb25zXG4gICAgICB0aGlzLmhpZGVCdXR0b25zKG9wdGlvbnMuaGlkZGVuQnV0dG9ucyk7XG5cbiAgICAgIC8vIGRpc2FibGUgZGlzYWJsZWQgYnV0dG9ucyBmcm9tIG9wdGlvbnNcbiAgICAgIHRoaXMuZGlzYWJsZUJ1dHRvbnMob3B0aW9ucy5kaXNhYmxlZEJ1dHRvbnMpO1xuXG4gICAgICAvLyBUcmlnZ2VyIHRoZSBvblNob3cgaG9va1xuICAgICAgb3B0aW9ucy5vblNob3codGhpcyk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIHBhcnNlQ29udGVudDogZnVuY3Rpb24odmFsKSB7XG4gICAgICB2YXIgY29udGVudDtcblxuICAgICAgLy8gcGFyc2Ugd2l0aCBzdXBwb3J0ZWQgbWFya2Rvd24gcGFyc2VyXG4gICAgICB2YXIgdmFsID0gdmFsIHx8IHRoaXMuJHRleHRhcmVhLnZhbCgpO1xuXG4gICAgICBpZiAodGhpcy4kb3B0aW9ucy5wYXJzZXIpIHtcbiAgICAgICAgY29udGVudCA9IHRoaXMuJG9wdGlvbnMucGFyc2VyKHZhbCk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBtYXJrZG93biA9PSAnb2JqZWN0Jykge1xuICAgICAgICBjb250ZW50ID0gbWFya2Rvd24udG9IVE1MKHZhbCk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBtYXJrZWQgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjb250ZW50ID0gbWFya2VkKHZhbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZW50ID0gdmFsO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gY29udGVudDtcbiAgICB9XG5cbiAgLCBzaG93UHJldmlldzogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuJG9wdGlvbnMsXG4gICAgICAgICAgY29udGFpbmVyID0gdGhpcy4kdGV4dGFyZWEsXG4gICAgICAgICAgYWZ0ZXJDb250YWluZXIgPSBjb250YWluZXIubmV4dCgpLFxuICAgICAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyID0gJCgnPGRpdi8+Jyx7J2NsYXNzJzonbWQtcHJldmlldycsJ2RhdGEtcHJvdmlkZXInOidtYXJrZG93bi1wcmV2aWV3J30pLFxuICAgICAgICAgIGNvbnRlbnQsXG4gICAgICAgICAgY2FsbGJhY2tDb250ZW50O1xuXG4gICAgICBpZiAodGhpcy4kaXNQcmV2aWV3ID09IHRydWUpIHtcbiAgICAgICAgLy8gQXZvaWQgc2VxdWVuY2VkIGVsZW1lbnQgY3JlYXRpb24gb24gbWlzc3VzZWQgc2NlbmFyaW9cbiAgICAgICAgLy8gQHNlZSBodHRwczovL2dpdGh1Yi5jb20vdG9vcGF5L2Jvb3RzdHJhcC1tYXJrZG93bi9pc3N1ZXMvMTcwXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBHaXZlIGZsYWcgdGhhdCB0ZWxsIHRoZSBlZGl0b3IgZW50ZXIgcHJldmlldyBtb2RlXG4gICAgICB0aGlzLiRpc1ByZXZpZXcgPSB0cnVlO1xuICAgICAgLy8gRGlzYWJsZSBhbGwgYnV0dG9uc1xuICAgICAgdGhpcy5kaXNhYmxlQnV0dG9ucygnYWxsJykuZW5hYmxlQnV0dG9ucygnY21kUHJldmlldycpO1xuXG4gICAgICAvLyBUcnkgdG8gZ2V0IHRoZSBjb250ZW50IGZyb20gY2FsbGJhY2tcbiAgICAgIGNhbGxiYWNrQ29udGVudCA9IG9wdGlvbnMub25QcmV2aWV3KHRoaXMpO1xuICAgICAgLy8gU2V0IHRoZSBjb250ZW50IGJhc2VkIGZyb20gdGhlIGNhbGxiYWNrIGNvbnRlbnQgaWYgc3RyaW5nIG90aGVyd2lzZSBwYXJzZSB2YWx1ZSBmcm9tIHRleHRhcmVhXG4gICAgICBjb250ZW50ID0gdHlwZW9mIGNhbGxiYWNrQ29udGVudCA9PSAnc3RyaW5nJyA/IGNhbGxiYWNrQ29udGVudCA6IHRoaXMucGFyc2VDb250ZW50KCk7XG5cbiAgICAgIC8vIEJ1aWxkIHByZXZpZXcgZWxlbWVudFxuICAgICAgcmVwbGFjZW1lbnRDb250YWluZXIuaHRtbChjb250ZW50KTtcblxuICAgICAgaWYgKGFmdGVyQ29udGFpbmVyICYmIGFmdGVyQ29udGFpbmVyLmF0dHIoJ2NsYXNzJykgPT0gJ21kLWZvb3RlcicpIHtcbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgZm9vdGVyIGVsZW1lbnQsIGluc2VydCB0aGUgcHJldmlldyBjb250YWluZXIgYmVmb3JlIGl0XG4gICAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyLmluc2VydEJlZm9yZShhZnRlckNvbnRhaW5lcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBPdGhlcndpc2UsIGp1c3QgYXBwZW5kIGl0IGFmdGVyIHRleHRhcmVhXG4gICAgICAgIGNvbnRhaW5lci5wYXJlbnQoKS5hcHBlbmQocmVwbGFjZW1lbnRDb250YWluZXIpO1xuICAgICAgfVxuXG4gICAgICAvLyBTZXQgdGhlIHByZXZpZXcgZWxlbWVudCBkaW1lbnNpb25zXG4gICAgICByZXBsYWNlbWVudENvbnRhaW5lci5jc3Moe1xuICAgICAgICB3aWR0aDogY29udGFpbmVyLm91dGVyV2lkdGgoKSArICdweCcsXG4gICAgICAgIGhlaWdodDogY29udGFpbmVyLm91dGVySGVpZ2h0KCkgKyAncHgnXG4gICAgICB9KTtcblxuICAgICAgaWYgKHRoaXMuJG9wdGlvbnMucmVzaXplKSB7XG4gICAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyLmNzcygncmVzaXplJyx0aGlzLiRvcHRpb25zLnJlc2l6ZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEhpZGUgdGhlIGxhc3QtYWN0aXZlIHRleHRhcmVhXG4gICAgICBjb250YWluZXIuaGlkZSgpO1xuXG4gICAgICAvLyBBdHRhY2ggdGhlIGVkaXRvciBpbnN0YW5jZXNcbiAgICAgIHJlcGxhY2VtZW50Q29udGFpbmVyLmRhdGEoJ21hcmtkb3duJyx0aGlzKTtcblxuICAgICAgaWYgKHRoaXMuJGVsZW1lbnQuaXMoJzpkaXNhYmxlZCcpIHx8IHRoaXMuJGVsZW1lbnQuaXMoJ1tyZWFkb25seV0nKSkge1xuICAgICAgICB0aGlzLiRlZGl0b3IuYWRkQ2xhc3MoJ21kLWVkaXRvci1kaXNhYmxlZCcpO1xuICAgICAgICB0aGlzLmRpc2FibGVCdXR0b25zKCdhbGwnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgaGlkZVByZXZpZXc6IGZ1bmN0aW9uKCkge1xuICAgICAgLy8gR2l2ZSBmbGFnIHRoYXQgdGVsbCB0aGUgZWRpdG9yIHF1aXQgcHJldmlldyBtb2RlXG4gICAgICB0aGlzLiRpc1ByZXZpZXcgPSBmYWxzZTtcblxuICAgICAgLy8gT2J0YWluIHRoZSBwcmV2aWV3IGNvbnRhaW5lclxuICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuJGVkaXRvci5maW5kKCdkaXZbZGF0YS1wcm92aWRlcj1cIm1hcmtkb3duLXByZXZpZXdcIl0nKTtcblxuICAgICAgLy8gUmVtb3ZlIHRoZSBwcmV2aWV3IGNvbnRhaW5lclxuICAgICAgY29udGFpbmVyLnJlbW92ZSgpO1xuXG4gICAgICAvLyBFbmFibGUgYWxsIGJ1dHRvbnNcbiAgICAgIHRoaXMuZW5hYmxlQnV0dG9ucygnYWxsJyk7XG4gICAgICAvLyBEaXNhYmxlIGNvbmZpZ3VyZWQgZGlzYWJsZWQgYnV0dG9uc1xuICAgICAgdGhpcy5kaXNhYmxlQnV0dG9ucyh0aGlzLiRvcHRpb25zLmRpc2FibGVkQnV0dG9ucyk7XG5cbiAgICAgIC8vIEJhY2sgdG8gdGhlIGVkaXRvclxuICAgICAgdGhpcy4kdGV4dGFyZWEuc2hvdygpO1xuICAgICAgdGhpcy5fX3NldExpc3RlbmVyKCk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGlzRGlydHk6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuJG9sZENvbnRlbnQgIT0gdGhpcy5nZXRDb250ZW50KCk7XG4gICAgfVxuXG4gICwgZ2V0Q29udGVudDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy4kdGV4dGFyZWEudmFsKCk7XG4gICAgfVxuXG4gICwgc2V0Q29udGVudDogZnVuY3Rpb24oY29udGVudCkge1xuICAgICAgdGhpcy4kdGV4dGFyZWEudmFsKGNvbnRlbnQpO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBmaW5kU2VsZWN0aW9uOiBmdW5jdGlvbihjaHVuaykge1xuICAgIHZhciBjb250ZW50ID0gdGhpcy5nZXRDb250ZW50KCksIHN0YXJ0Q2h1bmtQb3NpdGlvbjtcblxuICAgIGlmIChzdGFydENodW5rUG9zaXRpb24gPSBjb250ZW50LmluZGV4T2YoY2h1bmspLCBzdGFydENodW5rUG9zaXRpb24gPj0gMCAmJiBjaHVuay5sZW5ndGggPiAwKSB7XG4gICAgICB2YXIgb2xkU2VsZWN0aW9uID0gdGhpcy5nZXRTZWxlY3Rpb24oKSwgc2VsZWN0aW9uO1xuXG4gICAgICB0aGlzLnNldFNlbGVjdGlvbihzdGFydENodW5rUG9zaXRpb24sc3RhcnRDaHVua1Bvc2l0aW9uK2NodW5rLmxlbmd0aCk7XG4gICAgICBzZWxlY3Rpb24gPSB0aGlzLmdldFNlbGVjdGlvbigpO1xuXG4gICAgICB0aGlzLnNldFNlbGVjdGlvbihvbGRTZWxlY3Rpb24uc3RhcnQsb2xkU2VsZWN0aW9uLmVuZCk7XG5cbiAgICAgIHJldHVybiBzZWxlY3Rpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gICwgZ2V0U2VsZWN0aW9uOiBmdW5jdGlvbigpIHtcblxuICAgICAgdmFyIGUgPSB0aGlzLiR0ZXh0YXJlYVswXTtcblxuICAgICAgcmV0dXJuIChcblxuICAgICAgICAgICgnc2VsZWN0aW9uU3RhcnQnIGluIGUgJiYgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIHZhciBsID0gZS5zZWxlY3Rpb25FbmQgLSBlLnNlbGVjdGlvblN0YXJ0O1xuICAgICAgICAgICAgICByZXR1cm4geyBzdGFydDogZS5zZWxlY3Rpb25TdGFydCwgZW5kOiBlLnNlbGVjdGlvbkVuZCwgbGVuZ3RoOiBsLCB0ZXh0OiBlLnZhbHVlLnN1YnN0cihlLnNlbGVjdGlvblN0YXJ0LCBsKSB9O1xuICAgICAgICAgIH0pIHx8XG5cbiAgICAgICAgICAvKiBicm93c2VyIG5vdCBzdXBwb3J0ZWQgKi9cbiAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cblxuICAgICAgKSgpO1xuXG4gICAgfVxuXG4gICwgc2V0U2VsZWN0aW9uOiBmdW5jdGlvbihzdGFydCxlbmQpIHtcblxuICAgICAgdmFyIGUgPSB0aGlzLiR0ZXh0YXJlYVswXTtcblxuICAgICAgcmV0dXJuIChcblxuICAgICAgICAgICgnc2VsZWN0aW9uU3RhcnQnIGluIGUgJiYgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIGUuc2VsZWN0aW9uU3RhcnQgPSBzdGFydDtcbiAgICAgICAgICAgICAgZS5zZWxlY3Rpb25FbmQgPSBlbmQ7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9KSB8fFxuXG4gICAgICAgICAgLyogYnJvd3NlciBub3Qgc3VwcG9ydGVkICovXG4gICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG5cbiAgICAgICkoKTtcblxuICAgIH1cblxuICAsIHJlcGxhY2VTZWxlY3Rpb246IGZ1bmN0aW9uKHRleHQpIHtcblxuICAgICAgdmFyIGUgPSB0aGlzLiR0ZXh0YXJlYVswXTtcblxuICAgICAgcmV0dXJuIChcblxuICAgICAgICAgICgnc2VsZWN0aW9uU3RhcnQnIGluIGUgJiYgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIGUudmFsdWUgPSBlLnZhbHVlLnN1YnN0cigwLCBlLnNlbGVjdGlvblN0YXJ0KSArIHRleHQgKyBlLnZhbHVlLnN1YnN0cihlLnNlbGVjdGlvbkVuZCwgZS52YWx1ZS5sZW5ndGgpO1xuICAgICAgICAgICAgICAvLyBTZXQgY3Vyc29yIHRvIHRoZSBsYXN0IHJlcGxhY2VtZW50IGVuZFxuICAgICAgICAgICAgICBlLnNlbGVjdGlvblN0YXJ0ID0gZS52YWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgIH0pIHx8XG5cbiAgICAgICAgICAvKiBicm93c2VyIG5vdCBzdXBwb3J0ZWQgKi9cbiAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgZS52YWx1ZSArPSB0ZXh0O1xuICAgICAgICAgICAgICByZXR1cm4galF1ZXJ5KGUpO1xuICAgICAgICAgIH1cblxuICAgICAgKSgpO1xuICAgIH1cblxuICAsIGdldE5leHRUYWI6IGZ1bmN0aW9uKCkge1xuICAgICAgLy8gU2hpZnQgdGhlIG5leHRUYWJcbiAgICAgIGlmICh0aGlzLiRuZXh0VGFiLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBuZXh0VGFiLCB0YWIgPSB0aGlzLiRuZXh0VGFiLnNoaWZ0KCk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB0YWIgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIG5leHRUYWIgPSB0YWIoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGFiID09ICdvYmplY3QnICYmIHRhYi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgbmV4dFRhYiA9IHRhYjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXh0VGFiO1xuICAgICAgfVxuICAgIH1cblxuICAsIHNldE5leHRUYWI6IGZ1bmN0aW9uKHN0YXJ0LGVuZCkge1xuICAgICAgLy8gUHVzaCBuZXcgc2VsZWN0aW9uIGludG8gbmV4dFRhYiBjb2xsZWN0aW9uc1xuICAgICAgaWYgKHR5cGVvZiBzdGFydCA9PSAnc3RyaW5nJykge1xuICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgIHRoaXMuJG5leHRUYWIucHVzaChmdW5jdGlvbigpe1xuICAgICAgICAgIHJldHVybiB0aGF0LmZpbmRTZWxlY3Rpb24oc3RhcnQpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHN0YXJ0ID09ICdudW1iZXInICYmIHR5cGVvZiBlbmQgPT0gJ251bWJlcicpIHtcbiAgICAgICAgdmFyIG9sZFNlbGVjdGlvbiA9IHRoaXMuZ2V0U2VsZWN0aW9uKCk7XG5cbiAgICAgICAgdGhpcy5zZXRTZWxlY3Rpb24oc3RhcnQsZW5kKTtcbiAgICAgICAgdGhpcy4kbmV4dFRhYi5wdXNoKHRoaXMuZ2V0U2VsZWN0aW9uKCkpO1xuXG4gICAgICAgIHRoaXMuc2V0U2VsZWN0aW9uKG9sZFNlbGVjdGlvbi5zdGFydCxvbGRTZWxlY3Rpb24uZW5kKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAsIF9fcGFyc2VCdXR0b25OYW1lUGFyYW06IGZ1bmN0aW9uIChuYW1lcykge1xuICAgICAgcmV0dXJuIHR5cGVvZiBuYW1lcyA9PSAnc3RyaW5nJyA/XG4gICAgICAgICAgICAgICAgICAgICAgbmFtZXMuc3BsaXQoJyAnKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbmFtZXM7XG5cbiAgICB9XG5cbiAgLCBlbmFibGVCdXR0b25zOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgICB2YXIgYnV0dG9ucyA9IHRoaXMuX19wYXJzZUJ1dHRvbk5hbWVQYXJhbShuYW1lKSxcbiAgICAgICAgdGhhdCA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChidXR0b25zLCBmdW5jdGlvbihpLCB2KSB7XG4gICAgICAgIHRoYXQuX19hbHRlckJ1dHRvbnMoYnV0dG9uc1tpXSwgZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgZWwucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgZGlzYWJsZUJ1dHRvbnM6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBidXR0b25zID0gdGhpcy5fX3BhcnNlQnV0dG9uTmFtZVBhcmFtKG5hbWUpLFxuICAgICAgICB0aGF0ID0gdGhpcztcblxuICAgICAgJC5lYWNoKGJ1dHRvbnMsIGZ1bmN0aW9uKGksIHYpIHtcbiAgICAgICAgdGhhdC5fX2FsdGVyQnV0dG9ucyhidXR0b25zW2ldLCBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICBlbC5hdHRyKCdkaXNhYmxlZCcsJ2Rpc2FibGVkJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAsIGhpZGVCdXR0b25zOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgICB2YXIgYnV0dG9ucyA9IHRoaXMuX19wYXJzZUJ1dHRvbk5hbWVQYXJhbShuYW1lKSxcbiAgICAgICAgdGhhdCA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChidXR0b25zLCBmdW5jdGlvbihpLCB2KSB7XG4gICAgICAgIHRoYXQuX19hbHRlckJ1dHRvbnMoYnV0dG9uc1tpXSwgZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgZWwuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgLCBzaG93QnV0dG9uczogZnVuY3Rpb24obmFtZSkge1xuICAgICAgdmFyIGJ1dHRvbnMgPSB0aGlzLl9fcGFyc2VCdXR0b25OYW1lUGFyYW0obmFtZSksXG4gICAgICAgIHRoYXQgPSB0aGlzO1xuXG4gICAgICAkLmVhY2goYnV0dG9ucywgZnVuY3Rpb24oaSwgdikge1xuICAgICAgICB0aGF0Ll9fYWx0ZXJCdXR0b25zKGJ1dHRvbnNbaV0sIGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIGVsLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgZXZlbnRTdXBwb3J0ZWQ6IGZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuICAgICAgdmFyIGlzU3VwcG9ydGVkID0gZXZlbnROYW1lIGluIHRoaXMuJGVsZW1lbnQ7XG4gICAgICBpZiAoIWlzU3VwcG9ydGVkKSB7XG4gICAgICAgIHRoaXMuJGVsZW1lbnQuc2V0QXR0cmlidXRlKGV2ZW50TmFtZSwgJ3JldHVybjsnKTtcbiAgICAgICAgaXNTdXBwb3J0ZWQgPSB0eXBlb2YgdGhpcy4kZWxlbWVudFtldmVudE5hbWVdID09PSAnZnVuY3Rpb24nO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzU3VwcG9ydGVkO1xuICAgIH1cblxuICAsIGtleXVwOiBmdW5jdGlvbiAoZSkge1xuICAgICAgdmFyIGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgIHN3aXRjaChlLmtleUNvZGUpIHtcbiAgICAgICAgY2FzZSA0MDogLy8gZG93biBhcnJvd1xuICAgICAgICBjYXNlIDM4OiAvLyB1cCBhcnJvd1xuICAgICAgICBjYXNlIDE2OiAvLyBzaGlmdFxuICAgICAgICBjYXNlIDE3OiAvLyBjdHJsXG4gICAgICAgIGNhc2UgMTg6IC8vIGFsdFxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgOTogLy8gdGFiXG4gICAgICAgICAgdmFyIG5leHRUYWI7XG4gICAgICAgICAgaWYgKG5leHRUYWIgPSB0aGlzLmdldE5leHRUYWIoKSxuZXh0VGFiICE9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBHZXQgdGhlIG5leHRUYWIgaWYgZXhpc3RzXG4gICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgIHRoYXQuc2V0U2VsZWN0aW9uKG5leHRUYWIuc3RhcnQsbmV4dFRhYi5lbmQpO1xuICAgICAgICAgICAgfSw1MDApO1xuXG4gICAgICAgICAgICBibG9ja2VkID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhlIG5leHQgdGFiIG1lbW9yeSBjb250YWlucyBub3RoaW5nLi4uXG4gICAgICAgICAgICAvLyBjaGVjayB0aGUgY3Vyc29yIHBvc2l0aW9uIHRvIGRldGVybWluZSB0YWIgYWN0aW9uXG4gICAgICAgICAgICB2YXIgY3Vyc29yID0gdGhpcy5nZXRTZWxlY3Rpb24oKTtcblxuICAgICAgICAgICAgaWYgKGN1cnNvci5zdGFydCA9PSBjdXJzb3IuZW5kICYmIGN1cnNvci5lbmQgPT0gdGhpcy5nZXRDb250ZW50KCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIC8vIFRoZSBjdXJzb3IgYWxyZWFkeSByZWFjaCB0aGUgZW5kIG9mIHRoZSBjb250ZW50XG4gICAgICAgICAgICAgIGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIFB1dCB0aGUgY3Vyc29yIHRvIHRoZSBlbmRcbiAgICAgICAgICAgICAgdGhpcy5zZXRTZWxlY3Rpb24odGhpcy5nZXRDb250ZW50KCkubGVuZ3RoLHRoaXMuZ2V0Q29udGVudCgpLmxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgYmxvY2tlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAxMzogLy8gZW50ZXJcbiAgICAgICAgICBibG9ja2VkID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjc6IC8vIGVzY2FwZVxuICAgICAgICAgIGlmICh0aGlzLiRpc0Z1bGxzY3JlZW4pIHRoaXMuc2V0RnVsbHNjcmVlbihmYWxzZSk7XG4gICAgICAgICAgYmxvY2tlZCA9IGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgYmxvY2tlZCA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAoYmxvY2tlZCkge1xuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuJG9wdGlvbnMub25DaGFuZ2UodGhpcyk7XG4gICAgfVxuXG4gICwgY2hhbmdlOiBmdW5jdGlvbihlKSB7XG4gICAgICB0aGlzLiRvcHRpb25zLm9uQ2hhbmdlKHRoaXMpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAsIHNlbGVjdDogZnVuY3Rpb24gKGUpIHtcbiAgICAgIHRoaXMuJG9wdGlvbnMub25TZWxlY3QodGhpcyk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICwgZm9jdXM6IGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuJG9wdGlvbnMsXG4gICAgICAgICAgaXNIaWRlYWJsZSA9IG9wdGlvbnMuaGlkZWFibGUsXG4gICAgICAgICAgZWRpdG9yID0gdGhpcy4kZWRpdG9yO1xuXG4gICAgICBlZGl0b3IuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xuXG4gICAgICAvLyBCbHVyIG90aGVyIG1hcmtkb3duKHMpXG4gICAgICAkKGRvY3VtZW50KS5maW5kKCcubWQtZWRpdG9yJykuZWFjaChmdW5jdGlvbigpe1xuICAgICAgICBpZiAoJCh0aGlzKS5hdHRyKCdpZCcpICE9PSBlZGl0b3IuYXR0cignaWQnKSkge1xuICAgICAgICAgIHZhciBhdHRhY2hlZE1hcmtkb3duO1xuXG4gICAgICAgICAgaWYgKGF0dGFjaGVkTWFya2Rvd24gPSAkKHRoaXMpLmZpbmQoJ3RleHRhcmVhJykuZGF0YSgnbWFya2Rvd24nKSxcbiAgICAgICAgICAgICAgYXR0YWNoZWRNYXJrZG93biA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICBhdHRhY2hlZE1hcmtkb3duID0gJCh0aGlzKS5maW5kKCdkaXZbZGF0YS1wcm92aWRlcj1cIm1hcmtkb3duLXByZXZpZXdcIl0nKS5kYXRhKCdtYXJrZG93bicpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChhdHRhY2hlZE1hcmtkb3duKSB7XG4gICAgICAgICAgICBhdHRhY2hlZE1hcmtkb3duLmJsdXIoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBUcmlnZ2VyIHRoZSBvbkZvY3VzIGhvb2tcbiAgICAgIG9wdGlvbnMub25Gb2N1cyh0aGlzKTtcblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICwgYmx1cjogZnVuY3Rpb24gKGUpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy4kb3B0aW9ucyxcbiAgICAgICAgICBpc0hpZGVhYmxlID0gb3B0aW9ucy5oaWRlYWJsZSxcbiAgICAgICAgICBlZGl0b3IgPSB0aGlzLiRlZGl0b3IsXG4gICAgICAgICAgZWRpdGFibGUgPSB0aGlzLiRlZGl0YWJsZTtcblxuICAgICAgaWYgKGVkaXRvci5oYXNDbGFzcygnYWN0aXZlJykgfHwgdGhpcy4kZWxlbWVudC5wYXJlbnQoKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZWRpdG9yLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcblxuICAgICAgICBpZiAoaXNIaWRlYWJsZSkge1xuICAgICAgICAgIC8vIENoZWNrIGZvciBlZGl0YWJsZSBlbGVtZW50c1xuICAgICAgICAgIGlmIChlZGl0YWJsZS5lbCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gQnVpbGQgdGhlIG9yaWdpbmFsIGVsZW1lbnRcbiAgICAgICAgICAgIHZhciBvbGRFbGVtZW50ID0gJCgnPCcrZWRpdGFibGUudHlwZSsnLz4nKSxcbiAgICAgICAgICAgICAgICBjb250ZW50ID0gdGhpcy5nZXRDb250ZW50KCksXG4gICAgICAgICAgICAgICAgY3VycmVudENvbnRlbnQgPSB0aGlzLnBhcnNlQ29udGVudChjb250ZW50KTtcblxuICAgICAgICAgICAgJChlZGl0YWJsZS5hdHRyS2V5cykuZWFjaChmdW5jdGlvbihrLHYpIHtcbiAgICAgICAgICAgICAgb2xkRWxlbWVudC5hdHRyKGVkaXRhYmxlLmF0dHJLZXlzW2tdLGVkaXRhYmxlLmF0dHJWYWx1ZXNba10pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIEdldCB0aGUgZWRpdG9yIGNvbnRlbnRcbiAgICAgICAgICAgIG9sZEVsZW1lbnQuaHRtbChjdXJyZW50Q29udGVudCk7XG5cbiAgICAgICAgICAgIGVkaXRvci5yZXBsYWNlV2l0aChvbGRFbGVtZW50KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWRpdG9yLmhpZGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmlnZ2VyIHRoZSBvbkJsdXIgaG9va1xuICAgICAgICBvcHRpb25zLm9uQmx1cih0aGlzKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gIH07XG5cbiAvKiBNQVJLRE9XTiBQTFVHSU4gREVGSU5JVElPTlxuICAqID09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cbiAgdmFyIG9sZCA9ICQuZm4ubWFya2Rvd247XG5cbiAgJC5mbi5tYXJrZG93biA9IGZ1bmN0aW9uIChvcHRpb24pIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkdGhpcyA9ICQodGhpcylcbiAgICAgICAgLCBkYXRhID0gJHRoaXMuZGF0YSgnbWFya2Rvd24nKVxuICAgICAgICAsIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvbjtcbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnbWFya2Rvd24nLCAoZGF0YSA9IG5ldyBNYXJrZG93bih0aGlzLCBvcHRpb25zKSkpXG4gICAgfSlcbiAgfTtcblxuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzID0ge307XG5cbiAgJC5mbi5tYXJrZG93bi5kZWZhdWx0cyA9IHtcbiAgICAvKiBFZGl0b3IgUHJvcGVydGllcyAqL1xuICAgIGF1dG9mb2N1czogZmFsc2UsXG4gICAgaGlkZWFibGU6IGZhbHNlLFxuICAgIHNhdmFibGU6IGZhbHNlLFxuICAgIHdpZHRoOiAnaW5oZXJpdCcsXG4gICAgaGVpZ2h0OiAnaW5oZXJpdCcsXG4gICAgcmVzaXplOiAnbm9uZScsXG4gICAgaWNvbmxpYnJhcnk6ICdnbHlwaCcsXG4gICAgbGFuZ3VhZ2U6ICdlbicsXG4gICAgaW5pdGlhbHN0YXRlOiAnZWRpdG9yJyxcbiAgICBwYXJzZXI6IG51bGwsXG5cbiAgICAvKiBCdXR0b25zIFByb3BlcnRpZXMgKi9cbiAgICBidXR0b25zOiBbXG4gICAgICBbe1xuICAgICAgICBuYW1lOiAnZ3JvdXBGb250JyxcbiAgICAgICAgZGF0YTogW3tcbiAgICAgICAgICBuYW1lOiAnY21kQm9sZCcsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtCJyxcbiAgICAgICAgICB0aXRsZTogJ0JvbGQnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWJvbGQnLCBmYTogJ2ZhIGZhLWJvbGQnLCAnZmEtMyc6ICdpY29uLWJvbGQnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gR2l2ZS9yZW1vdmUgKiogc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnc3Ryb25nIHRleHQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNodW5rID0gc2VsZWN0ZWQudGV4dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdHJhbnNmb3JtIHNlbGVjdGlvbiBhbmQgc2V0IHRoZSBjdXJzb3IgaW50byBjaHVua2VkIHRleHRcbiAgICAgICAgICAgIGlmIChjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC0yLDIpID09PSAnKionXG4gICAgICAgICAgICAgICAgJiYgY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuZW5kLDIpID09PSAnKionICkge1xuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihzZWxlY3RlZC5zdGFydC0yLHNlbGVjdGVkLmVuZCsyKTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKGNodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQtMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignKionK2NodW5rKycqKicpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSx7XG4gICAgICAgICAgbmFtZTogJ2NtZEl0YWxpYycsXG4gICAgICAgICAgdGl0bGU6ICdJdGFsaWMnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrSScsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24taXRhbGljJywgZmE6ICdmYSBmYS1pdGFsaWMnLCAnZmEtMyc6ICdpY29uLWl0YWxpYycgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBHaXZlL3JlbW92ZSAqIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKTtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2VtcGhhc2l6ZWQgdGV4dCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLnN0YXJ0LTEsMSkgPT09ICdfJ1xuICAgICAgICAgICAgICAgICYmIGNvbnRlbnQuc3Vic3RyKHNlbGVjdGVkLmVuZCwxKSA9PT0gJ18nICkge1xuICAgICAgICAgICAgICBlLnNldFNlbGVjdGlvbihzZWxlY3RlZC5zdGFydC0xLHNlbGVjdGVkLmVuZCsxKTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKGNodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQtMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignXycrY2h1bmsrJ18nKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0se1xuICAgICAgICAgIG5hbWU6ICdjbWRIZWFkaW5nJyxcbiAgICAgICAgICB0aXRsZTogJ0hlYWRpbmcnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrSCcsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24taGVhZGVyJywgZmE6ICdmYSBmYS1oZWFkZXInLCAnZmEtMyc6ICdpY29uLWZvbnQnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gQXBwZW5kL3JlbW92ZSAjIyMgc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpLCBwb2ludGVyLCBwcmV2Q2hhcjtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2hlYWRpbmcgdGV4dCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0ICsgJ1xcbic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoKHBvaW50ZXIgPSA0LCBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC1wb2ludGVyLHBvaW50ZXIpID09PSAnIyMjICcpXG4gICAgICAgICAgICAgICAgfHwgKHBvaW50ZXIgPSAzLCBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5zdGFydC1wb2ludGVyLHBvaW50ZXIpID09PSAnIyMjJykpIHtcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oc2VsZWN0ZWQuc3RhcnQtcG9pbnRlcixzZWxlY3RlZC5lbmQpO1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oY2h1bmspO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydC1wb2ludGVyO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzZWxlY3RlZC5zdGFydCA+IDAgJiYgKHByZXZDaGFyID0gY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtMSwxKSwgISFwcmV2Q2hhciAmJiBwcmV2Q2hhciAhPSAnXFxuJykpIHtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdcXG5cXG4jIyMgJytjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzY7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBFbXB0eSBzdHJpbmcgYmVmb3JlIGVsZW1lbnRcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCcjIyMgJytjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XVxuICAgICAgfSx7XG4gICAgICAgIG5hbWU6ICdncm91cExpbmsnLFxuICAgICAgICBkYXRhOiBbe1xuICAgICAgICAgIG5hbWU6ICdjbWRVcmwnLFxuICAgICAgICAgIHRpdGxlOiAnVVJML0xpbmsnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrTCcsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tbGluaycsIGZhOiAnZmEgZmEtbGluaycsICdmYS0zJzogJ2ljb24tbGluaycgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBHaXZlIFtdIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb24gYW5kIHByZXBlbmQgdGhlIGxpbmtcbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKSwgbGluaztcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsaW5rID0gcHJvbXB0KGUuX19sb2NhbGl6ZSgnSW5zZXJ0IEh5cGVybGluaycpLCdodHRwOi8vJyk7XG5cbiAgICAgICAgICAgIHZhciB1cmxSZWdleCA9IG5ldyBSZWdFeHAoJ14oKGh0dHB8aHR0cHMpOi8vfChtYWlsdG86KXwoLy8pKVthLXowLTldJywgJ2knKTtcbiAgICAgICAgICAgIGlmIChsaW5rICE9PSBudWxsICYmIGxpbmsgIT09ICcnICYmIGxpbmsgIT09ICdodHRwOi8vJyAmJiB1cmxSZWdleC50ZXN0KGxpbmspKSB7XG4gICAgICAgICAgICAgIHZhciBzYW5pdGl6ZWRMaW5rID0gJCgnPGRpdj4nK2xpbmsrJzwvZGl2PicpLnRleHQoKTtcblxuICAgICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ1snK2NodW5rKyddKCcrc2FuaXRpemVkTGluaysnKScpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsxO1xuXG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0se1xuICAgICAgICAgIG5hbWU6ICdjbWRJbWFnZScsXG4gICAgICAgICAgdGl0bGU6ICdJbWFnZScsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtHJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1waWN0dXJlJywgZmE6ICdmYSBmYS1waWN0dXJlLW8nLCAnZmEtMyc6ICdpY29uLXBpY3R1cmUnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gR2l2ZSAhW10gc3Vycm91bmQgdGhlIHNlbGVjdGlvbiBhbmQgcHJlcGVuZCB0aGUgaW1hZ2UgbGlua1xuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpLCBsaW5rO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsaW5rID0gcHJvbXB0KGUuX19sb2NhbGl6ZSgnSW5zZXJ0IEltYWdlIEh5cGVybGluaycpLCdodHRwOi8vJyk7XG5cbiAgICAgICAgICAgIHZhciB1cmxSZWdleCA9IG5ldyBSZWdFeHAoJ14oKGh0dHB8aHR0cHMpOi8vfCgvLykpW2EtejAtOV0nLCAnaScpO1xuICAgICAgICAgICAgaWYgKGxpbmsgIT09IG51bGwgJiYgbGluayAhPT0gJycgJiYgbGluayAhPT0gJ2h0dHA6Ly8nICYmIHVybFJlZ2V4LnRlc3QobGluaykpIHtcbiAgICAgICAgICAgICAgdmFyIHNhbml0aXplZExpbmsgPSAkKCc8ZGl2PicrbGluaysnPC9kaXY+JykudGV4dCgpO1xuXG4gICAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignIVsnK2NodW5rKyddKCcrc2FuaXRpemVkTGluaysnIFwiJytlLl9fbG9jYWxpemUoJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnKSsnXCIpJyk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG5cbiAgICAgICAgICAgICAgLy8gU2V0IHRoZSBuZXh0IHRhYlxuICAgICAgICAgICAgICBlLnNldE5leHRUYWIoZS5fX2xvY2FsaXplKCdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJykpO1xuXG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1dXG4gICAgICB9LHtcbiAgICAgICAgbmFtZTogJ2dyb3VwTWlzYycsXG4gICAgICAgIGRhdGE6IFt7XG4gICAgICAgICAgbmFtZTogJ2NtZExpc3QnLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrVScsXG4gICAgICAgICAgdGl0bGU6ICdVbm9yZGVyZWQgTGlzdCcsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tbGlzdCcsIGZhOiAnZmEgZmEtbGlzdCcsICdmYS0zJzogJ2ljb24tbGlzdC11bCcgfSxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICAvLyBQcmVwZW5kL0dpdmUgLSBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgnbGlzdCB0ZXh0IGhlcmUnKTtcblxuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJy0gJytjaHVuayk7XG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWQudGV4dC5pbmRleE9mKCdcXG4nKSA8IDApIHtcbiAgICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJy0gJytjaHVuayk7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzI7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpc3QgPSBbXTtcblxuICAgICAgICAgICAgICAgIGxpc3QgPSBzZWxlY3RlZC50ZXh0LnNwbGl0KCdcXG4nKTtcbiAgICAgICAgICAgICAgICBjaHVuayA9IGxpc3RbMF07XG5cbiAgICAgICAgICAgICAgICAkLmVhY2gobGlzdCxmdW5jdGlvbihrLHYpIHtcbiAgICAgICAgICAgICAgICAgIGxpc3Rba10gPSAnLSAnK3Y7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ1xcblxcbicrbGlzdC5qb2luKCdcXG4nKSk7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKGN1cnNvcixjdXJzb3IrY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnY21kTGlzdE8nLFxuICAgICAgICAgIGhvdGtleTogJ0N0cmwrTycsXG4gICAgICAgICAgdGl0bGU6ICdPcmRlcmVkIExpc3QnLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLXRoLWxpc3QnLCBmYTogJ2ZhIGZhLWxpc3Qtb2wnLCAnZmEtMyc6ICdpY29uLWxpc3Qtb2wnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpIHtcblxuICAgICAgICAgICAgLy8gUHJlcGVuZC9HaXZlIC0gc3Vycm91bmQgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgdmFyIGNodW5rLCBjdXJzb3IsIHNlbGVjdGVkID0gZS5nZXRTZWxlY3Rpb24oKSwgY29udGVudCA9IGUuZ2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm0gc2VsZWN0aW9uIGFuZCBzZXQgdGhlIGN1cnNvciBpbnRvIGNodW5rZWQgdGV4dFxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2xpc3QgdGV4dCBoZXJlJyk7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignMS4gJytjaHVuayk7XG4gICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0KzM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWQudGV4dC5pbmRleE9mKCdcXG4nKSA8IDApIHtcbiAgICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG5cbiAgICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJzEuICcrY2h1bmspO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCszO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ID0gW107XG5cbiAgICAgICAgICAgICAgICBsaXN0ID0gc2VsZWN0ZWQudGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBsaXN0WzBdO1xuXG4gICAgICAgICAgICAgICAgJC5lYWNoKGxpc3QsZnVuY3Rpb24oayx2KSB7XG4gICAgICAgICAgICAgICAgICBsaXN0W2tdID0gJzEuICcrdjtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignXFxuXFxuJytsaXN0LmpvaW4oJ1xcbicpKTtcblxuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQrNTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdjbWRDb2RlJyxcbiAgICAgICAgICBob3RrZXk6ICdDdHJsK0snLFxuICAgICAgICAgIHRpdGxlOiAnQ29kZScsXG4gICAgICAgICAgaWNvbjogeyBnbHlwaDogJ2dseXBoaWNvbiBnbHlwaGljb24tYXN0ZXJpc2snLCBmYTogJ2ZhIGZhLWNvZGUnLCAnZmEtMyc6ICdpY29uLWNvZGUnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIC8vIEdpdmUvcmVtb3ZlICoqIHN1cnJvdW5kIHRoZSBzZWxlY3Rpb25cbiAgICAgICAgICAgIHZhciBjaHVuaywgY3Vyc29yLCBzZWxlY3RlZCA9IGUuZ2V0U2VsZWN0aW9uKCksIGNvbnRlbnQgPSBlLmdldENvbnRlbnQoKTtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGV4dHJhIHdvcmRcbiAgICAgICAgICAgICAgY2h1bmsgPSBlLl9fbG9jYWxpemUoJ2NvZGUgdGV4dCBoZXJlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjaHVuayA9IHNlbGVjdGVkLnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtNCw0KSA9PT0gJ2BgYFxcbidcbiAgICAgICAgICAgICAgICAmJiBjb250ZW50LnN1YnN0cihzZWxlY3RlZC5lbmQsNCkgPT09ICdcXG5gYGAnKSB7XG4gICAgICAgICAgICAgIGUuc2V0U2VsZWN0aW9uKHNlbGVjdGVkLnN0YXJ0LTQsIHNlbGVjdGVkLmVuZCs0KTtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKGNodW5rKTtcbiAgICAgICAgICAgICAgY3Vyc29yID0gc2VsZWN0ZWQuc3RhcnQtNDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuc3RhcnQtMSwxKSA9PT0gJ2AnXG4gICAgICAgICAgICAgICAgJiYgY29udGVudC5zdWJzdHIoc2VsZWN0ZWQuZW5kLDEpID09PSAnYCcpIHtcbiAgICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oc2VsZWN0ZWQuc3RhcnQtMSxzZWxlY3RlZC5lbmQrMSk7XG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbihjaHVuayk7XG4gICAgICAgICAgICAgIGN1cnNvciA9IHNlbGVjdGVkLnN0YXJ0LTE7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbnRlbnQuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICAgICAgICBlLnJlcGxhY2VTZWxlY3Rpb24oJ2BgYFxcbicrY2h1bmsrJ1xcbmBgYCcpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCs0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdgJytjaHVuaysnYCcpO1xuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgZS5zZXRTZWxlY3Rpb24oY3Vyc29yLGN1cnNvcitjaHVuay5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdjbWRRdW90ZScsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtRJyxcbiAgICAgICAgICB0aXRsZTogJ1F1b3RlJyxcbiAgICAgICAgICBpY29uOiB7IGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1jb21tZW50JywgZmE6ICdmYSBmYS1xdW90ZS1sZWZ0JywgJ2ZhLTMnOiAnaWNvbi1xdW90ZS1sZWZ0JyB9LFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAvLyBQcmVwZW5kL0dpdmUgLSBzdXJyb3VuZCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICB2YXIgY2h1bmssIGN1cnNvciwgc2VsZWN0ZWQgPSBlLmdldFNlbGVjdGlvbigpLCBjb250ZW50ID0gZS5nZXRDb250ZW50KCk7XG5cbiAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBzZWxlY3Rpb24gYW5kIHNldCB0aGUgY3Vyc29yIGludG8gY2h1bmtlZCB0ZXh0XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIC8vIEdpdmUgZXh0cmEgd29yZFxuICAgICAgICAgICAgICBjaHVuayA9IGUuX19sb2NhbGl6ZSgncXVvdGUgaGVyZScpO1xuXG4gICAgICAgICAgICAgIGUucmVwbGFjZVNlbGVjdGlvbignPiAnK2NodW5rKTtcblxuICAgICAgICAgICAgICAvLyBTZXQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkLnRleHQuaW5kZXhPZignXFxuJykgPCAwKSB7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBzZWxlY3RlZC50ZXh0O1xuXG4gICAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCc+ICcrY2h1bmspO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCsyO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ID0gW107XG5cbiAgICAgICAgICAgICAgICBsaXN0ID0gc2VsZWN0ZWQudGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICAgICAgICAgICAgY2h1bmsgPSBsaXN0WzBdO1xuXG4gICAgICAgICAgICAgICAgJC5lYWNoKGxpc3QsZnVuY3Rpb24oayx2KSB7XG4gICAgICAgICAgICAgICAgICBsaXN0W2tdID0gJz4gJyt2O1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgZS5yZXBsYWNlU2VsZWN0aW9uKCdcXG5cXG4nK2xpc3Quam9pbignXFxuJykpO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICBjdXJzb3IgPSBzZWxlY3RlZC5zdGFydCs0O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY3Vyc29yXG4gICAgICAgICAgICBlLnNldFNlbGVjdGlvbihjdXJzb3IsY3Vyc29yK2NodW5rLmxlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XVxuICAgICAgfSx7XG4gICAgICAgIG5hbWU6ICdncm91cFV0aWwnLFxuICAgICAgICBkYXRhOiBbe1xuICAgICAgICAgIG5hbWU6ICdjbWRQcmV2aWV3JyxcbiAgICAgICAgICB0b2dnbGU6IHRydWUsXG4gICAgICAgICAgaG90a2V5OiAnQ3RybCtQJyxcbiAgICAgICAgICB0aXRsZTogJ1ByZXZpZXcnLFxuICAgICAgICAgIGJ0blRleHQ6ICdQcmV2aWV3JyxcbiAgICAgICAgICBidG5DbGFzczogJ2J0biBidG4tcHJpbWFyeSBidG4tc20nLFxuICAgICAgICAgIGljb246IHsgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLXNlYXJjaCcsIGZhOiAnZmEgZmEtc2VhcmNoJywgJ2ZhLTMnOiAnaWNvbi1zZWFyY2gnIH0sXG4gICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHByZXZpZXcgbW9kZSBhbmQgdG9nZ2xlIGJhc2VkIG9uIHRoaXMgZmxhZ1xuICAgICAgICAgICAgdmFyIGlzUHJldmlldyA9IGUuJGlzUHJldmlldyxjb250ZW50O1xuXG4gICAgICAgICAgICBpZiAoaXNQcmV2aWV3ID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAvLyBHaXZlIGZsYWcgdGhhdCB0ZWxsIHRoZSBlZGl0b3IgZW50ZXIgcHJldmlldyBtb2RlXG4gICAgICAgICAgICAgIGUuc2hvd1ByZXZpZXcoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGUuaGlkZVByZXZpZXcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1dXG4gICAgICB9XVxuICAgIF0sXG4gICAgYWRkaXRpb25hbEJ1dHRvbnM6W10sIC8vIFBsYWNlIHRvIGhvb2sgbW9yZSBidXR0b25zIGJ5IGNvZGVcbiAgICByZW9yZGVyQnV0dG9uR3JvdXBzOltdLFxuICAgIGhpZGRlbkJ1dHRvbnM6W10sIC8vIERlZmF1bHQgaGlkZGVuIGJ1dHRvbnNcbiAgICBkaXNhYmxlZEJ1dHRvbnM6W10sIC8vIERlZmF1bHQgZGlzYWJsZWQgYnV0dG9uc1xuICAgIGZvb3RlcjogJycsXG4gICAgZnVsbHNjcmVlbjoge1xuICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgaWNvbnM6IHtcbiAgICAgICAgZnVsbHNjcmVlbk9uOiB7XG4gICAgICAgICAgZmE6ICdmYSBmYS1leHBhbmQnLFxuICAgICAgICAgIGdseXBoOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1mdWxsc2NyZWVuJyxcbiAgICAgICAgICAnZmEtMyc6ICdpY29uLXJlc2l6ZS1mdWxsJ1xuICAgICAgICB9LFxuICAgICAgICBmdWxsc2NyZWVuT2ZmOiB7XG4gICAgICAgICAgZmE6ICdmYSBmYS1jb21wcmVzcycsXG4gICAgICAgICAgZ2x5cGg6ICdnbHlwaGljb24gZ2x5cGhpY29uLWZ1bGxzY3JlZW4nLFxuICAgICAgICAgICdmYS0zJzogJ2ljb24tcmVzaXplLXNtYWxsJ1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcblxuICAgIC8qIEV2ZW50cyBob29rICovXG4gICAgb25TaG93OiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25QcmV2aWV3OiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25TYXZlOiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25CbHVyOiBmdW5jdGlvbiAoZSkge30sXG4gICAgb25Gb2N1czogZnVuY3Rpb24gKGUpIHt9LFxuICAgIG9uQ2hhbmdlOiBmdW5jdGlvbihlKSB7fSxcbiAgICBvbkZ1bGxzY3JlZW46IGZ1bmN0aW9uKGUpIHt9LFxuICAgIG9uU2VsZWN0OiBmdW5jdGlvbiAoZSkge31cbiAgfTtcblxuICAkLmZuLm1hcmtkb3duLkNvbnN0cnVjdG9yID0gTWFya2Rvd247XG5cblxuIC8qIE1BUktET1dOIE5PIENPTkZMSUNUXG4gICogPT09PT09PT09PT09PT09PT09PT0gKi9cblxuICAkLmZuLm1hcmtkb3duLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi5tYXJrZG93biA9IG9sZDtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICAvKiBNQVJLRE9XTiBHTE9CQUwgRlVOQ1RJT04gJiBEQVRBLUFQSVxuICAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuICB2YXIgaW5pdE1hcmtkb3duID0gZnVuY3Rpb24oZWwpIHtcbiAgICB2YXIgJHRoaXMgPSBlbDtcblxuICAgIGlmICgkdGhpcy5kYXRhKCdtYXJrZG93bicpKSB7XG4gICAgICAkdGhpcy5kYXRhKCdtYXJrZG93bicpLnNob3dFZGl0b3IoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAkdGhpcy5tYXJrZG93bigpXG4gIH07XG5cbiAgdmFyIGJsdXJOb25Gb2N1c2VkID0gZnVuY3Rpb24oZSkge1xuICAgIHZhciAkYWN0aXZlRWxlbWVudCA9ICQoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCk7XG5cbiAgICAvLyBCbHVyIGV2ZW50XG4gICAgJChkb2N1bWVudCkuZmluZCgnLm1kLWVkaXRvcicpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgIHZhciAkdGhpcyAgICAgICAgICAgID0gJCh0aGlzKSxcbiAgICAgICAgICBmb2N1c2VkICAgICAgICAgID0gJGFjdGl2ZUVsZW1lbnQuY2xvc2VzdCgnLm1kLWVkaXRvcicpWzBdID09PSB0aGlzLFxuICAgICAgICAgIGF0dGFjaGVkTWFya2Rvd24gPSAkdGhpcy5maW5kKCd0ZXh0YXJlYScpLmRhdGEoJ21hcmtkb3duJykgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMuZmluZCgnZGl2W2RhdGEtcHJvdmlkZXI9XCJtYXJrZG93bi1wcmV2aWV3XCJdJykuZGF0YSgnbWFya2Rvd24nKTtcblxuICAgICAgaWYgKGF0dGFjaGVkTWFya2Rvd24gJiYgIWZvY3VzZWQpIHtcbiAgICAgICAgYXR0YWNoZWRNYXJrZG93bi5ibHVyKCk7XG4gICAgICB9XG4gICAgfSlcbiAgfTtcblxuICAkKGRvY3VtZW50KVxuICAgIC5vbignY2xpY2subWFya2Rvd24uZGF0YS1hcGknLCAnW2RhdGEtcHJvdmlkZT1cIm1hcmtkb3duLWVkaXRhYmxlXCJdJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGluaXRNYXJrZG93bigkKHRoaXMpKTtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9KVxuICAgIC5vbignY2xpY2sgZm9jdXNpbicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBibHVyTm9uRm9jdXNlZChlKTtcbiAgICB9KVxuICAgIC5yZWFkeShmdW5jdGlvbigpe1xuICAgICAgJCgndGV4dGFyZWFbZGF0YS1wcm92aWRlPVwibWFya2Rvd25cIl0nKS5lYWNoKGZ1bmN0aW9uKCl7XG4gICAgICAgIGluaXRNYXJrZG93bigkKHRoaXMpKTtcbiAgICAgIH0pXG4gICAgfSk7XG5cbn0pKTtcbiIsIi8qXG4gKiBBcmFiaWMgdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogR2VvcmdlIEFqYW0gPGdlb3JnZS5lamFhbUBnbWFpbC5jb20+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLm5sID0ge1xuICAgICdCb2xkJzogXCLYutin2YXZglwiLFxuICAgICdJdGFsaWMnOiBcItmF2KfYptmEXCIsXG4gICAgJ0hlYWRpbmcnOiBcIti52YbZiNin2YZcIixcbiAgICAnVVJML0xpbmsnOiBcIlVSTC/Ysdin2KjYt1wiLFxuICAgICdJbWFnZSc6IFwi2LXZiNix2KlcIixcbiAgICAnTGlzdCc6IFwi2YLYp9im2YXYqVwiLFxuICAgICdQcmV2aWV3JzogXCLYp9iz2KrYudix2KfYtlwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwi2YbYtSDYutin2YXZglwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcItmG2LUg2YfYp9mFXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwi2KfZhNi52YbZiNin2YZcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCLYp9iv2K7ZhCDZiNi12YEg2KfZhNix2KfYqNi3INmH2YbYp1wiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCLYp9iv2K7ZhCDYp9mE2LHYp9io2Lcg2YfZhtinXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcItin2K/YrtmEINmI2LXZgSDYp9mE2LXZiNix2Kkg2YfZhtinXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcItin2K/YrtmEINix2KfYqNi3INin2YTYtdmI2LHYqSDZh9mG2KdcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwi2KfYr9iu2YQg2LnZhtmI2KfZhiDYp9mE2LXZiNix2Kkg2YfZhtinXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCLYp9mD2KrYqCDYp9mE2YbYtSDZh9mG2KdcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogQ3plY2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogVsOtdCBLYWJlbGUgPHZpdEBrYWJlbGUubWU+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLmNzID0ge1xuICAgICdCb2xkJzogXCJUdcSNbsSbXCIsXG4gICAgJ0l0YWxpYyc6IFwiS3VyesOtdmFcIixcbiAgICAnSGVhZGluZyc6IFwiTmFkcGlzXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJVUkwvT2RrYXpcIixcbiAgICAnSW1hZ2UnOiBcIk9icsOhemVrXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJTZXpuYW1cIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCJTZcWZYXplbsO9IHNlem5hbVwiLFxuICAgICdDb2RlJzogXCLDmnNlayBrw7NkdVwiLFxuICAgICdRdW90ZSc6IFwiQ2l0YWNlXCIsXG4gICAgJ1ByZXZpZXcnOiBcIk7DoWhsZWRcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcInR1xI1uw70gdGV4dFwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcInpkxa9yYXpuxJtuw70gdGV4dFwiLFxuICAgICdoZWFkaW5nIHRleHQnOiBcInRleHQgbmFkcGlzdVwiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcInNlbSB2bG/FviBwb3BpcyBvZGthenVcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiVmxvxb5pdCBIeXBlcmxpbmtcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwic2VtIHZsb8W+IHBvcGlzIG9icsOhemt1XCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIlZsb8W+IGFkcmVzdSBvYnLDoXprdVwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJzZW0gdmxvxb4gcG9waXMgb2Jyw6F6a3VcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcInBvbG/FvmthIHNlem5hbXVcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogRGFuaXNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIERhbiBTdG9ybSA8c3Rvcm1AY2F0YWx5c3Rjb2RlLm5ldD5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMubmIgPSB7XG4gICAgJ0JvbGQnOiAnRmVkJyxcbiAgICAnSXRhbGljJzogJ0t1cnNpdicsXG4gICAgJ0hlYWRpbmcnOiAnT3ZlcnNrcmlmdCcsXG4gICAgJ1VSTC9MaW5rJzogJ1VSTC9MaW5rJyxcbiAgICAnSW1hZ2UnOiAnQmlsbGVkZScsXG4gICAgJ0xpc3QnOiAnTGlzdGUnLFxuICAgICdQcmV2aWV3JzogJ0ZvcmjDpW5kc3Zpc25pbmcnLFxuICAgICdzdHJvbmcgdGV4dCc6ICdzdMOmcmsgdGVrc3QnLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiAnZnJlbWjDpnZldCB0ZWtzdCcsXG4gICAgJ2hlYWRpbmcgdGV4dCc6ICdvdmVyc2tyaWZ0IHRla3N0JyxcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogJ1Nrcml2IGxpbmsgYmVza3JpdmVsc2UgaGVyJyxcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6ICdJbmRzw6Z0IGxpbmsnLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogJ0luZHPDpnQgYmlsbGVkZSBiZXNrcml2ZWxzZSBoZXInLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogJ0luZHPDpnQgYmlsbGVkZSBsaW5rJyxcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6ICdJbmRzw6Z0IGJpbGxlZGUgdGl0ZWwnLFxuICAgICdsaXN0IHRleHQgaGVyZSc6ICdJbmRzw6Z0IGxpc3RlIHRla3N0IGhlcicsXG4gICAgJ3F1b3RlIGhlcmUnOiAnSW5kc8OmdCBjaXRhdCBoZXInLFxuICAgICdjb2RlIHRleHQgaGVyZSc6ICdJbmRzw6Z0IGtvZGUgaGVyJ1xuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogR2VybWFuIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIFRvYmlhcyBOaXRzY2hlIDx0b2JpYXMtbml0c2NoZUBnbXgubmV0PlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5kZSA9IHtcbiAgICAnQm9sZCc6IFwiRmV0dFwiLFxuICAgICdJdGFsaWMnOiBcIkt1cnNpdlwiLFxuICAgICdIZWFkaW5nJzogXCLDnGJlcnNjaHJpZnRcIixcbiAgICAnVVJML0xpbmsnOiBcIkxpbmsgaGluenVmw7xnZW5cIixcbiAgICAnSW1hZ2UnOiBcIkJpbGQgaGluenVmw7xnZW5cIixcbiAgICAnVW5vcmRlcmVkIExpc3QnOiBcIlVubnVtbWVyaWVydGUgTGlzdGVcIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCJOdW1tZXJpZXJ0ZSBMaXN0ZVwiLFxuICAgICdDb2RlJzogXCJRdWVsbHRleHRcIixcbiAgICAnUXVvdGUnOiBcIlppdGF0XCIsXG4gICAgJ1ByZXZpZXcnOiBcIlZvcnNjaGF1XCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJTZWhyIGJldG9udGVyIFRleHRcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJCZXRvbnRlciBUZXh0XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwiw5xiZXJzY2hyaWZ0IFRleHRcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJMaW5rYmVzY2hyZWlidW5nXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIlVSTFwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJCaWxkYmVzY2hyZWlidW5nXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIkJpbGQtVVJMXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIlRpdGVsIGRlcyBCaWxkZXNcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcIkF1ZnrDpGhsdW5ncy1UZXh0XCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIFNwYW5pc2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogYnkgTGVhbmRybyBQb2JsZXQgPGxlYW5kcm9kcmhvdXNlQGdtYWlsLmNvbT5cbiAqL1xuOyhmdW5jdGlvbigkKXtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlc1snZXMnXSA9IHtcbiAgICAnQm9sZCc6IFwiTmVncml0YVwiLFxuICAgICdJdGFsaWMnOiBcIkl0w6FsaWNhXCIsXG4gICAgJ0hlYWRpbmcnOiBcIlTDrXR1bG9cIixcbiAgICAnVVJML0xpbmsnOiBcIkluc2VydGUgdW4gbGlua1wiLFxuICAgICdJbWFnZSc6IFwiSW5zZXJ0ZSB1bmEgaW1hZ2VuXCIsXG4gICAgJ0xpc3QnOiBcIkxpc3RhIGRlIGl0ZW1zXCIsXG4gICAgJ1ByZXZpZXcnOiBcIlByZXZpc3VhbGl6YXJcIixcbiAgICAnc3Ryb25nIHRleHQnOiBcInRleHRvIGltcG9ydGFudGVcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCJ0ZXh0byBjb24gw6luZmFzaXNcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJ0ZXh0byB0aXR1bGFyXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwiZGVzY3JpcGNpw7NuIGRlbCBsaW5rXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIkluc2VydGUgdW4gaGlwZXJ2w61uY3Vsb1wiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJkZXNjcmlwY2nDs24gZGUgbGEgaW1hZ2VuXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIkluc2VydGUgdW5hIGltYWdlbiBjb24gdW4gaGlwZXJ2w61uY3Vsb1wiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJJbnNlcnRlIHVuYSBpbWFnZW4gY29uIHTDrXR1bG9cIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcImxpc3RhIGNvbiB0ZXh0b1wiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBQZXJzaWFuKEZhcnNpKSB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBTYWphZCBEZWhzaGlyaSA8UGVsYWt3ZWIuaXI+XG4gKi9cbihmdW5jdGlvbiAoJCkge1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzLmZhID0ge1xuICAgICdCb2xkJzogXCLYqtmI2b7YsVwiLFxuICAgICdJdGFsaWMnOiBcItmF2YjYsdioXCIsXG4gICAgJ0hlYWRpbmcnOiBcIti52YbZiNin2YZcIixcbiAgICAnVVJML0xpbmsnOiBcItm+24zZiNmG2K9cIixcbiAgICAnSW1hZ2UnOiBcItiq2LXZiNuM2LFcIixcbiAgICAnTGlzdCc6IFwi2YHZh9ix2LPYqlwiLFxuICAgICdQcmV2aWV3JzogXCLZvtuM2LQg2YbZhdin24zYtFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwi2YXYqtmGINi22K7bjNmFXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwi2YbZiNi02KrZhyDYqtin2qnbjNiv24xcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLYudmG2YjYp9mGXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwi2KrZiNi224zYrdin2Kog2b7bjNmI2YbYryDYsdinINio2YbZiNuM2LPbjNivLlwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCLZvtuM2YjZhtivINix2Kcg2K/YsdisINmG2YXYp9uM24zYrzpcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwi2KrZiNi224zYrduMINio2LHYp9uMINiq2LXZiNuMINio2YbZiNuM2LPbjNivLlwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCLYotiv2LHYsyDYqti12YjbjNixINix2Kcg2KjZhtmI24zYs9uM2K8uXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIti52YbZiNin2YYg2KrYtdmI24zYsSDYsdinINin24zZhtis2Kcg2KjZhtmI24zYs9uM2K9cIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcItmF2K3ZhCDZhdiq2YYg2YHZh9ix2LPYqlwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBGcmVuY2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogQmVub8OudCBCb3VyZ2VvaXMgPGJpZXJkb2tAZ21haWwuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5mciA9IHtcbiAgICAnQm9sZCc6IFwiR3Jhc1wiLFxuICAgICdJdGFsaWMnOiBcIkl0YWxpcXVlXCIsXG4gICAgJ0hlYWRpbmcnOiBcIlRpdHJlXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJJbnPDqXJlciB1biBsaWVuIEhUVFBcIixcbiAgICAnSW1hZ2UnOiBcIkluc8OpcmVyIHVuZSBpbWFnZVwiLFxuICAgICdMaXN0JzogXCJMaXN0ZSDDoCBwdWNlc1wiLFxuICAgICdQcmV2aWV3JzogXCJQcsOpdmlzdWFsaXNlclwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwidGV4dGUgaW1wb3J0YW50XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwidGV4dGUgZW4gaXRhbGlxdWVcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCJ0ZXh0ZSBkJ2VudMOqdGVcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJlbnRyZXogbGEgZGVzY3JpcHRpb24gZHUgbGllbiBpY2lcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiSW5zw6lyZXogbGUgbGllbiBoeXBlcnRleHRlXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcImVudHJleiBsYSBkZXNjcmlwdGlvbiBkZSBsJ2ltYWdlIGljaVwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJJbnPDqXJleiBsZSBsaWVuIGh5cGVydGV4dGUgZGUgbCdpbWFnZVwiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJlbnRyZXogbGUgdGl0cmUgZGUgbCdpbWFnZSBpY2lcIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcInRleHRlIMOgIHB1Y2UgaWNpXCIsXG4gICAgJ1NhdmUnOiBcIlNhdXZlZ2FyZGVyXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwiTGlzdGUgb3Jkb25uw6llXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJMaXN0ZSBkw6lzb3Jkb25uw6llXCIsXG4gICAgJ1F1b3RlJzogXCJDaXRhdGlvblwiLFxuICAgICdxdW90ZSBoZXJlJzogXCJWb3RyZSBjaXRhdGlvblwiLFxuICAgICdDb2RlJzogXCJDb2RlXCIsXG4gICAgJ2NvZGUgdGV4dCBoZXJlJzogXCLDqWNyaXJlIGR1IGNvZGUgaWNpXCJcbiAgfTtcbn0oalF1ZXJ5KSk7XG4iLCIvKipcbiAqIEphcGFuZXNlIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIEtlbnRhIE11cmFrYW1pIDxrbnRtcmttQGdtYWlsLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXNbJ2phJ10gPSB7XG4gICAgJ0JvbGQnOiBcIuWkquWtl1wiLFxuICAgICdJdGFsaWMnOiBcIuaWnOS9k1wiLFxuICAgICdIZWFkaW5nJzogXCLopovlh7rjgZdcIixcbiAgICAnVVJML0xpbmsnOiBcIuODquODs+OCr1wiLFxuICAgICdJbWFnZSc6IFwi55S75YOPXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCLjg6rjgrnjg4hcIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCLmlbDlrZfjg6rjgrnjg4hcIixcbiAgICAnQ29kZSc6IFwi44Kz44O844OJXCIsXG4gICAgJ1F1b3RlJzogXCLlvJXnlKhcIixcbiAgICAnUHJldmlldyc6IFwi44OX44Os44OT44Ol44O8XCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCLlpKrlrZdcIixcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogXCLlvLfoqr9cIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLopovlh7rjgZdcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCLjg6rjg7Pjgq/oqqzmmI5cIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwi44Oq44Oz44Kv5oy/5YWlXCIsXG4gICAgJ2VudGVyIGltYWdlIGRlc2NyaXB0aW9uIGhlcmUnOiBcIueUu+WDj+iqrOaYjlwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCLnlLvlg4/mjL/lhaVcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwi55S75YOP44K/44Kk44OI44OrXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCLjg6rjgrnjg4jmjL/lhaVcIixcbiAgICAnY29kZSB0ZXh0IGhlcmUnOiBcIuOCs+ODvOODiVwiLFxuICAgICdxdW90ZSBoZXJlJzogXCLlvJXnlKjmjL/lhaVcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICsgKiBLb3JlYW4gdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICsgKiBXb29uZ0JpIEtpbSA8c3NpbnNzQGdtYWlsLmNvbT5cbiArICovXG47KGZ1bmN0aW9uKCQpe1xuICAkLmZuLm1hcmtkb3duLm1lc3NhZ2VzWydrciddID0ge1xuICAgICdCb2xkJzogXCLsp4TtlZjqsoxcIixcbiAgICAnSXRhbGljJzogXCLsnbTtg6Trpq3ssrRcIixcbiAgICAnSGVhZGluZyc6IFwi66i466as6riAXCIsXG4gICAgJ1VSTC9MaW5rJzogXCLrp4Htgazso7zshoxcIixcbiAgICAnSW1hZ2UnOiBcIuydtOuvuOyngFwiLFxuICAgICdMaXN0JzogXCLrpqzsiqTtirhcIixcbiAgICAnUHJldmlldyc6IFwi66+466as67O06riwXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCLqsJXtlZwg6rCV7KGwIO2FjeyKpO2KuFwiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcIuqwleyhsCDthY3siqTtirhcIixcbiAgICAnaGVhZGluZyB0ZXh0JzogXCLrqLjrpqzquIAg7YWN7Iqk7Yq4XCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwi7Jes6riw7JeQIOunge2BrOydmCDshKTrqoXsnYQg7KCB7Jy87IS47JqUXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIu2VmOydtO2NvOunge2BrCDsgr3snoVcIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwi7Jes6riw7IS4IOydtOuvuOyngCDshKTrqoXsnYQg7KCB7Jy87IS47JqUXCIsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiBcIuydtOuvuOyngCDrp4Htgawg7IK97J6FXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIuyXrOq4sOyXkCDsnbTrr7jsp4Ag7KCc66qp7J2EIOyggeycvOyEuOyalFwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwi66as7Iqk7Yq4IO2FjeyKpO2KuFwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBOb3J3ZWdpYW4gYm9rbcOlbCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBUb2JpYXMgQm9od2FsbGkgPGhpQGZ1dGhyLmlvPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5uYiA9IHtcbiAgICAnQm9sZCc6ICdGZXQnLFxuICAgICdJdGFsaWMnOiAnS3Vyc2l2JyxcbiAgICAnSGVhZGluZyc6ICdPdmVyc2tyaWZ0JyxcbiAgICAnVVJML0xpbmsnOiAnVVJML0xlbmtlJyxcbiAgICAnSW1hZ2UnOiAnQmlsZGUnLFxuICAgICdMaXN0JzogJ0xpc3RlJyxcbiAgICAnUHJldmlldyc6ICdGb3Jow6VuZHN2aXNuaW5nJyxcbiAgICAnc3Ryb25nIHRleHQnOiAnc3RlcmsgdGVrc3QnLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiAnc3RyZWtldCB0ZWtzdCcsXG4gICAgJ2hlYWRpbmcgdGV4dCc6ICdvdmVyc2tyaWZ0ZW4gdGVrc3QnLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiAnU2tyaXYgbGlua2VuIGJlc2tyaXZlbHNlIGhlcicsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiAnU2V0dCBpbm4gbGVua2UnLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogJ0FuZ2kgYmlsZGViZXNrcml2ZWxzZSBoZXInLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogJ1NldHQgaW5uIGxlbmtlIGZvciBiaWxkZScsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiAnQW5naSBiaWxkZXRpdHRlbCBoZXInLFxuICAgICdsaXN0IHRleHQgaGVyZSc6ICdsaXN0ZSB0ZWtzdCBoZXInXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBEdXRjaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBKZXJvZW4gVGhvcmEgPGplcm9lbnRob3JhQGdtYWlsLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMubmwgPSB7XG4gICAgJ0JvbGQnOiBcIlZldFwiLFxuICAgICdJdGFsaWMnOiBcIkN1cnNpZWZcIixcbiAgICAnSGVhZGluZyc6IFwiVGl0ZWxcIixcbiAgICAnVVJML0xpbmsnOiBcIlVSTC9MaW5rXCIsXG4gICAgJ0ltYWdlJzogXCJBZmJlZWxkaW5nXCIsXG4gICAgJ0xpc3QnOiBcIkxpanN0XCIsXG4gICAgJ1ByZXZpZXcnOiBcIlZvb3JiZWVsZFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwidmV0IGdlZHJ1a3RlIHRla3N0XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwic2NodWluIGdlZHJ1a3RlIHRla3N0XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwiVGl0ZWxcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJWb2VyIGVlbiBsaW5rIGJlc2NocmlqdmluZyBpblwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJWb2VyIGVlbiBodHRwIGxpbmsgaW5cIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwiVm9lciBlZW4gYWZiZWVsZGluZyBiZXNjaHJpanZpbmcgaW5cIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiVm9lciBlZW4gYWZiZWVsZGluZyBsaW5rIGluXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIlZvZXIgZGUgYWZiZWVsZGluZyB0aXRlbCBpblwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwibGlqc3QgaXRlbVwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBQb2xpc2ggdHJhbnNsYXRpb24gZm9yIGJvb3RzdHJhcC1tYXJrZG93blxuICogTWFyZWsgS2FwdXRcbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMucGwgPSB7XG4gICAgJ0JvbGQnOiBcIlBvZ3J1YmllbmllXCIsXG4gICAgJ0l0YWxpYyc6IFwiS3Vyc3l3YVwiLFxuICAgICdIZWFkaW5nJzogXCJOYWfFgsOzd2VrXCIsXG4gICAgJ1VSTC9MaW5rJzogXCJXc3RhdyBsaW5rXCIsXG4gICAgJ0ltYWdlJzogXCJXc3RhdyBvYnJhemVrXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJMaXN0YSBwdW5rdG93YW5hXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwiTGlzdGEgbnVtZXJvd2FuYVwiLFxuICAgICdDb2RlJzogXCJLb2Qgxbpyw7NkxYJvd3lcIixcbiAgICAnUXVvdGUnOiBcIkN5dGF0XCIsXG4gICAgJ1ByZXZpZXcnOiBcIlBvZGdsxIVkXCIsXG4gICAgJ3N0cm9uZyB0ZXh0JzogXCJwb2dydWJpb255IHRla3N0XCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwicG9jaHlsb255IHRla3N0XCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwibmFnxYLDs3dla1wiLFxuICAgICdlbnRlciBsaW5rIGRlc2NyaXB0aW9uIGhlcmUnOiBcIm9waXMgbGlua2FcIixcbiAgICAnSW5zZXJ0IEh5cGVybGluayc6IFwiV3N0YXcgbGlua1wiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCJvcGlzIG9icmF6a2FcIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwiV3N0YXcgb2JyYXpla1wiLFxuICAgICdlbnRlciBpbWFnZSB0aXRsZSBoZXJlJzogXCJ0eXR1xYIgb2JyYXprYVwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwibGlzdGFcIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogU2xvdmVuaWFuIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIERhdm9yIFBhZG92YW4gPGRhdm9yLnBhZG92YW5AZ21haWwuY29tPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5zbCA9IHtcbiAgICAnQm9sZCc6IFwiT2RlYmVsamVub1wiLFxuICAgICdJdGFsaWMnOiBcIlBvxaFldm5vXCIsXG4gICAgJ0hlYWRpbmcnOiBcIk5hc2xvdlwiLFxuICAgICdVUkwvTGluayc6IFwiUG92ZXphdmFcIixcbiAgICAnSW1hZ2UnOiBcIlNsaWthXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JzogXCJOZXVyZWplbiBzZXpuYW1cIixcbiAgICAnT3JkZXJlZCBMaXN0JzogXCJVcmVqZW4gc2V6bmFtXCIsXG4gICAgJ0NvZGUnOiBcIktvZGFcIixcbiAgICAnUXVvdGUnOiBcIkNpdGF0XCIsXG4gICAgJ1ByZXZpZXcnOiBcIlByZWRvZ2xlZFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwib2RlYmVsamVubyBiZXNlZGlsb1wiLFxuICAgICdlbXBoYXNpemVkIHRleHQnOiBcInBvxaFldm5vIGJlc2VkaWxvXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwibmFzbG92XCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwib3BpcyBwb3ZlemF2ZVwiLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogXCJWc3RhdmkgcG92ZXphdm9cIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwib3BpcyBzbGlrZVwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJWc3RhdmkgcG92ZXphdm8gZG8gc2xpa2VcIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwibmFzbG92IHNsaWtlXCIsXG4gICAgJ2xpc3QgdGV4dCBoZXJlJzogXCJzZXpuYW1cIlxuICB9O1xufShqUXVlcnkpKTtcbiIsIi8qKlxuICogU3dlZGlzaCB0cmFuc2xhdGlvbiBmb3IgYm9vdHN0cmFwLW1hcmtkb3duXG4gKiBUb2JpYXMgQm9od2FsbGkgPGhpQGZ1dGhyLmlvPlxuICovXG4oZnVuY3Rpb24gKCQpIHtcbiAgJC5mbi5tYXJrZG93bi5tZXNzYWdlcy5zdiA9IHtcbiAgICAnQm9sZCc6ICdGZXQnLFxuICAgICdJdGFsaWMnOiAnS3Vyc2l2JyxcbiAgICAnSGVhZGluZyc6ICdSdWJyaWsnLFxuICAgICdVUkwvTGluayc6ICdVUkwvTMOkbmsnLFxuICAgICdJbWFnZSc6ICdCaWxkJyxcbiAgICAnTGlzdCc6ICdMaXN0YScsXG4gICAgJ1ByZXZpZXcnOiAnRsO2cmhhbmRzZ3JhbnNrYScsXG4gICAgJ3N0cm9uZyB0ZXh0JzogJ2ZldCB0ZXh0JyxcbiAgICAnZW1waGFzaXplZCB0ZXh0JzogJ8O2dmVyc3RydWtlbiB0ZXh0JyxcbiAgICAnaGVhZGluZyB0ZXh0JzogJ1J1YnJpaycsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6ICdBbmdlIGzDpG5rIGJlc2tyaXZuaW5nIGjDpHInLFxuICAgICdJbnNlcnQgSHlwZXJsaW5rJzogJ1PDpHR0IGluIGzDpG5rJyxcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6ICdBbmdlIGJpbGQgYmVza3Jpdm5pbmcgaMOkcicsXG4gICAgJ0luc2VydCBJbWFnZSBIeXBlcmxpbmsnOiAnU8OkdHQgaW4gbMOkbmsgZsO2ciBiaWxkJyxcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6ICdBbmdlIGJpbGQgcnVicmlrIGjDpHInLFxuICAgICdsaXN0IHRleHQgaGVyZSc6ICdsaXN0IHRleHQnXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBUdXJraXNoIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIFNlcmthbiBBbGd1ciA8aW5mb0B3cGFkYW1pLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMudHIgPSB7XG4gICAgJ0JvbGQnOiBcIkthbMSxblwiLFxuICAgICdJdGFsaWMnOiBcIsSwdGFsaWtcIixcbiAgICAnSGVhZGluZyc6IFwiQmHFn2zEsWtcIixcbiAgICAnVVJML0xpbmsnOiBcIkxpbmsgZWtsZVwiLFxuICAgICdJbWFnZSc6IFwiUmVzaW0gZWtsZVwiLFxuICAgICdMaXN0JzogXCJMaXN0ZSBPbHXFn3R1cnVuXCIsXG4gICAgJ1ByZXZpZXcnOiBcIsOWbml6bGVtZVwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwia2FsxLFuIHlhesSxXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwiaXRhbGlrIHlhesSxXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwiQmHFn2zEsWsgWWF6xLFzxLFcIixcbiAgICAnZW50ZXIgbGluayBkZXNjcmlwdGlvbiBoZXJlJzogXCJMaW5rIGHDp8Sxa2xhbWFzxLFuxLEgYnVyYXlhIGdpcmluXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIsSwbnRlcm5ldCBhZHJlc2kgZ2lyaW5cIixcbiAgICAnZW50ZXIgaW1hZ2UgZGVzY3JpcHRpb24gaGVyZSc6IFwicmVzaW0gYcOnxLFrbGFtYXPEsW7EsSBidXJheWEgZWtsZXlpblwiLFxuICAgICdJbnNlcnQgSW1hZ2UgSHlwZXJsaW5rJzogXCJSZXNpbSBsaW5raW5pIGVrbGV5aW5cIixcbiAgICAnZW50ZXIgaW1hZ2UgdGl0bGUgaGVyZSc6IFwicmVzaW0gYmHFn2zEscSfxLFuxLEgYnVyYXlhIGVrbGV5aW5cIixcbiAgICAnbGlzdCB0ZXh0IGhlcmUnOiBcImxpc3RlIHlhesSxc8SxXCIsXG4gICAgJ1NhdmUnIDogXCJLYXlkZXRcIixcbiAgICAnT3JkZXJlZCBMaXN0JyA6IFwiTnVtYXJhbMSxIExpc3RlXCIsXG4gICAgJ1Vub3JkZXJlZCBMaXN0JyA6IFwiTWFkZGUgaW1saSBsaXN0ZVwiLFxuICAgICdRdW90ZScgOiBcIkFsxLFudMSxXCIsXG4gICAgJ3F1b3RlIGhlcmUnIDogXCJhbMSxbnTEsXnEsSBidXJheWEgZWtsZXlpblwiLFxuICAgICdDb2RlJyA6IFwiS29kXCIsXG4gICAgJ2NvZGUgdGV4dCBoZXJlJyA6IFwia29kdSBidXJheWEgZWtsZXlpblwiXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiLyoqXG4gKiBDaGluZXNlIHRyYW5zbGF0aW9uIGZvciBib290c3RyYXAtbWFya2Rvd25cbiAqIGJlbmhhaWxlIDxkZW5naGFpZXJAMTYzLmNvbT5cbiAqL1xuKGZ1bmN0aW9uICgkKSB7XG4gICQuZm4ubWFya2Rvd24ubWVzc2FnZXMuemggPSB7XG4gICAgJ0JvbGQnOiBcIueyl+S9k1wiLFxuICAgICdJdGFsaWMnOiBcIuaWnOS9k1wiLFxuICAgICdIZWFkaW5nJzogXCLmoIfpophcIixcbiAgICAnVVJML0xpbmsnOiBcIumTvuaOpVwiLFxuICAgICdJbWFnZSc6IFwi5Zu+54mHXCIsXG4gICAgJ0xpc3QnOiBcIuWIl+ihqFwiLFxuICAgICdVbm9yZGVyZWQgTGlzdCc6IFwi5peg5bqP5YiX6KGoXCIsXG4gICAgJ09yZGVyZWQgTGlzdCc6IFwi5pyJ5bqP5YiX6KGoXCIsXG4gICAgJ0NvZGUnOiBcIuS7o+eggVwiLFxuICAgICdRdW90ZSc6IFwi5byV55SoXCIsXG4gICAgJ1ByZXZpZXcnOiBcIumihOiniFwiLFxuICAgICdzdHJvbmcgdGV4dCc6IFwi57KX5L2TXCIsXG4gICAgJ2VtcGhhc2l6ZWQgdGV4dCc6IFwi5by66LCDXCIsXG4gICAgJ2hlYWRpbmcgdGV4dCc6IFwi5qCH6aKYXCIsXG4gICAgJ2VudGVyIGxpbmsgZGVzY3JpcHRpb24gaGVyZSc6IFwi6L6T5YWl6ZO+5o6l6K+05piOXCIsXG4gICAgJ0luc2VydCBIeXBlcmxpbmsnOiBcIlVSTOWcsOWdgFwiLFxuICAgICdlbnRlciBpbWFnZSBkZXNjcmlwdGlvbiBoZXJlJzogXCLovpPlhaXlm77niYfor7TmmI5cIixcbiAgICAnSW5zZXJ0IEltYWdlIEh5cGVybGluayc6IFwi5Zu+54mHVVJM5Zyw5Z2AXCIsXG4gICAgJ2VudGVyIGltYWdlIHRpdGxlIGhlcmUnOiBcIuWcqOi/memHjOi+k+WFpeWbvueJh+agh+mimFwiLFxuICAgICdsaXN0IHRleHQgaGVyZSc6IFwi6L+Z6YeM5piv5YiX6KGo5paH5pysXCIsXG4gICAgJ2NvZGUgdGV4dCBoZXJlJzogXCLov5nph4zovpPlhaXku6PnoIFcIixcbiAgICAncXVvdGUgaGVyZSc6IFwi6L+Z6YeM6L6T5YWl5byV55So5paH5pysXCJcblxuXG4gIH07XG59KGpRdWVyeSkpO1xuIiwiKGZ1bmN0aW9uIGRlZmluZU11c3RhY2hlKGdsb2JhbCxmYWN0b3J5KXtpZih0eXBlb2YgZXhwb3J0cz09PVwib2JqZWN0XCImJmV4cG9ydHMmJnR5cGVvZiBleHBvcnRzLm5vZGVOYW1lIT09XCJzdHJpbmdcIil7ZmFjdG9yeShleHBvcnRzKX1lbHNlIGlmKHR5cGVvZiBkZWZpbmU9PT1cImZ1bmN0aW9uXCImJmRlZmluZS5hbWQpe2RlZmluZShbXCJleHBvcnRzXCJdLGZhY3RvcnkpfWVsc2V7Z2xvYmFsLk11c3RhY2hlPXt9O2ZhY3RvcnkoZ2xvYmFsLk11c3RhY2hlKX19KSh0aGlzLGZ1bmN0aW9uIG11c3RhY2hlRmFjdG9yeShtdXN0YWNoZSl7dmFyIG9iamVjdFRvU3RyaW5nPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7dmFyIGlzQXJyYXk9QXJyYXkuaXNBcnJheXx8ZnVuY3Rpb24gaXNBcnJheVBvbHlmaWxsKG9iamVjdCl7cmV0dXJuIG9iamVjdFRvU3RyaW5nLmNhbGwob2JqZWN0KT09PVwiW29iamVjdCBBcnJheV1cIn07ZnVuY3Rpb24gaXNGdW5jdGlvbihvYmplY3Qpe3JldHVybiB0eXBlb2Ygb2JqZWN0PT09XCJmdW5jdGlvblwifWZ1bmN0aW9uIHR5cGVTdHIob2JqKXtyZXR1cm4gaXNBcnJheShvYmopP1wiYXJyYXlcIjp0eXBlb2Ygb2JqfWZ1bmN0aW9uIGVzY2FwZVJlZ0V4cChzdHJpbmcpe3JldHVybiBzdHJpbmcucmVwbGFjZSgvW1xcLVxcW1xcXXt9KCkqKz8uLFxcXFxcXF4kfCNcXHNdL2csXCJcXFxcJCZcIil9ZnVuY3Rpb24gaGFzUHJvcGVydHkob2JqLHByb3BOYW1lKXtyZXR1cm4gb2JqIT1udWxsJiZ0eXBlb2Ygb2JqPT09XCJvYmplY3RcIiYmcHJvcE5hbWUgaW4gb2JqfWZ1bmN0aW9uIHByaW1pdGl2ZUhhc093blByb3BlcnR5KHByaW1pdGl2ZSxwcm9wTmFtZSl7cmV0dXJuIHByaW1pdGl2ZSE9bnVsbCYmdHlwZW9mIHByaW1pdGl2ZSE9PVwib2JqZWN0XCImJnByaW1pdGl2ZS5oYXNPd25Qcm9wZXJ0eSYmcHJpbWl0aXZlLmhhc093blByb3BlcnR5KHByb3BOYW1lKX12YXIgcmVnRXhwVGVzdD1SZWdFeHAucHJvdG90eXBlLnRlc3Q7ZnVuY3Rpb24gdGVzdFJlZ0V4cChyZSxzdHJpbmcpe3JldHVybiByZWdFeHBUZXN0LmNhbGwocmUsc3RyaW5nKX12YXIgbm9uU3BhY2VSZT0vXFxTLztmdW5jdGlvbiBpc1doaXRlc3BhY2Uoc3RyaW5nKXtyZXR1cm4hdGVzdFJlZ0V4cChub25TcGFjZVJlLHN0cmluZyl9dmFyIGVudGl0eU1hcD17XCImXCI6XCImYW1wO1wiLFwiPFwiOlwiJmx0O1wiLFwiPlwiOlwiJmd0O1wiLCdcIic6XCImcXVvdDtcIixcIidcIjpcIiYjMzk7XCIsXCIvXCI6XCImI3gyRjtcIixcImBcIjpcIiYjeDYwO1wiLFwiPVwiOlwiJiN4M0Q7XCJ9O2Z1bmN0aW9uIGVzY2FwZUh0bWwoc3RyaW5nKXtyZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvWyY8PlwiJ2A9XFwvXS9nLGZ1bmN0aW9uIGZyb21FbnRpdHlNYXAocyl7cmV0dXJuIGVudGl0eU1hcFtzXX0pfXZhciB3aGl0ZVJlPS9cXHMqLzt2YXIgc3BhY2VSZT0vXFxzKy87dmFyIGVxdWFsc1JlPS9cXHMqPS87dmFyIGN1cmx5UmU9L1xccypcXH0vO3ZhciB0YWdSZT0vI3xcXF58XFwvfD58XFx7fCZ8PXwhLztmdW5jdGlvbiBwYXJzZVRlbXBsYXRlKHRlbXBsYXRlLHRhZ3Mpe2lmKCF0ZW1wbGF0ZSlyZXR1cm5bXTt2YXIgc2VjdGlvbnM9W107dmFyIHRva2Vucz1bXTt2YXIgc3BhY2VzPVtdO3ZhciBoYXNUYWc9ZmFsc2U7dmFyIG5vblNwYWNlPWZhbHNlO2Z1bmN0aW9uIHN0cmlwU3BhY2UoKXtpZihoYXNUYWcmJiFub25TcGFjZSl7d2hpbGUoc3BhY2VzLmxlbmd0aClkZWxldGUgdG9rZW5zW3NwYWNlcy5wb3AoKV19ZWxzZXtzcGFjZXM9W119aGFzVGFnPWZhbHNlO25vblNwYWNlPWZhbHNlfXZhciBvcGVuaW5nVGFnUmUsY2xvc2luZ1RhZ1JlLGNsb3NpbmdDdXJseVJlO2Z1bmN0aW9uIGNvbXBpbGVUYWdzKHRhZ3NUb0NvbXBpbGUpe2lmKHR5cGVvZiB0YWdzVG9Db21waWxlPT09XCJzdHJpbmdcIil0YWdzVG9Db21waWxlPXRhZ3NUb0NvbXBpbGUuc3BsaXQoc3BhY2VSZSwyKTtpZighaXNBcnJheSh0YWdzVG9Db21waWxlKXx8dGFnc1RvQ29tcGlsZS5sZW5ndGghPT0yKXRocm93IG5ldyBFcnJvcihcIkludmFsaWQgdGFnczogXCIrdGFnc1RvQ29tcGlsZSk7b3BlbmluZ1RhZ1JlPW5ldyBSZWdFeHAoZXNjYXBlUmVnRXhwKHRhZ3NUb0NvbXBpbGVbMF0pK1wiXFxcXHMqXCIpO2Nsb3NpbmdUYWdSZT1uZXcgUmVnRXhwKFwiXFxcXHMqXCIrZXNjYXBlUmVnRXhwKHRhZ3NUb0NvbXBpbGVbMV0pKTtjbG9zaW5nQ3VybHlSZT1uZXcgUmVnRXhwKFwiXFxcXHMqXCIrZXNjYXBlUmVnRXhwKFwifVwiK3RhZ3NUb0NvbXBpbGVbMV0pKX1jb21waWxlVGFncyh0YWdzfHxtdXN0YWNoZS50YWdzKTt2YXIgc2Nhbm5lcj1uZXcgU2Nhbm5lcih0ZW1wbGF0ZSk7dmFyIHN0YXJ0LHR5cGUsdmFsdWUsY2hyLHRva2VuLG9wZW5TZWN0aW9uO3doaWxlKCFzY2FubmVyLmVvcygpKXtzdGFydD1zY2FubmVyLnBvczt2YWx1ZT1zY2FubmVyLnNjYW5VbnRpbChvcGVuaW5nVGFnUmUpO2lmKHZhbHVlKXtmb3IodmFyIGk9MCx2YWx1ZUxlbmd0aD12YWx1ZS5sZW5ndGg7aTx2YWx1ZUxlbmd0aDsrK2kpe2Nocj12YWx1ZS5jaGFyQXQoaSk7aWYoaXNXaGl0ZXNwYWNlKGNocikpe3NwYWNlcy5wdXNoKHRva2Vucy5sZW5ndGgpfWVsc2V7bm9uU3BhY2U9dHJ1ZX10b2tlbnMucHVzaChbXCJ0ZXh0XCIsY2hyLHN0YXJ0LHN0YXJ0KzFdKTtzdGFydCs9MTtpZihjaHI9PT1cIlxcblwiKXN0cmlwU3BhY2UoKX19aWYoIXNjYW5uZXIuc2NhbihvcGVuaW5nVGFnUmUpKWJyZWFrO2hhc1RhZz10cnVlO3R5cGU9c2Nhbm5lci5zY2FuKHRhZ1JlKXx8XCJuYW1lXCI7c2Nhbm5lci5zY2FuKHdoaXRlUmUpO2lmKHR5cGU9PT1cIj1cIil7dmFsdWU9c2Nhbm5lci5zY2FuVW50aWwoZXF1YWxzUmUpO3NjYW5uZXIuc2NhbihlcXVhbHNSZSk7c2Nhbm5lci5zY2FuVW50aWwoY2xvc2luZ1RhZ1JlKX1lbHNlIGlmKHR5cGU9PT1cIntcIil7dmFsdWU9c2Nhbm5lci5zY2FuVW50aWwoY2xvc2luZ0N1cmx5UmUpO3NjYW5uZXIuc2NhbihjdXJseVJlKTtzY2FubmVyLnNjYW5VbnRpbChjbG9zaW5nVGFnUmUpO3R5cGU9XCImXCJ9ZWxzZXt2YWx1ZT1zY2FubmVyLnNjYW5VbnRpbChjbG9zaW5nVGFnUmUpfWlmKCFzY2FubmVyLnNjYW4oY2xvc2luZ1RhZ1JlKSl0aHJvdyBuZXcgRXJyb3IoXCJVbmNsb3NlZCB0YWcgYXQgXCIrc2Nhbm5lci5wb3MpO3Rva2VuPVt0eXBlLHZhbHVlLHN0YXJ0LHNjYW5uZXIucG9zXTt0b2tlbnMucHVzaCh0b2tlbik7aWYodHlwZT09PVwiI1wifHx0eXBlPT09XCJeXCIpe3NlY3Rpb25zLnB1c2godG9rZW4pfWVsc2UgaWYodHlwZT09PVwiL1wiKXtvcGVuU2VjdGlvbj1zZWN0aW9ucy5wb3AoKTtpZighb3BlblNlY3Rpb24pdGhyb3cgbmV3IEVycm9yKCdVbm9wZW5lZCBzZWN0aW9uIFwiJyt2YWx1ZSsnXCIgYXQgJytzdGFydCk7aWYob3BlblNlY3Rpb25bMV0hPT12YWx1ZSl0aHJvdyBuZXcgRXJyb3IoJ1VuY2xvc2VkIHNlY3Rpb24gXCInK29wZW5TZWN0aW9uWzFdKydcIiBhdCAnK3N0YXJ0KX1lbHNlIGlmKHR5cGU9PT1cIm5hbWVcInx8dHlwZT09PVwie1wifHx0eXBlPT09XCImXCIpe25vblNwYWNlPXRydWV9ZWxzZSBpZih0eXBlPT09XCI9XCIpe2NvbXBpbGVUYWdzKHZhbHVlKX19b3BlblNlY3Rpb249c2VjdGlvbnMucG9wKCk7aWYob3BlblNlY3Rpb24pdGhyb3cgbmV3IEVycm9yKCdVbmNsb3NlZCBzZWN0aW9uIFwiJytvcGVuU2VjdGlvblsxXSsnXCIgYXQgJytzY2FubmVyLnBvcyk7cmV0dXJuIG5lc3RUb2tlbnMoc3F1YXNoVG9rZW5zKHRva2VucykpfWZ1bmN0aW9uIHNxdWFzaFRva2Vucyh0b2tlbnMpe3ZhciBzcXVhc2hlZFRva2Vucz1bXTt2YXIgdG9rZW4sbGFzdFRva2VuO2Zvcih2YXIgaT0wLG51bVRva2Vucz10b2tlbnMubGVuZ3RoO2k8bnVtVG9rZW5zOysraSl7dG9rZW49dG9rZW5zW2ldO2lmKHRva2VuKXtpZih0b2tlblswXT09PVwidGV4dFwiJiZsYXN0VG9rZW4mJmxhc3RUb2tlblswXT09PVwidGV4dFwiKXtsYXN0VG9rZW5bMV0rPXRva2VuWzFdO2xhc3RUb2tlblszXT10b2tlblszXX1lbHNle3NxdWFzaGVkVG9rZW5zLnB1c2godG9rZW4pO2xhc3RUb2tlbj10b2tlbn19fXJldHVybiBzcXVhc2hlZFRva2Vuc31mdW5jdGlvbiBuZXN0VG9rZW5zKHRva2Vucyl7dmFyIG5lc3RlZFRva2Vucz1bXTt2YXIgY29sbGVjdG9yPW5lc3RlZFRva2Vuczt2YXIgc2VjdGlvbnM9W107dmFyIHRva2VuLHNlY3Rpb247Zm9yKHZhciBpPTAsbnVtVG9rZW5zPXRva2Vucy5sZW5ndGg7aTxudW1Ub2tlbnM7KytpKXt0b2tlbj10b2tlbnNbaV07c3dpdGNoKHRva2VuWzBdKXtjYXNlXCIjXCI6Y2FzZVwiXlwiOmNvbGxlY3Rvci5wdXNoKHRva2VuKTtzZWN0aW9ucy5wdXNoKHRva2VuKTtjb2xsZWN0b3I9dG9rZW5bNF09W107YnJlYWs7Y2FzZVwiL1wiOnNlY3Rpb249c2VjdGlvbnMucG9wKCk7c2VjdGlvbls1XT10b2tlblsyXTtjb2xsZWN0b3I9c2VjdGlvbnMubGVuZ3RoPjA/c2VjdGlvbnNbc2VjdGlvbnMubGVuZ3RoLTFdWzRdOm5lc3RlZFRva2VuczticmVhaztkZWZhdWx0OmNvbGxlY3Rvci5wdXNoKHRva2VuKX19cmV0dXJuIG5lc3RlZFRva2Vuc31mdW5jdGlvbiBTY2FubmVyKHN0cmluZyl7dGhpcy5zdHJpbmc9c3RyaW5nO3RoaXMudGFpbD1zdHJpbmc7dGhpcy5wb3M9MH1TY2FubmVyLnByb3RvdHlwZS5lb3M9ZnVuY3Rpb24gZW9zKCl7cmV0dXJuIHRoaXMudGFpbD09PVwiXCJ9O1NjYW5uZXIucHJvdG90eXBlLnNjYW49ZnVuY3Rpb24gc2NhbihyZSl7dmFyIG1hdGNoPXRoaXMudGFpbC5tYXRjaChyZSk7aWYoIW1hdGNofHxtYXRjaC5pbmRleCE9PTApcmV0dXJuXCJcIjt2YXIgc3RyaW5nPW1hdGNoWzBdO3RoaXMudGFpbD10aGlzLnRhaWwuc3Vic3RyaW5nKHN0cmluZy5sZW5ndGgpO3RoaXMucG9zKz1zdHJpbmcubGVuZ3RoO3JldHVybiBzdHJpbmd9O1NjYW5uZXIucHJvdG90eXBlLnNjYW5VbnRpbD1mdW5jdGlvbiBzY2FuVW50aWwocmUpe3ZhciBpbmRleD10aGlzLnRhaWwuc2VhcmNoKHJlKSxtYXRjaDtzd2l0Y2goaW5kZXgpe2Nhc2UtMTptYXRjaD10aGlzLnRhaWw7dGhpcy50YWlsPVwiXCI7YnJlYWs7Y2FzZSAwOm1hdGNoPVwiXCI7YnJlYWs7ZGVmYXVsdDptYXRjaD10aGlzLnRhaWwuc3Vic3RyaW5nKDAsaW5kZXgpO3RoaXMudGFpbD10aGlzLnRhaWwuc3Vic3RyaW5nKGluZGV4KX10aGlzLnBvcys9bWF0Y2gubGVuZ3RoO3JldHVybiBtYXRjaH07ZnVuY3Rpb24gQ29udGV4dCh2aWV3LHBhcmVudENvbnRleHQpe3RoaXMudmlldz12aWV3O3RoaXMuY2FjaGU9e1wiLlwiOnRoaXMudmlld307dGhpcy5wYXJlbnQ9cGFyZW50Q29udGV4dH1Db250ZXh0LnByb3RvdHlwZS5wdXNoPWZ1bmN0aW9uIHB1c2godmlldyl7cmV0dXJuIG5ldyBDb250ZXh0KHZpZXcsdGhpcyl9O0NvbnRleHQucHJvdG90eXBlLmxvb2t1cD1mdW5jdGlvbiBsb29rdXAobmFtZSl7dmFyIGNhY2hlPXRoaXMuY2FjaGU7dmFyIHZhbHVlO2lmKGNhY2hlLmhhc093blByb3BlcnR5KG5hbWUpKXt2YWx1ZT1jYWNoZVtuYW1lXX1lbHNle3ZhciBjb250ZXh0PXRoaXMsaW50ZXJtZWRpYXRlVmFsdWUsbmFtZXMsaW5kZXgsbG9va3VwSGl0PWZhbHNlO3doaWxlKGNvbnRleHQpe2lmKG5hbWUuaW5kZXhPZihcIi5cIik+MCl7aW50ZXJtZWRpYXRlVmFsdWU9Y29udGV4dC52aWV3O25hbWVzPW5hbWUuc3BsaXQoXCIuXCIpO2luZGV4PTA7d2hpbGUoaW50ZXJtZWRpYXRlVmFsdWUhPW51bGwmJmluZGV4PG5hbWVzLmxlbmd0aCl7aWYoaW5kZXg9PT1uYW1lcy5sZW5ndGgtMSlsb29rdXBIaXQ9aGFzUHJvcGVydHkoaW50ZXJtZWRpYXRlVmFsdWUsbmFtZXNbaW5kZXhdKXx8cHJpbWl0aXZlSGFzT3duUHJvcGVydHkoaW50ZXJtZWRpYXRlVmFsdWUsbmFtZXNbaW5kZXhdKTtpbnRlcm1lZGlhdGVWYWx1ZT1pbnRlcm1lZGlhdGVWYWx1ZVtuYW1lc1tpbmRleCsrXV19fWVsc2V7aW50ZXJtZWRpYXRlVmFsdWU9Y29udGV4dC52aWV3W25hbWVdO2xvb2t1cEhpdD1oYXNQcm9wZXJ0eShjb250ZXh0LnZpZXcsbmFtZSl9aWYobG9va3VwSGl0KXt2YWx1ZT1pbnRlcm1lZGlhdGVWYWx1ZTticmVha31jb250ZXh0PWNvbnRleHQucGFyZW50fWNhY2hlW25hbWVdPXZhbHVlfWlmKGlzRnVuY3Rpb24odmFsdWUpKXZhbHVlPXZhbHVlLmNhbGwodGhpcy52aWV3KTtyZXR1cm4gdmFsdWV9O2Z1bmN0aW9uIFdyaXRlcigpe3RoaXMuY2FjaGU9e319V3JpdGVyLnByb3RvdHlwZS5jbGVhckNhY2hlPWZ1bmN0aW9uIGNsZWFyQ2FjaGUoKXt0aGlzLmNhY2hlPXt9fTtXcml0ZXIucHJvdG90eXBlLnBhcnNlPWZ1bmN0aW9uIHBhcnNlKHRlbXBsYXRlLHRhZ3Mpe3ZhciBjYWNoZT10aGlzLmNhY2hlO3ZhciBjYWNoZUtleT10ZW1wbGF0ZStcIjpcIisodGFnc3x8bXVzdGFjaGUudGFncykuam9pbihcIjpcIik7dmFyIHRva2Vucz1jYWNoZVtjYWNoZUtleV07aWYodG9rZW5zPT1udWxsKXRva2Vucz1jYWNoZVtjYWNoZUtleV09cGFyc2VUZW1wbGF0ZSh0ZW1wbGF0ZSx0YWdzKTtyZXR1cm4gdG9rZW5zfTtXcml0ZXIucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbiByZW5kZXIodGVtcGxhdGUsdmlldyxwYXJ0aWFscyx0YWdzKXt2YXIgdG9rZW5zPXRoaXMucGFyc2UodGVtcGxhdGUsdGFncyk7dmFyIGNvbnRleHQ9dmlldyBpbnN0YW5jZW9mIENvbnRleHQ/dmlldzpuZXcgQ29udGV4dCh2aWV3KTtyZXR1cm4gdGhpcy5yZW5kZXJUb2tlbnModG9rZW5zLGNvbnRleHQscGFydGlhbHMsdGVtcGxhdGUsdGFncyl9O1dyaXRlci5wcm90b3R5cGUucmVuZGVyVG9rZW5zPWZ1bmN0aW9uIHJlbmRlclRva2Vucyh0b2tlbnMsY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlLHRhZ3Mpe3ZhciBidWZmZXI9XCJcIjt2YXIgdG9rZW4sc3ltYm9sLHZhbHVlO2Zvcih2YXIgaT0wLG51bVRva2Vucz10b2tlbnMubGVuZ3RoO2k8bnVtVG9rZW5zOysraSl7dmFsdWU9dW5kZWZpbmVkO3Rva2VuPXRva2Vuc1tpXTtzeW1ib2w9dG9rZW5bMF07aWYoc3ltYm9sPT09XCIjXCIpdmFsdWU9dGhpcy5yZW5kZXJTZWN0aW9uKHRva2VuLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSk7ZWxzZSBpZihzeW1ib2w9PT1cIl5cIil2YWx1ZT10aGlzLnJlbmRlckludmVydGVkKHRva2VuLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSk7ZWxzZSBpZihzeW1ib2w9PT1cIj5cIil2YWx1ZT10aGlzLnJlbmRlclBhcnRpYWwodG9rZW4sY29udGV4dCxwYXJ0aWFscyx0YWdzKTtlbHNlIGlmKHN5bWJvbD09PVwiJlwiKXZhbHVlPXRoaXMudW5lc2NhcGVkVmFsdWUodG9rZW4sY29udGV4dCk7ZWxzZSBpZihzeW1ib2w9PT1cIm5hbWVcIil2YWx1ZT10aGlzLmVzY2FwZWRWYWx1ZSh0b2tlbixjb250ZXh0KTtlbHNlIGlmKHN5bWJvbD09PVwidGV4dFwiKXZhbHVlPXRoaXMucmF3VmFsdWUodG9rZW4pO2lmKHZhbHVlIT09dW5kZWZpbmVkKWJ1ZmZlcis9dmFsdWV9cmV0dXJuIGJ1ZmZlcn07V3JpdGVyLnByb3RvdHlwZS5yZW5kZXJTZWN0aW9uPWZ1bmN0aW9uIHJlbmRlclNlY3Rpb24odG9rZW4sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKXt2YXIgc2VsZj10aGlzO3ZhciBidWZmZXI9XCJcIjt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2Z1bmN0aW9uIHN1YlJlbmRlcih0ZW1wbGF0ZSl7cmV0dXJuIHNlbGYucmVuZGVyKHRlbXBsYXRlLGNvbnRleHQscGFydGlhbHMpfWlmKCF2YWx1ZSlyZXR1cm47aWYoaXNBcnJheSh2YWx1ZSkpe2Zvcih2YXIgaj0wLHZhbHVlTGVuZ3RoPXZhbHVlLmxlbmd0aDtqPHZhbHVlTGVuZ3RoOysrail7YnVmZmVyKz10aGlzLnJlbmRlclRva2Vucyh0b2tlbls0XSxjb250ZXh0LnB1c2godmFsdWVbal0pLHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUpfX1lbHNlIGlmKHR5cGVvZiB2YWx1ZT09PVwib2JqZWN0XCJ8fHR5cGVvZiB2YWx1ZT09PVwic3RyaW5nXCJ8fHR5cGVvZiB2YWx1ZT09PVwibnVtYmVyXCIpe2J1ZmZlcis9dGhpcy5yZW5kZXJUb2tlbnModG9rZW5bNF0sY29udGV4dC5wdXNoKHZhbHVlKSxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKX1lbHNlIGlmKGlzRnVuY3Rpb24odmFsdWUpKXtpZih0eXBlb2Ygb3JpZ2luYWxUZW1wbGF0ZSE9PVwic3RyaW5nXCIpdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IHVzZSBoaWdoZXItb3JkZXIgc2VjdGlvbnMgd2l0aG91dCB0aGUgb3JpZ2luYWwgdGVtcGxhdGVcIik7dmFsdWU9dmFsdWUuY2FsbChjb250ZXh0LnZpZXcsb3JpZ2luYWxUZW1wbGF0ZS5zbGljZSh0b2tlblszXSx0b2tlbls1XSksc3ViUmVuZGVyKTtpZih2YWx1ZSE9bnVsbClidWZmZXIrPXZhbHVlfWVsc2V7YnVmZmVyKz10aGlzLnJlbmRlclRva2Vucyh0b2tlbls0XSxjb250ZXh0LHBhcnRpYWxzLG9yaWdpbmFsVGVtcGxhdGUpfXJldHVybiBidWZmZXJ9O1dyaXRlci5wcm90b3R5cGUucmVuZGVySW52ZXJ0ZWQ9ZnVuY3Rpb24gcmVuZGVySW52ZXJ0ZWQodG9rZW4sY29udGV4dCxwYXJ0aWFscyxvcmlnaW5hbFRlbXBsYXRlKXt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2lmKCF2YWx1ZXx8aXNBcnJheSh2YWx1ZSkmJnZhbHVlLmxlbmd0aD09PTApcmV0dXJuIHRoaXMucmVuZGVyVG9rZW5zKHRva2VuWzRdLGNvbnRleHQscGFydGlhbHMsb3JpZ2luYWxUZW1wbGF0ZSl9O1dyaXRlci5wcm90b3R5cGUucmVuZGVyUGFydGlhbD1mdW5jdGlvbiByZW5kZXJQYXJ0aWFsKHRva2VuLGNvbnRleHQscGFydGlhbHMsdGFncyl7aWYoIXBhcnRpYWxzKXJldHVybjt2YXIgdmFsdWU9aXNGdW5jdGlvbihwYXJ0aWFscyk/cGFydGlhbHModG9rZW5bMV0pOnBhcnRpYWxzW3Rva2VuWzFdXTtpZih2YWx1ZSE9bnVsbClyZXR1cm4gdGhpcy5yZW5kZXJUb2tlbnModGhpcy5wYXJzZSh2YWx1ZSx0YWdzKSxjb250ZXh0LHBhcnRpYWxzLHZhbHVlKX07V3JpdGVyLnByb3RvdHlwZS51bmVzY2FwZWRWYWx1ZT1mdW5jdGlvbiB1bmVzY2FwZWRWYWx1ZSh0b2tlbixjb250ZXh0KXt2YXIgdmFsdWU9Y29udGV4dC5sb29rdXAodG9rZW5bMV0pO2lmKHZhbHVlIT1udWxsKXJldHVybiB2YWx1ZX07V3JpdGVyLnByb3RvdHlwZS5lc2NhcGVkVmFsdWU9ZnVuY3Rpb24gZXNjYXBlZFZhbHVlKHRva2VuLGNvbnRleHQpe3ZhciB2YWx1ZT1jb250ZXh0Lmxvb2t1cCh0b2tlblsxXSk7aWYodmFsdWUhPW51bGwpcmV0dXJuIG11c3RhY2hlLmVzY2FwZSh2YWx1ZSl9O1dyaXRlci5wcm90b3R5cGUucmF3VmFsdWU9ZnVuY3Rpb24gcmF3VmFsdWUodG9rZW4pe3JldHVybiB0b2tlblsxXX07bXVzdGFjaGUubmFtZT1cIm11c3RhY2hlLmpzXCI7bXVzdGFjaGUudmVyc2lvbj1cIjMuMC4xXCI7bXVzdGFjaGUudGFncz1bXCJ7e1wiLFwifX1cIl07dmFyIGRlZmF1bHRXcml0ZXI9bmV3IFdyaXRlcjttdXN0YWNoZS5jbGVhckNhY2hlPWZ1bmN0aW9uIGNsZWFyQ2FjaGUoKXtyZXR1cm4gZGVmYXVsdFdyaXRlci5jbGVhckNhY2hlKCl9O211c3RhY2hlLnBhcnNlPWZ1bmN0aW9uIHBhcnNlKHRlbXBsYXRlLHRhZ3Mpe3JldHVybiBkZWZhdWx0V3JpdGVyLnBhcnNlKHRlbXBsYXRlLHRhZ3MpfTttdXN0YWNoZS5yZW5kZXI9ZnVuY3Rpb24gcmVuZGVyKHRlbXBsYXRlLHZpZXcscGFydGlhbHMsdGFncyl7aWYodHlwZW9mIHRlbXBsYXRlIT09XCJzdHJpbmdcIil7dGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCB0ZW1wbGF0ZSEgVGVtcGxhdGUgc2hvdWxkIGJlIGEgXCJzdHJpbmdcIiAnKydidXQgXCInK3R5cGVTdHIodGVtcGxhdGUpKydcIiB3YXMgZ2l2ZW4gYXMgdGhlIGZpcnN0ICcrXCJhcmd1bWVudCBmb3IgbXVzdGFjaGUjcmVuZGVyKHRlbXBsYXRlLCB2aWV3LCBwYXJ0aWFscylcIil9cmV0dXJuIGRlZmF1bHRXcml0ZXIucmVuZGVyKHRlbXBsYXRlLHZpZXcscGFydGlhbHMsdGFncyl9O211c3RhY2hlLnRvX2h0bWw9ZnVuY3Rpb24gdG9faHRtbCh0ZW1wbGF0ZSx2aWV3LHBhcnRpYWxzLHNlbmQpe3ZhciByZXN1bHQ9bXVzdGFjaGUucmVuZGVyKHRlbXBsYXRlLHZpZXcscGFydGlhbHMpO2lmKGlzRnVuY3Rpb24oc2VuZCkpe3NlbmQocmVzdWx0KX1lbHNle3JldHVybiByZXN1bHR9fTttdXN0YWNoZS5lc2NhcGU9ZXNjYXBlSHRtbDttdXN0YWNoZS5TY2FubmVyPVNjYW5uZXI7bXVzdGFjaGUuQ29udGV4dD1Db250ZXh0O211c3RhY2hlLldyaXRlcj1Xcml0ZXI7cmV0dXJuIG11c3RhY2hlfSk7XG4iLCIvKiFcbipcbiogIENvcHlyaWdodCAyMDE2IFlhbm4gTWFzc2FyZCAoaHR0cHM6Ly9naXRodWIuY29tL3lhbWFzcykgYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuKlxuKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiogIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiogIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuKlxuKiAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4qXG4qICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4qICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4qICBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiogIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiogIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKlxuKi9cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwianF1ZXJ5XCIsIFwibGV2ZW5zaHRlaW5cIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcbiAgICB2YXIgTGV2ZW5zaHRlaW4gPSByZXF1aXJlKFwibGV2ZW5zaHRlaW5cIik7XG4gICAgZXhwb3J0cy5rZXlDb2RlcyA9IHtcbiAgICAgICAgYmFja3NwYWNlOiA4LFxuICAgICAgICB0YWI6IDksXG4gICAgICAgIGVudGVyOiAxMyxcbiAgICAgICAgc2hpZnQ6IDE2LFxuICAgICAgICBjdHJsOiAxNyxcbiAgICAgICAgYWx0OiAxOCxcbiAgICAgICAgcGF1c2U6IDE5LFxuICAgICAgICBjYXBzX2xvY2s6IDIwLFxuICAgICAgICBlc2NhcGU6IDI3LFxuICAgICAgICBzcGFjZTogMzIsXG4gICAgICAgIHBhZ2VfdXA6IDMzLFxuICAgICAgICBwYWdlX2Rvd246IDM0LFxuICAgICAgICBlbmQ6IDM1LFxuICAgICAgICBob21lOiAzNixcbiAgICAgICAgbGVmdF9hcnJvdzogMzcsXG4gICAgICAgIHVwX2Fycm93OiAzOCxcbiAgICAgICAgcmlnaHRfYXJyb3c6IDM5LFxuICAgICAgICBkb3duX2Fycm93OiA0MCxcbiAgICAgICAgaW5zZXJ0OiA0NSxcbiAgICAgICAgXCJkZWxldGVcIjogNDYsXG4gICAgICAgIGxlZnRfd2luZG93X2tleTogOTEsXG4gICAgICAgIHJpZ2h0X3dpbmRvd19rZXk6IDkyLFxuICAgICAgICBzZWxlY3Rfa2V5OiA5MyxcbiAgICAgICAgbnVtX2xvY2s6IDE0NCxcbiAgICAgICAgc2Nyb2xsX2xvY2s6IDE0NSxcbiAgICAgICAgc3BlY2lhbEtleXM6IFs4LCA5LCAxMywgMTYsIDE3LCAxOCwgMTksIDIwLCAyNywgMzMsIDM0LCAzNSwgMzYsIDM3LCAzOCwgMzksIDQwLCA0NSwgNDYsIDkxLCA5MiwgOTMsIDE0NCwgMTQ1XSxcbiAgICAgICAgbnVtYmVyS2V5czogWzQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA5NiwgOTcsIDk4LCA5OSwgMTAwLCAxMDEsIDEwMiwgMTAzLCAxMDQsIDEwNV0sXG4gICAgICAgIGlzU3BlY2lhbEtleTogZnVuY3Rpb24gKGtleUNvZGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNwZWNpYWxLZXlzLmluZGV4T2Yoa2V5Q29kZSkgIT0gLTE7XG4gICAgICAgIH0sXG4gICAgICAgIGlzRGlnaXRLZXk6IGZ1bmN0aW9uIChrZXlDb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW1iZXJLZXlzLmluZGV4T2Yoa2V5Q29kZSkgIT0gLTE7XG4gICAgICAgIH0sXG4gICAgICAgIGlzTW9kaWZpZXJLZXk6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gW2V4cG9ydHMua2V5Q29kZXMuc2hpZnQsIGV4cG9ydHMua2V5Q29kZXMuY2Fwc19sb2NrLCBleHBvcnRzLmtleUNvZGVzLmFsdCwgZXhwb3J0cy5rZXlDb2Rlcy5jdHJsLCBleHBvcnRzLmtleUNvZGVzLmxlZnRfd2luZG93X2tleSwgZXhwb3J0cy5rZXlDb2Rlcy5yaWdodF93aW5kb3dfa2V5XVxuICAgICAgICAgICAgICAgIC5pbmRleE9mKGUud2hpY2gpICE9IC0xO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBleHBvcnRzLkRFRkFVTFRfVEVNUExBVEVTID0ge1xuICAgICAgICBpbWFnZTJMaW5lc1RlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRyLXRlbXBsYXRlLWltYWdlLTItbGluZXNcIj4nICtcbiAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJpbWctd3JhcHBlclwiIHN0eWxlPVwiYmFja2dyb3VuZC1pbWFnZTogdXJsKHt7aW1hZ2VVcmx9fSlcIj48L2Rpdj4nICtcbiAgICAgICAgICAgICcgIDxkaXYgY2xhc3M9XCJjb250ZW50LXdyYXBwZXIgdHItZWRpdG9yLWFyZWFcIj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJtYWluLWxpbmVcIj57e2Rpc3BsYXlWYWx1ZX19PC9kaXY+ICcgK1xuICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwiYWRkaXRpb25hbC1pbmZvXCI+e3thZGRpdGlvbmFsSW5mb319PC9kaXY+JyArXG4gICAgICAgICAgICAnICA8L2Rpdj4nICtcbiAgICAgICAgICAgICc8L2Rpdj4nLFxuICAgICAgICByb3VuZEltYWdlMkxpbmVzQ29sb3JCdWJibGVUZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJ0ci10ZW1wbGF0ZS1yb3VuZC1pbWFnZS0yLWxpbmVzLWNvbG9yLWJ1YmJsZVwiPicgK1xuICAgICAgICAgICAgJyAge3sjaW1hZ2VVcmx9fTxkaXYgY2xhc3M9XCJpbWctd3JhcHBlclwiIHN0eWxlPVwiYmFja2dyb3VuZC1pbWFnZTogdXJsKHt7aW1hZ2VVcmx9fSlcIj48L2Rpdj57ey9pbWFnZVVybH19JyArXG4gICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwiY29udGVudC13cmFwcGVyIHRyLWVkaXRvci1hcmVhXCI+ICcgK1xuICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwibWFpbi1saW5lXCI+e3tkaXNwbGF5VmFsdWV9fTwvZGl2PiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImFkZGl0aW9uYWwtaW5mb1wiPnt7I3N0YXR1c0NvbG9yfX08c3BhbiBjbGFzcz1cInN0YXR1cy1idWJibGVcIiBzdHlsZT1cImJhY2tncm91bmQtY29sb3I6IHt7c3RhdHVzQ29sb3J9fVwiPjwvc3Bhbj57ey9zdGF0dXNDb2xvcn19e3thZGRpdGlvbmFsSW5mb319PC9kaXY+JyArXG4gICAgICAgICAgICAnICA8L2Rpdj4nICtcbiAgICAgICAgICAgICc8L2Rpdj4nLFxuICAgICAgICBpY29uMkxpbmVzVGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtaWNvbi0yLWxpbmVzXCI+JyArXG4gICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwiaW1nLXdyYXBwZXJcIiBzdHlsZT1cImJhY2tncm91bmQtaW1hZ2U6IHVybCh7e2ltYWdlVXJsfX0pXCI+PC9kaXY+JyArXG4gICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwiY29udGVudC13cmFwcGVyIHRyLWVkaXRvci1hcmVhXCI+ICcgK1xuICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwibWFpbi1saW5lXCI+e3tkaXNwbGF5VmFsdWV9fTwvZGl2PiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImFkZGl0aW9uYWwtaW5mb1wiPnt7YWRkaXRpb25hbEluZm99fTwvZGl2PicgK1xuICAgICAgICAgICAgJyAgPC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgaWNvblNpbmdsZUxpbmVUZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJ0ci10ZW1wbGF0ZS1pY29uLXNpbmdsZS1saW5lXCI+JyArXG4gICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwiaW1nLXdyYXBwZXJcIiBzdHlsZT1cImJhY2tncm91bmQtaW1hZ2U6IHVybCh7e2ltYWdlVXJsfX0pXCI+PC9kaXY+JyArXG4gICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwiY29udGVudC13cmFwcGVyIHRyLWVkaXRvci1hcmVhXCI+e3tkaXNwbGF5VmFsdWV9fTwvZGl2PicgK1xuICAgICAgICAgICAgJzwvZGl2PicsXG4gICAgICAgIHNpbmdsZUxpbmVUZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJ0ci10ZW1wbGF0ZS1zaW5nbGUtbGluZVwiPicgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdj57e2Rpc3BsYXlWYWx1ZX19PC9kaXY+ICcgK1xuICAgICAgICAgICAgJyAgPC9kaXY+JyArXG4gICAgICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgY3VycmVuY3lTaW5nbGVMaW5lU2hvcnRUZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJ0ci10ZW1wbGF0ZS1jdXJyZW5jeS1zaW5nbGUtbGluZS1zaG9ydFwiPicgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdj57eyNzeW1ib2x9fTxzcGFuIGNsYXNzPVwiY3VycmVuY3ktc3ltYm9sXCI+e3tzeW1ib2x9fTwvc3Bhbj57ey9zeW1ib2x9fSB7eyNjb2RlfX08c3BhbiBjbGFzcz1cImN1cnJlbmN5LWNvZGVcIj57e2NvZGV9fTwvc3Bhbj57ey9jb2RlfX08L2Rpdj4gJyArXG4gICAgICAgICAgICAnICA8L2Rpdj4nICtcbiAgICAgICAgICAgICc8L2Rpdj4nLFxuICAgICAgICBjdXJyZW5jeVNpbmdsZUxpbmVMb25nVGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtY3VycmVuY3ktc2luZ2xlLWxpbmUtbG9uZ1wiPicgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cInN5bWJvbC1hbmQtY29kZVwiPnt7I2NvZGV9fTxzcGFuIGNsYXNzPVwiY3VycmVuY3ktY29kZVwiPnt7Y29kZX19PC9zcGFuPnt7L2NvZGV9fSB7eyNzeW1ib2x9fTxzcGFuIGNsYXNzPVwiY3VycmVuY3ktc3ltYm9sXCI+e3tzeW1ib2x9fTwvc3Bhbj57ey9zeW1ib2x9fTwvZGl2PicgK1xuICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwiY3VycmVuY3ktbmFtZVwiPnt7bmFtZX19PC9kaXY+JyArXG4gICAgICAgICAgICAnICA8L2Rpdj4nICtcbiAgICAgICAgICAgICc8L2Rpdj4nLFxuICAgICAgICBjdXJyZW5jeTJMaW5lVGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtY3VycmVuY3ktMi1saW5lc1wiPicgK1xuICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPiAnICtcbiAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cIm1haW4tbGluZVwiPicgK1xuICAgICAgICAgICAgJyAgICAgIDxzcGFuIGNsYXNzPVwiY3VycmVuY3ktY29kZVwiPnt7Y29kZX19PC9zcGFuPicgK1xuICAgICAgICAgICAgJyAgICAgIDxzcGFuIGNsYXNzPVwiY3VycmVuY3ktbmFtZVwiPnt7bmFtZX19PC9zcGFuPicgK1xuICAgICAgICAgICAgJyAgICA8L2Rpdj4gJyArXG4gICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJhZGRpdGlvbmFsLWluZm9cIj4nICtcbiAgICAgICAgICAgICcgICAgICA8c3BhbiBjbGFzcz1cImN1cnJlbmN5LXN5bWJvbFwiPnt7c3ltYm9sfX08L3NwYW4+Jm5ic3A7JyArXG4gICAgICAgICAgICAnICAgICAge3sjZXhjaGFuZ2VSYXRlfX0nICtcbiAgICAgICAgICAgICcgICAgICA8ZGl2IGNsYXNzPVwiZXhjaGFuZ2VcIj4nICtcbiAgICAgICAgICAgICcgICAgICAgID0gJyArXG4gICAgICAgICAgICAnICAgICAgICA8c3BhbiBjbGFzcz1cImV4Y2hhbmdlLXJhdGVcIj57e2V4Y2hhbmdlUmF0ZX19PC9zcGFuPicgK1xuICAgICAgICAgICAgJyAgICAgICAgPHNwYW4gY2xhc3M9XCJleGNoYW5nZS1yYXRlLWJhc2VcIj57e2V4Y2hhbmdlUmF0ZUJhc2V9fTwvc3Bhbj4nICtcbiAgICAgICAgICAgICcgICAgICA8L2Rpdj4nICtcbiAgICAgICAgICAgICcgICAgICB7ey9leGNoYW5nZVJhdGV9fScgK1xuICAgICAgICAgICAgJyAgICA8L2Rpdj4nICtcbiAgICAgICAgICAgICcgIDwvZGl2PicgK1xuICAgICAgICAgICAgJzwvZGl2PicsXG4gICAgICAgIGRlZmF1bHRTcGlubmVyVGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItZGVmYXVsdC1zcGlubmVyXCI+PGRpdiBjbGFzcz1cInNwaW5uZXJcIj48L2Rpdj48ZGl2PkZldGNoaW5nIGRhdGEuLi48L2Rpdj48L2Rpdj4nLFxuICAgICAgICBkZWZhdWx0Tm9FbnRyaWVzVGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwidHItZGVmYXVsdC1uby1kYXRhLWRpc3BsYXlcIj48ZGl2Pk5vIG1hdGNoaW5nIGVudHJpZXMuLi48L2Rpdj48L2Rpdj4nXG4gICAgfTtcbiAgICBmdW5jdGlvbiB3cmFwV2l0aERlZmF1bHRUYWdXcmFwcGVyKGVudHJ5SHRtbCkge1xuICAgICAgICByZXR1cm4gKCc8ZGl2IGNsYXNzPVwidHItdGFnYm94LWRlZmF1bHQtd3JhcHBlci10ZW1wbGF0ZVwiPicgK1xuICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJ0ci10YWdib3gtdGFnLWNvbnRlbnRcIj4jI2VudHJ5SHRtbCMjPC9kaXY+JyArXG4gICAgICAgICAgICAnPGRpdiBjbGFzcz1cInRyLXJlbW92ZS1idXR0b25cIj48L2Rpdj4nICtcbiAgICAgICAgICAgICc8L2Rpdj4nKS5yZXBsYWNlKFwiIyNlbnRyeUh0bWwjI1wiLCBlbnRyeUh0bWwpO1xuICAgIH1cbiAgICBleHBvcnRzLndyYXBXaXRoRGVmYXVsdFRhZ1dyYXBwZXIgPSB3cmFwV2l0aERlZmF1bHRUYWdXcmFwcGVyO1xuICAgIGZ1bmN0aW9uIGRlZmF1bHRMaXN0UXVlcnlGdW5jdGlvbkZhY3RvcnkoZW50cmllcywgbWF0Y2hpbmdPcHRpb25zKSB7XG4gICAgICAgIGZ1bmN0aW9uIGZpbHRlckVsZW1lbnRzKHF1ZXJ5U3RyaW5nKSB7XG4gICAgICAgICAgICB2YXIgdmlzaWJsZUVudHJpZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBlbnRyeSA9IGVudHJpZXNbaV07XG4gICAgICAgICAgICAgICAgdmFyICRlbnRyeUVsZW1lbnQgPSBlbnRyeS5fdHJFbnRyeUVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgaWYgKCFxdWVyeVN0cmluZyB8fCB0cml2aWFsTWF0Y2goJGVudHJ5RWxlbWVudC50ZXh0KCkudHJpbSgpLnJlcGxhY2UoL1xcc3syLH0vZywgJyAnKSwgcXVlcnlTdHJpbmcsIG1hdGNoaW5nT3B0aW9ucykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB2aXNpYmxlRW50cmllcy5wdXNoKGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmlzaWJsZUVudHJpZXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChxdWVyeVN0cmluZywgcmVzdWx0Q2FsbGJhY2spIHtcbiAgICAgICAgICAgIHJlc3VsdENhbGxiYWNrKGZpbHRlckVsZW1lbnRzKHF1ZXJ5U3RyaW5nKSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGV4cG9ydHMuZGVmYXVsdExpc3RRdWVyeUZ1bmN0aW9uRmFjdG9yeSA9IGRlZmF1bHRMaXN0UXVlcnlGdW5jdGlvbkZhY3Rvcnk7XG4gICAgZnVuY3Rpb24gY3JlYXRlUHJveHkoZGVsZWdhdGUpIHtcbiAgICAgICAgdmFyIHByb3h5Q29uc3RydWN0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIH07XG4gICAgICAgIHByb3h5Q29uc3RydWN0b3IucHJvdG90eXBlID0gZGVsZWdhdGU7XG4gICAgICAgIHZhciBwcm94eUNvbnN0cnVjdG9yVHlwZXNjcmlwdEhhY2sgPSBwcm94eUNvbnN0cnVjdG9yO1xuICAgICAgICByZXR1cm4gbmV3IHByb3h5Q29uc3RydWN0b3JUeXBlc2NyaXB0SGFjaygpO1xuICAgIH1cbiAgICBleHBvcnRzLmNyZWF0ZVByb3h5ID0gY3JlYXRlUHJveHk7XG4gICAgZnVuY3Rpb24gZGVmYXVsdEVudHJ5TWF0Y2hpbmdGdW5jdGlvbkZhY3Rvcnkoc2VhcmNoZWRQcm9wZXJ0eU5hbWVzLCBtYXRjaGluZ09wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChlbnRyeSwgcXVlcnlTdHJpbmcsIGRlcHRoKSB7XG4gICAgICAgICAgICByZXR1cm4gc2VhcmNoZWRQcm9wZXJ0eU5hbWVzXG4gICAgICAgICAgICAgICAgLnNvbWUoZnVuY3Rpb24gKHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IGVudHJ5W3Byb3BlcnR5TmFtZV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgdHJpdmlhbE1hdGNoKHZhbHVlLnRvU3RyaW5nKCksIHF1ZXJ5U3RyaW5nLCBtYXRjaGluZ09wdGlvbnMpLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZXhwb3J0cy5kZWZhdWx0RW50cnlNYXRjaGluZ0Z1bmN0aW9uRmFjdG9yeSA9IGRlZmF1bHRFbnRyeU1hdGNoaW5nRnVuY3Rpb25GYWN0b3J5O1xuICAgIGZ1bmN0aW9uIGRlZmF1bHRUcmVlUXVlcnlGdW5jdGlvbkZhY3RvcnkodG9wTGV2ZWxFbnRyaWVzLCBlbnRyeU1hdGNoaW5nRnVuY3Rpb24sIGNoaWxkcmVuUHJvcGVydHlOYW1lLCBleHBhbmRlZFByb3BlcnR5TmFtZSkge1xuICAgICAgICBmdW5jdGlvbiBmaW5kTWF0Y2hpbmdFbnRyaWVzQW5kVGhlaXJBbmNlc3RvcnMoZW50cnksIHF1ZXJ5U3RyaW5nLCBub2RlRGVwdGgpIHtcbiAgICAgICAgICAgIHZhciBlbnRyeVByb3h5ID0gY3JlYXRlUHJveHkoZW50cnkpO1xuICAgICAgICAgICAgZW50cnlQcm94eVtjaGlsZHJlblByb3BlcnR5TmFtZV0gPSBbXTtcbiAgICAgICAgICAgIGVudHJ5UHJveHlbZXhwYW5kZWRQcm9wZXJ0eU5hbWVdID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoZW50cnlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbnRyeVtjaGlsZHJlblByb3BlcnR5TmFtZV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gZW50cnlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRQcm94eSA9IGZpbmRNYXRjaGluZ0VudHJpZXNBbmRUaGVpckFuY2VzdG9ycyhjaGlsZCwgcXVlcnlTdHJpbmcsIG5vZGVEZXB0aCArIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGRQcm94eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW50cnlQcm94eVtjaGlsZHJlblByb3BlcnR5TmFtZV0ucHVzaChjaGlsZFByb3h5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5UHJveHlbZXhwYW5kZWRQcm9wZXJ0eU5hbWVdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBoYXNNYXRjaGluZ0NoaWxkcmVuID0gZW50cnlQcm94eVtjaGlsZHJlblByb3BlcnR5TmFtZV0ubGVuZ3RoID4gMDtcbiAgICAgICAgICAgIHZhciBtYXRjaGVzSXRzZWxmID0gZW50cnlNYXRjaGluZ0Z1bmN0aW9uKGVudHJ5LCBxdWVyeVN0cmluZywgbm9kZURlcHRoKTtcbiAgICAgICAgICAgIGlmIChtYXRjaGVzSXRzZWxmICYmICFoYXNNYXRjaGluZ0NoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgZW50cnlQcm94eVtjaGlsZHJlblByb3BlcnR5TmFtZV0gPSBlbnRyeVtjaGlsZHJlblByb3BlcnR5TmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlc0l0c2VsZiB8fCBoYXNNYXRjaGluZ0NoaWxkcmVuID8gZW50cnlQcm94eSA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChxdWVyeVN0cmluZywgcmVzdWx0Q2FsbGJhY2spIHtcbiAgICAgICAgICAgIGlmICghcXVlcnlTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRDYWxsYmFjayh0b3BMZXZlbEVudHJpZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoaW5nRW50cmllcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdG9wTGV2ZWxFbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbEVudHJ5ID0gdG9wTGV2ZWxFbnRyaWVzW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZW50cnlQcm94eSA9IGZpbmRNYXRjaGluZ0VudHJpZXNBbmRUaGVpckFuY2VzdG9ycyh0b3BMZXZlbEVudHJ5LCBxdWVyeVN0cmluZywgMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbnRyeVByb3h5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ0VudHJpZXMucHVzaChlbnRyeVByb3h5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHRDYWxsYmFjayhtYXRjaGluZ0VudHJpZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbiAgICBleHBvcnRzLmRlZmF1bHRUcmVlUXVlcnlGdW5jdGlvbkZhY3RvcnkgPSBkZWZhdWx0VHJlZVF1ZXJ5RnVuY3Rpb25GYWN0b3J5O1xuICAgIGZ1bmN0aW9uIGN1c3RvbVRyZWVRdWVyeUZ1bmN0aW9uRmFjdG9yeSh0b3BMZXZlbEVudHJpZXMsIGNoaWxkcmVuUHJvcGVydHlOYW1lLCBleHBhbmRlZFByb3BlcnR5TmFtZSwgY3VzdG9tTm9kZU1hdGNoaW5nRnVuY3Rpb24pIHtcbiAgICAgICAgZnVuY3Rpb24gZmluZE1hdGNoaW5nRW50cmllc0FuZFRoZWlyQW5jZXN0b3JzKGVudHJ5LCBxdWVyeVN0cmluZywgbm9kZURlcHRoKSB7XG4gICAgICAgICAgICB2YXIgZW50cnlQcm94eSA9IGNyZWF0ZVByb3h5KGVudHJ5KTtcbiAgICAgICAgICAgIGVudHJ5UHJveHlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdID0gW107XG4gICAgICAgICAgICBlbnRyeVByb3h5W2V4cGFuZGVkUHJvcGVydHlOYW1lXSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGVudHJ5W2NoaWxkcmVuUHJvcGVydHlOYW1lXSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW50cnlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGVudHJ5W2NoaWxkcmVuUHJvcGVydHlOYW1lXVtpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkUHJveHkgPSBmaW5kTWF0Y2hpbmdFbnRyaWVzQW5kVGhlaXJBbmNlc3RvcnMoY2hpbGQsIHF1ZXJ5U3RyaW5nLCBub2RlRGVwdGggKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkUHJveHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5UHJveHlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdLnB1c2goY2hpbGRQcm94eSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbnRyeVByb3h5W2V4cGFuZGVkUHJvcGVydHlOYW1lXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaGFzTWF0Y2hpbmdDaGlsZHJlbiA9IGVudHJ5UHJveHlbY2hpbGRyZW5Qcm9wZXJ0eU5hbWVdLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICB2YXIgbWF0Y2hlc0l0c2VsZiA9IGN1c3RvbU5vZGVNYXRjaGluZ0Z1bmN0aW9uKGVudHJ5LCBxdWVyeVN0cmluZywgbm9kZURlcHRoKTtcbiAgICAgICAgICAgIGlmIChtYXRjaGVzSXRzZWxmICYmICFoYXNNYXRjaGluZ0NoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgZW50cnlQcm94eVtjaGlsZHJlblByb3BlcnR5TmFtZV0gPSBlbnRyeVtjaGlsZHJlblByb3BlcnR5TmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlc0l0c2VsZiB8fCBoYXNNYXRjaGluZ0NoaWxkcmVuID8gZW50cnlQcm94eSA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChxdWVyeVN0cmluZywgcmVzdWx0Q2FsbGJhY2spIHtcbiAgICAgICAgICAgIGlmICghcXVlcnlTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRDYWxsYmFjayh0b3BMZXZlbEVudHJpZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoaW5nRW50cmllcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdG9wTGV2ZWxFbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbEVudHJ5ID0gdG9wTGV2ZWxFbnRyaWVzW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZW50cnlQcm94eSA9IGZpbmRNYXRjaGluZ0VudHJpZXNBbmRUaGVpckFuY2VzdG9ycyh0b3BMZXZlbEVudHJ5LCBxdWVyeVN0cmluZywgMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbnRyeVByb3h5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ0VudHJpZXMucHVzaChlbnRyeVByb3h5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHRDYWxsYmFjayhtYXRjaGluZ0VudHJpZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbiAgICBleHBvcnRzLmN1c3RvbVRyZWVRdWVyeUZ1bmN0aW9uRmFjdG9yeSA9IGN1c3RvbVRyZWVRdWVyeUZ1bmN0aW9uRmFjdG9yeTtcbiAgICBmdW5jdGlvbiBzZWxlY3RFbGVtZW50Q29udGVudHMoZG9tRWxlbWVudCwgc3RhcnQsIGVuZCkge1xuICAgICAgICBkb21FbGVtZW50ID0gZG9tRWxlbWVudC5maXJzdENoaWxkIHx8IGRvbUVsZW1lbnQ7XG4gICAgICAgIGVuZCA9IGVuZCB8fCBzdGFydDtcbiAgICAgICAgdmFyIHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgcmFuZ2Uuc2V0U3RhcnQoZG9tRWxlbWVudCwgc3RhcnQpO1xuICAgICAgICByYW5nZS5zZXRFbmQoZG9tRWxlbWVudCwgZW5kKTtcbiAgICAgICAgdmFyIHNlbCA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHNlbC5yZW1vdmVBbGxSYW5nZXMoKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICB9XG4gICAgICAgIHNlbC5hZGRSYW5nZShyYW5nZSk7XG4gICAgfVxuICAgIGV4cG9ydHMuc2VsZWN0RWxlbWVudENvbnRlbnRzID0gc2VsZWN0RWxlbWVudENvbnRlbnRzO1xuICAgIGV4cG9ydHMuZXNjYXBlU3BlY2lhbFJlZ2V4Q2hhcmFjdGVyID0gZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgcmV0dXJuIHMucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csIFwiXFxcXCQmXCIpO1xuICAgIH07XG4gICAgZnVuY3Rpb24gb2JqZWN0RXF1YWxzKHgsIHkpIHtcbiAgICAgICAgJ3VzZSBzdHJpY3QnO1xuICAgICAgICBpZiAoeCA9PT0gbnVsbCB8fCB4ID09PSB1bmRlZmluZWQgfHwgeSA9PT0gbnVsbCB8fCB5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB4ID09PSB5O1xuICAgICAgICB9XG4gICAgICAgIGlmICh4LmNvbnN0cnVjdG9yICE9PSB5LmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHggaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIHggPT09IHk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHggaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB4ID09PSB5O1xuICAgICAgICB9XG4gICAgICAgIGlmICh4ID09PSB5IHx8IHgudmFsdWVPZigpID09PSB5LnZhbHVlT2YoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoeCkgJiYgeC5sZW5ndGggIT09IHkubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHggaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEoeCBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISh5IGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwID0gT2JqZWN0LmtleXMoeCk7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh5KS5ldmVyeShmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgcmV0dXJuIHAuaW5kZXhPZihpKSAhPT0gLTE7XG4gICAgICAgIH0pICYmXG4gICAgICAgICAgICBwLmV2ZXJ5KGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdEVxdWFscyh4W2ldLCB5W2ldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cbiAgICBleHBvcnRzLm9iamVjdEVxdWFscyA9IG9iamVjdEVxdWFscztcbiAgICBmdW5jdGlvbiB0cml2aWFsTWF0Y2godGV4dCwgc2VhcmNoU3RyaW5nLCBvcHRpb25zKSB7XG4gICAgICAgIGlmICghc2VhcmNoU3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gW3tcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IDAsXG4gICAgICAgICAgICAgICAgICAgIGxlbmd0aDogdGV4dC5sZW5ndGhcbiAgICAgICAgICAgICAgICB9XTtcbiAgICAgICAgfVxuICAgICAgICBvcHRpb25zID0gJC5leHRlbmQoe1xuICAgICAgICAgICAgbWF0Y2hpbmdNb2RlOiAnY29udGFpbnMnLFxuICAgICAgICAgICAgaWdub3JlQ2FzZTogdHJ1ZSxcbiAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDNcbiAgICAgICAgfSwgb3B0aW9ucyB8fCBudWxsKTtcbiAgICAgICAgaWYgKG9wdGlvbnMuaWdub3JlQ2FzZSkge1xuICAgICAgICAgICAgdGV4dCA9IHRleHQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIHNlYXJjaFN0cmluZyA9IHNlYXJjaFN0cmluZy50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGZpbmRSZWdleE1hdGNoZXMocmVnZXgpIHtcbiAgICAgICAgICAgIHZhciBtYXRjaGVzID0gW107XG4gICAgICAgICAgICB2YXIgbWF0Y2g7XG4gICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSByZWdleC5leGVjKHRleHQpKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IG1hdGNoLmluZGV4LFxuICAgICAgICAgICAgICAgICAgICBsZW5ndGg6IG1hdGNoWzBdLmxlbmd0aFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXM7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZmluZExldmVuc2h0ZWluTWF0Y2hlcyh0ZXh0LCBzZWFyY2hTdHJpbmcpIHtcbiAgICAgICAgICAgIHZhciBsZXZlbnNodGVpbiA9IG5ldyBMZXZlbnNodGVpbih0ZXh0LCBzZWFyY2hTdHJpbmcpO1xuICAgICAgICAgICAgaWYgKGxldmVuc2h0ZWluLmRpc3RhbmNlIDw9IG9wdGlvbnMubWF4TGV2ZW5zaHRlaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGg6IHNlYXJjaFN0cmluZy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZTogbGV2ZW5zaHRlaW4uZGlzdGFuY2VcbiAgICAgICAgICAgICAgICAgICAgfV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMubWF0Y2hpbmdNb2RlID09ICdjb250YWlucycpIHtcbiAgICAgICAgICAgIHNlYXJjaFN0cmluZyA9IHNlYXJjaFN0cmluZy5yZXBsYWNlKC9bLVtcXF17fSgpKis/LixcXFxcXiR8I1xcc10vZywgXCJcXFxcJCZcIik7XG4gICAgICAgICAgICByZXR1cm4gZmluZFJlZ2V4TWF0Y2hlcyhuZXcgUmVnRXhwKHNlYXJjaFN0cmluZywgXCJnXCIpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvcHRpb25zLm1hdGNoaW5nTW9kZSA9PSAncHJlZml4Jykge1xuICAgICAgICAgICAgc2VhcmNoU3RyaW5nID0gc2VhcmNoU3RyaW5nLnJlcGxhY2UoL1stW1xcXXt9KCkqKz8uLFxcXFxeJHwjXFxzXS9nLCBcIlxcXFwkJlwiKTtcbiAgICAgICAgICAgIHJldHVybiBmaW5kUmVnZXhNYXRjaGVzKG5ldyBSZWdFeHAoJ14nICsgc2VhcmNoU3RyaW5nLCBcImdcIikpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9wdGlvbnMubWF0Y2hpbmdNb2RlID09ICdwcmVmaXgtd29yZCcpIHtcbiAgICAgICAgICAgIHNlYXJjaFN0cmluZyA9IHNlYXJjaFN0cmluZy5yZXBsYWNlKC9bLVtcXF17fSgpKis/LixcXFxcXiR8I1xcc10vZywgXCJcXFxcJCZcIik7XG4gICAgICAgICAgICBpZiAoc2VhcmNoU3RyaW5nLmNoYXJBdCgwKS5tYXRjaCgvXlxcdy8pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZpbmRSZWdleE1hdGNoZXMobmV3IFJlZ0V4cCgnXFxcXGInICsgc2VhcmNoU3RyaW5nLCBcImdcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZpbmRSZWdleE1hdGNoZXMobmV3IFJlZ0V4cChzZWFyY2hTdHJpbmcsIFwiZ1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3B0aW9ucy5tYXRjaGluZ01vZGUgPT0gJ3ByZWZpeC1sZXZlbnNodGVpbicpIHtcbiAgICAgICAgICAgIHJldHVybiBmaW5kTGV2ZW5zaHRlaW5NYXRjaGVzKHRleHQuc3Vic3RyKDAsIE1hdGgubWluKHNlYXJjaFN0cmluZy5sZW5ndGgsIHRleHQubGVuZ3RoKSksIHNlYXJjaFN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3B0aW9ucy5tYXRjaGluZ01vZGUgPT0gJ2xldmVuc2h0ZWluJykge1xuICAgICAgICAgICAgcmV0dXJuIGZpbmRMZXZlbnNodGVpbk1hdGNoZXModGV4dCwgc2VhcmNoU3RyaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IFwidW5rbm93biBtYXRjaGluZ01vZGU6IFwiICsgb3B0aW9ucy5tYXRjaGluZ01vZGU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZXhwb3J0cy50cml2aWFsTWF0Y2ggPSB0cml2aWFsTWF0Y2g7XG4gICAgZnVuY3Rpb24gbWluaW1hbGx5U2Nyb2xsVG8oZWxlbWVudCwgdGFyZ2V0KSB7XG4gICAgICAgIHZhciAkdGFyZ2V0ID0gJCh0YXJnZXQpO1xuICAgICAgICAkKGVsZW1lbnQpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcbiAgICAgICAgICAgIHZhciB2aWV3UG9ydE1pblkgPSAkdGhpcy5zY3JvbGxUb3AoKTtcbiAgICAgICAgICAgIHZhciB2aWV3UG9ydE1heFkgPSB2aWV3UG9ydE1pblkgKyAkdGhpcy5pbm5lckhlaWdodCgpO1xuICAgICAgICAgICAgdmFyIHRhcmdldE1pblkgPSAkKCR0YXJnZXQpLm9mZnNldCgpLnRvcCAtICQodGhpcykub2Zmc2V0KCkudG9wICsgJHRoaXMuc2Nyb2xsVG9wKCk7XG4gICAgICAgICAgICB2YXIgdGFyZ2V0TWF4WSA9IHRhcmdldE1pblkgKyAkdGFyZ2V0LmhlaWdodCgpO1xuICAgICAgICAgICAgaWYgKHRhcmdldE1pblkgPCB2aWV3UG9ydE1pblkpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5zY3JvbGxUb3AodGFyZ2V0TWluWSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0YXJnZXRNYXhZID4gdmlld1BvcnRNYXhZKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2Nyb2xsVG9wKE1hdGgubWluKHRhcmdldE1pblksIHRhcmdldE1heFkgLSAkdGhpcy5pbm5lckhlaWdodCgpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgdmlld1BvcnRNaW5YID0gJHRoaXMuc2Nyb2xsTGVmdCgpO1xuICAgICAgICAgICAgdmFyIHZpZXdQb3J0TWF4WCA9IHZpZXdQb3J0TWluWCArICR0aGlzLmlubmVyV2lkdGgoKTtcbiAgICAgICAgICAgIHZhciB0YXJnZXRNaW5YID0gJCgkdGFyZ2V0KS5vZmZzZXQoKS5sZWZ0IC0gJCh0aGlzKS5vZmZzZXQoKS5sZWZ0ICsgJHRoaXMuc2Nyb2xsTGVmdCgpO1xuICAgICAgICAgICAgdmFyIHRhcmdldE1heFggPSB0YXJnZXRNaW5YICsgJHRhcmdldC53aWR0aCgpO1xuICAgICAgICAgICAgaWYgKHRhcmdldE1pblggPCB2aWV3UG9ydE1pblgpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5zY3JvbGxMZWZ0KHRhcmdldE1pblgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGFyZ2V0TWF4WCA+IHZpZXdQb3J0TWF4WCkge1xuICAgICAgICAgICAgICAgICR0aGlzLnNjcm9sbExlZnQoTWF0aC5taW4odGFyZ2V0TWluWCwgdGFyZ2V0TWF4WCAtICR0aGlzLmlubmVyV2lkdGgoKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZXhwb3J0cy5taW5pbWFsbHlTY3JvbGxUbyA9IG1pbmltYWxseVNjcm9sbFRvO1xuICAgIGZ1bmN0aW9uIHNldFRpbWVvdXRPckRvSW1tZWRpYXRlbHkoZiwgZGVsYXkpIHtcbiAgICAgICAgaWYgKGRlbGF5ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cuc2V0VGltZW91dChmKCksIGRlbGF5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB2b2lkIGYoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBleHBvcnRzLnNldFRpbWVvdXRPckRvSW1tZWRpYXRlbHkgPSBzZXRUaW1lb3V0T3JEb0ltbWVkaWF0ZWx5O1xufSk7XG5cblxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIiwgXCJqcXVlcnlcIiwgXCJtb21lbnRcIiwgXCIuL1RyaXZpYWxFdmVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBtb21lbnQgPSByZXF1aXJlKFwibW9tZW50XCIpO1xuICAgIHZhciBUcml2aWFsRXZlbnRfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxFdmVudFwiKTtcbiAgICB2YXIgV2Vla0RheTtcbiAgICAoZnVuY3Rpb24gKFdlZWtEYXkpIHtcbiAgICAgICAgV2Vla0RheVtXZWVrRGF5W1wiTU9OREFZXCJdID0gMV0gPSBcIk1PTkRBWVwiO1xuICAgICAgICBXZWVrRGF5W1dlZWtEYXlbXCJUVUVTREFZXCJdID0gMl0gPSBcIlRVRVNEQVlcIjtcbiAgICAgICAgV2Vla0RheVtXZWVrRGF5W1wiV0VETkVTREFZXCJdID0gM10gPSBcIldFRE5FU0RBWVwiO1xuICAgICAgICBXZWVrRGF5W1dlZWtEYXlbXCJUSFVSU0RBWVwiXSA9IDRdID0gXCJUSFVSU0RBWVwiO1xuICAgICAgICBXZWVrRGF5W1dlZWtEYXlbXCJGUklEQVlcIl0gPSA1XSA9IFwiRlJJREFZXCI7XG4gICAgICAgIFdlZWtEYXlbV2Vla0RheVtcIlNBVFVSREFZXCJdID0gNl0gPSBcIlNBVFVSREFZXCI7XG4gICAgICAgIFdlZWtEYXlbV2Vla0RheVtcIlNVTkRBWVwiXSA9IDddID0gXCJTVU5EQVlcIjtcbiAgICB9KShXZWVrRGF5ID0gZXhwb3J0cy5XZWVrRGF5IHx8IChleHBvcnRzLldlZWtEYXkgPSB7fSkpO1xuICAgIHZhciBUcml2aWFsQ2FsZW5kYXJCb3ggPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsQ2FsZW5kYXJCb3goJGNvbnRhaW5lciwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgICAgIHRoaXMuJGNvbnRhaW5lciA9ICRjb250YWluZXI7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMub25PbkVkaXRpbmdUaW1lVW5pdENoYW5nZSA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZERhdGU6IG1vbWVudCgpLFxuICAgICAgICAgICAgICAgIGZpcnN0RGF5T2ZXZWVrOiBXZWVrRGF5Lk1PTkRBWSxcbiAgICAgICAgICAgICAgICBtb2RlOiAnZGF0ZXRpbWUnLFxuICAgICAgICAgICAgICAgIGhpZ2hsaWdodEtleWJvYXJkTmF2aWdhdGlvblN0YXRlOiBmYWxzZVxuICAgICAgICAgICAgfSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmtleWJvYXJkTmF2aWdhdGlvblN0YXRlID0gdGhpcy5jb25maWcubW9kZSA9PSAndGltZScgPyAnaG91cicgOiAnZGF5JztcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmROYXZDc3NDbGFzcyA9IHRoaXMuY29uZmlnLmhpZ2hsaWdodEtleWJvYXJkTmF2aWdhdGlvblN0YXRlID8gXCJrZXlib2FyZC1uYXZcIiA6IFwiXCI7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IHRoaXMuY29uZmlnLnNlbGVjdGVkRGF0ZTtcbiAgICAgICAgICAgIHRoaXMuJGNhbGVuZGFyQm94ID0gJCgnPGRpdiBjbGFzcz1cInRyLWNhbGVuZGFyYm94XCIvPicpLmFwcGVuZFRvKHRoaXMuJGNvbnRhaW5lcik7XG4gICAgICAgICAgICB0aGlzLiRjYWxlbmRhckRpc3BsYXkgPSAkKCc8ZGl2IGNsYXNzPVwidHItY2FsZW5kYXItZGlzcGxheVwiLz4nKTtcbiAgICAgICAgICAgIHRoaXMuJHllYXJEaXNwbGF5ID0gJCgnPGRpdiBjbGFzcz1cInllYXJcIj48c3BhbiBjbGFzcz1cImJhY2stYnV0dG9uXCIvPjxzcGFuIGNsYXNzPVwibmFtZVwiLz48c3BhbiBjbGFzcz1cImZvcndhcmQtYnV0dG9uXCIvPjwvZGl2PicpLmFwcGVuZFRvKHRoaXMuJGNhbGVuZGFyRGlzcGxheSk7XG4gICAgICAgICAgICB0aGlzLiRtb250aERpc3BsYXkgPSAkKCc8ZGl2IGNsYXNzPVwibW9udGhcIj48c3BhbiBjbGFzcz1cImJhY2stYnV0dG9uXCIvPjxzcGFuIGNsYXNzPVwibmFtZVwiLz48c3BhbiBjbGFzcz1cImZvcndhcmQtYnV0dG9uXCIvPjwvZGl2PicpLmFwcGVuZFRvKHRoaXMuJGNhbGVuZGFyRGlzcGxheSk7XG4gICAgICAgICAgICB0aGlzLiRtb250aFRhYmxlID0gJCgnPGRpdiBjbGFzcz1cIm1vbnRoLXRhYmxlXCI+JykuYXBwZW5kVG8odGhpcy4kY2FsZW5kYXJEaXNwbGF5KTtcbiAgICAgICAgICAgIHRoaXMuJHllYXIgPSB0aGlzLiR5ZWFyRGlzcGxheS5maW5kKFwiLm5hbWVcIik7XG4gICAgICAgICAgICB0aGlzLiRtb250aCA9IHRoaXMuJG1vbnRoRGlzcGxheS5maW5kKFwiLm5hbWVcIik7XG4gICAgICAgICAgICB0aGlzLiR5ZWFyRGlzcGxheS5jbGljayh0aGlzLnNldEtleWJvYXJkTmF2aWdhdGlvblN0YXRlLmJpbmQodGhpcywgXCJ5ZWFyXCIpKTtcbiAgICAgICAgICAgIHRoaXMuJHllYXJEaXNwbGF5LmZpbmQoJy5iYWNrLWJ1dHRvbicpLmNsaWNrKHRoaXMubmF2aWdhdGVCeVVuaXQuYmluZCh0aGlzLCBcInllYXJcIiwgXCJsZWZ0XCIsIHRydWUpKTtcbiAgICAgICAgICAgIHRoaXMuJHllYXJEaXNwbGF5LmZpbmQoJy5mb3J3YXJkLWJ1dHRvbicpLmNsaWNrKHRoaXMubmF2aWdhdGVCeVVuaXQuYmluZCh0aGlzLCBcInllYXJcIiwgXCJyaWdodFwiLCB0cnVlKSk7XG4gICAgICAgICAgICB0aGlzLiRtb250aERpc3BsYXkuY2xpY2sodGhpcy5zZXRLZXlib2FyZE5hdmlnYXRpb25TdGF0ZS5iaW5kKHRoaXMsIFwibW9udGhcIikpO1xuICAgICAgICAgICAgdGhpcy4kbW9udGhEaXNwbGF5LmZpbmQoJy5iYWNrLWJ1dHRvbicpLmNsaWNrKHRoaXMubmF2aWdhdGVCeVVuaXQuYmluZCh0aGlzLCBcIm1vbnRoXCIsIFwibGVmdFwiLCB0cnVlKSk7XG4gICAgICAgICAgICB0aGlzLiRtb250aERpc3BsYXkuZmluZCgnLmZvcndhcmQtYnV0dG9uJykuY2xpY2sodGhpcy5uYXZpZ2F0ZUJ5VW5pdC5iaW5kKHRoaXMsIFwibW9udGhcIiwgXCJyaWdodFwiLCB0cnVlKSk7XG4gICAgICAgICAgICB0aGlzLiRjbG9ja0Rpc3BsYXkgPSAkKCc8ZGl2IGNsYXNzPVwidHItY2xvY2stZGlzcGxheVwiLz4nKVxuICAgICAgICAgICAgICAgIC5hcHBlbmQoJzxzdmcgY2xhc3M9XCJjbG9ja1wiIHZpZXdCb3g9XCIwIDAgMTAwIDEwMFwiIHdpZHRoPVwiMTAwXCIgaGVpZ2h0PVwiMTAwXCI+ICcgK1xuICAgICAgICAgICAgICAgICc8Y2lyY2xlIGNsYXNzPVwiY2xvY2tjaXJjbGVcIiBjeD1cIjUwXCIgY3k9XCI1MFwiIHI9XCI0NVwiLz4gJyArXG4gICAgICAgICAgICAgICAgJzxnIGNsYXNzPVwidGlja3NcIiA+ICcgK1xuICAgICAgICAgICAgICAgICcgPGxpbmUgeDE9XCI1MFwiIHkxPVwiNS4wMDBcIiB4Mj1cIjUwLjAwXCIgeTI9XCIxMC4wMFwiLz4gPGxpbmUgeDE9XCI3Mi41MFwiIHkxPVwiMTEuMDNcIiB4Mj1cIjcwLjAwXCIgeTI9XCIxNS4zNlwiLz4gPGxpbmUgeDE9XCI4OC45N1wiIHkxPVwiMjcuNTBcIiB4Mj1cIjg0LjY0XCIgeTI9XCIzMC4wMFwiLz4gPGxpbmUgeDE9XCI5NS4wMFwiIHkxPVwiNTAuMDBcIiB4Mj1cIjkwLjAwXCIgeTI9XCI1MC4wMFwiLz4gPGxpbmUgeDE9XCI4OC45N1wiIHkxPVwiNzIuNTBcIiB4Mj1cIjg0LjY0XCIgeTI9XCI3MC4wMFwiLz4gPGxpbmUgeDE9XCI3Mi41MFwiIHkxPVwiODguOTdcIiB4Mj1cIjcwLjAwXCIgeTI9XCI4NC42NFwiLz4gPGxpbmUgeDE9XCI1MC4wMFwiIHkxPVwiOTUuMDBcIiB4Mj1cIjUwLjAwXCIgeTI9XCI5MC4wMFwiLz4gPGxpbmUgeDE9XCIyNy41MFwiIHkxPVwiODguOTdcIiB4Mj1cIjMwLjAwXCIgeTI9XCI4NC42NFwiLz4gPGxpbmUgeDE9XCIxMS4wM1wiIHkxPVwiNzIuNTBcIiB4Mj1cIjE1LjM2XCIgeTI9XCI3MC4wMFwiLz4gPGxpbmUgeDE9XCI1LjAwMFwiIHkxPVwiNTAuMDBcIiB4Mj1cIjEwLjAwXCIgeTI9XCI1MC4wMFwiLz4gPGxpbmUgeDE9XCIxMS4wM1wiIHkxPVwiMjcuNTBcIiB4Mj1cIjE1LjM2XCIgeTI9XCIzMC4wMFwiLz4gPGxpbmUgeDE9XCIyNy41MFwiIHkxPVwiMTEuMDNcIiB4Mj1cIjMwLjAwXCIgeTI9XCIxNS4zNlwiLz4gJyArXG4gICAgICAgICAgICAgICAgJzwvZz4gJyArXG4gICAgICAgICAgICAgICAgJzxnIGNsYXNzPVwibnVtYmVyc1wiPicgK1xuICAgICAgICAgICAgICAgICcgPHRleHQgeD1cIjUwXCIgeT1cIjIyXCI+MTI8L3RleHQ+IDx0ZXh0IHg9XCI4NVwiIHk9XCI1NVwiPjM8L3RleHQ+IDx0ZXh0IHg9XCI1MFwiIHk9XCI4OFwiPjY8L3RleHQ+IDx0ZXh0IHg9XCIxNVwiIHk9XCI1NVwiPjk8L3RleHQ+ICcgK1xuICAgICAgICAgICAgICAgICc8L2c+ICcgK1xuICAgICAgICAgICAgICAgICc8ZyBjbGFzcz1cImhhbmRzXCI+JyArXG4gICAgICAgICAgICAgICAgJyA8bGluZSBjbGFzcz1cIm1pbnV0ZWhhbmRcIiB4MT1cIjUwXCIgeTE9XCI1MFwiIHgyPVwiNTBcIiB5Mj1cIjIwXCIvPicgK1xuICAgICAgICAgICAgICAgICcgPGxpbmUgY2xhc3M9XCJob3VyaGFuZFwiIHgxPVwiNTBcIiB5MT1cIjUwXCIgeDI9XCI1MFwiIHkyPVwiMjZcIi8+ICcgK1xuICAgICAgICAgICAgICAgICc8L2c+ICcgK1xuICAgICAgICAgICAgICAgICc8ZyBjbGFzcz1cImFtLXBtLWJveFwiPicgK1xuICAgICAgICAgICAgICAgICcgPHJlY3QgeD1cIjU4XCIgeT1cIjU5XCIgd2lkdGg9XCIyMFwiIGhlaWdodD1cIjE1XCIvPicgK1xuICAgICAgICAgICAgICAgICcgPHRleHQgY2xhc3M9XCJhbS1wbS10ZXh0XCIgeD1cIjYwXCIgeT1cIjcwXCIgPj8/PC90ZXh0PicgK1xuICAgICAgICAgICAgICAgICc8L2c+JyArXG4gICAgICAgICAgICAgICAgJzwvc3ZnPicpLmFwcGVuZCgnPGRpdiBjbGFzcz1cImRpZ2l0YWwtdGltZS1kaXNwbGF5XCI+PGRpdiBjbGFzcz1cImhvdXItd3JhcHBlclwiPicgK1xuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwidXAtYnV0dG9uXCIvPjxkaXYgY2xhc3M9XCJob3VyXCI+Pz88L2Rpdj48ZGl2IGNsYXNzPVwiZG93bi1idXR0b25cIi8+JyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Pjo8ZGl2IGNsYXNzPVwibWludXRlLXdyYXBwZXJcIj4nICtcbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cInVwLWJ1dHRvblwiLz48ZGl2IGNsYXNzPVwibWludXRlXCI+Pz88L2Rpdj48ZGl2IGNsYXNzPVwiZG93bi1idXR0b25cIi8+JyArXG4gICAgICAgICAgICAgICAgJzwvZGl2PjwvZGl2PicpO1xuICAgICAgICAgICAgdGhpcy4kaG91ckhhbmQgPSB0aGlzLiRjbG9ja0Rpc3BsYXkuZmluZCgnLmhvdXJoYW5kJyk7XG4gICAgICAgICAgICB0aGlzLiRtaW51dGVIYW5kID0gdGhpcy4kY2xvY2tEaXNwbGF5LmZpbmQoJy5taW51dGVoYW5kJyk7XG4gICAgICAgICAgICB0aGlzLiRhbVBtVGV4dCA9IHRoaXMuJGNsb2NrRGlzcGxheS5maW5kKCcuYW0tcG0tdGV4dCcpO1xuICAgICAgICAgICAgdGhpcy4kZGlnaXRhbFRpbWVIb3VyRGlzcGxheVdyYXBwZXIgPSB0aGlzLiRjbG9ja0Rpc3BsYXkuZmluZCgnLmRpZ2l0YWwtdGltZS1kaXNwbGF5IC5ob3VyLXdyYXBwZXInKTtcbiAgICAgICAgICAgIHRoaXMuJGRpZ2l0YWxUaW1lSG91ckRpc3BsYXkgPSB0aGlzLiRjbG9ja0Rpc3BsYXkuZmluZCgnLmRpZ2l0YWwtdGltZS1kaXNwbGF5IC5ob3VyJyk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZUhvdXJEaXNwbGF5V3JhcHBlci5jbGljayh0aGlzLnNldEtleWJvYXJkTmF2aWdhdGlvblN0YXRlLmJpbmQodGhpcywgXCJob3VyXCIpKTtcbiAgICAgICAgICAgIHRoaXMuJGRpZ2l0YWxUaW1lSG91ckRpc3BsYXlXcmFwcGVyLmZpbmQoXCIudXAtYnV0dG9uXCIpLmNsaWNrKHRoaXMubmF2aWdhdGVCeVVuaXQuYmluZCh0aGlzLCBcImhvdXJcIiwgXCJ1cFwiLCB0cnVlKSk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZUhvdXJEaXNwbGF5V3JhcHBlci5maW5kKFwiLmRvd24tYnV0dG9uXCIpLmNsaWNrKHRoaXMubmF2aWdhdGVCeVVuaXQuYmluZCh0aGlzLCBcImhvdXJcIiwgXCJkb3duXCIsIHRydWUpKTtcbiAgICAgICAgICAgIHRoaXMuJGRpZ2l0YWxUaW1lTWludXRlRGlzcGxheVdyYXBwZXIgPSB0aGlzLiRjbG9ja0Rpc3BsYXkuZmluZCgnLmRpZ2l0YWwtdGltZS1kaXNwbGF5IC5taW51dGUtd3JhcHBlcicpO1xuICAgICAgICAgICAgdGhpcy4kZGlnaXRhbFRpbWVNaW51dGVEaXNwbGF5ID0gdGhpcy4kY2xvY2tEaXNwbGF5LmZpbmQoJy5kaWdpdGFsLXRpbWUtZGlzcGxheSAubWludXRlJyk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZU1pbnV0ZURpc3BsYXlXcmFwcGVyLmNsaWNrKHRoaXMuc2V0S2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUuYmluZCh0aGlzLCBcIm1pbnV0ZVwiKSk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZU1pbnV0ZURpc3BsYXlXcmFwcGVyLmZpbmQoXCIudXAtYnV0dG9uXCIpLmNsaWNrKHRoaXMubmF2aWdhdGVCeVVuaXQuYmluZCh0aGlzLCBcIm1pbnV0ZVwiLCBcInVwXCIsIHRydWUpKTtcbiAgICAgICAgICAgIHRoaXMuJGRpZ2l0YWxUaW1lTWludXRlRGlzcGxheVdyYXBwZXIuZmluZChcIi5kb3duLWJ1dHRvblwiKS5jbGljayh0aGlzLm5hdmlnYXRlQnlVbml0LmJpbmQodGhpcywgXCJtaW51dGVcIiwgXCJkb3duXCIsIHRydWUpKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5tb2RlID09ICdkYXRlJyB8fCB0aGlzLmNvbmZpZy5tb2RlID09ICdkYXRldGltZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRjYWxlbmRhckRpc3BsYXkuYXBwZW5kVG8odGhpcy4kY2FsZW5kYXJCb3gpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLm1vZGUgPT0gJ3RpbWUnIHx8IHRoaXMuY29uZmlnLm1vZGUgPT09ICdkYXRldGltZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRjbG9ja0Rpc3BsYXkuYXBwZW5kVG8odGhpcy4kY2FsZW5kYXJCb3gpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWREYXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVNb250aERpc3BsYXkodGhpcy5zZWxlY3RlZERhdGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlQ2xvY2tEaXNwbGF5KHRoaXMuc2VsZWN0ZWREYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTW9udGhEaXNwbGF5KG1vbWVudCgpKTtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUNsb2NrRGlzcGxheShtb21lbnQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LmdldERheXNGb3JDYWxlbmRhckRpc3BsYXkgPSBmdW5jdGlvbiAoZGF0ZUluTW9udGhEb0JlRGlzcGxheWVkLCBmaXJzdERheU9mV2Vlaykge1xuICAgICAgICAgICAgdmFyIGZpcnN0RGF5T2ZNb250aCA9IGRhdGVJbk1vbnRoRG9CZURpc3BsYXllZC5jbG9uZSgpLnV0YygpLnN0YXJ0T2YoJ21vbnRoJykuaG91cigxMik7XG4gICAgICAgICAgICB2YXIgZmlyc3REYXlUb0JlRGlzcGxheWVkID0gZmlyc3REYXlPZk1vbnRoLmNsb25lKCkuaXNvV2Vla2RheShmaXJzdERheU9mV2VlayA8PSBmaXJzdERheU9mTW9udGguaXNvV2Vla2RheSgpID8gZmlyc3REYXlPZldlZWsgOiBmaXJzdERheU9mV2VlayAtIDcpO1xuICAgICAgICAgICAgdmFyIGRheXNPZk1vbnRoID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBkYXkgPSBmaXJzdERheVRvQmVEaXNwbGF5ZWQuY2xvbmUoKTsgZGF5c09mTW9udGgubGVuZ3RoIDwgNDI7IGRheS5hZGQoMSwgJ2RheScpKSB7XG4gICAgICAgICAgICAgICAgZGF5c09mTW9udGgucHVzaChkYXkuY2xvbmUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZGF5c09mTW9udGg7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUudXBkYXRlTW9udGhEaXNwbGF5ID0gZnVuY3Rpb24gKGRhdGVJbk1vbnRoVG9CZURpc3BsYXllZCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuJHllYXIudGV4dChkYXRlSW5Nb250aFRvQmVEaXNwbGF5ZWQueWVhcigpKTtcbiAgICAgICAgICAgIHRoaXMuJG1vbnRoLnRleHQobW9tZW50Lm1vbnRocygpW2RhdGVJbk1vbnRoVG9CZURpc3BsYXllZC5tb250aCgpXSk7XG4gICAgICAgICAgICB0aGlzLiRtb250aFRhYmxlLnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kbW9udGhUYWJsZSA9ICQoJzxkaXYgY2xhc3M9XCJtb250aC10YWJsZVwiPicpLmFwcGVuZFRvKHRoaXMuJGNhbGVuZGFyRGlzcGxheSk7XG4gICAgICAgICAgICB2YXIgZGF5c1RvQmVEaXNwbGF5ZWQgPSBUcml2aWFsQ2FsZW5kYXJCb3guZ2V0RGF5c0ZvckNhbGVuZGFyRGlzcGxheShkYXRlSW5Nb250aFRvQmVEaXNwbGF5ZWQsIDEpO1xuICAgICAgICAgICAgdmFyICR0ciA9ICQoJzx0cj4nKS5hcHBlbmRUbyh0aGlzLiRtb250aFRhYmxlKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgJHRyLmFwcGVuZCgnPHRoPicgKyBtb21lbnQud2Vla2RheXNNaW4oKVsodGhpcy5jb25maWcuZmlyc3REYXlPZldlZWsgKyBpKSAlIDddICsgJzwvdGg+Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciB3ID0gMDsgdyA8IGRheXNUb0JlRGlzcGxheWVkLmxlbmd0aCAvIDc7IHcrKykge1xuICAgICAgICAgICAgICAgICR0ciA9ICQoJzx0cj4nKS5hcHBlbmRUbyh0aGlzLiRtb250aFRhYmxlKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBkID0gMDsgZCA8IDc7IGQrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGF5ID0gZGF5c1RvQmVEaXNwbGF5ZWRbdyAqIDcgKyBkXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyICR0ZCA9ICQoJzx0ZD4nICsgZGF5LmRhdGUoKSArICc8L3RkPicpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF5Lm1vbnRoKCkgPT0gZGF0ZUluTW9udGhUb0JlRGlzcGxheWVkLm1vbnRoKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0ZC5hZGRDbGFzcygnY3VycmVudC1tb250aCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRkLmFkZENsYXNzKCdvdGhlci1tb250aCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXkueWVhcigpID09IG1vbWVudCgpLnllYXIoKSAmJiBkYXkuZGF5T2ZZZWFyKCkgPT0gbW9tZW50KCkuZGF5T2ZZZWFyKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0ZC5hZGRDbGFzcygndG9kYXknKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF5LnllYXIoKSA9PSB0aGlzLnNlbGVjdGVkRGF0ZS55ZWFyKCkgJiYgZGF5LmRheU9mWWVhcigpID09IHRoaXMuc2VsZWN0ZWREYXRlLmRheU9mWWVhcigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGQuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5rZXlib2FyZE5hdmlnYXRpb25TdGF0ZSA9PT0gJ2RheScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGQuYWRkQ2xhc3ModGhpcy5rZXlib2FyZE5hdkNzc0NsYXNzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAkdGQuY2xpY2soKGZ1bmN0aW9uIChkYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldEtleWJvYXJkTmF2aWdhdGlvblN0YXRlKFwiZGF5XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0TW9udGhBbmREYXkoZGF5Lm1vbnRoKCkgKyAxLCBkYXkuZGF0ZSgpLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuYmluZCh0aGlzLCBkYXkpKTtcbiAgICAgICAgICAgICAgICAgICAgJHRyLmFwcGVuZCgkdGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS51cGRhdGVDbG9ja0Rpc3BsYXkgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICAgICAgdGhpcy4kYW1QbVRleHQudGV4dChkYXRlLmhvdXIoKSA+PSAxMiA/ICdwbScgOiAnYW0nKTtcbiAgICAgICAgICAgIHZhciBtaW51dGVzQW5nbGUgPSBkYXRlLm1pbnV0ZSgpICogNjtcbiAgICAgICAgICAgIHZhciBob3VycyA9IChkYXRlLmhvdXIoKSAlIDEyKSArIGRhdGUubWludXRlKCkgLyA2MDtcbiAgICAgICAgICAgIHZhciBob3VyQW5nbGUgPSBob3VycyAqIDMwO1xuICAgICAgICAgICAgdGhpcy4kaG91ckhhbmQuYXR0cihcInRyYW5zZm9ybVwiLCBcInJvdGF0ZShcIiArIGhvdXJBbmdsZSArIFwiLDUwLDUwKVwiKTtcbiAgICAgICAgICAgIHRoaXMuJG1pbnV0ZUhhbmQuYXR0cihcInRyYW5zZm9ybVwiLCBcInJvdGF0ZShcIiArIG1pbnV0ZXNBbmdsZSArIFwiLDUwLDUwKVwiKTtcbiAgICAgICAgICAgIHRoaXMuJGRpZ2l0YWxUaW1lSG91ckRpc3BsYXkudGV4dChkYXRlLmZvcm1hdCgnSEgnKSk7XG4gICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZU1pbnV0ZURpc3BsYXkudGV4dChkYXRlLmZvcm1hdCgnbW0nKSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUudXBkYXRlRGlzcGxheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTW9udGhEaXNwbGF5KHRoaXMuc2VsZWN0ZWREYXRlKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlQ2xvY2tEaXNwbGF5KHRoaXMuc2VsZWN0ZWREYXRlKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnNldFNlbGVjdGVkRGF0ZSA9IGZ1bmN0aW9uIChtb21lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlID0gbW9tZW50O1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5KCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUuc2V0WWVhciA9IGZ1bmN0aW9uICh5ZWFyLCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLnllYXIoeWVhcik7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uT25FZGl0aW5nVGltZVVuaXRDaGFuZ2UuZmlyZSgneWVhcicpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygneWVhcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnNldE1vbnRoID0gZnVuY3Rpb24gKG1vbnRoLCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLm1vbnRoKG1vbnRoIC0gMSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uT25FZGl0aW5nVGltZVVuaXRDaGFuZ2UuZmlyZSgnbW9udGgnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoJ21vbnRoJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUuc2V0RGF5T2ZNb250aCA9IGZ1bmN0aW9uIChkYXlPZk1vbnRoLCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLmRhdGUoZGF5T2ZNb250aCk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uT25FZGl0aW5nVGltZVVuaXRDaGFuZ2UuZmlyZSgnZGF5Jyk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCdkYXknKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5zZXRNb250aEFuZERheSA9IGZ1bmN0aW9uIChtb250aCwgZGF5LCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLm1vbnRoKG1vbnRoIC0gMSk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS5kYXRlKGRheSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uT25FZGl0aW5nVGltZVVuaXRDaGFuZ2UuZmlyZSgnZGF5Jyk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCdtb250aCcpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygnZGF5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUuc2V0SG91ciA9IGZ1bmN0aW9uIChob3VyLCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLmhvdXIoaG91cik7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uT25FZGl0aW5nVGltZVVuaXRDaGFuZ2UuZmlyZSgnaG91cicpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygnaG91cicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnNldE1pbnV0ZSA9IGZ1bmN0aW9uIChtaW51dGUsIGZpcmVFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGUubWludXRlKG1pbnV0ZSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uT25FZGl0aW5nVGltZVVuaXRDaGFuZ2UuZmlyZSgnbWludXRlJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCdtaW51dGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5maXJlQ2hhbmdlRXZlbnRzID0gZnVuY3Rpb24gKHRpbWVVbml0KSB7XG4gICAgICAgICAgICB0aGlzLiRjYWxlbmRhckJveC50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZS5maXJlKHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5nZXRTZWxlY3RlZERhdGUoKSxcbiAgICAgICAgICAgICAgICB0aW1lVW5pdEVkaXRlZDogdGltZVVuaXRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLnNldEtleWJvYXJkTmF2aWdhdGlvblN0YXRlID0gZnVuY3Rpb24gKG5ld0tleWJvYXJkTmF2aWdhdGlvblN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLmtleWJvYXJkTmF2aWdhdGlvblN0YXRlID0gbmV3S2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGU7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuaGlnaGxpZ2h0S2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgbWVfMSA9IHRoaXM7XG4gICAgICAgICAgICAgICAgJCh0aGlzLiR5ZWFyRGlzcGxheSkuYWRkKHRoaXMuJG1vbnRoRGlzcGxheSkuYWRkKHRoaXMuJG1vbnRoVGFibGUuZmluZCgndGQuJyArIHRoaXMua2V5Ym9hcmROYXZDc3NDbGFzcykpLmFkZCh0aGlzLiRob3VySGFuZCkuYWRkKHRoaXMuJGRpZ2l0YWxUaW1lSG91ckRpc3BsYXlXcmFwcGVyKS5hZGQodGhpcy4kbWludXRlSGFuZCkuYWRkKHRoaXMuJGRpZ2l0YWxUaW1lTWludXRlRGlzcGxheVdyYXBwZXIpXG4gICAgICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5hdHRyKFwiY2xhc3NcIiwgJCh0aGlzKS5hdHRyKFwiY2xhc3NcIikucmVwbGFjZShtZV8xLmtleWJvYXJkTmF2Q3NzQ2xhc3MsICcnKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUgPT0gJ3llYXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJHllYXJEaXNwbGF5LmFkZENsYXNzKHRoaXMua2V5Ym9hcmROYXZDc3NDbGFzcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uU3RhdGUgPT0gJ21vbnRoJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRtb250aERpc3BsYXkuYWRkQ2xhc3ModGhpcy5rZXlib2FyZE5hdkNzc0NsYXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5rZXlib2FyZE5hdmlnYXRpb25TdGF0ZSA9PSAnZGF5Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRtb250aFRhYmxlLmZpbmQoXCIuc2VsZWN0ZWRcIikuYWRkQ2xhc3ModGhpcy5rZXlib2FyZE5hdkNzc0NsYXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5rZXlib2FyZE5hdmlnYXRpb25TdGF0ZSA9PSAnaG91cicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kaG91ckhhbmQuYXR0cihcImNsYXNzXCIsIFwiaG91cmhhbmQgXCIgKyB0aGlzLmtleWJvYXJkTmF2Q3NzQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRkaWdpdGFsVGltZUhvdXJEaXNwbGF5V3JhcHBlci5hZGRDbGFzcyh0aGlzLmtleWJvYXJkTmF2Q3NzQ2xhc3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0aGlzLmtleWJvYXJkTmF2aWdhdGlvblN0YXRlID09ICdtaW51dGUnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJG1pbnV0ZUhhbmQuYXR0cihcImNsYXNzXCIsIFwibWludXRlaGFuZCBcIiArIHRoaXMua2V5Ym9hcmROYXZDc3NDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGRpZ2l0YWxUaW1lTWludXRlRGlzcGxheVdyYXBwZXIuYWRkQ2xhc3ModGhpcy5rZXlib2FyZE5hdkNzc0NsYXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUuZ2V0U2VsZWN0ZWREYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWREYXRlO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxDYWxlbmRhckJveC5wcm90b3R5cGUubmF2aWdhdGVCeVVuaXQgPSBmdW5jdGlvbiAodW5pdCwgZGlyZWN0aW9uLCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQgPT09IHZvaWQgMCkgeyBmaXJlRXZlbnQgPSBmYWxzZTsgfVxuICAgICAgICAgICAgaWYgKHVuaXQgPT0gJ3llYXInKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRpcmVjdGlvbiA9PSAnZG93bicgfHwgZGlyZWN0aW9uID09ICdsZWZ0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFllYXIodGhpcy5zZWxlY3RlZERhdGUueWVhcigpIC0gMSwgZmlyZUV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGlyZWN0aW9uID09ICd1cCcgfHwgZGlyZWN0aW9uID09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRZZWFyKHRoaXMuc2VsZWN0ZWREYXRlLnllYXIoKSArIDEsIGZpcmVFdmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpcmVFdmVudCAmJiB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoJ3llYXInKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHVuaXQgPT0gJ21vbnRoJykge1xuICAgICAgICAgICAgICAgIGlmIChkaXJlY3Rpb24gPT0gJ2Rvd24nIHx8IGRpcmVjdGlvbiA9PSAnbGVmdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRNb250aCh0aGlzLnNlbGVjdGVkRGF0ZS5tb250aCgpLCBmaXJlRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkaXJlY3Rpb24gPT0gJ3VwJyB8fCBkaXJlY3Rpb24gPT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldE1vbnRoKHRoaXMuc2VsZWN0ZWREYXRlLm1vbnRoKCkgKyAyLCBmaXJlRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmaXJlRXZlbnQgJiYgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCdtb250aCcpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodW5pdCA9PSAnZGF5Jykge1xuICAgICAgICAgICAgICAgIGlmIChkaXJlY3Rpb24gPT0gJ2Rvd24nKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLmRheU9mWWVhcih0aGlzLnNlbGVjdGVkRGF0ZS5kYXlPZlllYXIoKSArIDcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkaXJlY3Rpb24gPT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXRlLmRheU9mWWVhcih0aGlzLnNlbGVjdGVkRGF0ZS5kYXlPZlllYXIoKSAtIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkaXJlY3Rpb24gPT0gJ3VwJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZS5kYXlPZlllYXIodGhpcy5zZWxlY3RlZERhdGUuZGF5T2ZZZWFyKCkgLSA3KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGlyZWN0aW9uID09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGUuZGF5T2ZZZWFyKHRoaXMuc2VsZWN0ZWREYXRlLmRheU9mWWVhcigpICsgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRGlzcGxheSgpO1xuICAgICAgICAgICAgICAgIGZpcmVFdmVudCAmJiB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoJ2RheScpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodW5pdCA9PSAnaG91cicpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGlyZWN0aW9uID09ICdkb3duJyB8fCBkaXJlY3Rpb24gPT0gJ2xlZnQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0SG91cih0aGlzLnNlbGVjdGVkRGF0ZS5ob3VyKCkgLSAxLCBmaXJlRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkaXJlY3Rpb24gPT0gJ3VwJyB8fCBkaXJlY3Rpb24gPT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEhvdXIodGhpcy5zZWxlY3RlZERhdGUuaG91cigpICsgMSwgZmlyZUV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZmlyZUV2ZW50ICYmIHRoaXMuZmlyZUNoYW5nZUV2ZW50cygnaG91cicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodW5pdCA9PSAnbWludXRlJykge1xuICAgICAgICAgICAgICAgIGlmIChkaXJlY3Rpb24gPT0gJ2Rvd24nIHx8IGRpcmVjdGlvbiA9PSAnbGVmdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRNaW51dGUodGhpcy5zZWxlY3RlZERhdGUubWludXRlKCkgLSAodGhpcy5zZWxlY3RlZERhdGUubWludXRlKCkgJSA1KSAtIDUsIGZpcmVFdmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGRpcmVjdGlvbiA9PSAndXAnIHx8IGRpcmVjdGlvbiA9PSAncmlnaHQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TWludXRlKHRoaXMuc2VsZWN0ZWREYXRlLm1pbnV0ZSgpIC0gKHRoaXMuc2VsZWN0ZWREYXRlLm1pbnV0ZSgpICUgNSkgKyA1LCBmaXJlRXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmaXJlRXZlbnQgJiYgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCdtaW51dGUnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENhbGVuZGFyQm94LnByb3RvdHlwZS5uYXZpZ2F0ZSA9IGZ1bmN0aW9uIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMubmF2aWdhdGVCeVVuaXQodGhpcy5rZXlib2FyZE5hdmlnYXRpb25TdGF0ZSwgZGlyZWN0aW9uKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLmdldE1haW5Eb21FbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGNhbGVuZGFyQm94WzBdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ2FsZW5kYXJCb3gucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRjYWxlbmRhckJveC5yZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICByZXR1cm4gVHJpdmlhbENhbGVuZGFyQm94O1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsQ2FsZW5kYXJCb3ggPSBUcml2aWFsQ2FsZW5kYXJCb3g7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIm11c3RhY2hlXCIsIFwiLi9Ucml2aWFsQ29yZVwiLCBcIi4vVHJpdmlhbExpc3RCb3hcIiwgXCIuL1RyaXZpYWxFdmVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBNdXN0YWNoZSA9IHJlcXVpcmUoXCJtdXN0YWNoZVwiKTtcbiAgICB2YXIgVHJpdmlhbENvcmVfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxDb3JlXCIpO1xuICAgIHZhciBUcml2aWFsTGlzdEJveF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbExpc3RCb3hcIik7XG4gICAgdmFyIFRyaXZpYWxFdmVudF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpO1xuICAgIHZhciBUcml2aWFsQ29tYm9Cb3ggPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsQ29tYm9Cb3gob3JpZ2luYWxJbnB1dCwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycyA9ICQoKTtcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3RlZEVudHJ5Q2hhbmdlZCA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9uRm9jdXMgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbkJsdXIgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5pc0VkaXRvclZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubGFzdFF1ZXJ5U3RyaW5nID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMubGFzdENvbXBsZXRlSW5wdXRRdWVyeVN0cmluZyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cnkgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVUaW1lb3V0SWQgPSAtMTtcbiAgICAgICAgICAgIHRoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3hEaXJ0eSA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnVzaW5nRGVmYXVsdFF1ZXJ5RnVuY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuY29uZmlnID0gJC5leHRlbmQoe1xuICAgICAgICAgICAgICAgIHZhbHVlRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkgeyByZXR1cm4gZW50cnkgPyBcIlwiICsgZW50cnkuaWQgOiBudWxsOyB9LFxuICAgICAgICAgICAgICAgIGVudHJ5UmVuZGVyaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTXVzdGFjaGUucmVuZGVyKFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuaW1hZ2UyTGluZXNUZW1wbGF0ZSwgZW50cnkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeVJlbmRlcmluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLmNvbmZpZy5lbnRyeVJlbmRlcmluZ0Z1bmN0aW9uKGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnk6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBzcGlubmVyVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdFNwaW5uZXJUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICBub0VudHJpZXNUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0Tm9FbnRyaWVzVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgdGV4dEhpZ2hsaWdodGluZ0VudHJ5TGltaXQ6IDEwMCxcbiAgICAgICAgICAgICAgICBlbnRyaWVzOiBudWxsLFxuICAgICAgICAgICAgICAgIHF1ZXJ5RnVuY3Rpb246IG51bGwsXG4gICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZURlbGF5OiAwLFxuICAgICAgICAgICAgICAgIGVudHJ5VG9FZGl0b3JUZXh0RnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZW50cnlbXCJkaXNwbGF5VmFsdWVcIl07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGVGdW5jdGlvbjogZnVuY3Rpb24gKGVkaXRvclRleHQsIGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlZGl0b3JUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wZXJ0eU5hbWUgaW4gZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnkuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHlWYWx1ZSA9IGVudHJ5W3Byb3BlcnR5TmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0eVZhbHVlICYmIHByb3BlcnR5VmFsdWUudG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoZWRpdG9yVGV4dC50b0xvd2VyQ2FzZSgpKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb3BlcnR5VmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5ID8gX3RoaXMuY29uZmlnLmVudHJ5VG9FZGl0b3JUZXh0RnVuY3Rpb24oZW50cnkpIDogbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYWxsb3dGcmVlVGV4dDogZmFsc2UsXG4gICAgICAgICAgICAgICAgZnJlZVRleHRFbnRyeUZhY3Rvcnk6IGZ1bmN0aW9uIChmcmVlVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheVZhbHVlOiBmcmVlVGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIF9pc0ZyZWVUZXh0RW50cnk6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNob3dDbGVhckJ1dHRvbjogZmFsc2UsXG4gICAgICAgICAgICAgICAgc2hvd1RyaWdnZXI6IHRydWUsXG4gICAgICAgICAgICAgICAgbWF0Y2hpbmdPcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoaW5nTW9kZTogJ2NvbnRhaW5zJyxcbiAgICAgICAgICAgICAgICAgICAgaWdub3JlQ2FzZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWF4TGV2ZW5zaHRlaW5EaXN0YW5jZTogMlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZWRpdGluZ01vZGU6ICdlZGl0YWJsZScsXG4gICAgICAgICAgICAgICAgc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seTogZmFsc2VcbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbiA9IFRyaXZpYWxDb3JlXzEuZGVmYXVsdExpc3RRdWVyeUZ1bmN0aW9uRmFjdG9yeSh0aGlzLmNvbmZpZy5lbnRyaWVzIHx8IFtdLCB0aGlzLmNvbmZpZy5tYXRjaGluZ09wdGlvbnMpO1xuICAgICAgICAgICAgICAgIHRoaXMudXNpbmdEZWZhdWx0UXVlcnlGdW5jdGlvbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVudHJpZXMgPSB0aGlzLmNvbmZpZy5lbnRyaWVzO1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dCA9ICQob3JpZ2luYWxJbnB1dCk7XG4gICAgICAgICAgICB0aGlzLiRjb21ib0JveCA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1jb21ib2JveCB0ci1pbnB1dC13cmFwcGVyXCIvPicpXG4gICAgICAgICAgICAgICAgLmluc2VydEFmdGVyKHRoaXMuJG9yaWdpbmFsSW5wdXQpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItY29tYm9ib3gtc2VsZWN0ZWQtZW50cnktd3JhcHBlclwiLz4nKS5hcHBlbmRUbyh0aGlzLiRjb21ib0JveCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuc2hvd0NsZWFyQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2xlYXJCdXR0b24gPSAkKCc8ZGl2IGNsYXNzPVwidHItcmVtb3ZlLWJ1dHRvblwiPicpLmFwcGVuZFRvKHRoaXMuJGNvbWJvQm94KTtcbiAgICAgICAgICAgICAgICB0aGlzLiRjbGVhckJ1dHRvbi5tb3VzZWRvd24oZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci52YWwoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkobnVsbCwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuc2hvd1RyaWdnZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiR0cmlnZ2VyID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyaWdnZXJcIj48c3BhbiBjbGFzcz1cInRyLXRyaWdnZXItaWNvblwiLz48L2Rpdj4nKS5hcHBlbmRUbyh0aGlzLiRjb21ib0JveCk7XG4gICAgICAgICAgICAgICAgdGhpcy4kdHJpZ2dlci5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kZHJvcERvd24gPSAkKCc8ZGl2IGNsYXNzPVwidHItZHJvcGRvd25cIj48L2Rpdj4nKVxuICAgICAgICAgICAgICAgIC5zY3JvbGwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd25UYXJnZXRFbGVtZW50ID0gJChcImJvZHlcIik7XG4gICAgICAgICAgICB0aGlzLnNldEVkaXRpbmdNb2RlKHRoaXMuY29uZmlnLmVkaXRpbmdNb2RlKTtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQuYWRkQ2xhc3MoXCJ0ci1vcmlnaW5hbC1pbnB1dFwiKTtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvciA9ICQoJzxpbnB1dCB0eXBlPVwidGV4dFwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiLz4nKTtcbiAgICAgICAgICAgIHRoaXMuJGVkaXRvci5wcmVwZW5kVG8odGhpcy4kY29tYm9Cb3gpLmFkZENsYXNzKFwidHItY29tYm9ib3gtZWRpdG9yIHRyLWVkaXRvclwiKVxuICAgICAgICAgICAgICAgIC5mb2N1cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VySGFuZGxlcignZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub25Gb2N1cy5maXJlKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRjb21ib0JveC5hZGRDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmJsdXIoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJG9yaWdpbmFsSW5wdXQudHJpZ2dlckhhbmRsZXIoJ2JsdXInKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub25CbHVyLmZpcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGNvbWJvQm94LnJlbW92ZUNsYXNzKCdmb2N1cycpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZWRpdG9yQ29udGFpbnNGcmVlVGV4dCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIVRyaXZpYWxDb3JlXzEub2JqZWN0RXF1YWxzKF90aGlzLmdldFNlbGVjdGVkRW50cnkoKSwgX3RoaXMubGFzdENvbW1pdHRlZFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudmFsKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUsIGZhbHNlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5oaWRlRWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5rZXlkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuaXNNb2RpZmllcktleShlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy50YWIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnkgPSBfdGhpcy5saXN0Qm94LmdldEhpZ2hsaWdodGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuICYmIGhpZ2hsaWdodGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoaGlnaGxpZ2h0ZWRFbnRyeSwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIV90aGlzLiRlZGl0b3IudmFsKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkobnVsbCwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoX3RoaXMuY29uZmlnLmFsbG93RnJlZVRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5sZWZ0X2Fycm93IHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpc05vbklnbm9yZWRLZXkgPSAhVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5pc01vZGlmaWVyS2V5KGUpICYmIFtUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVudGVyLCBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVzY2FwZSwgVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy50YWJdLmluZGV4T2YoZS53aGljaCkgPT09IC0xO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZWRpdG9yVmFsdWVEb2VzTm90Q29ycmVzcG9uZFRvU2VsZWN0ZWRWYWx1ZSA9IF90aGlzLmlzRW50cnlTZWxlY3RlZCgpICYmIF90aGlzLiRlZGl0b3IudmFsKCkgIT09IF90aGlzLmNvbmZpZy5lbnRyeVRvRWRpdG9yVGV4dEZ1bmN0aW9uKF90aGlzLnNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNOb25JZ25vcmVkS2V5ICYmIChlZGl0b3JWYWx1ZURvZXNOb3RDb3JyZXNwb25kVG9TZWxlY3RlZFZhbHVlIHx8IF90aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKF90aGlzLmxpc3RCb3guZ2V0SGlnaGxpZ2h0ZWRFbnRyeSgpKSkgIT09IF90aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKF90aGlzLmdldFNlbGVjdGVkRW50cnkoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkobnVsbCwgZmFsc2UsIGZhbHNlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuYmFja3NwYWNlIHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5kZWxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy51cF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZG93bl9hcnJvdykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmlzRWRpdG9yVmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgZGlyZWN0aW9uID0gZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnVwX2Fycm93ID8gLTEgOiAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeShkaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMubGlzdEJveC5oaWdobGlnaHROZXh0RW50cnkoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmF1dG9Db21wbGV0ZUlmUG9zc2libGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lbnRlcikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNFZGl0b3JWaXNpYmxlIHx8IF90aGlzLmVkaXRvckNvbnRhaW5zRnJlZVRleHQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnkgPSBfdGhpcy5saXN0Qm94LmdldEhpZ2hsaWdodGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3BlbiAmJiBoaWdobGlnaHRlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShoaWdobGlnaHRlZEVudHJ5LCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFfdGhpcy4kZWRpdG9yLnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShudWxsLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKF90aGlzLmNvbmZpZy5hbGxvd0ZyZWVUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5nZXRTZWxlY3RlZEVudHJ5KCksIHRydWUsIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGlkZUVkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lc2NhcGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShfdGhpcy5lZGl0b3JDb250YWluc0ZyZWVUZXh0KCkgJiYgX3RoaXMuaXNEcm9wRG93bk9wZW4pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5oaWRlRWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnZhbChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmVudHJpZXMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUsIGZhbHNlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmlzRWRpdG9yVmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmNvbmZpZy5zaG93RHJvcERvd25PblJlc3VsdHNPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5saXN0Qm94LnNldEhpZ2hsaWdodGVkRW50cnkobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmF0dHIoXCJ0YWJpbmRleFwiLCB0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJ0YWJpbmRleFwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwiYXV0b2ZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRjb21ib0JveC5hZGQodGhpcy4kZHJvcERvd24pLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLm1vdXNldXAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkubW91c2VvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgY29uZmlnV2l0aG91dEVudHJpZXMgPSAkLmV4dGVuZCh7fSwgdGhpcy5jb25maWcpO1xuICAgICAgICAgICAgY29uZmlnV2l0aG91dEVudHJpZXMuZW50cmllcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94ID0gbmV3IFRyaXZpYWxMaXN0Qm94XzEuVHJpdmlhbExpc3RCb3godGhpcy4kZHJvcERvd24sIGNvbmZpZ1dpdGhvdXRFbnRyaWVzKTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveC5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmFkZExpc3RlbmVyKGZ1bmN0aW9uIChzZWxlY3RlZEVudHJ5LCBldmVudFNvdXJjZSwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoc2VsZWN0ZWRFbnRyeSwgdHJ1ZSwgIVRyaXZpYWxDb3JlXzEub2JqZWN0RXF1YWxzKHNlbGVjdGVkRW50cnksIF90aGlzLmxhc3RDb21taXR0ZWRWYWx1ZSksIG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5saXN0Qm94LnNldFNlbGVjdGVkRW50cnkobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMuaGlkZUVkaXRvcigpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeSwgdHJ1ZSwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24gKGhpZ2hsaWdodERpcmVjdGlvbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBxdWVyeVN0cmluZyA9IHRoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgdmFyIGNvbXBsZXRlSW5wdXRTdHJpbmcgPSB0aGlzLiRlZGl0b3IudmFsKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5sYXN0UXVlcnlTdHJpbmcgIT09IHF1ZXJ5U3RyaW5nIHx8IHRoaXMubGFzdENvbXBsZXRlSW5wdXRRdWVyeVN0cmluZyAhPT0gY29tcGxldGVJbnB1dFN0cmluZykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLiRzcGlubmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRzcGlubmVyID0gJCh0aGlzLmNvbmZpZy5zcGlubmVyVGVtcGxhdGUpLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSB0aGlzLiRzcGlubmVycy5hZGQoJHNwaW5uZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uKHF1ZXJ5U3RyaW5nLCBmdW5jdGlvbiAobmV3RW50cmllcykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy51cGRhdGVFbnRyaWVzKG5ld0VudHJpZXMsIGhpZ2hsaWdodERpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSAmJiBuZXdFbnRyaWVzICYmIG5ld0VudHJpZXMubGVuZ3RoID4gMCAmJiBfdGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdFF1ZXJ5U3RyaW5nID0gcXVlcnlTdHJpbmc7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0Q29tcGxldGVJbnB1dFF1ZXJ5U3RyaW5nID0gY29tcGxldGVJbnB1dFN0cmluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuZmlyZUNoYW5nZUV2ZW50cyA9IGZ1bmN0aW9uIChlbnRyeSwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VyKFwiY2hhbmdlXCIpO1xuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkLmZpcmUoZW50cnksIG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLnNldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoZW50cnksIGNvbW1pdCwgZmlyZUV2ZW50LCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoY29tbWl0ID09PSB2b2lkIDApIHsgY29tbWl0ID0gdHJ1ZTsgfVxuICAgICAgICAgICAgaWYgKGZpcmVFdmVudCA9PT0gdm9pZCAwKSB7IGZpcmVFdmVudCA9IGZhbHNlOyB9XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCh0aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKGVudHJ5KSk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cnkgPSBlbnRyeTtcbiAgICAgICAgICAgIHZhciAkc2VsZWN0ZWRFbnRyeSA9ICQodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeVJlbmRlcmluZ0Z1bmN0aW9uKGVudHJ5KSlcbiAgICAgICAgICAgICAgICAuYWRkQ2xhc3MoXCJ0ci1jb21ib2JveC1lbnRyeVwiKTtcbiAgICAgICAgICAgIHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyLmVtcHR5KCkuYXBwZW5kKCRzZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgICAgIGlmIChlbnRyeSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbCh0aGlzLmNvbmZpZy5lbnRyeVRvRWRpdG9yVGV4dEZ1bmN0aW9uKGVudHJ5KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29tbWl0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUgPSBlbnRyeTtcbiAgICAgICAgICAgICAgICBpZiAoZmlyZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cyhlbnRyeSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJGNsZWFyQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2xlYXJCdXR0b24udG9nZ2xlKGVudHJ5ICE9IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNFZGl0b3JWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuaXNFbnRyeVNlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRFbnRyeSAhPSBudWxsO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLnNob3dFZGl0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgJGVkaXRvckFyZWEgPSB0aGlzLiRzZWxlY3RlZEVudHJ5V3JhcHBlci5maW5kKFwiLnRyLWVkaXRvci1hcmVhXCIpO1xuICAgICAgICAgICAgaWYgKCRlZGl0b3JBcmVhLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICRlZGl0b3JBcmVhID0gdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3JcbiAgICAgICAgICAgICAgICAuY3NzKHtcbiAgICAgICAgICAgICAgICBcIndpZHRoXCI6IE1hdGgubWluKCRlZGl0b3JBcmVhWzBdLm9mZnNldFdpZHRoLCB0aGlzLiR0cmlnZ2VyID8gdGhpcy4kdHJpZ2dlclswXS5vZmZzZXRMZWZ0IC0gJGVkaXRvckFyZWFbMF0ub2Zmc2V0TGVmdCA6IDk5OTk5OTk5KSArIFwicHhcIixcbiAgICAgICAgICAgICAgICBcImhlaWdodFwiOiAoJGVkaXRvckFyZWFbMF0ub2Zmc2V0SGVpZ2h0KSArIFwicHhcIlxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAucG9zaXRpb24oe1xuICAgICAgICAgICAgICAgIG15OiBcImxlZnQgdG9wXCIsXG4gICAgICAgICAgICAgICAgYXQ6IFwibGVmdCB0b3BcIixcbiAgICAgICAgICAgICAgICBvZjogJGVkaXRvckFyZWFcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5pc0VkaXRvclZpc2libGUgPSB0cnVlO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmVkaXRvckNvbnRhaW5zRnJlZVRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCAmJiB0aGlzLiRlZGl0b3IudmFsKCkubGVuZ3RoID4gMCAmJiAhdGhpcy5pc0VudHJ5U2VsZWN0ZWQoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmhpZGVFZGl0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3Iud2lkdGgoMCkuaGVpZ2h0KDApO1xuICAgICAgICAgICAgdGhpcy5pc0VkaXRvclZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5yZXBvc2l0aW9uRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd25cbiAgICAgICAgICAgICAgICAuc2hvdygpXG4gICAgICAgICAgICAgICAgLnBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICBteTogXCJsZWZ0IHRvcFwiLFxuICAgICAgICAgICAgICAgIGF0OiBcImxlZnQgYm90dG9tXCIsXG4gICAgICAgICAgICAgICAgb2Y6IHRoaXMuJGNvbWJvQm94LFxuICAgICAgICAgICAgICAgIGNvbGxpc2lvbjogXCJmbGlwXCIsXG4gICAgICAgICAgICAgICAgdXNpbmc6IGZ1bmN0aW9uIChjYWxjdWxhdGVkUG9zaXRpb24sIGluZm8pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZm8udmVydGljYWwgPT09IFwidG9wXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRjb21ib0JveC5yZW1vdmVDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24ucmVtb3ZlQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGNvbWJvQm94LmFkZENsYXNzKFwiZHJvcGRvd24tZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5hZGRDbGFzcyhcImZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLmNzcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiBjYWxjdWxhdGVkUG9zaXRpb24ubGVmdCArICdweCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IGNhbGN1bGF0ZWRQb3NpdGlvbi50b3AgKyAncHgnXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLndpZHRoKHRoaXMuJGNvbWJvQm94LndpZHRoKCkpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUub3BlbkRyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdm9pZCAwO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk5lZWRlZCgpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubGlzdEJveERpcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTGlzdEJveEVudHJpZXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy4kY29tYm9Cb3guYWRkQ2xhc3MoXCJvcGVuXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuY2xvc2VEcm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJGNvbWJvQm94LnJlbW92ZUNsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmhpZGUoKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGVkaXRvci52YWwoKS5zdWJzdHJpbmcoMCwgdGhpcy4kZWRpdG9yWzBdLnNlbGVjdGlvblN0YXJ0KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5hdXRvQ29tcGxldGVJZlBvc3NpYmxlID0gZnVuY3Rpb24gKGRlbGF5KSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmF1dG9Db21wbGV0ZSkge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmF1dG9Db21wbGV0ZVRpbWVvdXRJZCk7XG4gICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnlfMSA9IHRoaXMubGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgaWYgKGhpZ2hsaWdodGVkRW50cnlfMSAmJiAhdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVUaW1lb3V0SWQgPSBUcml2aWFsQ29yZV8xLnNldFRpbWVvdXRPckRvSW1tZWRpYXRlbHkoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRFZGl0b3JWYWx1ZSA9IF90aGlzLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdXRvQ29tcGxldGVTdHJpbmcgPSBfdGhpcy5jb25maWcuYXV0b0NvbXBsZXRlRnVuY3Rpb24oY3VycmVudEVkaXRvclZhbHVlLCBoaWdobGlnaHRlZEVudHJ5XzEpIHx8IGN1cnJlbnRFZGl0b3JWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudmFsKGN1cnJlbnRFZGl0b3JWYWx1ZSArIGF1dG9Db21wbGV0ZVN0cmluZy5zdWJzdHIoY3VycmVudEVkaXRvclZhbHVlLmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yWzBdLnNldFNlbGVjdGlvblJhbmdlKGN1cnJlbnRFZGl0b3JWYWx1ZS5sZW5ndGgsIGF1dG9Db21wbGV0ZVN0cmluZy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9LCBkZWxheSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUudXBkYXRlTGlzdEJveEVudHJpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3gudXBkYXRlRW50cmllcyh0aGlzLmVudHJpZXMpO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94RGlydHkgPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS51cGRhdGVFbnRyaWVzID0gZnVuY3Rpb24gKG5ld0VudHJpZXMsIGhpZ2hsaWdodERpcmVjdGlvbikge1xuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gbmV3RW50cmllcztcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzLnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSAkKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTGlzdEJveEVudHJpZXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdEJveERpcnR5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBub25TZWxlY3RlZEVkaXRvclZhbHVlID0gdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3guaGlnaGxpZ2h0VGV4dE1hdGNoZXMobmV3RW50cmllcy5sZW5ndGggPD0gdGhpcy5jb25maWcudGV4dEhpZ2hsaWdodGluZ0VudHJ5TGltaXQgPyBub25TZWxlY3RlZEVkaXRvclZhbHVlIDogbnVsbCk7XG4gICAgICAgICAgICBpZiAoaGlnaGxpZ2h0RGlyZWN0aW9uID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGlzdEJveC5zZXRIaWdobGlnaHRlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5saXN0Qm94LmhpZ2hsaWdodE5leHRFbnRyeSgxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChoaWdobGlnaHREaXJlY3Rpb24gPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3RCb3guc2V0SGlnaGxpZ2h0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdEJveC5oaWdobGlnaHROZXh0RW50cnkoaGlnaGxpZ2h0RGlyZWN0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYXV0b0NvbXBsZXRlSWZQb3NzaWJsZSh0aGlzLmNvbmZpZy5hdXRvQ29tcGxldGVEZWxheSk7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuaXNEcm9wRG93bk5lZWRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVkaXRpbmdNb2RlID09ICdlZGl0YWJsZScgJiYgKHRoaXMuY29uZmlnLmVudHJpZXMgJiYgdGhpcy5jb25maWcuZW50cmllcy5sZW5ndGggPiAwIHx8ICF0aGlzLnVzaW5nRGVmYXVsdFF1ZXJ5RnVuY3Rpb24gfHwgdGhpcy5jb25maWcuc2hvd1RyaWdnZXIpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLnNldEVkaXRpbmdNb2RlID0gZnVuY3Rpb24gKG5ld0VkaXRpbmdNb2RlKSB7XG4gICAgICAgICAgICB0aGlzLmVkaXRpbmdNb2RlID0gbmV3RWRpdGluZ01vZGU7XG4gICAgICAgICAgICB0aGlzLiRjb21ib0JveC5yZW1vdmVDbGFzcyhcImVkaXRhYmxlIHJlYWRvbmx5IGRpc2FibGVkXCIpLmFkZENsYXNzKHRoaXMuZWRpdGluZ01vZGUpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk5lZWRlZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZHJvcERvd24uYXBwZW5kVG8odGhpcy4kZHJvcERvd25UYXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5nZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRFbnRyeSA9PSBudWxsICYmICghdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCB8fCAhdGhpcy4kZWRpdG9yLnZhbCgpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5zZWxlY3RlZEVudHJ5ID09IG51bGwgJiYgdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5mcmVlVGV4dEVudHJ5RmFjdG9yeSh0aGlzLiRlZGl0b3IudmFsKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkRW50cnlUb1JldHVybiA9ICQuZXh0ZW5kKHt9LCB0aGlzLnNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlUb1JldHVybi5fdHJFbnRyeUVsZW1lbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGVjdGVkRW50cnlUb1JldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5nZXRFZGl0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kZWRpdG9yWzBdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsQ29tYm9Cb3gucHJvdG90eXBlLmdldERyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGRyb3BEb3duO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxDb21ib0JveC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQucmVtb3ZlQ2xhc3MoJ3RyLW9yaWdpbmFsLWlucHV0JykuaW5zZXJ0QmVmb3JlKHRoaXMuJGNvbWJvQm94KTtcbiAgICAgICAgICAgIHRoaXMuJGNvbWJvQm94LnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd24ucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbENvbWJvQm94LnByb3RvdHlwZS5nZXRNYWluRG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRjb21ib0JveFswXTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFRyaXZpYWxDb21ib0JveDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbENvbWJvQm94ID0gVHJpdmlhbENvbWJvQm94O1xufSk7XG5cblxudmFyIF9fYXNzaWduID0gKHRoaXMgJiYgdGhpcy5fX2Fzc2lnbikgfHwgT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIHMgPSBhcmd1bWVudHNbaV07XG4gICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgIHRbcF0gPSBzW3BdO1xuICAgIH1cbiAgICByZXR1cm4gdDtcbn07XG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcIm1vbWVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyIG1vbWVudCA9IHJlcXVpcmUoXCJtb21lbnRcIik7XG4gICAgdmFyIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZShvcHRpb25zKSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSBfX2Fzc2lnbih7IHByZWZlcnJlZERhdGVGb3JtYXQ6IFwiWVlZWS1NTS1ERFwiIH0sIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5wcm90b3R5cGUuZ2VuZXJhdGVTdWdnZXN0aW9ucyA9IGZ1bmN0aW9uIChzZWFyY2hTdHJpbmcsIG5vdykge1xuICAgICAgICAgICAgbm93ID0gbW9tZW50KG5vdyk7XG4gICAgICAgICAgICB2YXIgc3VnZ2VzdGlvbnM7XG4gICAgICAgICAgICBpZiAoc2VhcmNoU3RyaW5nLm1hdGNoKC9bXlxcZF0vKSkge1xuICAgICAgICAgICAgICAgIHZhciBmcmFnbWVudHMgPSBzZWFyY2hTdHJpbmcuc3BsaXQoL1teXFxkXS8pLmZpbHRlcihmdW5jdGlvbiAoZikgeyByZXR1cm4gISFmOyB9KTtcbiAgICAgICAgICAgICAgICBzdWdnZXN0aW9ucyA9IHRoaXMuY3JlYXRlU3VnZ2VzdGlvbnNGb3JGcmFnbWVudHMoZnJhZ21lbnRzLCBub3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSB0aGlzLmdlbmVyYXRlU3VnZ2VzdGlvbnNGb3JEaWdpdHNPbmx5SW5wdXQoc2VhcmNoU3RyaW5nLCBub3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHByZWZlcnJlZFltZE9yZGVyID0gVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLmRhdGVGb3JtYXRUb1ltZE9yZGVyKHRoaXMub3B0aW9ucy5wcmVmZXJyZWREYXRlRm9ybWF0KTtcbiAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJlZmVycmVkWW1kT3JkZXIuaW5kZXhPZihhLnltZE9yZGVyKSA9PT0gLTEgJiYgcHJlZmVycmVkWW1kT3JkZXIuaW5kZXhPZihiLnltZE9yZGVyKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHByZWZlcnJlZFltZE9yZGVyLmluZGV4T2YoYS55bWRPcmRlcikgIT09IC0xICYmIHByZWZlcnJlZFltZE9yZGVyLmluZGV4T2YoYi55bWRPcmRlcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoYS55bWRPcmRlci5sZW5ndGggIT0gYi55bWRPcmRlci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEueW1kT3JkZXIubGVuZ3RoIC0gYi55bWRPcmRlci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5tb21lbnQuZGlmZihub3csICdkYXlzJykgLSBiLm1vbWVudC5kaWZmKG5vdywgJ2RheXMnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHN1Z2dlc3Rpb25zID0gdGhpcy5yZW1vdmVEdXBsaWNhdGVzKHN1Z2dlc3Rpb25zKTtcbiAgICAgICAgICAgIHJldHVybiBzdWdnZXN0aW9ucztcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLnByb3RvdHlwZS5yZW1vdmVEdXBsaWNhdGVzID0gZnVuY3Rpb24gKHN1Z2dlc3Rpb25zKSB7XG4gICAgICAgICAgICB2YXIgc2VlbkRhdGVzID0gW107XG4gICAgICAgICAgICByZXR1cm4gc3VnZ2VzdGlvbnMuZmlsdGVyKGZ1bmN0aW9uIChzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRhdGVBbHJlYWR5Q29udGFpbmVkID0gc2VlbkRhdGVzLmZpbHRlcihmdW5jdGlvbiAoc2VlbkRhdGUpIHsgcmV0dXJuIHMubW9tZW50LmlzU2FtZShzZWVuRGF0ZSwgJ2RheScpOyB9KS5sZW5ndGggPiAwO1xuICAgICAgICAgICAgICAgIGlmIChkYXRlQWxyZWFkeUNvbnRhaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzZWVuRGF0ZXMucHVzaChzLm1vbWVudCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuZGF0ZUZvcm1hdFRvWW1kT3JkZXIgPSBmdW5jdGlvbiAoZGF0ZUZvcm1hdCkge1xuICAgICAgICAgICAgdmFyIHltZEluZGV4ZXMgPSB7XG4gICAgICAgICAgICAgICAgRDogZGF0ZUZvcm1hdC5pbmRleE9mKFwiRFwiKSxcbiAgICAgICAgICAgICAgICBNOiBkYXRlRm9ybWF0LmluZGV4T2YoXCJNXCIpLFxuICAgICAgICAgICAgICAgIFk6IGRhdGVGb3JtYXQuaW5kZXhPZihcIllcIilcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gKFtcIkRcIiwgXCJNXCIsIFwiWVwiXS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiB5bWRJbmRleGVzW2FdIC0geW1kSW5kZXhlc1tiXTsgfSkuam9pbihcIlwiKSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVTdWdnZXN0aW9uID0gZnVuY3Rpb24gKG1vbWVudCwgeW1kT3JkZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IG1vbWVudDogbW9tZW50LCB5bWRPcmRlcjogeW1kT3JkZXIgfTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLnByb3RvdHlwZS5nZW5lcmF0ZVN1Z2dlc3Rpb25zRm9yRGlnaXRzT25seUlucHV0ID0gZnVuY3Rpb24gKGlucHV0LCB0b2RheSkge1xuICAgICAgICAgICAgaW5wdXQgPSBpbnB1dCB8fCBcIlwiO1xuICAgICAgICAgICAgaWYgKGlucHV0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVN1Z2dlc3Rpb25zRm9yRnJhZ21lbnRzKFtdLCB0b2RheSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpbnB1dC5sZW5ndGggPiA4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHN1Z2dlc3Rpb25zID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8PSBpbnB1dC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSBNYXRoLm1pbihpbnB1dC5sZW5ndGgsIGkgKyAxKTsgaiA8PSBpbnB1dC5sZW5ndGggJiYgaiAtIGkgPD0gNDsgaiAtIGkgPT09IDIgPyBqICs9IDIgOiBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSBzdWdnZXN0aW9ucy5jb25jYXQodGhpcy5jcmVhdGVTdWdnZXN0aW9uc0ZvckZyYWdtZW50cyhbaW5wdXQuc3Vic3RyaW5nKDAsIGkpLCBpbnB1dC5zdWJzdHJpbmcoaSwgaiksIGlucHV0LnN1YnN0cmluZyhqLCBpbnB1dC5sZW5ndGgpXSwgdG9kYXkpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3VnZ2VzdGlvbnM7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5wcm90b3R5cGUudG9kYXlPckZhdm9yaXRlRGlyZWN0aW9uID0gZnVuY3Rpb24gKG0sIHRvZGF5KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmZhdm9yUGFzdERhdGVzID8gdG9kYXkuaXNTYW1lT3JBZnRlcihtLCAnZGF5JykgOiB0b2RheS5pc1NhbWVPckJlZm9yZShtLCAnZGF5Jyk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5wcm90b3R5cGUuY3JlYXRlU3VnZ2VzdGlvbnNGb3JGcmFnbWVudHMgPSBmdW5jdGlvbiAoZnJhZ21lbnRzLCB0b2RheSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIGZ1bmN0aW9uIG1vZChuLCBtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICgobiAlIG0pICsgbSkgJSBtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gbnVtYmVyVG9ZZWFyKG4pIHtcbiAgICAgICAgICAgICAgICB2YXIgc2hvcnRZZWFyID0gdG9kYXkueWVhcigpICUgMTAwO1xuICAgICAgICAgICAgICAgIHZhciB5ZWFyU3VnZ2VzdGlvbkJvdW5kYXJ5ID0gKHNob3J0WWVhciArIDIwKSAlIDEwMDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudENlbnR1cnkgPSBNYXRoLmZsb29yKHRvZGF5LnllYXIoKSAvIDEwMCkgKiAxMDA7XG4gICAgICAgICAgICAgICAgaWYgKG4gPCB5ZWFyU3VnZ2VzdGlvbkJvdW5kYXJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50Q2VudHVyeSArIG47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG4gPCAxMDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRDZW50dXJ5IC0gMTAwICsgbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAobiA+IHRvZGF5LnllYXIoKSAtIDEwMCAmJiBuIDwgdG9kYXkueWVhcigpICsgMTAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHMxID0gZnJhZ21lbnRzWzBdLCBzMiA9IGZyYWdtZW50c1sxXSwgczMgPSBmcmFnbWVudHNbMl07XG4gICAgICAgICAgICB2YXIgX2EgPSBbcGFyc2VJbnQoczEpLCBwYXJzZUludChzMiksIHBhcnNlSW50KHMzKV0sIG4xID0gX2FbMF0sIG4yID0gX2FbMV0sIG4zID0gX2FbMl07XG4gICAgICAgICAgICB2YXIgc3VnZ2VzdGlvbnMgPSBbXTtcbiAgICAgICAgICAgIGlmICghczEgJiYgIXMyICYmICFzMykge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDc7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihtb21lbnQodG9kYXkpLmFkZCgodGhpcy5vcHRpb25zLmZhdm9yUGFzdERhdGVzID8gLTEgOiAxKSAqIGksIFwiZGF5XCIpLCBcIlwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChzMSAmJiAhczIgJiYgIXMzKSB7XG4gICAgICAgICAgICAgICAgaWYgKG4xID4gMCAmJiBuMSA8PSAzMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dFZhbGlkRGF0ZSA9IHRoaXMuZmluZE5leHRWYWxpZERhdGUoeyB5ZWFyOiB0b2RheS55ZWFyKCksIG1vbnRoOiB0b2RheS5tb250aCgpLCBkYXk6IG4xIH0sIGZ1bmN0aW9uIChjdXJyZW50RGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ZWFyOiBjdXJyZW50RGF0ZS55ZWFyICsgKF90aGlzLm9wdGlvbnMuZmF2b3JQYXN0RGF0ZXMgPyAoY3VycmVudERhdGUubW9udGggPT0gMCA/IC0xIDogMCkgOiAoY3VycmVudERhdGUubW9udGggPT0gMTEgPyAxIDogMCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vbnRoOiBtb2QoY3VycmVudERhdGUubW9udGggKyAoX3RoaXMub3B0aW9ucy5mYXZvclBhc3REYXRlcyA/IC0xIDogMSksIDEyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXk6IGN1cnJlbnREYXRlLmRheVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfSwgdG9kYXkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV4dFZhbGlkRGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihuZXh0VmFsaWREYXRlLCBcIkRcIikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoczEgJiYgczIgJiYgIXMzKSB7XG4gICAgICAgICAgICAgICAgaWYgKG4xIDw9IDEyICYmIG4yID4gMCAmJiBuMiA8PSAzMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dFZhbGlkRGF0ZSA9IHRoaXMuZmluZE5leHRWYWxpZERhdGUoeyB5ZWFyOiB0b2RheS55ZWFyKCksIG1vbnRoOiBuMSAtIDEsIGRheTogbjIgfSwgZnVuY3Rpb24gKGN1cnJlbnREYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllYXI6IGN1cnJlbnREYXRlLnllYXIgKyAoX3RoaXMub3B0aW9ucy5mYXZvclBhc3REYXRlcyA/IC0xIDogMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9udGg6IGN1cnJlbnREYXRlLm1vbnRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheTogY3VycmVudERhdGUuZGF5XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9LCB0b2RheSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXh0VmFsaWREYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWdnZXN0aW9ucy5wdXNoKFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVTdWdnZXN0aW9uKG5leHRWYWxpZERhdGUsIFwiTURcIikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChuMiA8PSAxMiAmJiBuMSA+IDAgJiYgbjEgPD0gMzEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRWYWxpZERhdGUgPSB0aGlzLmZpbmROZXh0VmFsaWREYXRlKHsgeWVhcjogdG9kYXkueWVhcigpLCBtb250aDogbjIgLSAxLCBkYXk6IG4xIH0sIGZ1bmN0aW9uIChjdXJyZW50RGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ZWFyOiBjdXJyZW50RGF0ZS55ZWFyICsgKF90aGlzLm9wdGlvbnMuZmF2b3JQYXN0RGF0ZXMgPyAtMSA6IDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vbnRoOiBjdXJyZW50RGF0ZS5tb250aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXk6IGN1cnJlbnREYXRlLmRheVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfSwgdG9kYXkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV4dFZhbGlkRGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihuZXh0VmFsaWREYXRlLCBcIkRNXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBtb20gPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgbW9tID0gbW9tZW50KFtudW1iZXJUb1llYXIobjEpLCBuMiAtIDEsIHMzXSk7XG4gICAgICAgICAgICAgICAgaWYgKG1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihtb20sIFwiWU1EXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbW9tID0gbW9tZW50KFtudW1iZXJUb1llYXIobjEpLCBuMyAtIDEsIHMyXSk7XG4gICAgICAgICAgICAgICAgaWYgKG1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihtb20sIFwiWURNXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbW9tID0gbW9tZW50KFtudW1iZXJUb1llYXIobjIpLCBuMSAtIDEsIHMzXSk7XG4gICAgICAgICAgICAgICAgaWYgKG1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihtb20sIFwiTVlEXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbW9tID0gbW9tZW50KFtudW1iZXJUb1llYXIobjIpLCBuMyAtIDEsIHMxXSk7XG4gICAgICAgICAgICAgICAgaWYgKG1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihtb20sIFwiRFlNXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbW9tID0gbW9tZW50KFtudW1iZXJUb1llYXIobjMpLCBuMSAtIDEsIHMyXSk7XG4gICAgICAgICAgICAgICAgaWYgKG1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihtb20sIFwiTURZXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbW9tID0gbW9tZW50KFtudW1iZXJUb1llYXIobjMpLCBuMiAtIDEsIHMxXSk7XG4gICAgICAgICAgICAgICAgaWYgKG1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlU3VnZ2VzdGlvbihtb20sIFwiRE1ZXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3VnZ2VzdGlvbnM7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbERhdGVTdWdnZXN0aW9uRW5naW5lLnByb3RvdHlwZS5maW5kTmV4dFZhbGlkRGF0ZSA9IGZ1bmN0aW9uIChzdGFydERhdGUsIGluY2VtZW50b3IsIHRvZGF5KSB7XG4gICAgICAgICAgICB2YXIgY3VycmVudERhdGUgPSBzdGFydERhdGU7XG4gICAgICAgICAgICB2YXIgbW9tZW50SW5OZXh0TW9udGggPSBtb21lbnQoc3RhcnREYXRlKTtcbiAgICAgICAgICAgIHZhciBudW1iZXJPZkl0ZXJhdGlvbnMgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKCEobW9tZW50SW5OZXh0TW9udGguaXNWYWxpZCgpICYmIHRoaXMudG9kYXlPckZhdm9yaXRlRGlyZWN0aW9uKG1vbWVudEluTmV4dE1vbnRoLCB0b2RheSkpICYmIG51bWJlck9mSXRlcmF0aW9ucyA8IDQpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50RGF0ZSA9IGluY2VtZW50b3IoY3VycmVudERhdGUpO1xuICAgICAgICAgICAgICAgIG1vbWVudEluTmV4dE1vbnRoID0gbW9tZW50KGN1cnJlbnREYXRlKTtcbiAgICAgICAgICAgICAgICBudW1iZXJPZkl0ZXJhdGlvbnMrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtb21lbnRJbk5leHRNb250aC5pc1ZhbGlkKCkgPyBtb21lbnRJbk5leHRNb250aCA6IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmU7XG4gICAgfSgpKTtcbiAgICBleHBvcnRzLlRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZSA9IFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZTtcbn0pO1xuXG5cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwianF1ZXJ5XCIsIFwibW9tZW50XCIsIFwibXVzdGFjaGVcIiwgXCIuL1RyaXZpYWxDb3JlXCIsIFwiLi9Ucml2aWFsRXZlbnRcIiwgXCIuL1RyaXZpYWxMaXN0Qm94XCIsIFwiLi9Ucml2aWFsQ2FsZW5kYXJCb3hcIiwgXCIuL1RyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZVwiLCBcIi4vVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lXCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIG1vbWVudCA9IHJlcXVpcmUoXCJtb21lbnRcIik7XG4gICAgdmFyIE11c3RhY2hlID0gcmVxdWlyZShcIm11c3RhY2hlXCIpO1xuICAgIHZhciBUcml2aWFsQ29yZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENvcmVcIik7XG4gICAgdmFyIFRyaXZpYWxFdmVudF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpO1xuICAgIHZhciBUcml2aWFsTGlzdEJveF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbExpc3RCb3hcIik7XG4gICAgdmFyIFRyaXZpYWxDYWxlbmRhckJveF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENhbGVuZGFyQm94XCIpO1xuICAgIHZhciBUcml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmVfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZVwiKTtcbiAgICB2YXIgVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lXzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmVcIik7XG4gICAgdmFyIE1vZGU7XG4gICAgKGZ1bmN0aW9uIChNb2RlKSB7XG4gICAgICAgIE1vZGVbTW9kZVtcIk1PREVfQ0FMRU5EQVJcIl0gPSAwXSA9IFwiTU9ERV9DQUxFTkRBUlwiO1xuICAgICAgICBNb2RlW01vZGVbXCJNT0RFX0RBVEVfTElTVFwiXSA9IDFdID0gXCJNT0RFX0RBVEVfTElTVFwiO1xuICAgICAgICBNb2RlW01vZGVbXCJNT0RFX1RJTUVfTElTVFwiXSA9IDJdID0gXCJNT0RFX1RJTUVfTElTVFwiO1xuICAgIH0pKE1vZGUgfHwgKE1vZGUgPSB7fSkpO1xuICAgIHZhciBUcml2aWFsRGF0ZVRpbWVGaWVsZCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFRyaXZpYWxEYXRlVGltZUZpZWxkKG9yaWdpbmFsSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5kYXRlSWNvblRlbXBsYXRlID0gXCI8c3ZnIHZpZXdCb3g9XFxcIjAgMCA1NDAgNTQwXFxcIiB3aWR0aD1cXFwiMjJcXFwiIGhlaWdodD1cXFwiMjJcXFwiIGNsYXNzPVxcXCJjYWxlbmRhci1pY29uXFxcIj5cXG4gICAgPGRlZnM+XFxuICAgICAgICA8bGluZWFyR3JhZGllbnQgaWQ9XFxcIkdyYWRpZW50MVxcXCIgeDE9XFxcIjBcXFwiIHgyPVxcXCIwXFxcIiB5MT1cXFwiMFxcXCIgeTI9XFxcIjFcXFwiPlxcbiAgICAgICAgICAgIDxzdG9wIGNsYXNzPVxcXCJjYWxlbmRhci1zeW1ib2wtcmluZy1ncmFkaWVudC1zdG9wMVxcXCIgb2Zmc2V0PVxcXCIwJVxcXCIvPlxcbiAgICAgICAgICAgIDxzdG9wIGNsYXNzPVxcXCJjYWxlbmRhci1zeW1ib2wtcmluZy1ncmFkaWVudC1zdG9wMlxcXCIgb2Zmc2V0PVxcXCI1MCVcXFwiLz5cXG4gICAgICAgICAgICA8c3RvcCBjbGFzcz1cXFwiY2FsZW5kYXItc3ltYm9sLXJpbmctZ3JhZGllbnQtc3RvcDNcXFwiIG9mZnNldD1cXFwiMTAwJVxcXCIvPlxcbiAgICAgICAgPC9saW5lYXJHcmFkaWVudD5cXG4gICAgPC9kZWZzPiAgICAgICAgXFxuICAgIDxnIGlkPVxcXCJsYXllcjFcXFwiPlxcbiAgICAgICAgPHJlY3QgY2xhc3M9XFxcImNhbGVuZGFyLXN5bWJvbC1wYWdlLWJhY2tncm91bmRcXFwiIHg9XFxcIjkwXFxcIiB5PVxcXCI5MFxcXCIgd2lkdGg9XFxcIjM2MFxcXCIgaGVpZ2h0PVxcXCI0MDBcXFwiIHJ5PVxcXCIzLjhcXFwiPjwvcmVjdD5cXG4gICAgICAgIDxyZWN0IGNsYXNzPVxcXCJjYWxlbmRhci1zeW1ib2wtY29sb3JcXFwiIHg9XFxcIjkwXFxcIiB5PVxcXCI5MFxcXCIgd2lkdGg9XFxcIjM2MFxcXCIgaGVpZ2h0PVxcXCIxMDBcXFwiIHJ5PVxcXCIzLjVcXFwiPjwvcmVjdD5cXG4gICAgICAgIDxyZWN0IGNsYXNzPVxcXCJjYWxlbmRhci1zeW1ib2wtcGFnZVxcXCIgeD1cXFwiOTBcXFwiIHk9XFxcIjkwXFxcIiB3aWR0aD1cXFwiMzYwXFxcIiBoZWlnaHQ9XFxcIjM5NVxcXCIgcnk9XFxcIjMuOFxcXCI+PC9yZWN0PlxcbiAgICAgICAgPHJlY3QgY2xhc3M9XFxcImNhbGVuZGFyLXN5bWJvbC1yaW5nXFxcIiBmaWxsPVxcXCJ1cmwoI0dyYWRpZW50MilcXFwiIHg9XFxcIjE0MFxcXCIgeT1cXFwiMzBcXFwiIHdpZHRoPVxcXCI0MFxcXCIgaGVpZ2h0PVxcXCIxMjBcXFwiIHJ5PVxcXCIzMC44XFxcIj48L3JlY3Q+XFxuICAgICAgICA8cmVjdCBjbGFzcz1cXFwiY2FsZW5kYXItc3ltYm9sLXJpbmdcXFwiIGZpbGw9XFxcInVybCgjR3JhZGllbnQyKVxcXCIgeD1cXFwiMjUwXFxcIiB5PVxcXCIzMFxcXCIgd2lkdGg9XFxcIjQwXFxcIiBoZWlnaHQ9XFxcIjEyMFxcXCIgcnk9XFxcIjMwLjhcXFwiPjwvcmVjdD5cXG4gICAgICAgIDxyZWN0IGNsYXNzPVxcXCJjYWxlbmRhci1zeW1ib2wtcmluZ1xcXCIgZmlsbD1cXFwidXJsKCNHcmFkaWVudDIpXFxcIiB4PVxcXCIzNjBcXFwiIHk9XFxcIjMwXFxcIiB3aWR0aD1cXFwiNDBcXFwiIGhlaWdodD1cXFwiMTIwXFxcIiByeT1cXFwiMzAuOFxcXCI+PC9yZWN0PlxcbiAgICAgICAgPHRleHQgY2xhc3M9XFxcImNhbGVuZGFyLXN5bWJvbC1kYXRlXFxcIiB4PVxcXCIyNzBcXFwiIHk9XFxcIjQxNVxcXCIgdGV4dC1hbmNob3I9XFxcIm1pZGRsZVxcXCI+e3t3ZWVrRGF5fX08L3RleHQ+XFxuICAgIDwvZz5cXG48L3N2Zz5cIjtcbiAgICAgICAgICAgIHRoaXMuZGF0ZVRlbXBsYXRlID0gJzxkaXYgY2xhc3M9XCJ0ci10ZW1wbGF0ZS1pY29uLXNpbmdsZS1saW5lXCI+J1xuICAgICAgICAgICAgICAgICsgdGhpcy5kYXRlSWNvblRlbXBsYXRlXG4gICAgICAgICAgICAgICAgKyAnPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPnt7ZGlzcGxheVN0cmluZ319PC9kaXY+J1xuICAgICAgICAgICAgICAgICsgJzwvZGl2Pic7XG4gICAgICAgICAgICB0aGlzLnRpbWVJY29uVGVtcGxhdGUgPSAnPHN2ZyBjbGFzcz1cImNsb2NrLWljb24gbmlnaHQte3tpc05pZ2h0fX1cIiB2aWV3Qm94PVwiMCAwIDExMCAxMTBcIiB3aWR0aD1cIjIyXCIgaGVpZ2h0PVwiMjJcIj4gJyArXG4gICAgICAgICAgICAgICAgJzxjaXJjbGUgY2xhc3M9XCJjbG9ja2NpcmNsZVwiIGN4PVwiNTVcIiBjeT1cIjU1XCIgcj1cIjQ1XCIvPicgK1xuICAgICAgICAgICAgICAgICc8ZyBjbGFzcz1cImhhbmRzXCI+JyArXG4gICAgICAgICAgICAgICAgJyA8bGluZSBjbGFzcz1cImhvdXJoYW5kXCIgeDE9XCI1NVwiIHkxPVwiNTVcIiB4Mj1cIjU1XCIgeTI9XCIzNVwiIHt7I2hvdXJBbmdsZX19dHJhbnNmb3JtPVwicm90YXRlKHt7aG91ckFuZ2xlfX0sNTUsNTUpXCJ7ey9ob3VyQW5nbGV9fS8+ICcgK1xuICAgICAgICAgICAgICAgICcgPGxpbmUgY2xhc3M9XCJtaW51dGVoYW5kXCIgeDE9XCI1NVwiIHkxPVwiNTVcIiB4Mj1cIjU1XCIgeTI9XCIyMlwiIHt7I21pbnV0ZUFuZ2xlfX10cmFuc2Zvcm09XCJyb3RhdGUoe3ttaW51dGVBbmdsZX19LDU1LDU1KVwie3svbWludXRlQW5nbGV9fS8+JyArXG4gICAgICAgICAgICAgICAgJzwvZz4gJyArXG4gICAgICAgICAgICAgICAgJzwvc3ZnPic7XG4gICAgICAgICAgICB0aGlzLnRpbWVUZW1wbGF0ZSA9ICc8ZGl2IGNsYXNzPVwidHItdGVtcGxhdGUtaWNvbi1zaW5nbGUtbGluZVwiPicgK1xuICAgICAgICAgICAgICAgIHRoaXMudGltZUljb25UZW1wbGF0ZSArXG4gICAgICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cImNvbnRlbnQtd3JhcHBlciB0ci1lZGl0b3ItYXJlYVwiPnt7ZGlzcGxheVN0cmluZ319PC9kaXY+JyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Pic7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZVZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudGltZVZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNHb2VzVG9PdGhlckVkaXRvciA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVUaW1lb3V0SWQgPSAtMTtcbiAgICAgICAgICAgIHRoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmNhbGVuZGFyQm94SW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZHJvcERvd25Nb2RlID0gTW9kZS5NT0RFX0NBTEVOREFSO1xuICAgICAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICB0aGlzLmNvbmZpZyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgICAgICBkYXRlRm9ybWF0OiBcIk1NL0REL1lZWVlcIixcbiAgICAgICAgICAgICAgICB0aW1lRm9ybWF0OiBcIkhIOm1tXCIsXG4gICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZURlbGF5OiAwLFxuICAgICAgICAgICAgICAgIHNob3dUcmlnZ2VyOiB0cnVlLFxuICAgICAgICAgICAgICAgIGVkaXRpbmdNb2RlOiBcImVkaXRhYmxlXCJcbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dCA9ICQob3JpZ2luYWxJbnB1dCkuYWRkQ2xhc3MoXCJ0ci1vcmlnaW5hbC1pbnB1dFwiKTtcbiAgICAgICAgICAgIHRoaXMuJGRhdGVUaW1lRmllbGQgPSAkKCc8ZGl2IGNsYXNzPVwidHItZGF0ZXRpbWVmaWVsZCB0ci1pbnB1dC13cmFwcGVyXCIvPicpXG4gICAgICAgICAgICAgICAgLmFkZENsYXNzKHRoaXMuY29uZmlnLmVkaXRpbmdNb2RlKVxuICAgICAgICAgICAgICAgIC5pbnNlcnRBZnRlcih0aGlzLiRvcmlnaW5hbElucHV0KTtcbiAgICAgICAgICAgIHZhciAkZWRpdG9yV3JhcHBlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1lZGl0b3Itd3JhcHBlclwiPicpLmFwcGVuZFRvKHRoaXMuJGRhdGVUaW1lRmllbGQpO1xuICAgICAgICAgICAgdGhpcy4kZGF0ZUljb25XcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLWRhdGUtaWNvbi13cmFwcGVyXCIvPicpLmFwcGVuZFRvKCRlZGl0b3JXcmFwcGVyKTtcbiAgICAgICAgICAgIHRoaXMuJGRhdGVFZGl0b3IgPSAkKCc8ZGl2IGNsYXNzPVwidHItZGF0ZS1lZGl0b3JcIiBjb250ZW50ZWRpdGFibGU9XCJ0cnVlXCIvPicpLmFwcGVuZFRvKCRlZGl0b3JXcmFwcGVyKTtcbiAgICAgICAgICAgIHRoaXMuJHRpbWVJY29uV3JhcHBlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10aW1lLWljb24td3JhcHBlclwiLz4nKS5hcHBlbmRUbygkZWRpdG9yV3JhcHBlcik7XG4gICAgICAgICAgICB0aGlzLiR0aW1lRWRpdG9yID0gJCgnPGRpdiBjbGFzcz1cInRyLXRpbWUtZWRpdG9yXCIgY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiLz4nKS5hcHBlbmRUbygkZWRpdG9yV3JhcHBlcik7XG4gICAgICAgICAgICB0aGlzLiRkYXRlSWNvbldyYXBwZXIuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLiRhY3RpdmVFZGl0b3IgPSBfdGhpcy4kZGF0ZUVkaXRvcjtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZXREcm9wRG93bk1vZGUoTW9kZS5NT0RFX0NBTEVOREFSKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy4kZGF0ZUVkaXRvclswXSwgMCwgX3RoaXMuJGRhdGVFZGl0b3IudGV4dCgpLmxlbmd0aCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJHRpbWVJY29uV3JhcHBlci5jbGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuJGFjdGl2ZUVkaXRvciA9IF90aGlzLiR0aW1lRWRpdG9yO1xuICAgICAgICAgICAgICAgIF90aGlzLnNldERyb3BEb3duTW9kZShNb2RlLk1PREVfQ0FMRU5EQVIpO1xuICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKF90aGlzLiR0aW1lRWRpdG9yWzBdLCAwLCBfdGhpcy4kdGltZUVkaXRvci50ZXh0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kZGF0ZUVkaXRvci5mb2N1cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuJGFjdGl2ZUVkaXRvciA9IF90aGlzLiRkYXRlRWRpdG9yO1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgfHwgX3RoaXMuZm9jdXNHb2VzVG9PdGhlckVkaXRvcikge1xuICAgICAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy4kZGF0ZUVkaXRvclswXSwgMCwgX3RoaXMuJGRhdGVFZGl0b3IudGV4dCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiR0aW1lRWRpdG9yLmZvY3VzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy4kYWN0aXZlRWRpdG9yID0gX3RoaXMuJHRpbWVFZGl0b3I7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCB8fCBfdGhpcy5mb2N1c0dvZXNUb090aGVyRWRpdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKF90aGlzLiR0aW1lRWRpdG9yWzBdLCAwLCBfdGhpcy4kdGltZUVkaXRvci50ZXh0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5zaG93VHJpZ2dlcikge1xuICAgICAgICAgICAgICAgIHZhciAkdHJpZ2dlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmlnZ2VyXCI+PHNwYW4gY2xhc3M9XCJ0ci10cmlnZ2VyLWljb25cIi8+PC9kaXY+JykuYXBwZW5kVG8odGhpcy4kZGF0ZVRpbWVGaWVsZCk7XG4gICAgICAgICAgICAgICAgJHRyaWdnZXIubW91c2Vkb3duKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXREcm9wRG93bk1vZGUoTW9kZS5NT0RFX0NBTEVOREFSKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jYWxlbmRhckJveC5zZXRTZWxlY3RlZERhdGUoX3RoaXMuZGF0ZVZhbHVlID8gX3RoaXMuZGF0ZVZhbHVlLm1vbWVudCA6IG1vbWVudCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kYWN0aXZlRWRpdG9yID0gX3RoaXMuJGRhdGVFZGl0b3I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuJGRhdGVFZGl0b3JbMF0sIDAsIF90aGlzLiRkYXRlRWRpdG9yLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duID0gJCgnPGRpdiBjbGFzcz1cInRyLWRyb3Bkb3duXCI+PC9kaXY+JylcbiAgICAgICAgICAgICAgICAuc2Nyb2xsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuZHJvcGRvd25OZWVkZWQgPSB0aGlzLmNvbmZpZy5lZGl0aW5nTW9kZSA9PSAnZWRpdGFibGUnO1xuICAgICAgICAgICAgaWYgKHRoaXMuZHJvcGRvd25OZWVkZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5hcHBlbmRUbyhcImJvZHlcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgJGRhdGVMaXN0Qm94ID0gJCgnPGRpdiBjbGFzcz1cImRhdGUtbGlzdGJveFwiPicpLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duKTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUxpc3RCb3ggPSBuZXcgVHJpdmlhbExpc3RCb3hfMS5Ucml2aWFsTGlzdEJveCgkZGF0ZUxpc3RCb3gsIHtcbiAgICAgICAgICAgICAgICBlbnRyeVJlbmRlcmluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE11c3RhY2hlLnJlbmRlcihfdGhpcy5kYXRlVGVtcGxhdGUsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUxpc3RCb3gub25TZWxlY3RlZEVudHJ5Q2hhbmdlZC5hZGRMaXN0ZW5lcihmdW5jdGlvbiAoc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgIGlmIChzZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldERhdGUoc2VsZWN0ZWRFbnRyeSwgc2VsZWN0ZWRFbnRyeS5kaXNwbGF5U3RyaW5nICE9IChfdGhpcy5kYXRlVmFsdWUgJiYgX3RoaXMuZGF0ZVZhbHVlLmRpc3BsYXlTdHJpbmcpKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZGF0ZUxpc3RCb3guc2V0U2VsZWN0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyICR0aW1lTGlzdEJveCA9ICQoJzxkaXYgY2xhc3M9XCJ0aW1lLWxpc3Rib3hcIj4nKS5hcHBlbmRUbyh0aGlzLiRkcm9wRG93bik7XG4gICAgICAgICAgICB0aGlzLnRpbWVMaXN0Qm94ID0gbmV3IFRyaXZpYWxMaXN0Qm94XzEuVHJpdmlhbExpc3RCb3goJHRpbWVMaXN0Qm94LCB7XG4gICAgICAgICAgICAgICAgZW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNdXN0YWNoZS5yZW5kZXIoX3RoaXMudGltZVRlbXBsYXRlLCBlbnRyeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnRpbWVMaXN0Qm94Lm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKHNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRUaW1lKHNlbGVjdGVkRW50cnksIHNlbGVjdGVkRW50cnkuZGlzcGxheVN0cmluZyAhPSAoX3RoaXMudGltZVZhbHVlICYmIF90aGlzLnRpbWVWYWx1ZS5kaXNwbGF5U3RyaW5nKSk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRhdGVMaXN0Qm94LnNldFNlbGVjdGVkRW50cnkobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGNhbGVuZGFyQm94ID0gJCgnPGRpdiBjbGFzcz1cImNhbGVuZGFyYm94XCI+JykuYXBwZW5kVG8odGhpcy4kZHJvcERvd24pO1xuICAgICAgICAgICAgdGhpcy4kZGF0ZUVkaXRvclxuICAgICAgICAgICAgICAgIC5hZGQodGhpcy4kdGltZUVkaXRvcilcbiAgICAgICAgICAgICAgICAuZm9jdXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLiRkYXRlVGltZUZpZWxkLmFkZENsYXNzKCdmb2N1cycpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuYmx1cihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZGF0ZVRpbWVGaWVsZC5yZW1vdmVDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRGlzcGxheSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAua2V5ZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChUcml2aWFsQ29yZV8xLmtleUNvZGVzLmlzTW9kaWZpZXJLZXkoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudGFiKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNlbGVjdEhpZ2hsaWdodGVkTGlzdEJveEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmxlZnRfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnJpZ2h0X2Fycm93KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5nZXRBY3RpdmVFZGl0b3IoKSA9PT0gX3RoaXMuJHRpbWVFZGl0b3IgJiYgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmxlZnRfYXJyb3cgJiYgd2luZG93LmdldFNlbGVjdGlvbigpLmZvY3VzT2Zmc2V0ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy4kZGF0ZUVkaXRvclswXSwgMCwgX3RoaXMuJGRhdGVFZGl0b3IudGV4dCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKCkgPT09IF90aGlzLiRkYXRlRWRpdG9yICYmIGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdyAmJiB3aW5kb3cuZ2V0U2VsZWN0aW9uKCkuZm9jdXNPZmZzZXQgPT09IF90aGlzLiRkYXRlRWRpdG9yLnRleHQoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKF90aGlzLiR0aW1lRWRpdG9yWzBdLCAwLCBfdGhpcy4kdGltZUVkaXRvci50ZXh0KCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuYmFja3NwYWNlIHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5kZWxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy51cF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZG93bl9hcnJvdykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5nZXRBY3RpdmVFZGl0b3IoKS5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpcmVjdGlvbiA9IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy51cF9hcnJvdyA/IC0xIDogMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXREcm9wRG93bk1vZGUoZS5jdXJyZW50VGFyZ2V0ID09PSBfdGhpcy4kZGF0ZUVkaXRvclswXSA/IE1vZGUuTU9ERV9EQVRFX0xJU1QgOiBNb2RlLk1PREVfVElNRV9MSVNUKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KGRpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5kcm9wRG93bk1vZGUgIT09IE1vZGUuTU9ERV9DQUxFTkRBUikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmdldEFjdGl2ZUJveCgpLm5hdmlnYXRlKGRpcmVjdGlvbiA9PT0gMSA/ICdkb3duJyA6ICd1cCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmF1dG9Db21wbGV0ZUlmUG9zc2libGUoX3RoaXMuY29uZmlnLmF1dG9Db21wbGV0ZURlbGF5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lbnRlcikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNlbGVjdEhpZ2hsaWdodGVkTGlzdEJveEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy5nZXRBY3RpdmVFZGl0b3IoKVswXSwgMCwgX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKCkudGV4dCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVzY2FwZSkge1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRGlzcGxheSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKClbMF0sIDAsIF90aGlzLmdldEFjdGl2ZUVkaXRvcigpLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldERyb3BEb3duTW9kZShlLmN1cnJlbnRUYXJnZXQgPT09IF90aGlzLiRkYXRlRWRpdG9yWzBdID8gTW9kZS5NT0RFX0RBVEVfTElTVCA6IE1vZGUuTU9ERV9USU1FX0xJU1QpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgxKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC52YWwoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VmFsdWUobW9tZW50KHRoaXMuJG9yaWdpbmFsSW5wdXQudmFsKCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRkYXRlRWRpdG9yLmFkZCh0aGlzLiR0aW1lRWRpdG9yKS5hdHRyKFwidGFiaW5kZXhcIiwgdGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcImF1dG9mb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGRhdGVFZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJGRhdGVUaW1lRmllbGQuYWRkKHRoaXMuJGRyb3BEb3duKS5tb3VzZWRvd24oZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGRhdGVFZGl0b3IuaXMoXCI6Zm9jdXNcIikgfHwgX3RoaXMuJHRpbWVFZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZS50YXJnZXQgPT09IF90aGlzLiRkYXRlRWRpdG9yWzBdXG4gICAgICAgICAgICAgICAgICAgIHx8IGUudGFyZ2V0ID09PSBfdGhpcy4kdGltZUVkaXRvclswXVxuICAgICAgICAgICAgICAgICAgICB8fCBlLnRhcmdldCA9PT0gX3RoaXMuJGRhdGVJY29uV3JhcHBlclswXVxuICAgICAgICAgICAgICAgICAgICB8fCBlLnRhcmdldCA9PT0gX3RoaXMuJHRpbWVJY29uV3JhcHBlclswXSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5mb2N1c0dvZXNUb090aGVyRWRpdG9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5vbignbW91c2V1cCBtb3VzZW91dCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgJiYgIV90aGlzLmZvY3VzR29lc1RvT3RoZXJFZGl0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKCkuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBfdGhpcy5mb2N1c0dvZXNUb090aGVyRWRpdG9yID0gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGFjdGl2ZUVkaXRvciA9IHRoaXMuJGRhdGVFZGl0b3I7XG4gICAgICAgICAgICB0aGlzLmRhdGVTdWdnZXN0aW9uRW5naW5lID0gbmV3IFRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZV8xLlRyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZSh7XG4gICAgICAgICAgICAgICAgcHJlZmVycmVkRGF0ZUZvcm1hdDogdGhpcy5jb25maWcuZGF0ZUZvcm1hdFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnRpbWVTdWdnZXN0aW9uRW5naW5lID0gbmV3IFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZV8xLlRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZSgpO1xuICAgICAgICB9XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5zZXREcm9wRG93bk1vZGUgPSBmdW5jdGlvbiAobW9kZSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuZHJvcERvd25Nb2RlID0gbW9kZTtcbiAgICAgICAgICAgIGlmICghdGhpcy5jYWxlbmRhckJveEluaXRpYWxpemVkICYmIG1vZGUgPT09IE1vZGUuTU9ERV9DQUxFTkRBUikge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJCb3ggPSBuZXcgVHJpdmlhbENhbGVuZGFyQm94XzEuVHJpdmlhbENhbGVuZGFyQm94KHRoaXMuJGNhbGVuZGFyQm94LCB7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0RGF5T2ZXZWVrOiAxLFxuICAgICAgICAgICAgICAgICAgICBtb2RlOiAnZGF0ZSdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGVuZGFyQm94LnNldEtleWJvYXJkTmF2aWdhdGlvblN0YXRlKCdtb250aCcpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsZW5kYXJCb3gub25DaGFuZ2UuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IF9hLnZhbHVlLCB0aW1lVW5pdEVkaXRlZCA9IF9hLnRpbWVVbml0RWRpdGVkO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXREYXRlKFRyaXZpYWxEYXRlVGltZUZpZWxkLmNyZWF0ZURhdGVDb21ib0JveEVudHJ5KHZhbHVlLCBfdGhpcy5jb25maWcuZGF0ZUZvcm1hdCkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGltZVVuaXRFZGl0ZWQgPT09ICdkYXknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kYWN0aXZlRWRpdG9yID0gX3RoaXMuJHRpbWVFZGl0b3I7XG4gICAgICAgICAgICAgICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyhfdGhpcy4kdGltZUVkaXRvclswXSwgMCwgX3RoaXMuJHRpbWVFZGl0b3IudGV4dCgpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5maXJlQ2hhbmdlRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGVuZGFyQm94SW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jYWxlbmRhckJveEluaXRpYWxpemVkICYmICQodGhpcy5jYWxlbmRhckJveC5nZXRNYWluRG9tRWxlbWVudCgpKS50b2dnbGUobW9kZSA9PT0gTW9kZS5NT0RFX0NBTEVOREFSKTtcbiAgICAgICAgICAgICQodGhpcy5kYXRlTGlzdEJveC5nZXRNYWluRG9tRWxlbWVudCgpKS50b2dnbGUobW9kZSA9PT0gTW9kZS5NT0RFX0RBVEVfTElTVCk7XG4gICAgICAgICAgICAkKHRoaXMudGltZUxpc3RCb3guZ2V0TWFpbkRvbUVsZW1lbnQoKSkudG9nZ2xlKG1vZGUgPT09IE1vZGUuTU9ERV9USU1FX0xJU1QpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuZ2V0QWN0aXZlQm94ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZHJvcERvd25Nb2RlID09PSBNb2RlLk1PREVfQ0FMRU5EQVIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jYWxlbmRhckJveDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuZHJvcERvd25Nb2RlID09PSBNb2RlLk1PREVfREFURV9MSVNUKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZUxpc3RCb3g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50aW1lTGlzdEJveDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLmdldEFjdGl2ZUVkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRhY3RpdmVFZGl0b3I7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5zZWxlY3RIaWdobGlnaHRlZExpc3RCb3hFbnRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRyb3BEb3duTW9kZSA9PT0gTW9kZS5NT0RFX0RBVEVfTElTVCB8fCB0aGlzLmRyb3BEb3duTW9kZSA9PT0gTW9kZS5NT0RFX1RJTUVfTElTVCkge1xuICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gdGhpcy5nZXRBY3RpdmVCb3goKS5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk9wZW4gJiYgaGlnaGxpZ2h0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5nZXRBY3RpdmVFZGl0b3IoKSA9PT0gdGhpcy4kZGF0ZUVkaXRvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXREYXRlKGhpZ2hsaWdodGVkRW50cnksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRUaW1lKGhpZ2hsaWdodGVkRW50cnksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUucXVlcnkgPSBmdW5jdGlvbiAoaGlnaGxpZ2h0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHF1ZXJ5U3RyaW5nID0gX3RoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5nZXRBY3RpdmVFZGl0b3IoKSA9PT0gX3RoaXMuJGRhdGVFZGl0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVudHJpZXMgPSBfdGhpcy5kYXRlU3VnZ2VzdGlvbkVuZ2luZS5nZW5lcmF0ZVN1Z2dlc3Rpb25zKHF1ZXJ5U3RyaW5nLCBtb21lbnQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKHMpIHsgcmV0dXJuIFRyaXZpYWxEYXRlVGltZUZpZWxkLmNyZWF0ZURhdGVDb21ib0JveEVudHJ5KHMubW9tZW50LCBfdGhpcy5jb25maWcuZGF0ZUZvcm1hdCk7IH0pO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy51cGRhdGVFbnRyaWVzKGVudHJpZXMsIGhpZ2hsaWdodERpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZW50cmllcyA9IF90aGlzLnRpbWVTdWdnZXN0aW9uRW5naW5lLmdlbmVyYXRlU3VnZ2VzdGlvbnMocXVlcnlTdHJpbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChzKSB7IHJldHVybiBUcml2aWFsRGF0ZVRpbWVGaWVsZC5jcmVhdGVUaW1lQ29tYm9Cb3hFbnRyeShzLmhvdXIsIHMubWludXRlLCBfdGhpcy5jb25maWcudGltZUZvcm1hdCk7IH0pO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy51cGRhdGVFbnRyaWVzKGVudHJpZXMsIGhpZ2hsaWdodERpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRhdGVWYWx1ZSA9PSBudWxsICYmIHRoaXMudGltZVZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuZGF0ZVZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMudGltZVZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9tZW50KFtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlVmFsdWUueWVhcixcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlVmFsdWUubW9udGggLSAxLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGVWYWx1ZS5kYXlcbiAgICAgICAgICAgICAgICBdKS5zdGFydE9mKCdkYXknKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb21lbnQoW1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGVWYWx1ZS55ZWFyLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGVWYWx1ZS5tb250aCAtIDEsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZVZhbHVlLmRheSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50aW1lVmFsdWUuaG91cixcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50aW1lVmFsdWUubWludXRlXG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLmZpcmVDaGFuZ2VFdmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlLmZpcmUodGhpcy5nZXRWYWx1ZSgpKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLnNldERhdGUgPSBmdW5jdGlvbiAobmV3RGF0ZVZhbHVlLCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQgPT09IHZvaWQgMCkgeyBmaXJlRXZlbnQgPSBmYWxzZTsgfVxuICAgICAgICAgICAgdGhpcy5kYXRlVmFsdWUgPSBuZXdEYXRlVmFsdWU7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLnNldFRpbWUgPSBmdW5jdGlvbiAobmV3VGltZVZhbHVlLCBmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQgPT09IHZvaWQgMCkgeyBmaXJlRXZlbnQgPSBmYWxzZTsgfVxuICAgICAgICAgICAgdGhpcy50aW1lVmFsdWUgPSBuZXdUaW1lVmFsdWU7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXkoKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLnVwZGF0ZURpc3BsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5kYXRlVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRkYXRlRWRpdG9yLnRleHQobW9tZW50KFt0aGlzLmRhdGVWYWx1ZS55ZWFyLCB0aGlzLmRhdGVWYWx1ZS5tb250aCAtIDEsIHRoaXMuZGF0ZVZhbHVlLmRheV0pLmZvcm1hdCh0aGlzLmNvbmZpZy5kYXRlRm9ybWF0KSk7XG4gICAgICAgICAgICAgICAgdGhpcy4kZGF0ZUljb25XcmFwcGVyLmVtcHR5KCkuYXBwZW5kKE11c3RhY2hlLnJlbmRlcih0aGlzLmRhdGVJY29uVGVtcGxhdGUsIHRoaXMuZGF0ZVZhbHVlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRkYXRlRWRpdG9yLnRleHQoXCJcIik7XG4gICAgICAgICAgICAgICAgdGhpcy4kZGF0ZUljb25XcmFwcGVyLmVtcHR5KCkuYXBwZW5kKE11c3RhY2hlLnJlbmRlcih0aGlzLmRhdGVJY29uVGVtcGxhdGUsIHt9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy50aW1lVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiR0aW1lRWRpdG9yLnRleHQobW9tZW50KFsxOTcwLCAwLCAxLCB0aGlzLnRpbWVWYWx1ZS5ob3VyLCB0aGlzLnRpbWVWYWx1ZS5taW51dGVdKS5mb3JtYXQodGhpcy5jb25maWcudGltZUZvcm1hdCkpO1xuICAgICAgICAgICAgICAgIHRoaXMuJHRpbWVJY29uV3JhcHBlci5lbXB0eSgpLmFwcGVuZChNdXN0YWNoZS5yZW5kZXIodGhpcy50aW1lSWNvblRlbXBsYXRlLCB0aGlzLnRpbWVWYWx1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kdGltZUVkaXRvci50ZXh0KFwiXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuJHRpbWVJY29uV3JhcHBlci5lbXB0eSgpLmFwcGVuZChNdXN0YWNoZS5yZW5kZXIodGhpcy50aW1lSWNvblRlbXBsYXRlLCB7fSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbiAobW9tKSB7XG4gICAgICAgICAgICB0aGlzLnNldERhdGUobW9tICYmIFRyaXZpYWxEYXRlVGltZUZpZWxkLmNyZWF0ZURhdGVDb21ib0JveEVudHJ5KG1vbSwgdGhpcy5jb25maWcuZGF0ZUZvcm1hdCkpO1xuICAgICAgICAgICAgdGhpcy5zZXRUaW1lKG1vbSAmJiBUcml2aWFsRGF0ZVRpbWVGaWVsZC5jcmVhdGVUaW1lQ29tYm9Cb3hFbnRyeShtb20uaG91cigpLCBtb20ubWludXRlKCksIHRoaXMuY29uZmlnLnRpbWVGb3JtYXQpKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLnJlcG9zaXRpb25Ecm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93blxuICAgICAgICAgICAgICAgIC5zaG93KClcbiAgICAgICAgICAgICAgICAucG9zaXRpb24oe1xuICAgICAgICAgICAgICAgIG15OiBcImxlZnQgdG9wXCIsXG4gICAgICAgICAgICAgICAgYXQ6IFwibGVmdCBib3R0b21cIixcbiAgICAgICAgICAgICAgICBvZjogdGhpcy4kZGF0ZVRpbWVGaWVsZCxcbiAgICAgICAgICAgICAgICBjb2xsaXNpb246IFwiZmxpcFwiLFxuICAgICAgICAgICAgICAgIHVzaW5nOiBmdW5jdGlvbiAoY2FsY3VsYXRlZFBvc2l0aW9uLCBpbmZvKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmZvLnZlcnRpY2FsID09PSBcInRvcFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZGF0ZVRpbWVGaWVsZC5yZW1vdmVDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24ucmVtb3ZlQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRhdGVUaW1lRmllbGQuYWRkQ2xhc3MoXCJkcm9wZG93bi1mbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLmFkZENsYXNzKFwiZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24uY3NzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQ6IGNhbGN1bGF0ZWRQb3NpdGlvbi5sZWZ0ICsgJ3B4JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogY2FsY3VsYXRlZFBvc2l0aW9uLnRvcCArICdweCdcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAud2lkdGgodGhpcy4kZGF0ZVRpbWVGaWVsZC53aWR0aCgpKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLm9wZW5Ecm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRyb3Bkb3duTmVlZGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZGF0ZVRpbWVGaWVsZC5hZGRDbGFzcyhcIm9wZW5cIik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXBvc2l0aW9uRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLmNsb3NlRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRkYXRlVGltZUZpZWxkLnJlbW92ZUNsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmhpZGUoKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZWRpdG9yVGV4dCA9IHRoaXMuZ2V0QWN0aXZlRWRpdG9yKCkudGV4dCgpLnJlcGxhY2UoU3RyaW5nLmZyb21DaGFyQ29kZSgxNjApLCBcIiBcIik7XG4gICAgICAgICAgICB2YXIgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgaWYgKHNlbGVjdGlvbi5hbmNob3JPZmZzZXQgIT0gc2VsZWN0aW9uLmZvY3VzT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVkaXRvclRleHQuc3Vic3RyaW5nKDAsIE1hdGgubWluKHNlbGVjdGlvbi5hbmNob3JPZmZzZXQsIHNlbGVjdGlvbi5mb2N1c09mZnNldCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVkaXRvclRleHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnByb3RvdHlwZS5hdXRvQ29tcGxldGVJZlBvc3NpYmxlID0gZnVuY3Rpb24gKGRlbGF5KSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmF1dG9Db21wbGV0ZSAmJiAodGhpcy5kcm9wRG93bk1vZGUgPT09IE1vZGUuTU9ERV9EQVRFX0xJU1QgfHwgdGhpcy5kcm9wRG93bk1vZGUgPT09IE1vZGUuTU9ERV9USU1FX0xJU1QpKSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuYXV0b0NvbXBsZXRlVGltZW91dElkKTtcbiAgICAgICAgICAgICAgICB2YXIgbGlzdEJveCA9IHRoaXMuZ2V0QWN0aXZlQm94KCk7XG4gICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnkgPSBsaXN0Qm94LmdldEhpZ2hsaWdodGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICBpZiAoaGlnaGxpZ2h0ZWRFbnRyeSAmJiB0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYXV0b0NvbXBsZXRpbmdFbnRyeURpc3BsYXlWYWx1ZV8xID0gaGlnaGxpZ2h0ZWRFbnRyeS5kaXNwbGF5U3RyaW5nO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXV0b0NvbXBsZXRpbmdFbnRyeURpc3BsYXlWYWx1ZV8xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmF1dG9Db21wbGV0ZVRpbWVvdXRJZCA9IHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2xkRWRpdG9yVmFsdWUgPSBfdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0VkaXRvclZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdXRvQ29tcGxldGluZ0VudHJ5RGlzcGxheVZhbHVlXzEudG9Mb3dlckNhc2UoKS5pbmRleE9mKG9sZEVkaXRvclZhbHVlLnRvTG93ZXJDYXNlKCkpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0VkaXRvclZhbHVlID0gb2xkRWRpdG9yVmFsdWUgKyBhdXRvQ29tcGxldGluZ0VudHJ5RGlzcGxheVZhbHVlXzEuc3Vic3RyKG9sZEVkaXRvclZhbHVlLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdFZGl0b3JWYWx1ZSA9IF90aGlzLmdldE5vblNlbGVjdGVkRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuZ2V0QWN0aXZlRWRpdG9yKCkudGV4dChuZXdFZGl0b3JWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmdldEFjdGl2ZUVkaXRvcigpLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKF90aGlzLmdldEFjdGl2ZUVkaXRvcigpWzBdLCBvbGRFZGl0b3JWYWx1ZS5sZW5ndGgsIG5ld0VkaXRvclZhbHVlLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSwgZGVsYXkgfHwgMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbERhdGVUaW1lRmllbGQucHJvdG90eXBlLnVwZGF0ZUVudHJpZXMgPSBmdW5jdGlvbiAobmV3RW50cmllcywgaGlnaGxpZ2h0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgbGlzdEJveCA9IHRoaXMuZ2V0QWN0aXZlQm94KCk7XG4gICAgICAgICAgICBoaWdobGlnaHREaXJlY3Rpb24gPSBoaWdobGlnaHREaXJlY3Rpb24gPT09IHVuZGVmaW5lZCA/IDEgOiBoaWdobGlnaHREaXJlY3Rpb247XG4gICAgICAgICAgICBsaXN0Qm94LnVwZGF0ZUVudHJpZXMobmV3RW50cmllcyk7XG4gICAgICAgICAgICBsaXN0Qm94LmhpZ2hsaWdodFRleHRNYXRjaGVzKHRoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpKTtcbiAgICAgICAgICAgIGxpc3RCb3guaGlnaGxpZ2h0TmV4dEVudHJ5KGhpZ2hsaWdodERpcmVjdGlvbik7XG4gICAgICAgICAgICB0aGlzLmF1dG9Db21wbGV0ZUlmUG9zc2libGUodGhpcy5jb25maWcuYXV0b0NvbXBsZXRlRGVsYXkpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5jcmVhdGVUaW1lQ29tYm9Cb3hFbnRyeSA9IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIHRpbWVGb3JtYXQpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaG91cjogaG91cixcbiAgICAgICAgICAgICAgICBtaW51dGU6IG1pbnV0ZSxcbiAgICAgICAgICAgICAgICBob3VyU3RyaW5nOiBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wYWQoaG91ciwgMiksXG4gICAgICAgICAgICAgICAgbWludXRlU3RyaW5nOiBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wYWQobWludXRlLCAyKSxcbiAgICAgICAgICAgICAgICBkaXNwbGF5U3RyaW5nOiBtb21lbnQoKS5ob3VyKGhvdXIpLm1pbnV0ZShtaW51dGUpLmZvcm1hdCh0aW1lRm9ybWF0KSxcbiAgICAgICAgICAgICAgICBob3VyQW5nbGU6ICgoaG91ciAlIDEyKSArIG1pbnV0ZSAvIDYwKSAqIDMwLFxuICAgICAgICAgICAgICAgIG1pbnV0ZUFuZ2xlOiBtaW51dGUgKiA2LFxuICAgICAgICAgICAgICAgIGlzTmlnaHQ6IGhvdXIgPCA2IHx8IGhvdXIgPj0gMjBcbiAgICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxEYXRlVGltZUZpZWxkLnBhZCA9IGZ1bmN0aW9uIChudW0sIHNpemUpIHtcbiAgICAgICAgICAgIHZhciBzID0gbnVtICsgXCJcIjtcbiAgICAgICAgICAgIHdoaWxlIChzLmxlbmd0aCA8IHNpemUpXG4gICAgICAgICAgICAgICAgcyA9IFwiMFwiICsgcztcbiAgICAgICAgICAgIHJldHVybiBzO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5jcmVhdGVEYXRlQ29tYm9Cb3hFbnRyeSA9IGZ1bmN0aW9uIChtLCBkYXRlRm9ybWF0KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1vbWVudDogbSxcbiAgICAgICAgICAgICAgICBkYXk6IG0uZGF0ZSgpLFxuICAgICAgICAgICAgICAgIHdlZWtEYXk6IG0uZm9ybWF0KCdkZCcpLFxuICAgICAgICAgICAgICAgIG1vbnRoOiBtLm1vbnRoKCkgKyAxLFxuICAgICAgICAgICAgICAgIHllYXI6IG0ueWVhcigpLFxuICAgICAgICAgICAgICAgIGRpc3BsYXlTdHJpbmc6IG0uZm9ybWF0KGRhdGVGb3JtYXQpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuZm9jdXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBUcml2aWFsQ29yZV8xLnNlbGVjdEVsZW1lbnRDb250ZW50cyh0aGlzLmdldEFjdGl2ZUVkaXRvcigpWzBdLCAwLCB0aGlzLmdldEFjdGl2ZUVkaXRvcigpLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQucmVtb3ZlQ2xhc3MoJ3RyLW9yaWdpbmFsLWlucHV0JykuaW5zZXJ0QmVmb3JlKHRoaXMuJGRhdGVUaW1lRmllbGQpO1xuICAgICAgICAgICAgdGhpcy4kZGF0ZVRpbWVGaWVsZC5yZW1vdmUoKTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLnJlbW92ZSgpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsRGF0ZVRpbWVGaWVsZC5wcm90b3R5cGUuZ2V0TWFpbkRvbUVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kZGF0ZVRpbWVGaWVsZFswXTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFRyaXZpYWxEYXRlVGltZUZpZWxkO1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsRGF0ZVRpbWVGaWVsZCA9IFRyaXZpYWxEYXRlVGltZUZpZWxkO1xufSk7XG5cblxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciB2ID0gZmFjdG9yeShyZXF1aXJlLCBleHBvcnRzKTtcbiAgICAgICAgaWYgKHYgIT09IHVuZGVmaW5lZCkgbW9kdWxlLmV4cG9ydHMgPSB2O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wicmVxdWlyZVwiLCBcImV4cG9ydHNcIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciBUcml2aWFsRXZlbnQgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsRXZlbnQoZXZlbnRTb3VyY2UpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTb3VyY2UgPSBldmVudFNvdXJjZTtcbiAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgVHJpdmlhbEV2ZW50LnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgdGhpcy5saXN0ZW5lcnMucHVzaChmbik7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbEV2ZW50LnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgdmFyIGxpc3RlbmVySW5kZXggPSB0aGlzLmxpc3RlbmVycy5pbmRleE9mKGZuKTtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lckluZGV4ICE9IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5saXN0ZW5lcnMuc3BsaWNlKGxpc3RlbmVySW5kZXgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxFdmVudC5wcm90b3R5cGUuZmlyZSA9IGZ1bmN0aW9uIChldmVudE9iamVjdCwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzW2ldLmNhbGwodGhpcy5saXN0ZW5lcnNbaV0sIGV2ZW50T2JqZWN0LCB0aGlzLmV2ZW50U291cmNlLCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICByZXR1cm4gVHJpdmlhbEV2ZW50O1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsRXZlbnQgPSBUcml2aWFsRXZlbnQ7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIm11c3RhY2hlXCIsIFwiLi9Ucml2aWFsQ29yZVwiLCBcIi4vVHJpdmlhbEV2ZW50XCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIE11c3RhY2hlID0gcmVxdWlyZShcIm11c3RhY2hlXCIpO1xuICAgIHZhciBUcml2aWFsQ29yZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENvcmVcIik7XG4gICAgdmFyIFRyaXZpYWxFdmVudF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpO1xuICAgIHZhciBUcml2aWFsTGlzdEJveCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFRyaXZpYWxMaXN0Qm94KCRjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5jb25maWcgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgZW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IGVudHJ5LnRlbXBsYXRlIHx8IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuaW1hZ2UyTGluZXNUZW1wbGF0ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE11c3RhY2hlLnJlbmRlcih0ZW1wbGF0ZSwgZW50cnkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeTogbnVsbCxcbiAgICAgICAgICAgICAgICBzcGlubmVyVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdFNwaW5uZXJUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICBlbnRyaWVzOiBudWxsLFxuICAgICAgICAgICAgICAgIG1hdGNoaW5nT3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ01vZGU6ICdjb250YWlucycsXG4gICAgICAgICAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG5vRW50cmllc1RlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHROb0VudHJpZXNUZW1wbGF0ZVxuICAgICAgICAgICAgfSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLiRsaXN0Qm94ID0gJCgnPGRpdiBjbGFzcz1cInRyLWxpc3Rib3hcIi8+JykuYXBwZW5kVG8oJGNvbnRhaW5lcik7XG4gICAgICAgICAgICB2YXIgbWUgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy4kbGlzdEJveC5vbihcIm1vdXNlZG93blwiLCBcIi50ci1saXN0Ym94LWVudHJ5XCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgbWUuc2V0U2VsZWN0ZWRFbnRyeSgkKHRoaXMpLmRhdGEoXCJlbnRyeVwiKSwgZSwgdHJ1ZSk7XG4gICAgICAgICAgICB9KS5vbihcIm1vdXNldXBcIiwgXCIudHItbGlzdGJveC1lbnRyeVwiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIG1lLiRsaXN0Qm94LnRyaWdnZXIoXCJtb3VzZXVwXCIsIGUpO1xuICAgICAgICAgICAgfSkub24oXCJtb3VzZWVudGVyXCIsIFwiLnRyLWxpc3Rib3gtZW50cnlcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBtZS5zZXRIaWdobGlnaHRlZEVudHJ5KCQodGhpcykuZGF0YShcImVudHJ5XCIpKTtcbiAgICAgICAgICAgIH0pLm9uKFwibW91c2VsZWF2ZVwiLCBcIi50ci1saXN0Ym94LWVudHJ5XCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEkKGUudG9FbGVtZW50KS5pcygnLnRyLWxpc3Rib3gtZW50cnknKSkge1xuICAgICAgICAgICAgICAgICAgICBtZS5zZXRIaWdobGlnaHRlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kZW50cnlMaXN0ID0gJCgnPGRpdiBjbGFzcz1cInRyLWxpc3Rib3gtZW50cnktbGlzdFwiPjwvZGl2PicpLmFwcGVuZFRvKHRoaXMuJGxpc3RCb3gpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVudHJpZXMgPSB0aGlzLmNvbmZpZy5lbnRyaWVzO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRW50cnlFbGVtZW50cyh0aGlzLmVudHJpZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kbGlzdEJveC5kYXRhKFwidHJpdmlhbExpc3RCb3hcIiwgdGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLnVwZGF0ZUVudHJ5RWxlbWVudHMgPSBmdW5jdGlvbiAoZW50cmllcykge1xuICAgICAgICAgICAgdGhpcy4kZW50cnlMaXN0LmRldGFjaCgpO1xuICAgICAgICAgICAgdGhpcy4kZW50cnlMaXN0LmVtcHR5KCk7XG4gICAgICAgICAgICBpZiAoZW50cmllcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlbnRyeSA9IGVudHJpZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHZhciAkZW50cnkgPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZW50cnkuX3RyRW50cnlFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaHRtbCA9IHRoaXMuY29uZmlnLmVudHJ5UmVuZGVyaW5nRnVuY3Rpb24oZW50cnkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGVudHJ5ID0gJChodG1sKS5hZGRDbGFzcyhcInRyLWxpc3Rib3gtZW50cnkgZmlsdGVyYWJsZS1pdGVtXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGVudHJ5ID0gZW50cnkuX3RyRW50cnlFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICRlbnRyeS5hcHBlbmRUbyh0aGlzLiRlbnRyeUxpc3QpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZGF0YShcImVudHJ5XCIsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgZW50cnkuX3RyRW50cnlFbGVtZW50ID0gJGVudHJ5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVudHJ5TGlzdC5hcHBlbmQodGhpcy5jb25maWcubm9FbnRyaWVzVGVtcGxhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kZW50cnlMaXN0LmFwcGVuZFRvKHRoaXMuJGxpc3RCb3gpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUudXBkYXRlRW50cmllcyA9IGZ1bmN0aW9uIChuZXdFbnRyaWVzKSB7XG4gICAgICAgICAgICBpZiAobmV3RW50cmllcyA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbmV3RW50cmllcyA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXRIaWdobGlnaHRlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gbmV3RW50cmllcztcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRW50cnlFbGVtZW50cyh0aGlzLmVudHJpZXMpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUubWluaW1hbGx5U2Nyb2xsVG8gPSBmdW5jdGlvbiAoJGVudHJ5V3JhcHBlcikge1xuICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5taW5pbWFsbHlTY3JvbGxUbyh0aGlzLiRsaXN0Qm94LnBhcmVudCgpLCAkZW50cnlXcmFwcGVyKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLnNldEhpZ2hsaWdodGVkRW50cnkgPSBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgIGlmIChlbnRyeSAhPT0gdGhpcy5oaWdobGlnaHRlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRlZEVudHJ5ID0gZW50cnk7XG4gICAgICAgICAgICAgICAgdGhpcy4kZW50cnlMaXN0LmZpbmQoJy50ci1saXN0Ym94LWVudHJ5JykucmVtb3ZlQ2xhc3MoJ3RyLWhpZ2hsaWdodGVkLWVudHJ5Jyk7XG4gICAgICAgICAgICAgICAgaWYgKGVudHJ5ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgZW50cnkuX3RyRW50cnlFbGVtZW50LmFkZENsYXNzKCd0ci1oaWdobGlnaHRlZC1lbnRyeScpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1pbmltYWxseVNjcm9sbFRvKGVudHJ5Ll90ckVudHJ5RWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUuZmlyZUNoYW5nZUV2ZW50cyA9IGZ1bmN0aW9uIChzZWxlY3RlZEVudHJ5LCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLiRsaXN0Qm94LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuZmlyZShzZWxlY3RlZEVudHJ5LCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLnNldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoZW50cnksIG9yaWdpbmFsRXZlbnQsIGZpcmVFdmVudCkge1xuICAgICAgICAgICAgaWYgKGZpcmVFdmVudCA9PT0gdm9pZCAwKSB7IGZpcmVFdmVudCA9IGZhbHNlOyB9XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cnkgPSBlbnRyeTtcbiAgICAgICAgICAgIHRoaXMuJGVudHJ5TGlzdC5maW5kKFwiLnRyLXNlbGVjdGVkLWVudHJ5XCIpLnJlbW92ZUNsYXNzKFwidHItc2VsZWN0ZWQtZW50cnlcIik7XG4gICAgICAgICAgICBpZiAoZW50cnkgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRFbnRyeS5fdHJFbnRyeUVsZW1lbnQuYWRkQ2xhc3MoXCJ0ci1zZWxlY3RlZC1lbnRyeVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHModGhpcy5zZWxlY3RlZEVudHJ5LCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLmhpZ2hsaWdodE5leHRFbnRyeSA9IGZ1bmN0aW9uIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBuZXdIaWdobGlnaHRlZEVudHJ5ID0gdGhpcy5nZXROZXh0SGlnaGxpZ2h0YWJsZUVudHJ5KGRpcmVjdGlvbik7XG4gICAgICAgICAgICBpZiAobmV3SGlnaGxpZ2h0ZWRFbnRyeSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRIaWdobGlnaHRlZEVudHJ5KG5ld0hpZ2hsaWdodGVkRW50cnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUuZ2V0TmV4dEhpZ2hsaWdodGFibGVFbnRyeSA9IGZ1bmN0aW9uIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBuZXdIaWdobGlnaHRlZEVsZW1lbnRJbmRleDtcbiAgICAgICAgICAgIGlmICh0aGlzLmVudHJpZXMgPT0gbnVsbCB8fCB0aGlzLmVudHJpZXMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSA9PSBudWxsICYmIGRpcmVjdGlvbiA+IDApIHtcbiAgICAgICAgICAgICAgICBuZXdIaWdobGlnaHRlZEVsZW1lbnRJbmRleCA9IC0xICsgZGlyZWN0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5oaWdobGlnaHRlZEVudHJ5ID09IG51bGwgJiYgZGlyZWN0aW9uIDwgMCkge1xuICAgICAgICAgICAgICAgIG5ld0hpZ2hsaWdodGVkRWxlbWVudEluZGV4ID0gdGhpcy5lbnRyaWVzLmxlbmd0aCArIGRpcmVjdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SGlnaGxpZ2h0ZWRFbGVtZW50SW5kZXggPSB0aGlzLmVudHJpZXMuaW5kZXhPZih0aGlzLmhpZ2hsaWdodGVkRW50cnkpO1xuICAgICAgICAgICAgICAgIG5ld0hpZ2hsaWdodGVkRWxlbWVudEluZGV4ID0gKGN1cnJlbnRIaWdobGlnaHRlZEVsZW1lbnRJbmRleCArIHRoaXMuZW50cmllcy5sZW5ndGggKyBkaXJlY3Rpb24pICUgdGhpcy5lbnRyaWVzLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVudHJpZXNbbmV3SGlnaGxpZ2h0ZWRFbGVtZW50SW5kZXhdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUuaGlnaGxpZ2h0VGV4dE1hdGNoZXMgPSBmdW5jdGlvbiAoc2VhcmNoU3RyaW5nKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciAkZW50cnlFbGVtZW50ID0gdGhpcy5lbnRyaWVzW2ldLl90ckVudHJ5RWxlbWVudDtcbiAgICAgICAgICAgICAgICAkZW50cnlFbGVtZW50LnRyaXZpYWxIaWdobGlnaHQoc2VhcmNoU3RyaW5nLCB0aGlzLmNvbmZpZy5tYXRjaGluZ09wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUuZ2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWRFbnRyeVRvUmV0dXJuID0gJC5leHRlbmQoe30sIHRoaXMuc2VsZWN0ZWRFbnRyeSk7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeVRvUmV0dXJuLl90ckVudHJ5RWxlbWVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZWN0ZWRFbnRyeVRvUmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxMaXN0Qm94LnByb3RvdHlwZS5nZXRIaWdobGlnaHRlZEVudHJ5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsTGlzdEJveC5wcm90b3R5cGUubmF2aWdhdGUgPSBmdW5jdGlvbiAoZGlyZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoZGlyZWN0aW9uID09PSAndXAnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHROZXh0RW50cnkoLTEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoZGlyZWN0aW9uID09PSAnZG93bicpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZ2hsaWdodE5leHRFbnRyeSgxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbExpc3RCb3gucHJvdG90eXBlLmdldE1haW5Eb21FbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGxpc3RCb3hbMF07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxMaXN0Qm94LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kbGlzdEJveC5yZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICByZXR1cm4gVHJpdmlhbExpc3RCb3g7XG4gICAgfSgpKTtcbiAgICBleHBvcnRzLlRyaXZpYWxMaXN0Qm94ID0gVHJpdmlhbExpc3RCb3g7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIm11c3RhY2hlXCIsIFwiLi9Ucml2aWFsTGlzdEJveFwiLCBcIi4vVHJpdmlhbENvcmVcIiwgXCIuL1RyaXZpYWxFdmVudFwiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBNdXN0YWNoZSA9IHJlcXVpcmUoXCJtdXN0YWNoZVwiKTtcbiAgICB2YXIgVHJpdmlhbExpc3RCb3hfMSA9IHJlcXVpcmUoXCIuL1RyaXZpYWxMaXN0Qm94XCIpO1xuICAgIHZhciBUcml2aWFsQ29yZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENvcmVcIik7XG4gICAgdmFyIFRyaXZpYWxFdmVudF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpO1xuICAgIHZhciBUcml2aWFsVGFnQ29tYm9Cb3ggPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsVGFnQ29tYm9Cb3gob3JpZ2luYWxJbnB1dCwgb3B0aW9ucykge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gJCgpO1xuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMub25Gb2N1cyA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9uQmx1ciA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmxhc3RRdWVyeVN0cmluZyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmxhc3RDb21wbGV0ZUlucHV0UXVlcnlTdHJpbmcgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEVudHJpZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuYXV0b0NvbXBsZXRlVGltZW91dElkID0gLTE7XG4gICAgICAgICAgICB0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94RGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5yZXBvc2l0aW9uRHJvcERvd25TY2hlZHVsZXIgPSBudWxsO1xuICAgICAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICB0aGlzLmNvbmZpZyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgICAgICB2YWx1ZUZ1bmN0aW9uOiBmdW5jdGlvbiAoZW50cmllcykgeyByZXR1cm4gZW50cmllcy5tYXAoZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGUuX2lzRnJlZVRleHRFbnRyeSA/IGUuZGlzcGxheVZhbHVlIDogZS5pZDsgfSkuam9pbignLCcpOyB9LFxuICAgICAgICAgICAgICAgIGVudHJ5UmVuZGVyaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTXVzdGFjaGUucmVuZGVyKFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuaW1hZ2UyTGluZXNUZW1wbGF0ZSwgZW50cnkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeVJlbmRlcmluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRyaXZpYWxDb3JlXzEud3JhcFdpdGhEZWZhdWx0VGFnV3JhcHBlcihfdGhpcy5jb25maWcuZW50cnlSZW5kZXJpbmdGdW5jdGlvbihlbnRyeSkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc3Bpbm5lclRlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHRTcGlubmVyVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgbm9FbnRyaWVzVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdE5vRW50cmllc1RlbXBsYXRlLFxuICAgICAgICAgICAgICAgIHRleHRIaWdobGlnaHRpbmdFbnRyeUxpbWl0OiAxMDAsXG4gICAgICAgICAgICAgICAgZW50cmllczogbnVsbCxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJpZXM6IFtdLFxuICAgICAgICAgICAgICAgIG1heFNlbGVjdGVkRW50cmllczogbnVsbCxcbiAgICAgICAgICAgICAgICBxdWVyeUZ1bmN0aW9uOiBudWxsLFxuICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGVEZWxheTogMCxcbiAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGVGdW5jdGlvbjogZnVuY3Rpb24gKGVkaXRvclRleHQsIGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlZGl0b3JUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wZXJ0eU5hbWUgaW4gZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnkuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHlWYWx1ZSA9IGVudHJ5W3Byb3BlcnR5TmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0eVZhbHVlICYmIChcIlwiICsgcHJvcGVydHlWYWx1ZSkudG9Mb3dlckNhc2UoKS5pbmRleE9mKGVkaXRvclRleHQudG9Mb3dlckNhc2UoKSkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcIlwiICsgcHJvcGVydHlWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGFsbG93RnJlZVRleHQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGZyZWVUZXh0U2VwYXJhdG9yczogWycsJywgJzsnXSxcbiAgICAgICAgICAgICAgICBmcmVlVGV4dEVudHJ5RmFjdG9yeTogZnVuY3Rpb24gKGZyZWVUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5VmFsdWU6IGZyZWVUZXh0LFxuICAgICAgICAgICAgICAgICAgICAgICAgX2lzRnJlZVRleHRFbnRyeTogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2hvd1RyaWdnZXI6IHRydWUsXG4gICAgICAgICAgICAgICAgZGlzdGluY3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgbWF0Y2hpbmdPcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoaW5nTW9kZTogJ2NvbnRhaW5zJyxcbiAgICAgICAgICAgICAgICAgICAgaWdub3JlQ2FzZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWF4TGV2ZW5zaHRlaW5EaXN0YW5jZTogMlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZWRpdGluZ01vZGU6IFwiZWRpdGFibGVcIixcbiAgICAgICAgICAgICAgICBzaG93RHJvcERvd25PblJlc3VsdHNPbmx5OiBmYWxzZVxuICAgICAgICAgICAgfSwgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLnF1ZXJ5RnVuY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uID0gVHJpdmlhbENvcmVfMS5kZWZhdWx0TGlzdFF1ZXJ5RnVuY3Rpb25GYWN0b3J5KHRoaXMuY29uZmlnLmVudHJpZXMgfHwgW10sIHRoaXMuY29uZmlnLm1hdGNoaW5nT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW50cmllcyA9IHRoaXMuY29uZmlnLmVudHJpZXM7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0ID0gJChvcmlnaW5hbElucHV0KS5hZGRDbGFzcyhcInRyLW9yaWdpbmFsLWlucHV0XCIpO1xuICAgICAgICAgICAgdGhpcy4kdGFnQ29tYm9Cb3ggPSAkKCc8ZGl2IGNsYXNzPVwidHItdGFnYm94IHRyLWlucHV0LXdyYXBwZXJcIi8+JylcbiAgICAgICAgICAgICAgICAuaW5zZXJ0QWZ0ZXIodGhpcy4kb3JpZ2luYWxJbnB1dCk7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LmFwcGVuZFRvKHRoaXMuJHRhZ0NvbWJvQm94KTtcbiAgICAgICAgICAgIHZhciAkdGFnQXJlYSA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10YWdib3gtdGFnYXJlYVwiLz4nKS5hcHBlbmRUbyh0aGlzLiR0YWdDb21ib0JveCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuc2hvd1RyaWdnZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiR0cmlnZ2VyID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyaWdnZXJcIj48c3BhbiBjbGFzcz1cInRyLXRyaWdnZXItaWNvblwiLz48L2Rpdj4nKS5hcHBlbmRUbyh0aGlzLiR0YWdDb21ib0JveCk7XG4gICAgICAgICAgICAgICAgdGhpcy4kdHJpZ2dlci5tb3VzZWRvd24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duID0gJCgnPGRpdiBjbGFzcz1cInRyLWRyb3Bkb3duXCI+PC9kaXY+JylcbiAgICAgICAgICAgICAgICAuc2Nyb2xsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duVGFyZ2V0RWxlbWVudCA9ICQoXCJib2R5XCIpO1xuICAgICAgICAgICAgdGhpcy5zZXRFZGl0aW5nTW9kZSh0aGlzLmNvbmZpZy5lZGl0aW5nTW9kZSk7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IgPSAkKCc8c3BhbiBjb250ZW50ZWRpdGFibGU9XCJ0cnVlXCIgY2xhc3M9XCJ0YWdib3gtZWRpdG9yXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCI+PC9zcGFuPicpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmFwcGVuZFRvKCR0YWdBcmVhKS5hZGRDbGFzcyhcInRyLXRhZ2JveC1lZGl0b3IgdHItZWRpdG9yXCIpXG4gICAgICAgICAgICAgICAgLmZvY3VzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXJIYW5kbGVyKCdmb2N1cycpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vbkZvY3VzLmZpcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJHRhZ0NvbWJvQm94LmFkZENsYXNzKCdmb2N1cycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5taW5pbWFsbHlTY3JvbGxUbygkdGFnQXJlYSwgX3RoaXMuJGVkaXRvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5ibHVyKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXJIYW5kbGVyKCdibHVyJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9uQmx1ci5maXJlKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiR0YWdDb21ib0JveC5yZW1vdmVDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZW50cmllcyA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5hbGxvd0ZyZWVUZXh0ICYmIF90aGlzLiRlZGl0b3IudGV4dCgpLnRyaW0oKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KF90aGlzLmNvbmZpZy5mcmVlVGV4dEVudHJ5RmFjdG9yeShfdGhpcy4kZWRpdG9yLnRleHQoKSksIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudGV4dChcIlwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5rZXlkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuaXNNb2RpZmllcktleShlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy50YWIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnkgPSBfdGhpcy5saXN0Qm94LmdldEhpZ2hsaWdodGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuICYmIGhpZ2hsaWdodGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoaGlnaGxpZ2h0ZWRFbnRyeSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMubGVmdF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5sZWZ0X2Fycm93ICYmIF90aGlzLiRlZGl0b3IudGV4dCgpLmxlbmd0aCA9PT0gMCAmJiB3aW5kb3cuZ2V0U2VsZWN0aW9uKCkuYW5jaG9yT2Zmc2V0ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGVkaXRvci5wcmV2KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmluc2VydEJlZm9yZShfdGhpcy4kZWRpdG9yLnByZXYoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdyAmJiBfdGhpcy4kZWRpdG9yLnRleHQoKS5sZW5ndGggPT09IDAgJiYgd2luZG93LmdldFNlbGVjdGlvbigpLmFuY2hvck9mZnNldCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IubmV4dCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5pbnNlcnRBZnRlcihfdGhpcy4kZWRpdG9yLm5leHQoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5iYWNrc3BhY2UgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmRlbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGVkaXRvci50ZXh0KCkgPT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRhZ1RvQmVSZW1vdmVkID0gX3RoaXMuc2VsZWN0ZWRFbnRyaWVzW190aGlzLiRlZGl0b3IuaW5kZXgoKSArIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuYmFja3NwYWNlID8gLTEgOiAwKV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFnVG9CZVJlbW92ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5yZW1vdmVUYWcodGFnVG9CZVJlbW92ZWQsIGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmRvd25fYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgPyAtMSA6IDE7XG4gICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KGRpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmNvbmZpZy5zaG93RHJvcERvd25PblJlc3VsdHNPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5saXN0Qm94LmhpZ2hsaWdodE5leHRFbnRyeShkaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuYXV0b0NvbXBsZXRlSWZQb3NzaWJsZShfdGhpcy5jb25maWcuYXV0b0NvbXBsZXRlRGVsYXkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVudGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gX3RoaXMubGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3BlbiAmJiBoaWdobGlnaHRlZEVudHJ5ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoaGlnaGxpZ2h0ZWRFbnRyeSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5lbnRyaWVzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChfdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCAmJiBfdGhpcy4kZWRpdG9yLnRleHQoKS50cmltKCkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5jb25maWcuZnJlZVRleHRFbnRyeUZhY3RvcnkoX3RoaXMuJGVkaXRvci50ZXh0KCkpLCBmYWxzZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lc2NhcGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnRleHQoXCJcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmNvbmZpZy5zaG93RHJvcERvd25PblJlc3VsdHNPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5rZXl1cChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHNwbGl0U3RyaW5nQnlTZXBhcmF0b3JDaGFycyhzLCBzZXBhcmF0b3JDaGFycykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcy5zcGxpdChuZXcgUmVnRXhwKFwiW1wiICsgVHJpdmlhbENvcmVfMS5lc2NhcGVTcGVjaWFsUmVnZXhDaGFyYWN0ZXIoc2VwYXJhdG9yQ2hhcnMuam9pbigpKSArIFwiXVwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLmZpbmQoJyonKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudGV4dChfdGhpcy4kZWRpdG9yLnRleHQoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuYWxsb3dGcmVlVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZWRpdG9yVmFsdWVCZWZvcmVDdXJzb3IgPSBfdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlZGl0b3JWYWx1ZUJlZm9yZUN1cnNvci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGFnVmFsdWVzRW50ZXJlZEJ5VXNlciA9IHNwbGl0U3RyaW5nQnlTZXBhcmF0b3JDaGFycyhlZGl0b3JWYWx1ZUJlZm9yZUN1cnNvciwgX3RoaXMuY29uZmlnLmZyZWVUZXh0U2VwYXJhdG9ycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRhZ1ZhbHVlc0VudGVyZWRCeVVzZXIubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gdGFnVmFsdWVzRW50ZXJlZEJ5VXNlcltpXS50cmltKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5jb25maWcuZnJlZVRleHRFbnRyeUZhY3RvcnkodmFsdWUpLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci50ZXh0KHRhZ1ZhbHVlc0VudGVyZWRCeVVzZXJbdGFnVmFsdWVzRW50ZXJlZEJ5VXNlci5sZW5ndGggLSAxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuJGVkaXRvclswXSwgX3RoaXMuJGVkaXRvci50ZXh0KCkubGVuZ3RoLCBfdGhpcy4kZWRpdG9yLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmVudHJpZXMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInBsYWNlaG9sZGVyXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmF0dHIoXCJwbGFjZWhvbGRlclwiLCB0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJwbGFjZWhvbGRlclwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IuYXR0cihcInRhYmluZGV4XCIsIHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJhdXRvZm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJHRhZ0NvbWJvQm94LmFkZCh0aGlzLiRkcm9wRG93bikubW91c2Vkb3duKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGVkaXRvci5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkubW91c2V1cChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlOyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5tb3VzZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlOyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBjb25maWdXaXRob3V0RW50cmllcyA9ICQuZXh0ZW5kKHt9LCB0aGlzLmNvbmZpZyk7XG4gICAgICAgICAgICBjb25maWdXaXRob3V0RW50cmllcy5lbnRyaWVzID0gW107XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3ggPSBuZXcgVHJpdmlhbExpc3RCb3hfMS5Ucml2aWFsTGlzdEJveCh0aGlzLiRkcm9wRG93biwgY29uZmlnV2l0aG91dEVudHJpZXMpO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94Lm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKHNlbGVjdGVkRW50cnksIGV2ZW50U291cmNlLCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShzZWxlY3RlZEVudHJ5LCB0cnVlLCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubGlzdEJveC5zZXRTZWxlY3RlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAkdGFnQXJlYS5jbGljayhmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KCk7XG4gICAgICAgICAgICAgICAgdmFyICR0YWdXaXRoU21hbGxlc3REaXN0YW5jZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgdmFyIHNtYWxsZXN0RGlzdGFuY2VYID0gMTAwMDAwMDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IF90aGlzLnNlbGVjdGVkRW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWRFbnRyeSA9IF90aGlzLnNlbGVjdGVkRW50cmllc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyICR0YWcgPSBzZWxlY3RlZEVudHJ5Ll90ckVudHJ5RWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRhZ0JvdW5kaW5nUmVjdCA9ICR0YWdbMF0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzYW1lUm93ID0gZS5jbGllbnRZID49IHRhZ0JvdW5kaW5nUmVjdC50b3AgJiYgZS5jbGllbnRZIDwgdGFnQm91bmRpbmdSZWN0LmJvdHRvbTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNhbWVDb2wgPSBlLmNsaWVudFggPj0gdGFnQm91bmRpbmdSZWN0LmxlZnQgJiYgZS5jbGllbnRYIDwgdGFnQm91bmRpbmdSZWN0LnJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGlzdGFuY2VYID0gc2FtZUNvbCA/IDAgOiBNYXRoLm1pbihNYXRoLmFicyhlLmNsaWVudFggLSB0YWdCb3VuZGluZ1JlY3QubGVmdCksIE1hdGguYWJzKGUuY2xpZW50WCAtIHRhZ0JvdW5kaW5nUmVjdC5yaWdodCkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2FtZVJvdyAmJiBkaXN0YW5jZVggPCBzbWFsbGVzdERpc3RhbmNlWCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRhZ1dpdGhTbWFsbGVzdERpc3RhbmNlID0gJHRhZztcbiAgICAgICAgICAgICAgICAgICAgICAgIHNtYWxsZXN0RGlzdGFuY2VYID0gZGlzdGFuY2VYO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRpc3RhbmNlWCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgkdGFnV2l0aFNtYWxsZXN0RGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRhZ0JvdW5kaW5nUmVjdCA9ICR0YWdXaXRoU21hbGxlc3REaXN0YW5jZVswXS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlzUmlnaHRTaWRlID0gZS5jbGllbnRYID4gKHRhZ0JvdW5kaW5nUmVjdC5sZWZ0ICsgdGFnQm91bmRpbmdSZWN0LnJpZ2h0KSAvIDI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1JpZ2h0U2lkZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5pbnNlcnRBZnRlcigkdGFnV2l0aFNtYWxsZXN0RGlzdGFuY2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5pbnNlcnRCZWZvcmUoJHRhZ1dpdGhTbWFsbGVzdERpc3RhbmNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0ZWRFbnRyaWVzKHRoaXMuY29uZmlnLnNlbGVjdGVkRW50cmllcyk7XG4gICAgICAgICAgICB0aGlzLiR0YWdDb21ib0JveC5kYXRhKFwidHJpdmlhbFRhZ0NvbWJvQm94XCIsIHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUudXBkYXRlTGlzdEJveEVudHJpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3gudXBkYXRlRW50cmllcyh0aGlzLmVudHJpZXMpO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94RGlydHkgPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS51cGRhdGVFbnRyaWVzID0gZnVuY3Rpb24gKG5ld0VudHJpZXMsIGhpZ2hsaWdodERpcmVjdGlvbikge1xuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gbmV3RW50cmllcztcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzLnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSAkKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTGlzdEJveEVudHJpZXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdEJveERpcnR5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBub25TZWxlY3RlZEVkaXRvclZhbHVlID0gdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3guaGlnaGxpZ2h0VGV4dE1hdGNoZXMobmV3RW50cmllcy5sZW5ndGggPD0gdGhpcy5jb25maWcudGV4dEhpZ2hsaWdodGluZ0VudHJ5TGltaXQgPyBub25TZWxlY3RlZEVkaXRvclZhbHVlIDogbnVsbCk7XG4gICAgICAgICAgICBpZiAoaGlnaGxpZ2h0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5saXN0Qm94LmhpZ2hsaWdodE5leHRFbnRyeShoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5saXN0Qm94LnNldEhpZ2hsaWdodGVkRW50cnkobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmF1dG9Db21wbGV0ZUlmUG9zc2libGUodGhpcy5jb25maWcuYXV0b0NvbXBsZXRlRGVsYXkpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLnJlbW92ZVRhZyA9IGZ1bmN0aW9uICh0YWdUb0JlUmVtb3ZlZCwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5zZWxlY3RlZEVudHJpZXMuaW5kZXhPZih0YWdUb0JlUmVtb3ZlZCk7XG4gICAgICAgICAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRFbnRyaWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YWdUb0JlUmVtb3ZlZC5fdHJFbnRyeUVsZW1lbnQucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCh0aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKHRoaXMuZ2V0U2VsZWN0ZWRFbnRyaWVzKCkpKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cyh0aGlzLmdldFNlbGVjdGVkRW50cmllcygpLCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uIChoaWdobGlnaHREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcXVlcnlTdHJpbmcgPSBfdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICAgICAgdmFyIGNvbXBsZXRlSW5wdXRTdHJpbmcgPSBfdGhpcy4kZWRpdG9yLnRleHQoKS5yZXBsYWNlKFN0cmluZy5mcm9tQ2hhckNvZGUoMTYwKSwgXCIgXCIpO1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5sYXN0UXVlcnlTdHJpbmcgIT09IHF1ZXJ5U3RyaW5nIHx8IF90aGlzLmxhc3RDb21wbGV0ZUlucHV0UXVlcnlTdHJpbmcgIT09IGNvbXBsZXRlSW5wdXRTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRzcGlubmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkc3Bpbm5lciA9ICQoX3RoaXMuY29uZmlnLnNwaW5uZXJUZW1wbGF0ZSkuYXBwZW5kVG8oX3RoaXMuJGRyb3BEb3duKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRzcGlubmVycyA9IF90aGlzLiRzcGlubmVycy5hZGQoJHNwaW5uZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uKHF1ZXJ5U3RyaW5nLCBmdW5jdGlvbiAobmV3RW50cmllcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRW50cmllcyhuZXdFbnRyaWVzLCBoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5zaG93RHJvcERvd25PblJlc3VsdHNPbmx5ICYmIG5ld0VudHJpZXMgJiYgbmV3RW50cmllcy5sZW5ndGggPiAwICYmIF90aGlzLiRlZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmxhc3RRdWVyeVN0cmluZyA9IHF1ZXJ5U3RyaW5nO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5sYXN0Q29tcGxldGVJbnB1dFF1ZXJ5U3RyaW5nID0gY29tcGxldGVJbnB1dFN0cmluZztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5maXJlQ2hhbmdlRXZlbnRzID0gZnVuY3Rpb24gKGVudHJpZXMsIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQudHJpZ2dlcihcImNoYW5nZVwiKTtcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3RlZEVudHJ5Q2hhbmdlZC5maXJlKGVudHJpZXMsIG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLnNldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoZW50cnksIGZpcmVFdmVudCwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQgPT09IHZvaWQgMCkgeyBmaXJlRXZlbnQgPSBmYWxzZTsgfVxuICAgICAgICAgICAgaWYgKGVudHJ5ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcubWF4U2VsZWN0ZWRFbnRyaWVzICYmIHRoaXMuc2VsZWN0ZWRFbnRyaWVzLmxlbmd0aCA+PSB0aGlzLmNvbmZpZy5tYXhTZWxlY3RlZEVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuZGlzdGluY3QgJiYgdGhpcy5zZWxlY3RlZEVudHJpZXMubWFwKGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihbZW50cnldKTtcbiAgICAgICAgICAgIH0pLmluZGV4T2YodGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihbZW50cnldKSkgIT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgdGFnID0gJC5leHRlbmQoe30sIGVudHJ5KTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRFbnRyaWVzLnNwbGljZSh0aGlzLiRlZGl0b3IuaW5kZXgoKSwgMCwgdGFnKTtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQudmFsKHRoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24odGhpcy5nZXRTZWxlY3RlZEVudHJpZXMoKSkpO1xuICAgICAgICAgICAgdmFyICRlbnRyeSA9ICQodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeVJlbmRlcmluZ0Z1bmN0aW9uKHRhZykpO1xuICAgICAgICAgICAgdmFyICR0YWdXcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLXRhZ2JveC10YWdcIj48L2Rpdj4nKTtcbiAgICAgICAgICAgICR0YWdXcmFwcGVyLmFwcGVuZCgkZW50cnkpLmluc2VydEJlZm9yZSh0aGlzLiRlZGl0b3IpO1xuICAgICAgICAgICAgdGFnLl90ckVudHJ5RWxlbWVudCA9ICR0YWdXcmFwcGVyO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmVkaXRpbmdNb2RlID09IFwiZWRpdGFibGVcIikge1xuICAgICAgICAgICAgICAgICRlbnRyeS5maW5kKCcudHItcmVtb3ZlLWJ1dHRvbicpLmNsaWNrKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnJlbW92ZVRhZyh0YWcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IudGV4dChcIlwiKTtcbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudHModGhpcy5nZXRTZWxlY3RlZEVudHJpZXMoKSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUucmVwb3NpdGlvbkRyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLnBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICBteTogXCJsZWZ0IHRvcFwiLFxuICAgICAgICAgICAgICAgIGF0OiBcImxlZnQgYm90dG9tXCIsXG4gICAgICAgICAgICAgICAgb2Y6IHRoaXMuJHRhZ0NvbWJvQm94LFxuICAgICAgICAgICAgICAgIGNvbGxpc2lvbjogXCJmbGlwXCIsXG4gICAgICAgICAgICAgICAgdXNpbmc6IGZ1bmN0aW9uIChjYWxjdWxhdGVkUG9zaXRpb24sIGluZm8pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZm8udmVydGljYWwgPT09IFwidG9wXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiR0YWdDb21ib0JveC5yZW1vdmVDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24ucmVtb3ZlQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJHRhZ0NvbWJvQm94LmFkZENsYXNzKFwiZHJvcGRvd24tZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5hZGRDbGFzcyhcImZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGRyb3BEb3duLmNzcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiBjYWxjdWxhdGVkUG9zaXRpb24ubGVmdCArICdweCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IGNhbGN1bGF0ZWRQb3NpdGlvbi50b3AgKyAncHgnXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLndpZHRoKHRoaXMuJHRhZ0NvbWJvQm94LndpZHRoKCkpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLm9wZW5Ecm9wRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0Ryb3BEb3duTmVlZGVkKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5saXN0Qm94RGlydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVMaXN0Qm94RW50cmllcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLiR0YWdDb21ib0JveC5hZGRDbGFzcyhcIm9wZW5cIik7XG4gICAgICAgICAgICAgICAgdGhpcy4kZHJvcERvd24uc2hvdygpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5yZXBvc2l0aW9uRHJvcERvd25TY2hlZHVsZXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duU2NoZWR1bGVyID0gd2luZG93LnNldEludGVydmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLnJlcG9zaXRpb25Ecm9wRG93bigpOyB9LCAxMDAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5jbG9zZURyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kdGFnQ29tYm9Cb3gucmVtb3ZlQ2xhc3MoXCJvcGVuXCIpO1xuICAgICAgICAgICAgdGhpcy4kZHJvcERvd24uaGlkZSgpO1xuICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVwb3NpdGlvbkRyb3BEb3duU2NoZWR1bGVyICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMucmVwb3NpdGlvbkRyb3BEb3duU2NoZWR1bGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVkaXRvclRleHQgPSB0aGlzLiRlZGl0b3IudGV4dCgpLnJlcGxhY2UoU3RyaW5nLmZyb21DaGFyQ29kZSgxNjApLCBcIiBcIik7XG4gICAgICAgICAgICB2YXIgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgaWYgKHNlbGVjdGlvbi5hbmNob3JPZmZzZXQgIT0gc2VsZWN0aW9uLmZvY3VzT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVkaXRvclRleHQuc3Vic3RyaW5nKDAsIE1hdGgubWluKHdpbmRvdy5nZXRTZWxlY3Rpb24oKS5iYXNlT2Zmc2V0LCB3aW5kb3cuZ2V0U2VsZWN0aW9uKCkuZm9jdXNPZmZzZXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBlZGl0b3JUZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLmF1dG9Db21wbGV0ZUlmUG9zc2libGUgPSBmdW5jdGlvbiAoZGVsYXkpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuYXV0b0NvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuYXV0b0NvbXBsZXRlVGltZW91dElkKTtcbiAgICAgICAgICAgICAgICB2YXIgaGlnaGxpZ2h0ZWRFbnRyeV8xID0gdGhpcy5saXN0Qm94LmdldEhpZ2hsaWdodGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICBpZiAoaGlnaGxpZ2h0ZWRFbnRyeV8xICYmICF0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmF1dG9Db21wbGV0ZVRpbWVvdXRJZCA9IHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjdXJyZW50RWRpdG9yVmFsdWUgPSBfdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXV0b0NvbXBsZXRlU3RyaW5nID0gX3RoaXMuY29uZmlnLmF1dG9Db21wbGV0ZUZ1bmN0aW9uKGN1cnJlbnRFZGl0b3JWYWx1ZSwgaGlnaGxpZ2h0ZWRFbnRyeV8xKSB8fCBjdXJyZW50RWRpdG9yVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnRleHQoY3VycmVudEVkaXRvclZhbHVlICsgYXV0b0NvbXBsZXRlU3RyaW5nLnJlcGxhY2UoJyAnLCBTdHJpbmcuZnJvbUNoYXJDb2RlKDE2MCkpLnN1YnN0cihjdXJyZW50RWRpdG9yVmFsdWUubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5yZXBvc2l0aW9uRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJpdmlhbENvcmVfMS5zZWxlY3RFbGVtZW50Q29udGVudHMoX3RoaXMuJGVkaXRvclswXSwgY3VycmVudEVkaXRvclZhbHVlLmxlbmd0aCwgYXV0b0NvbXBsZXRlU3RyaW5nLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0sIGRlbGF5IHx8IDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLmlzRHJvcERvd25OZWVkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lZGl0aW5nTW9kZSA9PSAnZWRpdGFibGUnICYmICh0aGlzLmNvbmZpZy5lbnRyaWVzICYmIHRoaXMuY29uZmlnLmVudHJpZXMubGVuZ3RoID4gMCB8fCAhdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uIHx8IHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5zZXRFZGl0aW5nTW9kZSA9IGZ1bmN0aW9uIChuZXdFZGl0aW5nTW9kZSkge1xuICAgICAgICAgICAgdGhpcy5lZGl0aW5nTW9kZSA9IG5ld0VkaXRpbmdNb2RlO1xuICAgICAgICAgICAgdGhpcy4kdGFnQ29tYm9Cb3gucmVtb3ZlQ2xhc3MoXCJlZGl0YWJsZSByZWFkb25seSBkaXNhYmxlZFwiKS5hZGRDbGFzcyh0aGlzLmVkaXRpbmdNb2RlKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25OZWVkZWQoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duVGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUuc2V0U2VsZWN0ZWRFbnRyaWVzID0gZnVuY3Rpb24gKGVudHJpZXMpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cmllc1xuICAgICAgICAgICAgICAgIC5zbGljZSgpXG4gICAgICAgICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLnJlbW92ZVRhZyhlKTsgfSk7XG4gICAgICAgICAgICBpZiAoZW50cmllcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkoZW50cmllc1tpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLmdldFNlbGVjdGVkRW50cmllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxlY3RlZEVudHJpZXNUb1JldHVybiA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnNlbGVjdGVkRW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBzZWxlY3RlZEVudHJ5VG9SZXR1cm4gPSAkLmV4dGVuZCh7fSwgdGhpcy5zZWxlY3RlZEVudHJpZXNbaV0pO1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlUb1JldHVybi5fdHJFbnRyeUVsZW1lbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyaWVzVG9SZXR1cm4ucHVzaChzZWxlY3RlZEVudHJ5VG9SZXR1cm4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNlbGVjdGVkRW50cmllc1RvUmV0dXJuO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUuZm9jdXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgIFRyaXZpYWxDb3JlXzEuc2VsZWN0RWxlbWVudENvbnRlbnRzKHRoaXMuJGVkaXRvclswXSwgMCwgdGhpcy4kZWRpdG9yLnRleHQoKS5sZW5ndGgpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUYWdDb21ib0JveC5wcm90b3R5cGUuZ2V0RWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGVkaXRvclswXTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRhZ0NvbWJvQm94LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC5yZW1vdmVDbGFzcygndHItb3JpZ2luYWwtaW5wdXQnKS5pbnNlcnRCZWZvcmUodGhpcy4kdGFnQ29tYm9Cb3gpO1xuICAgICAgICAgICAgdGhpcy4kdGFnQ29tYm9Cb3gucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5yZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVGFnQ29tYm9Cb3gucHJvdG90eXBlLmdldE1haW5Eb21FbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJHRhZ0NvbWJvQm94WzBdO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJpdmlhbFRhZ0NvbWJvQm94O1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsVGFnQ29tYm9Cb3ggPSBUcml2aWFsVGFnQ29tYm9Cb3g7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIHsgICB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgPSB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMgfHwge307ICBmYWN0b3J5KGZ1bmN0aW9uKG5hbWUpIHsgICAgaWYgKG5hbWUgPT09IFwianF1ZXJ5XCIpIHsgICAgICByZXR1cm4gd2luZG93LmpRdWVyeTsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcImxldmVuc2h0ZWluXCIpIHsgICAgICByZXR1cm4gd2luZG93LkxldmVuc2h0ZWluOyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibW9tZW50XCIpIHsgICAgICByZXR1cm4gd2luZG93Lm1vbWVudDsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm11c3RhY2hlXCIpIHsgICAgICByZXR1cm4gd2luZG93Lk11c3RhY2hlOyAgICB9IGVsc2UgeyAgICAgIHJldHVybiB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHM7ICAgIH0gIH0sIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyk7fVxufSkoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdmFyIFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZSgpIHtcbiAgICAgICAgfVxuICAgICAgICBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUucHJvdG90eXBlLmdlbmVyYXRlU3VnZ2VzdGlvbnMgPSBmdW5jdGlvbiAoc2VhcmNoU3RyaW5nKSB7XG4gICAgICAgICAgICB2YXIgc3VnZ2VzdGlvbnMgPSBbXTtcbiAgICAgICAgICAgIHZhciBtYXRjaCA9IHNlYXJjaFN0cmluZy5tYXRjaCgvW15cXGRdLyk7XG4gICAgICAgICAgICB2YXIgY29sb25JbmRleCA9IG1hdGNoICE9IG51bGwgPyBtYXRjaC5pbmRleCA6IG51bGw7XG4gICAgICAgICAgICBpZiAoY29sb25JbmRleCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHZhciBob3VyU3RyaW5nID0gc2VhcmNoU3RyaW5nLnN1YnN0cmluZygwLCBjb2xvbkluZGV4KTtcbiAgICAgICAgICAgICAgICB2YXIgbWludXRlU3RyaW5nID0gc2VhcmNoU3RyaW5nLnN1YnN0cmluZyhjb2xvbkluZGV4ICsgMSk7XG4gICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSBzdWdnZXN0aW9ucy5jb25jYXQoVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVRpbWVTdWdnZXN0aW9ucyhUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlSG91clN1Z2dlc3Rpb25zKGhvdXJTdHJpbmcpLCBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlTWludXRlU3VnZ2VzdGlvbnMobWludXRlU3RyaW5nKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoc2VhcmNoU3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VhcmNoU3RyaW5nLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBob3VyU3RyaW5nXzEgPSBzZWFyY2hTdHJpbmcuc3Vic3RyKDAsIDIpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWludXRlU3RyaW5nXzEgPSBzZWFyY2hTdHJpbmcuc3Vic3RyaW5nKDIsIHNlYXJjaFN0cmluZy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBzdWdnZXN0aW9ucyA9IHN1Z2dlc3Rpb25zLmNvbmNhdChUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlVGltZVN1Z2dlc3Rpb25zKFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVIb3VyU3VnZ2VzdGlvbnMoaG91clN0cmluZ18xKSwgVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZU1pbnV0ZVN1Z2dlc3Rpb25zKG1pbnV0ZVN0cmluZ18xKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgaG91clN0cmluZyA9IHNlYXJjaFN0cmluZy5zdWJzdHIoMCwgMSk7XG4gICAgICAgICAgICAgICAgdmFyIG1pbnV0ZVN0cmluZyA9IHNlYXJjaFN0cmluZy5zdWJzdHJpbmcoMSwgc2VhcmNoU3RyaW5nLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgaWYgKG1pbnV0ZVN0cmluZy5sZW5ndGggPD0gMikge1xuICAgICAgICAgICAgICAgICAgICBzdWdnZXN0aW9ucyA9IHN1Z2dlc3Rpb25zLmNvbmNhdChUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlVGltZVN1Z2dlc3Rpb25zKFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVIb3VyU3VnZ2VzdGlvbnMoaG91clN0cmluZyksIFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVNaW51dGVTdWdnZXN0aW9ucyhtaW51dGVTdHJpbmcpKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSBzdWdnZXN0aW9ucy5jb25jYXQoVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZVRpbWVTdWdnZXN0aW9ucyhUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuaW50UmFuZ2UoNiwgMjQpLmNvbmNhdChUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuaW50UmFuZ2UoMSwgNSkpLCBbMF0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdWdnZXN0aW9ucztcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmludFJhbmdlID0gZnVuY3Rpb24gKGZyb21JbmNsdXNpdmUsIHRvSW5jbHVzaXZlKSB7XG4gICAgICAgICAgICB2YXIgaW50cyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IGZyb21JbmNsdXNpdmU7IGkgPD0gdG9JbmNsdXNpdmU7IGkrKykge1xuICAgICAgICAgICAgICAgIGludHMucHVzaChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpbnRzO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuY3JlYXRlVGltZVN1Z2dlc3Rpb25zID0gZnVuY3Rpb24gKGhvdXJWYWx1ZXMsIG1pbnV0ZVZhbHVlcykge1xuICAgICAgICAgICAgdmFyIGVudHJpZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaG91clZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBob3VyID0gaG91clZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1pbnV0ZVZhbHVlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWludXRlID0gbWludXRlVmFsdWVzW2pdO1xuICAgICAgICAgICAgICAgICAgICBlbnRyaWVzLnB1c2goeyBob3VyOiBob3VyLCBtaW51dGU6IG1pbnV0ZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZW50cmllcztcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lLmNyZWF0ZU1pbnV0ZVN1Z2dlc3Rpb25zID0gZnVuY3Rpb24gKG1pbnV0ZVN0cmluZykge1xuICAgICAgICAgICAgdmFyIG0gPSBwYXJzZUludChtaW51dGVTdHJpbmcpO1xuICAgICAgICAgICAgaWYgKGlzTmFOKG0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFswXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG1pbnV0ZVN0cmluZy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFttICUgNjBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobSA8IDYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW20gKiAxMF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW20gJSA2MF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZS5jcmVhdGVIb3VyU3VnZ2VzdGlvbnMgPSBmdW5jdGlvbiAoaG91clN0cmluZykge1xuICAgICAgICAgICAgdmFyIGggPSBwYXJzZUludChob3VyU3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChpc05hTihoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmUuaW50UmFuZ2UoMSwgMjQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaCA8IDEyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtoLCAoaCArIDEyKSAlIDI0XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGggPD0gMjQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW2ggJSAyNF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBUcml2aWFsVGltZVN1Z2dlc3Rpb25FbmdpbmU7XG4gICAgfSgpKTtcbiAgICBleHBvcnRzLlRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZSA9IFRyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZTtcbn0pO1xuXG5cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwianF1ZXJ5XCIsIFwibXVzdGFjaGVcIiwgXCIuL1RyaXZpYWxUcmVlQm94XCIsIFwiLi9Ucml2aWFsQ29yZVwiLCBcIi4vVHJpdmlhbEV2ZW50XCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIE11c3RhY2hlID0gcmVxdWlyZShcIm11c3RhY2hlXCIpO1xuICAgIHZhciBUcml2aWFsVHJlZUJveF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbFRyZWVCb3hcIik7XG4gICAgdmFyIFRyaXZpYWxDb3JlXzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsQ29yZVwiKTtcbiAgICB2YXIgVHJpdmlhbEV2ZW50XzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsRXZlbnRcIik7XG4gICAgdmFyIFRyaXZpYWxUcmVlID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gVHJpdmlhbFRyZWUob3JpZ2luYWxJbnB1dCwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbk5vZGVFeHBhbnNpb25TdGF0ZUNoYW5nZWQgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSAkKCk7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgICAgICB2YWx1ZUZ1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHsgcmV0dXJuIGVudHJ5ID8gXCJcIiArIGVudHJ5LmlkIDogbnVsbDsgfSxcbiAgICAgICAgICAgICAgICBjaGlsZHJlblByb3BlcnR5OiBcImNoaWxkcmVuXCIsXG4gICAgICAgICAgICAgICAgbGF6eUNoaWxkcmVuRmxhZ1Byb3BlcnR5OiBcImhhc0xhenlDaGlsZHJlblwiLFxuICAgICAgICAgICAgICAgIHNlYXJjaEJhck1vZGU6ICdzaG93LWlmLWZpbGxlZCcsXG4gICAgICAgICAgICAgICAgbGF6eUNoaWxkcmVuUXVlcnlGdW5jdGlvbjogZnVuY3Rpb24gKG5vZGUsIHJlc3VsdENhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdENhbGxiYWNrKFtdKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGV4cGFuZGVkUHJvcGVydHk6ICdleHBhbmRlZCcsXG4gICAgICAgICAgICAgICAgZW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5LCBkZXB0aCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGVmYXVsdFRlbXBsYXRlcyA9IFtUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmljb24yTGluZXNUZW1wbGF0ZSwgVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5pY29uU2luZ2xlTGluZVRlbXBsYXRlXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRlbXBsYXRlID0gZW50cnkudGVtcGxhdGUgfHwgZGVmYXVsdFRlbXBsYXRlc1tNYXRoLm1pbihkZXB0aCwgZGVmYXVsdFRlbXBsYXRlcy5sZW5ndGggLSAxKV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNdXN0YWNoZS5yZW5kZXIodGVtcGxhdGUsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNwaW5uZXJUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0U3Bpbm5lclRlbXBsYXRlLFxuICAgICAgICAgICAgICAgIG5vRW50cmllc1RlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHROb0VudHJpZXNUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICBlbnRyaWVzOiBudWxsLFxuICAgICAgICAgICAgICAgIHF1ZXJ5RnVuY3Rpb246IG51bGwsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeUlkOiBudWxsLFxuICAgICAgICAgICAgICAgIG1hdGNoaW5nT3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ01vZGU6ICdjb250YWlucycsXG4gICAgICAgICAgICAgICAgICAgIGlnbm9yZUNhc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGRpcmVjdFNlbGVjdGlvblZpYUFycm93S2V5czogZmFsc2UsXG4gICAgICAgICAgICAgICAgcGVyZm9ybWFuY2VPcHRpbWl6YXRpb25TZXR0aW5nczoge1xuICAgICAgICAgICAgICAgICAgICB0b01hbnlWaXNpYmxlSXRlbXNSZW5kZXJEZWxheTogNzUwLFxuICAgICAgICAgICAgICAgICAgICB0b01hbnlWaXNpYmxlSXRlbXNUaHJlc2hvbGQ6IDc1XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLnF1ZXJ5RnVuY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uID0gVHJpdmlhbENvcmVfMS5kZWZhdWx0VHJlZVF1ZXJ5RnVuY3Rpb25GYWN0b3J5KHRoaXMuY29uZmlnLmVudHJpZXMgfHwgW10sIFRyaXZpYWxDb3JlXzEuZGVmYXVsdEVudHJ5TWF0Y2hpbmdGdW5jdGlvbkZhY3RvcnkoW1wiZGlzcGxheVZhbHVlXCIsIFwiYWRkaXRpb25hbEluZm9cIl0sIHRoaXMuY29uZmlnLm1hdGNoaW5nT3B0aW9ucyksIHRoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHksIHRoaXMuY29uZmlnLmV4cGFuZGVkUHJvcGVydHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gdGhpcy5jb25maWcuZW50cmllcztcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQgPSAkKG9yaWdpbmFsSW5wdXQpLmFkZENsYXNzKFwidHItb3JpZ2luYWwtaW5wdXRcIik7XG4gICAgICAgICAgICB0aGlzLiRjb21wb25lbnRXcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyZWVcIiB0YWJpbmRleD1cIjBcIi8+JykuaW5zZXJ0QWZ0ZXIodGhpcy4kb3JpZ2luYWxJbnB1dCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuc2VhcmNoQmFyTW9kZSAhPT0gJ2Fsd2F5cy12aXNpYmxlJykge1xuICAgICAgICAgICAgICAgIHRoaXMuJGNvbXBvbmVudFdyYXBwZXIuYWRkQ2xhc3MoXCJoaWRlLXNlYXJjaGZpZWxkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kY29tcG9uZW50V3JhcHBlci5rZXlkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy50YWIgfHwgVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5pc01vZGlmaWVyS2V5KGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IuaXMoJzp2aXNpYmxlJykgJiYgVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5zcGVjaWFsS2V5cy5pbmRleE9mKGUud2hpY2gpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmRvd25fYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpcmVjdGlvbiA9IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy51cF9hcnJvdyA/IC0xIDogMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmVudHJpZXMgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5kaXJlY3RTZWxlY3Rpb25WaWFBcnJvd0tleXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy50cmVlQm94LnNlbGVjdE5leHRFbnRyeShkaXJlY3Rpb24sIGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMudHJlZUJveC5oaWdobGlnaHROZXh0RW50cnkoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMubGVmdF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudHJlZUJveC5zZXRIaWdobGlnaHRlZE5vZGVFeHBhbmRlZChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMucmlnaHRfYXJyb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudHJlZUJveC5zZXRTZWxlY3RlZEVudHJ5KF90aGlzLnRyZWVCb3guZ2V0SGlnaGxpZ2h0ZWRFbnRyeSgpLCBlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVzY2FwZSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnZhbChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGNvbXBvbmVudFdyYXBwZXIuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yID0gJCgnPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJ0ci10cmVlLWVkaXRvciB0ci1lZGl0b3JcIi8+JylcbiAgICAgICAgICAgICAgICAucHJlcGVuZFRvKHRoaXMuJGNvbXBvbmVudFdyYXBwZXIpXG4gICAgICAgICAgICAgICAgLmF0dHIoXCJ0YWJpbmRleFwiLCB0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCItMVwiKSlcbiAgICAgICAgICAgICAgICAuZm9jdXMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLiRjb21wb25lbnRXcmFwcGVyLmFkZENsYXNzKCdmb2N1cycpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuYmx1cihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuJGNvbXBvbmVudFdyYXBwZXIucmVtb3ZlQ2xhc3MoJ2ZvY3VzJyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5rZXlkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5sZWZ0X2Fycm93IHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hhbmdlZEV4cGFuZGVkU3RhdGUgPSBfdGhpcy50cmVlQm94LnNldEhpZ2hsaWdodGVkTm9kZUV4cGFuZGVkKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGFuZ2VkRXhwYW5kZWRTdGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAub24oJ2tleXVwIGNoYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLnNlYXJjaEJhck1vZGUgPT09ICdzaG93LWlmLWZpbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IudmFsKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRjb21wb25lbnRXcmFwcGVyLnJlbW92ZUNsYXNzKCdoaWRlLXNlYXJjaGZpZWxkJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kY29tcG9uZW50V3JhcHBlci5hZGRDbGFzcygnaGlkZS1zZWFyY2hmaWVsZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuc2VhcmNoQmFyTW9kZSA9PT0gJ25vbmUnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmNzcyhcImRpc3BsYXlcIiwgXCJub25lXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInBsYWNlaG9sZGVyXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmF0dHIoXCJwbGFjZWhvbGRlclwiLCB0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJwbGFjZWhvbGRlclwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRjb21wb25lbnRXcmFwcGVyLmF0dHIoXCJ0YWJpbmRleFwiLCB0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJ0YWJpbmRleFwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwiYXV0b2ZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY29tcG9uZW50V3JhcHBlci5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy50cmVlQm94ID0gbmV3IFRyaXZpYWxUcmVlQm94XzEuVHJpdmlhbFRyZWVCb3godGhpcy4kY29tcG9uZW50V3JhcHBlciwgdGhpcy5jb25maWcpO1xuICAgICAgICAgICAgdGhpcy50cmVlQm94Lm9uTm9kZUV4cGFuc2lvblN0YXRlQ2hhbmdlZC5hZGRMaXN0ZW5lcihmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLm9uTm9kZUV4cGFuc2lvblN0YXRlQ2hhbmdlZC5maXJlKG5vZGUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3gub25TZWxlY3RlZEVudHJ5Q2hhbmdlZC5hZGRMaXN0ZW5lcihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkVHJlZUJveEVudHJ5ID0gX3RoaXMudHJlZUJveC5nZXRTZWxlY3RlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkVHJlZUJveEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoc2VsZWN0ZWRUcmVlQm94RW50cnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXRTZWxlY3RlZEVudHJ5KCh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5SWQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5SWQgIT09IG51bGwpID8gdGhpcy5maW5kRW50cnlCeUlkKHRoaXMuY29uZmlnLnNlbGVjdGVkRW50cnlJZCkgOiBudWxsKTtcbiAgICAgICAgfVxuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUudXBkYXRlRW50cmllcyA9IGZ1bmN0aW9uIChuZXdFbnRyaWVzKSB7XG4gICAgICAgICAgICB0aGlzLmVudHJpZXMgPSBuZXdFbnRyaWVzO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycyA9ICQoKTtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC51cGRhdGVFbnRyaWVzKG5ld0VudHJpZXMpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUucXVlcnkgPSBmdW5jdGlvbiAoaGlnaGxpZ2h0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNlYXJjaEJhck1vZGUgPT09ICdhbHdheXMtdmlzaWJsZScgfHwgdGhpcy5jb25maWcuc2VhcmNoQmFyTW9kZSA9PT0gJ3Nob3ctaWYtZmlsbGVkJykge1xuICAgICAgICAgICAgICAgIHZhciAkc3Bpbm5lciA9ICQodGhpcy5jb25maWcuc3Bpbm5lclRlbXBsYXRlKS5hcHBlbmRUbyh0aGlzLnRyZWVCb3guZ2V0TWFpbkRvbUVsZW1lbnQoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSB0aGlzLiRzcGlubmVycy5hZGQoJHNwaW5uZXIpO1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbihfdGhpcy4kZWRpdG9yLnZhbCgpLCBmdW5jdGlvbiAobmV3RW50cmllcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb2Nlc3NVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRW50cmllcyhuZXdFbnRyaWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGVkaXRvci52YWwoKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3guaGlnaGxpZ2h0VGV4dE1hdGNoZXMoX3RoaXMuJGVkaXRvci52YWwoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLmRpcmVjdFNlbGVjdGlvblZpYUFycm93S2V5cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMudHJlZUJveC5oaWdobGlnaHROZXh0TWF0Y2hpbmdFbnRyeShoaWdobGlnaHREaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3gucmV2ZWFsU2VsZWN0ZWRFbnRyeSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChfdGhpcy5wcm9jZXNzVXBkYXRlVGltZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvdW50VmlzaWJsZUVudHJpZXMobmV3RW50cmllcykgPCBfdGhpcy5jb25maWcucGVyZm9ybWFuY2VPcHRpbWl6YXRpb25TZXR0aW5ncy50b01hbnlWaXNpYmxlSXRlbXNUaHJlc2hvbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5wcm9jZXNzVXBkYXRlVGltZXIgPSB3aW5kb3cuc2V0VGltZW91dChwcm9jZXNzVXBkYXRlLCBfdGhpcy5jb25maWcucGVyZm9ybWFuY2VPcHRpbWl6YXRpb25TZXR0aW5ncy50b01hbnlWaXNpYmxlSXRlbXNSZW5kZXJEZWxheSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUuY291bnRWaXNpYmxlRW50cmllcyA9IGZ1bmN0aW9uIChlbnRyaWVzKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIGNvdW50VmlzaWJsZUNoaWxkcmVuQW5kU2VsZiA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbX3RoaXMuY29uZmlnLmV4cGFuZGVkUHJvcGVydHldICYmIG5vZGVbX3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XS5tYXAoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY291bnRWaXNpYmxlQ2hpbGRyZW5BbmRTZWxmKGVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgfSkucmVkdWNlKGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYSArIGI7XG4gICAgICAgICAgICAgICAgICAgIH0sIDApICsgMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gZW50cmllcy5tYXAoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvdW50VmlzaWJsZUNoaWxkcmVuQW5kU2VsZihlbnRyeSk7XG4gICAgICAgICAgICB9KS5yZWR1Y2UoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSArIGI7XG4gICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLmZpbmRFbnRyaWVzID0gZnVuY3Rpb24gKGZpbHRlckZ1bmN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIGZpbmRFbnRyaWVzSW5TdWJUcmVlID0gZnVuY3Rpb24gKG5vZGUsIGxpc3RPZkZvdW5kRW50cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChmaWx0ZXJGdW5jdGlvbi5jYWxsKF90aGlzLCBub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0T2ZGb3VuZEVudHJpZXMucHVzaChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbX3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IG5vZGVbX3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgZmluZEVudHJpZXNJblN1YlRyZWUoY2hpbGQsIGxpc3RPZkZvdW5kRW50cmllcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIG1hdGNoaW5nRW50cmllcyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcm9vdEVudHJ5ID0gdGhpcy5lbnRyaWVzW2ldO1xuICAgICAgICAgICAgICAgIGZpbmRFbnRyaWVzSW5TdWJUcmVlKHJvb3RFbnRyeSwgbWF0Y2hpbmdFbnRyaWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXRjaGluZ0VudHJpZXM7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5maW5kRW50cnlCeUlkID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluZEVudHJpZXMoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKGVudHJ5KSA9PT0gaWQudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH0pWzBdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUuc2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEVudHJ5SWQgPSBlbnRyeSA/IHRoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24oZW50cnkpIDogbnVsbDtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQudmFsKGVudHJ5ID8gdGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihlbnRyeSkgOiBudWxsKTtcbiAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50cyhlbnRyeSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5maXJlQ2hhbmdlRXZlbnRzID0gZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLiRjb21wb25lbnRXcmFwcGVyLnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuZmlyZShlbnRyeSk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5nZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy50cmVlQm94LmdldFNlbGVjdGVkRW50cnkoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUudXBkYXRlQ2hpbGRyZW4gPSBmdW5jdGlvbiAocGFyZW50Tm9kZUlkLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgdGhpcy50cmVlQm94LnVwZGF0ZUNoaWxkcmVuKHBhcmVudE5vZGVJZCwgY2hpbGRyZW4pO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS51cGRhdGVOb2RlID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC51cGRhdGVOb2RlKG5vZGUpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5yZW1vdmVOb2RlID0gZnVuY3Rpb24gKG5vZGVJZCkge1xuICAgICAgICAgICAgdGhpcy50cmVlQm94LnJlbW92ZU5vZGUobm9kZUlkKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZS5wcm90b3R5cGUuYWRkTm9kZSA9IGZ1bmN0aW9uIChwYXJlbnROb2RlSWQsIG5vZGUpIHtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC5hZGROb2RlKHBhcmVudE5vZGVJZCwgbm9kZSk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLnNlbGVjdE5vZGVCeUlkID0gZnVuY3Rpb24gKG5vZGVJZCkge1xuICAgICAgICAgICAgdGhpcy50cmVlQm94LnNldFNlbGVjdGVkRW50cnlCeUlkKG5vZGVJZCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWUucHJvdG90eXBlLmdldEVkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRlZGl0b3JbMF07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC5yZW1vdmVDbGFzcygndHItb3JpZ2luYWwtaW5wdXQnKS5pbnNlcnRCZWZvcmUodGhpcy4kY29tcG9uZW50V3JhcHBlcik7XG4gICAgICAgICAgICB0aGlzLiRjb21wb25lbnRXcmFwcGVyLnJlbW92ZSgpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlLnByb3RvdHlwZS5nZXRNYWluRG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRjb21wb25lbnRXcmFwcGVyWzBdO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJpdmlhbFRyZWU7XG4gICAgfSgpKTtcbiAgICBleHBvcnRzLlRyaXZpYWxUcmVlID0gVHJpdmlhbFRyZWU7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIm11c3RhY2hlXCIsIFwiLi9Ucml2aWFsQ29yZVwiLCBcIi4vVHJpdmlhbEV2ZW50XCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIE11c3RhY2hlID0gcmVxdWlyZShcIm11c3RhY2hlXCIpO1xuICAgIHZhciBUcml2aWFsQ29yZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENvcmVcIik7XG4gICAgdmFyIFRyaXZpYWxFdmVudF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbEV2ZW50XCIpO1xuICAgIHZhciBUcml2aWFsVHJlZUJveCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFRyaXZpYWxUcmVlQm94KCRjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbk5vZGVFeHBhbnNpb25TdGF0ZUNoYW5nZWQgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5jb25maWcgPSAkLmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgdmFsdWVGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7IHJldHVybiBlbnRyeSA/IFwiXCIgKyBlbnRyeS5pZCA6IG51bGw7IH0sXG4gICAgICAgICAgICAgICAgY2hpbGRyZW5Qcm9wZXJ0eTogXCJjaGlsZHJlblwiLFxuICAgICAgICAgICAgICAgIGxhenlDaGlsZHJlbkZsYWdQcm9wZXJ0eTogXCJoYXNMYXp5Q2hpbGRyZW5cIixcbiAgICAgICAgICAgICAgICBsYXp5Q2hpbGRyZW5RdWVyeUZ1bmN0aW9uOiBmdW5jdGlvbiAobm9kZSwgcmVzdWx0Q2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0Q2FsbGJhY2sobm9kZS5jaGlsZHJlbiB8fCBbXSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBleHBhbmRlZFByb3BlcnR5OiAnZXhwYW5kZWQnLFxuICAgICAgICAgICAgICAgIGVudHJ5UmVuZGVyaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlbnRyeSwgZGVwdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRlZmF1bHRUZW1wbGF0ZXMgPSBbVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5pY29uMkxpbmVzVGVtcGxhdGUsIFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuaWNvblNpbmdsZUxpbmVUZW1wbGF0ZV07XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IGVudHJ5LnRlbXBsYXRlIHx8IGRlZmF1bHRUZW1wbGF0ZXNbTWF0aC5taW4oZGVwdGgsIGRlZmF1bHRUZW1wbGF0ZXMubGVuZ3RoIC0gMSldO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTXVzdGFjaGUucmVuZGVyKHRlbXBsYXRlLCBlbnRyeSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzcGlubmVyVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdFNwaW5uZXJUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICBub0VudHJpZXNUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0Tm9FbnRyaWVzVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgZW50cmllczogbnVsbCxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJ5SWQ6IG51bGwsXG4gICAgICAgICAgICAgICAgbWF0Y2hpbmdPcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoaW5nTW9kZTogJ2NvbnRhaW5zJyxcbiAgICAgICAgICAgICAgICAgICAgaWdub3JlQ2FzZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWF4TGV2ZW5zaHRlaW5EaXN0YW5jZTogMlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYW5pbWF0aW9uRHVyYXRpb246IDcwLFxuICAgICAgICAgICAgICAgIHNob3dFeHBhbmRlcnM6IHRydWUsXG4gICAgICAgICAgICAgICAgb3Blbk9uU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBlbmZvcmNlU2luZ2xlRXhwYW5kZWRQYXRoOiBmYWxzZVxuICAgICAgICAgICAgfSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmVudHJpZXMgPSB0aGlzLmNvbmZpZy5lbnRyaWVzO1xuICAgICAgICAgICAgdGhpcy4kY29tcG9uZW50V3JhcHBlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmVlYm94XCIvPicpLmFwcGVuZFRvKCRjb250YWluZXIpO1xuICAgICAgICAgICAgdGhpcy4kY29tcG9uZW50V3JhcHBlci50b2dnbGVDbGFzcyhcImhpZGUtZXhwYW5kZXJzXCIsICF0aGlzLmNvbmZpZy5zaG93RXhwYW5kZXJzKTtcbiAgICAgICAgICAgIHRoaXMuJHRyZWUgPSAkKCc8ZGl2IGNsYXNzPVwidHItdHJlZS1lbnRyeVRyZWVcIj48L2Rpdj4nKS5hcHBlbmRUbyh0aGlzLiRjb21wb25lbnRXcmFwcGVyKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUVudHJpZXModGhpcy5lbnRyaWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0ZWRFbnRyeSgodGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeUlkICE9PSB1bmRlZmluZWQgJiYgdGhpcy5jb25maWcuc2VsZWN0ZWRFbnRyeUlkICE9PSBudWxsKSA/IHRoaXMuZmluZEVudHJ5QnlJZCh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5SWQpIDogbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmlzTGVhZiA9IGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgcmV0dXJuIChlbnRyeVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSA9PSBudWxsIHx8IGVudHJ5W3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldLmxlbmd0aCA9PSAwKSAmJiAhZW50cnlbdGhpcy5jb25maWcubGF6eUNoaWxkcmVuRmxhZ1Byb3BlcnR5XTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmNyZWF0ZUVudHJ5RWxlbWVudCA9IGZ1bmN0aW9uIChlbnRyeSwgZGVwdGgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgbGVhZiA9IHRoaXMuaXNMZWFmKGVudHJ5KTtcbiAgICAgICAgICAgIHZhciAkb3V0ZXJFbnRyeVdyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItdHJlZS1lbnRyeS1vdXRlci13cmFwcGVyICcgKyAobGVhZiA/ICcnIDogJ2hhcy1jaGlsZHJlbicpICsgJ1wiIGRhdGEtZGVwdGg9XCInICsgZGVwdGggKyAnXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgICBlbnRyeS5fdHJFbnRyeUVsZW1lbnQgPSAkb3V0ZXJFbnRyeVdyYXBwZXI7XG4gICAgICAgICAgICB2YXIgJGVudHJ5QW5kRXhwYW5kZXJXcmFwcGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyZWUtZW50cnktYW5kLWV4cGFuZGVyLXdyYXBwZXJcIj48L2Rpdj4nKVxuICAgICAgICAgICAgICAgIC5hcHBlbmRUbygkb3V0ZXJFbnRyeVdyYXBwZXIpO1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBkZXB0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgJGVudHJ5QW5kRXhwYW5kZXJXcmFwcGVyLmFwcGVuZCgnPGRpdiBjbGFzcz1cInRyLWluZGVudC1zcGFjZXJcIi8+Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgJGV4cGFuZGVyID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyZWUtZXhwYW5kZXJcIj48L2Rpdj4nKVxuICAgICAgICAgICAgICAgIC5hcHBlbmRUbygkZW50cnlBbmRFeHBhbmRlcldyYXBwZXIpO1xuICAgICAgICAgICAgdmFyICRlbnRyeSA9ICQodGhpcy5jb25maWcuZW50cnlSZW5kZXJpbmdGdW5jdGlvbihlbnRyeSwgZGVwdGgpKTtcbiAgICAgICAgICAgICRlbnRyeS5hZGRDbGFzcyhcInRyLXRyZWUtZW50cnkgZmlsdGVyYWJsZS1pdGVtXCIpLmFwcGVuZFRvKCRlbnRyeUFuZEV4cGFuZGVyV3JhcHBlcik7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihlbnRyeSkgPT09IHRoaXMuc2VsZWN0ZWRFbnRyeUlkKSB7XG4gICAgICAgICAgICAgICAgJGVudHJ5QW5kRXhwYW5kZXJXcmFwcGVyLmFkZENsYXNzKFwidHItc2VsZWN0ZWQtZW50cnlcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkZW50cnlBbmRFeHBhbmRlcldyYXBwZXJcbiAgICAgICAgICAgICAgICAubW91c2Vkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuJGNvbXBvbmVudFdyYXBwZXIudHJpZ2dlcihcIm1vdXNlZG93blwiLCBlKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KGVudHJ5KTtcbiAgICAgICAgICAgIH0pLm1vdXNldXAoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy4kY29tcG9uZW50V3JhcHBlci50cmlnZ2VyKFwibW91c2V1cFwiLCBlKTtcbiAgICAgICAgICAgIH0pLm1vdXNlZW50ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNldEhpZ2hsaWdodGVkRW50cnkoZW50cnkpO1xuICAgICAgICAgICAgfSkubW91c2VsZWF2ZShmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmICghJChlLnRvRWxlbWVudCkuaXMoJy50ci10cmVlLWVudHJ5LW91dGVyLXdyYXBwZXInKSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRIaWdobGlnaHRlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCFsZWFmKSB7XG4gICAgICAgICAgICAgICAgdmFyICRjaGlsZHJlbldyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItdHJlZS1lbnRyeS1jaGlsZHJlbi13cmFwcGVyXCI+PC9kaXY+JylcbiAgICAgICAgICAgICAgICAgICAgLmFwcGVuZFRvKCRvdXRlckVudHJ5V3JhcHBlcik7XG4gICAgICAgICAgICAgICAgJGV4cGFuZGVyLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9KS5jbGljayhmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXROb2RlRXhwYW5kZWQoZW50cnksICFlbnRyeVtfdGhpcy5jb25maWcuZXhwYW5kZWRQcm9wZXJ0eV0sIHRydWUpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChlbnRyeVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnlbdGhpcy5jb25maWcuZXhwYW5kZWRQcm9wZXJ0eV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW50cnlbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUVudHJ5RWxlbWVudChlbnRyeVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XVtpXSwgZGVwdGggKyAxKS5hcHBlbmRUbygkY2hpbGRyZW5XcmFwcGVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlbnRyeVt0aGlzLmNvbmZpZy5sYXp5Q2hpbGRyZW5GbGFnUHJvcGVydHldKSB7XG4gICAgICAgICAgICAgICAgICAgICRjaGlsZHJlbldyYXBwZXIuaGlkZSgpLmFwcGVuZCh0aGlzLmNvbmZpZy5zcGlubmVyVGVtcGxhdGUpLmZhZGVJbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnNldE5vZGVFeHBhbmRlZChlbnRyeSwgZW50cnlbdGhpcy5jb25maWcuZXhwYW5kZWRQcm9wZXJ0eV0sIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAkb3V0ZXJFbnRyeVdyYXBwZXI7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS51cGRhdGVUcmVlRW50cnlFbGVtZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJHRyZWUuZGV0YWNoKCk7XG4gICAgICAgICAgICB0aGlzLiR0cmVlID0gJCgnPGRpdiBjbGFzcz1cInRyLXRyZWUtZW50cnlUcmVlXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgICBpZiAodGhpcy5lbnRyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZW50cmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUVudHJ5RWxlbWVudCh0aGlzLmVudHJpZXNbaV0sIDApLmFwcGVuZFRvKHRoaXMuJHRyZWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuJHRyZWUuYXBwZW5kKHRoaXMuY29uZmlnLm5vRW50cmllc1RlbXBsYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJHRyZWUuYXBwZW5kVG8odGhpcy4kY29tcG9uZW50V3JhcHBlcik7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5zZXROb2RlRXhwYW5kZWQgPSBmdW5jdGlvbiAobm9kZSwgZXhwYW5kZWQsIGFuaW1hdGUpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgd2FzRXhwYW5kZWQgPSBub2RlW3RoaXMuY29uZmlnLmV4cGFuZGVkUHJvcGVydHldO1xuICAgICAgICAgICAgaWYgKGV4cGFuZGVkICYmIHRoaXMuY29uZmlnLmVuZm9yY2VTaW5nbGVFeHBhbmRlZFBhdGgpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudGx5RXhwYW5kZWROb2RlcyA9IHRoaXMuZmluZEVudHJpZXMoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhKG5bX3RoaXMuY29uZmlnLmV4cGFuZGVkUHJvcGVydHldKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3RXhwYW5kZWRQYXRoID0gdGhpcy5maW5kUGF0aFRvRmlyc3RNYXRjaGluZ05vZGUoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG4gPT09IG5vZGU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjdXJyZW50bHlFeHBhbmRlZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjdXJyZW50bHlFeHBhbmRlZE5vZGUgPSBjdXJyZW50bHlFeHBhbmRlZE5vZGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV3RXhwYW5kZWRQYXRoLmluZGV4T2YoY3VycmVudGx5RXhwYW5kZWROb2RlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0Tm9kZUV4cGFuZGVkKGN1cnJlbnRseUV4cGFuZGVkTm9kZSwgZmFsc2UsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9kZVt0aGlzLmNvbmZpZy5leHBhbmRlZFByb3BlcnR5XSA9ICEhZXhwYW5kZWQ7XG4gICAgICAgICAgICBub2RlLl90ckVudHJ5RWxlbWVudC50b2dnbGVDbGFzcyhcImV4cGFuZGVkXCIsICEhZXhwYW5kZWQpO1xuICAgICAgICAgICAgdmFyIG5vZGVIYXNVbnJlbmRlcmVkQ2hpbGRyZW4gPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSAmJiBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XS5zb21lKGZ1bmN0aW9uIChjaGlsZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gIWNoaWxkLl90ckVudHJ5RWxlbWVudCB8fCAhJC5jb250YWlucyhkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIGNoaWxkLl90ckVudHJ5RWxlbWVudFswXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGV4cGFuZGVkICYmIG5vZGVbdGhpcy5jb25maWcubGF6eUNoaWxkcmVuRmxhZ1Byb3BlcnR5XSAmJiAhbm9kZVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLmxhenlDaGlsZHJlblF1ZXJ5RnVuY3Rpb24obm9kZSwgZnVuY3Rpb24gKGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldENoaWxkcmVuKG5vZGUsIGNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGV4cGFuZGVkICYmIG5vZGVIYXNVbnJlbmRlcmVkQ2hpbGRyZW4obm9kZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlckNoaWxkcmVuKG5vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGV4cGFuZGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5taW5pbWFsbHlTY3JvbGxUbyhub2RlLl90ckVudHJ5RWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY2hpbGRyZW5XcmFwcGVyID0gbm9kZS5fdHJFbnRyeUVsZW1lbnQuZmluZChcIj4gLnRyLXRyZWUtZW50cnktY2hpbGRyZW4td3JhcHBlclwiKTtcbiAgICAgICAgICAgIGlmIChleHBhbmRlZCkge1xuICAgICAgICAgICAgICAgIGlmIChhbmltYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuV3JhcHBlci5zbGlkZURvd24odGhpcy5jb25maWcuYW5pbWF0aW9uRHVyYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW5XcmFwcGVyLmNzcyhcImRpc3BsYXlcIiwgXCJibG9ja1wiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoYW5pbWF0ZSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbldyYXBwZXIuc2xpZGVVcCh0aGlzLmNvbmZpZy5hbmltYXRpb25EdXJhdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbldyYXBwZXIuaGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXdhc0V4cGFuZGVkICE9ICEhZXhwYW5kZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uTm9kZUV4cGFuc2lvblN0YXRlQ2hhbmdlZC5maXJlKG5vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUubm9kZURlcHRoID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgIHJldHVybiBub2RlID8gcGFyc2VJbnQobm9kZS5fdHJFbnRyeUVsZW1lbnQuYXR0cignZGF0YS1kZXB0aCcpKSA6IDA7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5zZXRDaGlsZHJlbiA9IGZ1bmN0aW9uIChub2RlLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgbm9kZVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSA9IGNoaWxkcmVuO1xuICAgICAgICAgICAgbm9kZVt0aGlzLmNvbmZpZy5sYXp5Q2hpbGRyZW5GbGFnUHJvcGVydHldID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckNoaWxkcmVuKG5vZGUpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUucmVuZGVyQ2hpbGRyZW4gPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgdmFyICRjaGlsZHJlbldyYXBwZXIgPSBub2RlLl90ckVudHJ5RWxlbWVudC5maW5kKCc+IC50ci10cmVlLWVudHJ5LWNoaWxkcmVuLXdyYXBwZXInKTtcbiAgICAgICAgICAgICRjaGlsZHJlbldyYXBwZXIuZW1wdHkoKTtcbiAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IG5vZGVbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV07XG4gICAgICAgICAgICBpZiAoY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHZhciBkZXB0aCA9IHRoaXMubm9kZURlcHRoKG5vZGUpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlRW50cnlFbGVtZW50KGNoaWxkLCBkZXB0aCArIDEpLmFwcGVuZFRvKCRjaGlsZHJlbldyYXBwZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG5vZGUuX3RyRW50cnlFbGVtZW50LnJlbW92ZUNsYXNzKCdoYXMtY2hpbGRyZW4gZXhwYW5kZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLnVwZGF0ZUVudHJpZXMgPSBmdW5jdGlvbiAobmV3RW50cmllcykge1xuICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRlZEVudHJ5ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuZW50cmllcyA9IG5ld0VudHJpZXM7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVRyZWVFbnRyeUVsZW1lbnRzKCk7XG4gICAgICAgICAgICB2YXIgc2VsZWN0ZWRFbnRyeSA9IHRoaXMuZmluZEVudHJ5QnlJZCh0aGlzLnNlbGVjdGVkRW50cnlJZCk7XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgIHRoaXMubWFya1NlbGVjdGVkRW50cnkoc2VsZWN0ZWRFbnRyeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5maW5kRW50cmllcyA9IGZ1bmN0aW9uIChmaWx0ZXJGdW5jdGlvbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBmaW5kRW50cmllc0luU3ViVHJlZSA9IGZ1bmN0aW9uIChub2RlLCBsaXN0T2ZGb3VuZEVudHJpZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZmlsdGVyRnVuY3Rpb24uY2FsbChfdGhpcywgbm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdE9mRm91bmRFbnRyaWVzLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVbX3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XVtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmRFbnRyaWVzSW5TdWJUcmVlKGNoaWxkLCBsaXN0T2ZGb3VuZEVudHJpZXMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBtYXRjaGluZ0VudHJpZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5lbnRyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvb3RFbnRyeSA9IHRoaXMuZW50cmllc1tpXTtcbiAgICAgICAgICAgICAgICBmaW5kRW50cmllc0luU3ViVHJlZShyb290RW50cnksIG1hdGNoaW5nRW50cmllcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hpbmdFbnRyaWVzO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuZmluZFBhdGhUb0ZpcnN0TWF0Y2hpbmdOb2RlID0gZnVuY3Rpb24gKHByZWRpY2F0ZUZ1bmN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIHNlYXJjaEluU3ViVHJlZSA9IGZ1bmN0aW9uIChub2RlLCBwYXRoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZWRpY2F0ZUZ1bmN0aW9uLmNhbGwoX3RoaXMsIG5vZGUsIHBhdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGgucHVzaChub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3UGF0aCA9IHBhdGguc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgbmV3UGF0aC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVbX3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBub2RlW190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XVtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBzZWFyY2hJblN1YlRyZWUoY2hpbGQsIG5ld1BhdGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcm9vdEVudHJ5ID0gdGhpcy5lbnRyaWVzW2ldO1xuICAgICAgICAgICAgICAgIHZhciBwYXRoID0gc2VhcmNoSW5TdWJUcmVlKHJvb3RFbnRyeSwgW10pO1xuICAgICAgICAgICAgICAgIGlmIChwYXRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmZpbmRFbnRyeUJ5SWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maW5kRW50cmllcyhmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3RoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24oZW50cnkpID09PSBpZDtcbiAgICAgICAgICAgIH0pWzBdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuZmluZFBhcmVudE5vZGUgPSBmdW5jdGlvbiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluZEVudHJpZXMoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5W190aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XSAmJiBlbnRyeVtfdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0uaW5kZXhPZihjaGlsZE5vZGUpICE9IC0xO1xuICAgICAgICAgICAgfSlbMF07XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5zZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5LCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cnlJZCA9IGVudHJ5ID8gdGhpcy5jb25maWcudmFsdWVGdW5jdGlvbihlbnRyeSkgOiBudWxsO1xuICAgICAgICAgICAgdGhpcy5tYXJrU2VsZWN0ZWRFbnRyeShlbnRyeSk7XG4gICAgICAgICAgICB0aGlzLnNldEhpZ2hsaWdodGVkRW50cnkoZW50cnkpO1xuICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKGVudHJ5LCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgIGlmIChlbnRyeSAmJiB0aGlzLmNvbmZpZy5vcGVuT25TZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldE5vZGVFeHBhbmRlZChlbnRyeSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5zZXRTZWxlY3RlZEVudHJ5QnlJZCA9IGZ1bmN0aW9uIChub2RlSWQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0ZWRFbnRyeSh0aGlzLmZpbmRFbnRyeUJ5SWQobm9kZUlkKSwgbnVsbCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5taW5pbWFsbHlTY3JvbGxUbyA9IGZ1bmN0aW9uICgkZW50cnlXcmFwcGVyKSB7XG4gICAgICAgICAgICBUcml2aWFsQ29yZV8xLm1pbmltYWxseVNjcm9sbFRvKHRoaXMuJGNvbXBvbmVudFdyYXBwZXIucGFyZW50KCksICRlbnRyeVdyYXBwZXIpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUubWFya1NlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgIHRoaXMuJHRyZWUuZmluZChcIi50ci1zZWxlY3RlZC1lbnRyeVwiKS5yZW1vdmVDbGFzcyhcInRyLXNlbGVjdGVkLWVudHJ5XCIpO1xuICAgICAgICAgICAgaWYgKGVudHJ5ICYmIGVudHJ5Ll90ckVudHJ5RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHZhciAkZW50cnlXcmFwcGVyID0gZW50cnkuX3RyRW50cnlFbGVtZW50LmZpbmQoJz4udHItdHJlZS1lbnRyeS1hbmQtZXhwYW5kZXItd3JhcHBlcicpO1xuICAgICAgICAgICAgICAgICRlbnRyeVdyYXBwZXIuYWRkQ2xhc3MoXCJ0ci1zZWxlY3RlZC1lbnRyeVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmZpcmVDaGFuZ2VFdmVudHMgPSBmdW5jdGlvbiAoZW50cnksIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuJGNvbXBvbmVudFdyYXBwZXIudHJpZ2dlcihcImNoYW5nZVwiKTtcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3RlZEVudHJ5Q2hhbmdlZC5maXJlKGVudHJ5KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLnNlbGVjdE5leHRFbnRyeSA9IGZ1bmN0aW9uIChkaXJlY3Rpb24sIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBuZXh0VmlzaWJsZUVudHJ5ID0gdGhpcy5nZXROZXh0VmlzaWJsZUVudHJ5KHRoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgaWYgKG5leHRWaXNpYmxlRW50cnkgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0ZWRFbnRyeShuZXh0VmlzaWJsZUVudHJ5LCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLnNldEhpZ2hsaWdodGVkRW50cnkgPSBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgIGlmIChlbnRyeSAhPT0gdGhpcy5oaWdobGlnaHRlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRlZEVudHJ5ID0gZW50cnk7XG4gICAgICAgICAgICAgICAgdGhpcy4kdHJlZS5maW5kKCcudHItaGlnaGxpZ2h0ZWQtZW50cnknKS5yZW1vdmVDbGFzcygndHItaGlnaGxpZ2h0ZWQtZW50cnknKTtcbiAgICAgICAgICAgICAgICBpZiAoZW50cnkgIT0gbnVsbCAmJiBlbnRyeS5fdHJFbnRyeUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRlbnRyeSA9IGVudHJ5Ll90ckVudHJ5RWxlbWVudC5maW5kKCc+LnRyLXRyZWUtZW50cnktYW5kLWV4cGFuZGVyLXdyYXBwZXInKTtcbiAgICAgICAgICAgICAgICAgICAgJGVudHJ5LmFkZENsYXNzKCd0ci1oaWdobGlnaHRlZC1lbnRyeScpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1pbmltYWxseVNjcm9sbFRvKCRlbnRyeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWRFbnRyeSA9IHRoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRlZEVudHJ5ID0gc2VsZWN0ZWRFbnRyeTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmdldE5leHRWaXNpYmxlRW50cnkgPSBmdW5jdGlvbiAoY3VycmVudEVudHJ5LCBkaXJlY3Rpb24sIG9ubHlFbnRyaWVzV2l0aFRleHRNYXRjaGVzKSB7XG4gICAgICAgICAgICBpZiAob25seUVudHJpZXNXaXRoVGV4dE1hdGNoZXMgPT09IHZvaWQgMCkgeyBvbmx5RW50cmllc1dpdGhUZXh0TWF0Y2hlcyA9IGZhbHNlOyB9XG4gICAgICAgICAgICB2YXIgbmV3U2VsZWN0ZWRFbGVtZW50SW5kZXg7XG4gICAgICAgICAgICB2YXIgdmlzaWJsZUVudHJpZXNBc0xpc3QgPSB0aGlzLmZpbmRFbnRyaWVzKGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIGlmICghZW50cnkuX3RyRW50cnlFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvbmx5RW50cmllc1dpdGhUZXh0TWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5Ll90ckVudHJ5RWxlbWVudC5pcygnOnZpc2libGUnKSAmJiBlbnRyeS5fdHJFbnRyeUVsZW1lbnQuaGFzKCc+LnRyLXRyZWUtZW50cnktYW5kLWV4cGFuZGVyLXdyYXBwZXIgLnRyLWhpZ2hsaWdodGVkLXRleHQnKS5sZW5ndGggPiAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5Ll90ckVudHJ5RWxlbWVudC5pcygnOnZpc2libGUnKSB8fCBlbnRyeSA9PT0gY3VycmVudEVudHJ5O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodmlzaWJsZUVudHJpZXNBc0xpc3QgPT0gbnVsbCB8fCB2aXNpYmxlRW50cmllc0FzTGlzdC5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY3VycmVudEVudHJ5ID09IG51bGwgJiYgZGlyZWN0aW9uID4gMCkge1xuICAgICAgICAgICAgICAgIG5ld1NlbGVjdGVkRWxlbWVudEluZGV4ID0gLTEgKyBkaXJlY3Rpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjdXJyZW50RW50cnkgPT0gbnVsbCAmJiBkaXJlY3Rpb24gPCAwKSB7XG4gICAgICAgICAgICAgICAgbmV3U2VsZWN0ZWRFbGVtZW50SW5kZXggPSB2aXNpYmxlRW50cmllc0FzTGlzdC5sZW5ndGggKyBkaXJlY3Rpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudFNlbGVjdGVkRWxlbWVudEluZGV4ID0gdmlzaWJsZUVudHJpZXNBc0xpc3QuaW5kZXhPZihjdXJyZW50RW50cnkpO1xuICAgICAgICAgICAgICAgIG5ld1NlbGVjdGVkRWxlbWVudEluZGV4ID0gKGN1cnJlbnRTZWxlY3RlZEVsZW1lbnRJbmRleCArIHZpc2libGVFbnRyaWVzQXNMaXN0Lmxlbmd0aCArIGRpcmVjdGlvbikgJSB2aXNpYmxlRW50cmllc0FzTGlzdC5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmlzaWJsZUVudHJpZXNBc0xpc3RbbmV3U2VsZWN0ZWRFbGVtZW50SW5kZXhdO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuaGlnaGxpZ2h0VGV4dE1hdGNoZXMgPSBmdW5jdGlvbiAoc2VhcmNoU3RyaW5nKSB7XG4gICAgICAgICAgICB0aGlzLiR0cmVlLmRldGFjaCgpO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgZW50cnkgPSB0aGlzLmVudHJpZXNbaV07XG4gICAgICAgICAgICAgICAgdmFyICRlbnRyeUVsZW1lbnQgPSBlbnRyeS5fdHJFbnRyeUVsZW1lbnQuZmluZCgnLnRyLXRyZWUtZW50cnknKTtcbiAgICAgICAgICAgICAgICAkZW50cnlFbGVtZW50LnRyaXZpYWxIaWdobGlnaHQoc2VhcmNoU3RyaW5nLCB0aGlzLmNvbmZpZy5tYXRjaGluZ09wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kdHJlZS5hcHBlbmRUbyh0aGlzLiRjb21wb25lbnRXcmFwcGVyKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmdldFNlbGVjdGVkRW50cnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuc2VsZWN0ZWRFbnRyeUlkICE9PSB1bmRlZmluZWQgJiYgdGhpcy5zZWxlY3RlZEVudHJ5SWQgIT09IG51bGwpID8gdGhpcy5maW5kRW50cnlCeUlkKHRoaXMuc2VsZWN0ZWRFbnRyeUlkKSA6IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS5yZXZlYWxTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKGFuaW1hdGUpIHtcbiAgICAgICAgICAgIGlmIChhbmltYXRlID09PSB2b2lkIDApIHsgYW5pbWF0ZSA9IGZhbHNlOyB9XG4gICAgICAgICAgICB2YXIgc2VsZWN0ZWRFbnRyeSA9IHRoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpO1xuICAgICAgICAgICAgaWYgKCFzZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGN1cnJlbnRFbnRyeSA9IHNlbGVjdGVkRW50cnk7XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudEVudHJ5ID0gdGhpcy5maW5kUGFyZW50Tm9kZShjdXJyZW50RW50cnkpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXROb2RlRXhwYW5kZWQoY3VycmVudEVudHJ5LCB0cnVlLCBhbmltYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubWluaW1hbGx5U2Nyb2xsVG8oc2VsZWN0ZWRFbnRyeS5fdHJFbnRyeUVsZW1lbnQpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuaGlnaGxpZ2h0TmV4dEVudHJ5ID0gZnVuY3Rpb24gKGRpcmVjdGlvbikge1xuICAgICAgICAgICAgdmFyIG5leHRWaXNpYmxlRW50cnkgPSB0aGlzLmdldE5leHRWaXNpYmxlRW50cnkodGhpcy5oaWdobGlnaHRlZEVudHJ5IHx8IHRoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgaWYgKG5leHRWaXNpYmxlRW50cnkgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SGlnaGxpZ2h0ZWRFbnRyeShuZXh0VmlzaWJsZUVudHJ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmhpZ2hsaWdodE5leHRNYXRjaGluZ0VudHJ5ID0gZnVuY3Rpb24gKGRpcmVjdGlvbikge1xuICAgICAgICAgICAgdmFyIG5leHRNYXRjaGluZ0VudHJ5ID0gdGhpcy5nZXROZXh0VmlzaWJsZUVudHJ5KHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSB8fCB0aGlzLmdldFNlbGVjdGVkRW50cnkoKSwgZGlyZWN0aW9uLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChuZXh0TWF0Y2hpbmdFbnRyeSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRIaWdobGlnaHRlZEVudHJ5KG5leHRNYXRjaGluZ0VudHJ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLnNlbGVjdE5leHRNYXRjaGluZ0VudHJ5ID0gZnVuY3Rpb24gKGRpcmVjdGlvbikge1xuICAgICAgICAgICAgdmFyIG5leHRNYXRjaGluZ0VudHJ5ID0gdGhpcy5nZXROZXh0VmlzaWJsZUVudHJ5KHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSwgZGlyZWN0aW9uLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChuZXh0TWF0Y2hpbmdFbnRyeSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTZWxlY3RlZEVudHJ5KG5leHRNYXRjaGluZ0VudHJ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmdldEhpZ2hsaWdodGVkRW50cnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oaWdobGlnaHRlZEVudHJ5O1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuc2V0SGlnaGxpZ2h0ZWROb2RlRXhwYW5kZWQgPSBmdW5jdGlvbiAoZXhwYW5kZWQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5oaWdobGlnaHRlZEVudHJ5IHx8IHRoaXMuaXNMZWFmKHRoaXMuaGlnaGxpZ2h0ZWRFbnRyeSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgd2FzRXhwYW5kZWQgPSB0aGlzLmhpZ2hsaWdodGVkRW50cnlbdGhpcy5jb25maWcuZXhwYW5kZWRQcm9wZXJ0eV07XG4gICAgICAgICAgICAgICAgdGhpcy5zZXROb2RlRXhwYW5kZWQodGhpcy5oaWdobGlnaHRlZEVudHJ5LCBleHBhbmRlZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuICF3YXNFeHBhbmRlZCAhPSAhZXhwYW5kZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQm94LnByb3RvdHlwZS51cGRhdGVDaGlsZHJlbiA9IGZ1bmN0aW9uIChwYXJlbnROb2RlSWQsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZmluZEVudHJ5QnlJZChwYXJlbnROb2RlSWQpO1xuICAgICAgICAgICAgaWYgKG5vZGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldENoaWxkcmVuKG5vZGUsIGNoaWxkcmVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZvaWQgMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUudXBkYXRlTm9kZSA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICB2YXIgb2xkTm9kZSA9IHRoaXMuZmluZEVudHJ5QnlJZCh0aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKG5vZGUpKTtcbiAgICAgICAgICAgIHZhciBwYXJlbnQgPSB0aGlzLmZpbmRQYXJlbnROb2RlKG9sZE5vZGUpO1xuICAgICAgICAgICAgaWYgKHBhcmVudCkge1xuICAgICAgICAgICAgICAgIHBhcmVudFt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XVtwYXJlbnRbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0uaW5kZXhPZihvbGROb2RlKV0gPSBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbnRyaWVzW3RoaXMuZW50cmllcy5pbmRleE9mKG9sZE5vZGUpXSA9IG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZUVudHJ5RWxlbWVudChub2RlLCB0aGlzLm5vZGVEZXB0aChvbGROb2RlKSkuaW5zZXJ0QWZ0ZXIob2xkTm9kZS5fdHJFbnRyeUVsZW1lbnQpO1xuICAgICAgICAgICAgb2xkTm9kZS5fdHJFbnRyeUVsZW1lbnQucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLnJlbW92ZU5vZGUgPSBmdW5jdGlvbiAobm9kZUlkKSB7XG4gICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gdGhpcy5maW5kRW50cnlCeUlkKG5vZGVJZCk7XG4gICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSB0aGlzLmZpbmRQYXJlbnROb2RlKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XS5zcGxpY2UocGFyZW50Tm9kZVt0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5XS5pbmRleE9mKGNoaWxkTm9kZSksIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbnRyaWVzLnNwbGljZSh0aGlzLmVudHJpZXMuaW5kZXhPZihjaGlsZE5vZGUpLCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2hpbGROb2RlLl90ckVudHJ5RWxlbWVudC5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuYWRkTm9kZSA9IGZ1bmN0aW9uIChwYXJlbnROb2RlSWQsIG5vZGUpIHtcbiAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gdGhpcy5maW5kRW50cnlCeUlkKHBhcmVudE5vZGVJZCk7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xlYWYocGFyZW50Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICB2b2lkIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXBhcmVudE5vZGVbdGhpcy5jb25maWcuY2hpbGRyZW5Qcm9wZXJ0eV0pIHtcbiAgICAgICAgICAgICAgICBwYXJlbnROb2RlW3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXJlbnROb2RlW3RoaXMuY29uZmlnLmNoaWxkcmVuUHJvcGVydHldLnB1c2gobm9kZSk7XG4gICAgICAgICAgICB2YXIgZW50cnlFbGVtZW50ID0gdGhpcy5jcmVhdGVFbnRyeUVsZW1lbnQobm9kZSwgdGhpcy5ub2RlRGVwdGgocGFyZW50Tm9kZSkgKyAxKTtcbiAgICAgICAgICAgIGVudHJ5RWxlbWVudFxuICAgICAgICAgICAgICAgIC5hcHBlbmRUbyhwYXJlbnROb2RlLl90ckVudHJ5RWxlbWVudC5maW5kKCc+LnRyLXRyZWUtZW50cnktY2hpbGRyZW4td3JhcHBlcicpKTtcbiAgICAgICAgICAgIHBhcmVudE5vZGUuX3RyRW50cnlFbGVtZW50LmFkZENsYXNzKCdoYXMtY2hpbGRyZW4nKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZUJveC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJGNvbXBvbmVudFdyYXBwZXIucmVtb3ZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVCb3gucHJvdG90eXBlLmdldE1haW5Eb21FbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGNvbXBvbmVudFdyYXBwZXJbMF07XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBUcml2aWFsVHJlZUJveDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbFRyZWVCb3ggPSBUcml2aWFsVHJlZUJveDtcbn0pO1xuXG5cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwianF1ZXJ5XCIsIFwibXVzdGFjaGVcIiwgXCIuL1RyaXZpYWxDb3JlXCIsIFwiLi9Ucml2aWFsVHJlZUJveFwiLCBcIi4vVHJpdmlhbEV2ZW50XCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIE11c3RhY2hlID0gcmVxdWlyZShcIm11c3RhY2hlXCIpO1xuICAgIHZhciBUcml2aWFsQ29yZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENvcmVcIik7XG4gICAgdmFyIFRyaXZpYWxUcmVlQm94XzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsVHJlZUJveFwiKTtcbiAgICB2YXIgVHJpdmlhbEV2ZW50XzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsRXZlbnRcIik7XG4gICAgdmFyIFRyaXZpYWxUcmVlQ29tYm9Cb3ggPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUcml2aWFsVHJlZUNvbWJvQm94KG9yaWdpbmFsSW5wdXQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5pc0VkaXRvclZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubGFzdFF1ZXJ5U3RyaW5nID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMubGFzdENvbXBsZXRlSW5wdXRRdWVyeVN0cmluZyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRW50cnkgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5hdXRvQ29tcGxldGVUaW1lb3V0SWQgPSAtMTtcbiAgICAgICAgICAgIHRoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnVzaW5nRGVmYXVsdFF1ZXJ5RnVuY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzID0gJCgpO1xuICAgICAgICAgICAgdGhpcy5vblNlbGVjdGVkRW50cnlDaGFuZ2VkID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMub25Gb2N1cyA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9uQmx1ciA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgICAgICB2YWx1ZUZ1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHsgcmV0dXJuIGVudHJ5ID8gXCJcIiArIGVudHJ5LmlkIDogbnVsbDsgfSxcbiAgICAgICAgICAgICAgICBlbnRyeVJlbmRlcmluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnksIGRlcHRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkZWZhdWx0VGVtcGxhdGVzID0gW1RyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuaWNvbjJMaW5lc1RlbXBsYXRlLCBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmljb25TaW5nbGVMaW5lVGVtcGxhdGVdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSBkZWZhdWx0VGVtcGxhdGVzW01hdGgubWluKGRlcHRoLCBkZWZhdWx0VGVtcGxhdGVzLmxlbmd0aCAtIDEpXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE11c3RhY2hlLnJlbmRlcih0ZW1wbGF0ZSwgZW50cnkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeVJlbmRlcmluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLmNvbmZpZy5lbnRyeVJlbmRlcmluZ0Z1bmN0aW9uKGVudHJ5LCAwKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnk6IG51bGwsXG4gICAgICAgICAgICAgICAgc3Bpbm5lclRlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHRTcGlubmVyVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgbm9FbnRyaWVzVGVtcGxhdGU6IFRyaXZpYWxDb3JlXzEuREVGQVVMVF9URU1QTEFURVMuZGVmYXVsdE5vRW50cmllc1RlbXBsYXRlLFxuICAgICAgICAgICAgICAgIHRleHRIaWdobGlnaHRpbmdFbnRyeUxpbWl0OiAxMDAsXG4gICAgICAgICAgICAgICAgZW50cmllczogbnVsbCxcbiAgICAgICAgICAgICAgICBxdWVyeUZ1bmN0aW9uOiBudWxsLFxuICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGVEZWxheTogMCxcbiAgICAgICAgICAgICAgICBlbnRyeVRvRWRpdG9yVGV4dEZ1bmN0aW9uOiBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5W1wiZGlzcGxheVZhbHVlXCJdO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlRnVuY3Rpb246IGZ1bmN0aW9uIChlZGl0b3JUZXh0LCBlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWRpdG9yVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcGVydHlOYW1lIGluIGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5VmFsdWUgPSBlbnRyeVtwcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0eVZhbHVlICYmIHByb3BlcnR5VmFsdWUudG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoZWRpdG9yVGV4dC50b0xvd2VyQ2FzZSgpKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvcGVydHlWYWx1ZS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5ID8gX3RoaXMuY29uZmlnLmVudHJ5VG9FZGl0b3JUZXh0RnVuY3Rpb24oZW50cnkpIDogbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYWxsb3dGcmVlVGV4dDogZmFsc2UsXG4gICAgICAgICAgICAgICAgZnJlZVRleHRFbnRyeUZhY3Rvcnk6IGZ1bmN0aW9uIChmcmVlVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheVZhbHVlOiBmcmVlVGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIF9pc0ZyZWVUZXh0RW50cnk6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNob3dDbGVhckJ1dHRvbjogZmFsc2UsXG4gICAgICAgICAgICAgICAgc2hvd1RyaWdnZXI6IHRydWUsXG4gICAgICAgICAgICAgICAgbWF0Y2hpbmdPcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoaW5nTW9kZTogJ2NvbnRhaW5zJyxcbiAgICAgICAgICAgICAgICAgICAgaWdub3JlQ2FzZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWF4TGV2ZW5zaHRlaW5EaXN0YW5jZTogMlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY2hpbGRyZW5Qcm9wZXJ0eTogXCJjaGlsZHJlblwiLFxuICAgICAgICAgICAgICAgIGxhenlDaGlsZHJlbkZsYWdQcm9wZXJ0eTogXCJoYXNMYXp5Q2hpbGRyZW5cIixcbiAgICAgICAgICAgICAgICBleHBhbmRlZFByb3BlcnR5OiAnZXhwYW5kZWQnLFxuICAgICAgICAgICAgICAgIGVkaXRpbmdNb2RlOiBcImVkaXRhYmxlXCIsXG4gICAgICAgICAgICAgICAgc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seTogZmFsc2VcbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbiA9IFRyaXZpYWxDb3JlXzEuZGVmYXVsdFRyZWVRdWVyeUZ1bmN0aW9uRmFjdG9yeSh0aGlzLmNvbmZpZy5lbnRyaWVzIHx8IFtdLCBUcml2aWFsQ29yZV8xLmRlZmF1bHRFbnRyeU1hdGNoaW5nRnVuY3Rpb25GYWN0b3J5KFtcImRpc3BsYXlWYWx1ZVwiLCBcImFkZGl0aW9uYWxJbmZvXCJdLCB0aGlzLmNvbmZpZy5tYXRjaGluZ09wdGlvbnMpLCB0aGlzLmNvbmZpZy5jaGlsZHJlblByb3BlcnR5LCB0aGlzLmNvbmZpZy5leHBhbmRlZFByb3BlcnR5KTtcbiAgICAgICAgICAgICAgICB0aGlzLnVzaW5nRGVmYXVsdFF1ZXJ5RnVuY3Rpb24gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dCA9ICQob3JpZ2luYWxJbnB1dCk7XG4gICAgICAgICAgICB0aGlzLiR0cmVlQ29tYm9Cb3ggPSAkKCc8ZGl2IGNsYXNzPVwidHItdHJlZWNvbWJvYm94IHRyLWNvbWJvYm94IHRyLWlucHV0LXdyYXBwZXJcIi8+JylcbiAgICAgICAgICAgICAgICAuaW5zZXJ0QWZ0ZXIodGhpcy4kb3JpZ2luYWxJbnB1dCk7XG4gICAgICAgICAgICB0aGlzLiRzZWxlY3RlZEVudHJ5V3JhcHBlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1jb21ib2JveC1zZWxlY3RlZC1lbnRyeS13cmFwcGVyXCIvPicpLmFwcGVuZFRvKHRoaXMuJHRyZWVDb21ib0JveCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuc2hvd0NsZWFyQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2xlYXJCdXR0b24gPSAkKCc8ZGl2IGNsYXNzPVwidHItcmVtb3ZlLWJ1dHRvblwiPicpLmFwcGVuZFRvKHRoaXMuJHRyZWVDb21ib0JveCk7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2xlYXJCdXR0b24ubW91c2Vkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IudmFsKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KG51bGwsIHRydWUsIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kdHJpZ2dlciA9ICQoJzxkaXYgY2xhc3M9XCJ0ci10cmlnZ2VyXCI+PHNwYW4gY2xhc3M9XCJ0ci10cmlnZ2VyLWljb25cIi8+PC9kaXY+JykuYXBwZW5kVG8odGhpcy4kdHJlZUNvbWJvQm94KTtcbiAgICAgICAgICAgICAgICB0aGlzLiR0cmlnZ2VyLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93biA9ICQoJzxkaXYgY2xhc3M9XCJ0ci1kcm9wZG93blwiPjwvZGl2PicpXG4gICAgICAgICAgICAgICAgLnNjcm9sbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93blRhcmdldEVsZW1lbnQgPSAkKFwiYm9keVwiKTtcbiAgICAgICAgICAgIHRoaXMuc2V0RWRpdGluZ01vZGUodGhpcy5jb25maWcuZWRpdGluZ01vZGUpO1xuICAgICAgICAgICAgdGhpcy4kb3JpZ2luYWxJbnB1dC5hZGRDbGFzcyhcInRyLW9yaWdpbmFsLWlucHV0XCIpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yID0gJCgnPGlucHV0IHR5cGU9XCJ0ZXh0XCIgYXV0b2NvbXBsZXRlPVwib2ZmXCIvPicpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnByZXBlbmRUbyh0aGlzLiR0cmVlQ29tYm9Cb3gpLmFkZENsYXNzKFwidHItY29tYm9ib3gtZWRpdG9yIHRyLWVkaXRvclwiKVxuICAgICAgICAgICAgICAgIC5mb2N1cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kb3JpZ2luYWxJbnB1dC50cmlnZ2VySGFuZGxlcignZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMub25Gb2N1cy5maXJlKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiR0cmVlQ29tYm9Cb3guYWRkQ2xhc3MoJ2ZvY3VzJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5ibHVyKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXJIYW5kbGVyKCdibHVyJyk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9uQmx1ci5maXJlKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiR0cmVlQ29tYm9Cb3gucmVtb3ZlQ2xhc3MoJ2ZvY3VzJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5lZGl0b3JDb250YWluc0ZyZWVUZXh0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghVHJpdmlhbENvcmVfMS5vYmplY3RFcXVhbHMoX3RoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCBfdGhpcy5sYXN0Q29tbWl0dGVkVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5nZXRTZWxlY3RlZEVudHJ5KCksIHRydWUsIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci52YWwoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KF90aGlzLmxhc3RDb21taXR0ZWRWYWx1ZSwgZmFsc2UsIGZhbHNlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5oaWRlRWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5rZXlkb3duKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuaXNNb2RpZmllcktleShlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy50YWIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnkgPSBfdGhpcy50cmVlQm94LmdldEhpZ2hsaWdodGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuICYmIGhpZ2hsaWdodGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoaGlnaGxpZ2h0ZWRFbnRyeSwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIV90aGlzLiRlZGl0b3IudmFsKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkobnVsbCwgdHJ1ZSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoX3RoaXMuY29uZmlnLmFsbG93RnJlZVRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMuZ2V0U2VsZWN0ZWRFbnRyeSgpLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5sZWZ0X2Fycm93IHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGFuZ2VkRXhwYW5kZWRTdGF0ZSA9IF90aGlzLnRyZWVCb3guc2V0SGlnaGxpZ2h0ZWROb2RlRXhwYW5kZWQoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnJpZ2h0X2Fycm93KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGFuZ2VkRXhwYW5kZWRTdGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpc05vbklnbm9yZWRLZXkgPSAhVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5pc01vZGlmaWVyS2V5KGUpICYmIFtUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVudGVyLCBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVzY2FwZSwgVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy50YWJdLmluZGV4T2YoZS53aGljaCkgPT09IC0xO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZWRpdG9yVmFsdWVEb2VzTm90Q29ycmVzcG9uZFRvU2VsZWN0ZWRWYWx1ZSA9IF90aGlzLmlzRW50cnlTZWxlY3RlZCgpICYmIF90aGlzLiRlZGl0b3IudmFsKCkgIT09IF90aGlzLmNvbmZpZy5lbnRyeVRvRWRpdG9yVGV4dEZ1bmN0aW9uKF90aGlzLnNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNOb25JZ25vcmVkS2V5ICYmIChlZGl0b3JWYWx1ZURvZXNOb3RDb3JyZXNwb25kVG9TZWxlY3RlZFZhbHVlIHx8IF90aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKF90aGlzLnRyZWVCb3guZ2V0SGlnaGxpZ2h0ZWRFbnRyeSgpKSkgIT09IF90aGlzLmNvbmZpZy52YWx1ZUZ1bmN0aW9uKF90aGlzLmdldFNlbGVjdGVkRW50cnkoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkobnVsbCwgZmFsc2UsIGZhbHNlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuYmFja3NwYWNlIHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5kZWxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZG9Ob0F1dG9Db21wbGV0ZUJlY2F1c2VCYWNrc3BhY2VXYXNQcmVzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy51cF9hcnJvdyB8fCBlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMuZG93bl9hcnJvdykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmlzRWRpdG9yVmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgZGlyZWN0aW9uID0gZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLnVwX2Fycm93ID8gLTEgOiAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeShkaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMudHJlZUJveC5oaWdobGlnaHROZXh0RW50cnkoZGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmF1dG9Db21wbGV0ZUlmUG9zc2libGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lbnRlcikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNFZGl0b3JWaXNpYmxlIHx8IF90aGlzLmVkaXRvckNvbnRhaW5zRnJlZVRleHQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhpZ2hsaWdodGVkRW50cnkgPSBfdGhpcy50cmVlQm94LmdldEhpZ2hsaWdodGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3BlbiAmJiBoaWdobGlnaHRlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShoaWdobGlnaHRlZEVudHJ5LCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFfdGhpcy4kZWRpdG9yLnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShudWxsLCB0cnVlLCB0cnVlLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKF90aGlzLmNvbmZpZy5hbGxvd0ZyZWVUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5nZXRTZWxlY3RlZEVudHJ5KCksIHRydWUsIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuaGlkZUVkaXRvcigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5lc2NhcGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShfdGhpcy5lZGl0b3JDb250YWluc0ZyZWVUZXh0KCkgJiYgX3RoaXMuaXNEcm9wRG93bk9wZW4pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5oaWRlRWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnZhbChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnNldFNlbGVjdGVkRW50cnkoX3RoaXMubGFzdENvbW1pdHRlZFZhbHVlLCBmYWxzZSwgZmFsc2UsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMuaXNFZGl0b3JWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMuY29uZmlnLnNob3dEcm9wRG93bk9uUmVzdWx0c09ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IudmFsKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnF1ZXJ5KDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3guc2V0SGlnaGxpZ2h0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAubW91c2Vkb3duKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmNvbmZpZy5zaG93RHJvcERvd25PblJlc3VsdHNPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IuYXR0cihcInRhYmluZGV4XCIsIHRoaXMuJG9yaWdpbmFsSW5wdXQuYXR0cihcInRhYmluZGV4XCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLiRvcmlnaW5hbElucHV0LmF0dHIoXCJhdXRvZm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuJHRyZWVDb21ib0JveC5hZGQodGhpcy4kZHJvcERvd24pXG4gICAgICAgICAgICAgICAgLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm1vdXNldXAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAubW91c2VvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3ggPSBuZXcgVHJpdmlhbFRyZWVCb3hfMS5Ucml2aWFsVHJlZUJveCh0aGlzLiRkcm9wRG93biwgdGhpcy5jb25maWcpO1xuICAgICAgICAgICAgdGhpcy50cmVlQm94Lm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKHNlbGVjdGVkRW50cnksIGV2ZW50U291cmNlLCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShzZWxlY3RlZEVudHJ5LCB0cnVlLCAhVHJpdmlhbENvcmVfMS5vYmplY3RFcXVhbHMoc2VsZWN0ZWRFbnRyeSwgX3RoaXMubGFzdENvbW1pdHRlZFZhbHVlKSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnRyZWVCb3guc2V0U2VsZWN0ZWRFbnRyeShudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy5oaWRlRWRpdG9yKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0ZWRFbnRyeSh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5LCB0cnVlLCBmYWxzZSwgbnVsbCk7XG4gICAgICAgICAgICB0aGlzLiRzZWxlY3RlZEVudHJ5V3JhcHBlci5jbGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2hvd0VkaXRvcigpO1xuICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24gKGhpZ2hsaWdodERpcmVjdGlvbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBxdWVyeVN0cmluZyA9IHRoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgdmFyIGNvbXBsZXRlSW5wdXRTdHJpbmcgPSB0aGlzLiRlZGl0b3IudmFsKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5sYXN0UXVlcnlTdHJpbmcgIT09IHF1ZXJ5U3RyaW5nIHx8IHRoaXMubGFzdENvbXBsZXRlSW5wdXRRdWVyeVN0cmluZyAhPT0gY29tcGxldGVJbnB1dFN0cmluZykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLiRzcGlubmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRzcGlubmVyID0gJCh0aGlzLmNvbmZpZy5zcGlubmVyVGVtcGxhdGUpLmFwcGVuZFRvKHRoaXMuJGRyb3BEb3duKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSB0aGlzLiRzcGlubmVycy5hZGQoJHNwaW5uZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5xdWVyeUZ1bmN0aW9uKHF1ZXJ5U3RyaW5nLCBmdW5jdGlvbiAobmV3RW50cmllcykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy51cGRhdGVFbnRyaWVzKG5ld0VudHJpZXMsIGhpZ2hsaWdodERpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuc2hvd0Ryb3BEb3duT25SZXN1bHRzT25seSAmJiBuZXdFbnRyaWVzICYmIG5ld0VudHJpZXMubGVuZ3RoID4gMCAmJiBfdGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdFF1ZXJ5U3RyaW5nID0gcXVlcnlTdHJpbmc7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0Q29tcGxldGVJbnB1dFF1ZXJ5U3RyaW5nID0gY29tcGxldGVJbnB1dFN0cmluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmZpcmVDaGFuZ2VFdmVudHMgPSBmdW5jdGlvbiAoZW50cnksIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQudHJpZ2dlcihcImNoYW5nZVwiKTtcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3RlZEVudHJ5Q2hhbmdlZC5maXJlKGVudHJ5LCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuc2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uIChlbnRyeSwgY29tbWl0LCBmaXJlRXZlbnQsIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQudmFsKHRoaXMuY29uZmlnLnZhbHVlRnVuY3Rpb24oZW50cnkpKTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRFbnRyeSA9IGVudHJ5O1xuICAgICAgICAgICAgdmFyICRzZWxlY3RlZEVudHJ5ID0gJCh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5UmVuZGVyaW5nRnVuY3Rpb24oZW50cnkpKVxuICAgICAgICAgICAgICAgIC5hZGRDbGFzcyhcInRyLWNvbWJvYm94LWVudHJ5XCIpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIuZW1wdHkoKS5hcHBlbmQoJHNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgaWYgKGVudHJ5ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuY29uZmlnLmVudHJ5VG9FZGl0b3JUZXh0RnVuY3Rpb24oZW50cnkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb21taXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RDb21taXR0ZWRWYWx1ZSA9IGVudHJ5O1xuICAgICAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKGVudHJ5LCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy4kY2xlYXJCdXR0b24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRjbGVhckJ1dHRvbi50b2dnbGUoZW50cnkgIT0gbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc0VkaXRvclZpc2libGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dFZGl0b3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXBvc2l0aW9uRHJvcERvd24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuaXNFbnRyeVNlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRFbnRyeSAhPSBudWxsO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5zaG93RWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyICRlZGl0b3JBcmVhID0gdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIuZmluZChcIi50ci1lZGl0b3ItYXJlYVwiKTtcbiAgICAgICAgICAgIGlmICgkZWRpdG9yQXJlYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAkZWRpdG9yQXJlYSA9IHRoaXMuJHNlbGVjdGVkRW50cnlXcmFwcGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy4kZWRpdG9yXG4gICAgICAgICAgICAgICAgLmNzcyh7XG4gICAgICAgICAgICAgICAgXCJ3aWR0aFwiOiBNYXRoLm1pbigkZWRpdG9yQXJlYVswXS5vZmZzZXRXaWR0aCwgdGhpcy4kdHJpZ2dlciA/IHRoaXMuJHRyaWdnZXJbMF0ub2Zmc2V0TGVmdCAtICRlZGl0b3JBcmVhWzBdLm9mZnNldExlZnQgOiA5OTk5OTk5OSkgKyBcInB4XCIsXG4gICAgICAgICAgICAgICAgXCJoZWlnaHRcIjogKCRlZGl0b3JBcmVhWzBdLm9mZnNldEhlaWdodCkgKyBcInB4XCJcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICBteTogXCJsZWZ0IHRvcFwiLFxuICAgICAgICAgICAgICAgIGF0OiBcImxlZnQgdG9wXCIsXG4gICAgICAgICAgICAgICAgb2Y6ICRlZGl0b3JBcmVhXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuaXNFZGl0b3JWaXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuZWRpdG9yQ29udGFpbnNGcmVlVGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5hbGxvd0ZyZWVUZXh0ICYmIHRoaXMuJGVkaXRvci52YWwoKS5sZW5ndGggPiAwICYmICF0aGlzLmlzRW50cnlTZWxlY3RlZCgpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmhpZGVFZGl0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3Iud2lkdGgoMCkuaGVpZ2h0KDApO1xuICAgICAgICAgICAgdGhpcy5pc0VkaXRvclZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUucmVwb3NpdGlvbkRyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duXG4gICAgICAgICAgICAgICAgLnNob3coKVxuICAgICAgICAgICAgICAgIC5wb3NpdGlvbih7XG4gICAgICAgICAgICAgICAgbXk6IFwibGVmdCB0b3BcIixcbiAgICAgICAgICAgICAgICBhdDogXCJsZWZ0IGJvdHRvbVwiLFxuICAgICAgICAgICAgICAgIG9mOiB0aGlzLiR0cmVlQ29tYm9Cb3gsXG4gICAgICAgICAgICAgICAgY29sbGlzaW9uOiBcImZsaXBcIixcbiAgICAgICAgICAgICAgICB1c2luZzogZnVuY3Rpb24gKGNhbGN1bGF0ZWRQb3NpdGlvbiwgaW5mbykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5mby52ZXJ0aWNhbCA9PT0gXCJ0b3BcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJHRyZWVDb21ib0JveC5yZW1vdmVDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24ucmVtb3ZlQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJHRyZWVDb21ib0JveC5hZGRDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24uYWRkQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5jc3Moe1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogY2FsY3VsYXRlZFBvc2l0aW9uLmxlZnQgKyAncHgnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wOiBjYWxjdWxhdGVkUG9zaXRpb24udG9wICsgJ3B4J1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC53aWR0aCh0aGlzLiR0cmVlQ29tYm9Cb3gud2lkdGgoKSk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUub3BlbkRyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk5lZWRlZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kdHJlZUNvbWJvQm94LmFkZENsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcG9zaXRpb25Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5jbG9zZURyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kdHJlZUNvbWJvQm94LnJlbW92ZUNsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmhpZGUoKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRlZGl0b3IudmFsKCkuc3Vic3RyaW5nKDAsIHRoaXMuJGVkaXRvclswXS5zZWxlY3Rpb25TdGFydCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmF1dG9Db21wbGV0ZUlmUG9zc2libGUgPSBmdW5jdGlvbiAoZGVsYXkpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuYXV0b0NvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuYXV0b0NvbXBsZXRlVGltZW91dElkKTtcbiAgICAgICAgICAgICAgICB2YXIgaGlnaGxpZ2h0ZWRFbnRyeV8xID0gdGhpcy50cmVlQm94LmdldEhpZ2hsaWdodGVkRW50cnkoKTtcbiAgICAgICAgICAgICAgICBpZiAoaGlnaGxpZ2h0ZWRFbnRyeV8xICYmICF0aGlzLmRvTm9BdXRvQ29tcGxldGVCZWNhdXNlQmFja3NwYWNlV2FzUHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmF1dG9Db21wbGV0ZVRpbWVvdXRJZCA9IFRyaXZpYWxDb3JlXzEuc2V0VGltZW91dE9yRG9JbW1lZGlhdGVseShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY3VycmVudEVkaXRvclZhbHVlID0gX3RoaXMuZ2V0Tm9uU2VsZWN0ZWRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF1dG9Db21wbGV0ZVN0cmluZyA9IF90aGlzLmNvbmZpZy5hdXRvQ29tcGxldGVGdW5jdGlvbihjdXJyZW50RWRpdG9yVmFsdWUsIGhpZ2hsaWdodGVkRW50cnlfMSkgfHwgY3VycmVudEVkaXRvclZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci52YWwoY3VycmVudEVkaXRvclZhbHVlICsgYXV0b0NvbXBsZXRlU3RyaW5nLnN1YnN0cihjdXJyZW50RWRpdG9yVmFsdWUubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuJGVkaXRvci5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3JbMF0uc2V0U2VsZWN0aW9uUmFuZ2UoY3VycmVudEVkaXRvclZhbHVlLmxlbmd0aCwgYXV0b0NvbXBsZXRlU3RyaW5nLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0sIGRlbGF5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5kb05vQXV0b0NvbXBsZXRlQmVjYXVzZUJhY2tzcGFjZVdhc1ByZXNzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUudXBkYXRlRW50cmllcyA9IGZ1bmN0aW9uIChuZXdFbnRyaWVzLCBoaWdobGlnaHREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuJHNwaW5uZXJzLnJlbW92ZSgpO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSAkKCk7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3gudXBkYXRlRW50cmllcyhuZXdFbnRyaWVzKTtcbiAgICAgICAgICAgIHZhciBub25TZWxlY3RlZEVkaXRvclZhbHVlID0gdGhpcy5nZXROb25TZWxlY3RlZEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3guaGlnaGxpZ2h0VGV4dE1hdGNoZXMobmV3RW50cmllcy5sZW5ndGggPD0gdGhpcy5jb25maWcudGV4dEhpZ2hsaWdodGluZ0VudHJ5TGltaXQgPyBub25TZWxlY3RlZEVkaXRvclZhbHVlIDogbnVsbCk7XG4gICAgICAgICAgICBpZiAoaGlnaGxpZ2h0RGlyZWN0aW9uID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZWxlY3RlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHJlZUJveC5zZXRIaWdobGlnaHRlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vblNlbGVjdGVkRWRpdG9yVmFsdWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmVlQm94LmhpZ2hsaWdodE5leHRNYXRjaGluZ0VudHJ5KDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmVlQm94LmhpZ2hsaWdodE5leHRFbnRyeSgxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGhpZ2hsaWdodERpcmVjdGlvbiA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHJlZUJveC5zZXRIaWdobGlnaHRlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vblNlbGVjdGVkRWRpdG9yVmFsdWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRyZWVCb3guaGlnaGxpZ2h0TmV4dE1hdGNoaW5nRW50cnkoMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRyZWVCb3guaGlnaGxpZ2h0TmV4dEVudHJ5KDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYXV0b0NvbXBsZXRlSWZQb3NzaWJsZSh0aGlzLmNvbmZpZy5hdXRvQ29tcGxldGVEZWxheSk7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmlzRHJvcERvd25OZWVkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lZGl0aW5nTW9kZSA9PSAnZWRpdGFibGUnICYmICh0aGlzLmNvbmZpZy5lbnRyaWVzICYmIHRoaXMuY29uZmlnLmVudHJpZXMubGVuZ3RoID4gMCB8fCAhdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uIHx8IHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuc2V0RWRpdGluZ01vZGUgPSBmdW5jdGlvbiAobmV3RWRpdGluZ01vZGUpIHtcbiAgICAgICAgICAgIHRoaXMuZWRpdGluZ01vZGUgPSBuZXdFZGl0aW5nTW9kZTtcbiAgICAgICAgICAgIHRoaXMuJHRyZWVDb21ib0JveC5yZW1vdmVDbGFzcyhcImVkaXRhYmxlIHJlYWRvbmx5IGRpc2FibGVkXCIpLmFkZENsYXNzKHRoaXMuZWRpdGluZ01vZGUpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk5lZWRlZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZHJvcERvd24uYXBwZW5kVG8odGhpcy4kZHJvcERvd25UYXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuZ2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkRW50cnkgPT0gbnVsbCAmJiAoIXRoaXMuY29uZmlnLmFsbG93RnJlZVRleHQgfHwgIXRoaXMuJGVkaXRvci52YWwoKSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRFbnRyeSA9PSBudWxsICYmIHRoaXMuY29uZmlnLmFsbG93RnJlZVRleHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZnJlZVRleHRFbnRyeUZhY3RvcnkodGhpcy4kZWRpdG9yLnZhbCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzZWxlY3RlZEVudHJ5VG9SZXR1cm4gPSAkLmV4dGVuZCh7fSwgdGhpcy5zZWxlY3RlZEVudHJ5KTtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZEVudHJ5VG9SZXR1cm4uX3RyRW50cnlFbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHJldHVybiBzZWxlY3RlZEVudHJ5VG9SZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLnVwZGF0ZUNoaWxkcmVuID0gZnVuY3Rpb24gKHBhcmVudE5vZGVJZCwgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC51cGRhdGVDaGlsZHJlbihwYXJlbnROb2RlSWQsIGNoaWxkcmVuKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUudXBkYXRlTm9kZSA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICB0aGlzLnRyZWVCb3gudXBkYXRlTm9kZShub2RlKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUucmVtb3ZlTm9kZSA9IGZ1bmN0aW9uIChub2RlSWQpIHtcbiAgICAgICAgICAgIHRoaXMudHJlZUJveC5yZW1vdmVOb2RlKG5vZGVJZCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxUcmVlQ29tYm9Cb3gucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5zaG93RWRpdG9yKCk7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuZ2V0RWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGVkaXRvclswXTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuZ2V0RHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kZHJvcERvd247XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFRyZWVDb21ib0JveC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQucmVtb3ZlQ2xhc3MoJ3RyLW9yaWdpbmFsLWlucHV0JykuaW5zZXJ0QmVmb3JlKHRoaXMuJHRyZWVDb21ib0JveCk7XG4gICAgICAgICAgICB0aGlzLiR0cmVlQ29tYm9Cb3gucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5yZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgO1xuICAgICAgICBUcml2aWFsVHJlZUNvbWJvQm94LnByb3RvdHlwZS5nZXRNYWluRG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiR0cmVlQ29tYm9Cb3hbMF07XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBUcml2aWFsVHJlZUNvbWJvQm94O1xuICAgIH0oKSk7XG4gICAgZXhwb3J0cy5Ucml2aWFsVHJlZUNvbWJvQm94ID0gVHJpdmlhbFRyZWVDb21ib0JveDtcbn0pO1xuXG5cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwianF1ZXJ5XCIsIFwibXVzdGFjaGVcIiwgXCIuL1RyaXZpYWxMaXN0Qm94XCIsIFwiLi9Ucml2aWFsQ29yZVwiLCBcIi4vVHJpdmlhbEV2ZW50XCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG4gICAgdmFyIE11c3RhY2hlID0gcmVxdWlyZShcIm11c3RhY2hlXCIpO1xuICAgIHZhciBUcml2aWFsTGlzdEJveF8xID0gcmVxdWlyZShcIi4vVHJpdmlhbExpc3RCb3hcIik7XG4gICAgdmFyIFRyaXZpYWxDb3JlXzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsQ29yZVwiKTtcbiAgICB2YXIgVHJpdmlhbEV2ZW50XzEgPSByZXF1aXJlKFwiLi9Ucml2aWFsRXZlbnRcIik7XG4gICAgdmFyIFRyaXZpYWxVbml0Qm94ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gVHJpdmlhbFVuaXRCb3gob3JpZ2luYWxJbnB1dCwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlID0gbmV3IFRyaXZpYWxFdmVudF8xLlRyaXZpYWxFdmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMub25TZWxlY3RlZEVudHJ5Q2hhbmdlZCA9IG5ldyBUcml2aWFsRXZlbnRfMS5Ucml2aWFsRXZlbnQodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9uRm9jdXMgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5vbkJsdXIgPSBuZXcgVHJpdmlhbEV2ZW50XzEuVHJpdmlhbEV2ZW50KHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5pc0Ryb3BEb3duT3BlbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSAkKCk7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZyA9ICQuZXh0ZW5kKHtcbiAgICAgICAgICAgICAgICB1bml0VmFsdWVQcm9wZXJ0eTogJ2NvZGUnLFxuICAgICAgICAgICAgICAgIHVuaXRJZFByb3BlcnR5OiAnY29kZScsXG4gICAgICAgICAgICAgICAgZGVjaW1hbFByZWNpc2lvbjogMixcbiAgICAgICAgICAgICAgICBkZWNpbWFsU2VwYXJhdG9yOiAnLicsXG4gICAgICAgICAgICAgICAgdGhvdXNhbmRzU2VwYXJhdG9yOiAnLCcsXG4gICAgICAgICAgICAgICAgdW5pdERpc3BsYXlQb3NpdGlvbjogJ3JpZ2h0JyxcbiAgICAgICAgICAgICAgICBhbGxvd051bGxBbW91bnQ6IHRydWUsXG4gICAgICAgICAgICAgICAgZW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNdXN0YWNoZS5yZW5kZXIoVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5jdXJyZW5jeTJMaW5lVGVtcGxhdGUsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlSZW5kZXJpbmdGdW5jdGlvbjogZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNdXN0YWNoZS5yZW5kZXIoVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5jdXJyZW5jeVNpbmdsZUxpbmVTaG9ydFRlbXBsYXRlLCBlbnRyeSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhbW91bnQ6IG51bGwsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbnRyeTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIHNwaW5uZXJUZW1wbGF0ZTogVHJpdmlhbENvcmVfMS5ERUZBVUxUX1RFTVBMQVRFUy5kZWZhdWx0U3Bpbm5lclRlbXBsYXRlLFxuICAgICAgICAgICAgICAgIG5vRW50cmllc1RlbXBsYXRlOiBUcml2aWFsQ29yZV8xLkRFRkFVTFRfVEVNUExBVEVTLmRlZmF1bHROb0VudHJpZXNUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICBlbnRyaWVzOiBudWxsLFxuICAgICAgICAgICAgICAgIHF1ZXJ5RnVuY3Rpb246IG51bGwsXG4gICAgICAgICAgICAgICAgcXVlcnlPbk5vbk51bWJlckNoYXJhY3RlcnM6IHRydWUsXG4gICAgICAgICAgICAgICAgb3BlbkRyb3Bkb3duT25FZGl0b3JDbGljazogZmFsc2UsXG4gICAgICAgICAgICAgICAgc2hvd1RyaWdnZXI6IHRydWUsXG4gICAgICAgICAgICAgICAgbWF0Y2hpbmdPcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoaW5nTW9kZTogJ3ByZWZpeC13b3JkJyxcbiAgICAgICAgICAgICAgICAgICAgaWdub3JlQ2FzZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWF4TGV2ZW5zaHRlaW5EaXN0YW5jZTogMlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZWRpdGluZ01vZGU6ICdlZGl0YWJsZScsXG4gICAgICAgICAgICB9LCBvcHRpb25zKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25maWcucXVlcnlGdW5jdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLnF1ZXJ5RnVuY3Rpb24gPSBUcml2aWFsQ29yZV8xLmRlZmF1bHRMaXN0UXVlcnlGdW5jdGlvbkZhY3RvcnkodGhpcy5jb25maWcuZW50cmllcyB8fCBbXSwgdGhpcy5jb25maWcubWF0Y2hpbmdPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB0aGlzLnVzaW5nRGVmYXVsdFF1ZXJ5RnVuY3Rpb24gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbnRyaWVzID0gdGhpcy5jb25maWcuZW50cmllcztcbiAgICAgICAgICAgIHRoaXMubnVtYmVyUmVnZXggPSBuZXcgUmVnRXhwKCdcXFxcZCpcXFxcJyArIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IgKyAnP1xcXFxkKicsICdnJyk7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0ID0gJChvcmlnaW5hbElucHV0KS5hZGRDbGFzcyhcInRyLW9yaWdpbmFsLWlucHV0XCIpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yID0gJCgnPGlucHV0IHR5cGU9XCJ0ZXh0XCIvPicpO1xuICAgICAgICAgICAgdGhpcy4kdW5pdEJveCA9ICQoJzxkaXYgY2xhc3M9XCJ0ci11bml0Ym94IHRyLWlucHV0LXdyYXBwZXJcIi8+JykuaW5zZXJ0QWZ0ZXIodGhpcy4kb3JpZ2luYWxJbnB1dClcbiAgICAgICAgICAgICAgICAuYWRkQ2xhc3ModGhpcy5jb25maWcudW5pdERpc3BsYXlQb3NpdGlvbiA9PT0gJ2xlZnQnID8gJ3VuaXQtZGlzcGxheS1sZWZ0JyA6ICd1bml0LWRpc3BsYXktcmlnaHQnKTtcbiAgICAgICAgICAgIHRoaXMuJG9yaWdpbmFsSW5wdXQuYXBwZW5kVG8odGhpcy4kdW5pdEJveCk7XG4gICAgICAgICAgICB0aGlzLiRzZWxlY3RlZEVudHJ5QW5kVHJpZ2dlcldyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItdW5pdGJveC1zZWxlY3RlZC1lbnRyeS1hbmQtdHJpZ2dlci13cmFwcGVyXCIvPicpLmFwcGVuZFRvKHRoaXMuJHVuaXRCb3gpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHItdW5pdGJveC1zZWxlY3RlZC1lbnRyeS13cmFwcGVyXCIvPicpLmFwcGVuZFRvKHRoaXMuJHNlbGVjdGVkRW50cnlBbmRUcmlnZ2VyV3JhcHBlcik7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuc2hvd1RyaWdnZXIpIHtcbiAgICAgICAgICAgICAgICAkKCc8ZGl2IGNsYXNzPVwidHItdHJpZ2dlclwiPjxzcGFuIGNsYXNzPVwidHItdHJpZ2dlci1pY29uXCIvPjwvZGl2PicpLmFwcGVuZFRvKHRoaXMuJHNlbGVjdGVkRW50cnlBbmRUcmlnZ2VyV3JhcHBlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRzZWxlY3RlZEVudHJ5QW5kVHJpZ2dlcldyYXBwZXIubW91c2Vkb3duKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xvc2VEcm9wRG93bigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChfdGhpcy5lZGl0aW5nTW9kZSA9PT0gXCJlZGl0YWJsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duID0gJCgnPGRpdiBjbGFzcz1cInRyLWRyb3Bkb3duXCI+PC9kaXY+JylcbiAgICAgICAgICAgICAgICAuc2Nyb2xsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duVGFyZ2V0RWxlbWVudCA9ICQoXCJib2R5XCIpO1xuICAgICAgICAgICAgdGhpcy5zZXRFZGl0aW5nTW9kZSh0aGlzLmNvbmZpZy5lZGl0aW5nTW9kZSk7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IucHJlcGVuZFRvKHRoaXMuJHVuaXRCb3gpLmFkZENsYXNzKFwidHItdW5pdGJveC1lZGl0b3IgdHItZWRpdG9yXCIpXG4gICAgICAgICAgICAgICAgLmZvY3VzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZWRpdGluZ01vZGUgIT09IFwiZWRpdGFibGVcIikge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmJsdXIoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9uRm9jdXMuZmlyZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdW5pdEJveC5hZGRDbGFzcygnZm9jdXMnKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY2xlYW51cEVkaXRvclZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3Iuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuYmx1cihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3IuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9uQmx1ci5maXJlKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiR1bml0Qm94LnJlbW92ZUNsYXNzKCdmb2N1cycpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5mb3JtYXRFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAua2V5ZG93bihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChUcml2aWFsQ29yZV8xLmtleUNvZGVzLmlzTW9kaWZpZXJLZXkoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudGFiKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoaWdobGlnaHRlZEVudHJ5ID0gX3RoaXMubGlzdEJveC5nZXRIaWdobGlnaHRlZEVudHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3BlbiAmJiBoaWdobGlnaHRlZEVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRTZWxlY3RlZEVudHJ5KGhpZ2hsaWdodGVkRW50cnksIHRydWUsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5sZWZ0X2Fycm93IHx8IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5yaWdodF9hcnJvdykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlLndoaWNoID09IFRyaXZpYWxDb3JlXzEua2V5Q29kZXMudXBfYXJyb3cgfHwgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmRvd25fYXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpcmVjdGlvbiA9IGUud2hpY2ggPT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy51cF9hcnJvdyA/IC0xIDogMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmlzRHJvcERvd25PcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5saXN0Qm94LmhpZ2hsaWdodE5leHRFbnRyeShkaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeShkaXJlY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoX3RoaXMuaXNEcm9wRG93bk9wZW4gJiYgZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVudGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShfdGhpcy5saXN0Qm94LmdldEhpZ2hsaWdodGVkRW50cnkoKSwgdHJ1ZSwgZSk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsb3NlRHJvcERvd24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZS53aGljaCA9PSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmVzY2FwZSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsZWFudXBFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICghZS5zaGlmdEtleSAmJiBUcml2aWFsQ29yZV8xLmtleUNvZGVzLm51bWJlcktleXMuaW5kZXhPZihlLndoaWNoKSAhPSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbnVtYmVyUGFydCA9IF90aGlzLmdldEVkaXRvclZhbHVlTnVtYmVyUGFydCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbnVtYmVyUGFydERlY2ltYWxTZXBhcmF0b3JJbmRleCA9IG51bWJlclBhcnQuaW5kZXhPZihfdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXhEZWNpbWFsRGlnaXRzUmVhY2hlZCA9IG51bWJlclBhcnREZWNpbWFsU2VwYXJhdG9ySW5kZXggIT0gLTEgJiYgbnVtYmVyUGFydC5sZW5ndGggLSAobnVtYmVyUGFydERlY2ltYWxTZXBhcmF0b3JJbmRleCArIDEpID49IF90aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZWRpdG9yVmFsdWUgPSBfdGhpcy4kZWRpdG9yLnZhbCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGVjaW1hbFNlcGFyYXRvckluZGV4ID0gZWRpdG9yVmFsdWUuaW5kZXhPZihfdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3Rpb25TdGFydCA9IF90aGlzLiRlZGl0b3JbMF0uc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3Rpb25FbmQgPSBfdGhpcy4kZWRpdG9yWzBdLnNlbGVjdGlvbkVuZDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdvdWxkQWRkQW5vdGhlckRpZ2l0ID0gZGVjaW1hbFNlcGFyYXRvckluZGV4ICE9PSAtMSAmJiBzZWxlY3Rpb25FbmQgPiBkZWNpbWFsU2VwYXJhdG9ySW5kZXggJiYgc2VsZWN0aW9uU3RhcnQgPT09IHNlbGVjdGlvbkVuZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1heERlY2ltYWxEaWdpdHNSZWFjaGVkICYmIHdvdWxkQWRkQW5vdGhlckRpZ2l0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoL15cXGQkLy50ZXN0KGVkaXRvclZhbHVlW3NlbGVjdGlvbkVuZF0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVkaXRvci52YWwoZWRpdG9yVmFsdWUuc3Vic3RyaW5nKDAsIHNlbGVjdGlvbkVuZCkgKyBlZGl0b3JWYWx1ZS5zdWJzdHJpbmcoc2VsZWN0aW9uRW5kICsgMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlZGl0b3JbMF0uc2V0U2VsZWN0aW9uUmFuZ2Uoc2VsZWN0aW9uRW5kLCBzZWxlY3Rpb25FbmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAua2V5dXAoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5zcGVjaWFsS2V5cy5pbmRleE9mKGUud2hpY2gpICE9IC0xXG4gICAgICAgICAgICAgICAgICAgICYmIGUud2hpY2ggIT0gVHJpdmlhbENvcmVfMS5rZXlDb2Rlcy5iYWNrc3BhY2VcbiAgICAgICAgICAgICAgICAgICAgJiYgZS53aGljaCAhPSBUcml2aWFsQ29yZV8xLmtleUNvZGVzLmRlbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBoYXNEb3VibGVEZWNpbWFsU2VwYXJhdG9yID0gbmV3IFJlZ0V4cChcIig/OlxcXFxcIiArIF90aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yICsgXCIuKilcIiArIFwiXFxcXFwiICsgX3RoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsIFwiZ1wiKS50ZXN0KF90aGlzLiRlZGl0b3IudmFsKCkpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNEb3VibGVEZWNpbWFsU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNsZWFudXBFZGl0b3JWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yWzBdLnNldFNlbGVjdGlvblJhbmdlKF90aGlzLiRlZGl0b3IudmFsKCkubGVuZ3RoIC0gX3RoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIF90aGlzLiRlZGl0b3IudmFsKCkubGVuZ3RoIC0gX3RoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLnF1ZXJ5T25Ob25OdW1iZXJDaGFyYWN0ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5nZXRRdWVyeVN0cmluZygpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMucXVlcnkoMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmVuc3VyZURlY2ltYWxJbnB1dCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5vcGVuRHJvcGRvd25PbkVkaXRvckNsaWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5Ecm9wRG93bigpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZW50cmllcyA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5xdWVyeSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2hhbmdlKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlT3JpZ2luYWxJbnB1dFZhbHVlKCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuZmlyZUNoYW5nZUV2ZW50cyhlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kdW5pdEJveC5hZGQodGhpcy4kZHJvcERvd24pLm1vdXNlZG93bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLiRlZGl0b3IuaXMoXCI6Zm9jdXNcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuYmx1ckNhdXNlZEJ5Q2xpY2tJbnNpZGVDb21wb25lbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLm1vdXNldXAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkubW91c2VvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5ibHVyQ2F1c2VkQnlDbGlja0luc2lkZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZWRpdG9yLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJsdXJDYXVzZWRCeUNsaWNrSW5zaWRlQ29tcG9uZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmxpc3RCb3ggPSBuZXcgVHJpdmlhbExpc3RCb3hfMS5Ucml2aWFsTGlzdEJveCh0aGlzLiRkcm9wRG93biwgdGhpcy5jb25maWcpO1xuICAgICAgICAgICAgdGhpcy5saXN0Qm94Lm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKHNlbGVjdGVkRW50cnksIGV2ZW50U291cmNlLCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0U2VsZWN0ZWRFbnRyeShzZWxlY3RlZEVudHJ5LCB0cnVlLCBvcmlnaW5hbEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubGlzdEJveC5zZXRTZWxlY3RlZEVudHJ5KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZURyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuY29uZmlnLmFtb3VudCB8fCB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCgpKTtcbiAgICAgICAgICAgIHRoaXMuZm9ybWF0RWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2VsZWN0ZWRFbnRyeSh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5IHx8IG51bGwsIGZhbHNlLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZW5zdXJlRGVjaW1hbElucHV0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGN1cnNvclBvc2l0aW9uID0gdGhpcy4kZWRpdG9yWzBdLnNlbGVjdGlvbkVuZDtcbiAgICAgICAgICAgIHZhciBvbGRWYWx1ZSA9IHRoaXMuJGVkaXRvci52YWwoKTtcbiAgICAgICAgICAgIHZhciBuZXdWYWx1ZSA9IG9sZFZhbHVlLnJlcGxhY2UobmV3IFJlZ0V4cCgnW15cXC0wLTknICsgdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvciArIHRoaXMuY29uZmlnLnRob3VzYW5kc1NlcGFyYXRvciArICddJywgJ2cnKSwgJycpO1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBuZXdWYWx1ZS5yZXBsYWNlKC8oXFxkKlxcLlxcZCopXFwuL2csICckMScpO1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBuZXdWYWx1ZS5yZXBsYWNlKC8oLiktKi9nLCAnJDEnKTtcbiAgICAgICAgICAgIHZhciBkZWNpbWFsU2VwYXJhdG9ySW5kZXggPSBuZXdWYWx1ZS5pbmRleE9mKHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IpO1xuICAgICAgICAgICAgaWYgKGRlY2ltYWxTZXBhcmF0b3JJbmRleCAhPSAtMSAmJiBuZXdWYWx1ZS5sZW5ndGggLSBkZWNpbWFsU2VwYXJhdG9ySW5kZXggLSAxID4gdGhpcy5jb25maWcuZGVjaW1hbFByZWNpc2lvbikge1xuICAgICAgICAgICAgICAgIG5ld1ZhbHVlID0gbmV3VmFsdWUuc3Vic3RyaW5nKDAsIGRlY2ltYWxTZXBhcmF0b3JJbmRleCArIDEgKyB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvbGRWYWx1ZSAhPT0gbmV3VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKG5ld1ZhbHVlKTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q3Vyc29yUG9zaXRpb24gPSBNYXRoLm1pbih0aGlzLiRlZGl0b3IudmFsKCkubGVuZ3RoLCBjdXJzb3JQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yWzBdLnNldFNlbGVjdGlvblJhbmdlKG5ld0N1cnNvclBvc2l0aW9uLCBuZXdDdXJzb3JQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZ2V0UXVlcnlTdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy4kZWRpdG9yLnZhbCgpLnJlcGxhY2UodGhpcy5udW1iZXJSZWdleCwgJycpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZ2V0RWRpdG9yVmFsdWVOdW1iZXJQYXJ0ID0gZnVuY3Rpb24gKGZpbGx1cERlY2ltYWxzKSB7XG4gICAgICAgICAgICB2YXIgcmF3TnVtYmVyID0gdGhpcy4kZWRpdG9yLnZhbCgpLm1hdGNoKHRoaXMubnVtYmVyUmVnZXgpLmpvaW4oJycpO1xuICAgICAgICAgICAgdmFyIGRlY2ltYWxEZXBhcmF0b3JJbmRleCA9IHJhd051bWJlci5pbmRleE9mKHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IpO1xuICAgICAgICAgICAgdmFyIGludGVnZXJQYXJ0O1xuICAgICAgICAgICAgdmFyIGZyYWN0aW9uYWxQYXJ0O1xuICAgICAgICAgICAgaWYgKGRlY2ltYWxEZXBhcmF0b3JJbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBpbnRlZ2VyUGFydCA9IHJhd051bWJlci5zdWJzdHJpbmcoMCwgZGVjaW1hbERlcGFyYXRvckluZGV4KTtcbiAgICAgICAgICAgICAgICBmcmFjdGlvbmFsUGFydCA9IHJhd051bWJlci5zdWJzdHJpbmcoZGVjaW1hbERlcGFyYXRvckluZGV4ICsgMSwgcmF3TnVtYmVyLmxlbmd0aCkucmVwbGFjZSgvXFxEL2csICcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGludGVnZXJQYXJ0ID0gcmF3TnVtYmVyO1xuICAgICAgICAgICAgICAgIGZyYWN0aW9uYWxQYXJ0ID0gXCJcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpbnRlZ2VyUGFydC5sZW5ndGggPT0gMCAmJiBmcmFjdGlvbmFsUGFydC5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGZpbGx1cERlY2ltYWxzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyYWN0aW9uYWxQYXJ0ID0gKGZyYWN0aW9uYWxQYXJ0ICsgbmV3IEFycmF5KHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24gKyAxKS5qb2luKFwiMFwiKSkuc3Vic3RyKDAsIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gaW50ZWdlclBhcnQgKyB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yICsgZnJhY3Rpb25hbFBhcnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uIChoaWdobGlnaHREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgJHNwaW5uZXIgPSAkKHRoaXMuY29uZmlnLnNwaW5uZXJUZW1wbGF0ZSkuYXBwZW5kVG8odGhpcy4kZHJvcERvd24pO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMgPSB0aGlzLiRzcGlubmVycy5hZGQoJHNwaW5uZXIpO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY29uZmlnLnF1ZXJ5RnVuY3Rpb24oX3RoaXMuZ2V0UXVlcnlTdHJpbmcoKSwgZnVuY3Rpb24gKG5ld0VudHJpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlRW50cmllcyhuZXdFbnRyaWVzKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHF1ZXJ5U3RyaW5nID0gX3RoaXMuZ2V0UXVlcnlTdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHF1ZXJ5U3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmxpc3RCb3guaGlnaGxpZ2h0VGV4dE1hdGNoZXMocXVlcnlTdHJpbmcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmxpc3RCb3guaGlnaGxpZ2h0TmV4dEVudHJ5KGhpZ2hsaWdodERpcmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Ryb3BEb3duT3Blbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlbkRyb3BEb3duKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZmlyZVNlbGVjdGVkRW50cnlDaGFuZ2VkRXZlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLm9uU2VsZWN0ZWRFbnRyeUNoYW5nZWQuZmlyZSh0aGlzLnNlbGVjdGVkRW50cnkpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZmlyZUNoYW5nZUV2ZW50cyA9IGZ1bmN0aW9uIChvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnRyaWdnZXIoXCJjaGFuZ2VcIik7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlLmZpcmUoe1xuICAgICAgICAgICAgICAgIHVuaXQ6IHRoaXMuc2VsZWN0ZWRFbnRyeSAhPSBudWxsID8gdGhpcy5zZWxlY3RlZEVudHJ5W3RoaXMuY29uZmlnLnVuaXRWYWx1ZVByb3BlcnR5XSA6IG51bGwsXG4gICAgICAgICAgICAgICAgdW5pdEVudHJ5OiB0aGlzLnNlbGVjdGVkRW50cnksXG4gICAgICAgICAgICAgICAgYW1vdW50OiB0aGlzLmdldEFtb3VudCgpLFxuICAgICAgICAgICAgICAgIGFtb3VudEFzRmxvYXRpbmdQb2ludE51bWJlcjogcGFyc2VGbG9hdCh0aGlzLmZvcm1hdEFtb3VudCh0aGlzLmdldEFtb3VudCgpLCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCB0aGlzLmNvbmZpZy50aG91c2FuZHNTZXBhcmF0b3IpKVxuICAgICAgICAgICAgfSwgb3JpZ2luYWxFdmVudCk7XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5zZXRTZWxlY3RlZEVudHJ5ID0gZnVuY3Rpb24gKGVudHJ5LCBmaXJlRXZlbnQsIG9yaWdpbmFsRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRFbnRyeSA9IGVudHJ5O1xuICAgICAgICAgICAgdmFyICRzZWxlY3RlZEVudHJ5ID0gJCh0aGlzLmNvbmZpZy5zZWxlY3RlZEVudHJ5UmVuZGVyaW5nRnVuY3Rpb24oZW50cnkpKVxuICAgICAgICAgICAgICAgIC5hZGRDbGFzcyhcInRyLWNvbWJvYm94LWVudHJ5XCIpO1xuICAgICAgICAgICAgdGhpcy4kc2VsZWN0ZWRFbnRyeVdyYXBwZXIuZW1wdHkoKS5hcHBlbmQoJHNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgdGhpcy5jbGVhbnVwRWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlT3JpZ2luYWxJbnB1dFZhbHVlKCk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuJGVkaXRvci5pcyhcIjpmb2N1c1wiKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0RWRpdG9yVmFsdWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaXJlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVTZWxlY3RlZEVudHJ5Q2hhbmdlZEV2ZW50KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ2hhbmdlRXZlbnRzKG9yaWdpbmFsRXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZm9ybWF0RWRpdG9yVmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuZm9ybWF0QW1vdW50KHRoaXMuZ2V0QW1vdW50KCksIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsIHRoaXMuY29uZmlnLnRob3VzYW5kc1NlcGFyYXRvcikpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuY2xlYW51cEVkaXRvclZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuJGVkaXRvci52YWwoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci52YWwodGhpcy5nZXRFZGl0b3JWYWx1ZU51bWJlclBhcnQodHJ1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZm9ybWF0QW1vdW50ID0gZnVuY3Rpb24gKGludGVnZXJOdW1iZXIsIHByZWNpc2lvbiwgZGVjaW1hbFNlcGFyYXRvciwgdGhvdXNhbmRzU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICBpZiAoaW50ZWdlck51bWJlciA9PSBudWxsIHx8IGlzTmFOKGludGVnZXJOdW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgYW1vdW50QXNTdHJpbmcgPSBcIlwiICsgaW50ZWdlck51bWJlcjtcbiAgICAgICAgICAgIGlmIChhbW91bnRBc1N0cmluZy5sZW5ndGggPD0gcHJlY2lzaW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDAgKyBkZWNpbWFsU2VwYXJhdG9yICsgbmV3IEFycmF5KHByZWNpc2lvbiAtIGFtb3VudEFzU3RyaW5nLmxlbmd0aCArIDEpLmpvaW4oXCIwXCIpICsgYW1vdW50QXNTdHJpbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgaW50ZWdlclBhcnQgPSBhbW91bnRBc1N0cmluZy5zdWJzdHJpbmcoMCwgYW1vdW50QXNTdHJpbmcubGVuZ3RoIC0gcHJlY2lzaW9uKTtcbiAgICAgICAgICAgICAgICB2YXIgZm9ybWF0dGVkSW50ZWdlclBhcnQgPSBpbnRlZ2VyUGFydC5yZXBsYWNlKC9cXEIoPz0oXFxkezN9KSsoPyFcXGQpKS9nLCB0aG91c2FuZHNTZXBhcmF0b3IpO1xuICAgICAgICAgICAgICAgIHZhciBmcmFjdGlvbmFsUGFydCA9IGFtb3VudEFzU3RyaW5nLnN1YnN0cihhbW91bnRBc1N0cmluZy5sZW5ndGggLSBwcmVjaXNpb24sIHByZWNpc2lvbik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlZEludGVnZXJQYXJ0ICsgZGVjaW1hbFNlcGFyYXRvciArIGZyYWN0aW9uYWxQYXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUucmVwb3NpdGlvbkRyb3BEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duXG4gICAgICAgICAgICAgICAgLnNob3coKVxuICAgICAgICAgICAgICAgIC5wb3NpdGlvbih7XG4gICAgICAgICAgICAgICAgbXk6IFwibGVmdCB0b3BcIixcbiAgICAgICAgICAgICAgICBhdDogXCJsZWZ0IGJvdHRvbVwiLFxuICAgICAgICAgICAgICAgIG9mOiB0aGlzLiR1bml0Qm94LFxuICAgICAgICAgICAgICAgIGNvbGxpc2lvbjogXCJmbGlwXCIsXG4gICAgICAgICAgICAgICAgdXNpbmc6IGZ1bmN0aW9uIChjYWxjdWxhdGVkUG9zaXRpb24sIGluZm8pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZm8udmVydGljYWwgPT09IFwidG9wXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiR1bml0Qm94LnJlbW92ZUNsYXNzKFwiZHJvcGRvd24tZmxpcHBlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5yZW1vdmVDbGFzcyhcImZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kdW5pdEJveC5hZGRDbGFzcyhcImRyb3Bkb3duLWZsaXBwZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZHJvcERvd24uYWRkQ2xhc3MoXCJmbGlwcGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLiRkcm9wRG93bi5jc3Moe1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogY2FsY3VsYXRlZFBvc2l0aW9uLmxlZnQgKyAncHgnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wOiBjYWxjdWxhdGVkUG9zaXRpb24udG9wICsgJ3B4J1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC53aWR0aCh0aGlzLiR1bml0Qm94LndpZHRoKCkpO1xuICAgICAgICB9O1xuICAgICAgICA7XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5vcGVuRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiR1bml0Qm94LmFkZENsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgIHRoaXMucmVwb3NpdGlvbkRyb3BEb3duKCk7XG4gICAgICAgICAgICB0aGlzLmlzRHJvcERvd25PcGVuID0gdHJ1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmNsb3NlRHJvcERvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiR1bml0Qm94LnJlbW92ZUNsYXNzKFwib3BlblwiKTtcbiAgICAgICAgICAgIHRoaXMuJGRyb3BEb3duLmhpZGUoKTtcbiAgICAgICAgICAgIHRoaXMuaXNEcm9wRG93bk9wZW4gPSBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnVwZGF0ZU9yaWdpbmFsSW5wdXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy51bml0RGlzcGxheVBvc2l0aW9uID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCgodGhpcy5zZWxlY3RlZEVudHJ5ID8gdGhpcy5zZWxlY3RlZEVudHJ5W3RoaXMuY29uZmlnLnVuaXRWYWx1ZVByb3BlcnR5XSA6ICcnKSArIHRoaXMuZm9ybWF0QW1vdW50KHRoaXMuZ2V0QW1vdW50KCksIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsICcnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnZhbCh0aGlzLmZvcm1hdEFtb3VudCh0aGlzLmdldEFtb3VudCgpLCB0aGlzLmNvbmZpZy5kZWNpbWFsUHJlY2lzaW9uLCB0aGlzLmNvbmZpZy5kZWNpbWFsU2VwYXJhdG9yLCAnJykgKyAodGhpcy5zZWxlY3RlZEVudHJ5ID8gdGhpcy5zZWxlY3RlZEVudHJ5W3RoaXMuY29uZmlnLnVuaXRWYWx1ZVByb3BlcnR5XSA6ICcnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIFRyaXZpYWxVbml0Qm94LnByb3RvdHlwZS5nZXRBbW91bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZWRpdG9yVmFsdWVOdW1iZXJQYXJ0ID0gdGhpcy5nZXRFZGl0b3JWYWx1ZU51bWJlclBhcnQoZmFsc2UpO1xuICAgICAgICAgICAgaWYgKGVkaXRvclZhbHVlTnVtYmVyUGFydC5sZW5ndGggPT09IDAgJiYgdGhpcy5jb25maWcuYWxsb3dOdWxsQW1vdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChlZGl0b3JWYWx1ZU51bWJlclBhcnQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5nZXRFZGl0b3JWYWx1ZU51bWJlclBhcnQodHJ1ZSkucmVwbGFjZSgvXFxEL2csIFwiXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmlzRHJvcERvd25OZWVkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lZGl0aW5nTW9kZSA9PSAnZWRpdGFibGUnICYmICh0aGlzLmNvbmZpZy5lbnRyaWVzICYmIHRoaXMuY29uZmlnLmVudHJpZXMubGVuZ3RoID4gMCB8fCAhdGhpcy51c2luZ0RlZmF1bHRRdWVyeUZ1bmN0aW9uIHx8IHRoaXMuY29uZmlnLnNob3dUcmlnZ2VyKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnNldEVkaXRpbmdNb2RlID0gZnVuY3Rpb24gKG5ld0VkaXRpbmdNb2RlKSB7XG4gICAgICAgICAgICB0aGlzLmVkaXRpbmdNb2RlID0gbmV3RWRpdGluZ01vZGU7XG4gICAgICAgICAgICB0aGlzLiR1bml0Qm94LnJlbW92ZUNsYXNzKFwiZWRpdGFibGUgcmVhZG9ubHkgZGlzYWJsZWRcIikuYWRkQ2xhc3ModGhpcy5lZGl0aW5nTW9kZSk7XG4gICAgICAgICAgICB0aGlzLiRlZGl0b3IucHJvcChcInJlYWRvbmx5XCIsIG5ld0VkaXRpbmdNb2RlICE9PSBcImVkaXRhYmxlXCIpO1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLmF0dHIoXCJ0YWJpbmRleFwiLCBuZXdFZGl0aW5nTW9kZSA9PT0gXCJlZGl0YWJsZVwiID8gdGhpcy4kb3JpZ2luYWxJbnB1dC5hdHRyKFwidGFiaW5kZXhcIikgOiBcIi0xXCIpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcm9wRG93bk5lZWRlZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZHJvcERvd24uYXBwZW5kVG8odGhpcy4kZHJvcERvd25UYXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnNlbGVjdFVuaXQgPSBmdW5jdGlvbiAodW5pdElkZW50aWZpZXIpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLnNldFNlbGVjdGVkRW50cnkodGhpcy5lbnRyaWVzLmZpbHRlcihmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZW50cnlbX3RoaXMuY29uZmlnLnVuaXRJZFByb3BlcnR5XSA9PT0gdW5pdElkZW50aWZpZXI7XG4gICAgICAgICAgICB9KVswXSwgZmFsc2UsIG51bGwpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUudXBkYXRlRW50cmllcyA9IGZ1bmN0aW9uIChuZXdFbnRyaWVzKSB7XG4gICAgICAgICAgICB0aGlzLmVudHJpZXMgPSBuZXdFbnRyaWVzO1xuICAgICAgICAgICAgdGhpcy4kc3Bpbm5lcnMucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRzcGlubmVycyA9ICQoKTtcbiAgICAgICAgICAgIHRoaXMubGlzdEJveC51cGRhdGVFbnRyaWVzKG5ld0VudHJpZXMpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZ2V0U2VsZWN0ZWRFbnRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkRW50cnkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkRW50cnlUb1JldHVybiA9ICQuZXh0ZW5kKHt9LCB0aGlzLnNlbGVjdGVkRW50cnkpO1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkRW50cnlUb1JldHVybi5fdHJFbnRyeUVsZW1lbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGVjdGVkRW50cnlUb1JldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLnNldEFtb3VudCA9IGZ1bmN0aW9uIChhbW91bnQpIHtcbiAgICAgICAgICAgIGlmIChhbW91bnQgIT0gbnVsbCAmJiBhbW91bnQgIT09IE1hdGguZmxvb3IoYW1vdW50KSkge1xuICAgICAgICAgICAgICAgIHRocm93IFwiVHJpdmlhbFVuaXRCb3g6IFlvdSBtdXN0IHNwZWNpZnkgYW4gaW50ZWdlciBhbW91bnQhXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYW1vdW50ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcuYWxsb3dOdWxsQW1vdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGVkaXRvci52YWwoXCJcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuZm9ybWF0QW1vdW50KDAsIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsICcnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy4kZWRpdG9yLmlzKFwiOmZvY3VzXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnZhbCh0aGlzLmZvcm1hdEFtb3VudChhbW91bnQsIHRoaXMuY29uZmlnLmRlY2ltYWxQcmVjaXNpb24sIHRoaXMuY29uZmlnLmRlY2ltYWxTZXBhcmF0b3IsICcnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRlZGl0b3IudmFsKHRoaXMuZm9ybWF0QW1vdW50KGFtb3VudCwgdGhpcy5jb25maWcuZGVjaW1hbFByZWNpc2lvbiwgdGhpcy5jb25maWcuZGVjaW1hbFNlcGFyYXRvciwgdGhpcy5jb25maWcudGhvdXNhbmRzU2VwYXJhdG9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIDtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kZWRpdG9yLnNlbGVjdCgpO1xuICAgICAgICB9O1xuICAgICAgICBUcml2aWFsVW5pdEJveC5wcm90b3R5cGUuZ2V0RWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGVkaXRvclswXTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRvcmlnaW5hbElucHV0LnJlbW92ZUNsYXNzKCd0ci1vcmlnaW5hbC1pbnB1dCcpLmluc2VydEJlZm9yZSh0aGlzLiR1bml0Qm94KTtcbiAgICAgICAgICAgIHRoaXMuJHVuaXRCb3gucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLiRkcm9wRG93bi5yZW1vdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgVHJpdmlhbFVuaXRCb3gucHJvdG90eXBlLmdldE1haW5Eb21FbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJHVuaXRCb3hbMF07XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBUcml2aWFsVW5pdEJveDtcbiAgICB9KCkpO1xuICAgIGV4cG9ydHMuVHJpdmlhbFVuaXRCb3ggPSBUcml2aWFsVW5pdEJveDtcbn0pO1xuXG5cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB2YXIgdiA9IGZhY3RvcnkocmVxdWlyZSwgZXhwb3J0cyk7XG4gICAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIG1vZHVsZS5leHBvcnRzID0gdjtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcInJlcXVpcmVcIiwgXCJleHBvcnRzXCIsIFwiLi9Ucml2aWFsQ2FsZW5kYXJCb3hcIiwgXCIuL1RyaXZpYWxDb21ib0JveFwiLCBcIi4vVHJpdmlhbENvcmVcIiwgXCIuL1RyaXZpYWxEYXRlU3VnZ2VzdGlvbkVuZ2luZVwiLCBcIi4vVHJpdmlhbERhdGVUaW1lRmllbGRcIiwgXCIuL1RyaXZpYWxFdmVudFwiLCBcIi4vVHJpdmlhbExpc3RCb3hcIiwgXCIuL1RyaXZpYWxUYWdDb21ib0JveFwiLCBcIi4vVHJpdmlhbFRpbWVTdWdnZXN0aW9uRW5naW5lXCIsIFwiLi9Ucml2aWFsVHJlZVwiLCBcIi4vVHJpdmlhbFRyZWVCb3hcIiwgXCIuL1RyaXZpYWxUcmVlQ29tYm9Cb3hcIiwgXCIuL1RyaXZpYWxVbml0Qm94XCJdLCBmYWN0b3J5KTtcbiAgICB9IGVsc2UgeyAgIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyA9IHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50cyB8fCB7fTsgIGZhY3RvcnkoZnVuY3Rpb24obmFtZSkgeyAgICBpZiAobmFtZSA9PT0gXCJqcXVlcnlcIikgeyAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibGV2ZW5zaHRlaW5cIikgeyAgICAgIHJldHVybiB3aW5kb3cuTGV2ZW5zaHRlaW47ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtb21lbnRcIikgeyAgICAgIHJldHVybiB3aW5kb3cubW9tZW50OyAgICB9IGVsc2UgaWYgKG5hbWUgPT09IFwibXVzdGFjaGVcIikgeyAgICAgIHJldHVybiB3aW5kb3cuTXVzdGFjaGU7ICAgIH0gZWxzZSB7ICAgICAgcmV0dXJuIHdpbmRvdy5Ucml2aWFsQ29tcG9uZW50czsgICAgfSAgfSwgd2luZG93LlRyaXZpYWxDb21wb25lbnRzKTt9XG59KShmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIGZ1bmN0aW9uIF9fZXhwb3J0KG0pIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAoIWV4cG9ydHMuaGFzT3duUHJvcGVydHkocCkpIGV4cG9ydHNbcF0gPSBtW3BdO1xuICAgIH1cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgX19leHBvcnQocmVxdWlyZShcIi4vVHJpdmlhbENhbGVuZGFyQm94XCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsQ29tYm9Cb3hcIikpO1xuICAgIF9fZXhwb3J0KHJlcXVpcmUoXCIuL1RyaXZpYWxDb3JlXCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsRGF0ZVN1Z2dlc3Rpb25FbmdpbmVcIikpO1xuICAgIF9fZXhwb3J0KHJlcXVpcmUoXCIuL1RyaXZpYWxEYXRlVGltZUZpZWxkXCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsRXZlbnRcIikpO1xuICAgIF9fZXhwb3J0KHJlcXVpcmUoXCIuL1RyaXZpYWxMaXN0Qm94XCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsVGFnQ29tYm9Cb3hcIikpO1xuICAgIF9fZXhwb3J0KHJlcXVpcmUoXCIuL1RyaXZpYWxUaW1lU3VnZ2VzdGlvbkVuZ2luZVwiKSk7XG4gICAgX19leHBvcnQocmVxdWlyZShcIi4vVHJpdmlhbFRyZWVcIikpO1xuICAgIF9fZXhwb3J0KHJlcXVpcmUoXCIuL1RyaXZpYWxUcmVlQm94XCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsVHJlZUNvbWJvQm94XCIpKTtcbiAgICBfX2V4cG9ydChyZXF1aXJlKFwiLi9Ucml2aWFsVW5pdEJveFwiKSk7XG59KTtcblxuXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdmFyIHYgPSBmYWN0b3J5KHJlcXVpcmUsIGV4cG9ydHMpO1xuICAgICAgICBpZiAodiAhPT0gdW5kZWZpbmVkKSBtb2R1bGUuZXhwb3J0cyA9IHY7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJyZXF1aXJlXCIsIFwiZXhwb3J0c1wiLCBcImpxdWVyeVwiLCBcIi4vVHJpdmlhbENvcmVcIl0sIGZhY3RvcnkpO1xuICAgIH0gZWxzZSB7ICAgd2luZG93LlRyaXZpYWxDb21wb25lbnRzID0gd2luZG93LlRyaXZpYWxDb21wb25lbnRzIHx8IHt9OyAgZmFjdG9yeShmdW5jdGlvbihuYW1lKSB7ICAgIGlmIChuYW1lID09PSBcImpxdWVyeVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5qUXVlcnk7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJsZXZlbnNodGVpblwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5MZXZlbnNodGVpbjsgICAgfSBlbHNlIGlmIChuYW1lID09PSBcIm1vbWVudFwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5tb21lbnQ7ICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gXCJtdXN0YWNoZVwiKSB7ICAgICAgcmV0dXJuIHdpbmRvdy5NdXN0YWNoZTsgICAgfSBlbHNlIHsgICAgICByZXR1cm4gd2luZG93LlRyaXZpYWxDb21wb25lbnRzOyAgICB9ICB9LCB3aW5kb3cuVHJpdmlhbENvbXBvbmVudHMpO31cbn0pKGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuICAgIHZhciBqUXVlcnkgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuICAgIHZhciBUcml2aWFsQ29yZV8xID0gcmVxdWlyZShcIi4vVHJpdmlhbENvcmVcIik7XG4gICAgKGZ1bmN0aW9uICgkKSB7XG4gICAgICAgICQuZXhwcltcIjpcIl0uY29udGFpbnNJZ25vcmVDYXNlID0gJC5leHByLmNyZWF0ZVBzZXVkbyhmdW5jdGlvbiAoYXJnKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGVsZW0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJChlbGVtKS50ZXh0KCkudG9VcHBlckNhc2UoKS5pbmRleE9mKGFyZy50b1VwcGVyQ2FzZSgpKSA+PSAwO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfSkoalF1ZXJ5KTtcbiAgICAoZnVuY3Rpb24gKCQpIHtcbiAgICAgICAgdmFyIGlzSUUxMSA9ICEod2luZG93LkFjdGl2ZVhPYmplY3QpICYmIFwiQWN0aXZlWE9iamVjdFwiIGluIHdpbmRvdztcbiAgICAgICAgZnVuY3Rpb24gbm9ybWFsaXplRm9ySUUxMShub2RlKSB7XG4gICAgICAgICAgICBpZiAoIW5vZGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobm9kZS5ub2RlVHlwZSA9PSAzKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKG5vZGUubmV4dFNpYmxpbmcgJiYgbm9kZS5uZXh0U2libGluZy5ub2RlVHlwZSA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGUubm9kZVZhbHVlICs9IG5vZGUubmV4dFNpYmxpbmcubm9kZVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBub2RlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQobm9kZS5uZXh0U2libGluZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9ybWFsaXplRm9ySUUxMShub2RlLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9ybWFsaXplRm9ySUUxMShub2RlLm5leHRTaWJsaW5nKTtcbiAgICAgICAgfVxuICAgICAgICAkLmZuLnRyaXZpYWxIaWdobGlnaHQgPSBmdW5jdGlvbiAoc2VhcmNoU3RyaW5nLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gJC5leHRlbmQoe1xuICAgICAgICAgICAgICAgIGhpZ2hsaWdodENsYXNzTmFtZTogJ3RyLWhpZ2hsaWdodGVkLXRleHQnLFxuICAgICAgICAgICAgICAgIG1hdGNoaW5nTW9kZTogJ2NvbnRhaW5zJyxcbiAgICAgICAgICAgICAgICBpZ25vcmVDYXNlOiB0cnVlLFxuICAgICAgICAgICAgICAgIG1heExldmVuc2h0ZWluRGlzdGFuY2U6IDNcbiAgICAgICAgICAgIH0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluZCgnKicpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmluZCgnLicgKyBvcHRpb25zLmhpZ2hsaWdodENsYXNzTmFtZSkuY29udGVudHMoKS51bndyYXAoKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNJRTExKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZUZvcklFMTEodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc2VhcmNoU3RyaW5nICYmIHNlYXJjaFN0cmluZyAhPT0gJycpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuY29udGVudHMoKS5maWx0ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubm9kZVR5cGUgPT0gMyAmJiBUcml2aWFsQ29yZV8xLnRyaXZpYWxNYXRjaCh0aGlzLm5vZGVWYWx1ZSwgc2VhcmNoU3RyaW5nLCBvcHRpb25zKS5sZW5ndGggPiAwO1xuICAgICAgICAgICAgICAgICAgICB9KS5yZXBsYWNlV2l0aChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2xkTm9kZVZhbHVlID0gKHRoaXMubm9kZVZhbHVlIHx8IFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld05vZGVWYWx1ZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IFRyaXZpYWxDb3JlXzEudHJpdmlhbE1hdGNoKHRoaXMubm9kZVZhbHVlLCBzZWFyY2hTdHJpbmcsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9sZE1hdGNoRW5kID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWF0Y2hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtYXRjaCA9IG1hdGNoZXNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZVZhbHVlICs9IHRoaXMubm9kZVZhbHVlLnN1YnN0cmluZyhvbGRNYXRjaEVuZCwgbWF0Y2guc3RhcnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGVWYWx1ZSArPSBcIjxzcGFuIGNsYXNzPVxcXCJcIiArIG9wdGlvbnMuaGlnaGxpZ2h0Q2xhc3NOYW1lICsgXCJcXFwiPlwiICsgb2xkTm9kZVZhbHVlLnN1YnN0cihtYXRjaC5zdGFydCwgbWF0Y2gubGVuZ3RoKSArIFwiPC9zcGFuPlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9sZE1hdGNoRW5kID0gbWF0Y2guc3RhcnQgKyBtYXRjaC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlVmFsdWUgKz0gb2xkTm9kZVZhbHVlLnN1YnN0cmluZyhvbGRNYXRjaEVuZCwgb2xkTm9kZVZhbHVlLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICB9KGpRdWVyeSkpO1xufSk7XG5cbiJdfQ==
    </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>